diff --git a/access/resource_ip_access_list.go b/access/resource_ip_access_list.go index 5b899ffd7a..1792d73f67 100644 --- a/access/resource_ip_access_list.go +++ b/access/resource_ip_access_list.go @@ -11,6 +11,7 @@ import ( ) type ipAccessListUpdateRequest struct { + common.Namespace Label string `json:"label"` ListType settings.ListType `json:"list_type"` IpAddresses []string `json:"ip_addresses"` @@ -26,12 +27,16 @@ func ResourceIPAccessList() common.Resource { Type: schema.TypeString, ValidateFunc: validation.Any(validation.IsIPv4Address, validation.IsCIDR), } + common.NamespaceCustomizeSchemaMap(s) return s }) return common.Resource{ Schema: s, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -45,7 +50,7 @@ func ResourceIPAccessList() common.Resource { return nil }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -57,7 +62,7 @@ func ResourceIPAccessList() common.Resource { return nil }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -67,7 +72,7 @@ func ResourceIPAccessList() common.Resource { return w.IpAccessLists.Update(ctx, iacl) }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } diff --git a/aws/data_aws_crossaccount_policy.go b/aws/data_aws_crossaccount_policy.go index 5ac0a3866e..3b8f68195f 100644 --- a/aws/data_aws_crossaccount_policy.go +++ b/aws/data_aws_crossaccount_policy.go @@ -14,6 +14,7 @@ import ( // DataAwsCrossaccountPolicy defines the cross-account policy func DataAwsCrossaccountPolicy() common.Resource { type AwsCrossAccountPolicy struct { + common.Namespace PolicyType string `json:"policy_type,omitempty" tf:"default:managed"` PassRole []string `json:"pass_roles,omitempty"` JSON string `json:"json" tf:"computed"` diff --git a/aws/data_aws_unity_catalog_assume_role_policy.go b/aws/data_aws_unity_catalog_assume_role_policy.go index 4aadceeafa..ac514e9378 100644 --- a/aws/data_aws_unity_catalog_assume_role_policy.go +++ b/aws/data_aws_unity_catalog_assume_role_policy.go @@ -12,6 +12,7 @@ import ( func DataAwsUnityCatalogAssumeRolePolicy() common.Resource { type AwsUcAssumeRolePolicy struct { + common.Namespace RoleName string `json:"role_name"` UnityCatalogIamArn string `json:"unity_catalog_iam_arn,omitempty" tf:"computed"` ExternalId string `json:"external_id"` diff --git a/aws/data_instance_profiles.go b/aws/data_instance_profiles.go index 0679a4564a..7c71964136 100644 --- a/aws/data_instance_profiles.go +++ b/aws/data_instance_profiles.go @@ -16,6 +16,7 @@ func DataSourceInstanceProfiles() common.Resource { IsMeta bool `json:"is_meta,omitempty" tf:"computed"` } return common.WorkspaceData(func(ctx context.Context, data *struct { + common.Namespace InstanceProfiles []instanceProfileData `json:"instance_profiles,omitempty" tf:"computed"` }, w *databricks.WorkspaceClient) error { instanceProfiles, err := w.InstanceProfiles.ListAll(ctx) diff --git a/aws/resource_instance_profile.go b/aws/resource_instance_profile.go index 886681fa1f..1f38931e10 100644 --- a/aws/resource_instance_profile.go +++ b/aws/resource_instance_profile.go @@ -18,6 +18,7 @@ import ( // InstanceProfileInfo contains the ARN for aws instance profiles type InstanceProfileInfo struct { + common.Namespace InstanceProfileArn string `json:"instance_profile_arn"` IamRoleArn string `json:"iam_role_arn,omitempty"` IsMetaInstanceProfile bool `json:"is_meta_instance_profile,omitempty"` @@ -157,10 +158,14 @@ func ResourceInstanceProfile() common.Resource { } return false } + common.NamespaceCustomizeSchemaMap(m) return m }) return common.Resource{ Schema: instanceProfileSchema, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { profile, err := NewInstanceProfilesAPI(ctx, c).Read(d.Id()) if err != nil { diff --git a/catalog/data_catalog.go b/catalog/data_catalog.go index 23dc3325f6..217df088a2 100644 --- a/catalog/data_catalog.go +++ b/catalog/data_catalog.go @@ -10,6 +10,7 @@ import ( func DataSourceCatalog() common.Resource { return common.WorkspaceData(func(ctx context.Context, data *struct { + common.Namespace Id string `json:"id,omitempty" tf:"computed"` Name string `json:"name"` Catalog *catalog.CatalogInfo `json:"catalog_info,omitempty" tf:"computed"` diff --git a/catalog/data_catalogs.go b/catalog/data_catalogs.go index 42803da34a..1c1a6721df 100644 --- a/catalog/data_catalogs.go +++ b/catalog/data_catalogs.go @@ -10,6 +10,7 @@ import ( func DataSourceCatalogs() common.Resource { return common.WorkspaceData(func(ctx context.Context, data *struct { + common.Namespace Ids []string `json:"ids,omitempty" tf:"computed,slice_set"` }, w *databricks.WorkspaceClient) error { catalogs, err := w.Catalogs.ListAll(ctx, catalog.ListCatalogsRequest{}) diff --git a/catalog/data_current_metastore.go b/catalog/data_current_metastore.go index 084c38638d..3a2b67d2d2 100644 --- a/catalog/data_current_metastore.go +++ b/catalog/data_current_metastore.go @@ -11,6 +11,7 @@ import ( func DataSourceCurrentMetastore() common.Resource { type CurrentMetastore struct { + common.Namespace Id string `json:"id,omitempty" tf:"computed"` Metastore *catalog.GetMetastoreSummaryResponse `json:"metastore_info,omitempty" tf:"computed" ` } diff --git a/catalog/data_external_location.go b/catalog/data_external_location.go index cc97683e02..23e8b17d33 100644 --- a/catalog/data_external_location.go +++ b/catalog/data_external_location.go @@ -10,6 +10,7 @@ import ( func DataSourceExternalLocation() common.Resource { type ExternalLocationByID struct { + common.Namespace Id string `json:"id,omitempty" tf:"computed"` Name string `json:"name"` ExternalLocation *catalog.ExternalLocationInfo `json:"external_location_info,omitempty" tf:"computed" ` diff --git a/catalog/data_external_locations.go b/catalog/data_external_locations.go index a2e629bbdb..c984ee73ef 100644 --- a/catalog/data_external_locations.go +++ b/catalog/data_external_locations.go @@ -10,6 +10,7 @@ import ( func DataSourceExternalLocations() common.Resource { type externalLocationsData struct { + common.Namespace Names []string `json:"names,omitempty" tf:"computed"` } return common.WorkspaceData(func(ctx context.Context, data *externalLocationsData, w *databricks.WorkspaceClient) error { diff --git a/catalog/data_metastore.go b/catalog/data_metastore.go index aa6427d5fe..db725bc06e 100644 --- a/catalog/data_metastore.go +++ b/catalog/data_metastore.go @@ -12,6 +12,7 @@ import ( func DataSourceMetastore() common.Resource { type AccountMetastoreByID struct { + common.Namespace Id string `json:"id,omitempty" tf:"computed"` MetastoreId string `json:"metastore_id,omitempty" tf:"computed"` Name string `json:"name,omitempty" tf:"computed"` diff --git a/catalog/data_metastores.go b/catalog/data_metastores.go index f6fe312972..5323d2e4a2 100644 --- a/catalog/data_metastores.go +++ b/catalog/data_metastores.go @@ -10,6 +10,7 @@ import ( func DataSourceMetastores() common.Resource { type metastoresData struct { + common.Namespace Ids map[string]string `json:"ids,omitempty" tf:"computed"` } return common.AccountData(func(ctx context.Context, data *metastoresData, acc *databricks.AccountClient) error { diff --git a/catalog/data_schema.go b/catalog/data_schema.go index d93a0f682a..f2436320a8 100644 --- a/catalog/data_schema.go +++ b/catalog/data_schema.go @@ -10,6 +10,7 @@ import ( func DataSourceSchema() common.Resource { return common.WorkspaceData(func(ctx context.Context, data *struct { + common.Namespace Id string `json:"id,omitempty" tf:"computed"` Name string `json:"name"` Schema *catalog.SchemaInfo `json:"schema_info,omitempty" tf:"computed"` diff --git a/catalog/data_schemas.go b/catalog/data_schemas.go index 73a2ded5b0..bc070d6c54 100644 --- a/catalog/data_schemas.go +++ b/catalog/data_schemas.go @@ -10,6 +10,7 @@ import ( func DataSourceSchemas() common.Resource { return common.WorkspaceData(func(ctx context.Context, data *struct { + common.Namespace CatalogName string `json:"catalog_name"` Ids []string `json:"ids,omitempty" tf:"computed,slice_set"` }, w *databricks.WorkspaceClient) error { diff --git a/catalog/data_storage_credential.go b/catalog/data_storage_credential.go index f57a38f026..d1f4b1be63 100644 --- a/catalog/data_storage_credential.go +++ b/catalog/data_storage_credential.go @@ -10,6 +10,7 @@ import ( func DataSourceStorageCredential() common.Resource { type AccountMetastoreByID struct { + common.Namespace Id string `json:"id,omitempty" tf:"computed"` Name string `json:"name"` StorageCredential *catalog.StorageCredentialInfo `json:"storage_credential_info,omitempty" tf:"computed" ` diff --git a/catalog/data_storage_credentials.go b/catalog/data_storage_credentials.go index 228610e874..516b391034 100644 --- a/catalog/data_storage_credentials.go +++ b/catalog/data_storage_credentials.go @@ -10,6 +10,7 @@ import ( func DataSourceStorageCredentials() common.Resource { type storageCredentialsData struct { + common.Namespace Names []string `json:"names,omitempty" tf:"computed"` } return common.WorkspaceData(func(ctx context.Context, data *storageCredentialsData, w *databricks.WorkspaceClient) error { diff --git a/catalog/data_table.go b/catalog/data_table.go index 299310192b..dd560624a2 100644 --- a/catalog/data_table.go +++ b/catalog/data_table.go @@ -10,6 +10,7 @@ import ( func DataSourceTable() common.Resource { return common.WorkspaceData(func(ctx context.Context, data *struct { + common.Namespace Id string `json:"id,omitempty" tf:"computed"` Name string `json:"name"` Table *catalog.TableInfo `json:"table_info,omitempty" tf:"computed"` diff --git a/catalog/data_tables.go b/catalog/data_tables.go index e1aca33cd4..a96a73802b 100644 --- a/catalog/data_tables.go +++ b/catalog/data_tables.go @@ -10,6 +10,7 @@ import ( func DataSourceTables() common.Resource { return common.WorkspaceData(func(ctx context.Context, data *struct { + common.Namespace CatalogName string `json:"catalog_name"` SchemaName string `json:"schema_name"` Ids []string `json:"ids,omitempty" tf:"computed,slice_set"` diff --git a/catalog/data_views.go b/catalog/data_views.go index b4e4255c83..68b5efdab1 100644 --- a/catalog/data_views.go +++ b/catalog/data_views.go @@ -10,6 +10,7 @@ import ( func DataSourceViews() common.Resource { return common.WorkspaceData(func(ctx context.Context, data *struct { + common.Namespace CatalogName string `json:"catalog_name"` SchemaName string `json:"schema_name"` Ids []string `json:"ids,omitempty" tf:"computed,slice_set"` diff --git a/catalog/data_volume.go b/catalog/data_volume.go index 598160206a..a05fdf87a1 100644 --- a/catalog/data_volume.go +++ b/catalog/data_volume.go @@ -10,6 +10,7 @@ import ( func DataSourceVolume() common.Resource { return common.WorkspaceData(func(ctx context.Context, data *struct { + common.Namespace Id string `json:"id,omitempty" tf:"computed"` Name string `json:"name"` Volume *catalog.VolumeInfo `json:"volume_info,omitempty" tf:"computed"` diff --git a/catalog/data_volumes.go b/catalog/data_volumes.go index 903e7f0bb9..dfa2a3bbf3 100644 --- a/catalog/data_volumes.go +++ b/catalog/data_volumes.go @@ -10,6 +10,7 @@ import ( func DataSourceVolumes() common.Resource { return common.WorkspaceData(func(ctx context.Context, data *struct { + common.Namespace CatalogName string `json:"catalog_name"` SchemaName string `json:"schema_name"` Ids []string `json:"ids,omitempty" tf:"computed,slice_set"` diff --git a/catalog/resource_artifact_allowlist.go b/catalog/resource_artifact_allowlist.go index 9ce2e10467..a2012e237d 100644 --- a/catalog/resource_artifact_allowlist.go +++ b/catalog/resource_artifact_allowlist.go @@ -9,6 +9,7 @@ import ( ) type ArtifactAllowlistInfo struct { + common.Namespace // A list of allowed artifact match patterns. ArtifactMatchers []catalog.ArtifactMatcher `json:"artifact_matchers" tf:"slice_set,alias:artifact_matcher"` // The artifact type of the allowlist. @@ -21,12 +22,17 @@ type ArtifactAllowlistInfo struct { MetastoreId string `json:"metastore_id,omitempty" tf:"computed"` } +func (ArtifactAllowlistInfo) CustomizeSchema(s *common.CustomizableSchema) *common.CustomizableSchema { + common.NamespaceCustomizeSchema(s) + return s +} + func ResourceArtifactAllowlist() common.Resource { - allowlistSchema := common.StructToSchema(ArtifactAllowlistInfo{}, common.NoCustomize) + allowlistSchema := common.StructToSchema(ArtifactAllowlistInfo{}, nil) p := common.NewPairID("metastore_id", "artifact_type") createOrUpdate := func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -53,9 +59,12 @@ func ResourceArtifactAllowlist() common.Resource { } return common.Resource{ Schema: allowlistSchema, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, Create: createOrUpdate, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -82,7 +91,7 @@ func ResourceArtifactAllowlist() common.Resource { }, Update: createOrUpdate, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } diff --git a/catalog/resource_catalog.go b/catalog/resource_catalog.go index db7f70cdc8..f4d5097e7c 100644 --- a/catalog/resource_catalog.go +++ b/catalog/resource_catalog.go @@ -28,8 +28,13 @@ func ucDirectoryPathSlashAndEmptySuppressDiff(k, old, new string, d *schema.Reso return false } +type CatalogInfo struct { + catalog.CatalogInfo + common.Namespace +} + func ResourceCatalog() common.Resource { - catalogSchema := common.StructToSchema(catalog.CatalogInfo{}, + catalogSchema := common.StructToSchema(CatalogInfo{}, func(s map[string]*schema.Schema) map[string]*schema.Schema { s["force_destroy"] = &schema.Schema{ Type: schema.TypeBool, @@ -58,12 +63,13 @@ func ResourceCatalog() common.Resource { common.CustomizeSchemaPath(s, v).SetReadOnly() } common.CustomizeSchemaPath(s, "effective_predictive_optimization_flag").SetComputed().SetSuppressDiff() + common.NamespaceCustomizeSchemaMap(s) return s }) return common.Resource{ Schema: catalogSchema, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -107,7 +113,7 @@ func ResourceCatalog() common.Resource { return bindings.AddCurrentWorkspaceBindings(ctx, d, w, ci.Name, bindings.BindingsSecurableTypeCatalog) }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -119,7 +125,7 @@ func ResourceCatalog() common.Resource { return common.StructToData(ci, catalogSchema, d) }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -188,7 +194,7 @@ func ResourceCatalog() common.Resource { return bindings.AddCurrentWorkspaceBindings(ctx, d, w, ci.Name, bindings.BindingsSecurableTypeCatalog) }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -242,7 +248,7 @@ func ResourceCatalog() common.Resource { } } } - return nil + return common.NamespaceCustomizeDiff(d) }, } } diff --git a/catalog/resource_connection.go b/catalog/resource_connection.go index 10a7fac257..6d50e13250 100644 --- a/catalog/resource_connection.go +++ b/catalog/resource_connection.go @@ -10,6 +10,11 @@ import ( "golang.org/x/exp/slices" ) +type ConnectionInfo struct { + catalog.ConnectionInfo + common.Namespace +} + var sensitiveOptions = []string{"user", "password", "personalAccessToken", "access_token", "client_secret", "pem_private_key", "OAuthPvtKey", "GoogleServiceAccountKeyJson", "bearer_token"} @@ -26,7 +31,7 @@ func suppressComputedFields(k, old, new string, d *schema.ResourceData) bool { } func ResourceConnection() common.Resource { - s := common.StructToSchema(catalog.ConnectionInfo{}, + s := common.StructToSchema(ConnectionInfo{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { for _, v := range []string{"url", "metastore_id", "credential_type", "connection_id", "created_at", "created_by", "full_name", "provisioning_info", "securable_type", "updated_at", "updated_by"} { @@ -40,7 +45,7 @@ func ResourceConnection() common.Resource { } common.CustomizeSchemaPath(m, "options").SetSensitive().SetCustomSuppressDiff(suppressComputedFields) common.CustomizeSchemaPath(m, "name").SetCustomSuppressDiff(common.EqualFoldDiffSuppress) - + common.NamespaceCustomizeSchemaMap(m) return m }) pi := common.NewPairID("metastore_id", "name").Schema( @@ -50,7 +55,7 @@ func ResourceConnection() common.Resource { return common.Resource{ Schema: s, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -79,7 +84,7 @@ func ResourceConnection() common.Resource { return nil }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -113,7 +118,7 @@ func ResourceConnection() common.Resource { return common.StructToData(conn, s, d) }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -161,7 +166,7 @@ func ResourceConnection() common.Resource { return nil }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -171,5 +176,8 @@ func ResourceConnection() common.Resource { } return w.Connections.DeleteByName(ctx, connName) }, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, } } diff --git a/catalog/resource_credential.go b/catalog/resource_credential.go index 634a1c5531..3b71d5be64 100644 --- a/catalog/resource_credential.go +++ b/catalog/resource_credential.go @@ -9,7 +9,12 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -var credentialSchema = common.StructToSchema(catalog.CredentialInfo{}, +type CredentialInfo struct { + catalog.CredentialInfo + common.Namespace +} + +var credentialSchema = common.StructToSchema(CredentialInfo{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { var alofServiceCreds = []string{"aws_iam_role", "azure_managed_identity", "azure_service_principal", "databricks_gcp_service_account"} @@ -55,6 +60,7 @@ var credentialSchema = common.StructToSchema(catalog.CredentialInfo{}, Computed: true, } m["name"].DiffSuppressFunc = common.EqualFoldDiffSuppress + common.NamespaceCustomizeSchemaMap(m) return m }) @@ -62,7 +68,7 @@ func ResourceCredential() common.Resource { return common.Resource{ Schema: credentialSchema, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -94,7 +100,7 @@ func ResourceCredential() common.Resource { return bindings.AddCurrentWorkspaceBindings(ctx, d, w, cred.Name, bindings.BindingsSecurableTypeCredential) }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -115,7 +121,7 @@ func ResourceCredential() common.Resource { }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { force := d.Get("force_update").(bool) - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -173,7 +179,7 @@ func ResourceCredential() common.Resource { }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { force := d.Get("force_destroy").(bool) - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -182,5 +188,8 @@ func ResourceCredential() common.Resource { Force: force, }) }, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, } } diff --git a/catalog/resource_external_location.go b/catalog/resource_external_location.go index cbc445da26..d10d0ffa40 100644 --- a/catalog/resource_external_location.go +++ b/catalog/resource_external_location.go @@ -12,6 +12,7 @@ import ( // This structure contains the fields of both catalog.UpdateExternalLocation and catalog.CreateExternalLocation type ExternalLocationInfo struct { catalog.ExternalLocationInfo + common.Namespace SkipValidation bool `json:"skip_validation,omitempty"` } @@ -57,12 +58,16 @@ func ResourceExternalLocation() common.Resource { common.CustomizeSchemaPath(m, "file_event_queue", "managed_aqs", "subscription_id").SetRequired() common.CustomizeSchemaPath(m, "file_event_queue").SetMaxItems(1) + common.NamespaceCustomizeSchemaMap(m) return m }) return common.Resource{ Schema: s, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -95,7 +100,7 @@ func ResourceExternalLocation() common.Resource { return bindings.AddCurrentWorkspaceBindings(ctx, d, w, el.Name, bindings.BindingsSecurableTypeExternalLocation) }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -107,7 +112,7 @@ func ResourceExternalLocation() common.Resource { }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { force := d.Get("force_update").(bool) - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -184,7 +189,7 @@ func ResourceExternalLocation() common.Resource { }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { force := d.Get("force_destroy").(bool) - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } diff --git a/catalog/resource_grant.go b/catalog/resource_grant.go index 60a77f5da9..7bb9fa6f38 100644 --- a/catalog/resource_grant.go +++ b/catalog/resource_grant.go @@ -14,6 +14,11 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) +type UnityCatalogPrivilegeAssignment struct { + permissions.UnityCatalogPrivilegeAssignment + common.Namespace +} + // diffPermissionsForPrincipal returns an array of catalog.PermissionsChange of this permissions list with `diff` privileges removed func diffPermissionsForPrincipal(principal string, desired []catalog.PrivilegeAssignment, existing []catalog.PrivilegeAssignment) (diff []catalog.PermissionsChange) { // diffs change sets for principal @@ -127,7 +132,7 @@ func parseSecurableId(d *schema.ResourceData) (string, string, string, error) { } func ResourceGrant() common.Resource { - s := common.StructToSchema(permissions.UnityCatalogPrivilegeAssignment{}, + s := common.StructToSchema(UnityCatalogPrivilegeAssignment{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { common.CustomizeSchemaPath(m, "principal").SetForceNew() @@ -150,13 +155,14 @@ func ResourceGrant() common.Resource { ConflictsWith: permissions.SliceWithoutString(allFields, field), } } + common.NamespaceCustomizeSchemaMap(m) return m }) return common.Resource{ Schema: s, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -203,7 +209,7 @@ func ResourceGrant() common.Resource { return d.Set(securable, name) }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -228,7 +234,7 @@ func ResourceGrant() common.Resource { return replacePermissionsForPrincipal(unityCatalogPermissionsAPI, securable, name, principal, grants) }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -243,5 +249,8 @@ func ResourceGrant() common.Resource { unityCatalogPermissionsAPI := permissions.NewUnityCatalogPermissionsAPI(ctx, c) return replacePermissionsForPrincipal(unityCatalogPermissionsAPI, securable, name, principal, catalog.GetPermissionsResponse{}) }, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, } } diff --git a/catalog/resource_grants.go b/catalog/resource_grants.go index ddaf5b76ab..4935116847 100644 --- a/catalog/resource_grants.go +++ b/catalog/resource_grants.go @@ -23,6 +23,7 @@ type PrivilegeAssignment struct { // PermissionsList reflects it's shape on terraform resource with // privilege_assignments column renamed to `grant` block for simplicity type PermissionsList struct { + common.Namespace Assignments []PrivilegeAssignment `json:"privilege_assignments" tf:"slice_set,alias:grant"` } @@ -155,12 +156,16 @@ func ResourceGrants() common.Resource { for field := range permissions.Mappings { s[field].AtLeastOneOf = alof } + common.NamespaceCustomizeSchemaMap(s) return s }) return common.Resource{ Schema: s, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -204,7 +209,7 @@ func ResourceGrants() common.Resource { return d.Set(securable, name) }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -222,7 +227,7 @@ func ResourceGrants() common.Resource { return replaceAllPermissions(unityCatalogPermissionsAPI, securable, name, grants.toSdkPermissionsList()) }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } diff --git a/catalog/resource_metastore.go b/catalog/resource_metastore.go index b831fad042..a6ef8afe9f 100644 --- a/catalog/resource_metastore.go +++ b/catalog/resource_metastore.go @@ -14,6 +14,7 @@ import ( ) type MetastoreInfo struct { + common.Namespace Name string `json:"name"` StorageRoot string `json:"storage_root,omitempty" tf:"force_new"` DefaultDacID string `json:"default_data_access_config_id,omitempty" tf:"suppress_diff"` @@ -56,11 +57,15 @@ func ResourceMetastore() common.Resource { return false } m["name"].DiffSuppressFunc = common.EqualFoldDiffSuppress + common.NamespaceCustomizeSchemaMap(m) return m }) return common.Resource{ Schema: s, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { var create catalog.CreateMetastore var update catalog.UpdateMetastore diff --git a/catalog/resource_online_table.go b/catalog/resource_online_table.go index 7e658b6f48..bc5ac4b5a0 100644 --- a/catalog/resource_online_table.go +++ b/catalog/resource_online_table.go @@ -16,6 +16,11 @@ import ( const onlineTableDefaultProvisionTimeout = 90 * time.Minute +type OnlineTable struct { + catalog.OnlineTable + common.Namespace +} + func waitForOnlineTableDeletion(w *databricks.WorkspaceClient, ctx context.Context, onlineTableName string) error { return retry.RetryContext(ctx, onlineTableDefaultProvisionTimeout, func() *retry.RetryError { _, err := w.OnlineTables.GetByName(ctx, onlineTableName) @@ -30,7 +35,7 @@ func waitForOnlineTableDeletion(w *databricks.WorkspaceClient, ctx context.Conte } func ResourceOnlineTable() common.Resource { - s := common.StructToSchema(catalog.OnlineTable{}, + s := common.StructToSchema(OnlineTable{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { m["name"].DiffSuppressFunc = common.EqualFoldDiffSuppress common.CustomizeSchemaPath(m, "spec", "source_table_full_name").SetCustomSuppressDiff(common.EqualFoldDiffSuppress) @@ -43,12 +48,13 @@ func ResourceOnlineTable() common.Resource { runTypes := []string{"spec.0.run_triggered", "spec.0.run_continuously"} common.CustomizeSchemaPath(m, "spec", "run_triggered").SetAtLeastOneOf(runTypes).SetSuppressDiff() common.CustomizeSchemaPath(m, "spec", "run_continuously").SetAtLeastOneOf(runTypes).SetSuppressDiff() + common.NamespaceCustomizeSchemaMap(m) return m }) return common.Resource{ Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -69,7 +75,7 @@ func ResourceOnlineTable() common.Resource { return nil }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -80,7 +86,7 @@ func ResourceOnlineTable() common.Resource { return common.StructToData(*table, s, d) }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -96,5 +102,8 @@ func ResourceOnlineTable() common.Resource { Timeouts: &schema.ResourceTimeout{ Create: schema.DefaultTimeout(onlineTableDefaultProvisionTimeout), }, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, } } diff --git a/catalog/resource_quality_monitor.go b/catalog/resource_quality_monitor.go index c6450a0d93..ee621cf338 100644 --- a/catalog/resource_quality_monitor.go +++ b/catalog/resource_quality_monitor.go @@ -14,6 +14,11 @@ import ( const qualityMonitorDefaultProvisionTimeout = 15 * time.Minute +type MonitorInfo struct { + catalog.MonitorInfo + common.Namespace +} + func WaitForMonitor(w *databricks.WorkspaceClient, ctx context.Context, monitorName string) error { return retry.RetryContext(ctx, qualityMonitorDefaultProvisionTimeout, func() *retry.RetryError { endpoint, err := w.QualityMonitors.Get(ctx, catalog.GetQualityMonitorRequest{ @@ -35,7 +40,7 @@ func WaitForMonitor(w *databricks.WorkspaceClient, ctx context.Context, monitorN func ResourceQualityMonitor() common.Resource { monitorSchema := common.StructToSchema( - catalog.MonitorInfo{}, + MonitorInfo{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { common.CustomizeSchemaPath(m, "assets_dir").SetRequired() common.CustomizeSchemaPath(m, "output_schema_name").SetRequired() @@ -56,13 +61,14 @@ func ResourceQualityMonitor() common.Resource { common.CustomizeSchemaPath(m, "status").SetReadOnly() common.CustomizeSchemaPath(m, "dashboard_id").SetReadOnly() common.CustomizeSchemaPath(m, "schedule", "pause_status").SetReadOnly() + common.NamespaceCustomizeSchemaMap(m) return m }, ) return common.Resource{ Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -83,7 +89,7 @@ func ResourceQualityMonitor() common.Resource { return nil }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -108,7 +114,7 @@ func ResourceQualityMonitor() common.Resource { return nil }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -125,7 +131,7 @@ func ResourceQualityMonitor() common.Resource { return WaitForMonitor(w, ctx, update.TableName) }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -138,5 +144,8 @@ func ResourceQualityMonitor() common.Resource { Timeouts: &schema.ResourceTimeout{ Create: schema.DefaultTimeout(qualityMonitorDefaultProvisionTimeout), }, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, } } diff --git a/catalog/resource_registered_model.go b/catalog/resource_registered_model.go index 9a211a7047..d6f68f8fe2 100644 --- a/catalog/resource_registered_model.go +++ b/catalog/resource_registered_model.go @@ -8,9 +8,14 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) +type CreateRegisteredModelRequest struct { + catalog.CreateRegisteredModelRequest + common.Namespace +} + func ResourceRegisteredModel() common.Resource { s := common.StructToSchema( - catalog.CreateRegisteredModelRequest{}, + CreateRegisteredModelRequest{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { caseInsensitiveFields := []string{"name", "catalog_name", "schema_name"} for _, field := range caseInsensitiveFields { @@ -26,13 +31,13 @@ func ResourceRegisteredModel() common.Resource { Computed: true, Optional: true, } - + common.NamespaceCustomizeSchemaMap(m) return m }) return common.Resource{ Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -58,7 +63,7 @@ func ResourceRegisteredModel() common.Resource { return nil }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -69,7 +74,7 @@ func ResourceRegisteredModel() common.Resource { return common.StructToData(*model, s, d) }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -115,7 +120,7 @@ func ResourceRegisteredModel() common.Resource { return err }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -124,5 +129,8 @@ func ResourceRegisteredModel() common.Resource { StateUpgraders: []schema.StateUpgrader{}, Schema: s, SchemaVersion: 0, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, } } diff --git a/catalog/resource_schema.go b/catalog/resource_schema.go index 7d2f895da6..4cd51b0275 100644 --- a/catalog/resource_schema.go +++ b/catalog/resource_schema.go @@ -10,6 +10,7 @@ import ( ) type SchemaInfo struct { + common.Namespace Name string `json:"name" tf:"force_new"` CatalogName string `json:"catalog_name" tf:"force_new"` StorageRoot string `json:"storage_root,omitempty" tf:"force_new"` @@ -38,12 +39,16 @@ func ResourceSchema() common.Resource { common.CustomizeSchemaPath(s, "enable_predictive_optimization").SetValidateFunc( validation.StringInSlice([]string{"DISABLE", "ENABLE", "INHERIT"}, false), ) + common.NamespaceCustomizeSchemaMap(s) return s }) return common.Resource{ Schema: s, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -81,7 +86,7 @@ func ResourceSchema() common.Resource { return nil }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -92,7 +97,7 @@ func ResourceSchema() common.Resource { return common.StructToData(schema, s, d) }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -149,7 +154,7 @@ func ResourceSchema() common.Resource { Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { force := d.Get("force_destroy").(bool) name := d.Id() - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } diff --git a/catalog/resource_sql_table.go b/catalog/resource_sql_table.go index 99019c7868..a2ca663c93 100644 --- a/catalog/resource_sql_table.go +++ b/catalog/resource_sql_table.go @@ -45,6 +45,7 @@ const IdentityColumnAlways IdentityColumn = "always" const IdentityColumnDefault IdentityColumn = "default" type SqlTableInfo struct { + common.Namespace Name string `json:"name"` CatalogName string `json:"catalog_name" tf:"force_new"` SchemaName string `json:"schema_name" tf:"force_new"` @@ -71,6 +72,7 @@ type SqlTableInfo struct { } func (ti SqlTableInfo) CustomizeSchema(s *common.CustomizableSchema) *common.CustomizableSchema { + common.NamespaceCustomizeSchema(s) caseInsensitiveFields := []string{"name", "catalog_name", "schema_name"} for _, field := range caseInsensitiveFields { s.SchemaPath(field).SetCustomSuppressDiff(common.EqualFoldDiffSuppress) @@ -175,7 +177,7 @@ func (ti *SqlTableInfo) initCluster(ctx context.Context, d *schema.ResourceData, } } ti.exec = c.CommandExecutor(ctx) - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -663,7 +665,7 @@ func ResourceSqlTable() common.Resource { if d.HasChange("comment") && d.Get("table_type") == "VIEW" { d.ForceNew("comment") } - return nil + return common.NamespaceCustomizeDiff(d) }, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { var ti = new(SqlTableInfo) @@ -675,7 +677,7 @@ func ResourceSqlTable() common.Resource { return err } if ti.Owner != "" { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -695,7 +697,7 @@ func ResourceSqlTable() common.Resource { if err != nil { return err } - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -729,7 +731,7 @@ func ResourceSqlTable() common.Resource { return common.StructToData(ti, tableSchema, d) }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } diff --git a/catalog/resource_storage_credential.go b/catalog/resource_storage_credential.go index 3eb88c0022..2dbfe5282a 100644 --- a/catalog/resource_storage_credential.go +++ b/catalog/resource_storage_credential.go @@ -13,6 +13,7 @@ import ( ) type StorageCredentialInfo struct { + common.Namespace Name string `json:"name" tf:"force_new"` Owner string `json:"owner,omitempty" tf:"computed"` Comment string `json:"comment,omitempty"` @@ -36,6 +37,7 @@ var storageCredentialSchema = common.StructToSchema(StorageCredentialInfo{}, } common.MustSchemaPath(m, "databricks_gcp_service_account", "email").Computed = true common.MustSchemaPath(m, "databricks_gcp_service_account", "credential_id").Computed = true + common.NamespaceCustomizeSchemaMap(m) return adjustDataAccessSchema(m) }) @@ -75,6 +77,9 @@ func parseStorageCredentialId(d *schema.ResourceData) (metastoreId, storageCrede func ResourceStorageCredential() common.Resource { return common.Resource{ Schema: storageCredentialSchema, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { metastoreId := d.Get("metastore_id").(string) diff --git a/catalog/resource_system_schema.go b/catalog/resource_system_schema.go index a8e65db3a1..7c7e7181e0 100644 --- a/catalog/resource_system_schema.go +++ b/catalog/resource_system_schema.go @@ -12,8 +12,13 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) +type SystemSchemaInfo struct { + catalog.SystemSchemaInfo + common.Namespace +} + func ResourceSystemSchema() common.Resource { - systemSchema := common.StructToSchema(catalog.SystemSchemaInfo{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { + systemSchema := common.StructToSchema(SystemSchemaInfo{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { m["metastore_id"] = &schema.Schema{ Type: schema.TypeString, Computed: true, @@ -30,6 +35,7 @@ func ResourceSystemSchema() common.Resource { Type: schema.TypeString, Computed: true, } + common.NamespaceCustomizeSchemaMap(m) return m }) pi := common.NewPairID("metastore_id", "schema").Schema( @@ -44,7 +50,7 @@ func ResourceSystemSchema() common.Resource { return fmt.Errorf("internal type casting error") } log.Printf("[DEBUG] Old system schema: %s, new: %s", old, new) - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -88,7 +94,7 @@ func ResourceSystemSchema() common.Resource { if err != nil { return err } - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -133,7 +139,7 @@ func ResourceSystemSchema() common.Resource { log.Printf("[WARN] %s is auto enabled, ignoring it", schemaName) return nil } - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -143,6 +149,9 @@ func ResourceSystemSchema() common.Resource { } return safeDisable(ctx, w, metastoreSummary.MetastoreId, schemaName) }, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, } } diff --git a/catalog/resource_table.go b/catalog/resource_table.go index 40cdb41ce8..0b4412ca60 100644 --- a/catalog/resource_table.go +++ b/catalog/resource_table.go @@ -33,6 +33,7 @@ type ColumnInfo struct { } type TableInfo struct { + common.Namespace Name string `json:"name"` CatalogName string `json:"catalog_name" tf:"force_new"` SchemaName string `json:"schema_name" tf:"force_new"` @@ -71,6 +72,7 @@ func ResourceTable() common.Resource { for _, field := range caseInsensitiveFields { m[field].DiffSuppressFunc = common.EqualFoldDiffSuppress } + common.NamespaceCustomizeSchemaMap(m) return m }) update := updateFunctionFactory("/unity-catalog/tables", []string{ @@ -80,9 +82,9 @@ func ResourceTable() common.Resource { Schema: tableSchema, CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { if d.Get("table_type") != "EXTERNAL" { - return nil + return common.NamespaceCustomizeDiff(d) } - return nil + return common.NamespaceCustomizeDiff(d) }, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { var ti TableInfo diff --git a/catalog/resource_volume.go b/catalog/resource_volume.go index 3ee2a32542..cfdabf0b18 100644 --- a/catalog/resource_volume.go +++ b/catalog/resource_volume.go @@ -15,6 +15,7 @@ import ( // We need to create this because we need Owner, FullNameArg, SchemaName and CatalogName which aren't present in a single of them. // We also need to annotate tf:"computed" for the Owner field. type VolumeInfo struct { + common.Namespace // The name of the catalog where the schema and the volume are CatalogName string `json:"catalog_name" tf:"force_new"` // The comment attached to the volume @@ -58,12 +59,16 @@ func ResourceVolume() common.Resource { // If server side validation is added in the future, this validation function // can be removed. common.CustomizeSchemaPath(m, "volume_type").SetValidateFunc(validation.StringInSlice([]string{"MANAGED", "EXTERNAL"}, false)) + common.NamespaceCustomizeSchemaMap(m) return m }) return common.Resource{ Schema: s, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -90,7 +95,7 @@ func ResourceVolume() common.Resource { return nil }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -105,7 +110,7 @@ func ResourceVolume() common.Resource { return d.Set("volume_path", "/Volumes/"+strings.ReplaceAll(v.FullName, ".", "/")) }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -163,7 +168,7 @@ func ResourceVolume() common.Resource { return nil }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } diff --git a/catalog/resource_workspace_binding.go b/catalog/resource_workspace_binding.go index cae05bd724..f0a2941dbc 100644 --- a/catalog/resource_workspace_binding.go +++ b/catalog/resource_workspace_binding.go @@ -52,8 +52,13 @@ var getSecurableName = func(d *schema.ResourceData) string { return securableName.(string) } +type WorkspaceBinding struct { + catalog.WorkspaceBinding + common.Namespace +} + func ResourceWorkspaceBinding() common.Resource { - workspaceBindingSchema := common.StructToSchema(catalog.WorkspaceBinding{}, + workspaceBindingSchema := common.StructToSchema(WorkspaceBinding{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { m["catalog_name"] = &schema.Schema{ Type: schema.TypeString, @@ -80,6 +85,7 @@ func ResourceWorkspaceBinding() common.Resource { string(catalog.WorkspaceBindingBindingTypeBindingTypeReadWrite), string(catalog.WorkspaceBindingBindingTypeBindingTypeReadOnly), }, false)) + common.NamespaceCustomizeSchemaMap(m) return m }, ) @@ -94,7 +100,7 @@ func ResourceWorkspaceBinding() common.Resource { }, }, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -111,7 +117,7 @@ func ResourceWorkspaceBinding() common.Resource { return err }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -146,7 +152,7 @@ func ResourceWorkspaceBinding() common.Resource { } }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -159,6 +165,9 @@ func ResourceWorkspaceBinding() common.Resource { }) return err }, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, } } diff --git a/clusters/data_cluster.go b/clusters/data_cluster.go index aee0503619..b114ac8034 100644 --- a/clusters/data_cluster.go +++ b/clusters/data_cluster.go @@ -11,6 +11,7 @@ import ( func DataSourceCluster() common.Resource { return common.WorkspaceData(func(ctx context.Context, data *struct { + common.Namespace Id string `json:"id,omitempty" tf:"computed"` ClusterId string `json:"cluster_id,omitempty" tf:"computed"` Name string `json:"cluster_name,omitempty" tf:"computed"` diff --git a/clusters/data_clusters.go b/clusters/data_clusters.go index 3fbf55c5b4..aa0579b07f 100644 --- a/clusters/data_clusters.go +++ b/clusters/data_clusters.go @@ -11,6 +11,7 @@ import ( func DataSourceClusters() common.Resource { return common.WorkspaceData(func(ctx context.Context, data *struct { + common.Namespace Id string `json:"id,omitempty" tf:"computed"` Ids []string `json:"ids,omitempty" tf:"computed,slice_set"` ClusterNameContains string `json:"cluster_name_contains,omitempty"` diff --git a/clusters/data_node_type.go b/clusters/data_node_type.go index 6777689ece..188a5e7462 100644 --- a/clusters/data_node_type.go +++ b/clusters/data_node_type.go @@ -12,6 +12,7 @@ import ( ) type NodeTypeRequest struct { + common.Namespace compute.NodeTypeRequest Arm bool `json:"arm,omitempty"` } diff --git a/clusters/data_spark_version.go b/clusters/data_spark_version.go index 6f2f0250ae..6a4fca806a 100644 --- a/clusters/data_spark_version.go +++ b/clusters/data_spark_version.go @@ -9,11 +9,16 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) +type sparkVersionRequestWrapper struct { + common.Namespace + compute.SparkVersionRequest +} + // DataSourceSparkVersion returns DBR version matching to the specification func DataSourceSparkVersion() common.Resource { - return common.WorkspaceDataWithCustomizeFunc(func(ctx context.Context, data *compute.SparkVersionRequest, w *databricks.WorkspaceClient) error { + return common.WorkspaceDataWithCustomizeFunc(func(ctx context.Context, data *sparkVersionRequestWrapper, w *databricks.WorkspaceClient) error { data.Id = "" - version, err := w.Clusters.SelectSparkVersion(ctx, *data) + version, err := w.Clusters.SelectSparkVersion(ctx, data.SparkVersionRequest) if err != nil { return err } diff --git a/clusters/data_zones.go b/clusters/data_zones.go index 888c6775a5..631c667f3c 100644 --- a/clusters/data_zones.go +++ b/clusters/data_zones.go @@ -10,6 +10,7 @@ import ( // DataSourceClusterZones ... func DataSourceClusterZones() common.Resource { return common.WorkspaceData(func(ctx context.Context, data *struct { + common.Namespace Id string `json:"id,omitempty" tf:"computed"` DefaultZone string `json:"default_zone,omitempty" tf:"computed"` Zones []string `json:"zones,omitempty" tf:"computed"` diff --git a/clusters/resource_cluster.go b/clusters/resource_cluster.go index a5347b198d..e7107f9e5b 100644 --- a/clusters/resource_cluster.go +++ b/clusters/resource_cluster.go @@ -31,6 +31,9 @@ const ( func ResourceCluster() common.Resource { return common.Resource{ + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, Create: resourceClusterCreate, Read: resourceClusterRead, Update: resourceClusterUpdate, @@ -275,6 +278,7 @@ type LibraryWithAlias struct { type ClusterSpec struct { compute.ClusterSpec + common.Namespace LibraryWithAlias } @@ -323,6 +327,7 @@ func (ClusterSpec) CustomizeSchemaResourceSpecific(s *common.CustomizableSchema) } func (ClusterSpec) CustomizeSchema(s *common.CustomizableSchema) *common.CustomizableSchema { + common.NamespaceCustomizeSchema(s) s.SchemaPath("enable_elastic_disk").SetComputed() s.SchemaPath("enable_local_disk_encryption").SetComputed() s.SchemaPath("node_type_id").SetComputed().SetConflictsWith([]string{"driver_instance_pool_id", "instance_pool_id"}) @@ -388,7 +393,7 @@ func resourceClusterSchema() map[string]*schema.Schema { func resourceClusterCreate(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { start := time.Now() timeout := d.Timeout(schema.TimeoutCreate) - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -480,7 +485,7 @@ func setPinnedStatus(ctx context.Context, d *schema.ResourceData, clusterAPI com } func resourceClusterRead(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -532,7 +537,7 @@ func hasClusterConfigChanged(d *schema.ResourceData) bool { } func resourceClusterUpdate(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -697,7 +702,7 @@ func resourceClusterUpdate(ctx context.Context, d *schema.ResourceData, c *commo } func resourceClusterDelete(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } diff --git a/clusters/resource_library.go b/clusters/resource_library.go index 715e51bfea..e7b948a5c5 100644 --- a/clusters/resource_library.go +++ b/clusters/resource_library.go @@ -15,6 +15,7 @@ import ( type LibraryResource struct { compute.Library + common.Namespace } func (LibraryResource) CustomizeSchemaResourceSpecific(s *common.CustomizableSchema) *common.CustomizableSchema { @@ -28,6 +29,7 @@ func (LibraryResource) CustomizeSchemaResourceSpecific(s *common.CustomizableSch const EggDeprecationWarning = "The `egg` library type is deprecated. Please use `whl` or `pypi` instead." func (LibraryResource) CustomizeSchema(s *common.CustomizableSchema) *common.CustomizableSchema { + common.NamespaceCustomizeSchema(s) s.SchemaPath("egg").SetDeprecated(EggDeprecationWarning) return s } @@ -43,8 +45,11 @@ func ResourceLibrary() common.Resource { } return common.Resource{ Schema: libraySdkSchema, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -74,7 +79,7 @@ func ResourceLibrary() common.Resource { }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { clusterID, libraryRep := parseId(d.Id()) - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -106,7 +111,7 @@ func ResourceLibrary() common.Resource { }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { clusterID, libraryRep := parseId(d.Id()) - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } diff --git a/common/check_plan.go b/common/check_plan.go new file mode 100644 index 0000000000..9099f48168 --- /dev/null +++ b/common/check_plan.go @@ -0,0 +1,106 @@ +package common + +import ( + "context" + "fmt" + "strings" + + tfjson "github.com/hashicorp/terraform-json" + "github.com/hashicorp/terraform-plugin-testing/plancheck" +) + +// findResourceChange finds a resource change by address in the plan +func findResourceChange(req plancheck.CheckPlanRequest, address string) (*tfjson.ResourceChange, error) { + for _, resourceChange := range req.Plan.ResourceChanges { + if resourceChange.Address == address { + return resourceChange, nil + } + } + + addressesWithPlannedChanges := make([]string, 0, len(req.Plan.ResourceChanges)) + for _, change := range req.Plan.ResourceChanges { + addressesWithPlannedChanges = append(addressesWithPlannedChanges, change.Address) + } + return nil, fmt.Errorf("address %s not found in resource changes; only planned changes for addresses %s", + address, strings.Join(addressesWithPlannedChanges, ", ")) +} + +// getPlannedActions returns a string slice of all planned actions +func getPlannedActions(change *tfjson.ResourceChange) []string { + plannedActions := make([]string, 0, len(change.Change.Actions)) + for _, action := range change.Change.Actions { + plannedActions = append(plannedActions, string(action)) + } + return plannedActions +} + +// hasAction checks if a specific action is in the planned actions +func hasAction(change *tfjson.ResourceChange, targetAction tfjson.Action) bool { + for _, action := range change.Change.Actions { + if action == targetAction { + return true + } + } + return false +} + +// checkActionPresence checks if an action is present (or absent) in the plan +func checkActionPresence(req plancheck.CheckPlanRequest, resp *plancheck.CheckPlanResponse, + address string, action tfjson.Action, shouldBePresent bool) { + + change, err := findResourceChange(req, address) + if err != nil { + resp.Error = err + return + } + + actionPresent := hasAction(change, action) + + if shouldBePresent && !actionPresent { + resp.Error = fmt.Errorf("no %s is planned for %s; planned actions are: %s", + action, address, strings.Join(getPlannedActions(change), ", ")) + } else if !shouldBePresent && actionPresent { + resp.Error = fmt.Errorf("%s is planned for %s; planned actions are: %s", + action, address, strings.Join(getPlannedActions(change), ", ")) + } +} + +type CheckResourceCreate struct { + Address string +} + +func (c CheckResourceCreate) CheckPlan(_ context.Context, req plancheck.CheckPlanRequest, resp *plancheck.CheckPlanResponse) { + checkActionPresence(req, resp, c.Address, tfjson.ActionCreate, true) +} + +type CheckResourceUpdate struct { + Address string +} + +func (c CheckResourceUpdate) CheckPlan(_ context.Context, req plancheck.CheckPlanRequest, resp *plancheck.CheckPlanResponse) { + checkActionPresence(req, resp, c.Address, tfjson.ActionUpdate, true) +} + +type CheckResourceDelete struct { + Address string +} + +func (c CheckResourceDelete) CheckPlan(_ context.Context, req plancheck.CheckPlanRequest, resp *plancheck.CheckPlanResponse) { + checkActionPresence(req, resp, c.Address, tfjson.ActionDelete, true) +} + +type CheckResourceNoCreate struct { + Address string +} + +func (c CheckResourceNoCreate) CheckPlan(_ context.Context, req plancheck.CheckPlanRequest, resp *plancheck.CheckPlanResponse) { + checkActionPresence(req, resp, c.Address, tfjson.ActionCreate, false) +} + +type CheckResourceNoDelete struct { + Address string +} + +func (c CheckResourceNoDelete) CheckPlan(_ context.Context, req plancheck.CheckPlanRequest, resp *plancheck.CheckPlanResponse) { + checkActionPresence(req, resp, c.Address, tfjson.ActionDelete, false) +} diff --git a/common/client.go b/common/client.go index bfb452a0d2..bbd4d29935 100644 --- a/common/client.go +++ b/common/client.go @@ -6,6 +6,7 @@ import ( "fmt" "log" "net/http" + "strconv" "strings" "sync" @@ -59,6 +60,10 @@ type DatabricksClient struct { // configured for the provider cachedWorkspaceClient *databricks.WorkspaceClient + // cachedWorkspaceID is the cached workspace ID of the workspace client + // authenticated to the workspace configured for the provider + cachedWorkspaceID int64 + // cachedWorkspaceClients is a map of workspace clients for each workspace ID // populated when fetching a WorkspaceClient for a specific workspace ID using // a provider configured at the account level @@ -72,9 +77,162 @@ type DatabricksClient struct { mu sync.Mutex } -// GetWorkspaceClient returns the Databricks WorkspaceClient or a diagnostics if that fails. -// This is used by resources and data sources that are developed over plugin framework. -func (c *DatabricksClient) GetWorkspaceClient() (*databricks.WorkspaceClient, diag.Diagnostics) { +func (c *DatabricksClient) WorkspaceClientUnifiedProvider(ctx context.Context, d *schema.ResourceData) (*databricks.WorkspaceClient, error) { + workspaceIDFromSchema := d.Get("provider_config.0.workspace_id") + var workspaceID string + // workspace_id does not exist in the schema + if workspaceIDFromSchema == nil { + return c.GetWorkspaceClientForUnifiedProvider(ctx, "") + } + workspaceID, ok := workspaceIDFromSchema.(string) + if !ok { + return nil, fmt.Errorf("workspace_id must be a string") + } + return c.GetWorkspaceClientForUnifiedProvider(ctx, workspaceID) +} + +// GetWorkspaceClientForUnifiedProviderWithDiagnostics returns the Databricks +// WorkspaceClient for workspace level resources or diagnostics if that fails +// for terraform provider, the provider can be configured at account level or workspace level. +// This implementation will be used by resources and data sources that are developed +// over plugin framework. +func (c *DatabricksClient) GetWorkspaceClientForUnifiedProviderWithDiagnostics( + ctx context.Context, workspaceID string, +) (*databricks.WorkspaceClient, diag.Diagnostics) { + w, err := c.GetWorkspaceClientForUnifiedProvider(ctx, workspaceID) + if err != nil { + return nil, diag.Diagnostics{diag.NewErrorDiagnostic("failed to get workspace client", err.Error())} + } + return w, nil +} + +// GetWorkspaceClientForUnifiedProvider returns the Databricks +// WorkspaceClient for workspace level resources or diagnostics if that fails +// for terraform provider, the provider can be configured at account level or workspace level. +// This implementation will be used by resources and data sources that are developed +// over SDKv2. +func (c *DatabricksClient) GetWorkspaceClientForUnifiedProvider( + ctx context.Context, workspaceID string, +) (*databricks.WorkspaceClient, error) { + // The provider can be configured at account level or workspace level. + if c.Config.IsAccountClient() { + return c.getWorkspaceClientForAccountConfiguredProvider(ctx, workspaceID) + } + return c.getWorkspaceClientForWorkspaceConfiguredProvider(ctx, workspaceID) +} + +// getWorkspaceClientForAccountConfiguredProvider gets the workspace client for +// the workspace ID specified in the resource when the provider is configured +// at account level. +func (c *DatabricksClient) getWorkspaceClientForAccountConfiguredProvider( + ctx context.Context, workspaceID string, +) (*databricks.WorkspaceClient, error) { + // Workspace ID must be set in a workspace level resource if + // the provider is configured at account level. + // TODO: Link to the documentation once migration guide is published + if workspaceID == "" { + return nil, fmt.Errorf("workspace_id is not set, please set the workspace_id in the provider_config") + } + + // Parse the workspace ID to int. + workspaceIDInt, err := parseWorkspaceID(workspaceID) + if err != nil { + return nil, err + } + + // Get the workspace client for the workspace ID. + w, err := c.WorkspaceClientForWorkspace(ctx, workspaceIDInt) + if err != nil { + return nil, fmt.Errorf("failed to get workspace client with workspace_id %d: %w", workspaceIDInt, err) + } + return w, nil +} + +// getWorkspaceClientForWorkspaceConfiguredProvider gets the workspace client for +// the workspace ID specified in the resource when the provider is configured at workspace level. +func (c *DatabricksClient) getWorkspaceClientForWorkspaceConfiguredProvider( + ctx context.Context, workspaceID string, +) (*databricks.WorkspaceClient, error) { + // Provider is configured at workspace level and we get the + // workspace client from the provider. + if workspaceID == "" { + return c.WorkspaceClient() + } + + workspaceIDInt, err := parseWorkspaceID(workspaceID) + if err != nil { + return nil, err + } + + // Check if the workspace ID specified in the resource matches + // the workspace ID of the provider configured workspace client. + w, err := c.WorkspaceClient() + if err != nil { + return nil, err + } + + err = c.validateWorkspaceIDFromProvider(ctx, workspaceIDInt, w) + if err != nil { + return nil, fmt.Errorf("failed to validate workspace_id: %w", err) + } + // The provider is configured at the workspace level and the + // workspace ID matches + return w, nil +} + +// parseWorkspaceID parses the workspace ID from string to int64. +func parseWorkspaceID(workspaceID string) (int64, error) { + workspaceIDInt, err := strconv.ParseInt(workspaceID, 10, 64) + if err != nil { + return 0, fmt.Errorf("failed to parse workspace_id, please check if the workspace_id in provider_config is a valid integer: %w", err) + + } + return workspaceIDInt, nil +} + +// validateWorkspaceIDFromProvider validates the workspace ID specified in the +// resource or data soruce matches the workspace ID of the provider configured workspace client. +func (c *DatabricksClient) validateWorkspaceIDFromProvider(ctx context.Context, workspaceID int64, + w *databricks.WorkspaceClient) error { + // If the workspace ID is not cached, we make an API call to the workspace to get + // the current workspace ID and cache it. + if c.cachedWorkspaceID == 0 { + err := c.setCachedWorkspaceID(ctx, w) + if err != nil { + return err + } + } + + if c.cachedWorkspaceID != workspaceID { + return fmt.Errorf("workspace_id mismatch: provider is configured for workspace %d but got %d in provider_config. "+ + "please check the workspace_id provided in provider_config", + c.cachedWorkspaceID, workspaceID) + } + return nil +} + +// setCachedWorkspaceID sets the cached workspace ID. +func (c *DatabricksClient) setCachedWorkspaceID(ctx context.Context, w *databricks.WorkspaceClient) error { + // Acquire the lock to avoid race conditions. + c.mu.Lock() + defer c.mu.Unlock() + // Double checked locking + if c.cachedWorkspaceID == 0 { + id, err := w.CurrentWorkspaceID(ctx) + if err != nil { + return fmt.Errorf("failed to get the workspace_id: %w", + err) + } + c.cachedWorkspaceID = id + } + return nil +} + +// GetWorkspaceClient returns the Databricks WorkspaceClient or a diagnostics if +// that fails. This is used by resources and data sources that are developed +// over plugin framework. +func (c *DatabricksClient) GetWorkspaceClient() (*databricks.WorkspaceClient, + diag.Diagnostics) { w, err := c.WorkspaceClient() if err != nil { return nil, diag.Diagnostics{diag.NewErrorDiagnostic("Failed to get workspace client", err.Error())} diff --git a/common/resource.go b/common/resource.go index 69c5edd1b5..0abbdf376e 100644 --- a/common/resource.go +++ b/common/resource.go @@ -219,14 +219,19 @@ func MustCompileKeyRE(name string) *regexp.Regexp { // Deprecated: migrate to WorkspaceData func DataResource(sc any, read func(context.Context, any, *DatabricksClient) error) Resource { // TODO: migrate to go1.18 and get schema from second function argument?.. - s := StructToSchema(sc, func(m map[string]*schema.Schema) map[string]*schema.Schema { - return m - }) + s := StructToSchema(sc, NamespaceCustomizeSchemaMap) return Resource{ Schema: s, Read: func(ctx context.Context, d *schema.ResourceData, m *DatabricksClient) (err error) { ptr := reflect.New(reflect.ValueOf(sc).Type()) DataToReflectValue(d, s, ptr.Elem()) + if m.DatabricksClient != nil && !m.Config.IsAccountClient() { + w, err := m.WorkspaceClientUnifiedProvider(ctx, d) + if err != nil { + return err + } + m.SetWorkspaceClient(w) + } err = read(ctx, ptr.Interface(), m) if err != nil { err = nicerError(ctx, err, "read data") @@ -256,9 +261,13 @@ func DataResource(sc any, read func(context.Context, any, *DatabricksClient) err // ... // }) func WorkspaceData[T any](read func(context.Context, *T, *databricks.WorkspaceClient) error) Resource { - return genericDatabricksData((*DatabricksClient).WorkspaceClient, func(ctx context.Context, s struct{}, t *T, wc *databricks.WorkspaceClient) error { - return read(ctx, t, wc) - }, false, NoCustomize) + return genericDatabricksData( + func(client *DatabricksClient, ctx context.Context, d *schema.ResourceData) (*databricks.WorkspaceClient, error) { + return client.WorkspaceClientUnifiedProvider(ctx, d) + }, + func(ctx context.Context, s T, t *T, wc *databricks.WorkspaceClient) error { + return read(ctx, t, wc) + }, false, NamespaceCustomizeSchemaMap) } // WorkspaceDataWithParams defines a data source that can be used to read data from the workspace API. @@ -293,14 +302,18 @@ func WorkspaceData[T any](read func(context.Context, *T, *databricks.WorkspaceCl // ... // }) func WorkspaceDataWithParams[T, P any](read func(context.Context, P, *databricks.WorkspaceClient) (*T, error)) Resource { - return genericDatabricksData((*DatabricksClient).WorkspaceClient, func(ctx context.Context, o P, s *T, w *databricks.WorkspaceClient) error { - res, err := read(ctx, o, w) - if err != nil { - return err - } - *s = *res - return nil - }, true, NoCustomize) + return genericDatabricksData( + func(client *DatabricksClient, ctx context.Context, d *schema.ResourceData) (*databricks.WorkspaceClient, error) { + return client.WorkspaceClientUnifiedProvider(ctx, d) + }, + func(ctx context.Context, o P, s *T, w *databricks.WorkspaceClient) error { + res, err := read(ctx, o, w) + if err != nil { + return err + } + *s = *res + return nil + }, true, NoCustomize) } // WorkspaceDataWithCustomizeFunc defines a data source that can be used to read data from the workspace API. @@ -308,13 +321,16 @@ func WorkspaceDataWithParams[T, P any](read func(context.Context, P, *databricks // customizeSchemaFunc function. // // The additional argument is a function that will be called to customize the schema of the data source. - func WorkspaceDataWithCustomizeFunc[T any]( read func(context.Context, *T, *databricks.WorkspaceClient) error, customizeSchemaFunc func(map[string]*schema.Schema) map[string]*schema.Schema) Resource { - return genericDatabricksData((*DatabricksClient).WorkspaceClient, func(ctx context.Context, s struct{}, t *T, wc *databricks.WorkspaceClient) error { - return read(ctx, t, wc) - }, false, customizeSchemaFunc) + return genericDatabricksData( + func(client *DatabricksClient, ctx context.Context, d *schema.ResourceData) (*databricks.WorkspaceClient, error) { + return client.WorkspaceClientUnifiedProvider(ctx, d) + }, + func(ctx context.Context, s struct{}, t *T, wc *databricks.WorkspaceClient) error { + return read(ctx, t, wc) + }, false, customizeSchemaFunc) } // AccountData is a generic way to define account data resources in Terraform provider. @@ -329,9 +345,13 @@ func WorkspaceDataWithCustomizeFunc[T any]( // ... // }) func AccountData[T any](read func(context.Context, *T, *databricks.AccountClient) error) Resource { - return genericDatabricksData((*DatabricksClient).AccountClient, func(ctx context.Context, s struct{}, t *T, ac *databricks.AccountClient) error { - return read(ctx, t, ac) - }, false, NoCustomize) + return genericDatabricksData( + func(client *DatabricksClient, ctx context.Context, d *schema.ResourceData) (*databricks.AccountClient, error) { + return client.AccountClient() + }, + func(ctx context.Context, s struct{}, t *T, ac *databricks.AccountClient) error { + return read(ctx, t, ac) + }, false, NoCustomize) } // AccountDataWithParams defines a data source that can be used to read data from the account API. @@ -366,14 +386,18 @@ func AccountData[T any](read func(context.Context, *T, *databricks.AccountClient // ... // }) func AccountDataWithParams[T, P any](read func(context.Context, P, *databricks.AccountClient) (*T, error)) Resource { - return genericDatabricksData((*DatabricksClient).AccountClient, func(ctx context.Context, o P, s *T, a *databricks.AccountClient) error { - res, err := read(ctx, o, a) - if err != nil { - return err - } - *s = *res - return nil - }, true, NoCustomize) + return genericDatabricksData( + func(client *DatabricksClient, ctx context.Context, d *schema.ResourceData) (*databricks.AccountClient, error) { + return client.AccountClient() + }, + func(ctx context.Context, o P, s *T, a *databricks.AccountClient) error { + res, err := read(ctx, o, a) + if err != nil { + return err + } + *s = *res + return nil + }, true, NoCustomize) } // genericDatabricksData is generic and common way to define both account and workspace data and calls their respective clients. @@ -382,7 +406,7 @@ func AccountDataWithParams[T, P any](read func(context.Context, P, *databricks.A // from OtherFields will be overlaid on top of the schema generated by SdkType. Otherwise, the schema generated by // SdkType will be used directly. func genericDatabricksData[T, P, C any]( - getClient func(*DatabricksClient) (C, error), + getClient func(*DatabricksClient, context.Context, *schema.ResourceData) (C, error), read func(context.Context, P, *T, C) error, hasOther bool, customizeSchemaFunc func(map[string]*schema.Schema) map[string]*schema.Schema) Resource { @@ -427,7 +451,7 @@ func genericDatabricksData[T, P, C any]( var other P DataToStructPointer(d, s, &other) DataToStructPointer(d, s, &dummy) - c, err := getClient(client) + c, err := getClient(client, ctx, d) if err != nil { return nicerError(ctx, err, "get client") } @@ -494,7 +518,10 @@ func AddAccountIdField(s map[string]*schema.Schema) map[string]*schema.Schema { // NoClientData is a generic way to define data resources in Terraform provider that doesn't require any client. // usage is similar to AccountData and WorkspaceData, but the read function doesn't take a client. func NoClientData[T any](read func(context.Context, *T) error) Resource { - return genericDatabricksData(func(*DatabricksClient) (any, error) { return nil, nil }, + return genericDatabricksData( + func(client *DatabricksClient, ctx context.Context, d *schema.ResourceData) (any, error) { + return nil, nil + }, func(ctx context.Context, s struct{}, t *T, ac any) error { return read(ctx, t) }, false, NoCustomize) diff --git a/common/unified_terraform_provider.go b/common/unified_terraform_provider.go new file mode 100644 index 0000000000..b53830d9e7 --- /dev/null +++ b/common/unified_terraform_provider.go @@ -0,0 +1,44 @@ +package common + +import ( + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +type Namespace struct { + ProviderConfig *ProviderConfig `json:"provider_config,omitempty"` +} + +type ProviderConfig struct { + WorkspaceID string `json:"workspace_id"` +} + +func workspaceIDValidateFunc() func(interface{}, string) ([]string, []error) { + return validation.StringIsNotEmpty +} + +func NamespaceCustomizeSchema(s *CustomizableSchema) { + s.SchemaPath("provider_config", "workspace_id").SetValidateFunc(workspaceIDValidateFunc()) +} + +func NamespaceCustomizeSchemaMap(m map[string]*schema.Schema) map[string]*schema.Schema { + if providerConfig, ok := m["provider_config"]; ok { + if elem, ok := providerConfig.Elem.(*schema.Resource); ok { + if workspaceID, ok := elem.Schema["workspace_id"]; ok { + workspaceID.ValidateFunc = workspaceIDValidateFunc() + } + } + } + return m +} + +func NamespaceCustomizeDiff(d *schema.ResourceDiff) error { + workspaceIDKey := "provider_config.0.workspace_id" + oldWorkspaceID, newWorkspaceID := d.GetChange(workspaceIDKey) + if oldWorkspaceID != "" && newWorkspaceID != "" && oldWorkspaceID != newWorkspaceID { + if err := d.ForceNew(workspaceIDKey); err != nil { + return err + } + } + return nil +} diff --git a/dashboards/resource_dashboard.go b/dashboards/resource_dashboard.go index b1c9d71be2..293006ecf2 100644 --- a/dashboards/resource_dashboard.go +++ b/dashboards/resource_dashboard.go @@ -14,6 +14,7 @@ import ( type Dashboard struct { dashboards.Dashboard + common.Namespace EmbedCredentials bool `json:"embed_credentials,omitempty"` FilePath string `json:"file_path,omitempty"` Md5 string `json:"md5,omitempty"` @@ -29,6 +30,7 @@ func customDiffSerializedDashboard(k, old, new string, d *schema.ResourceData) b } func (Dashboard) CustomizeSchema(s *common.CustomizableSchema) *common.CustomizableSchema { + common.NamespaceCustomizeSchema(s) // Required fields s.SchemaPath("display_name").SetRequired() s.SchemaPath("parent_path").SetRequired() @@ -65,8 +67,11 @@ var dashboardSchema = common.StructToSchema(Dashboard{}, nil) func ResourceDashboard() common.Resource { return common.Resource{ Schema: dashboardSchema, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -115,7 +120,7 @@ func ResourceDashboard() common.Resource { return nil }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -138,7 +143,7 @@ func ResourceDashboard() common.Resource { return common.StructToData(resp, dashboardSchema, d) }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -181,7 +186,7 @@ func ResourceDashboard() common.Resource { return nil }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } diff --git a/internal/providers/pluginfw/products/app/data_app.go b/internal/providers/pluginfw/products/app/data_app.go index 2d36537fa0..1f2584e185 100644 --- a/internal/providers/pluginfw/products/app/data_app.go +++ b/internal/providers/pluginfw/products/app/data_app.go @@ -11,8 +11,8 @@ import ( "github.com/databricks/terraform-provider-databricks/internal/providers/pluginfw/tfschema" "github.com/databricks/terraform-provider-databricks/internal/service/apps_tf" "github.com/hashicorp/terraform-plugin-framework/datasource" - "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-framework/types/basetypes" ) func DataSourceApp() datasource.DataSource { @@ -24,20 +24,22 @@ type dataSourceApp struct { } type dataApp struct { - Name types.String `tfsdk:"name"` - App types.Object `tfsdk:"app"` + Name types.String `tfsdk:"name"` + App types.Object `tfsdk:"app"` + ProviderConfigData types.Object `tfsdk:"provider_config"` } func (dataApp) ApplySchemaCustomizations(attrs map[string]tfschema.AttributeBuilder) map[string]tfschema.AttributeBuilder { attrs["name"] = attrs["name"].SetRequired() attrs["app"] = attrs["app"].SetComputed() - + attrs["provider_config"] = attrs["provider_config"].SetOptional() return attrs } func (dataApp) GetComplexFieldTypes(context.Context) map[string]reflect.Type { return map[string]reflect.Type{ - "app": reflect.TypeOf(apps_tf.App{}), + "app": reflect.TypeOf(apps_tf.App{}), + "provider_config": reflect.TypeOf(tfschema.ProviderConfigData{}), } } @@ -59,19 +61,33 @@ func (a *dataSourceApp) Configure(ctx context.Context, req datasource.ConfigureR func (a *dataSourceApp) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { ctx = pluginfwcontext.SetUserAgentInDataSourceContext(ctx, resourceName) - w, diags := a.client.GetWorkspaceClient() - resp.Diagnostics.Append(diags...) + + var config dataApp + resp.Diagnostics.Append(req.Config.Get(ctx, &config)...) if resp.Diagnostics.HasError() { return } - var name types.String - resp.Diagnostics.Append(req.Config.GetAttribute(ctx, path.Root("name"), &name)...) + var workspaceID string + if !config.ProviderConfigData.IsNull() { + var namespace tfschema.ProviderConfigData + resp.Diagnostics.Append(config.ProviderConfigData.As(ctx, &namespace, basetypes.ObjectAsOptions{ + UnhandledNullAsEmpty: true, + UnhandledUnknownAsEmpty: true, + })...) + if resp.Diagnostics.HasError() { + return + } + workspaceID = namespace.WorkspaceID.ValueString() + } + + w, diags := a.client.GetWorkspaceClientForUnifiedProviderWithDiagnostics(ctx, workspaceID) + resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } - appGoSdk, err := w.Apps.GetByName(ctx, name.ValueString()) + appGoSdk, err := w.Apps.GetByName(ctx, config.Name.ValueString()) if err != nil { resp.Diagnostics.AddError("failed to read app", err.Error()) return @@ -82,7 +98,7 @@ func (a *dataSourceApp) Read(ctx context.Context, req datasource.ReadRequest, re if resp.Diagnostics.HasError() { return } - dataApp := dataApp{Name: name, App: newApp.ToObjectValue(ctx)} + dataApp := dataApp{Name: config.Name, App: newApp.ToObjectValue(ctx), ProviderConfigData: config.ProviderConfigData} resp.Diagnostics.Append(resp.State.Set(ctx, dataApp)...) if resp.Diagnostics.HasError() { return diff --git a/internal/providers/pluginfw/products/app/data_apps.go b/internal/providers/pluginfw/products/app/data_apps.go index 19ebeeb6ed..a4f149d7b1 100644 --- a/internal/providers/pluginfw/products/app/data_apps.go +++ b/internal/providers/pluginfw/products/app/data_apps.go @@ -14,6 +14,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-framework/types/basetypes" ) func DataSourceApps() datasource.DataSource { @@ -25,18 +26,20 @@ type dataSourceApps struct { } type dataApps struct { - Apps types.List `tfsdk:"app"` + Apps types.List `tfsdk:"app"` + ProviderConfigData types.Object `tfsdk:"provider_config"` } func (dataApps) ApplySchemaCustomizations(attrs map[string]tfschema.AttributeBuilder) map[string]tfschema.AttributeBuilder { attrs["app"] = attrs["app"].SetComputed() - + attrs["provider_config"] = attrs["provider_config"].SetOptional() return attrs } func (dataApps) GetComplexFieldTypes(context.Context) map[string]reflect.Type { return map[string]reflect.Type{ - "app": reflect.TypeOf(apps_tf.App{}), + "app": reflect.TypeOf(apps_tf.App{}), + "provider_config": reflect.TypeOf(tfschema.ProviderConfigData{}), } } @@ -58,7 +61,27 @@ func (a *dataSourceApps) Configure(ctx context.Context, req datasource.Configure func (a *dataSourceApps) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { ctx = pluginfwcontext.SetUserAgentInDataSourceContext(ctx, resourceName) - w, diags := a.client.GetWorkspaceClient() + + var config dataApps + resp.Diagnostics.Append(req.Config.Get(ctx, &config)...) + if resp.Diagnostics.HasError() { + return + } + + var workspaceID string + if !config.ProviderConfigData.IsNull() { + var namespace tfschema.ProviderConfigData + resp.Diagnostics.Append(config.ProviderConfigData.As(ctx, &namespace, basetypes.ObjectAsOptions{ + UnhandledNullAsEmpty: true, + UnhandledUnknownAsEmpty: true, + })...) + if resp.Diagnostics.HasError() { + return + } + workspaceID = namespace.WorkspaceID.ValueString() + } + + w, diags := a.client.GetWorkspaceClientForUnifiedProviderWithDiagnostics(ctx, workspaceID) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return @@ -79,7 +102,7 @@ func (a *dataSourceApps) Read(ctx context.Context, req datasource.ReadRequest, r } apps = append(apps, app.ToObjectValue(ctx)) } - dataApps := dataApps{Apps: types.ListValueMust(apps_tf.App{}.Type(ctx), apps)} + dataApps := dataApps{Apps: types.ListValueMust(apps_tf.App{}.Type(ctx), apps), ProviderConfigData: config.ProviderConfigData} resp.Diagnostics.Append(resp.State.Set(ctx, dataApps)...) if resp.Diagnostics.HasError() { return diff --git a/internal/providers/pluginfw/products/app/resource_app.go b/internal/providers/pluginfw/products/app/resource_app.go index 68eaeb4d3c..7028da7088 100644 --- a/internal/providers/pluginfw/products/app/resource_app.go +++ b/internal/providers/pluginfw/products/app/resource_app.go @@ -22,6 +22,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-framework/types/basetypes" ) const ( @@ -31,15 +32,23 @@ const ( type appResource struct { apps_tf.App - NoCompute types.Bool `tfsdk:"no_compute"` + NoCompute types.Bool `tfsdk:"no_compute"` + ProviderConfig types.Object `tfsdk:"provider_config"` } func (a appResource) ApplySchemaCustomizations(s map[string]tfschema.AttributeBuilder) map[string]tfschema.AttributeBuilder { s["no_compute"] = s["no_compute"].SetOptional() + s["provider_config"] = s["provider_config"].SetOptional() s = apps_tf.App{}.ApplySchemaCustomizations(s) return s } +func (a appResource) GetComplexFieldTypes(ctx context.Context) map[string]reflect.Type { + attrs := a.App.GetComplexFieldTypes(ctx) + attrs["provider_config"] = reflect.TypeOf(tfschema.ProviderConfig{}) + return attrs +} + func ResourceApp() resource.Resource { return &resourceApp{} } @@ -93,17 +102,32 @@ func (a *resourceApp) Configure(ctx context.Context, req resource.ConfigureReque func (a *resourceApp) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { ctx = pluginfwcontext.SetUserAgentInResourceContext(ctx, resourceName) - w, diags := a.client.GetWorkspaceClient() - resp.Diagnostics.Append(diags...) + + var app appResource + resp.Diagnostics.Append(req.Plan.Get(ctx, &app)...) if resp.Diagnostics.HasError() { return } - var app appResource - resp.Diagnostics.Append(req.Plan.Get(ctx, &app)...) + var workspaceID string + if !app.ProviderConfig.IsNull() { + var namespace tfschema.ProviderConfigData + resp.Diagnostics.Append(app.ProviderConfig.As(ctx, &namespace, basetypes.ObjectAsOptions{ + UnhandledNullAsEmpty: true, + UnhandledUnknownAsEmpty: true, + })...) + if resp.Diagnostics.HasError() { + return + } + workspaceID = namespace.WorkspaceID.ValueString() + } + + w, diags := a.client.GetWorkspaceClientForUnifiedProviderWithDiagnostics(ctx, workspaceID) + resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } + var appGoSdk apps.App resp.Diagnostics.Append(converters.TfSdkToGoSdkStruct(ctx, app, &appGoSdk)...) if resp.Diagnostics.HasError() { @@ -132,6 +156,7 @@ func (a *resourceApp) Create(ctx context.Context, req resource.CreateRequest, re return } newApp.NoCompute = app.NoCompute + newApp.ProviderConfig = app.ProviderConfig resp.Diagnostics.Append(resp.State.Set(ctx, newApp)...) if resp.Diagnostics.HasError() { return @@ -149,6 +174,7 @@ func (a *resourceApp) Create(ctx context.Context, req resource.CreateRequest, re if resp.Diagnostics.HasError() { return } + newApp.ProviderConfig = app.ProviderConfig resp.Diagnostics.Append(resp.State.Set(ctx, newApp)...) if resp.Diagnostics.HasError() { return @@ -194,14 +220,28 @@ func (a *resourceApp) waitForApp(ctx context.Context, w *databricks.WorkspaceCli func (a *resourceApp) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { ctx = pluginfwcontext.SetUserAgentInResourceContext(ctx, resourceName) - w, diags := a.client.GetWorkspaceClient() - resp.Diagnostics.Append(diags...) + + var app appResource + resp.Diagnostics.Append(req.State.Get(ctx, &app)...) if resp.Diagnostics.HasError() { return } - var app appResource - resp.Diagnostics.Append(req.State.Get(ctx, &app)...) + var workspaceID string + if !app.ProviderConfig.IsNull() { + var namespace tfschema.ProviderConfigData + resp.Diagnostics.Append(app.ProviderConfig.As(ctx, &namespace, basetypes.ObjectAsOptions{ + UnhandledNullAsEmpty: true, + UnhandledUnknownAsEmpty: true, + })...) + if resp.Diagnostics.HasError() { + return + } + workspaceID = namespace.WorkspaceID.ValueString() + } + + w, diags := a.client.GetWorkspaceClientForUnifiedProviderWithDiagnostics(ctx, workspaceID) + resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } @@ -218,6 +258,7 @@ func (a *resourceApp) Read(ctx context.Context, req resource.ReadRequest, resp * return } newApp.NoCompute = app.NoCompute + newApp.ProviderConfig = app.ProviderConfig resp.Diagnostics.Append(resp.State.Set(ctx, newApp)...) if resp.Diagnostics.HasError() { return @@ -226,14 +267,28 @@ func (a *resourceApp) Read(ctx context.Context, req resource.ReadRequest, resp * func (a *resourceApp) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { ctx = pluginfwcontext.SetUserAgentInResourceContext(ctx, resourceName) - w, diags := a.client.GetWorkspaceClient() - resp.Diagnostics.Append(diags...) + + var app appResource + resp.Diagnostics.Append(req.Plan.Get(ctx, &app)...) if resp.Diagnostics.HasError() { return } - var app appResource - resp.Diagnostics.Append(req.Plan.Get(ctx, &app)...) + var workspaceID string + if !app.ProviderConfig.IsNull() { + var namespace tfschema.ProviderConfigData + resp.Diagnostics.Append(app.ProviderConfig.As(ctx, &namespace, basetypes.ObjectAsOptions{ + UnhandledNullAsEmpty: true, + UnhandledUnknownAsEmpty: true, + })...) + if resp.Diagnostics.HasError() { + return + } + workspaceID = namespace.WorkspaceID.ValueString() + } + + w, diags := a.client.GetWorkspaceClientForUnifiedProviderWithDiagnostics(ctx, workspaceID) + resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } @@ -258,6 +313,7 @@ func (a *resourceApp) Update(ctx context.Context, req resource.UpdateRequest, re } // Modifying no_compute after creation has no effect. newApp.NoCompute = app.NoCompute + newApp.ProviderConfig = app.ProviderConfig resp.Diagnostics.Append(resp.State.Set(ctx, newApp)...) if resp.Diagnostics.HasError() { return @@ -266,14 +322,28 @@ func (a *resourceApp) Update(ctx context.Context, req resource.UpdateRequest, re func (a *resourceApp) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { ctx = pluginfwcontext.SetUserAgentInResourceContext(ctx, resourceName) - w, diags := a.client.GetWorkspaceClient() - resp.Diagnostics.Append(diags...) + + var app appResource + resp.Diagnostics.Append(req.State.Get(ctx, &app)...) if resp.Diagnostics.HasError() { return } - var app appResource - resp.Diagnostics.Append(req.State.Get(ctx, &app)...) + var workspaceID string + if !app.ProviderConfig.IsNull() { + var namespace tfschema.ProviderConfigData + resp.Diagnostics.Append(app.ProviderConfig.As(ctx, &namespace, basetypes.ObjectAsOptions{ + UnhandledNullAsEmpty: true, + UnhandledUnknownAsEmpty: true, + })...) + if resp.Diagnostics.HasError() { + return + } + workspaceID = namespace.WorkspaceID.ValueString() + } + + w, diags := a.client.GetWorkspaceClientForUnifiedProviderWithDiagnostics(ctx, workspaceID) + resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } diff --git a/internal/providers/pluginfw/products/catalog/data_functions.go b/internal/providers/pluginfw/products/catalog/data_functions.go index c60b8a62b6..f610bd6412 100644 --- a/internal/providers/pluginfw/products/catalog/data_functions.go +++ b/internal/providers/pluginfw/products/catalog/data_functions.go @@ -17,6 +17,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-framework/types/basetypes" ) const dataSourceName = "functions" @@ -32,10 +33,11 @@ type FunctionsDataSource struct { } type FunctionsData struct { - CatalogName types.String `tfsdk:"catalog_name"` - SchemaName types.String `tfsdk:"schema_name"` - IncludeBrowse types.Bool `tfsdk:"include_browse"` - Functions types.List `tfsdk:"functions"` + CatalogName types.String `tfsdk:"catalog_name"` + SchemaName types.String `tfsdk:"schema_name"` + IncludeBrowse types.Bool `tfsdk:"include_browse"` + Functions types.List `tfsdk:"functions"` + ProviderConfigData types.Object `tfsdk:"provider_config"` } func (FunctionsData) ApplySchemaCustomizations(attrs map[string]tfschema.AttributeBuilder) map[string]tfschema.AttributeBuilder { @@ -43,13 +45,14 @@ func (FunctionsData) ApplySchemaCustomizations(attrs map[string]tfschema.Attribu attrs["schema_name"] = attrs["schema_name"].SetRequired() attrs["include_browse"] = attrs["include_browse"].SetOptional() attrs["functions"] = attrs["functions"].SetOptional().SetComputed() - + attrs["provider_config"] = attrs["provider_config"].SetOptional() return attrs } func (FunctionsData) GetComplexFieldTypes(context.Context) map[string]reflect.Type { return map[string]reflect.Type{ - "functions": reflect.TypeOf(catalog_tf.FunctionInfo{}), + "functions": reflect.TypeOf(catalog_tf.FunctionInfo{}), + "provider_config": reflect.TypeOf(tfschema.ProviderConfigData{}), } } @@ -73,18 +76,33 @@ func (d *FunctionsDataSource) Configure(_ context.Context, req datasource.Config func (d *FunctionsDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { ctx = pluginfwcontext.SetUserAgentInDataSourceContext(ctx, dataSourceName) - w, diags := d.Client.GetWorkspaceClient() + + var functions FunctionsData + diags := req.Config.Get(ctx, &functions) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } - var functions FunctionsData - diags = req.Config.Get(ctx, &functions) + var workspaceID string + if !functions.ProviderConfigData.IsNull() { + var namespace tfschema.ProviderConfigData + resp.Diagnostics.Append(functions.ProviderConfigData.As(ctx, &namespace, basetypes.ObjectAsOptions{ + UnhandledNullAsEmpty: true, + UnhandledUnknownAsEmpty: true, + })...) + if resp.Diagnostics.HasError() { + return + } + workspaceID = namespace.WorkspaceID.ValueString() + } + + w, diags := d.Client.GetWorkspaceClientForUnifiedProviderWithDiagnostics(ctx, workspaceID) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } + catalogName := functions.CatalogName.ValueString() schemaName := functions.SchemaName.ValueString() functionsInfosSdk, err := w.Functions.ListAll(ctx, catalog.ListFunctionsRequest{ diff --git a/internal/providers/pluginfw/products/cluster/data_cluster.go b/internal/providers/pluginfw/products/cluster/data_cluster.go index e43740f3b3..315c3e5024 100644 --- a/internal/providers/pluginfw/products/cluster/data_cluster.go +++ b/internal/providers/pluginfw/products/cluster/data_cluster.go @@ -19,6 +19,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-framework/types/basetypes" ) const dataSourceName = "cluster" @@ -34,22 +35,24 @@ type ClusterDataSource struct { } type ClusterInfo struct { - ClusterId types.String `tfsdk:"cluster_id"` - Name types.String `tfsdk:"cluster_name"` - ClusterInfo types.List `tfsdk:"cluster_info"` + ClusterId types.String `tfsdk:"cluster_id"` + Name types.String `tfsdk:"cluster_name"` + ClusterInfo types.List `tfsdk:"cluster_info"` + ProviderConfigData types.Object `tfsdk:"provider_config"` } func (ClusterInfo) ApplySchemaCustomizations(attrs map[string]tfschema.AttributeBuilder) map[string]tfschema.AttributeBuilder { attrs["cluster_id"] = attrs["cluster_id"].SetOptional().SetComputed() attrs["cluster_name"] = attrs["cluster_name"].SetOptional().SetComputed() attrs["cluster_info"] = attrs["cluster_info"].SetOptional().SetComputed() - + attrs["provider_config"] = attrs["provider_config"].SetOptional() return attrs } func (ClusterInfo) GetComplexFieldTypes(context.Context) map[string]reflect.Type { return map[string]reflect.Type{ - "cluster_info": reflect.TypeOf(compute_tf.ClusterDetails_SdkV2{}), + "cluster_info": reflect.TypeOf(compute_tf.ClusterDetails_SdkV2{}), + "provider_config": reflect.TypeOf(tfschema.ProviderConfigData{}), } } @@ -73,14 +76,28 @@ func (d *ClusterDataSource) Configure(_ context.Context, req datasource.Configur func (d *ClusterDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { ctx = pluginfwcontext.SetUserAgentInDataSourceContext(ctx, dataSourceName) - w, diags := d.Client.GetWorkspaceClient() - resp.Diagnostics.Append(diags...) + + var clusterInfo ClusterInfo + resp.Diagnostics.Append(req.Config.Get(ctx, &clusterInfo)...) if resp.Diagnostics.HasError() { return } - var clusterInfo ClusterInfo - resp.Diagnostics.Append(req.Config.Get(ctx, &clusterInfo)...) + var workspaceID string + if !clusterInfo.ProviderConfigData.IsNull() { + var namespace tfschema.ProviderConfigData + resp.Diagnostics.Append(clusterInfo.ProviderConfigData.As(ctx, &namespace, basetypes.ObjectAsOptions{ + UnhandledNullAsEmpty: true, + UnhandledUnknownAsEmpty: true, + })...) + if resp.Diagnostics.HasError() { + return + } + workspaceID = namespace.WorkspaceID.ValueString() + } + + w, diags := d.Client.GetWorkspaceClientForUnifiedProviderWithDiagnostics(ctx, workspaceID) + resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } diff --git a/internal/providers/pluginfw/products/dashboards/data_dashboards.go b/internal/providers/pluginfw/products/dashboards/data_dashboards.go index 52b7b0603b..e27a7d25bd 100644 --- a/internal/providers/pluginfw/products/dashboards/data_dashboards.go +++ b/internal/providers/pluginfw/products/dashboards/data_dashboards.go @@ -17,6 +17,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-framework/types/basetypes" ) const dataSourceName = "dashboards" @@ -34,18 +35,20 @@ type DashboardsDataSource struct { type DashboardsInfo struct { DashboardNameContains types.String `tfsdk:"dashboard_name_contains"` Dashboards types.List `tfsdk:"dashboards"` + ProviderConfig types.Object `tfsdk:"provider_config"` } func (DashboardsInfo) ApplySchemaCustomizations(attrs map[string]tfschema.AttributeBuilder) map[string]tfschema.AttributeBuilder { attrs["dashboard_name_contains"] = attrs["dashboard_name_contains"].SetOptional() attrs["dashboards"] = attrs["dashboards"].SetComputed() - + attrs["provider_config"] = attrs["provider_config"].SetOptional() return attrs } func (DashboardsInfo) GetComplexFieldTypes(context.Context) map[string]reflect.Type { return map[string]reflect.Type{ - "dashboards": reflect.TypeOf(dashboards_tf.Dashboard{}), + "dashboards": reflect.TypeOf(dashboards_tf.Dashboard{}), + "provider_config": reflect.TypeOf(tfschema.ProviderConfigData{}), } } @@ -74,15 +77,28 @@ func AppendDiagAndCheckErrors(resp *datasource.ReadResponse, diags diag.Diagnost func (d *DashboardsDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { ctx = pluginfwcontext.SetUserAgentInDataSourceContext(ctx, dataSourceName) - w, diags := d.Client.GetWorkspaceClient() - if AppendDiagAndCheckErrors(resp, diags) { - return - } var dashboardInfo DashboardsInfo if AppendDiagAndCheckErrors(resp, req.Config.Get(ctx, &dashboardInfo)) { return } + var workspaceID string + if !dashboardInfo.ProviderConfig.IsNull() { + var namespace tfschema.ProviderConfigData + resp.Diagnostics.Append(dashboardInfo.ProviderConfig.As(ctx, &namespace, basetypes.ObjectAsOptions{ + UnhandledNullAsEmpty: true, + UnhandledUnknownAsEmpty: true, + })...) + if resp.Diagnostics.HasError() { + return + } + workspaceID = namespace.WorkspaceID.ValueString() + } + w, diags := d.Client.GetWorkspaceClientForUnifiedProviderWithDiagnostics(ctx, workspaceID) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } dashboardName := strings.ToLower(dashboardInfo.DashboardNameContains.ValueString()) diff --git a/internal/providers/pluginfw/products/library/resource_library.go b/internal/providers/pluginfw/products/library/resource_library.go index ea2aefecd8..01d685cf71 100644 --- a/internal/providers/pluginfw/products/library/resource_library.go +++ b/internal/providers/pluginfw/products/library/resource_library.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "reflect" "time" "github.com/databricks/databricks-sdk-go/apierr" @@ -24,6 +25,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/resource/schema/objectplanmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-framework/types/basetypes" "github.com/databricks/databricks-sdk-go" ) @@ -74,8 +76,15 @@ func readLibrary(ctx context.Context, w *databricks.WorkspaceClient, waitParams type LibraryExtended struct { compute_tf.Library_SdkV2 - ClusterId types.String `tfsdk:"cluster_id"` - ID types.String `tfsdk:"id"` // Adding ID field to stay compatible with SDKv2 + ClusterId types.String `tfsdk:"cluster_id"` + ID types.String `tfsdk:"id"` // Adding ID field to stay compatible with SDKv2 + ProviderConfig types.Object `tfsdk:"provider_config"` +} + +func (l LibraryExtended) GetComplexFieldTypes(ctx context.Context) map[string]reflect.Type { + attrs := l.Library_SdkV2.GetComplexFieldTypes(ctx) + attrs["provider_config"] = reflect.TypeOf(tfschema.ProviderConfig{}) + return attrs } type LibraryResource struct { @@ -105,6 +114,7 @@ func (r *LibraryResource) Schema(ctx context.Context, req resource.SchemaRequest } c.SetRequired("cluster_id") c.SetOptional("id") + c.SetOptional("provider_config") c.SetComputed("id") c.SetDeprecated(clusters.EggDeprecationWarning, "egg") return c @@ -124,13 +134,27 @@ func (r *LibraryResource) Configure(ctx context.Context, req resource.ConfigureR func (r *LibraryResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { ctx = pluginfwcontext.SetUserAgentInResourceContext(ctx, resourceName) - w, diags := r.Client.GetWorkspaceClient() - resp.Diagnostics.Append(diags...) + var libraryTfSDK LibraryExtended + resp.Diagnostics.Append(req.Plan.Get(ctx, &libraryTfSDK)...) if resp.Diagnostics.HasError() { return } - var libraryTfSDK LibraryExtended - resp.Diagnostics.Append(req.Plan.Get(ctx, &libraryTfSDK)...) + + var workspaceID string + if !libraryTfSDK.ProviderConfig.IsNull() { + var namespace tfschema.ProviderConfigData + resp.Diagnostics.Append(libraryTfSDK.ProviderConfig.As(ctx, &namespace, basetypes.ObjectAsOptions{ + UnhandledNullAsEmpty: true, + UnhandledUnknownAsEmpty: true, + })...) + if resp.Diagnostics.HasError() { + return + } + workspaceID = namespace.WorkspaceID.ValueString() + } + + w, diags := r.Client.GetWorkspaceClientForUnifiedProviderWithDiagnostics(ctx, workspaceID) + resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } @@ -171,21 +195,37 @@ func (r *LibraryResource) Create(ctx context.Context, req resource.CreateRequest } installedLib.ID = types.StringValue(libGoSDK.String()) + installedLib.ProviderConfig = libraryTfSDK.ProviderConfig resp.Diagnostics.Append(resp.State.Set(ctx, installedLib)...) } func (r *LibraryResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { ctx = pluginfwcontext.SetUserAgentInResourceContext(ctx, resourceName) - w, diags := r.Client.GetWorkspaceClient() - resp.Diagnostics.Append(diags...) + var libraryTfSDK LibraryExtended + resp.Diagnostics.Append(req.State.Get(ctx, &libraryTfSDK)...) if resp.Diagnostics.HasError() { return } - var libraryTfSDK LibraryExtended - resp.Diagnostics.Append(req.State.Get(ctx, &libraryTfSDK)...) + + var workspaceID string + if !libraryTfSDK.ProviderConfig.IsNull() { + var namespace tfschema.ProviderConfigData + resp.Diagnostics.Append(libraryTfSDK.ProviderConfig.As(ctx, &namespace, basetypes.ObjectAsOptions{ + UnhandledNullAsEmpty: true, + UnhandledUnknownAsEmpty: true, + })...) + if resp.Diagnostics.HasError() { + return + } + workspaceID = namespace.WorkspaceID.ValueString() + } + + w, diags := r.Client.GetWorkspaceClientForUnifiedProviderWithDiagnostics(ctx, workspaceID) + resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } + var libGoSDK compute.Library resp.Diagnostics.Append(converters.TfSdkToGoSdkStruct(ctx, libraryTfSDK, &libGoSDK)...) if resp.Diagnostics.HasError() { @@ -209,6 +249,7 @@ func (r *LibraryResource) Read(ctx context.Context, req resource.ReadRequest, re return } + installedLib.ProviderConfig = libraryTfSDK.ProviderConfig resp.Diagnostics.Append(resp.State.Set(ctx, installedLib)...) } @@ -218,16 +259,31 @@ func (r *LibraryResource) Update(ctx context.Context, req resource.UpdateRequest func (r *LibraryResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { ctx = pluginfwcontext.SetUserAgentInResourceContext(ctx, resourceName) - w, diags := r.Client.GetWorkspaceClient() - resp.Diagnostics.Append(diags...) + var libraryTfSDK LibraryExtended + resp.Diagnostics.Append(req.State.Get(ctx, &libraryTfSDK)...) if resp.Diagnostics.HasError() { return } - var libraryTfSDK LibraryExtended - resp.Diagnostics.Append(req.State.Get(ctx, &libraryTfSDK)...) + + var workspaceID string + if !libraryTfSDK.ProviderConfig.IsNull() { + var namespace tfschema.ProviderConfigData + resp.Diagnostics.Append(libraryTfSDK.ProviderConfig.As(ctx, &namespace, basetypes.ObjectAsOptions{ + UnhandledNullAsEmpty: true, + UnhandledUnknownAsEmpty: true, + })...) + if resp.Diagnostics.HasError() { + return + } + workspaceID = namespace.WorkspaceID.ValueString() + } + + w, diags := r.Client.GetWorkspaceClientForUnifiedProviderWithDiagnostics(ctx, workspaceID) + resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } + clusterID := libraryTfSDK.ClusterId.ValueString() var libGoSDK compute.Library resp.Diagnostics.Append(converters.TfSdkToGoSdkStruct(ctx, libraryTfSDK, &libGoSDK)...) diff --git a/internal/providers/pluginfw/products/notificationdestinations/data_notification_destinations.go b/internal/providers/pluginfw/products/notificationdestinations/data_notification_destinations.go index 1d5f5d6b7b..1c4c167db4 100755 --- a/internal/providers/pluginfw/products/notificationdestinations/data_notification_destinations.go +++ b/internal/providers/pluginfw/products/notificationdestinations/data_notification_destinations.go @@ -19,6 +19,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-framework/types/basetypes" ) const dataSourceName = "notification_destinations" @@ -37,19 +38,21 @@ type NotificationDestinationsInfo struct { DisplayNameContains types.String `tfsdk:"display_name_contains"` Type types.String `tfsdk:"type"` NotificationDestinations types.List `tfsdk:"notification_destinations"` + ProviderConfigData types.Object `tfsdk:"provider_config"` } func (NotificationDestinationsInfo) ApplySchemaCustomizations(attrs map[string]tfschema.AttributeBuilder) map[string]tfschema.AttributeBuilder { attrs["display_name_contains"] = attrs["display_name_contains"].SetOptional() attrs["type"] = attrs["type"].SetOptional() attrs["notification_destinations"] = attrs["notification_destinations"].SetComputed() - + attrs["provider_config"] = attrs["provider_config"].SetOptional() return attrs } func (NotificationDestinationsInfo) GetComplexFieldTypes(context.Context) map[string]reflect.Type { return map[string]reflect.Type{ "notification_destinations": reflect.TypeOf(settings_tf.ListNotificationDestinationsResult{}), + "provider_config": reflect.TypeOf(tfschema.ProviderConfigData{}), } } @@ -93,16 +96,31 @@ func AppendDiagAndCheckErrors(resp *datasource.ReadResponse, diags diag.Diagnost func (d *NotificationDestinationsDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { ctx = pluginfwcontext.SetUserAgentInDataSourceContext(ctx, dataSourceName) - w, diags := d.Client.GetWorkspaceClient() - if AppendDiagAndCheckErrors(resp, diags) { - return - } var notificationInfo NotificationDestinationsInfo if AppendDiagAndCheckErrors(resp, req.Config.Get(ctx, ¬ificationInfo)) { return } + var workspaceID string + if !notificationInfo.ProviderConfigData.IsNull() { + var namespace tfschema.ProviderConfigData + resp.Diagnostics.Append(notificationInfo.ProviderConfigData.As(ctx, &namespace, basetypes.ObjectAsOptions{ + UnhandledNullAsEmpty: true, + UnhandledUnknownAsEmpty: true, + })...) + if resp.Diagnostics.HasError() { + return + } + workspaceID = namespace.WorkspaceID.ValueString() + } + + w, diags := d.Client.GetWorkspaceClientForUnifiedProviderWithDiagnostics(ctx, workspaceID) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + notificationType := notificationInfo.Type.ValueString() notificationDisplayName := strings.ToLower(notificationInfo.DisplayNameContains.ValueString()) diff --git a/internal/providers/pluginfw/products/qualitymonitor/resource_quality_monitor.go b/internal/providers/pluginfw/products/qualitymonitor/resource_quality_monitor.go index 99849c4439..a9a4bd50de 100644 --- a/internal/providers/pluginfw/products/qualitymonitor/resource_quality_monitor.go +++ b/internal/providers/pluginfw/products/qualitymonitor/resource_quality_monitor.go @@ -21,6 +21,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-framework/types/basetypes" ) const resourceName = "quality_monitor" @@ -62,12 +63,15 @@ type MonitorInfoExtended struct { WarehouseId types.String `tfsdk:"warehouse_id"` SkipBuiltinDashboard types.Bool `tfsdk:"skip_builtin_dashboard"` ID types.String `tfsdk:"id"` // Adding ID field to stay compatible with SDKv2 + ProviderConfig types.Object `tfsdk:"provider_config"` } var _ pluginfwcommon.ComplexFieldTypeProvider = MonitorInfoExtended{} func (m MonitorInfoExtended) GetComplexFieldTypes(ctx context.Context) map[string]reflect.Type { - return m.MonitorInfo_SdkV2.GetComplexFieldTypes(ctx) + attrs := m.MonitorInfo_SdkV2.GetComplexFieldTypes(ctx) + attrs["provider_config"] = reflect.TypeOf(tfschema.ProviderConfig{}) + return attrs } type QualityMonitorResource struct { @@ -92,6 +96,7 @@ func (r *QualityMonitorResource) Schema(ctx context.Context, req resource.Schema c.SetOptional("skip_builtin_dashboard") c.SetComputed("id") c.SetOptional("id") + c.SetOptional("provider_config") return c }) resp.Schema = schema.Schema{ @@ -113,13 +118,27 @@ func (d *QualityMonitorResource) ImportState(ctx context.Context, req resource.I func (r *QualityMonitorResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { ctx = pluginfwcontext.SetUserAgentInResourceContext(ctx, resourceName) - w, diags := r.Client.GetWorkspaceClient() - resp.Diagnostics.Append(diags...) + var monitorInfoTfSDK MonitorInfoExtended + resp.Diagnostics.Append(req.Plan.Get(ctx, &monitorInfoTfSDK)...) if resp.Diagnostics.HasError() { return } - var monitorInfoTfSDK MonitorInfoExtended - resp.Diagnostics.Append(req.Plan.Get(ctx, &monitorInfoTfSDK)...) + + var workspaceID string + if !monitorInfoTfSDK.ProviderConfig.IsNull() { + var namespace tfschema.ProviderConfigData + resp.Diagnostics.Append(monitorInfoTfSDK.ProviderConfig.As(ctx, &namespace, basetypes.ObjectAsOptions{ + UnhandledNullAsEmpty: true, + UnhandledUnknownAsEmpty: true, + })...) + if resp.Diagnostics.HasError() { + return + } + workspaceID = namespace.WorkspaceID.ValueString() + } + + w, diags := r.Client.GetWorkspaceClientForUnifiedProviderWithDiagnostics(ctx, workspaceID) + resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } @@ -150,25 +169,41 @@ func (r *QualityMonitorResource) Create(ctx context.Context, req resource.Create // We need it to fill additional fields as they are not returned by the API newMonitorInfoTfSDK.WarehouseId = monitorInfoTfSDK.WarehouseId newMonitorInfoTfSDK.SkipBuiltinDashboard = monitorInfoTfSDK.SkipBuiltinDashboard + newMonitorInfoTfSDK.ProviderConfig = monitorInfoTfSDK.ProviderConfig resp.Diagnostics.Append(resp.State.Set(ctx, newMonitorInfoTfSDK)...) } func (r *QualityMonitorResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { ctx = pluginfwcontext.SetUserAgentInResourceContext(ctx, resourceName) - w, diags := r.Client.GetWorkspaceClient() - resp.Diagnostics.Append(diags...) + + var monitorInfoTfSDK MonitorInfoExtended + resp.Diagnostics.Append(req.State.Get(ctx, &monitorInfoTfSDK)...) if resp.Diagnostics.HasError() { return } - var getMonitor catalog_tf.GetQualityMonitorRequest - resp.Diagnostics.Append(req.State.GetAttribute(ctx, path.Root("table_name"), &getMonitor.TableName)...) + var workspaceID string + if !monitorInfoTfSDK.ProviderConfig.IsNull() { + var namespace tfschema.ProviderConfigData + resp.Diagnostics.Append(monitorInfoTfSDK.ProviderConfig.As(ctx, &namespace, basetypes.ObjectAsOptions{ + UnhandledNullAsEmpty: true, + UnhandledUnknownAsEmpty: true, + })...) + if resp.Diagnostics.HasError() { + return + } + workspaceID = namespace.WorkspaceID.ValueString() + } + + w, diags := r.Client.GetWorkspaceClientForUnifiedProviderWithDiagnostics(ctx, workspaceID) + resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } + endpoint, err := w.QualityMonitors.Get(ctx, catalog.GetQualityMonitorRequest{ - TableName: getMonitor.TableName.ValueString(), + TableName: monitorInfoTfSDK.TableName.ValueString(), }) if err != nil { if apierr.IsMissing(err) { @@ -178,38 +213,26 @@ func (r *QualityMonitorResource) Read(ctx context.Context, req resource.ReadRequ resp.Diagnostics.AddError("failed to get monitor", err.Error()) return } - var monitorInfoTfSDK MonitorInfoExtended - resp.Diagnostics.Append(converters.GoSdkToTfSdkStruct(ctx, endpoint, &monitorInfoTfSDK)...) + var newMonitorInfoTfSDK MonitorInfoExtended + resp.Diagnostics.Append(converters.GoSdkToTfSdkStruct(ctx, endpoint, &newMonitorInfoTfSDK)...) if resp.Diagnostics.HasError() { return } - monitorInfoTfSDK.ID = monitorInfoTfSDK.TableName - // We need it to fill additional fields as they are not returned by the API - var origWarehouseId types.String - var origSkipBuiltinDashboard types.Bool - resp.Diagnostics.Append(req.State.GetAttribute(ctx, path.Root("warehouse_id"), &origWarehouseId)...) - resp.Diagnostics.Append(req.State.GetAttribute(ctx, path.Root("skip_builtin_dashboard"), &origSkipBuiltinDashboard)...) - if resp.Diagnostics.HasError() { - return + newMonitorInfoTfSDK.ID = monitorInfoTfSDK.TableName + if monitorInfoTfSDK.WarehouseId.ValueString() != "" { + newMonitorInfoTfSDK.WarehouseId = monitorInfoTfSDK.WarehouseId } - if origWarehouseId.ValueString() != "" { - monitorInfoTfSDK.WarehouseId = origWarehouseId - } - if origSkipBuiltinDashboard.ValueBool() { - monitorInfoTfSDK.SkipBuiltinDashboard = origSkipBuiltinDashboard + if monitorInfoTfSDK.SkipBuiltinDashboard.ValueBool() { + newMonitorInfoTfSDK.SkipBuiltinDashboard = monitorInfoTfSDK.SkipBuiltinDashboard } - resp.Diagnostics.Append(resp.State.Set(ctx, monitorInfoTfSDK)...) + newMonitorInfoTfSDK.ProviderConfig = monitorInfoTfSDK.ProviderConfig + resp.Diagnostics.Append(resp.State.Set(ctx, newMonitorInfoTfSDK)...) } func (r *QualityMonitorResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { ctx = pluginfwcontext.SetUserAgentInResourceContext(ctx, resourceName) - w, diags := r.Client.GetWorkspaceClient() - resp.Diagnostics.Append(diags...) - if resp.Diagnostics.HasError() { - return - } var monitorInfoTfSDK MonitorInfoExtended resp.Diagnostics.Append(req.Plan.Get(ctx, &monitorInfoTfSDK)...) @@ -230,6 +253,26 @@ func (r *QualityMonitorResource) Update(ctx context.Context, req resource.Update if updateMonitorGoSDK.Schedule != nil { updateMonitorGoSDK.Schedule.PauseStatus = "" } + + var workspaceID string + if !monitorInfoTfSDK.ProviderConfig.IsNull() { + var namespace tfschema.ProviderConfigData + resp.Diagnostics.Append(monitorInfoTfSDK.ProviderConfig.As(ctx, &namespace, basetypes.ObjectAsOptions{ + UnhandledNullAsEmpty: true, + UnhandledUnknownAsEmpty: true, + })...) + if resp.Diagnostics.HasError() { + return + } + workspaceID = namespace.WorkspaceID.ValueString() + } + + w, diags := r.Client.GetWorkspaceClientForUnifiedProviderWithDiagnostics(ctx, workspaceID) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + monitor, err := w.QualityMonitors.Update(ctx, updateMonitorGoSDK) if err != nil { resp.Diagnostics.AddError("failed to update monitor", err.Error()) @@ -252,24 +295,40 @@ func (r *QualityMonitorResource) Update(ctx context.Context, req resource.Update return } + newMonitorInfoTfSDK.ProviderConfig = monitorInfoTfSDK.ProviderConfig resp.Diagnostics.Append(resp.State.Set(ctx, newMonitorInfoTfSDK)...) } func (r *QualityMonitorResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { ctx = pluginfwcontext.SetUserAgentInResourceContext(ctx, resourceName) - w, diags := r.Client.GetWorkspaceClient() - resp.Diagnostics.Append(diags...) + + var monitorInfoTfSDK MonitorInfoExtended + resp.Diagnostics.Append(req.State.Get(ctx, &monitorInfoTfSDK)...) if resp.Diagnostics.HasError() { return } - var deleteRequest catalog_tf.DeleteQualityMonitorRequest - resp.Diagnostics.Append(req.State.GetAttribute(ctx, path.Root("table_name"), &deleteRequest.TableName)...) + var workspaceID string + if !monitorInfoTfSDK.ProviderConfig.IsNull() { + var namespace tfschema.ProviderConfigData + resp.Diagnostics.Append(monitorInfoTfSDK.ProviderConfig.As(ctx, &namespace, basetypes.ObjectAsOptions{ + UnhandledNullAsEmpty: true, + UnhandledUnknownAsEmpty: true, + })...) + if resp.Diagnostics.HasError() { + return + } + workspaceID = namespace.WorkspaceID.ValueString() + } + + w, diags := r.Client.GetWorkspaceClientForUnifiedProviderWithDiagnostics(ctx, workspaceID) + resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } + _, err := w.QualityMonitors.Delete(ctx, catalog.DeleteQualityMonitorRequest{ - TableName: deleteRequest.TableName.ValueString(), + TableName: monitorInfoTfSDK.TableName.ValueString(), }) if err != nil && !apierr.IsMissing(err) { resp.Diagnostics.AddError("failed to delete monitor", err.Error()) diff --git a/internal/providers/pluginfw/products/qualitymonitor/resource_quality_monitor_acc_test.go b/internal/providers/pluginfw/products/qualitymonitor/resource_quality_monitor_acc_test.go index 710ba68ee5..a5f42de5df 100644 --- a/internal/providers/pluginfw/products/qualitymonitor/resource_quality_monitor_acc_test.go +++ b/internal/providers/pluginfw/products/qualitymonitor/resource_quality_monitor_acc_test.go @@ -160,6 +160,9 @@ func TestUcAccUpdateQualityMonitor(t *testing.T) { model_id_col = "model_id" problem_type = "PROBLEM_TYPE_REGRESSION" } + provider_config = { + workspace_id = "{env.THIS_WORKSPACE_ID}" + } } `, }) diff --git a/internal/providers/pluginfw/products/registered_model/data_registered_model.go b/internal/providers/pluginfw/products/registered_model/data_registered_model.go index 6dd8257b74..adc1941446 100644 --- a/internal/providers/pluginfw/products/registered_model/data_registered_model.go +++ b/internal/providers/pluginfw/products/registered_model/data_registered_model.go @@ -34,10 +34,11 @@ type RegisteredModelDataSource struct { } type RegisteredModelData struct { - FullName types.String `tfsdk:"full_name"` - IncludeAliases types.Bool `tfsdk:"include_aliases"` - IncludeBrowse types.Bool `tfsdk:"include_browse"` - ModelInfo types.List `tfsdk:"model_info"` + FullName types.String `tfsdk:"full_name"` + IncludeAliases types.Bool `tfsdk:"include_aliases"` + IncludeBrowse types.Bool `tfsdk:"include_browse"` + ModelInfo types.List `tfsdk:"model_info"` + ProviderConfigData types.Object `tfsdk:"provider_config"` } func (RegisteredModelData) ApplySchemaCustomizations(attrs map[string]tfschema.AttributeBuilder) map[string]tfschema.AttributeBuilder { @@ -45,12 +46,14 @@ func (RegisteredModelData) ApplySchemaCustomizations(attrs map[string]tfschema.A attrs["include_aliases"] = attrs["include_aliases"].SetOptional() attrs["include_browse"] = attrs["include_browse"].SetOptional() attrs["model_info"] = attrs["model_info"].SetOptional().SetComputed() + attrs["provider_config"] = attrs["provider_config"].SetOptional() return attrs } func (RegisteredModelData) GetComplexFieldTypes(context.Context) map[string]reflect.Type { return map[string]reflect.Type{ - "model_info": reflect.TypeOf(catalog_tf.RegisteredModelInfo_SdkV2{}), + "model_info": reflect.TypeOf(catalog_tf.RegisteredModelInfo_SdkV2{}), + "provider_config": reflect.TypeOf(tfschema.ProviderConfigData{}), } } @@ -74,14 +77,28 @@ func (d *RegisteredModelDataSource) Configure(_ context.Context, req datasource. func (d *RegisteredModelDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { ctx = pluginfwcontext.SetUserAgentInDataSourceContext(ctx, dataSourceName) - w, diags := d.Client.GetWorkspaceClient() + + var registeredModel RegisteredModelData + diags := req.Config.Get(ctx, ®isteredModel) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } - var registeredModel RegisteredModelData - diags = req.Config.Get(ctx, ®isteredModel) + var workspaceID string + if !registeredModel.ProviderConfigData.IsNull() { + var namespace tfschema.ProviderConfigData + resp.Diagnostics.Append(registeredModel.ProviderConfigData.As(ctx, &namespace, basetypes.ObjectAsOptions{ + UnhandledNullAsEmpty: true, + UnhandledUnknownAsEmpty: true, + })...) + if resp.Diagnostics.HasError() { + return + } + workspaceID = namespace.WorkspaceID.ValueString() + } + + w, diags := d.Client.GetWorkspaceClientForUnifiedProviderWithDiagnostics(ctx, workspaceID) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return diff --git a/internal/providers/pluginfw/products/registered_model/data_registered_model_versions.go b/internal/providers/pluginfw/products/registered_model/data_registered_model_versions.go index 3d17b589ae..7bf90f6aa7 100644 --- a/internal/providers/pluginfw/products/registered_model/data_registered_model_versions.go +++ b/internal/providers/pluginfw/products/registered_model/data_registered_model_versions.go @@ -14,6 +14,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-framework/types/basetypes" ) func DataSourceRegisteredModelVersions() datasource.DataSource { @@ -27,19 +28,22 @@ type RegisteredModelVersionsDataSource struct { } type RegisteredModelVersionsData struct { - FullName types.String `tfsdk:"full_name"` - ModelVersions types.List `tfsdk:"model_versions"` + FullName types.String `tfsdk:"full_name"` + ModelVersions types.List `tfsdk:"model_versions"` + ProviderConfigData types.Object `tfsdk:"provider_config"` } func (RegisteredModelVersionsData) ApplySchemaCustomizations(attrs map[string]tfschema.AttributeBuilder) map[string]tfschema.AttributeBuilder { attrs["full_name"] = attrs["full_name"].SetRequired() attrs["model_versions"] = attrs["model_versions"].SetOptional().SetComputed() + attrs["provider_config"] = attrs["provider_config"].SetOptional() return attrs } func (RegisteredModelVersionsData) GetComplexFieldTypes(context.Context) map[string]reflect.Type { return map[string]reflect.Type{ - "model_versions": reflect.TypeOf(catalog_tf.ModelVersionInfo_SdkV2{}), + "model_versions": reflect.TypeOf(catalog_tf.ModelVersionInfo_SdkV2{}), + "provider_config": reflect.TypeOf(tfschema.ProviderConfigData{}), } } @@ -62,18 +66,32 @@ func (d *RegisteredModelVersionsDataSource) Configure(_ context.Context, req dat } func (d *RegisteredModelVersionsDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { - w, diags := d.Client.GetWorkspaceClient() + var registeredModelVersions RegisteredModelVersionsData + diags := req.Config.Get(ctx, ®isteredModelVersions) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } - var registeredModelVersions RegisteredModelVersionsData - diags = req.Config.Get(ctx, ®isteredModelVersions) + var workspaceID string + if !registeredModelVersions.ProviderConfigData.IsNull() { + var namespace tfschema.ProviderConfigData + resp.Diagnostics.Append(registeredModelVersions.ProviderConfigData.As(ctx, &namespace, basetypes.ObjectAsOptions{ + UnhandledNullAsEmpty: true, + UnhandledUnknownAsEmpty: true, + })...) + if resp.Diagnostics.HasError() { + return + } + workspaceID = namespace.WorkspaceID.ValueString() + } + + w, diags := d.Client.GetWorkspaceClientForUnifiedProviderWithDiagnostics(ctx, workspaceID) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } + modelFullName := registeredModelVersions.FullName.ValueString() modelVersions, err := w.ModelVersions.ListByFullName(ctx, modelFullName) if err != nil { diff --git a/internal/providers/pluginfw/products/serving/data_serving_endpoints.go b/internal/providers/pluginfw/products/serving/data_serving_endpoints.go index 53a95a070d..df0cd116b4 100644 --- a/internal/providers/pluginfw/products/serving/data_serving_endpoints.go +++ b/internal/providers/pluginfw/products/serving/data_serving_endpoints.go @@ -14,6 +14,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-framework/types/basetypes" ) func DataSourceServingEndpoints() datasource.DataSource { @@ -27,18 +28,20 @@ type ServingEndpointsDataSource struct { } type ServingEndpointsData struct { - Endpoints types.List `tfsdk:"endpoints"` + Endpoints types.List `tfsdk:"endpoints"` + ProviderConfigData types.Object `tfsdk:"provider_config"` } func (ServingEndpointsData) ApplySchemaCustomizations(attrs map[string]tfschema.AttributeBuilder) map[string]tfschema.AttributeBuilder { attrs["endpoints"] = attrs["endpoints"].SetOptional().SetComputed() - + attrs["provider_config"] = attrs["provider_config"].SetOptional() return attrs } func (ServingEndpointsData) GetComplexFieldTypes(context.Context) map[string]reflect.Type { return map[string]reflect.Type{ - "endpoints": reflect.TypeOf(serving_tf.ServingEndpoint_SdkV2{}), + "endpoints": reflect.TypeOf(serving_tf.ServingEndpoint_SdkV2{}), + "provider_config": reflect.TypeOf(tfschema.ProviderConfigData{}), } } @@ -61,18 +64,32 @@ func (d *ServingEndpointsDataSource) Configure(_ context.Context, req datasource } func (d *ServingEndpointsDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { - w, diags := d.Client.GetWorkspaceClient() + var endpoints ServingEndpointsData + diags := req.Config.Get(ctx, &endpoints) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } - var endpoints ServingEndpointsData - diags = req.Config.Get(ctx, &endpoints) + var workspaceID string + if !endpoints.ProviderConfigData.IsNull() { + var namespace tfschema.ProviderConfigData + resp.Diagnostics.Append(endpoints.ProviderConfigData.As(ctx, &namespace, basetypes.ObjectAsOptions{ + UnhandledNullAsEmpty: true, + UnhandledUnknownAsEmpty: true, + })...) + if resp.Diagnostics.HasError() { + return + } + workspaceID = namespace.WorkspaceID.ValueString() + } + + w, diags := d.Client.GetWorkspaceClientForUnifiedProviderWithDiagnostics(ctx, workspaceID) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } + endpointsInfoSdk, err := w.ServingEndpoints.ListAll(ctx) if err != nil { if apierr.IsMissing(err) { diff --git a/internal/providers/pluginfw/products/sharing/data_share.go b/internal/providers/pluginfw/products/sharing/data_share.go index bfb9cbb9d4..248d5c28fa 100644 --- a/internal/providers/pluginfw/products/sharing/data_share.go +++ b/internal/providers/pluginfw/products/sharing/data_share.go @@ -2,6 +2,7 @@ package sharing import ( "context" + "reflect" "github.com/databricks/databricks-sdk-go/apierr" "github.com/databricks/databricks-sdk-go/service/sharing" @@ -13,6 +14,8 @@ import ( "github.com/databricks/terraform-provider-databricks/internal/service/sharing_tf" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-framework/types/basetypes" ) const dataSourceNameShare = "share" @@ -27,12 +30,29 @@ type ShareDataSource struct { Client *common.DatabricksClient } +type ShareData struct { + sharing_tf.ShareInfo + ProviderConfigData types.Object `tfsdk:"provider_config"` +} + +func (s ShareData) GetComplexFieldTypes(ctx context.Context) map[string]reflect.Type { + types := s.ShareInfo.GetComplexFieldTypes(ctx) + types["provider_config"] = reflect.TypeOf(tfschema.ProviderConfigData{}) + return types +} + +func (s ShareData) ApplySchemaCustomizations(attrs map[string]tfschema.AttributeBuilder) map[string]tfschema.AttributeBuilder { + s.ShareInfo.ApplySchemaCustomizations(attrs) + attrs["provider_config"] = attrs["provider_config"].SetOptional() + return attrs +} + func (d *ShareDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { resp.TypeName = pluginfwcommon.GetDatabricksStagingName(dataSourceNameShare) } func (d *ShareDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { - attrs, blocks := tfschema.DataSourceStructToSchemaMap(ctx, sharing_tf.ShareInfo{}, nil) + attrs, blocks := tfschema.DataSourceStructToSchemaMap(ctx, ShareData{}, nil) resp.Schema = schema.Schema{ Attributes: attrs, Blocks: blocks, @@ -47,14 +67,26 @@ func (d *ShareDataSource) Configure(_ context.Context, req datasource.ConfigureR func (d *ShareDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { ctx = pluginfwcontext.SetUserAgentInDataSourceContext(ctx, dataSourceNameShare) - w, diags := d.Client.GetWorkspaceClient() - resp.Diagnostics.Append(diags...) + + var config ShareData + resp.Diagnostics.Append(req.Config.Get(ctx, &config)...) if resp.Diagnostics.HasError() { return } - var config sharing_tf.ShareInfo - diags = req.Config.Get(ctx, &config) + var workspaceID string + if !config.ProviderConfigData.IsNull() { + var namespace tfschema.ProviderConfigData + resp.Diagnostics.Append(config.ProviderConfigData.As(ctx, &namespace, basetypes.ObjectAsOptions{ + UnhandledNullAsEmpty: true, + UnhandledUnknownAsEmpty: true, + })...) + if resp.Diagnostics.HasError() { + return + } + workspaceID = namespace.WorkspaceID.ValueString() + } + w, diags := d.Client.GetWorkspaceClientForUnifiedProviderWithDiagnostics(ctx, workspaceID) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return diff --git a/internal/providers/pluginfw/products/sharing/data_shares.go b/internal/providers/pluginfw/products/sharing/data_shares.go index bdc5301d0e..6051bf632b 100644 --- a/internal/providers/pluginfw/products/sharing/data_shares.go +++ b/internal/providers/pluginfw/products/sharing/data_shares.go @@ -13,34 +13,38 @@ import ( "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-framework/types/basetypes" ) const dataSourceNameShares = "shares" type SharesList struct { - Shares types.List `tfsdk:"shares"` + Shares types.List `tfsdk:"shares"` + ProviderConfigData types.Object `tfsdk:"provider_config"` } -func (SharesList) ApplySchemaCustomizations(attrs map[string]tfschema.AttributeBuilder) map[string]tfschema.AttributeBuilder { - attrs["shares"] = attrs["shares"].SetComputed().SetOptional() - - return attrs -} - -func (SharesList) GetComplexFieldTypes(context.Context) map[string]reflect.Type { +func (s SharesList) GetComplexFieldTypes(context.Context) map[string]reflect.Type { return map[string]reflect.Type{ - "shares": reflect.TypeOf(types.String{}), + "shares": reflect.TypeOf(types.String{}), + "provider_config": reflect.TypeOf(tfschema.ProviderConfigData{}), } } -func (SharesList) ToObjectType(ctx context.Context) types.ObjectType { +func (s SharesList) ToObjectType(ctx context.Context) types.ObjectType { return types.ObjectType{ AttrTypes: map[string]attr.Type{ - "shares": types.ListType{ElemType: types.StringType}, + "shares": types.ListType{ElemType: types.StringType}, + "provider_config": tfschema.ProviderConfigData{}.Type(ctx), }, } } +func (s SharesList) ApplySchemaCustomizations(attrs map[string]tfschema.AttributeBuilder) map[string]tfschema.AttributeBuilder { + attrs["shares"] = attrs["shares"].SetComputed().SetOptional() + attrs["provider_config"] = attrs["provider_config"].SetOptional() + return attrs +} + func DataSourceShares() datasource.DataSource { return &SharesDataSource{} } @@ -71,8 +75,28 @@ func (d *SharesDataSource) Configure(_ context.Context, req datasource.Configure func (d *SharesDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { ctx = pluginfwcontext.SetUserAgentInDataSourceContext(ctx, dataSourceNameShares) - w, diags := d.Client.GetWorkspaceClient() - resp.Diagnostics.Append(diags...) + + var config SharesList + resp.Diagnostics.Append(req.Config.Get(ctx, &config)...) + if resp.Diagnostics.HasError() { + return + } + + var workspaceID string + if !config.ProviderConfigData.IsNull() { + var namespace tfschema.ProviderConfigData + resp.Diagnostics.Append(config.ProviderConfigData.As(ctx, &namespace, basetypes.ObjectAsOptions{ + UnhandledNullAsEmpty: true, + UnhandledUnknownAsEmpty: true, + })...) + if resp.Diagnostics.HasError() { + return + } + workspaceID = namespace.WorkspaceID.ValueString() + } + w, clientDiags := d.Client.GetWorkspaceClientForUnifiedProviderWithDiagnostics(ctx, workspaceID) + + resp.Diagnostics.Append(clientDiags...) if resp.Diagnostics.HasError() { return } @@ -88,5 +112,9 @@ func (d *SharesDataSource) Read(ctx context.Context, req datasource.ReadRequest, shareNames[i] = types.StringValue(share.Name) } - resp.Diagnostics.Append(resp.State.Set(ctx, SharesList{Shares: types.ListValueMust(types.StringType, shareNames)})...) + newState := SharesList{ + Shares: types.ListValueMust(types.StringType, shareNames), + ProviderConfigData: config.ProviderConfigData, + } + resp.Diagnostics.Append(resp.State.Set(ctx, newState)...) } diff --git a/internal/providers/pluginfw/products/sharing/data_shares_acc_test.go b/internal/providers/pluginfw/products/sharing/data_shares_acc_test.go index aa0a9c553c..16389df703 100644 --- a/internal/providers/pluginfw/products/sharing/data_shares_acc_test.go +++ b/internal/providers/pluginfw/products/sharing/data_shares_acc_test.go @@ -19,72 +19,85 @@ func checkSharesDataSourcePopulated(t *testing.T) func(s *terraform.State) error return nil } } -func TestUcAccDataSourceShares(t *testing.T) { - acceptance.UnityWorkspaceLevel(t, acceptance.Step{ - Template: ` - resource "databricks_catalog" "sandbox" { - name = "sandbox{var.RANDOM}" - comment = "this catalog is managed by terraform" - properties = { - purpose = "testing" - } + +const sharesDataTemplate = ` + resource "databricks_catalog" "sandbox" { + name = "sandbox{var.STICKY_RANDOM}" + comment = "this catalog is managed by terraform" + properties = { + purpose = "testing" } + } - resource "databricks_schema" "things" { - catalog_name = databricks_catalog.sandbox.id - name = "things{var.RANDOM}" - comment = "this database is managed by terraform" - properties = { - kind = "various" - } + resource "databricks_schema" "things" { + catalog_name = databricks_catalog.sandbox.id + name = "things{var.STICKY_RANDOM}" + comment = "this database is managed by terraform" + properties = { + kind = "various" } + } - resource "databricks_sql_table" "mytable" { - catalog_name = databricks_catalog.sandbox.id - schema_name = databricks_schema.things.name - name = "bar" - table_type = "MANAGED" - warehouse_id = "{env.TEST_DEFAULT_WAREHOUSE_ID}" + resource "databricks_sql_table" "mytable" { + catalog_name = databricks_catalog.sandbox.id + schema_name = databricks_schema.things.name + name = "bar" + table_type = "MANAGED" + warehouse_id = "{env.TEST_DEFAULT_WAREHOUSE_ID}" - column { - name = "id" - type = "int" - } + column { + name = "id" + type = "int" } + } - resource "databricks_sql_table" "mytable_2" { - catalog_name = databricks_catalog.sandbox.id - schema_name = databricks_schema.things.name - name = "bar_2" - table_type = "MANAGED" - warehouse_id = "{env.TEST_DEFAULT_WAREHOUSE_ID}" + resource "databricks_sql_table" "mytable_2" { + catalog_name = databricks_catalog.sandbox.id + schema_name = databricks_schema.things.name + name = "bar_2" + table_type = "MANAGED" + warehouse_id = "{env.TEST_DEFAULT_WAREHOUSE_ID}" - column { - name = "id" - type = "int" - } + column { + name = "id" + type = "int" } + } - resource "databricks_share_pluginframework" "myshare" { - name = "{var.RANDOM}-terraform-delta-share" - object { - name = databricks_sql_table.mytable.id - comment = "c" - data_object_type = "TABLE" - history_data_sharing_status = "ENABLED" - } - object { - name = databricks_sql_table.mytable_2.id - comment = "c" - data_object_type = "TABLE" - history_data_sharing_status = "ENABLED" - } + resource "databricks_share_pluginframework" "myshare" { + name = "{var.STICKY_RANDOM}-terraform-delta-share" + object { + name = databricks_sql_table.mytable.id + comment = "c" + data_object_type = "TABLE" + history_data_sharing_status = "ENABLED" + } + object { + name = databricks_sql_table.mytable_2.id + comment = "c" + data_object_type = "TABLE" + history_data_sharing_status = "ENABLED" } + } +` +func TestUcAccDataSourceShares(t *testing.T) { + acceptance.UnityWorkspaceLevel(t, acceptance.Step{ + Template: sharesDataTemplate + ` data "databricks_shares_pluginframework" "this" { depends_on = [databricks_share_pluginframework.myshare] } `, Check: checkSharesDataSourcePopulated(t), + }, acceptance.Step{ + Template: sharesDataTemplate + ` + data "databricks_shares_pluginframework" "this" { + depends_on = [databricks_share_pluginframework.myshare] + provider_config = { + workspace_id = "{env.THIS_WORKSPACE_ID}" + } + } + `, + Check: checkSharesDataSourcePopulated(t), }) } diff --git a/internal/providers/pluginfw/products/sharing/resource_acc_test.go b/internal/providers/pluginfw/products/sharing/resource_acc_test.go index f3106a2d26..fa5adbbecf 100644 --- a/internal/providers/pluginfw/products/sharing/resource_acc_test.go +++ b/internal/providers/pluginfw/products/sharing/resource_acc_test.go @@ -2,9 +2,13 @@ package sharing_test import ( "fmt" + "regexp" "testing" + "github.com/databricks/terraform-provider-databricks/common" "github.com/databricks/terraform-provider-databricks/internal/acceptance" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/plancheck" "github.com/hashicorp/terraform-plugin-testing/terraform" ) @@ -192,6 +196,9 @@ func TestUcAccUpdateShareAddObject(t *testing.T) { data_object_type = "TABLE" history_data_sharing_status = "ENABLED" } + provider_config = { + workspace_id = "{env.THIS_WORKSPACE_ID}" + } }`, }) } @@ -351,3 +358,132 @@ func TestUcAccShareReorderObject(t *testing.T) { ExpectNonEmptyPlan: true, }) } + +func shareTemplate(provider_config string) string { + return fmt.Sprintf(` + resource "databricks_share_pluginframework" "myshare" { + name = "{var.STICKY_RANDOM}-share-config" + %s + object { + name = databricks_schema.schema1.id + data_object_type = "SCHEMA" + } + } +`, provider_config) +} + +func TestAccShare_ProviderConfig_Invalid(t *testing.T) { + acceptance.UnityWorkspaceLevel(t, acceptance.Step{ + Template: preTestTemplateSchema + shareTemplate(` + provider_config = { + workspace_id = "invalid" + } + `), + ExpectError: regexp.MustCompile(`(?s)failed to get workspace client.*failed to parse workspace_id.*valid integer`), + }) +} + +func TestAccJobCluster_ProviderConfig_Mismatched(t *testing.T) { + acceptance.UnityWorkspaceLevel(t, acceptance.Step{ + Template: preTestTemplateSchema + shareTemplate(` + provider_config = { + workspace_id = "123" + } + `), + ExpectError: regexp.MustCompile(`(?s)failed to get workspace client.*workspace_id mismatch.*please check the workspace_id provided in provider_config`), + }) +} + +func TestAccJobCluster_ProviderConfig_Required(t *testing.T) { + acceptance.UnityWorkspaceLevel(t, acceptance.Step{ + Template: preTestTemplateSchema + shareTemplate(` + provider_config = { + } + `), + ExpectError: regexp.MustCompile(`(?s).*workspace_id.*is required`), + }) +} + +func TestAccJobCluster_ProviderConfig_EmptyID(t *testing.T) { + acceptance.UnityWorkspaceLevel(t, acceptance.Step{ + Template: preTestTemplateSchema + shareTemplate(` + provider_config = { + workspace_id = "" + } + `), + ExpectError: regexp.MustCompile(`Attribute provider_config\.workspace_id string length must be at least 1`), + }) +} + +func TestAccJobCluster_ProviderConfig_NotProvided(t *testing.T) { + acceptance.UnityWorkspaceLevel(t, acceptance.Step{ + Template: preTestTemplateSchema + shareTemplate(""), + }) +} + +func TestAccJobCluster_ProviderConfig_Match(t *testing.T) { + // acceptance.LoadWorkspaceEnv(t) + // get workspace id here from workspace + acceptance.UnityWorkspaceLevel(t, acceptance.Step{ + Template: preTestTemplateSchema + shareTemplate(""), + }, acceptance.Step{ + Template: preTestTemplateSchema + shareTemplate(` + provider_config = { + workspace_id = "4220866301720038" + } + `), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + common.CheckResourceUpdate{Address: "databricks_share_pluginframework.myshare"}, + common.CheckResourceNoDelete{Address: "databricks_share_pluginframework.myshare"}, + common.CheckResourceNoCreate{Address: "databricks_share_pluginframework.myshare"}, + }, + }, + }) +} + +func TestAccJobCluster_ProviderConfig_Recreate(t *testing.T) { + acceptance.UnityWorkspaceLevel(t, acceptance.Step{ + Template: preTestTemplateSchema + shareTemplate(""), + }, acceptance.Step{ + Template: preTestTemplateSchema + shareTemplate(` + provider_config = { + workspace_id = "4220866301720038" + } + `), + }, acceptance.Step{ + Template: preTestTemplateSchema + shareTemplate(` + provider_config = { + workspace_id = "123" + } + `), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + common.CheckResourceCreate{Address: "databricks_share_pluginframework.myshare"}, + common.CheckResourceDelete{Address: "databricks_share_pluginframework.myshare"}, + }, + }, + ExpectError: regexp.MustCompile(`failed to validate workspace_id: workspace_id mismatch`), + }) +} + +func TestAccJobCluster_ProviderConfig_Remove(t *testing.T) { + acceptance.UnityWorkspaceLevel(t, acceptance.Step{ + Template: preTestTemplateSchema + shareTemplate(""), + }, acceptance.Step{ + Template: preTestTemplateSchema + shareTemplate(` + provider_config = { + workspace_id = "4220866301720038" + } + `), + }, acceptance.Step{ + Template: preTestTemplateSchema + shareTemplate(""), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + common.CheckResourceUpdate{Address: "databricks_share_pluginframework.myshare"}, + common.CheckResourceNoDelete{Address: "databricks_share_pluginframework.myshare"}, + common.CheckResourceNoCreate{Address: "databricks_share_pluginframework.myshare"}, + }, + }, + }) +} diff --git a/internal/providers/pluginfw/products/sharing/resource_share.go b/internal/providers/pluginfw/products/sharing/resource_share.go index 179c6dd937..63e1a14a8c 100644 --- a/internal/providers/pluginfw/products/sharing/resource_share.go +++ b/internal/providers/pluginfw/products/sharing/resource_share.go @@ -20,6 +20,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-framework/types/basetypes" ) const resourceName = "share" @@ -32,13 +33,16 @@ func ResourceShare() resource.Resource { type ShareInfoExtended struct { sharing_tf.ShareInfo_SdkV2 + tfschema.Namespace ID types.String `tfsdk:"id"` // Adding ID field to stay compatible with SDKv2 } var _ pluginfwcommon.ComplexFieldTypeProvider = ShareInfoExtended{} func (s ShareInfoExtended) GetComplexFieldTypes(ctx context.Context) map[string]reflect.Type { - return s.ShareInfo_SdkV2.GetComplexFieldTypes(ctx) + types := s.ShareInfo_SdkV2.GetComplexFieldTypes(ctx) + types["provider_config"] = reflect.TypeOf(tfschema.ProviderConfig{}) + return types } func matchOrder[T any, K comparable](target, reference []T, keyFunc func(T) K) { @@ -159,6 +163,7 @@ func (r *ShareResource) Schema(ctx context.Context, req resource.SchemaRequest, c.SetRequired("object", "partition", "value", "name") c.SetComputed("id") + c.SetOptional("provider_config") return c }) @@ -177,11 +182,7 @@ func (d *ShareResource) Configure(ctx context.Context, req resource.ConfigureReq func (r *ShareResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { ctx = pluginfwcontext.SetUserAgentInResourceContext(ctx, resourceName) - w, diags := r.Client.GetWorkspaceClient() - resp.Diagnostics.Append(diags...) - if resp.Diagnostics.HasError() { - return - } + var plan ShareInfoExtended resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) if resp.Diagnostics.HasError() { @@ -199,6 +200,25 @@ func (r *ShareResource) Create(ctx context.Context, req resource.CreateRequest, if resp.Diagnostics.HasError() { return } + + var workspaceID string + if !plan.ProviderConfig.IsNull() { + var namespace tfschema.ProviderConfig + resp.Diagnostics.Append(plan.ProviderConfig.As(ctx, &namespace, basetypes.ObjectAsOptions{ + UnhandledNullAsEmpty: true, + UnhandledUnknownAsEmpty: true, + })...) + if resp.Diagnostics.HasError() { + return + } + workspaceID = namespace.WorkspaceID.ValueString() + } + w, clientDiags := r.Client.GetWorkspaceClientForUnifiedProviderWithDiagnostics(ctx, workspaceID) + resp.Diagnostics.Append(clientDiags...) + if resp.Diagnostics.HasError() { + return + } + shareInfo, err := w.Shares.Create(ctx, createShare) if err != nil { resp.Diagnostics.AddError("failed to create share", err.Error()) @@ -252,15 +272,27 @@ func (r *ShareResource) Read(ctx context.Context, req resource.ReadRequest, resp return } - w, diags := r.Client.GetWorkspaceClient() - resp.Diagnostics.Append(diags...) + var getShareRequest sharing.GetShareRequest + getShareRequest.IncludeSharedData = true + resp.Diagnostics.Append(req.State.GetAttribute(ctx, path.Root("name"), &getShareRequest.Name)...) if resp.Diagnostics.HasError() { return } - var getShareRequest sharing.GetShareRequest - getShareRequest.IncludeSharedData = true - resp.Diagnostics.Append(req.State.GetAttribute(ctx, path.Root("name"), &getShareRequest.Name)...) + var workspaceID string + if !existingState.ProviderConfig.IsNull() { + var namespace tfschema.ProviderConfig + resp.Diagnostics.Append(existingState.ProviderConfig.As(ctx, &namespace, basetypes.ObjectAsOptions{ + UnhandledNullAsEmpty: true, + UnhandledUnknownAsEmpty: true, + })...) + if resp.Diagnostics.HasError() { + return + } + workspaceID = namespace.WorkspaceID.ValueString() + } + w, clientDiags := r.Client.GetWorkspaceClientForUnifiedProviderWithDiagnostics(ctx, workspaceID) + resp.Diagnostics.Append(clientDiags...) if resp.Diagnostics.HasError() { return } @@ -302,12 +334,6 @@ func (r *ShareResource) Update(ctx context.Context, req resource.UpdateRequest, return } - client, diags := r.Client.GetWorkspaceClient() - resp.Diagnostics.Append(diags...) - if resp.Diagnostics.HasError() { - return - } - var plan ShareInfoExtended resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) if resp.Diagnostics.HasError() { @@ -324,7 +350,24 @@ func (r *ShareResource) Update(ctx context.Context, req resource.UpdateRequest, getShareRequest.Name = state.Name.ValueString() getShareRequest.IncludeSharedData = true - currentShareInfo, err := client.Shares.Get(ctx, getShareRequest) + var workspaceID string + if !plan.ProviderConfig.IsNull() { + var namespace tfschema.ProviderConfig + resp.Diagnostics.Append(plan.ProviderConfig.As(ctx, &namespace, basetypes.ObjectAsOptions{ + UnhandledNullAsEmpty: true, + UnhandledUnknownAsEmpty: true, + })...) + if resp.Diagnostics.HasError() { + return + } + workspaceID = namespace.WorkspaceID.ValueString() + } + w, clientDiags := r.Client.GetWorkspaceClientForUnifiedProviderWithDiagnostics(ctx, workspaceID) + resp.Diagnostics.Append(clientDiags...) + if resp.Diagnostics.HasError() { + return + } + currentShareInfo, err := w.Shares.Get(ctx, getShareRequest) if err != nil { resp.Diagnostics.AddError("failed to get current share info", err.Error()) return @@ -337,7 +380,7 @@ func (r *ShareResource) Update(ctx context.Context, req resource.UpdateRequest, // if owner has changed, update the share owner if !plan.Owner.IsNull() { - updatedShareInfo, err := client.Shares.Update(ctx, sharing.UpdateShare{ + updatedShareInfo, err := w.Shares.Update(ctx, sharing.UpdateShare{ Name: state.Name.ValueString(), Owner: plan.Owner.ValueString(), }) @@ -362,12 +405,12 @@ func (r *ShareResource) Update(ctx context.Context, req resource.UpdateRequest, if !plan.Comment.IsNull() { update.Comment = plan.Comment.ValueString() } - upToDateShareInfo, err = client.Shares.Update(ctx, update) + upToDateShareInfo, err = w.Shares.Update(ctx, update) if err != nil { resp.Diagnostics.AddError("failed to update share", err.Error()) - rollbackShareInfo, rollbackErr := client.Shares.Update(ctx, sharing.UpdateShare{ + rollbackShareInfo, rollbackErr := w.Shares.Update(ctx, sharing.UpdateShare{ Name: currentShareInfo.Name, Owner: currentShareInfo.Owner, }) @@ -402,8 +445,8 @@ func (r *ShareResource) Update(ctx context.Context, req resource.UpdateRequest, func (r *ShareResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { ctx = pluginfwcontext.SetUserAgentInResourceContext(ctx, resourceName) - w, diags := r.Client.GetWorkspaceClient() - resp.Diagnostics.Append(diags...) + var state ShareInfoExtended + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) if resp.Diagnostics.HasError() { return } @@ -413,6 +456,24 @@ func (r *ShareResource) Delete(ctx context.Context, req resource.DeleteRequest, if resp.Diagnostics.HasError() { return } + + var workspaceID string + if !state.ProviderConfig.IsNull() { + var namespace tfschema.ProviderConfig + resp.Diagnostics.Append(state.ProviderConfig.As(ctx, &namespace, basetypes.ObjectAsOptions{ + UnhandledNullAsEmpty: true, + UnhandledUnknownAsEmpty: true, + })...) + if resp.Diagnostics.HasError() { + return + } + workspaceID = namespace.WorkspaceID.ValueString() + } + w, clientDiags := r.Client.GetWorkspaceClientForUnifiedProviderWithDiagnostics(ctx, workspaceID) + resp.Diagnostics.Append(clientDiags...) + if resp.Diagnostics.HasError() { + return + } err := w.Shares.DeleteByName(ctx, deleteShareRequest.Name.ValueString()) if err != nil && !apierr.IsMissing(err) { resp.Diagnostics.AddError("failed to delete share", err.Error()) @@ -456,5 +517,6 @@ func (r *ShareResource) syncEffectiveFields(ctx context.Context, plan, state Sha finalObjects = append(finalObjects, stateObjects[i]) } state.SetObjects(ctx, finalObjects) + state.ProviderConfig = plan.ProviderConfig // Preserve provider_config from plan return state, d } diff --git a/internal/providers/pluginfw/products/volume/data_volumes.go b/internal/providers/pluginfw/products/volume/data_volumes.go index e5772cce4b..262e8b80ef 100644 --- a/internal/providers/pluginfw/products/volume/data_volumes.go +++ b/internal/providers/pluginfw/products/volume/data_volumes.go @@ -16,6 +16,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-framework/types/basetypes" ) const dataSourceName = "volumes" @@ -31,21 +32,24 @@ type VolumesDataSource struct { } type VolumesList struct { - CatalogName types.String `tfsdk:"catalog_name"` - SchemaName types.String `tfsdk:"schema_name"` - Ids types.List `tfsdk:"ids"` + CatalogName types.String `tfsdk:"catalog_name"` + SchemaName types.String `tfsdk:"schema_name"` + Ids types.List `tfsdk:"ids"` + ProviderConfigData types.Object `tfsdk:"provider_config"` } func (VolumesList) ApplySchemaCustomizations(attrs map[string]tfschema.AttributeBuilder) map[string]tfschema.AttributeBuilder { attrs["catalog_name"] = attrs["catalog_name"].SetRequired() attrs["schema_name"] = attrs["schema_name"].SetRequired() attrs["ids"] = attrs["ids"].SetOptional().SetComputed() + attrs["provider_config"] = attrs["provider_config"].SetOptional() return attrs } func (VolumesList) GetComplexFieldTypes(context.Context) map[string]reflect.Type { return map[string]reflect.Type{ - "ids": reflect.TypeOf(types.String{}), + "ids": reflect.TypeOf(types.String{}), + "provider_config": reflect.TypeOf(tfschema.ProviderConfigData{}), } } @@ -69,20 +73,34 @@ func (d *VolumesDataSource) Configure(_ context.Context, req datasource.Configur func (d *VolumesDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { ctx = pluginfwcontext.SetUserAgentInDataSourceContext(ctx, dataSourceName) - w, diags := d.Client.GetWorkspaceClient() - resp.Diagnostics.Append(diags...) - if resp.Diagnostics.HasError() { - return - } var volumesList VolumesList - diags = req.Config.Get(ctx, &volumesList) + diags := req.Config.Get(ctx, &volumesList) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } var listVolumesRequest catalog.ListVolumesRequest converters.TfSdkToGoSdkStruct(ctx, volumesList, &listVolumesRequest) + + var workspaceID string + if !volumesList.ProviderConfigData.IsNull() { + var namespace tfschema.ProviderConfigData + resp.Diagnostics.Append(volumesList.ProviderConfigData.As(ctx, &namespace, basetypes.ObjectAsOptions{ + UnhandledNullAsEmpty: true, + UnhandledUnknownAsEmpty: true, + })...) + if resp.Diagnostics.HasError() { + return + } + workspaceID = namespace.WorkspaceID.ValueString() + } + w, clientDiags := d.Client.GetWorkspaceClientForUnifiedProviderWithDiagnostics(ctx, workspaceID) + resp.Diagnostics.Append(clientDiags...) + if resp.Diagnostics.HasError() { + return + } + volumes, err := w.Volumes.ListAll(ctx, listVolumesRequest) if err != nil { if apierr.IsMissing(err) { diff --git a/internal/providers/pluginfw/products/volume/data_volumes_acc_test.go b/internal/providers/pluginfw/products/volume/data_volumes_acc_test.go index 3195d47e02..e3ca113800 100644 --- a/internal/providers/pluginfw/products/volume/data_volumes_acc_test.go +++ b/internal/providers/pluginfw/products/volume/data_volumes_acc_test.go @@ -20,38 +20,53 @@ func checkDataSourceVolumesPopulated(t *testing.T) func(s *terraform.State) erro } } -func TestUcAccDataSourceVolumes(t *testing.T) { - acceptance.UnityWorkspaceLevel(t, acceptance.Step{ - Template: ` - resource "databricks_catalog" "sandbox" { - name = "sandbox{var.RANDOM}" - comment = "this catalog is managed by terraform" - properties = { - purpose = "testing" - } +const volumesTemplate = ` + resource "databricks_catalog" "sandbox" { + name = "sandbox{var.STICKY_RANDOM}" + comment = "this catalog is managed by terraform" + properties = { + purpose = "testing" } + } - resource "databricks_schema" "things" { - catalog_name = databricks_catalog.sandbox.id - name = "things{var.RANDOM}" - comment = "this database is managed by terraform" - properties = { - kind = "various" - } + resource "databricks_schema" "things" { + catalog_name = databricks_catalog.sandbox.id + name = "things{var.STICKY_RANDOM}" + comment = "this database is managed by terraform" + properties = { + kind = "various" } - resource "databricks_volume" "this" { - name = "volume_data_source_test" + } + resource "databricks_volume" "this" { + name = "volume_data_source_test" + catalog_name = databricks_catalog.sandbox.name + schema_name = databricks_schema.things.name + volume_type = "MANAGED" + } + output "volumes" { + value = length(data.databricks_volumes.this.ids) + } +` + +func TestUcAccDataSourceVolumes(t *testing.T) { + acceptance.UnityWorkspaceLevel(t, acceptance.Step{ + Template: volumesTemplate + ` + data "databricks_volumes" "this" { catalog_name = databricks_catalog.sandbox.name - schema_name = databricks_schema.things.name - volume_type = "MANAGED" + schema_name = databricks_schema.things.name + depends_on = [ databricks_volume.this ] } + `, + Check: checkDataSourceVolumesPopulated(t), + }, acceptance.Step{ + Template: volumesTemplate + ` data "databricks_volumes" "this" { catalog_name = databricks_catalog.sandbox.name schema_name = databricks_schema.things.name depends_on = [ databricks_volume.this ] - } - output "volumes" { - value = length(data.databricks_volumes.this.ids) + provider_config = { + workspace_id = "{env.THIS_WORKSPACE_ID}" + } } `, Check: checkDataSourceVolumesPopulated(t), diff --git a/internal/providers/pluginfw/tfschema/attribute_converter.go b/internal/providers/pluginfw/tfschema/attribute_converter.go index 56efce9569..7865b85aec 100644 --- a/internal/providers/pluginfw/tfschema/attribute_converter.go +++ b/internal/providers/pluginfw/tfschema/attribute_converter.go @@ -7,12 +7,16 @@ type Blockable interface { ToBlock() BlockBuilder } -// convertAttributesToBlocks converts all attributes implementing the Blockable interface to blocks, returning -// a new NestedBlockObject with the converted attributes and the original blocks. +// convertAttributesToBlocks converts all attributes implementing the Blockable interface to blocks except for "provider_config", +// returning a new NestedBlockObject with the converted attributes and the original blocks. func convertAttributesToBlocks(attributes map[string]AttributeBuilder, blocks map[string]BlockBuilder) NestedBlockObject { newAttributes := make(map[string]AttributeBuilder) newBlocks := make(map[string]BlockBuilder) for name, attr := range attributes { + if name == "provider_config" { + newAttributes[name] = attr + continue + } if lnab, ok := attr.(Blockable); ok { newBlocks[name] = lnab.ToBlock() } else { diff --git a/internal/providers/pluginfw/tfschema/unified_provider.go b/internal/providers/pluginfw/tfschema/unified_provider.go new file mode 100644 index 0000000000..38a1a43087 --- /dev/null +++ b/internal/providers/pluginfw/tfschema/unified_provider.go @@ -0,0 +1,94 @@ +package tfschema + +import ( + "context" + "reflect" + + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" + "github.com/hashicorp/terraform-plugin-framework/attr" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-framework/types/basetypes" +) + +type Namespace struct { + ProviderConfig types.Object `tfsdk:"provider_config"` +} + +// ProviderConfig is used to store the provider configurations for unified terraform provider +// across resources onboarded to plugin framework. +type ProviderConfig struct { + WorkspaceID types.String `tfsdk:"workspace_id"` +} + +func (r ProviderConfig) ApplySchemaCustomizations(attrs map[string]AttributeBuilder) map[string]AttributeBuilder { + attrs["workspace_id"] = attrs["workspace_id"].SetRequired() + attrs["workspace_id"] = attrs["workspace_id"].(StringAttributeBuilder).AddPlanModifier( + stringplanmodifier.RequiresReplaceIf(workspaceIDPlanModifier, "", "")) + attrs["workspace_id"] = attrs["workspace_id"].(StringAttributeBuilder).AddValidator(stringvalidator.LengthAtLeast(1)) + return attrs +} + +func workspaceIDPlanModifier(ctx context.Context, req planmodifier.StringRequest, resp *stringplanmodifier.RequiresReplaceIfFuncResponse) { + // Require replacement if workspace_id changes from one non-empty value to another + oldValue := req.StateValue.ValueString() + newValue := req.PlanValue.ValueString() + + if oldValue != "" && newValue != "" && oldValue != newValue { + resp.RequiresReplace = true + } +} + +func (r ProviderConfig) GetComplexFieldTypes(ctx context.Context) map[string]reflect.Type { + return map[string]reflect.Type{} +} + +func (r ProviderConfig) ToObjectValue(ctx context.Context) basetypes.ObjectValue { + return types.ObjectValueMust( + r.Type(ctx).(basetypes.ObjectType).AttrTypes, + map[string]attr.Value{ + "workspace_id": r.WorkspaceID, + }, + ) +} + +func (r ProviderConfig) Type(ctx context.Context) attr.Type { + return types.ObjectType{ + AttrTypes: map[string]attr.Type{ + "workspace_id": types.StringType, + }, + } +} + +// ProviderConfigData is used to store the provider configurations for unified terraform provider +// across data sources onboarded to plugin framework. +type ProviderConfigData struct { + WorkspaceID types.String `tfsdk:"workspace_id"` +} + +func (r ProviderConfigData) ApplySchemaCustomizations(attrs map[string]AttributeBuilder) map[string]AttributeBuilder { + attrs["workspace_id"] = attrs["workspace_id"].SetRequired() + return attrs +} + +func (r ProviderConfigData) GetComplexFieldTypes(ctx context.Context) map[string]reflect.Type { + return map[string]reflect.Type{} +} + +func (r ProviderConfigData) ToObjectValue(ctx context.Context) basetypes.ObjectValue { + return types.ObjectValueMust( + r.Type(ctx).(basetypes.ObjectType).AttrTypes, + map[string]attr.Value{ + "workspace_id": r.WorkspaceID, + }, + ) +} + +func (r ProviderConfigData) Type(ctx context.Context) attr.Type { + return types.ObjectType{ + AttrTypes: map[string]attr.Type{ + "workspace_id": types.StringType, + }, + } +} diff --git a/jobs/data_job.go b/jobs/data_job.go index 5559325e4e..3b3a70a4d0 100755 --- a/jobs/data_job.go +++ b/jobs/data_job.go @@ -14,6 +14,7 @@ func DataSourceJob() common.Resource { Name string `json:"name,omitempty" tf:"computed"` JobName string `json:"job_name,omitempty" tf:"computed"` Job *Job `json:"job_settings,omitempty" tf:"computed"` + common.Namespace } return common.DataResource(queryableJobData{}, func(ctx context.Context, e any, c *common.DatabricksClient) error { data := e.(*queryableJobData) diff --git a/jobs/data_job_acc_test.go b/jobs/data_job_acc_test.go index 4733280fbd..3480cd3295 100755 --- a/jobs/data_job_acc_test.go +++ b/jobs/data_job_acc_test.go @@ -1,9 +1,12 @@ package jobs_test import ( + "fmt" + "regexp" "testing" "github.com/databricks/terraform-provider-databricks/internal/acceptance" + "github.com/hashicorp/terraform-plugin-testing/terraform" ) func TestAccDataSourceJob(t *testing.T) { @@ -58,3 +61,82 @@ func TestAccDataSourceJob(t *testing.T) { }`, }) } + +func TestAccDataSourceJob_InvalidID(t *testing.T) { + acceptance.WorkspaceLevel(t, acceptance.Step{ + Template: jobClusterTemplate("") + ` + data "databricks_job" "this" { + job_name = databricks_job.this.name + provider_config { + workspace_id = "invalid" + } + }`, + ExpectError: regexp.MustCompile(`failed to parse workspace_id.*invalid syntax`), + }) +} + +func TestAccDataSourceJob_MismatchedID(t *testing.T) { + acceptance.WorkspaceLevel(t, acceptance.Step{ + Template: jobClusterTemplate("") + ` + data "databricks_job" "this" { + job_name = databricks_job.this.name + provider_config { + workspace_id = "123" + } + }`, + ExpectError: regexp.MustCompile(`workspace_id mismatch.*please check the workspace_id provided in provider_config`), + }) +} + +func TestAccDataSourceJob_EmptyID(t *testing.T) { + acceptance.WorkspaceLevel(t, acceptance.Step{ + Template: jobClusterTemplate("") + ` + data "databricks_job" "this" { + job_name = databricks_job.this.name + provider_config { + workspace_id = "" + } + }`, + ExpectError: regexp.MustCompile(`expected "provider_config.0.workspace_id" to not be an empty string`), + }) +} + +func TestAccDataSourceJob_EmptyBlock(t *testing.T) { + acceptance.WorkspaceLevel(t, acceptance.Step{ + Template: jobClusterTemplate("") + ` + data "databricks_job" "this" { + job_name = databricks_job.this.name + provider_config { + } + }`, + ExpectError: regexp.MustCompile(`The argument "workspace_id" is required, but no definition was found.`), + }) +} + +func TestAccDataSourceJob_Match(t *testing.T) { + acceptance.WorkspaceLevel(t, acceptance.Step{ + Template: jobClusterTemplate("") + ` + data "databricks_job" "this" { + job_name = databricks_job.this.name + }`, + }, acceptance.Step{ + Template: jobClusterTemplate("") + ` + data "databricks_job" "this" { + job_name = databricks_job.this.name + provider_config { + workspace_id = "1142582526922259" + } + }`, + Check: func(s *terraform.State) error { + r, ok := s.RootModule().Resources["data.databricks_job.this"] + if !ok { + return fmt.Errorf("data not found in state") + } + id := r.Primary.Attributes["provider_config.0.workspace_id"] + if id != "1142582526922259" { + return fmt.Errorf("wrong workspace_id found: %v", r.Primary.Attributes) + } + return nil + }, + }) +} diff --git a/jobs/data_jobs.go b/jobs/data_jobs.go index 14da68e1bc..91c2e3729f 100644 --- a/jobs/data_jobs.go +++ b/jobs/data_jobs.go @@ -21,6 +21,7 @@ func DataSourceJobs() common.Resource { Ids map[string]string `json:"ids,omitempty" tf:"computed"` NameFilter string `json:"job_name_contains,omitempty"` Key string `json:"key,omitempty" tf:"default:name"` + common.Namespace }, w *databricks.WorkspaceClient) error { iter := w.Jobs.List(ctx, jobs.ListJobsRequest{ExpandTasks: false, Limit: 100}) data.Ids = map[string]string{} diff --git a/jobs/data_jobs_acc_test.go b/jobs/data_jobs_acc_test.go new file mode 100644 index 0000000000..f7d1cf0842 --- /dev/null +++ b/jobs/data_jobs_acc_test.go @@ -0,0 +1,89 @@ +package jobs_test + +import ( + "fmt" + "regexp" + "testing" + + "github.com/databricks/terraform-provider-databricks/internal/acceptance" + "github.com/hashicorp/terraform-plugin-testing/terraform" +) + +func TestAccDataSourcesJob_InvalidID(t *testing.T) { + acceptance.WorkspaceLevel(t, acceptance.Step{ + Template: ` + data "databricks_jobs" "all" { + key = "id" + provider_config { + workspace_id = "invalid" + } + }`, + ExpectError: regexp.MustCompile(`failed to parse workspace_id.*invalid syntax`), + }) +} + +func TestAccDataSourcesJob_MismatchedID(t *testing.T) { + acceptance.WorkspaceLevel(t, acceptance.Step{ + Template: ` + data "databricks_jobs" "all" { + key = "id" + provider_config { + workspace_id = "123" + } + }`, + ExpectError: regexp.MustCompile(`workspace_id mismatch.*please check the workspace_id provided in provider_config`), + }) +} + +func TestAccDataSourcesJob_EmptyID(t *testing.T) { + acceptance.WorkspaceLevel(t, acceptance.Step{ + Template: ` + data "databricks_jobs" "all" { + key = "id" + provider_config { + workspace_id = "" + } + }`, + ExpectError: regexp.MustCompile(`expected "provider_config.0.workspace_id" to not be an empty string`), + }) +} + +func TestAccDataSourcesJob_EmptyBlock(t *testing.T) { + acceptance.WorkspaceLevel(t, acceptance.Step{ + Template: ` + data "databricks_jobs" "all" { + key = "id" + provider_config { + } + }`, + ExpectError: regexp.MustCompile(`The argument "workspace_id" is required, but no definition was found.`), + }) +} + +func TestAccDataSourcesJob(t *testing.T) { + acceptance.WorkspaceLevel(t, acceptance.Step{ + Template: ` + data "databricks_jobs" "all" { + key = "id" + }`, + }, acceptance.Step{ + Template: ` + data "databricks_jobs" "all" { + key = "id" + provider_config { + workspace_id = "1142582526922259" + } + }`, + Check: func(s *terraform.State) error { + r, ok := s.RootModule().Resources["data.databricks_jobs.all"] + if !ok { + return fmt.Errorf("data not found in state") + } + id := r.Primary.Attributes["provider_config.0.workspace_id"] + if id != "1142582526922259" { + return fmt.Errorf("wrong workspace_id found: %v", r.Primary.Attributes) + } + return nil + }, + }) +} diff --git a/jobs/job_test.go b/jobs/job_test.go index 2812338cad..4ef86b695d 100644 --- a/jobs/job_test.go +++ b/jobs/job_test.go @@ -3,6 +3,8 @@ package jobs_test import ( "context" "errors" + "fmt" + "regexp" "strconv" "testing" "time" @@ -12,9 +14,201 @@ import ( "github.com/databricks/terraform-provider-databricks/common" "github.com/databricks/terraform-provider-databricks/internal/acceptance" "github.com/databricks/terraform-provider-databricks/qa" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/plancheck" "github.com/stretchr/testify/assert" ) +func jobClusterTemplate(provider_config string) string { + return fmt.Sprintf(` + data "databricks_current_user" "me" {} + data "databricks_spark_version" "latest" {} + data "databricks_node_type" "smallest" { + local_disk = true + } + + resource "databricks_notebook" "this" { + path = "${data.databricks_current_user.me.home}/Terraform{var.RANDOM}" + language = "PYTHON" + content_base64 = base64encode(<<-EOT + # created from ${abspath(path.module)} + display(spark.range(10)) + EOT + ) + } + + resource "databricks_job" "this" { + name = "{var.RANDOM}" + + %s + + job_cluster { + job_cluster_key = "j" + new_cluster { + num_workers = 0 // Setting it to zero intentionally to cover edge case. + spark_version = data.databricks_spark_version.latest.id + node_type_id = data.databricks_node_type.smallest.id + custom_tags = { + "ResourceClass" = "SingleNode" + } + spark_conf = { + "spark.databricks.cluster.profile" : "singleNode" + "spark.master" : "local[*,4]" + } + } + } + + task { + task_key = "a" + + new_cluster { + num_workers = 1 + spark_version = data.databricks_spark_version.latest.id + node_type_id = data.databricks_node_type.smallest.id + } + + notebook_task { + notebook_path = databricks_notebook.this.path + } + } + + task { + task_key = "b" + + depends_on { + task_key = "a" + } + + new_cluster { + num_workers = 8 + spark_version = data.databricks_spark_version.latest.id + node_type_id = data.databricks_node_type.smallest.id + } + + notebook_task { + notebook_path = databricks_notebook.this.path + } + } + } +`, provider_config) +} + +func TestAccJobCluster_ProviderConfig_Invalid(t *testing.T) { + acceptance.WorkspaceLevel(t, acceptance.Step{ + Template: jobClusterTemplate(` + provider_config { + workspace_id = "invalid" + } + `), + ExpectError: regexp.MustCompile(`failed to parse workspace_id.*invalid syntax`), + }) +} + +func TestAccJobCluster_ProviderConfig_Mismatched(t *testing.T) { + acceptance.WorkspaceLevel(t, acceptance.Step{ + Template: jobClusterTemplate(` + provider_config { + workspace_id = "123" + } + `), + ExpectError: regexp.MustCompile(`workspace_id mismatch.*please check the workspace_id provided in provider_config`), + }) +} + +func TestAccJobCluster_ProviderConfig_Required(t *testing.T) { + acceptance.WorkspaceLevel(t, acceptance.Step{ + Template: jobClusterTemplate(` + provider_config { + } + `), + ExpectError: regexp.MustCompile(`The argument "workspace_id" is required, but no definition was found.`), + }) +} + +func TestAccJobCluster_ProviderConfig_EmptyID(t *testing.T) { + acceptance.WorkspaceLevel(t, acceptance.Step{ + Template: jobClusterTemplate(` + provider_config { + workspace_id = "" + } + `), + ExpectError: regexp.MustCompile(`expected "provider_config.0.workspace_id" to not be an empty string`), + }) +} + +func TestAccJobCluster_ProviderConfig_NotProvided(t *testing.T) { + acceptance.WorkspaceLevel(t, acceptance.Step{ + Template: jobClusterTemplate(""), + }) +} + +func TestAccJobCluster_ProviderConfig_Match(t *testing.T) { + acceptance.LoadWorkspaceEnv(t) + // get workspace id here from workspace + acceptance.WorkspaceLevel(t, acceptance.Step{ + Template: jobClusterTemplate(""), + }, acceptance.Step{ + Template: jobClusterTemplate(` + provider_config { + workspace_id = "1142582526922259" + } + `), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + common.CheckResourceUpdate{Address: "databricks_job.this"}, + common.CheckResourceNoDelete{Address: "databricks_job.this"}, + common.CheckResourceNoCreate{Address: "databricks_job.this"}, + }, + }, + }) +} + +func TestAccJobCluster_ProviderConfig_Recreate(t *testing.T) { + acceptance.WorkspaceLevel(t, acceptance.Step{ + Template: jobClusterTemplate(""), + }, acceptance.Step{ + Template: jobClusterTemplate(` + provider_config { + workspace_id = "1142582526922259" + } + `), + }, acceptance.Step{ + Template: jobClusterTemplate(` + provider_config { + workspace_id = "123" + } + `), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + common.CheckResourceCreate{Address: "databricks_job.this"}, + common.CheckResourceDelete{Address: "databricks_job.this"}, + }, + }, + ExpectError: regexp.MustCompile(`failed to validate workspace_id: workspace_id mismatch`), + }) +} + +func TestAccJobCluster_ProviderConfig_Remove(t *testing.T) { + acceptance.WorkspaceLevel(t, acceptance.Step{ + Template: jobClusterTemplate(""), + }, acceptance.Step{ + Template: jobClusterTemplate(` + provider_config { + workspace_id = "1142582526922259" + } + `), + }, acceptance.Step{ + Template: jobClusterTemplate(""), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + common.CheckResourceUpdate{Address: "databricks_job.this"}, + common.CheckResourceNoDelete{Address: "databricks_job.this"}, + common.CheckResourceNoCreate{Address: "databricks_job.this"}, + }, + }, + }) +} + func TestAccJobTasks(t *testing.T) { acceptance.WorkspaceLevel(t, acceptance.Step{ Template: ` diff --git a/jobs/resource_job.go b/jobs/resource_job.go index 0490b1d232..6a97533d2f 100644 --- a/jobs/resource_job.go +++ b/jobs/resource_job.go @@ -486,6 +486,7 @@ func (JobCreateStruct) CustomizeSchema(s *common.CustomizableSchema) *common.Cus type JobSettingsResource struct { jobs.JobSettings + common.Namespace // BEGIN Jobs API 2.0 ExistingClusterID string `json:"existing_cluster_id,omitempty" tf:"group:cluster_type"` @@ -510,6 +511,7 @@ func (JobSettingsResource) Aliases() map[string]map[string]string { } func (JobSettingsResource) CustomizeSchema(s *common.CustomizableSchema) *common.CustomizableSchema { + common.NamespaceCustomizeSchema(s) // Suppress diffs s.SchemaPath("email_notifications").SetSuppressDiff() s.SchemaPath("webhook_notifications").SetSuppressDiff() @@ -657,6 +659,8 @@ func (JobSettingsResource) CustomizeSchema(s *common.CustomizableSchema) *common // Technically this is required by the API, but marking it optional since we can infer it from the hostname. s.SchemaPath("git_source", "provider").SetOptional() + common.NamespaceCustomizeSchema(s) + return s } @@ -1088,14 +1092,14 @@ func ResourceJob() common.Resource { return fmt.Errorf("`control_run_state` must be specified only with `max_concurrent_runs = 1`") } } - return nil + return common.NamespaceCustomizeDiff(d) }, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { var jsr JobSettingsResource common.DataToStructPointer(d, jobsGoSdkSchema, &jsr) if jsr.isMultiTask() { // Api 2.1 - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -1131,7 +1135,7 @@ func ResourceJob() common.Resource { common.DataToStructPointer(d, jobsGoSdkSchema, &jsr) if jsr.isMultiTask() { // Api 2.1 - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -1173,7 +1177,7 @@ func ResourceJob() common.Resource { if err != nil { return err } - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -1200,7 +1204,7 @@ func ResourceJob() common.Resource { }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { ctx = getReadCtx(ctx, d) - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } diff --git a/mlflow/data_mlflow_experiment.go b/mlflow/data_mlflow_experiment.go index e4ed958a34..c3718bfc30 100644 --- a/mlflow/data_mlflow_experiment.go +++ b/mlflow/data_mlflow_experiment.go @@ -11,6 +11,7 @@ import ( func DataSourceExperiment() common.Resource { type experimentDataParams struct { + common.Namespace ExperimentId string `json:"experiment_id" tf:"computed,optional"` Name string `json:"name" tf:"computed,optional"` } diff --git a/mlflow/data_mlflow_model.go b/mlflow/data_mlflow_model.go index 7855002743..a2cf73c459 100644 --- a/mlflow/data_mlflow_model.go +++ b/mlflow/data_mlflow_model.go @@ -10,6 +10,7 @@ import ( func DataSourceModel() common.Resource { return common.WorkspaceData(func(ctx context.Context, data *struct { + common.Namespace Name string `json:"name"` UserId string `json:"user_id,omitempty" tf:"computed"` Description string `json:"description,omitempty" tf:"computed"` diff --git a/mlflow/data_mlflow_models.go b/mlflow/data_mlflow_models.go index 127b4f465f..6654efdd33 100644 --- a/mlflow/data_mlflow_models.go +++ b/mlflow/data_mlflow_models.go @@ -10,6 +10,7 @@ import ( ) type modelsData struct { + common.Namespace Names []string `json:"names,omitempty" tf:"computed"` } diff --git a/mlflow/resource_mlflow_experiment.go b/mlflow/resource_mlflow_experiment.go index eb8668f466..64af7a6481 100644 --- a/mlflow/resource_mlflow_experiment.go +++ b/mlflow/resource_mlflow_experiment.go @@ -10,6 +10,11 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) +type Experiment struct { + ml.Experiment + common.Namespace +} + func experimentNameSuppressDiff(k, old, new string, d *schema.ResourceData) bool { if strings.TrimSuffix(strings.TrimPrefix(new, "/Workspace"), "/") == strings.TrimSuffix(strings.TrimPrefix(old, "/Workspace"), "/") { @@ -21,7 +26,7 @@ func experimentNameSuppressDiff(k, old, new string, d *schema.ResourceData) bool func ResourceMlflowExperiment() common.Resource { s := common.StructToSchema( - ml.Experiment{}, + Experiment{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { for _, p := range []string{"creation_time", "experiment_id", "last_update_time", "lifecycle_stage", "tags"} { common.CustomizeSchemaPath(m, p).SetComputed() @@ -34,12 +39,13 @@ func ResourceMlflowExperiment() common.Resource { Type: schema.TypeString, Deprecated: "Remove the description attribute as it no longer is used and will be removed in a future version.", } + common.NamespaceCustomizeSchemaMap(m) return m }) return common.Resource{ Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -53,7 +59,7 @@ func ResourceMlflowExperiment() common.Resource { return nil }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -64,7 +70,7 @@ func ResourceMlflowExperiment() common.Resource { return common.StructToData(e.Experiment, s, d) }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -74,7 +80,7 @@ func ResourceMlflowExperiment() common.Resource { }) }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -84,5 +90,8 @@ func ResourceMlflowExperiment() common.Resource { Schema: s, SchemaVersion: 0, Timeouts: &schema.ResourceTimeout{}, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, } } diff --git a/mlflow/resource_mlflow_model.go b/mlflow/resource_mlflow_model.go index a461287215..e3765b9dc0 100644 --- a/mlflow/resource_mlflow_model.go +++ b/mlflow/resource_mlflow_model.go @@ -8,21 +8,27 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) +type CreateModelRequest struct { + ml.CreateModelRequest + common.Namespace +} + func ResourceMlflowModel() common.Resource { s := common.StructToSchema( - ml.CreateModelRequest{}, + CreateModelRequest{}, func(s map[string]*schema.Schema) map[string]*schema.Schema { s["name"].ForceNew = true s["registered_model_id"] = &schema.Schema{ Computed: true, Type: schema.TypeString, } + common.NamespaceCustomizeSchemaMap(s) return s }) return common.Resource{ Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -36,7 +42,7 @@ func ResourceMlflowModel() common.Resource { return nil }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -55,7 +61,7 @@ func ResourceMlflowModel() common.Resource { return nil }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -68,7 +74,7 @@ func ResourceMlflowModel() common.Resource { return nil }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -78,5 +84,8 @@ func ResourceMlflowModel() common.Resource { return w.ModelRegistry.DeleteModel(ctx, req) }, Schema: s, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, } } diff --git a/mlflow/resource_mlflow_webhook.go b/mlflow/resource_mlflow_webhook.go index 91ef36c261..18bfd94f45 100644 --- a/mlflow/resource_mlflow_webhook.go +++ b/mlflow/resource_mlflow_webhook.go @@ -13,6 +13,11 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) +type CreateRegistryWebhook struct { + ml.CreateRegistryWebhook + common.Namespace +} + func readWebHook(w *databricks.WorkspaceClient, ctx context.Context, ID string) (ml.RegistryWebhook, error) { m, err := w.ModelRegistry.ListWebhooksAll(ctx, ml.ListWebhooksRequest{}) if err != nil { @@ -29,7 +34,7 @@ func readWebHook(w *databricks.WorkspaceClient, ctx context.Context, ID string) func ResourceMlflowWebhook() common.Resource { s := common.StructToSchema( - ml.CreateRegistryWebhook{}, + CreateRegistryWebhook{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { m["status"].ValidateFunc = validation.StringInSlice([]string{"ACTIVE", "TEST_MODE", "DISABLED"}, true) if p, err := common.SchemaPath(m, "http_url_spec", "url"); err == nil { @@ -40,13 +45,13 @@ func ResourceMlflowWebhook() common.Resource { common.MustSchemaPath(m, "http_url_spec", "enable_ssl_verification").Default = true common.MustSchemaPath(m, "http_url_spec", "secret").Sensitive = true common.MustSchemaPath(m, "job_spec", "access_token").Sensitive = true - + common.NamespaceCustomizeSchemaMap(m) return m }) return common.Resource{ Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -66,7 +71,7 @@ func ResourceMlflowWebhook() common.Resource { Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { var mOrig ml.CreateRegistryWebhook common.DataToStructPointer(d, s, &mOrig) - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -88,7 +93,7 @@ func ResourceMlflowWebhook() common.Resource { return nil }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -102,12 +107,15 @@ func ResourceMlflowWebhook() common.Resource { return nil }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } return w.ModelRegistry.DeleteWebhook(ctx, ml.DeleteWebhookRequest{Id: d.Id()}) }, Schema: s, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, } } diff --git a/mws/data_current_config.go b/mws/data_current_config.go index 4e45a0b656..7a4a76c275 100644 --- a/mws/data_current_config.go +++ b/mws/data_current_config.go @@ -7,6 +7,7 @@ import ( ) type currentConfig struct { + common.Namespace IsAccount bool `json:"is_account,omitempty" tf:"computed"` AccountId string `json:"account_id,omitempty" tf:"computed"` Host string `json:"host,omitempty" tf:"computed"` diff --git a/mws/data_mws_credentials.go b/mws/data_mws_credentials.go index aa757fd858..4305717067 100755 --- a/mws/data_mws_credentials.go +++ b/mws/data_mws_credentials.go @@ -9,6 +9,7 @@ import ( func DataSourceMwsCredentials() common.Resource { type mwsCredentialsData struct { + common.Namespace Ids map[string]string `json:"ids,omitempty" tf:"computed"` } return common.DataResource(mwsCredentialsData{}, func(ctx context.Context, e any, c *common.DatabricksClient) error { diff --git a/mws/data_mws_network_connectivity_config.go b/mws/data_mws_network_connectivity_config.go index ba50160886..864a5c40cd 100644 --- a/mws/data_mws_network_connectivity_config.go +++ b/mws/data_mws_network_connectivity_config.go @@ -10,10 +10,12 @@ import ( func DataSourceMwsNetworkConnectivityConfig() common.Resource { type mwsNetworkConnectivityConfiguration struct { + common.Namespace settings.NetworkConnectivityConfiguration } type mwsNetworkConnectivityConfigurationParams struct { + common.Namespace Name string `json:"name"` } diff --git a/mws/data_mws_network_connectivity_configs.go b/mws/data_mws_network_connectivity_configs.go index 5fd4a09a70..b36a0a5c26 100644 --- a/mws/data_mws_network_connectivity_configs.go +++ b/mws/data_mws_network_connectivity_configs.go @@ -10,10 +10,12 @@ import ( func DataSourceMwsNetworkConnectivityConfigs() common.Resource { type mwsNetworkConnectivityConfiguration struct { + common.Namespace Names []string `json:"names" tf:"computed,optional"` } type mwsNetworkConnectivityConfigurationParams struct { + common.Namespace Names []string `json:"names" tf:"computed,optional"` Region string `json:"region" tf:"optional"` } diff --git a/mws/data_mws_workspaces.go b/mws/data_mws_workspaces.go index 4c2d48a9a4..82f6e0a6da 100755 --- a/mws/data_mws_workspaces.go +++ b/mws/data_mws_workspaces.go @@ -9,6 +9,7 @@ import ( func DataSourceMwsWorkspaces() common.Resource { type mwsWorkspacesData struct { + common.Namespace Ids map[string]int64 `json:"ids" tf:"computed"` } return common.DataResource(mwsWorkspacesData{}, func(ctx context.Context, e any, c *common.DatabricksClient) error { diff --git a/mws/mws.go b/mws/mws.go index 3df789fbe7..3a6818ac5b 100644 --- a/mws/mws.go +++ b/mws/mws.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/databricks/databricks-sdk-go/marshal" + "github.com/databricks/terraform-provider-databricks/common" "github.com/databricks/terraform-provider-databricks/internal/docs" ) @@ -73,6 +74,7 @@ type GcpNetworkInfo struct { // Network is the object that contains all the information for BYOVPC type Network struct { + common.Namespace AccountID string `json:"account_id" tf:"force_new"` NetworkID string `json:"network_id,omitempty" tf:"computed"` NetworkName string `json:"network_name" tf:"force_new"` @@ -98,6 +100,7 @@ type GcpVpcEndpointInfo struct { // VPCEndpoint is the object that contains all the information for registering an VPC endpoint type VPCEndpoint struct { + common.Namespace VPCEndpointID string `json:"vpc_endpoint_id,omitempty" tf:"computed"` AwsVPCEndpointID string `json:"aws_vpc_endpoint_id,omitempty"` AccountID string `json:"account_id,omitempty"` diff --git a/mws/resource_mws_customer_managed_keys.go b/mws/resource_mws_customer_managed_keys.go index 1163ef39c5..9b27dd2ad8 100644 --- a/mws/resource_mws_customer_managed_keys.go +++ b/mws/resource_mws_customer_managed_keys.go @@ -25,6 +25,7 @@ type GcpKeyInfo struct { // CustomerManagedKey contains key information and metadata for BYOK for E2 // You must specify either AwsKeyInfo for AWS or GcpKeyInfo for GCP, but not both type CustomerManagedKey struct { + common.Namespace 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"` @@ -33,6 +34,11 @@ type CustomerManagedKey struct { UseCases []string `json:"use_cases"` } +func (CustomerManagedKey) CustomizeSchema(s *common.CustomizableSchema) *common.CustomizableSchema { + common.NamespaceCustomizeSchema(s) + return s +} + // NewCustomerManagedKeysAPI creates CustomerManagedKeysAPI instance from provider meta func NewCustomerManagedKeysAPI(ctx context.Context, m any) CustomerManagedKeysAPI { return CustomerManagedKeysAPI{m.(*common.DatabricksClient), ctx} @@ -75,6 +81,9 @@ func ResourceMwsCustomerManagedKeys() common.Resource { s := common.StructToSchema(CustomerManagedKey{}, nil) p := common.NewPairSeparatedID("account_id", "customer_managed_key_id", "/") return common.Resource{ + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { var cmk CustomerManagedKey common.DataToStructPointer(d, s, &cmk) diff --git a/mws/resource_mws_log_delivery.go b/mws/resource_mws_log_delivery.go index 34514440fb..4b550d59b3 100644 --- a/mws/resource_mws_log_delivery.go +++ b/mws/resource_mws_log_delivery.go @@ -17,6 +17,7 @@ type LogDelivery struct { // LogDeliveryConfiguration describes log delivery type LogDeliveryConfiguration struct { + common.Namespace AccountID string `json:"account_id" tf:"force_new"` ConfigID string `json:"config_id,omitempty" tf:"computed,force_new"` CredentialsID string `json:"credentials_id" tf:"force_new"` @@ -75,10 +76,14 @@ func ResourceMwsLogDelivery() common.Resource { k, old, new string, d *schema.ResourceData) bool { return false } + common.NamespaceCustomizeSchemaMap(s) return s }) return common.Resource{ Schema: s, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { var ldc LogDeliveryConfiguration common.DataToStructPointer(d, s, &ldc) diff --git a/mws/resource_mws_ncc_binding.go b/mws/resource_mws_ncc_binding.go index 8550ea59a1..21c4b03d13 100644 --- a/mws/resource_mws_ncc_binding.go +++ b/mws/resource_mws_ncc_binding.go @@ -10,12 +10,13 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) +type NccBinding struct { + WorkspaceId int64 `json:"workspace_id" tf:"force_new"` + NccId string `json:"network_connectivity_config_id"` +} + func ResourceMwsNccBinding() common.Resource { - type binding struct { - WorkspaceId int64 `json:"workspace_id" tf:"force_new"` - NccId string `json:"network_connectivity_config_id"` - } - s := common.StructToSchema(binding{}, common.NoCustomize) + s := common.StructToSchema(NccBinding{}, nil) p := common.NewPairSeparatedID("workspace_id", "network_connectivity_config_id", "/") createOrUpdate := func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { acc, err := c.AccountClient() diff --git a/mws/resource_mws_workspaces.go b/mws/resource_mws_workspaces.go index 71f148f8b3..52a4ea71aa 100644 --- a/mws/resource_mws_workspaces.go +++ b/mws/resource_mws_workspaces.go @@ -80,6 +80,7 @@ type externalCustomerInfo struct { // Workspace is the object that contains all the information for deploying a workspace type Workspace struct { + common.Namespace AccountID string `json:"account_id"` WorkspaceName string `json:"workspace_name"` DeploymentName string `json:"deployment_name,omitempty"` @@ -381,6 +382,7 @@ func (s SensitiveString) String() string { // ephemeral entity to use with StructToData() type WorkspaceToken struct { + common.Namespace WorkspaceURL string `json:"workspace_url,omitempty"` Token *Token `json:"token,omitempty"` } @@ -560,6 +562,7 @@ func ResourceMwsWorkspaces() common.Resource { common.CustomizeSchemaPath(s, "gcp_managed_network_config", "gke_cluster_pod_ip_range").SetDeprecated(getGkeDeprecationMessage("gcp_managed_network_config.gke_cluster_pod_ip_range", docOptions)) common.CustomizeSchemaPath(s, "gcp_managed_network_config", "gke_cluster_service_ip_range").SetDeprecated(getGkeDeprecationMessage("gcp_managed_network_config.gke_cluster_service_ip_range", docOptions)) common.CustomizeSchemaPath(s, "compute_mode").SetValidateDiagFunc(validation.ToDiagFunc(validation.StringInSlice([]string{"SERVERLESS"}, false))) + common.NamespaceCustomizeSchemaMap(s) return s }) p := common.NewPairSeparatedID("account_id", "workspace_id", "/").Schema( @@ -693,7 +696,7 @@ func ResourceMwsWorkspaces() common.Resource { } } } - return nil + return common.NamespaceCustomizeDiff(d) }, Timeouts: &schema.ResourceTimeout{ Create: schema.DefaultTimeout(DefaultProvisionTimeout), diff --git a/permissions/resource_access_control_rule_set.go b/permissions/resource_access_control_rule_set.go index 7d0b2a5466..02df642cb9 100644 --- a/permissions/resource_access_control_rule_set.go +++ b/permissions/resource_access_control_rule_set.go @@ -24,7 +24,7 @@ func ResourceAccessControlRuleSet() common.Resource { return m }) - readFromWsOrAcc := func(ctx context.Context, c *common.DatabricksClient, getRuleSetReq iam.GetRuleSetRequest) (*iam.RuleSetResponse, error) { + readFromWsOrAcc := func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient, getRuleSetReq iam.GetRuleSetRequest) (*iam.RuleSetResponse, error) { if c.Config.AccountID != "" { accountClient, err := c.AccountClient() if err != nil { @@ -32,13 +32,13 @@ func ResourceAccessControlRuleSet() common.Resource { } return accountClient.AccessControl.GetRuleSet(ctx, getRuleSetReq) } - workspaceClient, err := c.WorkspaceClient() + workspaceClient, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return nil, err } return workspaceClient.AccountAccessControlProxy.GetRuleSet(ctx, getRuleSetReq) } - updateThroughWsOrAcc := func(ctx context.Context, c *common.DatabricksClient, updateRuleSetReq iam.UpdateRuleSetRequest) (*iam.RuleSetResponse, error) { + updateThroughWsOrAcc := func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient, updateRuleSetReq iam.UpdateRuleSetRequest) (*iam.RuleSetResponse, error) { if c.Config.AccountID != "" { accountClient, err := c.AccountClient() if err != nil { @@ -46,14 +46,14 @@ func ResourceAccessControlRuleSet() common.Resource { } return accountClient.AccessControl.UpdateRuleSet(ctx, updateRuleSetReq) } - workspaceClient, err := c.WorkspaceClient() + workspaceClient, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return nil, err } return workspaceClient.AccountAccessControlProxy.UpdateRuleSet(ctx, updateRuleSetReq) } - fetchLatestEtag := func(ctx context.Context, c *common.DatabricksClient, name string) (string, error) { - ruleSetGetRes, err := readFromWsOrAcc(ctx, c, iam.GetRuleSetRequest{ + fetchLatestEtag := func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient, name string) (string, error) { + ruleSetGetRes, err := readFromWsOrAcc(ctx, d, c, iam.GetRuleSetRequest{ Name: name, Etag: "", }) @@ -62,22 +62,22 @@ func ResourceAccessControlRuleSet() common.Resource { } return ruleSetGetRes.Etag, nil } - updateRuleSet := func(ctx context.Context, c *common.DatabricksClient, + updateRuleSet := func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient, ruleSetUpdateReq iam.UpdateRuleSetRequest) (*iam.RuleSetResponse, error) { - latestEtag, err := fetchLatestEtag(ctx, c, ruleSetUpdateReq.Name) + latestEtag, err := fetchLatestEtag(ctx, d, c, ruleSetUpdateReq.Name) if err != nil { return nil, err } ruleSetUpdateReq.RuleSet.Etag = latestEtag - ruleSetUpdateRes, err := updateThroughWsOrAcc(ctx, c, ruleSetUpdateReq) + ruleSetUpdateRes, err := updateThroughWsOrAcc(ctx, d, c, ruleSetUpdateReq) if err != nil { return nil, err } return ruleSetUpdateRes, nil } - handleConflictAndUpdate := func(ctx context.Context, c *common.DatabricksClient, + handleConflictAndUpdate := func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient, ruleSetUpdateReq iam.UpdateRuleSetRequest) (*iam.RuleSetResponse, error) { - ruleSetUpdateRes, err := updateThroughWsOrAcc(ctx, c, ruleSetUpdateReq) + ruleSetUpdateRes, err := updateThroughWsOrAcc(ctx, d, c, ruleSetUpdateReq) if err != nil { var aerr *apierr.APIError if !errors.As(err, &aerr) { @@ -86,7 +86,7 @@ func ResourceAccessControlRuleSet() common.Resource { if aerr.StatusCode == http.StatusConflict { if aerr.ErrorCode == "RESOURCE_CONFLICT" { // we need to get and update - etag, err := updateRuleSet(ctx, c, ruleSetUpdateReq) + etag, err := updateRuleSet(ctx, d, c, ruleSetUpdateReq) return etag, err } } @@ -103,7 +103,7 @@ func ResourceAccessControlRuleSet() common.Resource { var ruleSetUpdateReq iam.UpdateRuleSetRequest common.DataToStructPointer(d, s, &ruleSetUpdateReq.RuleSet) ruleSetUpdateReq.Name = ruleSetUpdateReq.RuleSet.Name - response, err := updateRuleSet(ctx, c, ruleSetUpdateReq) + response, err := updateRuleSet(ctx, d, c, ruleSetUpdateReq) if err != nil { return err } @@ -117,7 +117,7 @@ func ResourceAccessControlRuleSet() common.Resource { return nil }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - data, err := readFromWsOrAcc(ctx, c, iam.GetRuleSetRequest{ + data, err := readFromWsOrAcc(ctx, d, c, iam.GetRuleSetRequest{ Name: d.Id(), Etag: "", }) @@ -130,7 +130,7 @@ func ResourceAccessControlRuleSet() common.Resource { }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { // Fetch the latest Etag - latestEtag, err := fetchLatestEtag(ctx, c, d.Id()) + latestEtag, err := fetchLatestEtag(ctx, d, c, d.Id()) if err != nil { return err } @@ -139,7 +139,7 @@ func ResourceAccessControlRuleSet() common.Resource { common.DataToStructPointer(d, s, &ruleSetUpdateReq.RuleSet) ruleSetUpdateReq.Name = ruleSetUpdateReq.RuleSet.Name ruleSetUpdateReq.RuleSet.Etag = latestEtag - response, err := handleConflictAndUpdate(ctx, c, ruleSetUpdateReq) + response, err := handleConflictAndUpdate(ctx, d, c, ruleSetUpdateReq) if err != nil { return err } @@ -154,13 +154,13 @@ func ResourceAccessControlRuleSet() common.Resource { }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { // Fetch the latest Etag - latestEtag, err := fetchLatestEtag(ctx, c, d.Id()) + latestEtag, err := fetchLatestEtag(ctx, d, c, d.Id()) if err != nil { return err } // we remove all grant rules. Account admins will still be able to update rule set - _, err = handleConflictAndUpdate(ctx, c, iam.UpdateRuleSetRequest{ + _, err = handleConflictAndUpdate(ctx, d, c, iam.UpdateRuleSetRequest{ Name: d.Id(), RuleSet: iam.RuleSetUpdateRequest{ Name: d.Id(), diff --git a/permissions/resource_permissions.go b/permissions/resource_permissions.go index b132ebf56f..591176d173 100644 --- a/permissions/resource_permissions.go +++ b/permissions/resource_permissions.go @@ -158,8 +158,13 @@ func (a PermissionsAPI) Read(objectID string, mapping resourcePermissions, exist } // ResourcePermissions definition +type PermissionsEntity struct { + entity.PermissionsEntity + common.Namespace +} + func ResourcePermissions() common.Resource { - s := common.StructToSchema(entity.PermissionsEntity{}, func(s map[string]*schema.Schema) map[string]*schema.Schema { + s := common.StructToSchema(PermissionsEntity{}, func(s map[string]*schema.Schema) map[string]*schema.Schema { for _, mapping := range allResourcePermissions() { s[mapping.field] = &schema.Schema{ ForceNew: true, @@ -174,11 +179,15 @@ func ResourcePermissions() common.Resource { } } s["access_control"].MinItems = 1 + common.NamespaceCustomizeSchemaMap(s) return s }) return common.Resource{ Schema: s, CustomizeDiff: func(ctx context.Context, diff *schema.ResourceDiff) error { + if err := common.NamespaceCustomizeDiff(diff); err != nil { + return err + } mapping, _, err := getResourcePermissionsFromState(diff) if err != nil { // This preserves current behavior but is likely only exercised in tests where @@ -238,7 +247,7 @@ func ResourcePermissions() common.Resource { Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { var entity entity.PermissionsEntity common.DataToStructPointer(d, s, &entity) - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } diff --git a/pipelines/data_pipelines.go b/pipelines/data_pipelines.go index b4c6451ecb..507a115bd0 100755 --- a/pipelines/data_pipelines.go +++ b/pipelines/data_pipelines.go @@ -12,6 +12,7 @@ import ( func DataSourcePipelines() common.Resource { type pipelinesData struct { + common.Namespace PipelineNameContains string `json:"pipeline_name,omitempty"` Ids []string `json:"ids,omitempty" tf:"computed,slice_set"` } diff --git a/pipelines/resource_pipeline.go b/pipelines/resource_pipeline.go index ff568e66e6..12f8f28381 100644 --- a/pipelines/resource_pipeline.go +++ b/pipelines/resource_pipeline.go @@ -160,6 +160,7 @@ func (updatePipelineRequestStruct) CustomizeSchema(s *common.CustomizableSchema) type Pipeline struct { pipelines.PipelineSpec + common.Namespace AllowDuplicateNames bool `json:"allow_duplicate_names,omitempty"` Cause string `json:"cause,omitempty"` ClusterId string `json:"cluster_id,omitempty"` @@ -195,6 +196,7 @@ func suppressStorageDiff(k, old, new string, d *schema.ResourceData) bool { } func (Pipeline) CustomizeSchema(s *common.CustomizableSchema) *common.CustomizableSchema { + common.NamespaceCustomizeSchema(s) // ForceNew fields s.SchemaPath("storage").SetForceNew() @@ -281,15 +283,18 @@ var pipelineSchema = common.StructToSchema(Pipeline{}, nil) func ResourcePipeline() common.Resource { return common.Resource{ Schema: pipelineSchema, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } return Create(w, ctx, d, d.Timeout(schema.TimeoutCreate)) }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -317,7 +322,7 @@ func ResourcePipeline() common.Resource { return common.StructToData(p, pipelineSchema, d) }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -325,7 +330,7 @@ func ResourcePipeline() common.Resource { }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } diff --git a/policies/data_cluster_policy.go b/policies/data_cluster_policy.go index 1389f8d8b7..e772062a9f 100644 --- a/policies/data_cluster_policy.go +++ b/policies/data_cluster_policy.go @@ -12,6 +12,7 @@ import ( // DataSourceClusterPolicy returns information about cluster policy specified by name func DataSourceClusterPolicy() common.Resource { resource := common.WorkspaceData(func(ctx context.Context, data *struct { + common.Namespace Id string `json:"id,omitempty" tf:"computed"` Name string `json:"name,omitempty" tf:"computed"` Definition string `json:"definition,omitempty" tf:"computed"` diff --git a/policies/resource_cluster_policy.go b/policies/resource_cluster_policy.go index ab55443736..45ad1d99cf 100644 --- a/policies/resource_cluster_policy.go +++ b/policies/resource_cluster_policy.go @@ -57,7 +57,7 @@ func ResourceClusterPolicy() common.Resource { }, }, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -94,7 +94,7 @@ func ResourceClusterPolicy() common.Resource { return nil }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -105,7 +105,7 @@ func ResourceClusterPolicy() common.Resource { return common.StructToData(resp, rcpSchema, d) }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -120,7 +120,7 @@ func ResourceClusterPolicy() common.Resource { return w.ClusterPolicies.Edit(ctx, request) }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } diff --git a/pools/data_instance_pool.go b/pools/data_instance_pool.go index 1c733246d0..72fa385473 100644 --- a/pools/data_instance_pool.go +++ b/pools/data_instance_pool.go @@ -25,6 +25,7 @@ func getPool(poolsAPI InstancePoolsAPI, name string) (*InstancePoolAndStats, err // DataSourceInstancePool returns information about instance pool specified by name func DataSourceInstancePool() common.Resource { type poolDetails struct { + common.Namespace Name string `json:"name"` Attributes *InstancePoolAndStats `json:"pool_info,omitempty" tf:"computed"` } diff --git a/pools/resource_instance_pool.go b/pools/resource_instance_pool.go index b748d3cb94..ea26145a06 100644 --- a/pools/resource_instance_pool.go +++ b/pools/resource_instance_pool.go @@ -73,6 +73,7 @@ type AwsInstancePoolFleetAttributes struct { // InstancePool describes the instance pool object on Databricks type InstancePool struct { + common.Namespace InstancePoolID string `json:"instance_pool_id,omitempty" tf:"computed"` InstancePoolName string `json:"instance_pool_name"` MinIdleInstances int32 `json:"min_idle_instances,omitempty"` @@ -246,10 +247,14 @@ func ResourceInstancePool() common.Resource { v.ForceNew = true } + common.NamespaceCustomizeSchemaMap(s) return s }) return common.Resource{ Schema: s, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { var ip InstancePool common.DataToStructPointer(d, s, &ip) diff --git a/repos/resource_git_credential.go b/repos/resource_git_credential.go index ee4cb90458..1021de335a 100644 --- a/repos/resource_git_credential.go +++ b/repos/resource_git_credential.go @@ -37,7 +37,7 @@ func ResourceGitCredential() common.Resource { Schema: s, SchemaVersion: 1, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -71,7 +71,7 @@ func ResourceGitCredential() common.Resource { return nil }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -96,7 +96,7 @@ func ResourceGitCredential() common.Resource { return err } req.CredentialId = cred_id - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -109,7 +109,7 @@ func ResourceGitCredential() common.Resource { return w.GitCredentials.Update(ctx, req) }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } diff --git a/repos/resource_repo.go b/repos/resource_repo.go index ab00947da4..879bd98dfc 100644 --- a/repos/resource_repo.go +++ b/repos/resource_repo.go @@ -31,6 +31,7 @@ type ReposSparseCheckout struct { // ReposInformation provides information about given repository type ReposInformation struct { + common.Namespace ID int64 `json:"id"` Url string `json:"url" tf:"force_new"` Provider string `json:"provider,omitempty" tf:"computed,alias:git_provider,force_new"` @@ -183,12 +184,16 @@ func ResourceRepo() common.Resource { } delete(s, "id") + common.NamespaceCustomizeSchemaMap(s) return s }) return common.Resource{ Schema: s, SchemaVersion: 1, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { reposAPI := NewReposAPI(ctx, c) var repo ReposInformation diff --git a/scim/data_current_user.go b/scim/data_current_user.go index 7a6066c1bd..580cf95a7f 100644 --- a/scim/data_current_user.go +++ b/scim/data_current_user.go @@ -46,7 +46,7 @@ func DataSourceCurrentUser() common.Resource { }, }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } diff --git a/scim/data_group.go b/scim/data_group.go index b0512ef840..0ddea49db1 100644 --- a/scim/data_group.go +++ b/scim/data_group.go @@ -14,6 +14,7 @@ import ( // DataSourceGroup returns information about group specified by display name func DataSourceGroup() common.Resource { type entity struct { + common.Namespace DisplayName string `json:"display_name"` Recursive bool `json:"recursive,omitempty"` Members []string `json:"members,omitempty" tf:"slice_set,computed"` diff --git a/scim/data_service_principal.go b/scim/data_service_principal.go index 87b4f3a83c..89675b7bcc 100644 --- a/scim/data_service_principal.go +++ b/scim/data_service_principal.go @@ -11,6 +11,7 @@ import ( // DataSourceServicePrincipal returns information about the spn specified by the application_id, id, display_name, or scim_id func DataSourceServicePrincipal() common.Resource { type spnData struct { + common.Namespace ApplicationID string `json:"application_id,omitempty" tf:"computed"` DisplayName string `json:"display_name,omitempty" tf:"computed"` SpID string `json:"sp_id,omitempty" tf:"computed"` diff --git a/scim/data_service_principals.go b/scim/data_service_principals.go index f01d56795b..81e3e5bb63 100644 --- a/scim/data_service_principals.go +++ b/scim/data_service_principals.go @@ -11,6 +11,7 @@ import ( // DataSourceServicePrincipals searches for service principals based on display_name func DataSourceServicePrincipals() common.Resource { type spnsData struct { + common.Namespace DisplayNameContains string `json:"display_name_contains,omitempty" tf:"computed"` ApplicationIDs []string `json:"application_ids,omitempty" tf:"computed,slice_set"` } diff --git a/scim/resource_entitlement.go b/scim/resource_entitlement.go index 892b0a5601..c073f6d8ca 100644 --- a/scim/resource_entitlement.go +++ b/scim/resource_entitlement.go @@ -9,24 +9,31 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) +type EntitlementEntity struct { + common.Namespace + GroupId string `json:"group_id,omitempty" tf:"force_new"` + UserId string `json:"user_id,omitempty" tf:"force_new"` + SpnId string `json:"service_principal_id,omitempty" tf:"force_new"` +} + // ResourceGroup manages user groups func ResourceEntitlements() common.Resource { - type entity struct { - GroupId string `json:"group_id,omitempty" tf:"force_new"` - UserId string `json:"user_id,omitempty" tf:"force_new"` - SpnId string `json:"service_principal_id,omitempty" tf:"force_new"` - } - entitlementSchema := common.StructToSchema(entity{}, + entitlementSchema := common.StructToSchema(EntitlementEntity{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { addEntitlementsToSchema(m) alof := []string{"group_id", "user_id", "service_principal_id"} for _, field := range alof { m[field].AtLeastOneOf = alof } + common.NamespaceCustomizeSchemaMap(m) return m }) addEntitlementsToSchema(entitlementSchema) return common.Resource{ + Schema: entitlementSchema, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { if c.Config.IsAccountClient() { return fmt.Errorf("entitlements can only be managed with a provider configured at the workspace-level") @@ -77,7 +84,6 @@ func ResourceEntitlements() common.Resource { Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { return patchEntitlements(ctx, d, c, "remove") }, - Schema: entitlementSchema, } } diff --git a/scim/resource_group.go b/scim/resource_group.go index 9b59855ddf..758246ac2e 100644 --- a/scim/resource_group.go +++ b/scim/resource_group.go @@ -10,14 +10,16 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) +type GroupEntity struct { + common.Namespace + DisplayName string `json:"display_name"` + ExternalID string `json:"external_id,omitempty" tf:"force_new,suppress_diff"` + URL string `json:"url,omitempty" tf:"computed"` +} + // ResourceGroup manages user groups func ResourceGroup() common.Resource { - type entity struct { - DisplayName string `json:"display_name"` - ExternalID string `json:"external_id,omitempty" tf:"force_new,suppress_diff"` - URL string `json:"url,omitempty" tf:"computed"` - } - groupSchema := common.StructToSchema(entity{}, + groupSchema := common.StructToSchema(GroupEntity{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { addEntitlementsToSchema(m) // https://github.com/databricks/terraform-provider-databricks/issues/1089 @@ -32,10 +34,15 @@ func ResourceGroup() common.Resource { Optional: true, Computed: true, } + common.NamespaceCustomizeSchemaMap(m) return m }) addEntitlementsToSchema(groupSchema) return common.Resource{ + Schema: groupSchema, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { g := Group{ DisplayName: d.Get("display_name").(string), @@ -73,7 +80,6 @@ func ResourceGroup() common.Resource { Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { return NewGroupsAPI(ctx, c).Delete(d.Id()) }, - Schema: groupSchema, } } diff --git a/scim/resource_service_principal.go b/scim/resource_service_principal.go index 40f2d82914..bf0219d788 100644 --- a/scim/resource_service_principal.go +++ b/scim/resource_service_principal.go @@ -14,6 +14,14 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) +type ServicePrincipalEntity struct { + common.Namespace + ApplicationID string `json:"application_id,omitempty" tf:"computed,force_new"` + DisplayName string `json:"display_name,omitempty" tf:"computed"` + Active bool `json:"active,omitempty"` + ExternalID string `json:"external_id,omitempty" tf:"suppress_diff"` +} + // NewServicePrincipalsAPI creates ServicePrincipalsAPI instance from provider meta func NewServicePrincipalsAPI(ctx context.Context, m any) ServicePrincipalsAPI { return ServicePrincipalsAPI{m.(*common.DatabricksClient), ctx} @@ -96,13 +104,7 @@ func (a ServicePrincipalsAPI) Delete(servicePrincipalID string) error { // ResourceServicePrincipal manages service principals within workspace func ResourceServicePrincipal() common.Resource { - type entity struct { - ApplicationID string `json:"application_id,omitempty" tf:"computed,force_new"` - DisplayName string `json:"display_name,omitempty" tf:"computed"` - Active bool `json:"active,omitempty"` - ExternalID string `json:"external_id,omitempty" tf:"suppress_diff"` - } - servicePrincipalSchema := common.StructToSchema(entity{}, + servicePrincipalSchema := common.StructToSchema(ServicePrincipalEntity{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { addEntitlementsToSchema(m) m["active"].Default = true @@ -139,10 +141,11 @@ func ResourceServicePrincipal() common.Resource { } m["application_id"].AtLeastOneOf = []string{"application_id", "display_name"} m["display_name"].AtLeastOneOf = []string{"application_id", "display_name"} + common.NamespaceCustomizeSchemaMap(m) return m }) spFromData := func(d *schema.ResourceData) User { - var u entity + var u ServicePrincipalEntity common.DataToStructPointer(d, servicePrincipalSchema, &u) return User{ ApplicationID: u.ApplicationID, @@ -154,6 +157,9 @@ func ResourceServicePrincipal() common.Resource { } return common.Resource{ Schema: servicePrincipalSchema, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { sp := spFromData(d) spAPI := NewServicePrincipalsAPI(ctx, c) diff --git a/scim/resource_user.go b/scim/resource_user.go index e46533f7d9..16b490afd1 100644 --- a/scim/resource_user.go +++ b/scim/resource_user.go @@ -31,15 +31,17 @@ func setCommonUserFields(d *schema.ResourceData, user User, username string) { d.Set("repos", fmt.Sprintf("/Repos/%s", username)) } +type UserEntity struct { + common.Namespace + UserName string `json:"user_name" tf:"force_new"` + DisplayName string `json:"display_name,omitempty" tf:"computed"` + Active bool `json:"active,omitempty"` + ExternalID string `json:"external_id,omitempty" tf:"suppress_diff"` +} + // ResourceUser manages users within workspace func ResourceUser() common.Resource { - type entity struct { - UserName string `json:"user_name" tf:"force_new"` - DisplayName string `json:"display_name,omitempty" tf:"computed"` - Active bool `json:"active,omitempty"` - ExternalID string `json:"external_id,omitempty" tf:"suppress_diff"` - } - userSchema := common.StructToSchema(entity{}, + userSchema := common.StructToSchema(UserEntity{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { addEntitlementsToSchema(m) m["user_name"].DiffSuppressFunc = common.EqualFoldDiffSuppress @@ -76,10 +78,11 @@ func ResourceUser() common.Resource { Optional: true, Computed: true, } + common.NamespaceCustomizeSchemaMap(m) return m }) scimUserFromData := func(d *schema.ResourceData) (user User, err error) { - var u entity + var u UserEntity common.DataToStructPointer(d, userSchema, &u) return User{ UserName: u.UserName, @@ -91,6 +94,9 @@ func ResourceUser() common.Resource { } return common.Resource{ Schema: userSchema, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { u, err := scimUserFromData(d) if err != nil { diff --git a/secrets/resource_secret.go b/secrets/resource_secret.go index e4507c2692..a1de1ecc1b 100644 --- a/secrets/resource_secret.go +++ b/secrets/resource_secret.go @@ -70,7 +70,7 @@ func ResourceSecret() common.Resource { return common.Resource{ Schema: s, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -88,7 +88,7 @@ func ResourceSecret() common.Resource { if err != nil { return err } - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -104,7 +104,7 @@ func ResourceSecret() common.Resource { if err != nil { return err } - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } diff --git a/secrets/resource_secret_acl.go b/secrets/resource_secret_acl.go index e271c651d4..4c89d6d75e 100644 --- a/secrets/resource_secret_acl.go +++ b/secrets/resource_secret_acl.go @@ -41,7 +41,7 @@ func ResourceSecretACL() common.Resource { return true }, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -58,7 +58,7 @@ func ResourceSecretACL() common.Resource { if err != nil { return err } - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -76,7 +76,7 @@ func ResourceSecretACL() common.Resource { if err != nil { return err } - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } diff --git a/secrets/resource_secret_scope.go b/secrets/resource_secret_scope.go index ebb19f9efa..0c3ae778aa 100644 --- a/secrets/resource_secret_scope.go +++ b/secrets/resource_secret_scope.go @@ -15,9 +15,13 @@ import ( ) // SecretScope is a struct that encapsulates the secret scope -type SecretScope workspace.CreateScope +type SecretScope struct { + workspace.CreateScope + common.Namespace +} func (s SecretScope) CustomizeSchema(m *common.CustomizableSchema) *common.CustomizableSchema { + common.NamespaceCustomizeSchema(m) m.SchemaPath("name").SetValidateFunc(validScope) m.SchemaPath("backend_type").SetComputed() return m @@ -67,8 +71,11 @@ func ResourceSecretScope() common.Resource { return common.Resource{ Schema: s, SchemaVersion: 2, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -79,14 +86,14 @@ func ResourceSecretScope() common.Resource { } else { scope.ScopeBackendType = "DATABRICKS" } - if err := w.Secrets.CreateScope(ctx, workspace.CreateScope(scope)); err != nil { + if err := w.Secrets.CreateScope(ctx, workspace.CreateScope(scope.CreateScope)); err != nil { return err } d.SetId(scope.Scope) return nil }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -97,7 +104,7 @@ func ResourceSecretScope() common.Resource { return common.StructToData(scope, s, d) }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } diff --git a/serving/resource_model_serving.go b/serving/resource_model_serving.go index c9bbfa3f0b..b74ce139ef 100644 --- a/serving/resource_model_serving.go +++ b/serving/resource_model_serving.go @@ -131,9 +131,14 @@ func updateAiGateway(ctx context.Context, w *databricks.WorkspaceClient, name st return err } +type CreateServingEndpoint struct { + serving.CreateServingEndpoint + common.Namespace +} + func ResourceModelServing() common.Resource { s := common.StructToSchema( - serving.CreateServingEndpoint{}, + CreateServingEndpoint{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { // Use the newer CustomizeSchemaPath approach for better maintainability common.CustomizeSchemaPath(m, "name").SetForceNew() @@ -182,12 +187,13 @@ func ResourceModelServing() common.Resource { Computed: true, Type: schema.TypeString, } + common.NamespaceCustomizeSchemaMap(m) return m }) return common.Resource{ Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -210,7 +216,7 @@ func ResourceModelServing() common.Resource { return nil }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) var sOrig serving.ServingEndpointDetailed common.DataToStructPointer(d, s, &sOrig) if err != nil { @@ -242,7 +248,7 @@ func ResourceModelServing() common.Resource { return nil }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -266,7 +272,7 @@ func ResourceModelServing() common.Resource { return nil }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -279,5 +285,8 @@ func ResourceModelServing() common.Resource { Create: schema.DefaultTimeout(DefaultProvisionTimeout), Update: schema.DefaultTimeout(DefaultProvisionTimeout), }, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, } } diff --git a/serving/resource_model_serving_provisioned_throughput.go b/serving/resource_model_serving_provisioned_throughput.go index bd0a933a04..c0c3605560 100644 --- a/serving/resource_model_serving_provisioned_throughput.go +++ b/serving/resource_model_serving_provisioned_throughput.go @@ -39,7 +39,7 @@ func ResourceModelServingProvisionedThroughput() common.Resource { return common.Resource{ Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -62,7 +62,7 @@ func ResourceModelServingProvisionedThroughput() common.Resource { return nil }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) var sOrig serving.ServingEndpointDetailed common.DataToStructPointer(d, s, &sOrig) if err != nil { @@ -80,7 +80,7 @@ func ResourceModelServingProvisionedThroughput() common.Resource { return nil }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -113,7 +113,7 @@ func ResourceModelServingProvisionedThroughput() common.Resource { return nil }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } diff --git a/settings/resource_notification_destination.go b/settings/resource_notification_destination.go index a610c4c2d4..0d51d493c5 100644 --- a/settings/resource_notification_destination.go +++ b/settings/resource_notification_destination.go @@ -108,9 +108,11 @@ func Delete(ctx context.Context, d *schema.ResourceData, w *databricks.Workspace type NDStruct struct { settings.NotificationDestination + common.Namespace } func (NDStruct) CustomizeSchema(s *common.CustomizableSchema) *common.CustomizableSchema { + common.NamespaceCustomizeSchema(s) // Required fields s.SchemaPath("display_name").SetRequired() @@ -166,30 +168,33 @@ var ndSchema = common.StructToSchema(NDStruct{}, nil) func ResourceNotificationDestination() common.Resource { return common.Resource{ Schema: ndSchema, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } return Create(ctx, d, w) }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } return Read(ctx, d, w) }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } return Update(ctx, d, w) }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } diff --git a/sharing/data_share.go b/sharing/data_share.go index 1e15176112..2645cae140 100644 --- a/sharing/data_share.go +++ b/sharing/data_share.go @@ -9,6 +9,7 @@ import ( ) type ShareDetail struct { + common.Namespace Name string `json:"name,omitempty" tf:"computed"` Objects []sharing.SharedDataObject `json:"objects,omitempty" tf:"computed,slice_set,alias:object"` CreatedAt int64 `json:"created_at,omitempty" tf:"computed"` diff --git a/sharing/data_shares.go b/sharing/data_shares.go index b09d812725..33edbb2c76 100644 --- a/sharing/data_shares.go +++ b/sharing/data_shares.go @@ -10,6 +10,7 @@ import ( func DataSourceShares() common.Resource { return common.WorkspaceData(func(ctx context.Context, data *struct { + common.Namespace Shares []string `json:"shares,omitempty" tf:"computed,slice_set"` }, w *databricks.WorkspaceClient) error { diff --git a/sharing/data_shares_test.go b/sharing/data_shares_test.go index 8afddc0b33..7848718eb6 100644 --- a/sharing/data_shares_test.go +++ b/sharing/data_shares_test.go @@ -16,7 +16,7 @@ func TestSharesData(t *testing.T) { Response: Shares{ Shares: []ShareInfo{ { - sharing.ShareInfo{ + ShareInfo: sharing.ShareInfo{ Name: "a", Objects: []sharing.SharedDataObject{ { diff --git a/sharing/resource_provider.go b/sharing/resource_provider.go index e40ba08c8e..d284483355 100644 --- a/sharing/resource_provider.go +++ b/sharing/resource_provider.go @@ -18,6 +18,7 @@ func NewProvidersAPI(ctx context.Context, m interface{}) ProvidersAPI { } type ProviderInfo struct { + common.Namespace Name string `json:"name" tf:"force_new"` Comment string `json:"comment,omitempty"` AuthenticationType string `json:"authentication_type"` @@ -53,6 +54,7 @@ func (a ProvidersAPI) updateProvider(ci *ProviderInfo) error { func ResourceProvider() common.Resource { providerSchema := common.StructToSchema(ProviderInfo{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { m["authentication_type"].ValidateFunc = validation.StringInSlice([]string{"TOKEN"}, false) + common.NamespaceCustomizeSchemaMap(m) return m }) @@ -63,6 +65,9 @@ func ResourceProvider() common.Resource { } return common.Resource{ Schema: providerSchema, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { var ri ProviderInfo common.DataToStructPointer(d, providerSchema, &ri) diff --git a/sharing/resource_recipient.go b/sharing/resource_recipient.go index ce5232e53b..9a1399c51a 100644 --- a/sharing/resource_recipient.go +++ b/sharing/resource_recipient.go @@ -11,6 +11,11 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) +type RecipientInfo struct { + sharing.RecipientInfo + common.Namespace +} + func recepientPropertiesSuppressDiff(k, old, new string, d *schema.ResourceData) bool { isPossiblySetAutomatically := k == "properties_kvpairs.0.properties.%" && old == "1" && new == "0" isAutoGeneratedName := strings.HasPrefix(k, "properties_kvpairs.0.properties.databricks.") && new == "" @@ -22,7 +27,7 @@ func recepientPropertiesSuppressDiff(k, old, new string, d *schema.ResourceData) } func ResourceRecipient() common.Resource { - recipientSchema := common.StructToSchema(sharing.RecipientInfo{}, func(s map[string]*schema.Schema) map[string]*schema.Schema { + recipientSchema := common.StructToSchema(RecipientInfo{}, func(s map[string]*schema.Schema) map[string]*schema.Schema { common.CustomizeSchemaPath(s, "authentication_type").SetForceNew().SetRequired().SetValidateFunc( validation.StringInSlice([]string{"TOKEN", "DATABRICKS"}, false)) common.CustomizeSchemaPath(s, "sharing_code").SetSuppressDiff().SetForceNew().SetSensitive() @@ -42,13 +47,13 @@ func ResourceRecipient() common.Resource { for _, path := range []string{"id", "created_at", "created_by", "activation_url", "expiration_time", "updated_at", "updated_by"} { common.CustomizeSchemaPath(s, "tokens", path).SetReadOnly() } - + common.NamespaceCustomizeSchemaMap(s) return s }) return common.Resource{ Schema: recipientSchema, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -62,7 +67,7 @@ func ResourceRecipient() common.Resource { return nil }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -81,7 +86,7 @@ func ResourceRecipient() common.Resource { return common.StructToData(ri, recipientSchema, d) }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -122,11 +127,14 @@ func ResourceRecipient() common.Resource { return nil }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } return w.Recipients.DeleteByName(ctx, d.Id()) }, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, } } diff --git a/sharing/resource_share.go b/sharing/resource_share.go index d079190a56..d4f3a7301d 100644 --- a/sharing/resource_share.go +++ b/sharing/resource_share.go @@ -12,9 +12,11 @@ import ( type ShareInfo struct { sharing.ShareInfo + common.Namespace } func (ShareInfo) CustomizeSchema(s *common.CustomizableSchema) *common.CustomizableSchema { + common.NamespaceCustomizeSchema(s) s.SchemaPath("name").SetRequired() s.SchemaPath("name").SetForceNew() s.SchemaPath("name").SetCustomSuppressDiff(common.EqualFoldDiffSuppress) @@ -154,8 +156,11 @@ func ResourceShare() common.Resource { shareSchema := common.StructToSchema(ShareInfo{}, nil) return common.Resource{ Schema: shareSchema, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -184,7 +189,7 @@ func ResourceShare() common.Resource { return nil }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - client, err := c.WorkspaceClient() + client, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -193,7 +198,7 @@ func ResourceShare() common.Resource { Name: d.Id(), IncludeSharedData: true, }) - si := ShareInfo{*shareInfo} + si := ShareInfo{ShareInfo: *shareInfo} si.sortSharesByName() si.suppressCDFEnabledDiff() if err != nil { @@ -203,7 +208,7 @@ func ResourceShare() common.Resource { return common.StructToData(si, shareSchema, d) }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - client, err := c.WorkspaceClient() + client, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -216,7 +221,7 @@ func ResourceShare() common.Resource { return err } - beforeSi := ShareInfo{*si} + beforeSi := ShareInfo{ShareInfo: *si} beforeSi.sortSharesByName() beforeSi.suppressCDFEnabledDiff() var afterSi ShareInfo @@ -263,7 +268,7 @@ func ResourceShare() common.Resource { return nil }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } diff --git a/sharing/resource_share_test.go b/sharing/resource_share_test.go index c4f6b9b409..6a060a0857 100644 --- a/sharing/resource_share_test.go +++ b/sharing/resource_share_test.go @@ -350,7 +350,7 @@ func TestUpdateShare(t *testing.T) { Method: "GET", Resource: "/api/2.1/unity-catalog/shares/abc?include_shared_data=true", Response: ShareInfo{ - sharing.ShareInfo{ + ShareInfo: sharing.ShareInfo{ Name: "abc", Owner: "admin", Comment: "cba", @@ -408,7 +408,7 @@ func TestUpdateShareRollback(t *testing.T) { Method: "GET", Resource: "/api/2.1/unity-catalog/shares/abc?include_shared_data=true", Response: ShareInfo{ - sharing.ShareInfo{ + ShareInfo: sharing.ShareInfo{ Name: "abc", Objects: []sharing.SharedDataObject{ { @@ -486,7 +486,7 @@ func TestUpdateShareRollback(t *testing.T) { Method: "GET", Resource: "/api/2.1/unity-catalog/shares/abc?include_shared_data=true", Response: ShareInfo{ - sharing.ShareInfo{ + ShareInfo: sharing.ShareInfo{ Name: "abc", Comment: "cba", Objects: []sharing.SharedDataObject{ @@ -546,7 +546,7 @@ func TestUpdateShare_NoChanges(t *testing.T) { Method: "GET", Resource: "/api/2.1/unity-catalog/shares/abc?include_shared_data=true", Response: ShareInfo{ - sharing.ShareInfo{ + ShareInfo: sharing.ShareInfo{ Name: "abc", Objects: []sharing.SharedDataObject{ { @@ -566,7 +566,7 @@ func TestUpdateShare_NoChanges(t *testing.T) { Method: "GET", Resource: "/api/2.1/unity-catalog/shares/abc?include_shared_data=true", Response: ShareInfo{ - sharing.ShareInfo{ + ShareInfo: sharing.ShareInfo{ Name: "abc", Objects: []sharing.SharedDataObject{ { @@ -607,7 +607,7 @@ func TestCreateShare_ThrowError(t *testing.T) { Method: "POST", Resource: "/api/2.1/unity-catalog/shares", ExpectedRequest: ShareInfo{ - sharing.ShareInfo{ + ShareInfo: sharing.ShareInfo{ Name: "a", }, }, @@ -645,12 +645,12 @@ func TestCreateShareButPatchFails(t *testing.T) { Method: "POST", Resource: "/api/2.1/unity-catalog/shares", ExpectedRequest: ShareInfo{ - sharing.ShareInfo{ + ShareInfo: sharing.ShareInfo{ Name: "a", }, }, Response: ShareInfo{ - sharing.ShareInfo{ + ShareInfo: sharing.ShareInfo{ Name: "a", }, }, @@ -717,7 +717,7 @@ func TestUpdateShareComplexDiff(t *testing.T) { Method: "GET", Resource: "/api/2.1/unity-catalog/shares/abc?include_shared_data=true", Response: ShareInfo{ - sharing.ShareInfo{ + ShareInfo: sharing.ShareInfo{ Name: "abc", Objects: []sharing.SharedDataObject{ { @@ -752,7 +752,7 @@ func TestUpdateShareComplexDiff(t *testing.T) { Method: "GET", Resource: "/api/2.1/unity-catalog/shares/abc?include_shared_data=true", Response: ShareInfo{ - sharing.ShareInfo{ + ShareInfo: sharing.ShareInfo{ Name: "abc", Objects: []sharing.SharedDataObject{ { diff --git a/sql/data_sql_warehouse.go b/sql/data_sql_warehouse.go index 99074ecd2a..962cdea5d0 100644 --- a/sql/data_sql_warehouse.go +++ b/sql/data_sql_warehouse.go @@ -12,6 +12,7 @@ import ( // Note that these fields are both marked as computed/optional because users can specify either the name or the ID // of the warehouse to retrieve. type sqlWarehouseDataParams struct { + common.Namespace Id string `json:"id" tf:"computed,optional"` Name string `json:"name" tf:"computed,optional"` } diff --git a/sql/data_sql_warehouses.go b/sql/data_sql_warehouses.go index f21a412da2..2b9352a159 100644 --- a/sql/data_sql_warehouses.go +++ b/sql/data_sql_warehouses.go @@ -12,6 +12,7 @@ import ( func DataSourceWarehouses() common.Resource { type warehousesData struct { + common.Namespace WarehouseNameContains string `json:"warehouse_name_contains,omitempty"` Ids []string `json:"ids,omitempty" tf:"computed,slice_set"` } diff --git a/sql/resource_alert.go b/sql/resource_alert.go index c7d71e8c61..f42c34182f 100644 --- a/sql/resource_alert.go +++ b/sql/resource_alert.go @@ -11,8 +11,13 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) +type Alert struct { + sql.Alert + common.Namespace +} + func ResourceAlert() common.Resource { - s := common.StructToSchema(sql.Alert{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { + s := common.StructToSchema(Alert{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { common.CustomizeSchemaPath(m, "display_name").SetRequired() common.CustomizeSchemaPath(m, "query_id").SetRequired() common.CustomizeSchemaPath(m, "condition").SetRequired() @@ -45,12 +50,13 @@ func ResourceAlert() common.Resource { common.CustomizeSchemaPath(m, "state").SetReadOnly() common.CustomizeSchemaPath(m, "trigger_time").SetReadOnly() common.CustomizeSchemaPath(m, "update_time").SetReadOnly() + common.NamespaceCustomizeSchemaMap(m) return m }) return common.Resource{ Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -78,7 +84,7 @@ func ResourceAlert() common.Resource { return err }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -94,7 +100,7 @@ func ResourceAlert() common.Resource { return common.StructToData(apiAlert, s, d) }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -118,12 +124,15 @@ func ResourceAlert() common.Resource { return err }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } return w.Alerts.DeleteById(ctx, d.Id()) }, Schema: s, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, } } diff --git a/sql/resource_query.go b/sql/resource_query.go index 4db7820d21..128dea2f0b 100644 --- a/sql/resource_query.go +++ b/sql/resource_query.go @@ -14,6 +14,7 @@ import ( // Need a struct for Query because there are aliases we need and it'll be needed in the create method. type QueryStruct struct { sql.Query + common.Namespace } var queryAliasMap = map[string]string{ @@ -27,6 +28,7 @@ func (QueryStruct) Aliases() map[string]map[string]string { } func (QueryStruct) CustomizeSchema(m *common.CustomizableSchema) *common.CustomizableSchema { + common.NamespaceCustomizeSchema(m) m.SchemaPath("display_name").SetRequired().SetValidateFunc(validation.StringIsNotWhiteSpace) m.SchemaPath("query_text").SetRequired() m.SchemaPath("warehouse_id").SetRequired().SetValidateFunc(validation.StringIsNotWhiteSpace) @@ -92,8 +94,11 @@ func (queryUpdateStruct) CustomizeSchema(s *common.CustomizableSchema) *common.C func ResourceQuery() common.Resource { s := common.StructToSchema(QueryStruct{}, nil) return common.Resource{ + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -121,7 +126,7 @@ func ResourceQuery() common.Resource { return err }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -137,7 +142,7 @@ func ResourceQuery() common.Resource { return common.StructToData(QueryStruct{Query: *apiQuery}, s, d) }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -160,7 +165,7 @@ func ResourceQuery() common.Resource { return err }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } diff --git a/sql/resource_sql_alerts.go b/sql/resource_sql_alerts.go index 7a54a59ecb..81f271d111 100644 --- a/sql/resource_sql_alerts.go +++ b/sql/resource_sql_alerts.go @@ -23,6 +23,7 @@ type AlertOptions struct { } type AlertEntity struct { + common.Namespace Name string `json:"name"` QueryId string `json:"query_id"` Rearm int `json:"rearm,omitempty"` @@ -125,12 +126,16 @@ func (a *AlertEntity) fromAPIObject(apiAlert *sql.LegacyAlert, s map[string]*sch func ResourceSqlAlert() common.Resource { s := common.StructToSchema(AlertEntity{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { common.MustSchemaPath(m, "options", "op").ValidateFunc = validation.StringInSlice([]string{">", ">=", "<", "<=", "==", "!="}, true) + common.NamespaceCustomizeSchemaMap(m) return m }) return common.Resource{ + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, Create: func(ctx context.Context, data *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, data) if err != nil { return err } @@ -147,7 +152,7 @@ func ResourceSqlAlert() common.Resource { return nil }, Read: func(ctx context.Context, data *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, data) if err != nil { return err } @@ -160,7 +165,7 @@ func ResourceSqlAlert() common.Resource { return a.fromAPIObject(apiAlert, s, data) }, Update: func(ctx context.Context, data *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, data) if err != nil { return err } @@ -172,7 +177,7 @@ func ResourceSqlAlert() common.Resource { return w.AlertsLegacy.Update(ctx, ca) }, Delete: func(ctx context.Context, data *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, data) if err != nil { return err } diff --git a/sql/resource_sql_endpoint.go b/sql/resource_sql_endpoint.go index a08e138fd5..9f159e07e4 100644 --- a/sql/resource_sql_endpoint.go +++ b/sql/resource_sql_endpoint.go @@ -21,6 +21,7 @@ var ( type SqlWarehouse struct { sql.GetWarehouseResponse + common.Namespace // The data source ID is not part of the endpoint API response. // We manually resolve it by retrieving the list of data sources @@ -98,6 +99,7 @@ func ResourceSqlEndpoint() common.Resource { }, } + common.NamespaceCustomizeSchemaMap(m) return m }) return common.Resource{ @@ -105,7 +107,7 @@ func ResourceSqlEndpoint() common.Resource { Create: schema.DefaultTimeout(30 * time.Minute), }, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -138,7 +140,7 @@ func ResourceSqlEndpoint() common.Resource { return nil }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -153,7 +155,7 @@ func ResourceSqlEndpoint() common.Resource { return common.StructToData(warehouse, s, d) }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -168,7 +170,7 @@ func ResourceSqlEndpoint() common.Resource { return nil }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -176,7 +178,10 @@ func ResourceSqlEndpoint() common.Resource { }, Schema: s, CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { - return d.Clear("health") + if err := d.Clear("health"); err != nil { + return err + } + return common.NamespaceCustomizeDiff(d) }, } } diff --git a/storage/generic_mounts.go b/storage/generic_mounts.go index 72e8d4dedb..84cfed6c0c 100644 --- a/storage/generic_mounts.go +++ b/storage/generic_mounts.go @@ -12,6 +12,7 @@ import ( // TODO: add support for encryption parameters in S3 type GenericMount struct { + common.Namespace URI string `json:"uri,omitempty" tf:"force_new"` Options map[string]string `json:"extra_configs,omitempty" tf:"force_new"` Abfs *AzureADLSGen2MountGeneric `json:"abfs,omitempty" tf:"force_new,suppress_diff"` diff --git a/storage/resource_file.go b/storage/resource_file.go index 85121b3d2e..0cef32087d 100644 --- a/storage/resource_file.go +++ b/storage/resource_file.go @@ -52,7 +52,7 @@ func getContentReader(data *schema.ResourceData) (*hashReadCloser, error) { } func upload(ctx context.Context, data *schema.ResourceData, c *common.DatabricksClient, path string) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, data) if err != nil { return err } @@ -104,7 +104,7 @@ func ResourceFile() common.Resource { return nil }, Read: func(ctx context.Context, data *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, data) if err != nil { return err } @@ -127,7 +127,7 @@ func ResourceFile() common.Resource { return upload(ctx, data, c, path) }, Delete: func(ctx context.Context, data *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, data) if err != nil { return err } diff --git a/tokens/resource_obo_token.go b/tokens/resource_obo_token.go index e5c724d54d..72c77b77f8 100644 --- a/tokens/resource_obo_token.go +++ b/tokens/resource_obo_token.go @@ -11,6 +11,7 @@ import ( ) type OboToken struct { + common.Namespace ApplicationID string `json:"application_id"` LifetimeSeconds int32 `json:"lifetime_seconds,omitempty"` Comment string `json:"comment,omitempty"` @@ -48,10 +49,14 @@ func ResourceOboToken() common.Resource { Computed: true, Sensitive: true, } + common.NamespaceCustomizeSchemaMap(m) return m }) return common.Resource{ Schema: oboTokenSchema, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { var request OboToken common.DataToStructPointer(d, oboTokenSchema, &request) diff --git a/tokens/resource_service_principal_secret.go b/tokens/resource_service_principal_secret.go index 2c00bc804e..14924a70f3 100644 --- a/tokens/resource_service_principal_secret.go +++ b/tokens/resource_service_principal_secret.go @@ -16,6 +16,7 @@ import ( type ServicePrincipalSecret struct { oauth2.CreateServicePrincipalSecretResponse + common.Namespace ServicePrincipalId string `json:"service_principal_id" tf:"force_new"` Lifetime string `json:"lifetime,omitempty" tf:"computed,force_new"` } @@ -40,10 +41,14 @@ func ResourceServicePrincipalSecret() common.Resource { m["secret"].Computed = true m["secret"].Sensitive = true m["status"].Computed = true + common.NamespaceCustomizeSchemaMap(m) return m }) return common.Resource{ Schema: spnSecretSchema, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, CanSkipReadAfterCreateAndUpdate: func(d *schema.ResourceData) bool { return true }, diff --git a/vectorsearch/resource_vector_search_endpoint.go b/vectorsearch/resource_vector_search_endpoint.go index b6bb62c2e5..48fe43c5b2 100644 --- a/vectorsearch/resource_vector_search_endpoint.go +++ b/vectorsearch/resource_vector_search_endpoint.go @@ -14,9 +14,14 @@ import ( const defaultEndpointProvisionTimeout = 75 * time.Minute const deleteCallTimeout = 10 * time.Second +type EndpointInfo struct { + vectorsearch.EndpointInfo + common.Namespace +} + func ResourceVectorSearchEndpoint() common.Resource { s := common.StructToSchema( - vectorsearch.EndpointInfo{}, + EndpointInfo{}, func(s map[string]*schema.Schema) map[string]*schema.Schema { common.CustomizeSchemaPath(s, "name").SetRequired().SetForceNew() common.CustomizeSchemaPath(s, "endpoint_type").SetRequired().SetForceNew() @@ -35,13 +40,13 @@ func ResourceVectorSearchEndpoint() common.Resource { Optional: true, Computed: true, }) - + common.NamespaceCustomizeSchemaMap(s) return s }) return common.Resource{ Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -64,7 +69,7 @@ func ResourceVectorSearchEndpoint() common.Resource { return nil }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -81,7 +86,7 @@ func ResourceVectorSearchEndpoint() common.Resource { return nil }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -98,7 +103,7 @@ func ResourceVectorSearchEndpoint() common.Resource { }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -110,5 +115,8 @@ func ResourceVectorSearchEndpoint() common.Resource { Timeouts: &schema.ResourceTimeout{ Create: schema.DefaultTimeout(defaultEndpointProvisionTimeout), }, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, } } diff --git a/vectorsearch/resource_vector_search_index.go b/vectorsearch/resource_vector_search_index.go index 85d9eaf205..b755a39070 100644 --- a/vectorsearch/resource_vector_search_index.go +++ b/vectorsearch/resource_vector_search_index.go @@ -18,6 +18,11 @@ import ( const defaultIndexProvisionTimeout = 15 * time.Minute +type VectorIndex struct { + vectorsearch.VectorIndex + common.Namespace +} + func waitForVectorSearchIndexDeletion(w *databricks.WorkspaceClient, ctx context.Context, searchIndexName string) error { return retry.RetryContext(ctx, defaultIndexProvisionTimeout, func() *retry.RetryError { _, err := w.VectorSearchIndexes.GetIndexByIndexName(ctx, searchIndexName) @@ -47,7 +52,7 @@ func waitForSearchIndexCreation(w *databricks.WorkspaceClient, ctx context.Conte func ResourceVectorSearchIndex() common.Resource { s := common.StructToSchema( - vectorsearch.VectorIndex{}, + VectorIndex{}, func(s map[string]*schema.Schema) map[string]*schema.Schema { common.MustSchemaPath(s, "delta_sync_index_spec", "embedding_vector_columns").MinItems = 1 exof := []string{"delta_sync_index_spec", "direct_access_index_spec"} @@ -62,12 +67,13 @@ func ResourceVectorSearchIndex() common.Resource { common.CustomizeSchemaPath(s, "name").SetRequired() common.CustomizeSchemaPath(s, "index_type").SetRequired() common.CustomizeSchemaPath(s, "delta_sync_index_spec", "pipeline_id").SetReadOnly() + common.NamespaceCustomizeSchemaMap(s) return s }) return common.Resource{ Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -89,7 +95,7 @@ func ResourceVectorSearchIndex() common.Resource { return nil }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -100,7 +106,7 @@ func ResourceVectorSearchIndex() common.Resource { return common.StructToData(*index, s, d) }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -116,5 +122,8 @@ func ResourceVectorSearchIndex() common.Resource { Timeouts: &schema.ResourceTimeout{ Create: schema.DefaultTimeout(defaultIndexProvisionTimeout), }, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, } } diff --git a/workspace/data_directory.go b/workspace/data_directory.go index c41eed7be4..f422a3c330 100644 --- a/workspace/data_directory.go +++ b/workspace/data_directory.go @@ -12,6 +12,7 @@ import ( // DataSourceDirectory ... func DataSourceDirectory() common.Resource { type Directory struct { + common.Namespace Id string `json:"id,omitempty" tf:"computed"` Path string `json:"path"` ObjectId int64 `json:"object_id,omitempty" tf:"computed"` diff --git a/workspace/resource_directory.go b/workspace/resource_directory.go index 2ed4bcc4df..8823fd180b 100644 --- a/workspace/resource_directory.go +++ b/workspace/resource_directory.go @@ -40,9 +40,10 @@ func ResourceDirectory() common.Resource { Computed: true, }, } + common.NamespaceCustomizeSchemaMap(s) directoryRead := func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - client, err := c.WorkspaceClient() + client, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -67,7 +68,7 @@ func ResourceDirectory() common.Resource { return common.Resource{ Schema: s, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - client, err := c.WorkspaceClient() + client, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -83,7 +84,7 @@ func ResourceDirectory() common.Resource { Read: directoryRead, Update: directoryRead, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - client, err := c.WorkspaceClient() + client, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -97,5 +98,8 @@ func ResourceDirectory() common.Resource { } return err }, + CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff) error { + return common.NamespaceCustomizeDiff(d) + }, } } diff --git a/workspace/resource_global_init_script.go b/workspace/resource_global_init_script.go index 37d915941f..5c3d316915 100644 --- a/workspace/resource_global_init_script.go +++ b/workspace/resource_global_init_script.go @@ -54,7 +54,7 @@ func ResourceGlobalInitScript() common.Resource { return fmt.Errorf("size of the global init script (%d bytes) exceeds maximal allowed (%d bytes)", contentLen, maxScriptSize) } - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -71,7 +71,7 @@ func ResourceGlobalInitScript() common.Resource { return nil }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -90,7 +90,7 @@ func ResourceGlobalInitScript() common.Resource { return fmt.Errorf("size of the global init script (%d bytes) exceeds maximal allowed (%d bytes)", contentLen, maxScriptSize) } - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -103,7 +103,7 @@ func ResourceGlobalInitScript() common.Resource { }) }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } diff --git a/workspace/resource_notebook.go b/workspace/resource_notebook.go index 1bff5895ff..38d86fb2d3 100644 --- a/workspace/resource_notebook.go +++ b/workspace/resource_notebook.go @@ -341,7 +341,7 @@ func ResourceNotebook() common.Resource { oldFormat = "SOURCE" } } - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } diff --git a/workspace/resource_workspace_conf.go b/workspace/resource_workspace_conf.go index 41e720b1c2..7d6be4fa87 100644 --- a/workspace/resource_workspace_conf.go +++ b/workspace/resource_workspace_conf.go @@ -64,7 +64,7 @@ func applyWorkspaceConf(ctx context.Context, d *schema.ResourceData, c *common.D } } - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -96,7 +96,7 @@ func updateWorkspaceConf(ctx context.Context, d *schema.ResourceData, c *common. } func deleteWorkspaceConf(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -222,7 +222,7 @@ func ResourceWorkspaceConf() common.Resource { Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { config := d.Get("custom_config").(map[string]any) log.Printf("[DEBUG] Config available in state: %v", config) - w, err := c.WorkspaceClient() + w, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } diff --git a/workspace/resource_workspace_file.go b/workspace/resource_workspace_file.go index 8a72107e1d..d228a92492 100644 --- a/workspace/resource_workspace_file.go +++ b/workspace/resource_workspace_file.go @@ -37,7 +37,7 @@ func ResourceWorkspaceFile() common.Resource { if err != nil { return err } - client, err := c.WorkspaceClient() + client, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -68,7 +68,7 @@ func ResourceWorkspaceFile() common.Resource { return nil }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - client, err := c.WorkspaceClient() + client, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -82,7 +82,7 @@ func ResourceWorkspaceFile() common.Resource { return common.StructToData(objectStatus, s, d) }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - client, err := c.WorkspaceClient() + client, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err } @@ -99,7 +99,7 @@ func ResourceWorkspaceFile() common.Resource { }) }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - client, err := c.WorkspaceClient() + client, err := c.WorkspaceClientUnifiedProvider(ctx, d) if err != nil { return err }