diff --git a/NEXT_CHANGELOG.md b/NEXT_CHANGELOG.md index 4f19731d9c..bdee8d90bf 100644 --- a/NEXT_CHANGELOG.md +++ b/NEXT_CHANGELOG.md @@ -7,6 +7,7 @@ ### New Features and Improvements * Added `expected_workspace_status` to `databricks_mws_workspaces` to support creating workspaces in provisioning status ([#5019](https://github.com/databricks/terraform-provider-databricks/pull/5019)) +* Make `account_id` optional in `mws_*` resources ([#5133](https://github.com/databricks/terraform-provider-databricks/pull/5133)) ### Bug Fixes diff --git a/docs/resources/mws_customer_managed_keys.md b/docs/resources/mws_customer_managed_keys.md index 73e3ee25cf..a6f02b2c10 100644 --- a/docs/resources/mws_customer_managed_keys.md +++ b/docs/resources/mws_customer_managed_keys.md @@ -66,7 +66,6 @@ resource "aws_kms_alias" "managed_services_customer_managed_key_alias" { } resource "databricks_mws_customer_managed_keys" "managed_services" { - account_id = var.databricks_account_id aws_key_info { key_arn = aws_kms_key.managed_services_customer_managed_key.arn key_alias = aws_kms_alias.managed_services_customer_managed_key_alias.name @@ -88,7 +87,6 @@ variable "cmek_resource_id" { } resource "databricks_mws_customer_managed_keys" "managed_services" { - account_id = var.databricks_account_id gcp_key_info { kms_key_id = var.cmek_resource_id } @@ -191,7 +189,6 @@ resource "aws_kms_alias" "storage_customer_managed_key_alias" { } resource "databricks_mws_customer_managed_keys" "storage" { - account_id = var.databricks_account_id aws_key_info { key_arn = aws_kms_key.storage_customer_managed_key.arn key_alias = aws_kms_alias.storage_customer_managed_key_alias.name @@ -213,7 +210,6 @@ variable "cmek_resource_id" { } resource "databricks_mws_customer_managed_keys" "storage" { - account_id = var.databricks_account_id gcp_key_info { kms_key_id = var.cmek_resource_id } @@ -228,7 +224,7 @@ The following arguments are required: * `aws_key_info` - This field is a block and is documented below. This conflicts with `gcp_key_info` * `gcp_key_info` - This field is a block and is documented below. This conflicts with `aws_key_info` -* `account_id` - Account Id that could be found in the top right corner of [Accounts Console](https://accounts.cloud.databricks.com/) +* `account_id` - (Optional) Account Id that could be found in the top right corner of [Accounts Console](https://accounts.cloud.databricks.com/) * `use_cases` - *(since v0.3.4)* List of use cases for which this key will be used. *If you've used the resource before, please add `use_cases = ["MANAGED_SERVICES"]` to keep the previous behaviour.* Possible values are: * `MANAGED_SERVICES` - for encryption of the workspace objects (notebooks, secrets) that are stored in the control plane * `STORAGE` - for encryption of the DBFS Storage & Cluster EBS Volumes diff --git a/docs/resources/mws_log_delivery.md b/docs/resources/mws_log_delivery.md index 8347b64e02..4d3fbacfba 100644 --- a/docs/resources/mws_log_delivery.md +++ b/docs/resources/mws_log_delivery.md @@ -69,7 +69,6 @@ resource "time_sleep" "wait" { } resource "databricks_mws_credentials" "log_writer" { - account_id = var.databricks_account_id credentials_name = "Usage Delivery" role_arn = aws_iam_role.logdelivery.arn depends_on = [ @@ -78,13 +77,11 @@ resource "databricks_mws_credentials" "log_writer" { } resource "databricks_mws_storage_configurations" "log_bucket" { - account_id = var.databricks_account_id storage_configuration_name = "Usage Logs" bucket_name = aws_s3_bucket.logdelivery.bucket } resource "databricks_mws_log_delivery" "usage_logs" { - account_id = var.databricks_account_id credentials_id = databricks_mws_credentials.log_writer.credentials_id storage_configuration_id = databricks_mws_storage_configurations.log_bucket.storage_configuration_id delivery_path_prefix = "billable-usage" @@ -94,7 +91,6 @@ resource "databricks_mws_log_delivery" "usage_logs" { } resource "databricks_mws_log_delivery" "audit_logs" { - account_id = var.databricks_account_id credentials_id = databricks_mws_credentials.log_writer.credentials_id storage_configuration_id = databricks_mws_storage_configurations.log_bucket.storage_configuration_id delivery_path_prefix = "audit-logs" @@ -112,7 +108,6 @@ Common processing scenario is to apply [cost allocation tags](https://docs.aws.a ```hcl resource "databricks_mws_log_delivery" "usage_logs" { - account_id = var.databricks_account_id credentials_id = databricks_mws_credentials.log_writer.credentials_id storage_configuration_id = databricks_mws_storage_configurations.log_bucket.storage_configuration_id delivery_path_prefix = "billable-usage" @@ -128,7 +123,6 @@ JSON files with [static schema](https://docs.databricks.com/administration-guide ```hcl resource "databricks_mws_log_delivery" "audit_logs" { - account_id = var.databricks_account_id credentials_id = databricks_mws_credentials.log_writer.credentials_id storage_configuration_id = databricks_mws_storage_configurations.log_bucket.storage_configuration_id delivery_path_prefix = "audit-logs" @@ -140,7 +134,7 @@ resource "databricks_mws_log_delivery" "audit_logs" { ## Argument reference -* `account_id` - Account Id that could be found in the top right corner of [Accounts Console](https://accounts.cloud.databricks.com/). +* `account_id` - (Optional) Account Id that could be found in the top right corner of [Accounts Console](https://accounts.cloud.databricks.com/). * `config_name` - The optional human-readable name of the log delivery configuration. Defaults to empty. * `log_type` - The type of log delivery. `BILLABLE_USAGE` and `AUDIT_LOGS` are supported. * `output_format` - The file type of log delivery. Currently `CSV` (for `BILLABLE_USAGE`) and `JSON` (for `AUDIT_LOGS`) are supported. diff --git a/docs/resources/mws_networks.md b/docs/resources/mws_networks.md index 01a0ab5b3d..60f5a99ae8 100644 --- a/docs/resources/mws_networks.md +++ b/docs/resources/mws_networks.md @@ -75,7 +75,6 @@ module "vpc" { resource "databricks_mws_networks" "this" { provider = databricks.mws - account_id = var.databricks_account_id network_name = "${local.prefix}-network" security_group_ids = [module.vpc.default_security_group_id] subnet_ids = module.vpc.private_subnets @@ -88,7 +87,6 @@ In order to create a VPC [that leverages AWS PrivateLink](https://docs.databrick ```hcl resource "databricks_mws_networks" "this" { provider = databricks.mws - account_id = var.databricks_account_id network_name = "${local.prefix}-network" security_group_ids = [module.vpc.default_security_group_id] subnet_ids = module.vpc.private_subnets @@ -137,7 +135,6 @@ resource "google_compute_router_nat" "nat" { } resource "databricks_mws_networks" "this" { - account_id = var.databricks_account_id network_name = "test-demo-${random_string.suffix.result}" gcp_network_info { network_project_id = var.google_project @@ -152,7 +149,6 @@ In order to create a VPC [that leverages GCP Private Service Connect](https://do ```hcl resource "databricks_mws_networks" "this" { - account_id = var.databricks_account_id network_name = "test-demo-${random_string.suffix.result}" gcp_network_info { network_project_id = var.google_project @@ -179,7 +175,7 @@ Due to specifics of platform APIs, changing any attribute of network configurati The following arguments are available: -* `account_id` - Account Id that could be found in the top right corner of [Accounts Console](https://accounts.cloud.databricks.com/) +* `account_id` - (Optional) Account Id that could be found in the top right corner of [Accounts Console](https://accounts.cloud.databricks.com/) * `network_name` - name under which this network is registered * `vpc_id` - (AWS only) [aws_vpc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc) id * `subnet_ids` - (AWS only) ids of [aws_subnet](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet) diff --git a/docs/resources/mws_private_access_settings.md b/docs/resources/mws_private_access_settings.md index 2db77f9545..e736d12468 100644 --- a/docs/resources/mws_private_access_settings.md +++ b/docs/resources/mws_private_access_settings.md @@ -18,7 +18,6 @@ It is strongly recommended that customers read the [Enable AWS Private Link](htt ```hcl resource "databricks_mws_private_access_settings" "pas" { provider = databricks.mws - account_id = var.databricks_account_id private_access_settings_name = "Private Access Settings for ${local.prefix}" region = var.region public_access_enabled = true diff --git a/docs/resources/mws_storage_configurations.md b/docs/resources/mws_storage_configurations.md index a4a15c3b23..a37f3a960c 100644 --- a/docs/resources/mws_storage_configurations.md +++ b/docs/resources/mws_storage_configurations.md @@ -32,7 +32,6 @@ resource "aws_s3_bucket_versioning" "root_versioning" { resource "databricks_mws_storage_configurations" "this" { provider = databricks.mws - account_id = var.databricks_account_id storage_configuration_name = "${var.prefix}-storage" bucket_name = aws_s3_bucket.root_storage_bucket.bucket } @@ -43,7 +42,7 @@ resource "databricks_mws_storage_configurations" "this" { The following arguments are required: * `bucket_name` - name of AWS S3 bucket -* `account_id` - Account Id that could be found in the top right corner of [Accounts Console](https://accounts.cloud.databricks.com/) +* `account_id` - (Optional) Account Id that could be found in the top right corner of [Accounts Console](https://accounts.cloud.databricks.com/) * `storage_configuration_name` - name under which this storage configuration is stored ## Attribute Reference diff --git a/docs/resources/mws_vpc_endpoint.md b/docs/resources/mws_vpc_endpoint.md index 6cf8189149..309db97b31 100644 --- a/docs/resources/mws_vpc_endpoint.md +++ b/docs/resources/mws_vpc_endpoint.md @@ -73,7 +73,6 @@ Once you have created the necessary endpoints, you need to register each of them ```hcl resource "databricks_mws_vpc_endpoint" "workspace" { provider = databricks.mws - account_id = var.databricks_account_id aws_vpc_endpoint_id = aws_vpc_endpoint.workspace.id vpc_endpoint_name = "VPC Relay for ${module.vpc.vpc_id}" region = var.region @@ -82,7 +81,6 @@ resource "databricks_mws_vpc_endpoint" "workspace" { resource "databricks_mws_vpc_endpoint" "relay" { provider = databricks.mws - account_id = var.databricks_account_id aws_vpc_endpoint_id = aws_vpc_endpoint.relay.id vpc_endpoint_name = "VPC Relay for ${module.vpc.vpc_id}" region = var.region @@ -95,7 +93,6 @@ Typically the next steps after this would be to create a [databricks_mws_private ```hcl resource "databricks_mws_workspaces" "this" { provider = databricks.mws - account_id = var.databricks_account_id aws_region = var.region workspace_name = local.prefix credentials_id = databricks_mws_credentials.this.credentials_id @@ -128,7 +125,6 @@ provider "databricks" { resource "databricks_mws_vpc_endpoint" "workspace" { provider = databricks.mws - account_id = var.databricks_account_id vpc_endpoint_name = "PSC Rest API endpoint" gcp_vpc_endpoint_info { project_id = var.google_project @@ -139,7 +135,6 @@ resource "databricks_mws_vpc_endpoint" "workspace" { resource "databricks_mws_vpc_endpoint" "relay" { provider = databricks.mws - account_id = var.databricks_account_id vpc_endpoint_name = "PSC Relay endpoint" gcp_vpc_endpoint_info { project_id = var.google_project @@ -154,7 +149,6 @@ Typically the next steps after this would be to create a [databricks_mws_private ```hcl resource "databricks_mws_workspaces" "this" { provider = databricks.mws - account_id = var.databricks_account_id workspace_name = "gcp workspace" location = var.subnet_region cloud_resource_container { @@ -177,7 +171,7 @@ resource "databricks_mws_workspaces" "this" { The following arguments are required: -* `account_id` - Account Id that could be found in the Accounts Console for [AWS](https://accounts.cloud.databricks.com/) or [GCP](https://accounts.gcp.databricks.com/) +* `account_id` - (Optional) Account Id that could be found in the Accounts Console for [AWS](https://accounts.cloud.databricks.com/) or [GCP](https://accounts.gcp.databricks.com/) * `aws_vpc_endpoint_id` - (AWS only) ID of configured [aws_vpc_endpoint](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_endpoint) * `vpc_endpoint_name` - Name of VPC Endpoint in Databricks Account * `region` - (AWS only) Region of AWS VPC diff --git a/docs/resources/mws_workspaces.md b/docs/resources/mws_workspaces.md index 13eae10b08..86fa2e86b4 100644 --- a/docs/resources/mws_workspaces.md +++ b/docs/resources/mws_workspaces.md @@ -21,7 +21,6 @@ To use serverless workspaces, you must enroll in the [Default Storage preview](h ```hcl resource "databricks_mws_workspaces" "serverless_workspace" { - account_id = "" # Your Databricks account ID workspace_name = "serverless-workspace" aws_region = "us-east-1" compute_mode = "SERVERLESS" @@ -45,14 +44,14 @@ variable "databricks_account_id" { } provider "databricks" { - alias = "mws" - host = "https://accounts.cloud.databricks.com" + alias = "mws" + host = "https://accounts.cloud.databricks.com" + account_id = var.account_id } // register cross-account ARN resource "databricks_mws_credentials" "this" { provider = databricks.mws - account_id = var.databricks_account_id credentials_name = "${var.prefix}-creds" role_arn = var.crossaccount_arn } @@ -60,7 +59,6 @@ resource "databricks_mws_credentials" "this" { // register root bucket resource "databricks_mws_storage_configurations" "this" { provider = databricks.mws - account_id = var.databricks_account_id storage_configuration_name = "${var.prefix}-storage" bucket_name = var.root_bucket } @@ -68,7 +66,6 @@ resource "databricks_mws_storage_configurations" "this" { // register VPC resource "databricks_mws_networks" "this" { provider = databricks.mws - account_id = var.databricks_account_id network_name = "${var.prefix}-network" vpc_id = var.vpc_id subnet_ids = var.subnets_private @@ -78,7 +75,6 @@ resource "databricks_mws_networks" "this" { // create workspace in given VPC with DBFS on root bucket resource "databricks_mws_workspaces" "this" { provider = databricks.mws - account_id = var.databricks_account_id workspace_name = var.prefix aws_region = var.region @@ -130,7 +126,6 @@ resource "aws_iam_role_policy" "this" { resource "databricks_mws_credentials" "this" { provider = databricks.mws - account_id = var.databricks_account_id credentials_name = "${local.prefix}-creds" role_arn = aws_iam_role.cross_account_role.arn } @@ -180,14 +175,12 @@ resource "aws_s3_bucket_policy" "root_bucket_policy" { resource "databricks_mws_storage_configurations" "this" { provider = databricks.mws - account_id = var.databricks_account_id storage_configuration_name = "${local.prefix}-storage" bucket_name = aws_s3_bucket.root_storage_bucket.bucket } resource "databricks_mws_workspaces" "this" { provider = databricks.mws - account_id = var.databricks_account_id workspace_name = local.prefix aws_region = "us-east-1" @@ -219,14 +212,14 @@ variable "databricks_google_service_account" {} variable "google_project" {} provider "databricks" { - alias = "mws" - host = "https://accounts.gcp.databricks.com" + alias = "mws" + host = "https://accounts.gcp.databricks.com" + account_id = var.account_id } // register VPC resource "databricks_mws_networks" "this" { - account_id = var.databricks_account_id network_name = "${var.prefix}-network" gcp_network_info { network_project_id = var.google_project @@ -240,7 +233,6 @@ resource "databricks_mws_networks" "this" { // create workspace in given VPC resource "databricks_mws_workspaces" "this" { - account_id = var.databricks_account_id workspace_name = var.prefix location = var.subnet_region cloud_resource_container { @@ -274,7 +266,6 @@ data "google_client_config" "current" { resource "databricks_mws_workspaces" "this" { provider = databricks.accounts - account_id = var.databricks_account_id workspace_name = var.prefix location = data.google_client_config.current.region @@ -292,7 +283,7 @@ resource "databricks_mws_workspaces" "this" { The following arguments are available: -* `account_id` - Account Id that could be found in the top right corner of [Accounts Console](https://accounts.cloud.databricks.com/). +* `account_id` - (Optional) Account Id that could be found in the top right corner of [Accounts Console](https://accounts.cloud.databricks.com/). If not specified, then it's taken from the provider config. * `deployment_name` - (Optional) part of URL as in `https://-.cloud.databricks.com`. Deployment name cannot be used until a deployment name prefix is defined. Please contact your Databricks representative. Once a new deployment prefix is added/updated, it only will affect the new workspaces created. * `workspace_name` - name of the workspace, will appear on UI. * `network_id` - (Optional) `network_id` from [networks](mws_networks.md). diff --git a/mws/mws.go b/mws/mws.go index 3df789fbe7..b18edff5d8 100644 --- a/mws/mws.go +++ b/mws/mws.go @@ -73,7 +73,7 @@ type GcpNetworkInfo struct { // Network is the object that contains all the information for BYOVPC type Network struct { - AccountID string `json:"account_id" tf:"force_new"` + AccountID string `json:"account_id,omitempty" tf:"computed,force_new"` NetworkID string `json:"network_id,omitempty" tf:"computed"` NetworkName string `json:"network_name" tf:"force_new"` VPCID string `json:"vpc_id,omitempty" tf:"force_new"` @@ -100,7 +100,7 @@ type GcpVpcEndpointInfo struct { type VPCEndpoint struct { VPCEndpointID string `json:"vpc_endpoint_id,omitempty" tf:"computed"` AwsVPCEndpointID string `json:"aws_vpc_endpoint_id,omitempty"` - AccountID string `json:"account_id,omitempty"` + AccountID string `json:"account_id,omitempty" tf:"computed,force_new"` VPCEndpointName string `json:"vpc_endpoint_name"` AwsVPCEndpointServiceID string `json:"aws_endpoint_service_id,omitempty" tf:"computed"` AWSAccountID string `json:"aws_account_id,omitempty" tf:"computed"` diff --git a/mws/resource_mws_customer_managed_keys.go b/mws/resource_mws_customer_managed_keys.go index 1163ef39c5..924500c1a2 100644 --- a/mws/resource_mws_customer_managed_keys.go +++ b/mws/resource_mws_customer_managed_keys.go @@ -28,7 +28,7 @@ type CustomerManagedKey struct { CustomerManagedKeyID string `json:"customer_managed_key_id,omitempty" tf:"computed"` AwsKeyInfo *AwsKeyInfo `json:"aws_key_info,omitempty" tf:"force_new,conflicts:gcp_key_info"` GcpKeyInfo *GcpKeyInfo `json:"gcp_key_info,omitempty" tf:"force_new,conflicts:aws_key_info"` - AccountID string `json:"account_id" tf:"force_new"` + AccountID string `json:"account_id,omitempty" tf:"computed,force_new"` CreationTime int64 `json:"creation_time,omitempty" tf:"computed"` UseCases []string `json:"use_cases"` } @@ -78,6 +78,13 @@ func ResourceMwsCustomerManagedKeys() common.Resource { Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { var cmk CustomerManagedKey common.DataToStructPointer(d, s, &cmk) + if cmk.AccountID == "" { + if c.Config == nil || c.Config.AccountID == "" { + return fmt.Errorf("account_id is required in the provider block or in the resource") + } + cmk.AccountID = c.Config.AccountID + d.Set("account_id", cmk.AccountID) + } customerManagedKeyData, err := NewCustomerManagedKeysAPI(ctx, c).Create(cmk) if err != nil { return err diff --git a/mws/resource_mws_customer_managed_keys_test.go b/mws/resource_mws_customer_managed_keys_test.go index 0d88239471..e5cb5bdd51 100644 --- a/mws/resource_mws_customer_managed_keys_test.go +++ b/mws/resource_mws_customer_managed_keys_test.go @@ -263,3 +263,67 @@ func TestAwsKeyInfoKeyAliasOptional(t *testing.T) { assert.Equal(t, "abc/cmkid", d.Id()) assert.Equal(t, "key-arn", d.Get("aws_key_info.0.key_arn")) } + +func TestResourceCustomerManagedKeyCreate_NoAccountIDInResource(t *testing.T) { + qa.ResourceFixture{ + Fixtures: []qa.HTTPFixture{ + { + Method: "POST", + Resource: "/api/2.0/accounts/abc/customer-managed-keys", + ExpectedRequest: CustomerManagedKey{ + AccountID: "abc", + AwsKeyInfo: &AwsKeyInfo{ + KeyArn: "key-arn", + KeyAlias: "key-alias", + }, + UseCases: []string{"MANAGED_SERVICES"}, + }, + Response: CustomerManagedKey{ + CustomerManagedKeyID: "cmkid", + }, + }, + { + Method: "GET", + Resource: "/api/2.0/accounts/abc/customer-managed-keys/cmkid", + Response: CustomerManagedKey{ + CustomerManagedKeyID: "cmkid", + AwsKeyInfo: &AwsKeyInfo{ + KeyArn: "key-arn", + KeyAlias: "key-alias", + KeyRegion: "us-east-1", + }, + AccountID: "abc", + UseCases: []string{"MANAGED_SERVICES"}, + CreationTime: 123, + }, + }, + }, + Resource: ResourceMwsCustomerManagedKeys(), + HCL: ` + aws_key_info { + key_arn = "key-arn" + key_alias = "key-alias" + } + use_cases = ["MANAGED_SERVICES"] + `, + AccountID: "abc", + Create: true, + }.ApplyAndExpectData(t, map[string]any{ + "account_id": "abc", + "id": "abc/cmkid", + }) +} + +func TestResourceCustomerManagedKeyCreate_NoAccountID(t *testing.T) { + qa.ResourceFixture{ + Resource: ResourceMwsCustomerManagedKeys(), + HCL: ` + aws_key_info { + key_arn = "key-arn" + key_alias = "key-alias" + } + use_cases = ["MANAGED_SERVICES"] + `, + Create: true, + }.ExpectError(t, "account_id is required in the provider block or in the resource") +} diff --git a/mws/resource_mws_log_delivery.go b/mws/resource_mws_log_delivery.go index 34514440fb..55e0b3b613 100644 --- a/mws/resource_mws_log_delivery.go +++ b/mws/resource_mws_log_delivery.go @@ -17,7 +17,7 @@ type LogDelivery struct { // LogDeliveryConfiguration describes log delivery type LogDeliveryConfiguration struct { - AccountID string `json:"account_id" tf:"force_new"` + AccountID string `json:"account_id,omitempty" tf:"computed,force_new"` ConfigID string `json:"config_id,omitempty" tf:"computed,force_new"` CredentialsID string `json:"credentials_id" tf:"force_new"` StorageConfigurationID string `json:"storage_configuration_id" tf:"force_new"` @@ -82,6 +82,13 @@ func ResourceMwsLogDelivery() common.Resource { Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { var ldc LogDeliveryConfiguration common.DataToStructPointer(d, s, &ldc) + if ldc.AccountID == "" { + if c.Config == nil || c.Config.AccountID == "" { + return fmt.Errorf("account_id is required in the provider block or in the resource") + } + ldc.AccountID = c.Config.AccountID + d.Set("account_id", ldc.AccountID) + } configID, err := NewLogDeliveryAPI(ctx, c).Create(ldc) if err != nil { return err @@ -95,6 +102,9 @@ func ResourceMwsLogDelivery() common.Resource { Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { var ldc LogDeliveryConfiguration common.DataToStructPointer(d, s, &ldc) + if ldc.AccountID == "" { + ldc.AccountID = c.Config.AccountID + } err := NewLogDeliveryAPI(ctx, c).Patch(ldc.AccountID, ldc.ConfigID, ldc.Status) if err != nil { return err diff --git a/mws/resource_mws_log_delivery_test.go b/mws/resource_mws_log_delivery_test.go index 1374e4a994..2217ee7158 100644 --- a/mws/resource_mws_log_delivery_test.go +++ b/mws/resource_mws_log_delivery_test.go @@ -383,3 +383,79 @@ func TestResourceLogDeliveryDelete_Error(t *testing.T) { qa.AssertErrorStartsWith(t, err, "Internal error happened") assert.Equal(t, "abc|nid", d.Id()) } + +func TestResourceLogDeliveryCreate_NoAccountIDInResource(t *testing.T) { + qa.ResourceFixture{ + Fixtures: []qa.HTTPFixture{ + { + Method: "POST", + Resource: "/api/2.0/accounts/abc/log-delivery", + ExpectedRequest: LogDelivery{ + LogDeliveryConfiguration: LogDeliveryConfiguration{ + AccountID: "abc", + ConfigName: "Audit logs", + CredentialsID: "bcd", + DeliveryPathPrefix: "/a/b", + LogType: "AUDIT_LOGS", + OutputFormat: "JSON", + StorageConfigurationID: "def", + DeliveryStartTime: "2020-10", + WorkspaceIdsFilter: []int64{1111111111111111, 222222222222222}, + }, + }, + Response: LogDelivery{ + LogDeliveryConfiguration: LogDeliveryConfiguration{ + ConfigID: "nid", + }, + }, + }, + { + Method: "GET", + Resource: "/api/2.0/accounts/abc/log-delivery/nid", + Response: LogDelivery{ + LogDeliveryConfiguration: LogDeliveryConfiguration{ + ConfigID: "nid", + AccountID: "abc", + ConfigName: "Audit logs", + CredentialsID: "bcd", + DeliveryPathPrefix: "/a/b", + LogType: "AUDIT_LOGS", + OutputFormat: "JSON", + StorageConfigurationID: "def", + DeliveryStartTime: "2020-10", + WorkspaceIdsFilter: []int64{1111111111111111, 222222222222222}, + }, + }, + }, + }, + Resource: ResourceMwsLogDelivery(), + HCL: ` + credentials_id = "bcd" + storage_configuration_id = "def" + config_name = "Audit logs" + log_type = "AUDIT_LOGS" + output_format = "JSON" + delivery_path_prefix = "/a/b" + workspace_ids_filter = [1111111111111111, 222222222222222] + delivery_start_time = "2020-10"`, + AccountID: "abc", + Create: true, + }.ApplyAndExpectData(t, map[string]any{ + "account_id": "abc", + "id": "abc|nid", + }) +} + +func TestResourceLogDeliveryCreate_NoAccountID(t *testing.T) { + qa.ResourceFixture{ + Resource: ResourceMwsLogDelivery(), + HCL: ` + credentials_id = "bcd" + storage_configuration_id = "def" + config_name = "Audit logs" + log_type = "AUDIT_LOGS" + output_format = "JSON" + delivery_path_prefix = "/a/b"`, + Create: true, + }.ExpectError(t, "account_id is required in the provider block or in the resource") +} diff --git a/mws/resource_mws_networks.go b/mws/resource_mws_networks.go index 1e554f987d..dfe4ae923f 100644 --- a/mws/resource_mws_networks.go +++ b/mws/resource_mws_networks.go @@ -98,6 +98,13 @@ func ResourceMwsNetworks() common.Resource { Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { var network Network common.DataToStructPointer(d, s, &network) + if network.AccountID == "" { + if c.Config == nil || c.Config.AccountID == "" { + return fmt.Errorf("account_id is required in the provider block or in the resource") + } + network.AccountID = c.Config.AccountID + d.Set("account_id", network.AccountID) + } if err := NewNetworksAPI(ctx, c).Create(&network); err != nil { return err } diff --git a/mws/resource_mws_networks_test.go b/mws/resource_mws_networks_test.go index e852041ff4..4ebbad44e8 100644 --- a/mws/resource_mws_networks_test.go +++ b/mws/resource_mws_networks_test.go @@ -340,3 +340,61 @@ func TestResourceNetworkDelete_Error(t *testing.T) { qa.AssertErrorStartsWith(t, err, "Internal error happened") assert.Equal(t, "abc/nid", d.Id()) } + +func TestResourceNetworkCreate_NoAccountIDInResource(t *testing.T) { + qa.ResourceFixture{ + Fixtures: []qa.HTTPFixture{ + { + Method: "POST", + Resource: "/api/2.0/accounts/abc/networks", + ExpectedRequest: Network{ + AccountID: "abc", + SecurityGroupIds: []string{"one", "two"}, + NetworkName: "Open Workers", + VPCID: "five", + SubnetIds: []string{"four", "three"}, + }, + Response: Network{ + AccountID: "abc", + NetworkID: "nid", + }, + }, + { + Method: "GET", + Resource: "/api/2.0/accounts/abc/networks/nid", + Response: Network{ + NetworkID: "nid", + SecurityGroupIds: []string{"one", "two"}, + NetworkName: "Open Workers", + VPCID: "five", + SubnetIds: []string{"four", "three"}, + }, + }, + }, + Resource: ResourceMwsNetworks(), + HCL: ` + network_name = "Open Workers" + security_group_ids = ["one", "two"] + subnet_ids = ["three", "four"] + vpc_id = "five" + `, + AccountID: "abc", + Create: true, + }.ApplyAndExpectData(t, map[string]any{ + "account_id": "abc", + "id": "abc/nid", + }) +} + +func TestResourceNetworkCreate_NoAccountID(t *testing.T) { + qa.ResourceFixture{ + Resource: ResourceMwsNetworks(), + HCL: ` + network_name = "Open Workers" + security_group_ids = ["one", "two"] + subnet_ids = ["three", "four"] + vpc_id = "five" + `, + Create: true, + }.ExpectError(t, "account_id is required in the provider block or in the resource") +} diff --git a/mws/resource_mws_storage_configurations.go b/mws/resource_mws_storage_configurations.go index 2b979cf448..7cbd5beead 100644 --- a/mws/resource_mws_storage_configurations.go +++ b/mws/resource_mws_storage_configurations.go @@ -62,6 +62,13 @@ func ResourceMwsStorageConfigurations() common.Resource { name := d.Get("storage_configuration_name").(string) bucketName := d.Get("bucket_name").(string) accountID := d.Get("account_id").(string) + if accountID == "" { + if c.Config == nil || c.Config.AccountID == "" { + return fmt.Errorf("account_id is required in the provider block or in the resource") + } + accountID = c.Config.AccountID + d.Set("account_id", accountID) + } storageConfiguration, err := NewStorageConfigurationsAPI(ctx, c).Create(accountID, name, bucketName) if err != nil { return err @@ -93,7 +100,9 @@ func ResourceMwsStorageConfigurations() common.Resource { Schema: map[string]*schema.Schema{ "account_id": { Type: schema.TypeString, - Required: true, + Optional: true, + Computed: true, + ForceNew: true, Sensitive: true, }, "storage_configuration_name": { diff --git a/mws/resource_mws_storage_configurations_test.go b/mws/resource_mws_storage_configurations_test.go index 740963a4e8..4f7738f711 100644 --- a/mws/resource_mws_storage_configurations_test.go +++ b/mws/resource_mws_storage_configurations_test.go @@ -177,3 +177,55 @@ func TestResourceStorageConfigurationDelete_Error(t *testing.T) { qa.AssertErrorStartsWith(t, err, "Internal error happened") assert.Equal(t, "abc/scid", d.Id()) } + +func TestResourceStorageConfigurationCreate_NoAccountIDInResource(t *testing.T) { + qa.ResourceFixture{ + Fixtures: []qa.HTTPFixture{ + { + Method: "POST", + Resource: "/api/2.0/accounts/abc/storage-configurations", + ExpectedRequest: StorageConfiguration{ + StorageConfigurationName: "Main Storage", + RootBucketInfo: &RootBucketInfo{ + BucketName: "bucket", + }, + }, + Response: StorageConfiguration{ + StorageConfigurationID: "scid", + }, + }, + { + Method: "GET", + Resource: "/api/2.0/accounts/abc/storage-configurations/scid", + Response: StorageConfiguration{ + StorageConfigurationID: "scid", + StorageConfigurationName: "Main Storage", + RootBucketInfo: &RootBucketInfo{ + BucketName: "bucket", + }, + }, + }, + }, + Resource: ResourceMwsStorageConfigurations(), + State: map[string]any{ + "bucket_name": "bucket", + "storage_configuration_name": "Main Storage", + }, + AccountID: "abc", + Create: true, + }.ApplyAndExpectData(t, map[string]any{ + "account_id": "abc", + "id": "abc/scid", + }) +} + +func TestResourceStorageConfigurationCreate_NoAccountID(t *testing.T) { + qa.ResourceFixture{ + Resource: ResourceMwsStorageConfigurations(), + State: map[string]any{ + "bucket_name": "bucket", + "storage_configuration_name": "Main Storage", + }, + Create: true, + }.ExpectError(t, "account_id is required in the provider block or in the resource") +} diff --git a/mws/resource_mws_vpc_endpoint.go b/mws/resource_mws_vpc_endpoint.go index 5160b540c7..89f84a9733 100644 --- a/mws/resource_mws_vpc_endpoint.go +++ b/mws/resource_mws_vpc_endpoint.go @@ -90,6 +90,13 @@ func ResourceMwsVpcEndpoint() common.Resource { Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { var vpcEndpoint VPCEndpoint common.DataToStructPointer(d, s, &vpcEndpoint) + if vpcEndpoint.AccountID == "" { + if c.Config == nil || c.Config.AccountID == "" { + return fmt.Errorf("account_id is required in the provider block or in the resource") + } + vpcEndpoint.AccountID = c.Config.AccountID + d.Set("account_id", vpcEndpoint.AccountID) + } if err := NewVPCEndpointAPI(ctx, c).Create(&vpcEndpoint); err != nil { return err } diff --git a/mws/resource_mws_vpc_endpoint_test.go b/mws/resource_mws_vpc_endpoint_test.go index ba265b1cbd..48bdc17efb 100644 --- a/mws/resource_mws_vpc_endpoint_test.go +++ b/mws/resource_mws_vpc_endpoint_test.go @@ -276,6 +276,62 @@ func TestResourceVPCEndpointDelete_Error(t *testing.T) { assert.Equal(t, "abc/veid", d.Id()) } +func TestResourceVPCEndpointCreate_NoAccountIDInResource(t *testing.T) { + qa.ResourceFixture{ + Fixtures: []qa.HTTPFixture{ + { + Method: "POST", + Resource: "/api/2.0/accounts/abc/vpc-endpoints", + ExpectedRequest: VPCEndpoint{ + AccountID: "abc", + VPCEndpointName: "ve_name", + Region: "ar", + AwsVPCEndpointID: "ave_id", + }, + Response: VPCEndpoint{ + VPCEndpointID: "ve_id", + }, + }, + { + Method: "GET", + Resource: "/api/2.0/accounts/abc/vpc-endpoints/ve_id", + ReuseRequest: true, + Response: VPCEndpoint{ + AccountID: "abc", + VPCEndpointName: "ve_name", + Region: "ar", + AwsVPCEndpointID: "ave_id", + VPCEndpointID: "ve_id", + State: "Available", + }, + }, + }, + Resource: ResourceMwsVpcEndpoint(), + HCL: ` + vpc_endpoint_name = "ve_name" + region = "ar" + aws_vpc_endpoint_id = "ave_id" + `, + AccountID: "abc", + Create: true, + }.ApplyAndExpectData(t, map[string]any{ + "account_id": "abc", + "id": "abc/ve_id", + }) +} + +func TestResourceVPCEndpointCreate_NoAccountID(t *testing.T) { + qa.ResourceFixture{ + Resource: ResourceMwsVpcEndpoint(), + HCL: ` + vpc_endpoint_name = "ve_name" + region = "ar" + aws_vpc_endpoint_id = "ave_id" + `, + Create: true, + }.ExpectError(t, "account_id is required in the provider block or in the resource") +} + func TestResourceVPCEndpointList(t *testing.T) { client, server, err := qa.HttpFixtureClient(t, []qa.HTTPFixture{ { diff --git a/mws/resource_mws_workspaces.go b/mws/resource_mws_workspaces.go index fe4754c517..d75d40f2c9 100644 --- a/mws/resource_mws_workspaces.go +++ b/mws/resource_mws_workspaces.go @@ -80,7 +80,7 @@ type externalCustomerInfo struct { // Workspace is the object that contains all the information for deploying a workspace type Workspace struct { - AccountID string `json:"account_id"` + AccountID string `json:"account_id,omitempty" tf:"computed,force_new"` WorkspaceName string `json:"workspace_name"` DeploymentName string `json:"deployment_name,omitempty"` AwsRegion string `json:"aws_region,omitempty"` // required for AWS, not allowed for GCP @@ -617,6 +617,13 @@ func ResourceMwsWorkspaces() common.Resource { var workspace Workspace workspacesAPI := NewWorkspacesAPI(ctx, c) common.DataToStructPointer(d, workspaceSchema, &workspace) + if workspace.AccountID == "" { + if c.Config == nil || c.Config.AccountID == "" { + return fmt.Errorf("account_id is required in the provider block or in the workspace resource") + } + workspace.AccountID = c.Config.AccountID + d.Set("account_id", workspace.AccountID) + } if c.IsAws() { if _, ok := d.GetOk("aws_region"); !ok { return fmt.Errorf("aws_region is required for AWS workspaces") @@ -690,6 +697,9 @@ func ResourceMwsWorkspaces() common.Resource { Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { var workspace Workspace common.DataToStructPointer(d, workspaceSchema, &workspace) + if workspace.AccountID == "" { + workspace.AccountID = c.Config.AccountID + } if len(workspace.CustomerManagedKeyID) > 0 && len(workspace.ManagedServicesCustomerManagedKeyID) == 0 { log.Print("[INFO] Using existing customer_managed_key_id as value for new managed_services_customer_managed_key_id") workspace.ManagedServicesCustomerManagedKeyID = workspace.CustomerManagedKeyID diff --git a/mws/resource_mws_workspaces_test.go b/mws/resource_mws_workspaces_test.go index 099ccc424f..3d23eca78c 100644 --- a/mws/resource_mws_workspaces_test.go +++ b/mws/resource_mws_workspaces_test.go @@ -17,55 +17,58 @@ import ( "github.com/stretchr/testify/require" ) -func TestResourceWorkspaceCreate(t *testing.T) { - d, err := qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - { - Method: "POST", - Resource: "/api/2.0/accounts/abc/workspaces", - ExpectedRequest: Workspace{ - AccountID: "abc", - IsNoPublicIPEnabled: true, - WorkspaceName: "labdata", - DeploymentName: "900150983cd24fb0", - AwsRegion: "us-east-1", - CredentialsID: "bcd", - StorageConfigurationID: "ghi", - NetworkID: "fgh", - ManagedServicesCustomerManagedKeyID: "def", - StorageCustomerManagedKeyID: "def", - CustomTags: map[string]string{ - "SoldToCode": "1234", - }, - }, - Response: Workspace{ - WorkspaceID: 1234, - AccountID: "abc", - DeploymentName: "900150983cd24fb0", - }, +var workspaceCreateFixtures = []qa.HTTPFixture{ + { + Method: "POST", + Resource: "/api/2.0/accounts/abc/workspaces", + ExpectedRequest: Workspace{ + AccountID: "abc", + IsNoPublicIPEnabled: true, + WorkspaceName: "labdata", + DeploymentName: "900150983cd24fb0", + AwsRegion: "us-east-1", + CredentialsID: "bcd", + StorageConfigurationID: "ghi", + NetworkID: "fgh", + ManagedServicesCustomerManagedKeyID: "def", + StorageCustomerManagedKeyID: "def", + CustomTags: map[string]string{ + "SoldToCode": "1234", }, - { - Method: "GET", - ReuseRequest: true, - Resource: "/api/2.0/accounts/abc/workspaces/1234", - Response: Workspace{ - WorkspaceID: 1234, - WorkspaceStatus: WorkspaceStatusRunning, - WorkspaceName: "labdata", - DeploymentName: "900150983cd24fb0", - AwsRegion: "us-east-1", - CredentialsID: "bcd", - StorageConfigurationID: "ghi", - NetworkID: "fgh", - ManagedServicesCustomerManagedKeyID: "def", - StorageCustomerManagedKeyID: "def", - AccountID: "abc", - CustomTags: map[string]string{ - "SoldToCode": "1234", - }, - }, + }, + Response: Workspace{ + WorkspaceID: 1234, + AccountID: "abc", + DeploymentName: "900150983cd24fb0", + }, + ReuseRequest: true, + }, + { + Method: "GET", + ReuseRequest: true, + Resource: "/api/2.0/accounts/abc/workspaces/1234", + Response: Workspace{ + WorkspaceID: 1234, + WorkspaceStatus: WorkspaceStatusRunning, + WorkspaceName: "labdata", + DeploymentName: "900150983cd24fb0", + AwsRegion: "us-east-1", + CredentialsID: "bcd", + StorageConfigurationID: "ghi", + NetworkID: "fgh", + ManagedServicesCustomerManagedKeyID: "def", + StorageCustomerManagedKeyID: "def", + AccountID: "abc", + CustomTags: map[string]string{ + "SoldToCode": "1234", }, }, + }, +} + +func TestResourceWorkspaceCreate(t *testing.T) { + qa.ResourceFixture{ + Fixtures: workspaceCreateFixtures, Resource: ResourceMwsWorkspaces(), State: map[string]any{ "account_id": "abc", @@ -82,9 +85,48 @@ func TestResourceWorkspaceCreate(t *testing.T) { }, }, Create: true, - }.Apply(t) - assert.NoError(t, err) - assert.Equal(t, "abc/1234", d.Id()) + }.ApplyAndExpectData(t, map[string]any{ + "id": "abc/1234", + }) +} + +func TestResourceWorkspaceCreate_NoAccountIDInResource(t *testing.T) { + qa.ResourceFixture{ + Fixtures: workspaceCreateFixtures, + Resource: ResourceMwsWorkspaces(), + State: map[string]any{ + "aws_region": "us-east-1", + "credentials_id": "bcd", + "managed_services_customer_managed_key_id": "def", + "storage_customer_managed_key_id": "def", + "deployment_name": "900150983cd24fb0", + "workspace_name": "labdata", + "network_id": "fgh", + "storage_configuration_id": "ghi", + "custom_tags": map[string]any{ + "SoldToCode": "1234", + }, + }, + AccountID: "abc", + Create: true, + }.ApplyAndExpectData(t, map[string]any{ + "account_id": "abc", + "id": "abc/1234", + }) +} + +func TestResourceWorkspaceCreate_NoAccountID(t *testing.T) { + qa.ResourceFixture{ + Fixtures: workspaceCreateFixtures, + Resource: ResourceMwsWorkspaces(), + State: map[string]any{ + "aws_region": "us-east-1", + "network_id": "fgh", + "storage_configuration_id": "ghi", + "workspace_name": "labdata", + }, + Create: true, + }.ExpectError(t, "account_id is required in the provider block or in the workspace resource") } func TestResourceWorkspaceCreateGcp(t *testing.T) {