From 1ad91bd3aace90cebdb206e1fc982b35a98a3c1f Mon Sep 17 00:00:00 2001 From: Miles Yucht Date: Wed, 31 Jan 2024 13:19:45 +0100 Subject: [PATCH 1/8] Working! --- clusters/data_spark_version.go | 7 ++- clusters/resource_cluster.go | 1 + common/client.go | 66 +++++++++++++++++++++++++++-- common/resource.go | 34 ++++++++++++--- go.mod | 2 + internal/acceptance/cluster_test.go | 24 +++++++++++ 6 files changed, 124 insertions(+), 10 deletions(-) diff --git a/clusters/data_spark_version.go b/clusters/data_spark_version.go index 60fa3140ed..8cd4c50d02 100644 --- a/clusters/data_spark_version.go +++ b/clusters/data_spark_version.go @@ -131,15 +131,20 @@ func DataSourceSparkVersion() *schema.Resource { s["photon"].Deprecated = "Specify runtime_engine=\"PHOTON\" in the cluster configuration" s["graviton"].Deprecated = "Not required anymore - it's automatically enabled on the Graviton-based node types" + common.AddWorkspaceIdField(s) return s }) return &schema.Resource{ Schema: s, ReadContext: func(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { + c, err := m.(*common.DatabricksClient).InConfiguredWorkspace(ctx, d) + if err != nil { + return diag.FromErr(err) + } var this SparkVersionRequest common.DataToStructPointer(d, s, &this) - version, err := NewClustersAPI(ctx, m).LatestSparkVersion(this) + version, err := NewClustersAPI(ctx, c).LatestSparkVersion(this) if err != nil { return diag.FromErr(err) } diff --git a/clusters/resource_cluster.go b/clusters/resource_cluster.go index f60e7b49e5..96e29f0f22 100644 --- a/clusters/resource_cluster.go +++ b/clusters/resource_cluster.go @@ -166,6 +166,7 @@ func (ClusterResourceProvider) CustomizeSchema(s map[string]*schema.Schema) map[ Schema: common.StructToSchema(MountInfo{}, nil), }, }) + common.AddWorkspaceIdField(s) return s } diff --git a/common/client.go b/common/client.go index bab0728658..1dbe3e107d 100644 --- a/common/client.go +++ b/common/client.go @@ -48,6 +48,16 @@ type DatabricksClient struct { cachedWorkspaceClient *databricks.WorkspaceClient cachedAccountClient *databricks.AccountClient mu sync.Mutex + + cachedWorkspaceClients map[int64]*databricks.WorkspaceClient + cachedWorkspaceClientsMu sync.Mutex +} + +func addCachedMe(w *databricks.WorkspaceClient) { + internalImpl := w.CurrentUser.Impl() + w.CurrentUser.WithImpl(&cachedMe{ + internalImpl: internalImpl, + }) } func (c *DatabricksClient) WorkspaceClient() (*databricks.WorkspaceClient, error) { @@ -60,14 +70,59 @@ func (c *DatabricksClient) WorkspaceClient() (*databricks.WorkspaceClient, error if err != nil { return nil, err } - internalImpl := w.CurrentUser.Impl() - w.CurrentUser.WithImpl(&cachedMe{ - internalImpl: internalImpl, - }) + addCachedMe(w) c.cachedWorkspaceClient = w return w, nil } +func (c *DatabricksClient) InConfiguredWorkspace(ctx context.Context, d *schema.ResourceData) (*DatabricksClient, error) { + workspaceId, ok := d.GetOk("workspace_id") + if !ok { + return c, nil + } + w, err := c.getConfiguredWorkspaceClient(ctx, int64(workspaceId.(int))) + if err != nil { + return nil, err + } + apiClient, err := client.New(w.Config) + if err != nil { + return nil, err + } + return &DatabricksClient{ + DatabricksClient: apiClient, + cachedWorkspaceClient: w, + }, nil +} + +func (c *DatabricksClient) getConfiguredWorkspaceClient(ctx context.Context, workspaceId int64) (*databricks.WorkspaceClient, error) { + if w, ok := c.cachedWorkspaceClients[workspaceId]; ok { + return w, nil + } + c.cachedWorkspaceClientsMu.Lock() + defer c.cachedWorkspaceClientsMu.Unlock() + if w, ok := c.cachedWorkspaceClients[workspaceId]; ok { + return w, nil + } + a, err := c.AccountClient() + if err != nil { + return nil, err + } + if c.cachedWorkspaceClients == nil { + c.cachedWorkspaceClients = make(map[int64]*databricks.WorkspaceClient) + } + ws, err := a.Workspaces.GetByWorkspaceId(ctx, workspaceId) + if err != nil { + return nil, err + } + w, err := a.GetWorkspaceClient(*ws) + if err != nil { + return nil, err + } + addCachedMe(w) + c.cachedWorkspaceClients[workspaceId] = w + return w, nil +} + // Set the cached workspace client. func (c *DatabricksClient) SetWorkspaceClient(w *databricks.WorkspaceClient) { c.mu.Lock() @@ -97,6 +152,9 @@ func (c *DatabricksClient) setAccountId(accountId string) error { } func (c *DatabricksClient) AccountClient() (*databricks.AccountClient, error) { + if c.cachedAccountClient != nil { + return c.cachedAccountClient, nil + } c.mu.Lock() defer c.mu.Unlock() if c.cachedAccountClient != nil { diff --git a/common/resource.go b/common/resource.go index 5838892942..5b7cd53b02 100644 --- a/common/resource.go +++ b/common/resource.go @@ -87,7 +87,10 @@ func (r Resource) ToResource() *schema.Resource { if r.Update != nil { update = func(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - c := m.(*DatabricksClient) + c, err := m.(*DatabricksClient).InConfiguredWorkspace(ctx, d) + if err != nil { + return diag.FromErr(err) + } if err := recoverable(r.Update)(ctx, d, c); err != nil { err = nicerError(ctx, err, "update") return diag.FromErr(err) @@ -124,7 +127,11 @@ func (r Resource) ToResource() *schema.Resource { m any) diag.Diagnostics { return func(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - err := recoverable(r.Read)(ctx, d, m.(*DatabricksClient)) + c, err := m.(*DatabricksClient).InConfiguredWorkspace(ctx, d) + if err != nil { + return diag.FromErr(err) + } + err = recoverable(r.Read)(ctx, d, c) // TODO: https://github.com/databricks/terraform-provider-databricks/issues/2021 if ignoreMissing && apierr.IsMissing(err) { log.Printf("[INFO] %s[id=%s] is removed on backend", @@ -146,8 +153,11 @@ func (r Resource) ToResource() *schema.Resource { CustomizeDiff: r.saferCustomizeDiff(), CreateContext: func(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - c := m.(*DatabricksClient) - err := recoverable(r.Create)(ctx, d, c) + c, err := m.(*DatabricksClient).InConfiguredWorkspace(ctx, d) + if err != nil { + return diag.FromErr(err) + } + err = recoverable(r.Create)(ctx, d, c) if err != nil { err = nicerError(ctx, err, "create") return diag.FromErr(err) @@ -162,7 +172,11 @@ func (r Resource) ToResource() *schema.Resource { UpdateContext: update, DeleteContext: func(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - err := recoverable(r.Delete)(ctx, d, m.(*DatabricksClient)) + c, err := m.(*DatabricksClient).InConfiguredWorkspace(ctx, d) + if err != nil { + return diag.FromErr(err) + } + err = recoverable(r.Delete)(ctx, d, c) if apierr.IsMissing(err) { // TODO: https://github.com/databricks/terraform-provider-databricks/issues/2021 log.Printf("[INFO] %s[id=%s] is removed on backend", @@ -447,3 +461,13 @@ func AddAccountIdField(s map[string]*schema.Schema) map[string]*schema.Schema { } return s } + +func AddWorkspaceIdField(s map[string]*schema.Schema) map[string]*schema.Schema { + s["workspace_id"] = &schema.Schema{ + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + Description: "The workspace id of the workspace, for example 1234567890. This can be retrieved from `databricks_mws_workspaces..workspace_id`. This attribute is required when using an account-level provider.", + } + return s +} diff --git a/go.mod b/go.mod index 6a1cb0de85..700d713c9b 100644 --- a/go.mod +++ b/go.mod @@ -82,3 +82,5 @@ require ( gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) + +replace github.com/databricks/databricks-sdk-go => /Users/miles/databricks-sdk-go \ No newline at end of file diff --git a/internal/acceptance/cluster_test.go b/internal/acceptance/cluster_test.go index 3cfe25b944..e2eefcf498 100644 --- a/internal/acceptance/cluster_test.go +++ b/internal/acceptance/cluster_test.go @@ -69,3 +69,27 @@ func TestAccClusterResource_CreateSingleNodeCluster(t *testing.T) { }`, }) } + +func TestMwsAccClusterResource_CreateClusterWithAccountLevelProvider(t *testing.T) { + accountLevel(t, step{ + Template: ` + data "databricks_spark_version" "latest" { + workspace_id = 5549111504720597 + } + resource "databricks_cluster" "this" { + workspace_id = 5549111504720597 + cluster_name = "singlenode-{var.RANDOM}" + spark_version = data.databricks_spark_version.latest.id + instance_pool_id = "1127-101603-faked620-pool-c10aq68g" + num_workers = 0 + autotermination_minutes = 10 + spark_conf = { + "spark.databricks.cluster.profile" = "singleNode" + "spark.master" = "local[*]" + } + custom_tags = { + "ResourceClass" = "SingleNode" + } + }`, + }) +} From eb7097bb456ee3bc99213fbee3bfc3fb7c4c8d75 Mon Sep 17 00:00:00 2001 From: Miles Yucht Date: Wed, 31 Jan 2024 17:08:26 +0100 Subject: [PATCH 2/8] apply to all resources & data sources --- common/client.go | 10 +- common/resource.go | 23 ++- provider/provider.go | 271 ++++++++++++++++--------------- settings/all_settings.go | 11 +- settings/generic_setting_test.go | 2 +- 5 files changed, 183 insertions(+), 134 deletions(-) diff --git a/common/client.go b/common/client.go index 1dbe3e107d..a071f038c1 100644 --- a/common/client.go +++ b/common/client.go @@ -76,7 +76,15 @@ func (c *DatabricksClient) WorkspaceClient() (*databricks.WorkspaceClient, error } func (c *DatabricksClient) InConfiguredWorkspace(ctx context.Context, d *schema.ResourceData) (*DatabricksClient, error) { - workspaceId, ok := d.GetOk("workspace_id") + return c.inConfiguredWorkspace(ctx, d, "workspace_id") +} + +func (c *DatabricksClient) InConfiguredWorkspaceForDelete(ctx context.Context, d *schema.ResourceData) (*DatabricksClient, error) { + return c.inConfiguredWorkspace(ctx, d, "original_workspace_id") +} + +func (c *DatabricksClient) inConfiguredWorkspace(ctx context.Context, d *schema.ResourceData, key string) (*DatabricksClient, error) { + workspaceId, ok := d.GetOk(key) if !ok { return c, nil } diff --git a/common/resource.go b/common/resource.go index 5b7cd53b02..75deb7a638 100644 --- a/common/resource.go +++ b/common/resource.go @@ -14,6 +14,18 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) +// Wrapper of the underlying Terraform resource. Needed as some resources are implemented directly +// with *schema.Resource rather than the Resource type in this package. +type DatabricksTerraformResource struct { + // The underlying TF resource + Resource *schema.Resource + + // Whether the resource is available at the workspace-level. If true, + // generated resources will have a `workspace_id` field for use when + // an account-level provider is used. + IsWorkspaceLevel bool +} + // Resource aims to simplify things like error & deleted entities handling type Resource struct { Create func(ctx context.Context, d *schema.ResourceData, c *DatabricksClient) error @@ -172,7 +184,7 @@ func (r Resource) ToResource() *schema.Resource { UpdateContext: update, DeleteContext: func(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - c, err := m.(*DatabricksClient).InConfiguredWorkspace(ctx, d) + c, err := m.(*DatabricksClient).InConfiguredWorkspaceForDelete(ctx, d) if err != nil { return diag.FromErr(err) } @@ -469,5 +481,14 @@ func AddWorkspaceIdField(s map[string]*schema.Schema) map[string]*schema.Schema ForceNew: true, Description: "The workspace id of the workspace, for example 1234567890. This can be retrieved from `databricks_mws_workspaces..workspace_id`. This attribute is required when using an account-level provider.", } + // Separate field to track the original workspace ID when using an account-level provider. + // Needed when changing the workspace ID, as `workspace_id` in state will reflect + // the new ID during apply. + s["original_workspace_id"] = &schema.Schema{ + Type: schema.TypeInt, + Optional: false, + Required: false, + Computed: true, + } return s } diff --git a/provider/provider.go b/provider/provider.go index 65c4a4f53c..5c65425bb3 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -50,135 +50,152 @@ func init() { // DatabricksProvider returns the entire terraform provider object func DatabricksProvider() *schema.Provider { - p := &schema.Provider{ - DataSourcesMap: map[string]*schema.Resource{ // must be in alphabetical order - "databricks_aws_crossaccount_policy": aws.DataAwsCrossaccountPolicy(), - "databricks_aws_assume_role_policy": aws.DataAwsAssumeRolePolicy(), - "databricks_aws_bucket_policy": aws.DataAwsBucketPolicy(), - "databricks_cluster": clusters.DataSourceCluster(), - "databricks_clusters": clusters.DataSourceClusters(), - "databricks_cluster_policy": policies.DataSourceClusterPolicy(), - "databricks_catalogs": catalog.DataSourceCatalogs(), - "databricks_current_config": mws.DataSourceCurrentConfiguration(), - "databricks_current_metastore": catalog.DataSourceCurrentMetastore(), - "databricks_current_user": scim.DataSourceCurrentUser(), - "databricks_dbfs_file": storage.DataSourceDbfsFile(), - "databricks_dbfs_file_paths": storage.DataSourceDbfsFilePaths(), - "databricks_directory": workspace.DataSourceDirectory(), - "databricks_group": scim.DataSourceGroup(), - "databricks_instance_pool": pools.DataSourceInstancePool(), - "databricks_instance_profiles": aws.DataSourceInstanceProfiles(), - "databricks_jobs": jobs.DataSourceJobs(), - "databricks_job": jobs.DataSourceJob(), - "databricks_metastore": catalog.DataSourceMetastore(), - "databricks_metastores": catalog.DataSourceMetastores(), - "databricks_mlflow_model": mlflow.DataSourceModel(), - "databricks_mws_credentials": mws.DataSourceMwsCredentials(), - "databricks_mws_workspaces": mws.DataSourceMwsWorkspaces(), - "databricks_node_type": clusters.DataSourceNodeType(), - "databricks_notebook": workspace.DataSourceNotebook(), - "databricks_notebook_paths": workspace.DataSourceNotebookPaths(), - "databricks_pipelines": pipelines.DataSourcePipelines(), - "databricks_schemas": catalog.DataSourceSchemas(), - "databricks_service_principal": scim.DataSourceServicePrincipal(), - "databricks_service_principals": scim.DataSourceServicePrincipals(), - "databricks_share": catalog.DataSourceShare(), - "databricks_shares": catalog.DataSourceShares(), - "databricks_spark_version": clusters.DataSourceSparkVersion(), - "databricks_sql_warehouse": sql.DataSourceWarehouse(), - "databricks_sql_warehouses": sql.DataSourceWarehouses(), - "databricks_tables": catalog.DataSourceTables(), - "databricks_views": catalog.DataSourceViews(), - "databricks_user": scim.DataSourceUser(), - "databricks_zones": clusters.DataSourceClusterZones(), - }, - ResourcesMap: map[string]*schema.Resource{ // must be in alphabetical order - "databricks_access_control_rule_set": permissions.ResourceAccessControlRuleSet(), - "databricks_artifact_allowlist": catalog.ResourceArtifactAllowlist(), - "databricks_aws_s3_mount": storage.ResourceAWSS3Mount(), - "databricks_azure_adls_gen1_mount": storage.ResourceAzureAdlsGen1Mount(), - "databricks_azure_adls_gen2_mount": storage.ResourceAzureAdlsGen2Mount(), - "databricks_azure_blob_mount": storage.ResourceAzureBlobMount(), - "databricks_catalog": catalog.ResourceCatalog(), - "databricks_catalog_workspace_binding": catalog.ResourceCatalogWorkspaceBinding(), - "databricks_connection": catalog.ResourceConnection(), - "databricks_cluster": clusters.ResourceCluster(), - "databricks_cluster_policy": policies.ResourceClusterPolicy(), - "databricks_dbfs_file": storage.ResourceDbfsFile(), - "databricks_directory": workspace.ResourceDirectory(), - "databricks_entitlements": scim.ResourceEntitlements(), - "databricks_external_location": catalog.ResourceExternalLocation(), - "databricks_git_credential": repos.ResourceGitCredential(), - "databricks_global_init_script": workspace.ResourceGlobalInitScript(), - "databricks_grant": catalog.ResourceGrant(), - "databricks_grants": catalog.ResourceGrants(), - "databricks_group": scim.ResourceGroup(), - "databricks_group_instance_profile": aws.ResourceGroupInstanceProfile(), - "databricks_group_member": scim.ResourceGroupMember(), - "databricks_group_role": scim.ResourceGroupRole(), - "databricks_instance_pool": pools.ResourceInstancePool(), - "databricks_instance_profile": aws.ResourceInstanceProfile(), - "databricks_ip_access_list": access.ResourceIPAccessList(), - "databricks_job": jobs.ResourceJob(), - "databricks_library": clusters.ResourceLibrary(), - "databricks_metastore": catalog.ResourceMetastore(), - "databricks_metastore_assignment": catalog.ResourceMetastoreAssignment(), - "databricks_metastore_data_access": catalog.ResourceMetastoreDataAccess(), - "databricks_mlflow_experiment": mlflow.ResourceMlflowExperiment(), - "databricks_mlflow_model": mlflow.ResourceMlflowModel(), - "databricks_mlflow_webhook": mlflow.ResourceMlflowWebhook(), - "databricks_model_serving": serving.ResourceModelServing(), - "databricks_mount": storage.ResourceMount(), - "databricks_mws_customer_managed_keys": mws.ResourceMwsCustomerManagedKeys(), - "databricks_mws_credentials": mws.ResourceMwsCredentials(), - "databricks_mws_log_delivery": mws.ResourceMwsLogDelivery(), - "databricks_mws_networks": mws.ResourceMwsNetworks(), - "databricks_mws_permission_assignment": mws.ResourceMwsPermissionAssignment(), - "databricks_mws_private_access_settings": mws.ResourceMwsPrivateAccessSettings(), - "databricks_mws_storage_configurations": mws.ResourceMwsStorageConfigurations(), - "databricks_mws_vpc_endpoint": mws.ResourceMwsVpcEndpoint(), - "databricks_mws_workspaces": mws.ResourceMwsWorkspaces(), - "databricks_notebook": workspace.ResourceNotebook(), - "databricks_obo_token": tokens.ResourceOboToken(), - "databricks_permission_assignment": access.ResourcePermissionAssignment(), - "databricks_permissions": permissions.ResourcePermissions(), - "databricks_pipeline": pipelines.ResourcePipeline(), - "databricks_provider": catalog.ResourceProvider(), - "databricks_recipient": sharing.ResourceRecipient(), - "databricks_registered_model": catalog.ResourceRegisteredModel(), - "databricks_repo": repos.ResourceRepo(), - "databricks_schema": catalog.ResourceSchema(), - "databricks_secret": secrets.ResourceSecret(), - "databricks_secret_scope": secrets.ResourceSecretScope(), - "databricks_secret_acl": secrets.ResourceSecretACL(), - "databricks_service_principal": scim.ResourceServicePrincipal(), - "databricks_service_principal_role": aws.ResourceServicePrincipalRole(), - "databricks_service_principal_secret": tokens.ResourceServicePrincipalSecret(), - "databricks_share": catalog.ResourceShare(), - "databricks_sql_dashboard": sql.ResourceSqlDashboard(), - "databricks_sql_endpoint": sql.ResourceSqlEndpoint(), - "databricks_sql_global_config": sql.ResourceSqlGlobalConfig(), - "databricks_sql_permissions": access.ResourceSqlPermissions(), - "databricks_sql_query": sql.ResourceSqlQuery(), - "databricks_sql_alert": sql.ResourceSqlAlert(), - "databricks_sql_table": catalog.ResourceSqlTable(), - "databricks_sql_visualization": sql.ResourceSqlVisualization(), - "databricks_sql_widget": sql.ResourceSqlWidget(), - "databricks_storage_credential": catalog.ResourceStorageCredential(), - "databricks_system_schema": catalog.ResourceSystemSchema(), - "databricks_table": catalog.ResourceTable(), - "databricks_token": tokens.ResourceToken(), - "databricks_user": scim.ResourceUser(), - "databricks_user_instance_profile": aws.ResourceUserInstanceProfile(), - "databricks_user_role": aws.ResourceUserRole(), - "databricks_volume": catalog.ResourceVolume(), - "databricks_workspace_conf": workspace.ResourceWorkspaceConf(), - "databricks_workspace_file": workspace.ResourceWorkspaceFile(), - }, - Schema: providerSchema(), + // must be in alphabetical order + dataSources := map[string]common.DatabricksTerraformResource{ + "databricks_aws_crossaccount_policy": {Resource: aws.DataAwsCrossaccountPolicy()}, + "databricks_aws_assume_role_policy": {Resource: aws.DataAwsAssumeRolePolicy()}, + "databricks_aws_bucket_policy": {Resource: aws.DataAwsBucketPolicy()}, + "databricks_cluster": {Resource: clusters.DataSourceCluster(), IsWorkspaceLevel: true}, + "databricks_clusters": {Resource: clusters.DataSourceClusters(), IsWorkspaceLevel: true}, + "databricks_cluster_policy": {Resource: policies.DataSourceClusterPolicy(), IsWorkspaceLevel: true}, + "databricks_catalogs": {Resource: catalog.DataSourceCatalogs(), IsWorkspaceLevel: true}, + "databricks_current_config": {Resource: mws.DataSourceCurrentConfiguration(), IsWorkspaceLevel: true}, + "databricks_current_metastore": {Resource: catalog.DataSourceCurrentMetastore(), IsWorkspaceLevel: true}, + "databricks_current_user": {Resource: scim.DataSourceCurrentUser(), IsWorkspaceLevel: true}, + "databricks_dbfs_file": {Resource: storage.DataSourceDbfsFile(), IsWorkspaceLevel: true}, + "databricks_dbfs_file_paths": {Resource: storage.DataSourceDbfsFilePaths(), IsWorkspaceLevel: true}, + "databricks_directory": {Resource: workspace.DataSourceDirectory(), IsWorkspaceLevel: true}, + "databricks_group": {Resource: scim.DataSourceGroup(), IsWorkspaceLevel: true}, + "databricks_instance_pool": {Resource: pools.DataSourceInstancePool(), IsWorkspaceLevel: true}, + "databricks_instance_profiles": {Resource: aws.DataSourceInstanceProfiles(), IsWorkspaceLevel: true}, + "databricks_jobs": {Resource: jobs.DataSourceJobs(), IsWorkspaceLevel: true}, + "databricks_job": {Resource: jobs.DataSourceJob(), IsWorkspaceLevel: true}, + "databricks_metastore": {Resource: catalog.DataSourceMetastore(), IsWorkspaceLevel: true}, + "databricks_metastores": {Resource: catalog.DataSourceMetastores(), IsWorkspaceLevel: true}, + "databricks_mlflow_model": {Resource: mlflow.DataSourceModel(), IsWorkspaceLevel: true}, + "databricks_mws_credentials": {Resource: mws.DataSourceMwsCredentials()}, + "databricks_mws_workspaces": {Resource: mws.DataSourceMwsWorkspaces()}, + "databricks_node_type": {Resource: clusters.DataSourceNodeType(), IsWorkspaceLevel: true}, + "databricks_notebook": {Resource: workspace.DataSourceNotebook(), IsWorkspaceLevel: true}, + "databricks_notebook_paths": {Resource: workspace.DataSourceNotebookPaths(), IsWorkspaceLevel: true}, + "databricks_pipelines": {Resource: pipelines.DataSourcePipelines(), IsWorkspaceLevel: true}, + "databricks_schemas": {Resource: catalog.DataSourceSchemas(), IsWorkspaceLevel: true}, + "databricks_service_principal": {Resource: scim.DataSourceServicePrincipal(), IsWorkspaceLevel: true}, + "databricks_service_principals": {Resource: scim.DataSourceServicePrincipals(), IsWorkspaceLevel: true}, + "databricks_share": {Resource: catalog.DataSourceShare(), IsWorkspaceLevel: true}, + "databricks_shares": {Resource: catalog.DataSourceShares(), IsWorkspaceLevel: true}, + "databricks_spark_version": {Resource: clusters.DataSourceSparkVersion(), IsWorkspaceLevel: true}, + "databricks_sql_warehouse": {Resource: sql.DataSourceWarehouse(), IsWorkspaceLevel: true}, + "databricks_sql_warehouses": {Resource: sql.DataSourceWarehouses(), IsWorkspaceLevel: true}, + "databricks_tables": {Resource: catalog.DataSourceTables(), IsWorkspaceLevel: true}, + "databricks_views": {Resource: catalog.DataSourceViews(), IsWorkspaceLevel: true}, + "databricks_user": {Resource: scim.DataSourceUser(), IsWorkspaceLevel: true}, + "databricks_zones": {Resource: clusters.DataSourceClusterZones(), IsWorkspaceLevel: true}, + } + // must be in alphabetical order + resources := map[string]common.DatabricksTerraformResource{ + "databricks_access_control_rule_set": {Resource: permissions.ResourceAccessControlRuleSet(), IsWorkspaceLevel: true}, + "databricks_artifact_allowlist": {Resource: catalog.ResourceArtifactAllowlist(), IsWorkspaceLevel: true}, + "databricks_aws_s3_mount": {Resource: storage.ResourceAWSS3Mount(), IsWorkspaceLevel: true}, + "databricks_azure_adls_gen1_mount": {Resource: storage.ResourceAzureAdlsGen1Mount(), IsWorkspaceLevel: true}, + "databricks_azure_adls_gen2_mount": {Resource: storage.ResourceAzureAdlsGen2Mount(), IsWorkspaceLevel: true}, + "databricks_azure_blob_mount": {Resource: storage.ResourceAzureBlobMount(), IsWorkspaceLevel: true}, + "databricks_catalog": {Resource: catalog.ResourceCatalog(), IsWorkspaceLevel: true}, + "databricks_catalog_workspace_binding": {Resource: catalog.ResourceCatalogWorkspaceBinding(), IsWorkspaceLevel: true}, + "databricks_connection": {Resource: catalog.ResourceConnection(), IsWorkspaceLevel: true}, + "databricks_cluster": {Resource: clusters.ResourceCluster(), IsWorkspaceLevel: true}, + "databricks_cluster_policy": {Resource: policies.ResourceClusterPolicy(), IsWorkspaceLevel: true}, + "databricks_dbfs_file": {Resource: storage.ResourceDbfsFile(), IsWorkspaceLevel: true}, + "databricks_directory": {Resource: workspace.ResourceDirectory(), IsWorkspaceLevel: true}, + "databricks_entitlements": {Resource: scim.ResourceEntitlements(), IsWorkspaceLevel: true}, + "databricks_external_location": {Resource: catalog.ResourceExternalLocation(), IsWorkspaceLevel: true}, + "databricks_git_credential": {Resource: repos.ResourceGitCredential(), IsWorkspaceLevel: true}, + "databricks_global_init_script": {Resource: workspace.ResourceGlobalInitScript(), IsWorkspaceLevel: true}, + "databricks_grant": {Resource: catalog.ResourceGrant(), IsWorkspaceLevel: true}, + "databricks_grants": {Resource: catalog.ResourceGrants(), IsWorkspaceLevel: true}, + "databricks_group": {Resource: scim.ResourceGroup(), IsWorkspaceLevel: true}, + "databricks_group_instance_profile": {Resource: aws.ResourceGroupInstanceProfile(), IsWorkspaceLevel: true}, + "databricks_group_member": {Resource: scim.ResourceGroupMember(), IsWorkspaceLevel: true}, + "databricks_group_role": {Resource: scim.ResourceGroupRole(), IsWorkspaceLevel: true}, + "databricks_instance_pool": {Resource: pools.ResourceInstancePool(), IsWorkspaceLevel: true}, + "databricks_instance_profile": {Resource: aws.ResourceInstanceProfile(), IsWorkspaceLevel: true}, + "databricks_ip_access_list": {Resource: access.ResourceIPAccessList(), IsWorkspaceLevel: true}, + "databricks_job": {Resource: jobs.ResourceJob(), IsWorkspaceLevel: true}, + "databricks_library": {Resource: clusters.ResourceLibrary(), IsWorkspaceLevel: true}, + "databricks_metastore": {Resource: catalog.ResourceMetastore(), IsWorkspaceLevel: true}, + "databricks_metastore_assignment": {Resource: catalog.ResourceMetastoreAssignment(), IsWorkspaceLevel: true}, + "databricks_metastore_data_access": {Resource: catalog.ResourceMetastoreDataAccess(), IsWorkspaceLevel: true}, + "databricks_mlflow_experiment": {Resource: mlflow.ResourceMlflowExperiment(), IsWorkspaceLevel: true}, + "databricks_mlflow_model": {Resource: mlflow.ResourceMlflowModel(), IsWorkspaceLevel: true}, + "databricks_mlflow_webhook": {Resource: mlflow.ResourceMlflowWebhook(), IsWorkspaceLevel: true}, + "databricks_model_serving": {Resource: serving.ResourceModelServing(), IsWorkspaceLevel: true}, + "databricks_mount": {Resource: storage.ResourceMount(), IsWorkspaceLevel: true}, + "databricks_mws_customer_managed_keys": {Resource: mws.ResourceMwsCustomerManagedKeys()}, + "databricks_mws_credentials": {Resource: mws.ResourceMwsCredentials()}, + "databricks_mws_log_delivery": {Resource: mws.ResourceMwsLogDelivery()}, + "databricks_mws_networks": {Resource: mws.ResourceMwsNetworks()}, + "databricks_mws_permission_assignment": {Resource: mws.ResourceMwsPermissionAssignment()}, + "databricks_mws_private_access_settings": {Resource: mws.ResourceMwsPrivateAccessSettings()}, + "databricks_mws_storage_configurations": {Resource: mws.ResourceMwsStorageConfigurations()}, + "databricks_mws_vpc_endpoint": {Resource: mws.ResourceMwsVpcEndpoint()}, + "databricks_mws_workspaces": {Resource: mws.ResourceMwsWorkspaces()}, + "databricks_notebook": {Resource: workspace.ResourceNotebook(), IsWorkspaceLevel: true}, + "databricks_obo_token": {Resource: tokens.ResourceOboToken(), IsWorkspaceLevel: true}, + "databricks_permission_assignment": {Resource: access.ResourcePermissionAssignment(), IsWorkspaceLevel: true}, + "databricks_permissions": {Resource: permissions.ResourcePermissions(), IsWorkspaceLevel: true}, + "databricks_pipeline": {Resource: pipelines.ResourcePipeline(), IsWorkspaceLevel: true}, + "databricks_provider": {Resource: catalog.ResourceProvider(), IsWorkspaceLevel: true}, + "databricks_recipient": {Resource: sharing.ResourceRecipient(), IsWorkspaceLevel: true}, + "databricks_registered_model": {Resource: catalog.ResourceRegisteredModel(), IsWorkspaceLevel: true}, + "databricks_repo": {Resource: repos.ResourceRepo(), IsWorkspaceLevel: true}, + "databricks_schema": {Resource: catalog.ResourceSchema(), IsWorkspaceLevel: true}, + "databricks_secret": {Resource: secrets.ResourceSecret(), IsWorkspaceLevel: true}, + "databricks_secret_scope": {Resource: secrets.ResourceSecretScope(), IsWorkspaceLevel: true}, + "databricks_secret_acl": {Resource: secrets.ResourceSecretACL(), IsWorkspaceLevel: true}, + "databricks_service_principal": {Resource: scim.ResourceServicePrincipal(), IsWorkspaceLevel: true}, + "databricks_service_principal_role": {Resource: aws.ResourceServicePrincipalRole(), IsWorkspaceLevel: true}, + "databricks_service_principal_secret": {Resource: tokens.ResourceServicePrincipalSecret(), IsWorkspaceLevel: true}, + "databricks_share": {Resource: catalog.ResourceShare(), IsWorkspaceLevel: true}, + "databricks_sql_dashboard": {Resource: sql.ResourceSqlDashboard(), IsWorkspaceLevel: true}, + "databricks_sql_endpoint": {Resource: sql.ResourceSqlEndpoint(), IsWorkspaceLevel: true}, + "databricks_sql_global_config": {Resource: sql.ResourceSqlGlobalConfig(), IsWorkspaceLevel: true}, + "databricks_sql_permissions": {Resource: access.ResourceSqlPermissions(), IsWorkspaceLevel: true}, + "databricks_sql_query": {Resource: sql.ResourceSqlQuery(), IsWorkspaceLevel: true}, + "databricks_sql_alert": {Resource: sql.ResourceSqlAlert(), IsWorkspaceLevel: true}, + "databricks_sql_table": {Resource: catalog.ResourceSqlTable(), IsWorkspaceLevel: true}, + "databricks_sql_visualization": {Resource: sql.ResourceSqlVisualization(), IsWorkspaceLevel: true}, + "databricks_sql_widget": {Resource: sql.ResourceSqlWidget(), IsWorkspaceLevel: true}, + "databricks_storage_credential": {Resource: catalog.ResourceStorageCredential(), IsWorkspaceLevel: true}, + "databricks_system_schema": {Resource: catalog.ResourceSystemSchema(), IsWorkspaceLevel: true}, + "databricks_table": {Resource: catalog.ResourceTable(), IsWorkspaceLevel: true}, + "databricks_token": {Resource: tokens.ResourceToken(), IsWorkspaceLevel: true}, + "databricks_user": {Resource: scim.ResourceUser(), IsWorkspaceLevel: true}, + "databricks_user_instance_profile": {Resource: aws.ResourceUserInstanceProfile(), IsWorkspaceLevel: true}, + "databricks_user_role": {Resource: aws.ResourceUserRole(), IsWorkspaceLevel: true}, + "databricks_volume": {Resource: catalog.ResourceVolume(), IsWorkspaceLevel: true}, + "databricks_workspace_conf": {Resource: workspace.ResourceWorkspaceConf(), IsWorkspaceLevel: true}, + "databricks_workspace_file": {Resource: workspace.ResourceWorkspaceFile(), IsWorkspaceLevel: true}, } for name, resource := range settings.AllSettingsResources() { - p.ResourcesMap[fmt.Sprintf("databricks_%s_setting", name)] = resource + resources[fmt.Sprintf("databricks_%s_setting", name)] = resource + } + + p := &schema.Provider{ + DataSourcesMap: map[string]*schema.Resource{}, + ResourcesMap: map[string]*schema.Resource{}, + Schema: providerSchema(), + } + for name, resource := range dataSources { + p.DataSourcesMap[name] = resource.Resource + if resource.IsWorkspaceLevel { + common.AddWorkspaceIdField(resource.Resource.Schema) + } + } + for name, resource := range resources { + p.ResourcesMap[name] = resource.Resource + if resource.IsWorkspaceLevel { + common.AddWorkspaceIdField(resource.Resource.Schema) + } } p.ConfigureContextFunc = func(ctx context.Context, d *schema.ResourceData) (any, diag.Diagnostics) { if p.TerraformVersion != "" { diff --git a/settings/all_settings.go b/settings/all_settings.go index e424760a19..70e4320a8a 100644 --- a/settings/all_settings.go +++ b/settings/all_settings.go @@ -3,7 +3,7 @@ package settings import ( "github.com/databricks/databricks-sdk-go" "github.com/databricks/databricks-sdk-go/service/settings" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/databricks/terraform-provider-databricks/common" ) // Instructions for adding a new setting: @@ -13,8 +13,11 @@ import ( // If the setting name is user-settable, it will be provided in the third argument to the updateFunc method. If not, you must set the // SettingName field appropriately. You must also set AllowMissing: true and the field mask to the field to update. // 3. Add a new entry to the AllSettingsResources map below. The final resource name will be "databricks__setting". -func AllSettingsResources() map[string]*schema.Resource { - return map[string]*schema.Resource{ - "default_namespace": makeSettingResource[settings.DefaultNamespaceSetting, *databricks.WorkspaceClient](defaultNamespaceSetting), +func AllSettingsResources() map[string]common.DatabricksTerraformResource { + return map[string]common.DatabricksTerraformResource{ + "default_namespace": { + Resource: makeSettingResource[settings.DefaultNamespaceSetting, *databricks.WorkspaceClient](defaultNamespaceSetting), + IsWorkspaceLevel: true, + }, } } diff --git a/settings/generic_setting_test.go b/settings/generic_setting_test.go index 4a273c90c0..e5644cf5a0 100644 --- a/settings/generic_setting_test.go +++ b/settings/generic_setting_test.go @@ -12,7 +12,7 @@ import ( ) // Choose an arbitrary setting to test. -var testSetting = AllSettingsResources()["default_namespace"] +var testSetting = AllSettingsResources()["default_namespace"].Resource func TestQueryCreateDefaultNameSetting(t *testing.T) { d, err := qa.ResourceFixture{ From 3a1360b80fc2d0034ccfe1099bf9f4d143c52c5c Mon Sep 17 00:00:00 2001 From: Miles Yucht Date: Wed, 31 Jan 2024 21:50:21 +0100 Subject: [PATCH 3/8] Use common.Resource consistently throughout the provider --- access/resource_ip_access_list.go | 4 +- access/resource_permission_assignment.go | 4 +- access/resource_sql_permissions.go | 4 +- aws/data_aws_assume_role_policy.go | 10 +- aws/data_aws_bucket_policy.go | 10 +- aws/data_aws_crossaccount_policy.go | 10 +- aws/data_instance_profiles.go | 3 +- aws/resource_group_instance_profile.go | 2 +- aws/resource_instance_profile.go | 4 +- aws/resource_service_principal_role.go | 4 +- aws/resource_user_instance_profile.go | 2 +- aws/resource_user_role.go | 3 +- catalog/data_catalogs.go | 3 +- catalog/data_current_metastore.go | 3 +- catalog/data_metastore.go | 3 +- catalog/data_metastores.go | 3 +- catalog/data_schemas.go | 3 +- catalog/data_share.go | 3 +- catalog/data_shares.go | 3 +- catalog/data_tables.go | 3 +- catalog/data_views.go | 3 +- catalog/resource_artifact_allowlist.go | 4 +- catalog/resource_catalog.go | 4 +- catalog/resource_catalog_workspace_binding.go | 4 +- catalog/resource_connection.go | 4 +- catalog/resource_external_location.go | 4 +- catalog/resource_grant.go | 4 +- catalog/resource_grants.go | 4 +- catalog/resource_metastore.go | 4 +- catalog/resource_metastore_assignment.go | 4 +- catalog/resource_metastore_data_access.go | 4 +- catalog/resource_provider.go | 4 +- catalog/resource_registered_model.go | 4 +- catalog/resource_schema.go | 4 +- catalog/resource_share.go | 4 +- catalog/resource_sql_table.go | 4 +- catalog/resource_storage_credential.go | 4 +- catalog/resource_system_schema.go | 4 +- catalog/resource_table.go | 4 +- catalog/resource_volume.go | 4 +- clusters/data_cluster.go | 3 +- clusters/data_clusters.go | 10 +- clusters/data_clusters_test.go | 3 +- clusters/data_node_type.go | 3 +- clusters/data_spark_version.go | 9 +- clusters/data_zones.go | 10 +- clusters/resource_cluster.go | 4 +- clusters/resource_library.go | 4 +- common/pair.go | 4 +- common/pair_test.go | 2 +- common/reflect_resource.go | 4 +- common/reflect_resource_test.go | 6 +- common/resource.go | 67 ++--- exporter/importables_test.go | 54 ++-- jobs/data_job.go | 3 +- jobs/data_jobs.go | 3 +- jobs/resource_job.go | 4 +- mlflow/data_mlflow_model.go | 3 +- mlflow/resource_mlflow_experiment.go | 4 +- mlflow/resource_mlflow_model.go | 4 +- mlflow/resource_mlflow_webhook.go | 4 +- mws/data_current_config.go | 3 +- mws/data_mws_credentials.go | 3 +- mws/data_mws_workspaces.go | 3 +- mws/resource_mws_credentials.go | 4 +- mws/resource_mws_customer_managed_keys.go | 4 +- mws/resource_mws_log_delivery.go | 4 +- mws/resource_mws_networks.go | 4 +- mws/resource_mws_permission_assignment.go | 4 +- mws/resource_mws_private_access_settings.go | 4 +- mws/resource_mws_storage_configurations.go | 4 +- mws/resource_mws_vpc_endpoint.go | 4 +- mws/resource_mws_workspaces.go | 4 +- mws/resource_mws_workspaces_test.go | 8 +- .../resource_access_control_rule_set.go | 4 +- permissions/resource_permissions.go | 4 +- permissions/resource_permissions_test.go | 15 +- pipelines/data_pipelines.go | 3 +- pipelines/resource_pipeline.go | 4 +- policies/data_cluster_policy.go | 3 +- policies/resource_cluster_policy.go | 4 +- pools/data_instance_pool.go | 11 +- pools/resource_instance_pool.go | 4 +- provider/provider.go | 242 +++++++++--------- qa/testing.go | 42 +-- qa/testing_test.go | 26 +- repos/resource_git_credential.go | 4 +- repos/resource_repo.go | 4 +- scim/data_current_user.go | 12 +- scim/data_group.go | 13 +- scim/data_service_principal.go | 3 +- scim/data_service_principals.go | 3 +- scim/data_user.go | 10 +- scim/resource_entitlement.go | 4 +- scim/resource_group.go | 4 +- scim/resource_group_member.go | 4 +- scim/resource_group_role.go | 3 +- scim/resource_group_test.go | 4 +- scim/resource_service_principal.go | 4 +- scim/resource_service_principal_test.go | 8 +- scim/resource_user.go | 4 +- scim/resource_user_test.go | 10 +- secrets/resource_secret.go | 4 +- secrets/resource_secret_acl.go | 4 +- secrets/resource_secret_scope.go | 4 +- serving/resource_model_serving.go | 4 +- settings/all_settings.go | 6 +- settings/generic_setting.go | 4 +- sharing/resource_recipient.go | 4 +- sql/data_sql_warehouse.go | 3 +- sql/data_sql_warehouses.go | 3 +- sql/resource_sql_alerts.go | 4 +- sql/resource_sql_dashboard.go | 4 +- sql/resource_sql_endpoint.go | 4 +- sql/resource_sql_global_config.go | 4 +- sql/resource_sql_query.go | 4 +- sql/resource_sql_visualization.go | 4 +- sql/resource_sql_widget.go | 4 +- storage/adls_gen1_mount.go | 4 +- storage/adls_gen2_mount.go | 4 +- storage/aws_s3_mount.go | 17 +- storage/azure_blob_mount.go | 4 +- storage/data_dbfs_file.go | 15 +- storage/data_dbfs_file_paths.go | 10 +- storage/gs_test.go | 6 +- storage/mounts.go | 58 +++-- storage/mounts_test.go | 22 +- storage/resource_dbfs_file.go | 4 +- storage/resource_mount.go | 31 ++- storage/s3_test.go | 4 +- tokens/resource_obo_token.go | 4 +- tokens/resource_service_principal_secret.go | 4 +- tokens/resource_token.go | 4 +- workspace/data_directory.go | 13 +- workspace/data_notebook.go | 13 +- workspace/data_notebook_paths.go | 10 +- workspace/resource_directory.go | 4 +- workspace/resource_global_init_script.go | 4 +- workspace/resource_notebook.go | 4 +- workspace/resource_notebook_test.go | 2 +- workspace/resource_workspace_conf.go | 4 +- workspace/resource_workspace_file.go | 4 +- 142 files changed, 585 insertions(+), 608 deletions(-) diff --git a/access/resource_ip_access_list.go b/access/resource_ip_access_list.go index 07c10d30b7..5b899ffd7a 100644 --- a/access/resource_ip_access_list.go +++ b/access/resource_ip_access_list.go @@ -18,7 +18,7 @@ type ipAccessListUpdateRequest struct { } // ResourceIPAccessList manages IP access lists -func ResourceIPAccessList() *schema.Resource { +func ResourceIPAccessList() common.Resource { s := common.StructToSchema(ipAccessListUpdateRequest{}, func(s map[string]*schema.Schema) map[string]*schema.Schema { // nolint s["list_type"].ValidateFunc = validation.StringInSlice([]string{"ALLOW", "BLOCK"}, false) @@ -73,5 +73,5 @@ func ResourceIPAccessList() *schema.Resource { } return w.IpAccessLists.DeleteByIpAccessListId(ctx, d.Id()) }, - }.ToResource() + } } diff --git a/access/resource_permission_assignment.go b/access/resource_permission_assignment.go index 546a344844..9456b02d80 100644 --- a/access/resource_permission_assignment.go +++ b/access/resource_permission_assignment.go @@ -76,7 +76,7 @@ func mustInt64(s string) int64 { // ResourcePermissionAssignment performs of users to a workspace // from a workspace context, though it requires additional set // data resource for "workspace account scim", whicl will be added later. -func ResourcePermissionAssignment() *schema.Resource { +func ResourcePermissionAssignment() common.Resource { type entity struct { PrincipalId int64 `json:"principal_id"` Permissions []string `json:"permissions" tf:"slice_as_set"` @@ -113,5 +113,5 @@ func ResourcePermissionAssignment() *schema.Resource { Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { return NewPermissionAssignmentAPI(ctx, c).Remove(d.Id()) }, - }.ToResource() + } } diff --git a/access/resource_sql_permissions.go b/access/resource_sql_permissions.go index 6c48977036..d0f601e1bc 100644 --- a/access/resource_sql_permissions.go +++ b/access/resource_sql_permissions.go @@ -316,7 +316,7 @@ func tableAclForLoad(ctx context.Context, d *schema.ResourceData, } // ResourceSqlPermissions manages table ACLs -func ResourceSqlPermissions() *schema.Resource { +func ResourceSqlPermissions() common.Resource { s := common.StructToSchema(SqlPermissions{}, func(s map[string]*schema.Schema) map[string]*schema.Schema { alof := []string{"database", "table", "view", "catalog", "any_file", "anonymous_function"} for _, field := range alof { @@ -376,5 +376,5 @@ func ResourceSqlPermissions() *schema.Resource { } return ta.revoke() }, - }.ToResource() + } } diff --git a/aws/data_aws_assume_role_policy.go b/aws/data_aws_assume_role_policy.go index e2f1a50f16..576321d819 100644 --- a/aws/data_aws_assume_role_policy.go +++ b/aws/data_aws_assume_role_policy.go @@ -5,7 +5,7 @@ import ( "encoding/json" "fmt" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/databricks/terraform-provider-databricks/common" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -27,9 +27,9 @@ type awsIamPolicyStatement struct { } // DataAwsAssumeRolePolicy ... -func DataAwsAssumeRolePolicy() *schema.Resource { - return &schema.Resource{ - ReadContext: func(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { +func DataAwsAssumeRolePolicy() common.Resource { + return common.Resource{ + Read: func(ctx context.Context, d *schema.ResourceData, m *common.DatabricksClient) error { externalID := d.Get("external_id").(string) policy := awsIamPolicy{ Version: "2012-10-17", @@ -57,7 +57,7 @@ func DataAwsAssumeRolePolicy() *schema.Resource { } policyJSON, err := json.MarshalIndent(policy, "", " ") if err != nil { - return diag.FromErr(err) + return err } d.SetId(externalID) // nolint diff --git a/aws/data_aws_bucket_policy.go b/aws/data_aws_bucket_policy.go index 2d65761747..b1cc42a8f4 100644 --- a/aws/data_aws_bucket_policy.go +++ b/aws/data_aws_bucket_policy.go @@ -6,15 +6,15 @@ import ( "fmt" "regexp" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/databricks/terraform-provider-databricks/common" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) // DataAwsBucketPolicy ... -func DataAwsBucketPolicy() *schema.Resource { - return &schema.Resource{ - ReadContext: func(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { +func DataAwsBucketPolicy() common.Resource { + return common.Resource{ + Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { bucket := d.Get("bucket").(string) policy := awsIamPolicy{ Version: "2012-10-17", @@ -52,7 +52,7 @@ func DataAwsBucketPolicy() *schema.Resource { } policyJSON, err := json.MarshalIndent(policy, "", " ") if err != nil { - return diag.FromErr(err) + return err } d.SetId(bucket) // nolint diff --git a/aws/data_aws_crossaccount_policy.go b/aws/data_aws_crossaccount_policy.go index aa28e2e474..8275aecdb3 100644 --- a/aws/data_aws_crossaccount_policy.go +++ b/aws/data_aws_crossaccount_policy.go @@ -4,14 +4,14 @@ import ( "context" "encoding/json" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/databricks/terraform-provider-databricks/common" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) // DataAwsCrossaccountPolicy defines the cross-account policy -func DataAwsCrossaccountPolicy() *schema.Resource { - return &schema.Resource{ - ReadContext: func(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { +func DataAwsCrossaccountPolicy() common.Resource { + return common.Resource{ + Read: func(ctx context.Context, d *schema.ResourceData, m *common.DatabricksClient) error { policy := awsIamPolicy{ Version: "2012-10-17", Statements: []*awsIamPolicyStatement{ @@ -126,7 +126,7 @@ func DataAwsCrossaccountPolicy() *schema.Resource { } policyJSON, err := json.MarshalIndent(policy, "", " ") if err != nil { - return diag.FromErr(err) + return err } d.SetId("cross-account") // nolint diff --git a/aws/data_instance_profiles.go b/aws/data_instance_profiles.go index 8544116d54..0679a4564a 100644 --- a/aws/data_instance_profiles.go +++ b/aws/data_instance_profiles.go @@ -6,10 +6,9 @@ import ( "github.com/databricks/databricks-sdk-go" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func DataSourceInstanceProfiles() *schema.Resource { +func DataSourceInstanceProfiles() common.Resource { type instanceProfileData struct { Name string `json:"name,omitempty" tf:"computed"` Arn string `json:"arn,omitempty" tf:"computed"` diff --git a/aws/resource_group_instance_profile.go b/aws/resource_group_instance_profile.go index 9e06a36e0e..3ac81f3fa8 100644 --- a/aws/resource_group_instance_profile.go +++ b/aws/resource_group_instance_profile.go @@ -12,7 +12,7 @@ import ( ) // ResourceGroupInstanceProfile defines group role resource -func ResourceGroupInstanceProfile() *schema.Resource { +func ResourceGroupInstanceProfile() common.Resource { r := common.NewPairID("group_id", "instance_profile_id").Schema(func( m map[string]*schema.Schema) map[string]*schema.Schema { m["instance_profile_id"].ValidateDiagFunc = ValidArn diff --git a/aws/resource_instance_profile.go b/aws/resource_instance_profile.go index fe92528785..04ba23b0a5 100644 --- a/aws/resource_instance_profile.go +++ b/aws/resource_instance_profile.go @@ -142,7 +142,7 @@ func (a InstanceProfilesAPI) Synchronized(arn string, testCallback func() bool) } // ResourceInstanceProfile manages Instance Profile ARN binding -func ResourceInstanceProfile() *schema.Resource { +func ResourceInstanceProfile() common.Resource { instanceProfileSchema := common.StructToSchema(InstanceProfileInfo{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { m["instance_profile_arn"].ValidateDiagFunc = ValidArn @@ -181,7 +181,7 @@ func ResourceInstanceProfile() *schema.Resource { common.DataToStructPointer(d, instanceProfileSchema, &profile) return NewInstanceProfilesAPI(ctx, c).Update(profile) }, - }.ToResource() + } } // ValidArn validate if it's valid instance profile or role ARN diff --git a/aws/resource_service_principal_role.go b/aws/resource_service_principal_role.go index 7dedb24909..444c8b11c3 100644 --- a/aws/resource_service_principal_role.go +++ b/aws/resource_service_principal_role.go @@ -7,12 +7,10 @@ import ( "github.com/databricks/databricks-sdk-go/apierr" "github.com/databricks/terraform-provider-databricks/common" "github.com/databricks/terraform-provider-databricks/scim" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) // ResourceServicePrincipalRole binds service principal and instance profile -func ResourceServicePrincipalRole() *schema.Resource { +func ResourceServicePrincipalRole() common.Resource { r := common.NewPairID("service_principal_id", "role").BindResource(common.BindResource{ CreateContext: func(ctx context.Context, servicePrincipalID, role string, c *common.DatabricksClient) error { return scim.NewServicePrincipalsAPI(ctx, c).Patch(servicePrincipalID, scim.PatchRequest("add", "roles", role)) diff --git a/aws/resource_user_instance_profile.go b/aws/resource_user_instance_profile.go index b316dfd02c..e7516ef61b 100644 --- a/aws/resource_user_instance_profile.go +++ b/aws/resource_user_instance_profile.go @@ -12,7 +12,7 @@ import ( ) // ResourceUserInstanceProfile binds user and instance profile -func ResourceUserInstanceProfile() *schema.Resource { +func ResourceUserInstanceProfile() common.Resource { r := common.NewPairID("user_id", "instance_profile_id").Schema(func( m map[string]*schema.Schema) map[string]*schema.Schema { m["instance_profile_id"].ValidateDiagFunc = ValidArn diff --git a/aws/resource_user_role.go b/aws/resource_user_role.go index ef65f0612e..e0c31e62d9 100644 --- a/aws/resource_user_role.go +++ b/aws/resource_user_role.go @@ -7,10 +7,9 @@ import ( "github.com/databricks/databricks-sdk-go/apierr" "github.com/databricks/terraform-provider-databricks/common" "github.com/databricks/terraform-provider-databricks/scim" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func ResourceUserRole() *schema.Resource { +func ResourceUserRole() common.Resource { return common.NewPairID("user_id", "role").BindResource(common.BindResource{ CreateContext: func(ctx context.Context, userID, role string, c *common.DatabricksClient) error { return scim.NewUsersAPI(ctx, c).Patch(userID, scim.PatchRequest("add", "roles", role)) diff --git a/catalog/data_catalogs.go b/catalog/data_catalogs.go index cfbb663ad8..a2d7312481 100644 --- a/catalog/data_catalogs.go +++ b/catalog/data_catalogs.go @@ -5,10 +5,9 @@ import ( "github.com/databricks/databricks-sdk-go" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func DataSourceCatalogs() *schema.Resource { +func DataSourceCatalogs() common.Resource { return common.WorkspaceData(func(ctx context.Context, data *struct { Ids []string `json:"ids,omitempty" tf:"computed,slice_set"` }, w *databricks.WorkspaceClient) error { diff --git a/catalog/data_current_metastore.go b/catalog/data_current_metastore.go index 023bf472b8..9c52f62c3c 100644 --- a/catalog/data_current_metastore.go +++ b/catalog/data_current_metastore.go @@ -6,10 +6,9 @@ import ( "github.com/databricks/databricks-sdk-go" "github.com/databricks/databricks-sdk-go/service/catalog" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func DataSourceCurrentMetastore() *schema.Resource { +func DataSourceCurrentMetastore() common.Resource { type CurrentMetastore struct { Id string `json:"id,omitempty" tf:"computed"` Metastore *catalog.GetMetastoreSummaryResponse `json:"metastore_info,omitempty" tf:"computed" ` diff --git a/catalog/data_metastore.go b/catalog/data_metastore.go index 1bd5425b7f..6c7f3842e3 100644 --- a/catalog/data_metastore.go +++ b/catalog/data_metastore.go @@ -6,10 +6,9 @@ import ( "github.com/databricks/databricks-sdk-go" "github.com/databricks/databricks-sdk-go/service/catalog" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func DataSourceMetastore() *schema.Resource { +func DataSourceMetastore() common.Resource { type AccountMetastoreByID struct { Id string `json:"metastore_id"` Metastore *catalog.MetastoreInfo `json:"metastore_info,omitempty" tf:"computed" ` diff --git a/catalog/data_metastores.go b/catalog/data_metastores.go index 5ac6165aba..f6fe312972 100644 --- a/catalog/data_metastores.go +++ b/catalog/data_metastores.go @@ -6,10 +6,9 @@ import ( "github.com/databricks/databricks-sdk-go" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func DataSourceMetastores() *schema.Resource { +func DataSourceMetastores() common.Resource { type metastoresData struct { Ids map[string]string `json:"ids,omitempty" tf:"computed"` } diff --git a/catalog/data_schemas.go b/catalog/data_schemas.go index 5fa1b0e40a..73a2ded5b0 100644 --- a/catalog/data_schemas.go +++ b/catalog/data_schemas.go @@ -6,10 +6,9 @@ import ( "github.com/databricks/databricks-sdk-go" "github.com/databricks/databricks-sdk-go/service/catalog" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func DataSourceSchemas() *schema.Resource { +func DataSourceSchemas() common.Resource { return common.WorkspaceData(func(ctx context.Context, data *struct { CatalogName string `json:"catalog_name"` Ids []string `json:"ids,omitempty" tf:"computed,slice_set"` diff --git a/catalog/data_share.go b/catalog/data_share.go index 494d4ff8e9..1b0d5d5b58 100644 --- a/catalog/data_share.go +++ b/catalog/data_share.go @@ -4,10 +4,9 @@ import ( "context" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func DataSourceShare() *schema.Resource { +func DataSourceShare() common.Resource { type ShareDetail struct { Name string `json:"name,omitempty" tf:"computed"` Objects []SharedDataObject `json:"objects,omitempty" tf:"computed,slice_set,alias:object"` diff --git a/catalog/data_shares.go b/catalog/data_shares.go index 6f0a3299d2..97f6787e4b 100644 --- a/catalog/data_shares.go +++ b/catalog/data_shares.go @@ -5,10 +5,9 @@ import ( "github.com/databricks/databricks-sdk-go" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func DataSourceShares() *schema.Resource { +func DataSourceShares() common.Resource { return common.WorkspaceData(func(ctx context.Context, data *struct { Shares []string `json:"shares,omitempty" tf:"computed,slice_set"` }, w *databricks.WorkspaceClient) error { diff --git a/catalog/data_tables.go b/catalog/data_tables.go index 0387a642cb..e1aca33cd4 100644 --- a/catalog/data_tables.go +++ b/catalog/data_tables.go @@ -6,10 +6,9 @@ import ( "github.com/databricks/databricks-sdk-go" "github.com/databricks/databricks-sdk-go/service/catalog" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func DataSourceTables() *schema.Resource { +func DataSourceTables() common.Resource { return common.WorkspaceData(func(ctx context.Context, data *struct { CatalogName string `json:"catalog_name"` SchemaName string `json:"schema_name"` diff --git a/catalog/data_views.go b/catalog/data_views.go index f02d5184f5..b4e4255c83 100644 --- a/catalog/data_views.go +++ b/catalog/data_views.go @@ -6,10 +6,9 @@ import ( "github.com/databricks/databricks-sdk-go" "github.com/databricks/databricks-sdk-go/service/catalog" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func DataSourceViews() *schema.Resource { +func DataSourceViews() common.Resource { return common.WorkspaceData(func(ctx context.Context, data *struct { CatalogName string `json:"catalog_name"` SchemaName string `json:"schema_name"` diff --git a/catalog/resource_artifact_allowlist.go b/catalog/resource_artifact_allowlist.go index 9dcdb36c63..9ce2e10467 100644 --- a/catalog/resource_artifact_allowlist.go +++ b/catalog/resource_artifact_allowlist.go @@ -21,7 +21,7 @@ type ArtifactAllowlistInfo struct { MetastoreId string `json:"metastore_id,omitempty" tf:"computed"` } -func ResourceArtifactAllowlist() *schema.Resource { +func ResourceArtifactAllowlist() common.Resource { allowlistSchema := common.StructToSchema(ArtifactAllowlistInfo{}, common.NoCustomize) p := common.NewPairID("metastore_id", "artifact_type") @@ -107,5 +107,5 @@ func ResourceArtifactAllowlist() *schema.Resource { return nil }, - }.ToResource() + } } diff --git a/catalog/resource_catalog.go b/catalog/resource_catalog.go index b7affc2db2..ddb113a16c 100644 --- a/catalog/resource_catalog.go +++ b/catalog/resource_catalog.go @@ -40,7 +40,7 @@ type CatalogInfo struct { MetastoreID string `json:"metastore_id,omitempty" tf:"computed"` } -func ResourceCatalog() *schema.Resource { +func ResourceCatalog() common.Resource { catalogSchema := common.StructToSchema(CatalogInfo{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { m["force_destroy"] = &schema.Schema{ @@ -219,5 +219,5 @@ func ResourceCatalog() *schema.Resource { } return w.Catalogs.Delete(ctx, catalog.DeleteCatalogRequest{Force: force, Name: d.Id()}) }, - }.ToResource() + } } diff --git a/catalog/resource_catalog_workspace_binding.go b/catalog/resource_catalog_workspace_binding.go index f262f5fb46..19cbbe25ef 100644 --- a/catalog/resource_catalog_workspace_binding.go +++ b/catalog/resource_catalog_workspace_binding.go @@ -21,7 +21,7 @@ var getSecurableName = func(d *schema.ResourceData) string { return securableName.(string) } -func ResourceCatalogWorkspaceBinding() *schema.Resource { +func ResourceCatalogWorkspaceBinding() common.Resource { workspaceBindingSchema := common.StructToSchema(catalog.WorkspaceBinding{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { m["catalog_name"] = &schema.Schema{ @@ -109,7 +109,7 @@ func ResourceCatalogWorkspaceBinding() *schema.Resource { }) return err }, - }.ToResource() + } } // migrate to v1 state, as catalog_name is moved to securable_name diff --git a/catalog/resource_connection.go b/catalog/resource_connection.go index 3f556f1631..498cf177ff 100644 --- a/catalog/resource_connection.go +++ b/catalog/resource_connection.go @@ -36,7 +36,7 @@ type ConnectionInfo struct { var sensitiveOptions = []string{"user", "password", "personalAccessToken", "access_token", "client_secret", "OAuthPvtKey", "GoogleServiceAccountKeyJson"} -func ResourceConnection() *schema.Resource { +func ResourceConnection() common.Resource { s := common.StructToSchema(ConnectionInfo{}, common.NoCustomize) pi := common.NewPairID("metastore_id", "name").Schema( @@ -156,5 +156,5 @@ func ResourceConnection() *schema.Resource { } return w.Connections.DeleteByNameArg(ctx, connName) }, - }.ToResource() + } } diff --git a/catalog/resource_external_location.go b/catalog/resource_external_location.go index dcaf85a674..f992349f97 100644 --- a/catalog/resource_external_location.go +++ b/catalog/resource_external_location.go @@ -22,7 +22,7 @@ type ExternalLocationInfo struct { EncDetails *catalog.EncryptionDetails `json:"encryption_details,omitempty"` } -func ResourceExternalLocation() *schema.Resource { +func ResourceExternalLocation() common.Resource { s := common.StructToSchema(ExternalLocationInfo{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { m["force_destroy"] = &schema.Schema{ @@ -141,5 +141,5 @@ func ResourceExternalLocation() *schema.Resource { Force: force, }) }, - }.ToResource() + } } diff --git a/catalog/resource_grant.go b/catalog/resource_grant.go index 491e44c39a..78bf5f1bb5 100644 --- a/catalog/resource_grant.go +++ b/catalog/resource_grant.go @@ -119,7 +119,7 @@ func parseSecurableId(d *schema.ResourceData) (string, string, string, error) { return split[0], split[1], split[2], nil } -func ResourceGrant() *schema.Resource { +func ResourceGrant() common.Resource { s := common.StructToSchema(permissions.UnityCatalogPrivilegeAssignment{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { @@ -227,5 +227,5 @@ func ResourceGrant() *schema.Resource { unityCatalogPermissionsAPI := permissions.NewUnityCatalogPermissionsAPI(ctx, c) return replacePermissionsForPrincipal(unityCatalogPermissionsAPI, securable, name, principal, catalog.PermissionsList{}) }, - }.ToResource() + } } diff --git a/catalog/resource_grants.go b/catalog/resource_grants.go index ef0b2ee335..829c0a5ca3 100644 --- a/catalog/resource_grants.go +++ b/catalog/resource_grants.go @@ -290,7 +290,7 @@ func parseId(d *schema.ResourceData) (string, string, error) { return split[0], split[1], nil } -func ResourceGrants() *schema.Resource { +func ResourceGrants() common.Resource { s := common.StructToSchema(PermissionsList{}, func(s map[string]*schema.Schema) map[string]*schema.Schema { alof := []string{} @@ -387,5 +387,5 @@ func ResourceGrants() *schema.Resource { unityCatalogPermissionsAPI := permissions.NewUnityCatalogPermissionsAPI(ctx, c) return replaceAllPermissions(unityCatalogPermissionsAPI, securable, name, catalog.PermissionsList{}) }, - }.ToResource() + } } diff --git a/catalog/resource_metastore.go b/catalog/resource_metastore.go index c45dfee673..66ccf8b620 100644 --- a/catalog/resource_metastore.go +++ b/catalog/resource_metastore.go @@ -38,7 +38,7 @@ func updateForceSendFields(req *catalog.UpdateMetastore) { } } -func ResourceMetastore() *schema.Resource { +func ResourceMetastore() common.Resource { s := common.StructToSchema(MetastoreInfo{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { m["force_destroy"] = &schema.Schema{ @@ -198,5 +198,5 @@ func ResourceMetastore() *schema.Resource { return w.Metastores.Delete(ctx, catalog.DeleteMetastoreRequest{Force: force, Id: d.Id()}) }) }, - }.ToResource() + } } diff --git a/catalog/resource_metastore_assignment.go b/catalog/resource_metastore_assignment.go index 6c808b56b4..9f8d48a2af 100644 --- a/catalog/resource_metastore_assignment.go +++ b/catalog/resource_metastore_assignment.go @@ -10,7 +10,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func ResourceMetastoreAssignment() *schema.Resource { +func ResourceMetastoreAssignment() common.Resource { s := common.StructToSchema(catalog.MetastoreAssignment{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { m["default_catalog_name"].Default = "hive_metastore" @@ -115,5 +115,5 @@ func ResourceMetastoreAssignment() *schema.Resource { }) }) }, - }.ToResource() + } } diff --git a/catalog/resource_metastore_data_access.go b/catalog/resource_metastore_data_access.go index 9fdb1087d0..4f1ef6e4dd 100644 --- a/catalog/resource_metastore_data_access.go +++ b/catalog/resource_metastore_data_access.go @@ -73,7 +73,7 @@ var dacSchema = common.StructToSchema(StorageCredentialInfo{}, return adjustDataAccessSchema(m) }) -func ResourceMetastoreDataAccess() *schema.Resource { +func ResourceMetastoreDataAccess() common.Resource { p := common.NewPairID("metastore_id", "name") return common.Resource{ Schema: dacSchema, @@ -194,7 +194,7 @@ func ResourceMetastoreDataAccess() *schema.Resource { }) }) }, - }.ToResource() + } } // migrate to v1 state, as the id is now changed diff --git a/catalog/resource_provider.go b/catalog/resource_provider.go index 3a1f3f59fb..132d9fefb9 100644 --- a/catalog/resource_provider.go +++ b/catalog/resource_provider.go @@ -50,7 +50,7 @@ func (a ProvidersAPI) updateProvider(ci *ProviderInfo) error { return a.client.Patch(a.context, "/unity-catalog/providers/"+ci.Name, patch) } -func ResourceProvider() *schema.Resource { +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) return m @@ -87,5 +87,5 @@ func ResourceProvider() *schema.Resource { Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { return NewProvidersAPI(ctx, c).deleteProvider(d.Id()) }, - }.ToResource() + } } diff --git a/catalog/resource_registered_model.go b/catalog/resource_registered_model.go index 99e3a67531..644850c706 100644 --- a/catalog/resource_registered_model.go +++ b/catalog/resource_registered_model.go @@ -8,7 +8,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func ResourceRegisteredModel() *schema.Resource { +func ResourceRegisteredModel() common.Resource { s := common.StructToSchema( catalog.CreateRegisteredModelRequest{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { @@ -68,5 +68,5 @@ func ResourceRegisteredModel() *schema.Resource { StateUpgraders: []schema.StateUpgrader{}, Schema: s, SchemaVersion: 0, - }.ToResource() + } } diff --git a/catalog/resource_schema.go b/catalog/resource_schema.go index f3cf93832c..0423c5ac4c 100644 --- a/catalog/resource_schema.go +++ b/catalog/resource_schema.go @@ -20,7 +20,7 @@ type SchemaInfo struct { FullName string `json:"full_name,omitempty" tf:"computed"` } -func ResourceSchema() *schema.Resource { +func ResourceSchema() common.Resource { s := common.StructToSchema(SchemaInfo{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { delete(m, "full_name") @@ -179,5 +179,5 @@ func ResourceSchema() *schema.Resource { } return w.Schemas.DeleteByFullName(ctx, name) }, - }.ToResource() + } } diff --git a/catalog/resource_share.go b/catalog/resource_share.go index 8cd209a919..0f7e4fe35d 100644 --- a/catalog/resource_share.go +++ b/catalog/resource_share.go @@ -173,7 +173,7 @@ func (beforeSi ShareInfo) Diff(afterSi ShareInfo) []ShareDataChange { return changes } -func ResourceShare() *schema.Resource { +func ResourceShare() common.Resource { shareSchema := common.StructToSchema(ShareInfo{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { return m }) @@ -263,5 +263,5 @@ func ResourceShare() *schema.Resource { } return w.Shares.DeleteByName(ctx, d.Id()) }, - }.ToResource() + } } diff --git a/catalog/resource_sql_table.go b/catalog/resource_sql_table.go index 7edba49fcd..ab7ef90fa1 100644 --- a/catalog/resource_sql_table.go +++ b/catalog/resource_sql_table.go @@ -384,7 +384,7 @@ func (ti *SqlTableInfo) applySql(sqlQuery string) error { return nil } -func ResourceSqlTable() *schema.Resource { +func ResourceSqlTable() common.Resource { tableSchema := common.StructToSchema(SqlTableInfo{}, func(s map[string]*schema.Schema) map[string]*schema.Schema { s["data_source_format"].DiffSuppressFunc = func(k, old, new string, d *schema.ResourceData) bool { @@ -471,5 +471,5 @@ func ResourceSqlTable() *schema.Resource { } return ti.deleteTable() }, - }.ToResource() + } } diff --git a/catalog/resource_storage_credential.go b/catalog/resource_storage_credential.go index 02c71e1f5f..f68a55ed3d 100644 --- a/catalog/resource_storage_credential.go +++ b/catalog/resource_storage_credential.go @@ -38,7 +38,7 @@ var storageCredentialSchema = common.StructToSchema(StorageCredentialInfo{}, return adjustDataAccessSchema(m) }) -func ResourceStorageCredential() *schema.Resource { +func ResourceStorageCredential() common.Resource { return common.Resource{ Schema: storageCredentialSchema, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { @@ -229,5 +229,5 @@ func ResourceStorageCredential() *schema.Resource { }) }) }, - }.ToResource() + } } diff --git a/catalog/resource_system_schema.go b/catalog/resource_system_schema.go index 9d0e9b3be1..1da5b3e682 100644 --- a/catalog/resource_system_schema.go +++ b/catalog/resource_system_schema.go @@ -11,7 +11,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func ResourceSystemSchema() *schema.Resource { +func ResourceSystemSchema() common.Resource { systemSchema := common.StructToSchema(catalog.SystemSchemaInfo{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { m["metastore_id"] = &schema.Schema{ Type: schema.TypeString, @@ -109,5 +109,5 @@ func ResourceSystemSchema() *schema.Resource { SchemaName: catalog.DisableSchemaName(schemaName), }) }, - }.ToResource() + } } diff --git a/catalog/resource_table.go b/catalog/resource_table.go index 6f41dd38db..36b4a9f5e1 100644 --- a/catalog/resource_table.go +++ b/catalog/resource_table.go @@ -63,7 +63,7 @@ func (a TablesAPI) deleteTable(name string) error { return a.client.Delete(a.context, "/unity-catalog/tables/"+name, nil) } -func ResourceTable() *schema.Resource { +func ResourceTable() common.Resource { tableSchema := common.StructToSchema(TableInfo{}, common.NoCustomize) update := updateFunctionFactory("/unity-catalog/tables", []string{ @@ -97,5 +97,5 @@ func ResourceTable() *schema.Resource { Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { return NewTablesAPI(ctx, c).deleteTable(d.Id()) }, - }.ToResource() + } } diff --git a/catalog/resource_volume.go b/catalog/resource_volume.go index f4b6871684..64bfdbe540 100644 --- a/catalog/resource_volume.go +++ b/catalog/resource_volume.go @@ -28,7 +28,7 @@ type VolumeInfo struct { VolumeType catalog.VolumeType `json:"volume_type" tf:"force_new"` } -func ResourceVolume() *schema.Resource { +func ResourceVolume() common.Resource { s := common.StructToSchema(VolumeInfo{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { m["storage_location"].DiffSuppressFunc = ucDirectoryPathSlashAndEmptySuppressDiff @@ -122,5 +122,5 @@ func ResourceVolume() *schema.Resource { } return w.Volumes.DeleteByFullNameArg(ctx, d.Id()) }, - }.ToResource() + } } diff --git a/clusters/data_cluster.go b/clusters/data_cluster.go index ff8b8598a0..8a45b7afdf 100644 --- a/clusters/data_cluster.go +++ b/clusters/data_cluster.go @@ -5,10 +5,9 @@ import ( "fmt" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func DataSourceCluster() *schema.Resource { +func DataSourceCluster() common.Resource { type clusterData struct { Id string `json:"id,omitempty" tf:"computed"` ClusterId string `json:"cluster_id,omitempty" tf:"computed"` diff --git a/clusters/data_clusters.go b/clusters/data_clusters.go index f89aa64041..2628c4968d 100644 --- a/clusters/data_clusters.go +++ b/clusters/data_clusters.go @@ -4,16 +4,16 @@ import ( "context" "strings" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/databricks/terraform-provider-databricks/common" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func DataSourceClusters() *schema.Resource { - return &schema.Resource{ - ReadContext: func(ctx context.Context, d *schema.ResourceData, i any) diag.Diagnostics { +func DataSourceClusters() common.Resource { + return common.Resource{ + Read: func(ctx context.Context, d *schema.ResourceData, i *common.DatabricksClient) error { clusters, err := NewClustersAPI(ctx, i).List() if err != nil { - return diag.FromErr(err) + return err } ids := schema.NewSet(schema.HashString, []any{}) name_contains := strings.ToLower(d.Get("cluster_name_contains").(string)) diff --git a/clusters/data_clusters_test.go b/clusters/data_clusters_test.go index 5fb60ac7dc..9b549fa4ed 100644 --- a/clusters/data_clusters_test.go +++ b/clusters/data_clusters_test.go @@ -78,9 +78,8 @@ func TestClustersDataSourceErrorsOut(t *testing.T) { RetryTimeoutSeconds: 1, HTTPTimeoutSeconds: 1, }) - diag := DataSourceClusters().ReadContext(context.Background(), nil, &common.DatabricksClient{ + diag := DataSourceClusters().Read(context.Background(), nil, &common.DatabricksClient{ DatabricksClient: client, }) assert.NotNil(t, diag) - assert.True(t, diag.HasError()) } diff --git a/clusters/data_node_type.go b/clusters/data_node_type.go index dd72c758ca..9bd975f85f 100644 --- a/clusters/data_node_type.go +++ b/clusters/data_node_type.go @@ -6,7 +6,6 @@ import ( "github.com/databricks/databricks-sdk-go/service/compute" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/databricks/databricks-sdk-go" ) @@ -41,7 +40,7 @@ func (a ClustersAPI) GetSmallestNodeType(request compute.NodeTypeRequest) string } // DataSourceNodeType returns smallest node depedning on the cloud -func DataSourceNodeType() *schema.Resource { +func DataSourceNodeType() common.Resource { return common.WorkspaceData(func(ctx context.Context, data *compute.NodeTypeRequest, w *databricks.WorkspaceClient) error { data.Id = smallestNodeType(ctx, *data, w) log.Printf("[DEBUG] smallest node: %s", data.Id) diff --git a/clusters/data_spark_version.go b/clusters/data_spark_version.go index 60fa3140ed..3b58fd4634 100644 --- a/clusters/data_spark_version.go +++ b/clusters/data_spark_version.go @@ -8,7 +8,6 @@ import ( "strings" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "golang.org/x/mod/semver" ) @@ -125,7 +124,7 @@ func (a ClustersAPI) LatestSparkVersionOrDefault(svr SparkVersionRequest) string } // DataSourceSparkVersion returns DBR version matching to the specification -func DataSourceSparkVersion() *schema.Resource { +func DataSourceSparkVersion() common.Resource { s := common.StructToSchema(SparkVersionRequest{}, func( s map[string]*schema.Schema) map[string]*schema.Schema { @@ -134,14 +133,14 @@ func DataSourceSparkVersion() *schema.Resource { return s }) - return &schema.Resource{ + return common.Resource{ Schema: s, - ReadContext: func(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { + Read: func(ctx context.Context, d *schema.ResourceData, m *common.DatabricksClient) error { var this SparkVersionRequest common.DataToStructPointer(d, s, &this) version, err := NewClustersAPI(ctx, m).LatestSparkVersion(this) if err != nil { - return diag.FromErr(err) + return err } d.SetId(version) return nil diff --git a/clusters/data_zones.go b/clusters/data_zones.go index 001fbdb3d4..c10620ce90 100644 --- a/clusters/data_zones.go +++ b/clusters/data_zones.go @@ -3,17 +3,17 @@ package clusters import ( "context" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/databricks/terraform-provider-databricks/common" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) // DataSourceClusterZones ... -func DataSourceClusterZones() *schema.Resource { - return &schema.Resource{ - ReadContext: func(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { +func DataSourceClusterZones() common.Resource { + return common.Resource{ + Read: func(ctx context.Context, d *schema.ResourceData, m *common.DatabricksClient) error { zonesInfo, err := NewClustersAPI(ctx, m).ListZones() if err != nil { - return diag.FromErr(err) + return err } d.SetId(zonesInfo.DefaultZone) d.Set("default_zone", zonesInfo.DefaultZone) diff --git a/clusters/resource_cluster.go b/clusters/resource_cluster.go index f60e7b49e5..3450970415 100644 --- a/clusters/resource_cluster.go +++ b/clusters/resource_cluster.go @@ -21,7 +21,7 @@ const DbfsDeprecationWarning = "For init scripts use 'volumes', 'workspace' or c var clusterSchema = resourceClusterSchema() // ResourceCluster - returns Cluster resource description -func ResourceCluster() *schema.Resource { +func ResourceCluster() common.Resource { return common.Resource{ Create: resourceClusterCreate, Read: resourceClusterRead, @@ -37,7 +37,7 @@ func ResourceCluster() *schema.Resource { Update: schema.DefaultTimeout(DefaultProvisionTimeout), Delete: schema.DefaultTimeout(DefaultProvisionTimeout), }, - }.ToResource() + } } func SparkConfDiffSuppressFunc(k, old, new string, d *schema.ResourceData) bool { diff --git a/clusters/resource_library.go b/clusters/resource_library.go index 3cbea56b2f..23ed736102 100644 --- a/clusters/resource_library.go +++ b/clusters/resource_library.go @@ -12,7 +12,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func ResourceLibrary() *schema.Resource { +func ResourceLibrary() common.Resource { libraySdkSchema := common.StructToSchema(compute.Library{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { m["cluster_id"] = &schema.Schema{ Type: schema.TypeString, @@ -106,5 +106,5 @@ func ResourceLibrary() *schema.Resource { } return apierr.NotFound(fmt.Sprintf("cannot find %s on %s", libraryRep, clusterID)) }, - }.ToResource() + } } diff --git a/common/pair.go b/common/pair.go index 3fa0819fcf..b0edf8dcf3 100644 --- a/common/pair.go +++ b/common/pair.go @@ -88,7 +88,7 @@ type BindResource struct { } // BindResource creates resource that relies on binding ID pair with simple schema & importer -func (p *Pair) BindResource(pr BindResource) *schema.Resource { +func (p *Pair) BindResource(pr BindResource) Resource { return Resource{ Schema: p.schema, Read: func(ctx context.Context, d *schema.ResourceData, c *DatabricksClient) error { @@ -121,5 +121,5 @@ func (p *Pair) BindResource(pr BindResource) *schema.Resource { } return pr.DeleteContext(ctx, left, right, c) }, - }.ToResource() + } } diff --git a/common/pair_test.go b/common/pair_test.go index 4efa0bcf9e..733e94fa17 100644 --- a/common/pair_test.go +++ b/common/pair_test.go @@ -153,7 +153,7 @@ func TestPairIDResource(t *testing.T) { DeleteContext: func(ctx context.Context, left, right string, c *DatabricksClient) error { return tt.err }, - }) + }).ToResource() ctx := context.Background() d := resource.Data(&terraform.InstanceState{ Attributes: state, diff --git a/common/reflect_resource.go b/common/reflect_resource.go index 31b25c2a9d..d7d603d12c 100644 --- a/common/reflect_resource.go +++ b/common/reflect_resource.go @@ -654,8 +654,8 @@ func DataToStructPointer(d *schema.ResourceData, scm map[string]*schema.Schema, } // DataToReflectValue reads reflect value from data -func DataToReflectValue(d *schema.ResourceData, r *schema.Resource, rv reflect.Value) error { - return readReflectValueFromData([]string{}, d, rv, r.Schema) +func DataToReflectValue(d *schema.ResourceData, s map[string]*schema.Schema, rv reflect.Value) error { + return readReflectValueFromData([]string{}, d, rv, s) } func readReflectValueFromData(path []string, d attributeGetter, diff --git a/common/reflect_resource_test.go b/common/reflect_resource_test.go index 7cb81e4f22..bb25ed2ff2 100644 --- a/common/reflect_resource_test.go +++ b/common/reflect_resource_test.go @@ -592,7 +592,7 @@ func TestStructToData_CornerCases(t *testing.T) { } func TestDataToReflectValueBypass(t *testing.T) { - err := DataToReflectValue(nil, &schema.Resource{Schema: map[string]*schema.Schema{}}, reflect.ValueOf(0)) + err := DataToReflectValue(nil, map[string]*schema.Schema{}, reflect.ValueOf(0)) assert.EqualError(t, err, "value of Struct is expected, but got Int: 0") } @@ -609,7 +609,7 @@ func TestDataResource(t *testing.T) { return fmt.Errorf("happens") } return nil - }) + }).ToResource() }() d := r.TestResourceData() d.Set("in", "test") @@ -639,7 +639,7 @@ func TestDataResourceWithID(t *testing.T) { dto.Out = "out: " + dto.In dto.ID = "abc" return nil - }) + }).ToResource() }() d := r.TestResourceData() d.Set("in", "id") diff --git a/common/resource.go b/common/resource.go index 5838892942..73361308d8 100644 --- a/common/resource.go +++ b/common/resource.go @@ -16,15 +16,17 @@ import ( // Resource aims to simplify things like error & deleted entities handling type Resource struct { - Create func(ctx context.Context, d *schema.ResourceData, c *DatabricksClient) error - Read func(ctx context.Context, d *schema.ResourceData, c *DatabricksClient) error - Update func(ctx context.Context, d *schema.ResourceData, c *DatabricksClient) error - Delete func(ctx context.Context, d *schema.ResourceData, c *DatabricksClient) error - CustomizeDiff func(ctx context.Context, d *schema.ResourceDiff) error - StateUpgraders []schema.StateUpgrader - Schema map[string]*schema.Schema - SchemaVersion int - Timeouts *schema.ResourceTimeout + Create func(ctx context.Context, d *schema.ResourceData, c *DatabricksClient) error + Read func(ctx context.Context, d *schema.ResourceData, c *DatabricksClient) error + Update func(ctx context.Context, d *schema.ResourceData, c *DatabricksClient) error + Delete func(ctx context.Context, d *schema.ResourceData, c *DatabricksClient) error + CustomizeDiff func(ctx context.Context, d *schema.ResourceDiff) error + StateUpgraders []schema.StateUpgrader + Schema map[string]*schema.Schema + SchemaVersion int + Timeouts *schema.ResourceTimeout + DeprecationMessage string + Importer *schema.ResourceImporter } func nicerError(ctx context.Context, err error, action string) error { @@ -139,7 +141,7 @@ func (r Resource) ToResource() *schema.Resource { return nil } } - return &schema.Resource{ + resource := &schema.Resource{ Schema: r.Schema, SchemaVersion: r.SchemaVersion, StateUpgraders: r.StateUpgraders, @@ -176,7 +178,12 @@ func (r Resource) ToResource() *schema.Resource { } return nil }, - Importer: &schema.ResourceImporter{ + Importer: r.Importer, + Timeouts: r.Timeouts, + DeprecationMessage: r.DeprecationMessage, + } + if resource.Importer == nil { + resource.Importer = &schema.ResourceImporter{ StateContext: func(ctx context.Context, d *schema.ResourceData, m any) (data []*schema.ResourceData, e error) { d.MarkNewResource() @@ -187,9 +194,9 @@ func (r Resource) ToResource() *schema.Resource { } return []*schema.ResourceData{d}, err }, - }, - Timeouts: r.Timeouts, + } } + return resource } func MustCompileKeyRE(name string) *regexp.Regexp { @@ -199,26 +206,25 @@ func MustCompileKeyRE(name string) *regexp.Regexp { } // Deprecated: migrate to WorkspaceData -func DataResource(sc any, read func(context.Context, any, *DatabricksClient) error) *schema.Resource { +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 }) - return &schema.Resource{ + return Resource{ Schema: s, - ReadContext: func(ctx context.Context, d *schema.ResourceData, m any) (diags diag.Diagnostics) { + Read: func(ctx context.Context, d *schema.ResourceData, m *DatabricksClient) (err error) { defer func() { // using recoverable() would cause more complex rewrapping of DataToStructPointer & StructToData if panic := recover(); panic != nil { - diags = diag.Errorf("panic: %v", panic) + err = fmt.Errorf("panic: %v", panic) } }() ptr := reflect.New(reflect.ValueOf(sc).Type()) - DataToReflectValue(d, &schema.Resource{Schema: s}, ptr.Elem()) - err := read(ctx, ptr.Interface(), m.(*DatabricksClient)) + DataToReflectValue(d, s, ptr.Elem()) + err = read(ctx, ptr.Interface(), m) if err != nil { err = nicerError(ctx, err, "read data") - diags = diag.FromErr(err) } StructToData(ptr.Elem().Interface(), s, d) // check if the resource schema has the `id` attribute (marked with `json:"id"` in the provided structure). @@ -244,7 +250,7 @@ func DataResource(sc any, read func(context.Context, any, *DatabricksClient) err // catalogs, err := w.Catalogs.ListAll(ctx) // ... // }) -func WorkspaceData[T any](read func(context.Context, *T, *databricks.WorkspaceClient) error) *schema.Resource { +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) @@ -281,7 +287,7 @@ func WorkspaceData[T any](read func(context.Context, *T, *databricks.WorkspaceCl // // The resource should be returned. // ... // }) -func WorkspaceDataWithParams[T, P any](read func(context.Context, P, *databricks.WorkspaceClient) (*T, error)) *schema.Resource { +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 { @@ -303,7 +309,7 @@ func WorkspaceDataWithParams[T, P any](read func(context.Context, P, *databricks // metastores, err := acc.Metastores.List(ctx) // ... // }) -func AccountData[T any](read func(context.Context, *T, *databricks.AccountClient) error) *schema.Resource { +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) @@ -340,7 +346,7 @@ func AccountData[T any](read func(context.Context, *T, *databricks.AccountClient // // The resource should be populated in the `workspace` parameter. // ... // }) -func AccountDataWithParams[T, P any](read func(context.Context, P, *databricks.AccountClient) (*T, error)) *schema.Resource { +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 { @@ -359,7 +365,7 @@ func AccountDataWithParams[T, P any](read func(context.Context, P, *databricks.A func genericDatabricksData[T, P, C any]( getClient func(*DatabricksClient) (C, error), read func(context.Context, P, *T, C) error, - hasOther bool) *schema.Resource { + hasOther bool) Resource { var dummy T var other P otherFields := StructToSchema(other, NoCustomize) @@ -386,29 +392,26 @@ func genericDatabricksData[T, P, C any]( } return m }) - return &schema.Resource{ + return Resource{ Schema: s, - ReadContext: func(ctx context.Context, d *schema.ResourceData, m any) (diags diag.Diagnostics) { + Read: func(ctx context.Context, d *schema.ResourceData, client *DatabricksClient) (err error) { defer func() { // using recoverable() would cause more complex rewrapping of DataToStructPointer & StructToData if panic := recover(); panic != nil { - diags = diag.Errorf("panic: %v", panic) + err = fmt.Errorf("panic: %v", panic) } }() var dummy T var other P DataToStructPointer(d, s, &other) DataToStructPointer(d, s, &dummy) - client := m.(*DatabricksClient) c, err := getClient(client) if err != nil { - err = nicerError(ctx, err, "get client") - return diag.FromErr(err) + return nicerError(ctx, err, "get client") } err = read(ctx, other, &dummy, c) if err != nil { err = nicerError(ctx, err, "read data") - diags = diag.FromErr(err) } StructToData(&dummy, s, d) // check if the resource schema has the `id` attribute (marked with `json:"id"` in the provided structure). diff --git a/exporter/importables_test.go b/exporter/importables_test.go index 2dc4d0bac3..bbeaff724e 100644 --- a/exporter/importables_test.go +++ b/exporter/importables_test.go @@ -68,7 +68,7 @@ func importContextForTestWithClient(ctx context.Context, client *common.Databric } func TestInstancePool(t *testing.T) { - d := pools.ResourceInstancePool().TestResourceData() + d := pools.ResourceInstancePool().ToResource().TestResourceData() d.Set("instance_pool_name", "blah-bah") ic := importContextForTest() ic.enableServices("access,pools") @@ -76,7 +76,7 @@ func TestInstancePool(t *testing.T) { name := resourcesMap["databricks_instance_pool"].Name(ic, d) assert.Equal(t, "blah-bah", name) - d = pools.ResourceInstancePool().TestResourceData() + d = pools.ResourceInstancePool().ToResource().TestResourceData() d.SetId("abc-bcd-def") name = resourcesMap["databricks_instance_pool"].Name(ic, d) assert.Equal(t, "def", name) @@ -91,7 +91,7 @@ func TestInstancePool(t *testing.T) { } func TestClusterPolicy(t *testing.T) { - d := policies.ResourceClusterPolicy().TestResourceData() + d := policies.ResourceClusterPolicy().ToResource().TestResourceData() d.Set("name", "bcd") definition := map[string]map[string]string{ "aws_attributes.instance_profile_arn": { @@ -123,7 +123,7 @@ func TestClusterPolicy(t *testing.T) { } func TestPredefinedClusterPolicy(t *testing.T) { - d := policies.ResourceClusterPolicy().TestResourceData() + d := policies.ResourceClusterPolicy().ToResource().TestResourceData() d.Set("policy_family_id", "job-cluster") policy, _ := json.Marshal(map[string]map[string]string{}) d.Set("definition", string(policy)) @@ -173,7 +173,7 @@ func TestGroup(t *testing.T) { }, }, } - d := scim.ResourceGroup().TestResourceData() + d := scim.ResourceGroup().ToResource().TestResourceData() d.Set("display_name", "foo") r := &resource{ Value: "foo", @@ -195,7 +195,7 @@ func TestGroup(t *testing.T) { func TestPermissions(t *testing.T) { p := permissions.ResourcePermissions() - d := p.TestResourceData() + d := p.ToResource().TestResourceData() d.SetId("abc") ic := importContextForTest() ic.enableServices("access,users,groups") @@ -229,7 +229,7 @@ func TestPermissions(t *testing.T) { } func TestSecretScope(t *testing.T) { - d := secrets.ResourceSecretScope().TestResourceData() + d := secrets.ResourceSecretScope().ToResource().TestResourceData() d.Set("name", "abc") ic := importContextForTest() name := ic.Importables["databricks_secret_scope"].Name(ic, d) @@ -238,7 +238,7 @@ func TestSecretScope(t *testing.T) { func TestInstancePoolNameFromID(t *testing.T) { ic := importContextForTest() - d := pools.ResourceInstancePool().TestResourceData() + d := pools.ResourceInstancePool().ToResource().TestResourceData() d.SetId("a-b-c") d.Set("instance_pool_name", "") assert.Equal(t, "c", resourcesMap["databricks_instance_pool"].Name(ic, d)) @@ -246,14 +246,14 @@ func TestInstancePoolNameFromID(t *testing.T) { func TestClusterNameFromID(t *testing.T) { ic := importContextForTest() - d := clusters.ResourceCluster().TestResourceData() + d := clusters.ResourceCluster().ToResource().TestResourceData() d.SetId("a-b-c") assert.Equal(t, "c", resourcesMap["databricks_cluster"].Name(ic, d)) } func TestRepoName(t *testing.T) { ic := importContextForTest() - d := repos.ResourceRepo().TestResourceData() + d := repos.ResourceRepo().ToResource().TestResourceData() d.SetId("12345") // Repo without path assert.Equal(t, "repo_12345", resourcesMap["databricks_repo"].Name(ic, d)) @@ -264,7 +264,7 @@ func TestRepoName(t *testing.T) { func TestRepoIgnore(t *testing.T) { ic := importContextForTest() - d := repos.ResourceRepo().TestResourceData() + d := repos.ResourceRepo().ToResource().TestResourceData() d.SetId("12345") d.Set("path", "/Repos/user/test") r := &resource{ID: "12345", Data: d} @@ -278,7 +278,7 @@ func TestRepoIgnore(t *testing.T) { func TestDLTIgnore(t *testing.T) { ic := importContextForTest() - d := pipelines.ResourcePipeline().TestResourceData() + d := pipelines.ResourcePipeline().ToResource().TestResourceData() d.SetId("12345") r := &resource{ID: "12345", Data: d} // job without libraries @@ -288,7 +288,7 @@ func TestDLTIgnore(t *testing.T) { func TestJobsIgnore(t *testing.T) { ic := importContextForTest() - d := jobs.ResourceJob().TestResourceData() + d := jobs.ResourceJob().ToResource().TestResourceData() d.SetId("12345") r := &resource{ID: "12345", Data: d} // job without tasks @@ -298,7 +298,7 @@ func TestJobsIgnore(t *testing.T) { func TestJobName(t *testing.T) { ic := importContextForTest() - d := jobs.ResourceJob().TestResourceData() + d := jobs.ResourceJob().ToResource().TestResourceData() d.SetId("12345") // job without name assert.Equal(t, "job_12345", resourcesMap["databricks_job"].Name(ic, d)) @@ -327,7 +327,7 @@ func TestImportClusterLibraries(t *testing.T) { }, }, func(ctx context.Context, client *common.DatabricksClient) { ic := importContextForTestWithClient(ctx, client) - d := clusters.ResourceCluster().TestResourceData() + d := clusters.ResourceCluster().ToResource().TestResourceData() d.SetId("abc") err := resourcesMap["databricks_cluster"].Import(ic, &resource{ ID: "abc", @@ -348,7 +348,7 @@ func TestImportClusterLibrariesFails(t *testing.T) { }, }, func(ctx context.Context, client *common.DatabricksClient) { ic := importContextForTestWithClient(ctx, client) - d := clusters.ResourceCluster().TestResourceData() + d := clusters.ResourceCluster().ToResource().TestResourceData() d.SetId("abc") err := resourcesMap["databricks_cluster"].Import(ic, &resource{ ID: "abc", @@ -437,7 +437,7 @@ func TestJobListNoNameMatch(t *testing.T) { } func TestClusterPolicyWrongDef(t *testing.T) { - d := policies.ResourceClusterPolicy().TestResourceData() + d := policies.ResourceClusterPolicy().ToResource().TestResourceData() d.Set("name", "abc") d.Set("definition", "..") ic := importContextForTest() @@ -449,7 +449,7 @@ func TestClusterPolicyWrongDef(t *testing.T) { } func TestClusterPolicyNoValues(t *testing.T) { - d := policies.ResourceClusterPolicy().TestResourceData() + d := policies.ResourceClusterPolicy().ToResource().TestResourceData() d.Set("name", "abc") d.Set("definition", `{"foo": {}}`) ic := importContextForTest() @@ -481,7 +481,7 @@ func TestGroupCacheError(t *testing.T) { ID: "nonsense", }) assert.EqualError(t, err, "nope") - d := scim.ResourceGroup().TestResourceData() + d := scim.ResourceGroup().ToResource().TestResourceData() d.Set("display_name", "nonsense") err = resourcesMap["databricks_group"].Import(ic, &resource{ ID: "nonsense", @@ -526,7 +526,7 @@ func TestUserSearchFails(t *testing.T) { userFixture[0], }, func(ctx context.Context, client *common.DatabricksClient) { ic := importContextForTestWithClient(ctx, client) - d := scim.ResourceUser().TestResourceData() + d := scim.ResourceUser().ToResource().TestResourceData() d.Set("user_name", "dbc") r := &resource{ Attribute: "display_name", @@ -546,7 +546,7 @@ func TestSpnSearchFails(t *testing.T) { qa.ListServicePrincipalsFixtures([]iam.ServicePrincipal{})[0], }, func(ctx context.Context, client *common.DatabricksClient) { ic := importContextForTestWithClient(ctx, client) - d := scim.ResourceServicePrincipal().TestResourceData() + d := scim.ResourceServicePrincipal().ToResource().TestResourceData() d.Set("application_id", "dbc") r := &resource{ Attribute: "application_id", @@ -578,7 +578,7 @@ func TestSpnSearchSuccess(t *testing.T) { }, }, func(ctx context.Context, client *common.DatabricksClient) { ic := importContextForTestWithClient(ctx, client) - d := scim.ResourceServicePrincipal().TestResourceData() + d := scim.ResourceServicePrincipal().ToResource().TestResourceData() d.Set("application_id", "dbc") d.Set("display_name", "dbc") r := &resource{ @@ -599,7 +599,7 @@ func TestSpnSearchSuccess(t *testing.T) { scim.ResourceServicePrincipal().Schema["display_name"], d)) // test for different branches in Name function - d2 := scim.ResourceServicePrincipal().TestResourceData() + d2 := scim.ResourceServicePrincipal().ToResource().TestResourceData() d2.SetId("123") d2.Set("application_id", "dbc") assert.Equal(t, "dbc_123", resourcesMap["databricks_service_principal"].Name(ic, d2)) @@ -612,7 +612,7 @@ func TestSpnSearchSuccess(t *testing.T) { } func TestShouldOmitForUsers(t *testing.T) { - d := scim.ResourceUser().TestResourceData() + d := scim.ResourceUser().ToResource().TestResourceData() d.SetId("user1") d.Set("user_name", "user@domain.com") d.Set("display_name", "") @@ -627,7 +627,7 @@ func TestShouldOmitForUsers(t *testing.T) { } func TestShouldOmitFoRepos(t *testing.T) { - d := repos.ResourceRepo().TestResourceData() + d := repos.ResourceRepo().ToResource().TestResourceData() d.SetId("1234") d.Set("path", "/Repos/Test/repo") assert.False(t, resourcesMap["databricks_repo"].ShouldOmitField(nil, "path", @@ -673,7 +673,7 @@ func TestUserImportSkipNonDirectGroups(t *testing.T) { }, }, func(ctx context.Context, client *common.DatabricksClient) { ic := importContextForTestWithClient(ctx, client) - d := scim.ResourceUser().TestResourceData() + d := scim.ResourceUser().ToResource().TestResourceData() d.Set("user_name", "dbc") r := &resource{ Attribute: "display_name", @@ -884,7 +884,7 @@ func TestMountsBodyGeneration(t *testing.T) { func TestGlobalInitScriptNameFromId(t *testing.T) { ic := importContextForTest() - d := workspace.ResourceGlobalInitScript().TestResourceData() + d := workspace.ResourceGlobalInitScript().ToResource().TestResourceData() d.SetId("abc") assert.Equal(t, "abc", resourcesMap["databricks_global_init_script"].Name(ic, d)) } diff --git a/jobs/data_job.go b/jobs/data_job.go index dd57f6dd8f..5559325e4e 100755 --- a/jobs/data_job.go +++ b/jobs/data_job.go @@ -5,10 +5,9 @@ import ( "fmt" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func DataSourceJob() *schema.Resource { +func DataSourceJob() common.Resource { type queryableJobData struct { Id string `json:"id,omitempty" tf:"computed"` JobId string `json:"job_id,omitempty" tf:"computed"` diff --git a/jobs/data_jobs.go b/jobs/data_jobs.go index 1c210fd600..a3d6a327c5 100644 --- a/jobs/data_jobs.go +++ b/jobs/data_jobs.go @@ -5,10 +5,9 @@ import ( "fmt" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func DataSourceJobs() *schema.Resource { +func DataSourceJobs() common.Resource { type jobsData struct { Ids map[string]string `json:"ids,omitempty" tf:"computed"` } diff --git a/jobs/resource_job.go b/jobs/resource_job.go index 3606ea5642..7bc95c8cb3 100644 --- a/jobs/resource_job.go +++ b/jobs/resource_job.go @@ -842,7 +842,7 @@ func prepareJobSettingsForUpdate(d *schema.ResourceData, js JobSettings) { } } -func ResourceJob() *schema.Resource { +func ResourceJob() common.Resource { getReadCtx := func(ctx context.Context, d *schema.ResourceData) context.Context { var js JobSettings common.DataToStructPointer(d, jobSchema, &js) @@ -940,5 +940,5 @@ func ResourceJob() *schema.Resource { } return w.Jobs.DeleteByJobId(ctx, jobID) }, - }.ToResource() + } } diff --git a/mlflow/data_mlflow_model.go b/mlflow/data_mlflow_model.go index e026806209..7855002743 100644 --- a/mlflow/data_mlflow_model.go +++ b/mlflow/data_mlflow_model.go @@ -6,10 +6,9 @@ import ( "github.com/databricks/databricks-sdk-go" "github.com/databricks/databricks-sdk-go/service/ml" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func DataSourceModel() *schema.Resource { +func DataSourceModel() common.Resource { return common.WorkspaceData(func(ctx context.Context, data *struct { Name string `json:"name"` UserId string `json:"user_id,omitempty" tf:"computed"` diff --git a/mlflow/resource_mlflow_experiment.go b/mlflow/resource_mlflow_experiment.go index 3765da0538..bcc3c87c43 100644 --- a/mlflow/resource_mlflow_experiment.go +++ b/mlflow/resource_mlflow_experiment.go @@ -67,7 +67,7 @@ func (a ExperimentsAPI) Delete(id string) error { }, nil) } -func ResourceMlflowExperiment() *schema.Resource { +func ResourceMlflowExperiment() common.Resource { s := common.StructToSchema( Experiment{}, common.NoCustomize) @@ -102,5 +102,5 @@ func ResourceMlflowExperiment() *schema.Resource { Schema: s, SchemaVersion: 0, Timeouts: &schema.ResourceTimeout{}, - }.ToResource() + } } diff --git a/mlflow/resource_mlflow_model.go b/mlflow/resource_mlflow_model.go index d6f5064606..80692cee87 100644 --- a/mlflow/resource_mlflow_model.go +++ b/mlflow/resource_mlflow_model.go @@ -8,7 +8,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func ResourceMlflowModel() *schema.Resource { +func ResourceMlflowModel() common.Resource { s := common.StructToSchema( ml.CreateModelRequest{}, func(s map[string]*schema.Schema) map[string]*schema.Schema { @@ -74,5 +74,5 @@ func ResourceMlflowModel() *schema.Resource { return w.ModelRegistry.DeleteModel(ctx, req) }, Schema: s, - }.ToResource() + } } diff --git a/mlflow/resource_mlflow_webhook.go b/mlflow/resource_mlflow_webhook.go index 65e0f81d1d..dd6f92de94 100644 --- a/mlflow/resource_mlflow_webhook.go +++ b/mlflow/resource_mlflow_webhook.go @@ -27,7 +27,7 @@ func readWebHook(w *databricks.WorkspaceClient, ctx context.Context, ID string) return ml.RegistryWebhook{}, fmt.Errorf("webhook with ID %s isn't found", ID) } -func ResourceMlflowWebhook() *schema.Resource { +func ResourceMlflowWebhook() common.Resource { s := common.StructToSchema( ml.CreateRegistryWebhook{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { @@ -103,5 +103,5 @@ func ResourceMlflowWebhook() *schema.Resource { return w.ModelRegistry.DeleteWebhook(ctx, ml.DeleteWebhookRequest{Id: d.Id()}) }, Schema: s, - }.ToResource() + } } diff --git a/mws/data_current_config.go b/mws/data_current_config.go index 6a84d1c5c0..4e45a0b656 100644 --- a/mws/data_current_config.go +++ b/mws/data_current_config.go @@ -4,7 +4,6 @@ import ( "context" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) type currentConfig struct { @@ -15,7 +14,7 @@ type currentConfig struct { AuthType string `json:"auth_type,omitempty" tf:"computed"` } -func DataSourceCurrentConfiguration() *schema.Resource { +func DataSourceCurrentConfiguration() common.Resource { return common.DataResource(currentConfig{}, func(ctx context.Context, e any, c *common.DatabricksClient) error { data := e.(*currentConfig) data.IsAccount = false diff --git a/mws/data_mws_credentials.go b/mws/data_mws_credentials.go index 701407aa63..aa757fd858 100755 --- a/mws/data_mws_credentials.go +++ b/mws/data_mws_credentials.go @@ -5,10 +5,9 @@ import ( "fmt" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func DataSourceMwsCredentials() *schema.Resource { +func DataSourceMwsCredentials() common.Resource { type mwsCredentialsData struct { Ids map[string]string `json:"ids,omitempty" tf:"computed"` } diff --git a/mws/data_mws_workspaces.go b/mws/data_mws_workspaces.go index 063629ab78..da5eabb2c5 100755 --- a/mws/data_mws_workspaces.go +++ b/mws/data_mws_workspaces.go @@ -5,10 +5,9 @@ import ( "fmt" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func DataSourceMwsWorkspaces() *schema.Resource { +func DataSourceMwsWorkspaces() common.Resource { type mwsWorkspacesData struct { Ids map[string]int64 `json:"ids,omitempty" tf:"computed"` } diff --git a/mws/resource_mws_credentials.go b/mws/resource_mws_credentials.go index 57da97acd3..b70a1e0ca1 100644 --- a/mws/resource_mws_credentials.go +++ b/mws/resource_mws_credentials.go @@ -45,7 +45,7 @@ type CredentialInfo struct { ExternalId string `json:"external_id,omitempty" tf:"computed"` } -func ResourceMwsCredentials() *schema.Resource { +func ResourceMwsCredentials() common.Resource { p := common.NewPairSeparatedID("account_id", "credentials_id", "/") return common.Resource{ Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { @@ -110,5 +110,5 @@ func ResourceMwsCredentials() *schema.Resource { s["account_id"].Deprecated = "`account_id` should be set as part of the Databricks Config, not in the resource." return s }), - }.ToResource() + } } diff --git a/mws/resource_mws_customer_managed_keys.go b/mws/resource_mws_customer_managed_keys.go index 2903e88a34..1163ef39c5 100644 --- a/mws/resource_mws_customer_managed_keys.go +++ b/mws/resource_mws_customer_managed_keys.go @@ -71,7 +71,7 @@ func (a CustomerManagedKeysAPI) List(accountID string) (kl []CustomerManagedKey, return } -func ResourceMwsCustomerManagedKeys() *schema.Resource { +func ResourceMwsCustomerManagedKeys() common.Resource { s := common.StructToSchema(CustomerManagedKey{}, nil) p := common.NewPairSeparatedID("account_id", "customer_managed_key_id", "/") return common.Resource{ @@ -113,7 +113,7 @@ func ResourceMwsCustomerManagedKeys() *schema.Resource { Upgrade: migrateResourceCustomerManagedKeyV0, }, }, - }.ToResource() + } } func migrateResourceCustomerManagedKeyV0(ctx context.Context, diff --git a/mws/resource_mws_log_delivery.go b/mws/resource_mws_log_delivery.go index 2e56c83b16..34514440fb 100644 --- a/mws/resource_mws_log_delivery.go +++ b/mws/resource_mws_log_delivery.go @@ -65,7 +65,7 @@ func (a LogDeliveryAPI) Patch(accountID, configID string, status string) error { }) } -func ResourceMwsLogDelivery() *schema.Resource { +func ResourceMwsLogDelivery() common.Resource { p := common.NewPairID("account_id", "config_id") s := common.StructToSchema(LogDeliveryConfiguration{}, func(s map[string]*schema.Schema) map[string]*schema.Schema { @@ -119,5 +119,5 @@ func ResourceMwsLogDelivery() *schema.Resource { } return NewLogDeliveryAPI(ctx, c).Patch(accountID, configID, "DISABLED") }, - }.ToResource() + } } diff --git a/mws/resource_mws_networks.go b/mws/resource_mws_networks.go index 1a41852791..56cb98bb98 100644 --- a/mws/resource_mws_networks.go +++ b/mws/resource_mws_networks.go @@ -68,7 +68,7 @@ func (a NetworksAPI) List(mwsAcctID string) ([]Network, error) { return mwsNetworkList, err } -func ResourceMwsNetworks() *schema.Resource { +func ResourceMwsNetworks() common.Resource { s := common.StructToSchema(Network{}, func(s map[string]*schema.Schema) map[string]*schema.Schema { s["account_id"].Sensitive = true // nolint @@ -115,5 +115,5 @@ func ResourceMwsNetworks() *schema.Resource { } return NewNetworksAPI(ctx, c).Delete(accountID, networkID) }, - }.ToResource() + } } diff --git a/mws/resource_mws_permission_assignment.go b/mws/resource_mws_permission_assignment.go index 9d2ffe02dd..aa561933a5 100644 --- a/mws/resource_mws_permission_assignment.go +++ b/mws/resource_mws_permission_assignment.go @@ -89,7 +89,7 @@ func mustInt64(s string) int64 { return n } -func ResourceMwsPermissionAssignment() *schema.Resource { +func ResourceMwsPermissionAssignment() common.Resource { type entity struct { WorkspaceId int64 `json:"workspace_id"` PrincipalId int64 `json:"principal_id"` @@ -137,5 +137,5 @@ func ResourceMwsPermissionAssignment() *schema.Resource { } return NewPermissionAssignmentAPI(ctx, c).Remove(workspaceId, principalId) }, - }.ToResource() + } } diff --git a/mws/resource_mws_private_access_settings.go b/mws/resource_mws_private_access_settings.go index da23cbace2..67e807dcf5 100644 --- a/mws/resource_mws_private_access_settings.go +++ b/mws/resource_mws_private_access_settings.go @@ -11,7 +11,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) -func ResourceMwsPrivateAccessSettings() *schema.Resource { +func ResourceMwsPrivateAccessSettings() common.Resource { s := common.StructToSchema(provisioning.PrivateAccessSettings{}, func(s map[string]*schema.Schema) map[string]*schema.Schema { // nolint s["private_access_settings_name"].ValidateFunc = validation.StringLenBetween(4, 256) @@ -74,5 +74,5 @@ func ResourceMwsPrivateAccessSettings() *schema.Resource { } return a.PrivateAccess.DeleteByPrivateAccessSettingsId(ctx, pasID) }, - }.ToResource() + } } diff --git a/mws/resource_mws_storage_configurations.go b/mws/resource_mws_storage_configurations.go index ac014480fa..2b979cf448 100644 --- a/mws/resource_mws_storage_configurations.go +++ b/mws/resource_mws_storage_configurations.go @@ -55,7 +55,7 @@ func (a StorageConfigurationsAPI) List(mwsAcctID string) ([]StorageConfiguration return mwsStorageConfigurationsList, err } -func ResourceMwsStorageConfigurations() *schema.Resource { +func ResourceMwsStorageConfigurations() common.Resource { p := common.NewPairSeparatedID("account_id", "storage_configuration_id", "/") return common.Resource{ Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { @@ -113,5 +113,5 @@ func ResourceMwsStorageConfigurations() *schema.Resource { Computed: true, }, }, - }.ToResource() + } } diff --git a/mws/resource_mws_vpc_endpoint.go b/mws/resource_mws_vpc_endpoint.go index af67b1a2d2..fd10d8cfaf 100644 --- a/mws/resource_mws_vpc_endpoint.go +++ b/mws/resource_mws_vpc_endpoint.go @@ -74,7 +74,7 @@ func (a VPCEndpointAPI) List(mwsAcctID string) ([]VPCEndpoint, error) { return mwsVPCEndpointList, err } -func ResourceMwsVpcEndpoint() *schema.Resource { +func ResourceMwsVpcEndpoint() common.Resource { s := common.StructToSchema(VPCEndpoint{}, func(s map[string]*schema.Schema) map[string]*schema.Schema { // nolint s["aws_vpc_endpoint_id"].ExactlyOneOf = []string{"aws_vpc_endpoint_id", "gcp_vpc_endpoint_info"} @@ -115,5 +115,5 @@ func ResourceMwsVpcEndpoint() *schema.Resource { } return NewVPCEndpointAPI(ctx, c).Delete(accountID, vpcEndpointID) }, - }.ToResource() + } } diff --git a/mws/resource_mws_workspaces.go b/mws/resource_mws_workspaces.go index b03ec9e63e..5f4d442bf0 100644 --- a/mws/resource_mws_workspaces.go +++ b/mws/resource_mws_workspaces.go @@ -460,7 +460,7 @@ func UpdateTokenIfNeeded(workspacesAPI WorkspacesAPI, } // ResourceMwsWorkspaces manages E2 workspaces -func ResourceMwsWorkspaces() *schema.Resource { +func ResourceMwsWorkspaces() common.Resource { workspaceSchema := common.StructToSchema(Workspace{}, func(s map[string]*schema.Schema) map[string]*schema.Schema { for name, fieldSchema := range s { @@ -613,7 +613,7 @@ func ResourceMwsWorkspaces() *schema.Resource { Read: schema.DefaultTimeout(DefaultProvisionTimeout), Update: schema.DefaultTimeout(DefaultProvisionTimeout), }, - }.ToResource() + } } func workspaceMigrateV2(ctx context.Context, rawState map[string]any, meta any) (map[string]any, error) { diff --git a/mws/resource_mws_workspaces_test.go b/mws/resource_mws_workspaces_test.go index 497b0c8796..9a7fa570f9 100644 --- a/mws/resource_mws_workspaces_test.go +++ b/mws/resource_mws_workspaces_test.go @@ -1429,7 +1429,7 @@ func TestEnsureTokenExists(t *testing.T) { }, }, func(ctx context.Context, client *common.DatabricksClient) { r := ResourceMwsWorkspaces() - d := r.TestResourceData() + d := r.ToResource().TestResourceData() d.Set("workspace_url", client.Config.Host) d.Set("token", []any{ map[string]any{ @@ -1459,7 +1459,7 @@ func TestEnsureTokenExists_NoRecreate(t *testing.T) { }, }, func(ctx context.Context, client *common.DatabricksClient) { r := ResourceMwsWorkspaces() - d := r.TestResourceData() + d := r.ToResource().TestResourceData() d.Set("workspace_url", client.Config.Host) d.Set("token", []any{ map[string]any{ @@ -1480,7 +1480,7 @@ func TestWorkspaceTokenWrongAuthCornerCase(t *testing.T) { t.Fatal(err) } r := ResourceMwsWorkspaces() - d := r.TestResourceData() + d := r.ToResource().TestResourceData() d.Set("workspace_url", client.Config.Host) d.Set("token", []any{ map[string]any{ @@ -1516,7 +1516,7 @@ func TestWorkspaceTokenHttpCornerCases(t *testing.T) { }, func(ctx context.Context, client *common.DatabricksClient) { wsApi := NewWorkspacesAPI(context.Background(), client) r := ResourceMwsWorkspaces() - d := r.TestResourceData() + d := r.ToResource().TestResourceData() d.Set("workspace_url", client.Config.Host) d.Set("token", []any{ map[string]any{ diff --git a/permissions/resource_access_control_rule_set.go b/permissions/resource_access_control_rule_set.go index 5e0e424a47..f3af9bcdc6 100644 --- a/permissions/resource_access_control_rule_set.go +++ b/permissions/resource_access_control_rule_set.go @@ -12,7 +12,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func ResourceAccessControlRuleSet() *schema.Resource { +func ResourceAccessControlRuleSet() common.Resource { s := common.StructToSchema( iam.RuleSetUpdateRequest{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { @@ -134,5 +134,5 @@ func ResourceAccessControlRuleSet() *schema.Resource { } return nil }, - }.ToResource() + } } diff --git a/permissions/resource_permissions.go b/permissions/resource_permissions.go index fe0f0257fb..0e284c5dce 100644 --- a/permissions/resource_permissions.go +++ b/permissions/resource_permissions.go @@ -365,7 +365,7 @@ func stringInSlice(a string, list []string) bool { } // ResourcePermissions definition -func ResourcePermissions() *schema.Resource { +func ResourcePermissions() common.Resource { s := common.StructToSchema(PermissionsEntity{}, func(s map[string]*schema.Schema) map[string]*schema.Schema { for _, mapping := range permissionsResourceIDFields() { s[mapping.field] = &schema.Schema{ @@ -482,5 +482,5 @@ func ResourcePermissions() *schema.Resource { Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { return NewPermissionsAPI(ctx, c).Delete(d.Id()) }, - }.ToResource() + } } diff --git a/permissions/resource_permissions_test.go b/permissions/resource_permissions_test.go index 6a0284e608..8fd9950377 100644 --- a/permissions/resource_permissions_test.go +++ b/permissions/resource_permissions_test.go @@ -13,6 +13,7 @@ import ( "github.com/databricks/terraform-provider-databricks/qa" "github.com/databricks/terraform-provider-databricks/workspace" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -468,11 +469,11 @@ func TestResourcePermissionsRead_ErrorOnScimMe(t *testing.T) { }, }, func(ctx context.Context, client *common.DatabricksClient) { r := ResourcePermissions() - d := r.TestResourceData() + d := r.ToResource().TestResourceData() d.SetId("/clusters/abc") - diags := r.ReadContext(ctx, d, client) - assert.True(t, diags.HasError()) - assert.Equal(t, "Internal error happened", diags[0].Summary) + diags := r.Read(ctx, d, client) + assert.NotNil(t, diags) + assert.Equal(t, "Internal error happened", diag.FromErr(diags)[0].Summary) }) } @@ -1476,7 +1477,7 @@ func TestObjectACLToPermissionsEntityCornerCases(t *testing.T) { GroupName: "admins", }, }, - }).ToPermissionsEntity(ResourcePermissions().TestResourceData(), "me") + }).ToPermissionsEntity(ResourcePermissions().ToResource().TestResourceData(), "me") assert.EqualError(t, err, "unknown object type bananas") } @@ -1498,9 +1499,9 @@ func TestDeleteMissing(t *testing.T) { }, }, func(ctx context.Context, client *common.DatabricksClient) { p := ResourcePermissions() - d := p.TestResourceData() + d := p.ToResource().TestResourceData() d.SetId("x") - diags := p.DeleteContext(ctx, d, client) + diags := p.Delete(ctx, d, client) assert.Nil(t, diags) }) } diff --git a/pipelines/data_pipelines.go b/pipelines/data_pipelines.go index 005be376f3..b4c6451ecb 100755 --- a/pipelines/data_pipelines.go +++ b/pipelines/data_pipelines.go @@ -8,10 +8,9 @@ import ( "github.com/databricks/databricks-sdk-go" "github.com/databricks/databricks-sdk-go/service/pipelines" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func DataSourcePipelines() *schema.Resource { +func DataSourcePipelines() common.Resource { type pipelinesData struct { 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 26d2a17b25..8924c5a8f7 100644 --- a/pipelines/resource_pipeline.go +++ b/pipelines/resource_pipeline.go @@ -351,7 +351,7 @@ func adjustPipelineResourceSchema(m map[string]*schema.Schema) map[string]*schem } // ResourcePipeline defines the Terraform resource for pipelines. -func ResourcePipeline() *schema.Resource { +func ResourcePipeline() common.Resource { var pipelineSchema = common.StructToSchema(PipelineSpec{}, adjustPipelineResourceSchema) return common.Resource{ Schema: pipelineSchema, @@ -389,5 +389,5 @@ func ResourcePipeline() *schema.Resource { Timeouts: &schema.ResourceTimeout{ Default: schema.DefaultTimeout(DefaultTimeout), }, - }.ToResource() + } } diff --git a/policies/data_cluster_policy.go b/policies/data_cluster_policy.go index 7924c672cb..4ee7480097 100644 --- a/policies/data_cluster_policy.go +++ b/policies/data_cluster_policy.go @@ -5,11 +5,10 @@ import ( "github.com/databricks/databricks-sdk-go" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) // DataSourceClusterPolicy returns information about cluster policy specified by name -func DataSourceClusterPolicy() *schema.Resource { +func DataSourceClusterPolicy() common.Resource { return common.WorkspaceData(func(ctx context.Context, data *struct { Id string `json:"id,omitempty" tf:"computed"` Name string `json:"name,omitempty" tf:"computed"` diff --git a/policies/resource_cluster_policy.go b/policies/resource_cluster_policy.go index 9e3a006822..96f80f6b44 100644 --- a/policies/resource_cluster_policy.go +++ b/policies/resource_cluster_policy.go @@ -25,7 +25,7 @@ func isBuiltinPolicyFamily(ctx context.Context, w *databricks.WorkspaceClient, f } // ResourceClusterPolicy ... -func ResourceClusterPolicy() *schema.Resource { +func ResourceClusterPolicy() common.Resource { s := common.StructToSchema( compute.CreatePolicy{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { @@ -128,5 +128,5 @@ func ResourceClusterPolicy() *schema.Resource { } return w.ClusterPolicies.DeleteByPolicyId(ctx, d.Id()) }, - }.ToResource() + } } diff --git a/pools/data_instance_pool.go b/pools/data_instance_pool.go index b50c4fab11..1c733246d0 100644 --- a/pools/data_instance_pool.go +++ b/pools/data_instance_pool.go @@ -5,7 +5,6 @@ import ( "fmt" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -24,24 +23,24 @@ func getPool(poolsAPI InstancePoolsAPI, name string) (*InstancePoolAndStats, err } // DataSourceInstancePool returns information about instance pool specified by name -func DataSourceInstancePool() *schema.Resource { +func DataSourceInstancePool() common.Resource { type poolDetails struct { Name string `json:"name"` Attributes *InstancePoolAndStats `json:"pool_info,omitempty" tf:"computed"` } s := common.StructToSchema(poolDetails{}, nil) - return &schema.Resource{ + return common.Resource{ Schema: s, - ReadContext: func(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { + Read: func(ctx context.Context, d *schema.ResourceData, m *common.DatabricksClient) error { name := d.Get("name").(string) poolsAPI := NewInstancePoolsAPI(ctx, m) pool, err := getPool(poolsAPI, name) if err != nil { - return diag.FromErr(err) + return err } d.SetId(pool.InstancePoolID) err = common.StructToData(poolDetails{Name: name, Attributes: pool}, s, d) - return diag.FromErr(err) + return err }, } } diff --git a/pools/resource_instance_pool.go b/pools/resource_instance_pool.go index 1c17333aaa..e9efada8c6 100644 --- a/pools/resource_instance_pool.go +++ b/pools/resource_instance_pool.go @@ -169,7 +169,7 @@ func (a InstancePoolsAPI) Delete(instancePoolID string) error { } // ResourceInstancePool ... -func ResourceInstancePool() *schema.Resource { +func ResourceInstancePool() common.Resource { s := common.StructToSchema(InstancePool{}, func(s map[string]*schema.Schema) map[string]*schema.Schema { s["enable_elastic_disk"].Default = true s["aws_attributes"].ConflictsWith = []string{"azure_attributes", "gcp_attributes"} @@ -270,5 +270,5 @@ func ResourceInstancePool() *schema.Resource { Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { return NewInstancePoolsAPI(ctx, c).Delete(d.Id()) }, - }.ToResource() + } } diff --git a/provider/provider.go b/provider/provider.go index 65c4a4f53c..2e94459399 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -52,133 +52,133 @@ func init() { func DatabricksProvider() *schema.Provider { p := &schema.Provider{ DataSourcesMap: map[string]*schema.Resource{ // must be in alphabetical order - "databricks_aws_crossaccount_policy": aws.DataAwsCrossaccountPolicy(), - "databricks_aws_assume_role_policy": aws.DataAwsAssumeRolePolicy(), - "databricks_aws_bucket_policy": aws.DataAwsBucketPolicy(), - "databricks_cluster": clusters.DataSourceCluster(), - "databricks_clusters": clusters.DataSourceClusters(), - "databricks_cluster_policy": policies.DataSourceClusterPolicy(), - "databricks_catalogs": catalog.DataSourceCatalogs(), - "databricks_current_config": mws.DataSourceCurrentConfiguration(), - "databricks_current_metastore": catalog.DataSourceCurrentMetastore(), - "databricks_current_user": scim.DataSourceCurrentUser(), - "databricks_dbfs_file": storage.DataSourceDbfsFile(), - "databricks_dbfs_file_paths": storage.DataSourceDbfsFilePaths(), - "databricks_directory": workspace.DataSourceDirectory(), - "databricks_group": scim.DataSourceGroup(), - "databricks_instance_pool": pools.DataSourceInstancePool(), - "databricks_instance_profiles": aws.DataSourceInstanceProfiles(), - "databricks_jobs": jobs.DataSourceJobs(), - "databricks_job": jobs.DataSourceJob(), - "databricks_metastore": catalog.DataSourceMetastore(), - "databricks_metastores": catalog.DataSourceMetastores(), - "databricks_mlflow_model": mlflow.DataSourceModel(), - "databricks_mws_credentials": mws.DataSourceMwsCredentials(), - "databricks_mws_workspaces": mws.DataSourceMwsWorkspaces(), - "databricks_node_type": clusters.DataSourceNodeType(), - "databricks_notebook": workspace.DataSourceNotebook(), - "databricks_notebook_paths": workspace.DataSourceNotebookPaths(), - "databricks_pipelines": pipelines.DataSourcePipelines(), - "databricks_schemas": catalog.DataSourceSchemas(), - "databricks_service_principal": scim.DataSourceServicePrincipal(), - "databricks_service_principals": scim.DataSourceServicePrincipals(), - "databricks_share": catalog.DataSourceShare(), - "databricks_shares": catalog.DataSourceShares(), - "databricks_spark_version": clusters.DataSourceSparkVersion(), - "databricks_sql_warehouse": sql.DataSourceWarehouse(), - "databricks_sql_warehouses": sql.DataSourceWarehouses(), - "databricks_tables": catalog.DataSourceTables(), - "databricks_views": catalog.DataSourceViews(), - "databricks_user": scim.DataSourceUser(), - "databricks_zones": clusters.DataSourceClusterZones(), + "databricks_aws_crossaccount_policy": aws.DataAwsCrossaccountPolicy().ToResource(), + "databricks_aws_assume_role_policy": aws.DataAwsAssumeRolePolicy().ToResource(), + "databricks_aws_bucket_policy": aws.DataAwsBucketPolicy().ToResource(), + "databricks_cluster": clusters.DataSourceCluster().ToResource(), + "databricks_clusters": clusters.DataSourceClusters().ToResource(), + "databricks_cluster_policy": policies.DataSourceClusterPolicy().ToResource(), + "databricks_catalogs": catalog.DataSourceCatalogs().ToResource(), + "databricks_current_config": mws.DataSourceCurrentConfiguration().ToResource(), + "databricks_current_metastore": catalog.DataSourceCurrentMetastore().ToResource(), + "databricks_current_user": scim.DataSourceCurrentUser().ToResource(), + "databricks_dbfs_file": storage.DataSourceDbfsFile().ToResource(), + "databricks_dbfs_file_paths": storage.DataSourceDbfsFilePaths().ToResource(), + "databricks_directory": workspace.DataSourceDirectory().ToResource(), + "databricks_group": scim.DataSourceGroup().ToResource(), + "databricks_instance_pool": pools.DataSourceInstancePool().ToResource(), + "databricks_instance_profiles": aws.DataSourceInstanceProfiles().ToResource(), + "databricks_jobs": jobs.DataSourceJobs().ToResource(), + "databricks_job": jobs.DataSourceJob().ToResource(), + "databricks_metastore": catalog.DataSourceMetastore().ToResource(), + "databricks_metastores": catalog.DataSourceMetastores().ToResource(), + "databricks_mlflow_model": mlflow.DataSourceModel().ToResource(), + "databricks_mws_credentials": mws.DataSourceMwsCredentials().ToResource(), + "databricks_mws_workspaces": mws.DataSourceMwsWorkspaces().ToResource(), + "databricks_node_type": clusters.DataSourceNodeType().ToResource(), + "databricks_notebook": workspace.DataSourceNotebook().ToResource(), + "databricks_notebook_paths": workspace.DataSourceNotebookPaths().ToResource(), + "databricks_pipelines": pipelines.DataSourcePipelines().ToResource(), + "databricks_schemas": catalog.DataSourceSchemas().ToResource(), + "databricks_service_principal": scim.DataSourceServicePrincipal().ToResource(), + "databricks_service_principals": scim.DataSourceServicePrincipals().ToResource(), + "databricks_share": catalog.DataSourceShare().ToResource(), + "databricks_shares": catalog.DataSourceShares().ToResource(), + "databricks_spark_version": clusters.DataSourceSparkVersion().ToResource(), + "databricks_sql_warehouse": sql.DataSourceWarehouse().ToResource(), + "databricks_sql_warehouses": sql.DataSourceWarehouses().ToResource(), + "databricks_tables": catalog.DataSourceTables().ToResource(), + "databricks_views": catalog.DataSourceViews().ToResource(), + "databricks_user": scim.DataSourceUser().ToResource(), + "databricks_zones": clusters.DataSourceClusterZones().ToResource(), }, ResourcesMap: map[string]*schema.Resource{ // must be in alphabetical order - "databricks_access_control_rule_set": permissions.ResourceAccessControlRuleSet(), - "databricks_artifact_allowlist": catalog.ResourceArtifactAllowlist(), - "databricks_aws_s3_mount": storage.ResourceAWSS3Mount(), - "databricks_azure_adls_gen1_mount": storage.ResourceAzureAdlsGen1Mount(), - "databricks_azure_adls_gen2_mount": storage.ResourceAzureAdlsGen2Mount(), - "databricks_azure_blob_mount": storage.ResourceAzureBlobMount(), - "databricks_catalog": catalog.ResourceCatalog(), - "databricks_catalog_workspace_binding": catalog.ResourceCatalogWorkspaceBinding(), - "databricks_connection": catalog.ResourceConnection(), - "databricks_cluster": clusters.ResourceCluster(), - "databricks_cluster_policy": policies.ResourceClusterPolicy(), - "databricks_dbfs_file": storage.ResourceDbfsFile(), - "databricks_directory": workspace.ResourceDirectory(), - "databricks_entitlements": scim.ResourceEntitlements(), - "databricks_external_location": catalog.ResourceExternalLocation(), - "databricks_git_credential": repos.ResourceGitCredential(), - "databricks_global_init_script": workspace.ResourceGlobalInitScript(), - "databricks_grant": catalog.ResourceGrant(), - "databricks_grants": catalog.ResourceGrants(), - "databricks_group": scim.ResourceGroup(), - "databricks_group_instance_profile": aws.ResourceGroupInstanceProfile(), - "databricks_group_member": scim.ResourceGroupMember(), - "databricks_group_role": scim.ResourceGroupRole(), - "databricks_instance_pool": pools.ResourceInstancePool(), - "databricks_instance_profile": aws.ResourceInstanceProfile(), - "databricks_ip_access_list": access.ResourceIPAccessList(), - "databricks_job": jobs.ResourceJob(), - "databricks_library": clusters.ResourceLibrary(), - "databricks_metastore": catalog.ResourceMetastore(), - "databricks_metastore_assignment": catalog.ResourceMetastoreAssignment(), - "databricks_metastore_data_access": catalog.ResourceMetastoreDataAccess(), - "databricks_mlflow_experiment": mlflow.ResourceMlflowExperiment(), - "databricks_mlflow_model": mlflow.ResourceMlflowModel(), - "databricks_mlflow_webhook": mlflow.ResourceMlflowWebhook(), - "databricks_model_serving": serving.ResourceModelServing(), - "databricks_mount": storage.ResourceMount(), - "databricks_mws_customer_managed_keys": mws.ResourceMwsCustomerManagedKeys(), - "databricks_mws_credentials": mws.ResourceMwsCredentials(), - "databricks_mws_log_delivery": mws.ResourceMwsLogDelivery(), - "databricks_mws_networks": mws.ResourceMwsNetworks(), - "databricks_mws_permission_assignment": mws.ResourceMwsPermissionAssignment(), - "databricks_mws_private_access_settings": mws.ResourceMwsPrivateAccessSettings(), - "databricks_mws_storage_configurations": mws.ResourceMwsStorageConfigurations(), - "databricks_mws_vpc_endpoint": mws.ResourceMwsVpcEndpoint(), - "databricks_mws_workspaces": mws.ResourceMwsWorkspaces(), - "databricks_notebook": workspace.ResourceNotebook(), - "databricks_obo_token": tokens.ResourceOboToken(), - "databricks_permission_assignment": access.ResourcePermissionAssignment(), - "databricks_permissions": permissions.ResourcePermissions(), - "databricks_pipeline": pipelines.ResourcePipeline(), - "databricks_provider": catalog.ResourceProvider(), - "databricks_recipient": sharing.ResourceRecipient(), - "databricks_registered_model": catalog.ResourceRegisteredModel(), - "databricks_repo": repos.ResourceRepo(), - "databricks_schema": catalog.ResourceSchema(), - "databricks_secret": secrets.ResourceSecret(), - "databricks_secret_scope": secrets.ResourceSecretScope(), - "databricks_secret_acl": secrets.ResourceSecretACL(), - "databricks_service_principal": scim.ResourceServicePrincipal(), - "databricks_service_principal_role": aws.ResourceServicePrincipalRole(), - "databricks_service_principal_secret": tokens.ResourceServicePrincipalSecret(), - "databricks_share": catalog.ResourceShare(), - "databricks_sql_dashboard": sql.ResourceSqlDashboard(), - "databricks_sql_endpoint": sql.ResourceSqlEndpoint(), - "databricks_sql_global_config": sql.ResourceSqlGlobalConfig(), - "databricks_sql_permissions": access.ResourceSqlPermissions(), - "databricks_sql_query": sql.ResourceSqlQuery(), - "databricks_sql_alert": sql.ResourceSqlAlert(), - "databricks_sql_table": catalog.ResourceSqlTable(), - "databricks_sql_visualization": sql.ResourceSqlVisualization(), - "databricks_sql_widget": sql.ResourceSqlWidget(), - "databricks_storage_credential": catalog.ResourceStorageCredential(), - "databricks_system_schema": catalog.ResourceSystemSchema(), - "databricks_table": catalog.ResourceTable(), - "databricks_token": tokens.ResourceToken(), - "databricks_user": scim.ResourceUser(), - "databricks_user_instance_profile": aws.ResourceUserInstanceProfile(), - "databricks_user_role": aws.ResourceUserRole(), - "databricks_volume": catalog.ResourceVolume(), - "databricks_workspace_conf": workspace.ResourceWorkspaceConf(), - "databricks_workspace_file": workspace.ResourceWorkspaceFile(), + "databricks_access_control_rule_set": permissions.ResourceAccessControlRuleSet().ToResource(), + "databricks_artifact_allowlist": catalog.ResourceArtifactAllowlist().ToResource(), + "databricks_aws_s3_mount": storage.ResourceAWSS3Mount().ToResource(), + "databricks_azure_adls_gen1_mount": storage.ResourceAzureAdlsGen1Mount().ToResource(), + "databricks_azure_adls_gen2_mount": storage.ResourceAzureAdlsGen2Mount().ToResource(), + "databricks_azure_blob_mount": storage.ResourceAzureBlobMount().ToResource(), + "databricks_catalog": catalog.ResourceCatalog().ToResource(), + "databricks_catalog_workspace_binding": catalog.ResourceCatalogWorkspaceBinding().ToResource(), + "databricks_connection": catalog.ResourceConnection().ToResource(), + "databricks_cluster": clusters.ResourceCluster().ToResource(), + "databricks_cluster_policy": policies.ResourceClusterPolicy().ToResource(), + "databricks_dbfs_file": storage.ResourceDbfsFile().ToResource(), + "databricks_directory": workspace.ResourceDirectory().ToResource(), + "databricks_entitlements": scim.ResourceEntitlements().ToResource(), + "databricks_external_location": catalog.ResourceExternalLocation().ToResource(), + "databricks_git_credential": repos.ResourceGitCredential().ToResource(), + "databricks_global_init_script": workspace.ResourceGlobalInitScript().ToResource(), + "databricks_grant": catalog.ResourceGrant().ToResource(), + "databricks_grants": catalog.ResourceGrants().ToResource(), + "databricks_group": scim.ResourceGroup().ToResource(), + "databricks_group_instance_profile": aws.ResourceGroupInstanceProfile().ToResource(), + "databricks_group_member": scim.ResourceGroupMember().ToResource(), + "databricks_group_role": scim.ResourceGroupRole().ToResource(), + "databricks_instance_pool": pools.ResourceInstancePool().ToResource(), + "databricks_instance_profile": aws.ResourceInstanceProfile().ToResource(), + "databricks_ip_access_list": access.ResourceIPAccessList().ToResource(), + "databricks_job": jobs.ResourceJob().ToResource(), + "databricks_library": clusters.ResourceLibrary().ToResource(), + "databricks_metastore": catalog.ResourceMetastore().ToResource(), + "databricks_metastore_assignment": catalog.ResourceMetastoreAssignment().ToResource(), + "databricks_metastore_data_access": catalog.ResourceMetastoreDataAccess().ToResource(), + "databricks_mlflow_experiment": mlflow.ResourceMlflowExperiment().ToResource(), + "databricks_mlflow_model": mlflow.ResourceMlflowModel().ToResource(), + "databricks_mlflow_webhook": mlflow.ResourceMlflowWebhook().ToResource(), + "databricks_model_serving": serving.ResourceModelServing().ToResource(), + "databricks_mount": storage.ResourceMount().ToResource(), + "databricks_mws_customer_managed_keys": mws.ResourceMwsCustomerManagedKeys().ToResource(), + "databricks_mws_credentials": mws.ResourceMwsCredentials().ToResource(), + "databricks_mws_log_delivery": mws.ResourceMwsLogDelivery().ToResource(), + "databricks_mws_networks": mws.ResourceMwsNetworks().ToResource(), + "databricks_mws_permission_assignment": mws.ResourceMwsPermissionAssignment().ToResource(), + "databricks_mws_private_access_settings": mws.ResourceMwsPrivateAccessSettings().ToResource(), + "databricks_mws_storage_configurations": mws.ResourceMwsStorageConfigurations().ToResource(), + "databricks_mws_vpc_endpoint": mws.ResourceMwsVpcEndpoint().ToResource(), + "databricks_mws_workspaces": mws.ResourceMwsWorkspaces().ToResource(), + "databricks_notebook": workspace.ResourceNotebook().ToResource(), + "databricks_obo_token": tokens.ResourceOboToken().ToResource(), + "databricks_permission_assignment": access.ResourcePermissionAssignment().ToResource(), + "databricks_permissions": permissions.ResourcePermissions().ToResource(), + "databricks_pipeline": pipelines.ResourcePipeline().ToResource(), + "databricks_provider": catalog.ResourceProvider().ToResource(), + "databricks_recipient": sharing.ResourceRecipient().ToResource(), + "databricks_registered_model": catalog.ResourceRegisteredModel().ToResource(), + "databricks_repo": repos.ResourceRepo().ToResource(), + "databricks_schema": catalog.ResourceSchema().ToResource(), + "databricks_secret": secrets.ResourceSecret().ToResource(), + "databricks_secret_scope": secrets.ResourceSecretScope().ToResource(), + "databricks_secret_acl": secrets.ResourceSecretACL().ToResource(), + "databricks_service_principal": scim.ResourceServicePrincipal().ToResource(), + "databricks_service_principal_role": aws.ResourceServicePrincipalRole().ToResource(), + "databricks_service_principal_secret": tokens.ResourceServicePrincipalSecret().ToResource(), + "databricks_share": catalog.ResourceShare().ToResource(), + "databricks_sql_dashboard": sql.ResourceSqlDashboard().ToResource(), + "databricks_sql_endpoint": sql.ResourceSqlEndpoint().ToResource(), + "databricks_sql_global_config": sql.ResourceSqlGlobalConfig().ToResource(), + "databricks_sql_permissions": access.ResourceSqlPermissions().ToResource(), + "databricks_sql_query": sql.ResourceSqlQuery().ToResource(), + "databricks_sql_alert": sql.ResourceSqlAlert().ToResource(), + "databricks_sql_table": catalog.ResourceSqlTable().ToResource(), + "databricks_sql_visualization": sql.ResourceSqlVisualization().ToResource(), + "databricks_sql_widget": sql.ResourceSqlWidget().ToResource(), + "databricks_storage_credential": catalog.ResourceStorageCredential().ToResource(), + "databricks_system_schema": catalog.ResourceSystemSchema().ToResource(), + "databricks_table": catalog.ResourceTable().ToResource(), + "databricks_token": tokens.ResourceToken().ToResource(), + "databricks_user": scim.ResourceUser().ToResource(), + "databricks_user_instance_profile": aws.ResourceUserInstanceProfile().ToResource(), + "databricks_user_role": aws.ResourceUserRole().ToResource(), + "databricks_volume": catalog.ResourceVolume().ToResource(), + "databricks_workspace_conf": workspace.ResourceWorkspaceConf().ToResource(), + "databricks_workspace_file": workspace.ResourceWorkspaceFile().ToResource(), }, Schema: providerSchema(), } for name, resource := range settings.AllSettingsResources() { - p.ResourcesMap[fmt.Sprintf("databricks_%s_setting", name)] = resource + p.ResourcesMap[fmt.Sprintf("databricks_%s_setting", name)] = resource.ToResource() } p.ConfigureContextFunc = func(ctx context.Context, d *schema.ResourceData) (any, diag.Diagnostics) { if p.TerraformVersion != "" { diff --git a/qa/testing.go b/qa/testing.go index 8f1861b37c..1d3c8d2c38 100644 --- a/qa/testing.go +++ b/qa/testing.go @@ -81,7 +81,7 @@ type ResourceFixture struct { MockAccountClientFunc func(*mocks.MockAccountClient) // The resource the unit test is testing. - Resource *schema.Resource + Resource common.Resource // Set to true if the diff generated in the test will force a recreation // of the resource. @@ -123,10 +123,10 @@ type ResourceFixture struct { } // wrapper type for calling resource methords -type resourceCRUD func(context.Context, *schema.ResourceData, any) diag.Diagnostics +type resourceCRUD func(context.Context, *schema.ResourceData, *common.DatabricksClient) error func (cb resourceCRUD) before(before func(d *schema.ResourceData)) resourceCRUD { - return func(ctx context.Context, d *schema.ResourceData, i any) diag.Diagnostics { + return func(ctx context.Context, d *schema.ResourceData, i *common.DatabricksClient) error { before(d) return cb(ctx, d, i) } @@ -144,7 +144,7 @@ func (f ResourceFixture) prepareExecution() (resourceCRUD, error) { if f.ID != "" { return nil, fmt.Errorf("ID is not available for Create") } - return resourceCRUD(f.Resource.CreateContext).before(func(d *schema.ResourceData) { + return resourceCRUD(f.Resource.Create).before(func(d *schema.ResourceData) { d.MarkNewResource() }), nil case f.Read: @@ -153,7 +153,7 @@ func (f ResourceFixture) prepareExecution() (resourceCRUD, error) { } preRead := f.State f.State = nil - return resourceCRUD(f.Resource.ReadContext).before(func(d *schema.ResourceData) { + return resourceCRUD(f.Resource.Read).before(func(d *schema.ResourceData) { if f.New { d.MarkNewResource() } @@ -165,12 +165,12 @@ func (f ResourceFixture) prepareExecution() (resourceCRUD, error) { if f.ID == "" { return nil, fmt.Errorf("ID must be set for Update") } - return resourceCRUD(f.Resource.UpdateContext).withId(f.ID), nil + return resourceCRUD(f.Resource.Update).withId(f.ID), nil case f.Delete: if f.ID == "" { return nil, fmt.Errorf("ID must be set for Delete") } - return resourceCRUD(f.Resource.DeleteContext).withId(f.ID), nil + return resourceCRUD(f.Resource.Delete).withId(f.ID), nil } return nil, fmt.Errorf("no `Create|Read|Update|Delete: true` specificed") } @@ -290,8 +290,9 @@ func (f ResourceFixture) Apply(t *testing.T) (*schema.ResourceData, error) { if err != nil { return nil, err } + resource := f.Resource.ToResource() if f.State != nil { - diags := f.Resource.Validate(resourceConfig) + diags := resource.Validate(resourceConfig) if diags.HasError() { return nil, fmt.Errorf("invalid config supplied. %s", strings.ReplaceAll(diagsToString(diags), "\"", "")) @@ -302,7 +303,7 @@ func (f ResourceFixture) Apply(t *testing.T) (*schema.ResourceData, error) { Attributes: f.InstanceState, } ctx := context.Background() - diff, err := f.Resource.Diff(ctx, is, resourceConfig, client) + diff, err := resource.Diff(ctx, is, resourceConfig, client) // TODO: f.Resource.Data(is) - check why it doesn't work if err != nil { return nil, err @@ -317,7 +318,7 @@ func (f ResourceFixture) Apply(t *testing.T) (*schema.ResourceData, error) { if err != nil { return nil, err } - err = f.Resource.InternalValidate(f.Resource.Schema, !f.NonWritable) + err = resource.InternalValidate(f.Resource.Schema, !f.NonWritable) if err != nil { return nil, err } @@ -325,14 +326,14 @@ func (f ResourceFixture) Apply(t *testing.T) (*schema.ResourceData, error) { // this is a bit strange, but we'll fix it later diags := execute(ctx, resourceData, client) if diags != nil { - return resourceData, fmt.Errorf(diagsToString(diags)) + return resourceData, fmt.Errorf(diagsToString(diag.FromErr(diags))) } } if resourceData.Id() == "" && !f.Removed { return resourceData, fmt.Errorf("resource is not expected to be removed") } newState := resourceData.State() - diff, err = schemaMap.Diff(ctx, newState, resourceConfig, f.Resource.CustomizeDiff, client, true) + diff, err = schemaMap.Diff(ctx, newState, resourceConfig, resource.CustomizeDiff, client, true) if err != nil { return nil, err } @@ -427,17 +428,17 @@ var HTTPFailures = []HTTPFixture{ } // ResourceCornerCases checks for corner cases of error handling. Optional field name used to create error -func ResourceCornerCases(t *testing.T, resource *schema.Resource, cc ...CornerCase) { +func ResourceCornerCases(t *testing.T, resource common.Resource, cc ...CornerCase) { config := map[string]string{ "id": "x", "expect_error": "i'm a teapot", "account_id": "", } - m := map[string]func(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics{ - "create": resource.CreateContext, - "read": resource.ReadContext, - "update": resource.UpdateContext, - "delete": resource.DeleteContext, + m := map[string]func(ctx context.Context, d *schema.ResourceData, m *common.DatabricksClient) error{ + "create": resource.Create, + "read": resource.Read, + "update": resource.Update, + "delete": resource.Delete, } for _, corner := range cc { if corner.part == "skip_crud" { @@ -445,8 +446,9 @@ func ResourceCornerCases(t *testing.T, resource *schema.Resource, cc ...CornerCa } config[corner.part] = corner.value } + r := resource.ToResource() HTTPFixturesApply(t, HTTPFailures, func(ctx context.Context, client *common.DatabricksClient) { - validData := resource.TestResourceData() + validData := r.TestResourceData() client.Config.AccountID = config["account_id"] for n, v := range m { if v == nil { @@ -455,7 +457,7 @@ func ResourceCornerCases(t *testing.T, resource *schema.Resource, cc ...CornerCa validData.SetId(config["id"]) diags := v(ctx, validData, client) if assert.Len(t, diags, 1) { - assert.Containsf(t, diags[0].Summary, config["expect_error"], + assert.Containsf(t, diag.FromErr(diags)[0].Summary, config["expect_error"], "%s didn't handle correct error on valid data", n) } } diff --git a/qa/testing_test.go b/qa/testing_test.go index 73b274f669..9229561b54 100644 --- a/qa/testing_test.go +++ b/qa/testing_test.go @@ -65,20 +65,24 @@ func TestResourceFixture_Hint(t *testing.T) { assert.True(t, t2.Failed()) } -var noopResource = &schema.Resource{ +func noopContext(_ context.Context, _ *schema.ResourceData, _ *common.DatabricksClient) error { + return nil +} + +var noopResource = common.Resource{ Schema: map[string]*schema.Schema{ "dummy": { Type: schema.TypeBool, Required: true, }, }, - ReadContext: schema.NoopContext, - CreateContext: schema.NoopContext, - UpdateContext: schema.NoopContext, - DeleteContext: schema.NoopContext, + Read: noopContext, + Create: noopContext, + Update: noopContext, + Delete: noopContext, } -var noopContextResource = &schema.Resource{ +var noopContextResource = common.Resource{ Schema: map[string]*schema.Schema{ "trigger": { Type: schema.TypeString, @@ -90,14 +94,14 @@ var noopContextResource = &schema.Resource{ Required: true, }, }, - ReadContext: schema.NoopContext, - CreateContext: schema.NoopContext, - UpdateContext: func(_ context.Context, d *schema.ResourceData, _ any) diag.Diagnostics { + Read: noopContext, + Create: noopContext, + Update: func(_ context.Context, d *schema.ResourceData, _ *common.DatabricksClient) error { // nolint d.Set("trigger", "corrupt") return nil }, - DeleteContext: schema.NoopContext, + Delete: noopContext, } func TestResourceFixture_ID(t *testing.T) { @@ -319,7 +323,7 @@ func TestResourceCornerCases(t *testing.T) { Required: true, }, }, - }.ToResource(), + }, CornerCaseID("x"), CornerCaseExpectError("i'm a teapot"), CornerCaseSkipCRUD("head")) diff --git a/repos/resource_git_credential.go b/repos/resource_git_credential.go index ad2232cc48..38f7b94044 100644 --- a/repos/resource_git_credential.go +++ b/repos/resource_git_credential.go @@ -11,7 +11,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func ResourceGitCredential() *schema.Resource { +func ResourceGitCredential() common.Resource { s := common.StructToSchema(workspace.CreateCredentials{}, func(s map[string]*schema.Schema) map[string]*schema.Schema { s["force"] = &schema.Schema{ Type: schema.TypeBool, @@ -105,5 +105,5 @@ func ResourceGitCredential() *schema.Resource { } return w.GitCredentials.DeleteByCredentialId(ctx, cred_id) }, - }.ToResource() + } } diff --git a/repos/resource_repo.go b/repos/resource_repo.go index 42bfcc14d5..46e6551125 100644 --- a/repos/resource_repo.go +++ b/repos/resource_repo.go @@ -167,7 +167,7 @@ func validatePath(i interface{}, k string) (_ []string, errors []error) { return } -func ResourceRepo() *schema.Resource { +func ResourceRepo() common.Resource { s := common.StructToSchema(ReposInformation{}, func(s map[string]*schema.Schema) map[string]*schema.Schema { s["url"].ValidateFunc = validation.IsURLWithScheme([]string{"https", "http"}) s["git_provider"].DiffSuppressFunc = common.EqualFoldDiffSuppress @@ -259,5 +259,5 @@ func ResourceRepo() *schema.Resource { Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { return NewReposAPI(ctx, c).Delete(d.Id()) }, - }.ToResource() + } } diff --git a/scim/data_current_user.go b/scim/data_current_user.go index fdaa4917ed..7a6066c1bd 100644 --- a/scim/data_current_user.go +++ b/scim/data_current_user.go @@ -7,15 +7,14 @@ import ( "strings" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) var nonAlphanumeric = regexp.MustCompile(`\W`) // DataSourceCurrentUser returns information about caller identity -func DataSourceCurrentUser() *schema.Resource { - return &schema.Resource{ +func DataSourceCurrentUser() common.Resource { + return common.Resource{ Schema: map[string]*schema.Schema{ "user_name": { Type: schema.TypeString, @@ -46,15 +45,14 @@ func DataSourceCurrentUser() *schema.Resource { Computed: true, }, }, - ReadContext: func(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - c := m.(*common.DatabricksClient) + Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { w, err := c.WorkspaceClient() if err != nil { - return diag.FromErr(err) + return err } me, err := w.CurrentUser.Me(ctx) if err != nil { - return diag.FromErr(err) + return err } d.Set("user_name", me.UserName) d.Set("home", fmt.Sprintf("/Users/%s", me.UserName)) diff --git a/scim/data_group.go b/scim/data_group.go index d7ffe2e4f3..8072380b9e 100644 --- a/scim/data_group.go +++ b/scim/data_group.go @@ -7,13 +7,12 @@ import ( "strings" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) // DataSourceGroup returns information about group specified by display name -func DataSourceGroup() *schema.Resource { +func DataSourceGroup() common.Resource { type entity struct { DisplayName string `json:"display_name"` Recursive bool `json:"recursive,omitempty"` @@ -37,16 +36,16 @@ func DataSourceGroup() *schema.Resource { return s }) - return &schema.Resource{ + return common.Resource{ Schema: s, - ReadContext: func(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { + Read: func(ctx context.Context, d *schema.ResourceData, m *common.DatabricksClient) error { var this entity common.DataToStructPointer(d, s, &this) groupsAPI := NewGroupsAPI(ctx, m) groupAttributes := "members,roles,entitlements,externalId" group, err := groupsAPI.ReadByDisplayName(this.DisplayName, groupAttributes) if err != nil { - return diag.FromErr(err) + return err } d.SetId(group.ID) queue := []Group{group} @@ -74,7 +73,7 @@ func DataSourceGroup() *schema.Resource { if this.Recursive { childGroup, err := groupsAPI.Read(x.Value, groupAttributes) if err != nil { - return diag.FromErr(err) + return err } queue = append(queue, childGroup) } @@ -90,7 +89,7 @@ func DataSourceGroup() *schema.Resource { sort.Strings(this.InstanceProfiles) err = common.StructToData(this, s, d) if err != nil { - return diag.FromErr(err) + return err } return nil }, diff --git a/scim/data_service_principal.go b/scim/data_service_principal.go index f2c139fdb1..68f989ed96 100644 --- a/scim/data_service_principal.go +++ b/scim/data_service_principal.go @@ -5,11 +5,10 @@ import ( "fmt" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) // DataSourceServicePrincipal returns information about the spn specified by the application_id -func DataSourceServicePrincipal() *schema.Resource { +func DataSourceServicePrincipal() common.Resource { type spnData struct { ApplicationID string `json:"application_id,omitempty" tf:"computed"` DisplayName string `json:"display_name,omitempty" tf:"computed"` diff --git a/scim/data_service_principals.go b/scim/data_service_principals.go index d0223fad7f..f01d56795b 100644 --- a/scim/data_service_principals.go +++ b/scim/data_service_principals.go @@ -6,11 +6,10 @@ import ( "sort" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) // DataSourceServicePrincipals searches for service principals based on display_name -func DataSourceServicePrincipals() *schema.Resource { +func DataSourceServicePrincipals() common.Resource { type spnsData struct { DisplayNameContains string `json:"display_name_contains,omitempty" tf:"computed"` ApplicationIDs []string `json:"application_ids,omitempty" tf:"computed,slice_set"` diff --git a/scim/data_user.go b/scim/data_user.go index 544d9a9a8b..71e7fddfc3 100644 --- a/scim/data_user.go +++ b/scim/data_user.go @@ -5,7 +5,7 @@ import ( "fmt" "strings" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/databricks/terraform-provider-databricks/common" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -26,8 +26,8 @@ func getUser(usersAPI UsersAPI, id, name string) (user User, err error) { } // DataSourceUser returns information about user specified by user name -func DataSourceUser() *schema.Resource { - return &schema.Resource{ +func DataSourceUser() common.Resource { + return common.Resource{ Schema: map[string]*schema.Schema{ "user_name": { Type: schema.TypeString, @@ -68,11 +68,11 @@ func DataSourceUser() *schema.Resource { Computed: true, }, }, - ReadContext: func(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { + Read: func(ctx context.Context, d *schema.ResourceData, m *common.DatabricksClient) error { usersAPI := NewUsersAPI(ctx, m) user, err := getUser(usersAPI, d.Get("user_id").(string), d.Get("user_name").(string)) if err != nil { - return diag.FromErr(err) + return err } d.Set("user_name", user.UserName) d.Set("display_name", user.DisplayName) diff --git a/scim/resource_entitlement.go b/scim/resource_entitlement.go index 6bc88acd05..40c7164c3b 100644 --- a/scim/resource_entitlement.go +++ b/scim/resource_entitlement.go @@ -10,7 +10,7 @@ import ( ) // ResourceGroup manages user groups -func ResourceEntitlements() *schema.Resource { +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"` @@ -67,7 +67,7 @@ func ResourceEntitlements() *schema.Resource { return patchEntitlements(ctx, d, c, "remove") }, Schema: entitlementSchema, - }.ToResource() + } } func patchEntitlements(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient, op string) error { diff --git a/scim/resource_group.go b/scim/resource_group.go index f495edcd10..2c56f931b7 100644 --- a/scim/resource_group.go +++ b/scim/resource_group.go @@ -11,7 +11,7 @@ import ( ) // ResourceGroup manages user groups -func ResourceGroup() *schema.Resource { +func ResourceGroup() common.Resource { type entity struct { DisplayName string `json:"display_name" tf:"force_new"` ExternalID string `json:"external_id,omitempty" tf:"force_new,suppress_diff"` @@ -74,7 +74,7 @@ func ResourceGroup() *schema.Resource { return NewGroupsAPI(ctx, c).Delete(d.Id()) }, Schema: groupSchema, - }.ToResource() + } } func createForceOverridesManuallyAddedGroup(err error, d *schema.ResourceData, groupsAPI GroupsAPI, g Group) error { diff --git a/scim/resource_group_member.go b/scim/resource_group_member.go index f707b4e519..e74333204d 100644 --- a/scim/resource_group_member.go +++ b/scim/resource_group_member.go @@ -6,12 +6,10 @@ import ( "github.com/databricks/databricks-sdk-go/apierr" "github.com/databricks/terraform-provider-databricks/common" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) // ResourceGroupMember bind group with member -func ResourceGroupMember() *schema.Resource { +func ResourceGroupMember() common.Resource { return common.NewPairID("group_id", "member_id").BindResource(common.BindResource{ CreateContext: func(ctx context.Context, groupID, memberID string, c *common.DatabricksClient) error { return NewGroupsAPI(ctx, c).Patch(groupID, PatchRequest("add", "members", memberID)) diff --git a/scim/resource_group_role.go b/scim/resource_group_role.go index bbebb0e2bb..cbca1e325e 100644 --- a/scim/resource_group_role.go +++ b/scim/resource_group_role.go @@ -6,11 +6,10 @@ import ( "github.com/databricks/databricks-sdk-go/apierr" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) // ResourceGroupRole bind group with role -func ResourceGroupRole() *schema.Resource { +func ResourceGroupRole() common.Resource { return common.NewPairID("group_id", "role").BindResource(common.BindResource{ CreateContext: func(ctx context.Context, groupID, role string, c *common.DatabricksClient) error { return NewGroupsAPI(ctx, c).Patch(groupID, PatchRequest("add", "roles", role)) diff --git a/scim/resource_group_test.go b/scim/resource_group_test.go index cb22b65da3..94bf186d61 100644 --- a/scim/resource_group_test.go +++ b/scim/resource_group_test.go @@ -362,7 +362,7 @@ func TestCreateForceOverwriteCannotListGroups(t *testing.T) { }, }, }, func(ctx context.Context, client *common.DatabricksClient) { - d := ResourceGroup().TestResourceData() + d := ResourceGroup().ToResource().TestResourceData() d.Set("force", true) err := createForceOverridesManuallyAddedGroup( fmt.Errorf("Group with name abc already exists."), @@ -402,7 +402,7 @@ func TestCreateForceOverwriteFindsAndSetsGroupID(t *testing.T) { }, }, }, func(ctx context.Context, client *common.DatabricksClient) { - d := ResourceGroup().TestResourceData() + d := ResourceGroup().ToResource().TestResourceData() d.Set("force", true) d.Set("display_name", "abc") err := createForceOverridesManuallyAddedGroup( diff --git a/scim/resource_service_principal.go b/scim/resource_service_principal.go index 8bef42d3c3..cec79c4b5a 100644 --- a/scim/resource_service_principal.go +++ b/scim/resource_service_principal.go @@ -95,7 +95,7 @@ func (a ServicePrincipalsAPI) Delete(servicePrincipalID string) error { } // ResourceServicePrincipal manages service principals within workspace -func ResourceServicePrincipal() *schema.Resource { +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,force_new"` @@ -236,7 +236,7 @@ func ResourceServicePrincipal() *schema.Resource { } return err }, - }.ToResource() + } } func createForceOverridesManuallyAddedServicePrincipal(err error, d *schema.ResourceData, spAPI ServicePrincipalsAPI, u User) error { diff --git a/scim/resource_service_principal_test.go b/scim/resource_service_principal_test.go index 57ee021804..91b52cb9a7 100644 --- a/scim/resource_service_principal_test.go +++ b/scim/resource_service_principal_test.go @@ -543,7 +543,7 @@ func TestResourceServicePrincipalDelete_NonExistingDir(t *testing.T) { } func TestCreateForceOverridesManuallyAddedServicePrincipalErrorNotMatched(t *testing.T) { - d := ResourceUser().TestResourceData() + d := ResourceUser().ToResource().TestResourceData() d.Set("force", true) rerr := createForceOverridesManuallyAddedServicePrincipal( fmt.Errorf("nonsense"), d, @@ -563,7 +563,7 @@ func TestCreateForceOverwriteCannotListServicePrincipals(t *testing.T) { }, }, }, func(ctx context.Context, client *common.DatabricksClient) { - d := ResourceUser().TestResourceData() + d := ResourceUser().ToResource().TestResourceData() d.Set("force", true) err := createForceOverridesManuallyAddedServicePrincipal( fmt.Errorf("Service principal with application ID %s already exists.", appID), @@ -585,7 +585,7 @@ func TestCreateForceOverwriteCannotListAccServicePrincipals(t *testing.T) { }, }, }, func(ctx context.Context, client *common.DatabricksClient) { - d := ResourceUser().TestResourceData() + d := ResourceUser().ToResource().TestResourceData() d.Set("force", true) err := createForceOverridesManuallyAddedServicePrincipal( fmt.Errorf("Service principal with application ID %s already exists.", appID), @@ -626,7 +626,7 @@ func TestCreateForceOverwriteFindsAndSetsServicePrincipalID(t *testing.T) { }, }, }, func(ctx context.Context, client *common.DatabricksClient) { - d := ResourceUser().TestResourceData() + d := ResourceUser().ToResource().TestResourceData() d.Set("force", true) d.Set("application_id", appID) err := createForceOverridesManuallyAddedServicePrincipal( diff --git a/scim/resource_user.go b/scim/resource_user.go index edc54d4395..f266310700 100644 --- a/scim/resource_user.go +++ b/scim/resource_user.go @@ -23,7 +23,7 @@ const ( ) // ResourceUser manages users within workspace -func ResourceUser() *schema.Resource { +func ResourceUser() common.Resource { type entity struct { UserName string `json:"user_name" tf:"force_new"` DisplayName string `json:"display_name,omitempty" tf:"computed"` @@ -162,7 +162,7 @@ func ResourceUser() *schema.Resource { } return err }, - }.ToResource() + } } func createForceOverridesManuallyAddedUser(err error, d *schema.ResourceData, usersAPI UsersAPI, u User) error { diff --git a/scim/resource_user_test.go b/scim/resource_user_test.go index 04edb795c7..fafa6b8674 100644 --- a/scim/resource_user_test.go +++ b/scim/resource_user_test.go @@ -620,7 +620,7 @@ func TestResourceUserDelete_ForceDeleteHomeDir(t *testing.T) { } func TestCreateForceOverridesManuallyAddedUserErrorNotMatched(t *testing.T) { - d := ResourceUser().TestResourceData() + d := ResourceUser().ToResource().TestResourceData() d.Set("force", true) rerr := createForceOverridesManuallyAddedUser( fmt.Errorf("nonsense"), d, @@ -639,7 +639,7 @@ func TestCreateForceOverwriteCannotListUsers(t *testing.T) { }, }, }, func(ctx context.Context, client *common.DatabricksClient) { - d := ResourceUser().TestResourceData() + d := ResourceUser().ToResource().TestResourceData() d.Set("force", true) err := createForceOverridesManuallyAddedUser( fmt.Errorf(userExistsErrorMessage("me@example.com", false)), @@ -660,7 +660,7 @@ func TestCreateForceOverwriteCannotListAccUsers(t *testing.T) { }, }, }, func(ctx context.Context, client *common.DatabricksClient) { - d := ResourceUser().TestResourceData() + d := ResourceUser().ToResource().TestResourceData() d.Set("force", true) err := createForceOverridesManuallyAddedUser( fmt.Errorf(userExistsErrorMessage("me@example.com", true)), @@ -700,7 +700,7 @@ func TestCreateForceOverwriteFindsAndSetsID(t *testing.T) { }, }, }, func(ctx context.Context, client *common.DatabricksClient) { - d := ResourceUser().TestResourceData() + d := ResourceUser().ToResource().TestResourceData() d.Set("force", true) d.Set("user_name", "me@example.com") err := createForceOverridesManuallyAddedUser( @@ -742,7 +742,7 @@ func TestCreateForceOverwriteFindsAndSetsAccID(t *testing.T) { }, }, }, func(ctx context.Context, client *common.DatabricksClient) { - d := ResourceUser().TestResourceData() + d := ResourceUser().ToResource().TestResourceData() d.Set("force", true) d.Set("user_name", "me@example.com") err := createForceOverridesManuallyAddedUser( diff --git a/secrets/resource_secret.go b/secrets/resource_secret.go index e0ee217cc6..879cff462d 100644 --- a/secrets/resource_secret.go +++ b/secrets/resource_secret.go @@ -114,7 +114,7 @@ func (a SecretsAPI) Read(scope string, key string) (SecretMetadata, error) { } // ResourceSecret manages secrets -func ResourceSecret() *schema.Resource { +func ResourceSecret() common.Resource { p := common.NewPairSeparatedID("scope", "key", "|||") return common.Resource{ Schema: map[string]*schema.Schema{ @@ -173,5 +173,5 @@ func ResourceSecret() *schema.Resource { } return NewSecretsAPI(ctx, c).Delete(scope, key) }, - }.ToResource() + } } diff --git a/secrets/resource_secret_acl.go b/secrets/resource_secret_acl.go index 76e70b64a7..6f5d3d3faf 100644 --- a/secrets/resource_secret_acl.go +++ b/secrets/resource_secret_acl.go @@ -56,7 +56,7 @@ func (a SecretAclsAPI) List(scope string) ([]ACLItem, error) { } // ResourceSecretACL manages access to secret scopes -func ResourceSecretACL() *schema.Resource { +func ResourceSecretACL() common.Resource { p := common.NewPairSeparatedID("scope", "principal", "|||") return common.Resource{ Schema: map[string]*schema.Schema{ @@ -105,5 +105,5 @@ func ResourceSecretACL() *schema.Resource { } return NewSecretAclsAPI(ctx, c).Delete(scope, principal) }, - }.ToResource() + } } diff --git a/secrets/resource_secret_scope.go b/secrets/resource_secret_scope.go index c3906b2cd3..fb9e653d0a 100644 --- a/secrets/resource_secret_scope.go +++ b/secrets/resource_secret_scope.go @@ -108,7 +108,7 @@ var validScope = validation.StringMatch(regexp.MustCompile(`^[\w\.@_/-]{1,128}$` "and may not exceed 128 characters.") // ResourceSecretScope manages secret scopes -func ResourceSecretScope() *schema.Resource { +func ResourceSecretScope() common.Resource { s := common.StructToSchema(SecretScope{}, func(s map[string]*schema.Schema) map[string]*schema.Schema { // TODO: DiffSuppressFunc for initial_manage_principal & importing // nolint @@ -139,5 +139,5 @@ func ResourceSecretScope() *schema.Resource { Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { return NewSecretScopesAPI(ctx, c).Delete(d.Id()) }, - }.ToResource() + } } diff --git a/serving/resource_model_serving.go b/serving/resource_model_serving.go index 760457fc7c..bd13c687d2 100644 --- a/serving/resource_model_serving.go +++ b/serving/resource_model_serving.go @@ -12,7 +12,7 @@ import ( const DefaultProvisionTimeout = 45 * time.Minute -func ResourceModelServing() *schema.Resource { +func ResourceModelServing() common.Resource { s := common.StructToSchema( serving.CreateServingEndpoint{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { @@ -94,5 +94,5 @@ func ResourceModelServing() *schema.Resource { Create: schema.DefaultTimeout(DefaultProvisionTimeout), Update: schema.DefaultTimeout(DefaultProvisionTimeout), }, - }.ToResource() + } } diff --git a/settings/all_settings.go b/settings/all_settings.go index e424760a19..90e06ee64f 100644 --- a/settings/all_settings.go +++ b/settings/all_settings.go @@ -3,7 +3,7 @@ package settings import ( "github.com/databricks/databricks-sdk-go" "github.com/databricks/databricks-sdk-go/service/settings" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/databricks/terraform-provider-databricks/common" ) // Instructions for adding a new setting: @@ -13,8 +13,8 @@ import ( // If the setting name is user-settable, it will be provided in the third argument to the updateFunc method. If not, you must set the // SettingName field appropriately. You must also set AllowMissing: true and the field mask to the field to update. // 3. Add a new entry to the AllSettingsResources map below. The final resource name will be "databricks__setting". -func AllSettingsResources() map[string]*schema.Resource { - return map[string]*schema.Resource{ +func AllSettingsResources() map[string]common.Resource { + return map[string]common.Resource{ "default_namespace": makeSettingResource[settings.DefaultNamespaceSetting, *databricks.WorkspaceClient](defaultNamespaceSetting), } } diff --git a/settings/generic_setting.go b/settings/generic_setting.go index 6095c88c4d..095080ca00 100644 --- a/settings/generic_setting.go +++ b/settings/generic_setting.go @@ -168,7 +168,7 @@ func (w accountSetting[T]) SetETag(t *T, newEtag string) { var _ accountSettingDefinition[struct{}] = accountSetting[struct{}]{} -func makeSettingResource[T, U any](defn genericSettingDefinition[T, U]) *schema.Resource { +func makeSettingResource[T, U any](defn genericSettingDefinition[T, U]) common.Resource { resourceSchema := common.StructToSchema(defn.SettingStruct(), func(s map[string]*schema.Schema) map[string]*schema.Schema { s["etag"].Computed = true @@ -307,5 +307,5 @@ func makeSettingResource[T, U any](defn genericSettingDefinition[T, U]) *schema. d.SetId(etag) return nil }, - }.ToResource() + } } diff --git a/sharing/resource_recipient.go b/sharing/resource_recipient.go index dce799d533..5f5f37662a 100644 --- a/sharing/resource_recipient.go +++ b/sharing/resource_recipient.go @@ -34,7 +34,7 @@ type RecipientInfo struct { IpAccessList *IpAccessList `json:"ip_access_list,omitempty"` } -func ResourceRecipient() *schema.Resource { +func ResourceRecipient() common.Resource { recipientSchema := common.StructToSchema(RecipientInfo{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { m["authentication_type"].ValidateFunc = validation.StringInSlice([]string{"TOKEN", "DATABRICKS"}, false) return m @@ -110,5 +110,5 @@ func ResourceRecipient() *schema.Resource { } return w.Recipients.DeleteByName(ctx, d.Id()) }, - }.ToResource() + } } diff --git a/sql/data_sql_warehouse.go b/sql/data_sql_warehouse.go index f3fa78fb30..99074ecd2a 100644 --- a/sql/data_sql_warehouse.go +++ b/sql/data_sql_warehouse.go @@ -7,7 +7,6 @@ import ( "github.com/databricks/databricks-sdk-go" "github.com/databricks/databricks-sdk-go/service/sql" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) // Note that these fields are both marked as computed/optional because users can specify either the name or the ID @@ -17,7 +16,7 @@ type sqlWarehouseDataParams struct { Name string `json:"name" tf:"computed,optional"` } -func DataSourceWarehouse() *schema.Resource { +func DataSourceWarehouse() common.Resource { return common.WorkspaceDataWithParams(func(ctx context.Context, data sqlWarehouseDataParams, w *databricks.WorkspaceClient) (*SqlWarehouse, error) { if data.Id == "" && data.Name == "" { return nil, fmt.Errorf("either 'id' or 'name' should be provided") diff --git a/sql/data_sql_warehouses.go b/sql/data_sql_warehouses.go index 5cbcb9cbbe..a3ea03e207 100644 --- a/sql/data_sql_warehouses.go +++ b/sql/data_sql_warehouses.go @@ -8,10 +8,9 @@ import ( "github.com/databricks/databricks-sdk-go" "github.com/databricks/databricks-sdk-go/service/sql" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func DataSourceWarehouses() *schema.Resource { +func DataSourceWarehouses() common.Resource { type warehousesData struct { WarehouseNameContains string `json:"warehouse_name_contains,omitempty"` Ids []string `json:"ids,omitempty" tf:"computed,slice_set"` diff --git a/sql/resource_sql_alerts.go b/sql/resource_sql_alerts.go index 6304863012..08c5b6f4ff 100644 --- a/sql/resource_sql_alerts.go +++ b/sql/resource_sql_alerts.go @@ -122,7 +122,7 @@ func (a *AlertEntity) fromAPIObject(apiAlert *sql.Alert, s map[string]*schema.Sc return common.StructToData(a, s, data) } -func ResourceSqlAlert() *schema.Resource { +func ResourceSqlAlert() common.Resource { s := common.StructToSchema(AlertEntity{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { options := m["options"].Elem.(*schema.Resource) options.Schema["op"].ValidateFunc = validation.StringInSlice([]string{">", ">=", "<", "<=", "==", "!="}, true) @@ -180,5 +180,5 @@ func ResourceSqlAlert() *schema.Resource { return w.Alerts.DeleteByAlertId(ctx, data.Id()) }, Schema: s, - }.ToResource() + } } diff --git a/sql/resource_sql_dashboard.go b/sql/resource_sql_dashboard.go index 4f774482ba..50bb644d74 100644 --- a/sql/resource_sql_dashboard.go +++ b/sql/resource_sql_dashboard.go @@ -96,7 +96,7 @@ func (a DashboardAPI) Delete(dashboardID string) error { return a.client.Delete(a.context, fmt.Sprintf("/preview/sql/dashboards/%s", dashboardID), nil) } -func ResourceSqlDashboard() *schema.Resource { +func ResourceSqlDashboard() common.Resource { s := common.StructToSchema( DashboardEntity{}, common.NoCustomize) @@ -141,5 +141,5 @@ func ResourceSqlDashboard() *schema.Resource { return NewDashboardAPI(ctx, c).Delete(data.Id()) }, Schema: s, - }.ToResource() + } } diff --git a/sql/resource_sql_endpoint.go b/sql/resource_sql_endpoint.go index 444e2e6ef7..fd48f45c08 100644 --- a/sql/resource_sql_endpoint.go +++ b/sql/resource_sql_endpoint.go @@ -51,7 +51,7 @@ func resolveDataSourceID(ctx context.Context, w *databricks.WorkspaceClient, war return "", fmt.Errorf("no data source found for endpoint %s", warehouseId) } -func ResourceSqlEndpoint() *schema.Resource { +func ResourceSqlEndpoint() common.Resource { s := common.StructToSchema(SqlWarehouse{}, func( m map[string]*schema.Schema) map[string]*schema.Schema { m["id"].Computed = true @@ -145,5 +145,5 @@ func ResourceSqlEndpoint() *schema.Resource { return w.Warehouses.DeleteById(ctx, d.Id()) }, Schema: s, - }.ToResource() + } } diff --git a/sql/resource_sql_global_config.go b/sql/resource_sql_global_config.go index 66fb23cac6..03fd06af23 100644 --- a/sql/resource_sql_global_config.go +++ b/sql/resource_sql_global_config.go @@ -111,7 +111,7 @@ func (a globalConfigAPI) Get() (GlobalConfig, error) { return gc, nil } -func ResourceSqlGlobalConfig() *schema.Resource { +func ResourceSqlGlobalConfig() common.Resource { s := common.StructToSchema(GlobalConfig{}, func( m map[string]*schema.Schema) map[string]*schema.Schema { m["enable_serverless_compute"].Deprecated = "This field is intended as an internal API " + @@ -142,5 +142,5 @@ func ResourceSqlGlobalConfig() *schema.Resource { return NewSqlGlobalConfigAPI(ctx, c).Set(GlobalConfig{SecurityPolicy: "DATA_ACCESS_CONTROL"}) }, Schema: s, - }.ToResource() + } } diff --git a/sql/resource_sql_query.go b/sql/resource_sql_query.go index 4c74e4aaac..8fc78eea80 100644 --- a/sql/resource_sql_query.go +++ b/sql/resource_sql_query.go @@ -510,7 +510,7 @@ func (a QueryAPI) Delete(queryID string) error { return a.client.Delete(a.context, fmt.Sprintf("/preview/sql/queries/%s", queryID), nil) } -func ResourceSqlQuery() *schema.Resource { +func ResourceSqlQuery() common.Resource { s := common.StructToSchema( QueryEntity{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { @@ -587,5 +587,5 @@ func ResourceSqlQuery() *schema.Resource { return NewQueryAPI(ctx, c).Delete(data.Id()) }, Schema: s, - }.ToResource() + } } diff --git a/sql/resource_sql_visualization.go b/sql/resource_sql_visualization.go index 64cc7bca59..d0025870b3 100644 --- a/sql/resource_sql_visualization.go +++ b/sql/resource_sql_visualization.go @@ -145,7 +145,7 @@ func suppressWhitespaceChangesInJSON(_, old, new string, d *schema.ResourceData) return bytes.Equal(oldp, newp) } -func ResourceSqlVisualization() *schema.Resource { +func ResourceSqlVisualization() common.Resource { p := common.NewPairSeparatedID("query_id", "visualization_id", "/") s := common.StructToSchema( VisualizationEntity{}, @@ -217,5 +217,5 @@ func ResourceSqlVisualization() *schema.Resource { return NewVisualizationAPI(ctx, c).Delete(visualizationID) }, Schema: s, - }.ToResource() + } } diff --git a/sql/resource_sql_widget.go b/sql/resource_sql_widget.go index 782866c5a7..e9c3417d61 100644 --- a/sql/resource_sql_widget.go +++ b/sql/resource_sql_widget.go @@ -251,7 +251,7 @@ func (a WidgetAPI) Delete(widgetID string) error { return a.client.Delete(a.context, fmt.Sprintf("/preview/sql/widgets/%s", widgetID), nil) } -func ResourceSqlWidget() *schema.Resource { +func ResourceSqlWidget() common.Resource { p := common.NewPairSeparatedID("dashboard_id", "widget_id", "/") s := common.StructToSchema( WidgetEntity{}, @@ -329,5 +329,5 @@ func ResourceSqlWidget() *schema.Resource { return NewWidgetAPI(ctx, c).Delete(widgetID) }, Schema: s, - }.ToResource() + } } diff --git a/storage/adls_gen1_mount.go b/storage/adls_gen1_mount.go index 39d300c902..8bb988e66c 100644 --- a/storage/adls_gen1_mount.go +++ b/storage/adls_gen1_mount.go @@ -45,8 +45,8 @@ func (m AzureADLSGen1Mount) Config(client *common.DatabricksClient) map[string]s } // ResourceAzureAdlsGen1Mount creates the resource -func ResourceAzureAdlsGen1Mount() *schema.Resource { - return deprecatedMountTesource(commonMountResource(AzureADLSGen1Mount{}, map[string]*schema.Schema{ +func ResourceAzureAdlsGen1Mount() common.Resource { + return deprecatedMountResource(commonMountResource(AzureADLSGen1Mount{}, map[string]*schema.Schema{ "cluster_id": { Type: schema.TypeString, Optional: true, diff --git a/storage/adls_gen2_mount.go b/storage/adls_gen2_mount.go index b713e3d7d7..0efd350ee9 100644 --- a/storage/adls_gen2_mount.go +++ b/storage/adls_gen2_mount.go @@ -47,8 +47,8 @@ func (m AzureADLSGen2Mount) Config(client *common.DatabricksClient) map[string]s } // ResourceAzureAdlsGen2Mount creates the resource -func ResourceAzureAdlsGen2Mount() *schema.Resource { - return deprecatedMountTesource(commonMountResource(AzureADLSGen2Mount{}, map[string]*schema.Schema{ +func ResourceAzureAdlsGen2Mount() common.Resource { + return deprecatedMountResource(commonMountResource(AzureADLSGen2Mount{}, map[string]*schema.Schema{ "cluster_id": { Type: schema.TypeString, Optional: true, diff --git a/storage/aws_s3_mount.go b/storage/aws_s3_mount.go index 93851f702e..d4a3c5b70a 100644 --- a/storage/aws_s3_mount.go +++ b/storage/aws_s3_mount.go @@ -7,7 +7,6 @@ import ( "github.com/databricks/terraform-provider-databricks/clusters" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -36,9 +35,9 @@ func (m AWSIamMount) Config(client *common.DatabricksClient) map[string]string { } // ResourceAWSS3Mount ... -func ResourceAWSS3Mount() *schema.Resource { +func ResourceAWSS3Mount() common.Resource { tpl := AWSIamMount{} - r := &schema.Resource{ + r := common.Resource{ DeprecationMessage: "Resource is deprecated and will be removed in further versions. " + "Please rewrite configuration using `databricks_mount` resource. More info at " + "https://registry.terraform.io/providers/databricks/databricks/latest/docs/" + @@ -76,21 +75,21 @@ func ResourceAWSS3Mount() *schema.Resource { StateContext: schema.ImportStatePassthroughContext, }, } - r.CreateContext = func(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { + r.Create = func(ctx context.Context, d *schema.ResourceData, m *common.DatabricksClient) error { if err := preprocessS3Mount(ctx, d, m); err != nil { - return diag.FromErr(err) + return err } return mountCreate(tpl, r)(ctx, d, m) } - r.ReadContext = func(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { + r.Read = func(ctx context.Context, d *schema.ResourceData, m *common.DatabricksClient) error { if err := preprocessS3Mount(ctx, d, m); err != nil { - return diag.FromErr(err) + return err } return mountRead(tpl, r)(ctx, d, m) } - r.DeleteContext = func(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { + r.Delete = func(ctx context.Context, d *schema.ResourceData, m *common.DatabricksClient) error { if err := preprocessS3Mount(ctx, d, m); err != nil { - return diag.FromErr(err) + return err } return mountDelete(tpl, r)(ctx, d, m) } diff --git a/storage/azure_blob_mount.go b/storage/azure_blob_mount.go index 61f3ce8fe4..c15f3c11f5 100644 --- a/storage/azure_blob_mount.go +++ b/storage/azure_blob_mount.go @@ -46,8 +46,8 @@ func (m AzureBlobMount) Config(client *common.DatabricksClient) map[string]strin } // ResourceAzureBlobMount creates the resource -func ResourceAzureBlobMount() *schema.Resource { - return deprecatedMountTesource(commonMountResource(AzureBlobMount{}, map[string]*schema.Schema{ +func ResourceAzureBlobMount() common.Resource { + return deprecatedMountResource(commonMountResource(AzureBlobMount{}, map[string]*schema.Schema{ "cluster_id": { Type: schema.TypeString, Optional: true, diff --git a/storage/data_dbfs_file.go b/storage/data_dbfs_file.go index 26c11e040d..16c879331e 100644 --- a/storage/data_dbfs_file.go +++ b/storage/data_dbfs_file.go @@ -3,22 +3,23 @@ package storage import ( "context" "encoding/base64" + "fmt" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/databricks/terraform-provider-databricks/common" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func DataSourceDbfsFile() *schema.Resource { - return &schema.Resource{ - ReadContext: func(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { +func DataSourceDbfsFile() common.Resource { + return common.Resource{ + Read: func(ctx context.Context, d *schema.ResourceData, m *common.DatabricksClient) error { limitFileSize := d.Get("limit_file_size").(bool) dbfsAPI := NewDbfsAPI(ctx, m) fileInfo, err := dbfsAPI.Status(d.Get("path").(string)) if err != nil { - return diag.FromErr(err) + return err } if limitFileSize && fileInfo.FileSize > 4e6 { - return diag.Errorf("Size of %s is too large: %d bytes", + return fmt.Errorf("size of %s is too large: %d bytes", fileInfo.Path, fileInfo.FileSize) } d.SetId(fileInfo.Path) @@ -26,7 +27,7 @@ func DataSourceDbfsFile() *schema.Resource { d.Set("file_size", fileInfo.FileSize) content, err := dbfsAPI.Read(fileInfo.Path) if err != nil { - return diag.FromErr(err) + return err } d.Set("content", base64.StdEncoding.EncodeToString(content)) return nil diff --git a/storage/data_dbfs_file_paths.go b/storage/data_dbfs_file_paths.go index bbfc2050ae..563c4986a1 100644 --- a/storage/data_dbfs_file_paths.go +++ b/storage/data_dbfs_file_paths.go @@ -3,19 +3,19 @@ package storage import ( "context" + "github.com/databricks/terraform-provider-databricks/common" "github.com/databricks/terraform-provider-databricks/workspace" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func DataSourceDbfsFilePaths() *schema.Resource { - return &schema.Resource{ - ReadContext: func(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { +func DataSourceDbfsFilePaths() common.Resource { + return common.Resource{ + Read: func(ctx context.Context, d *schema.ResourceData, m *common.DatabricksClient) error { path := d.Get("path").(string) recursive := d.Get("recursive").(bool) paths, err := NewDbfsAPI(ctx, m).List(path, recursive) if err != nil { - return diag.FromErr(err) + return err } d.SetId(path) pathList := []map[string]any{} diff --git a/storage/gs_test.go b/storage/gs_test.go index c2440d4981..18ef9bd3fb 100644 --- a/storage/gs_test.go +++ b/storage/gs_test.go @@ -20,7 +20,7 @@ func TestCreateOrValidateClusterForGoogleStorage_Failures(t *testing.T) { Response: apierr.NotFound("nope"), }, }, func(ctx context.Context, client *common.DatabricksClient) { - d := ResourceMount().TestResourceData() + d := ResourceMount().ToResource().TestResourceData() err := createOrValidateClusterForGoogleStorage(ctx, client, d, "a", "") assert.EqualError(t, err, "cannot re-create mounting cluster: nope") @@ -89,7 +89,7 @@ func TestCreateOrValidateClusterForGoogleStorage_WorksOnDeletedCluster(t *testin }, }, }, func(ctx context.Context, client *common.DatabricksClient) { - d := ResourceMount().TestResourceData() + d := ResourceMount().ToResource().TestResourceData() err := createOrValidateClusterForGoogleStorage(ctx, client, d, "removed-cluster", "service-account") assert.NoError(t, err) assert.Equal(t, "new-cluster", d.Get("cluster_id")) @@ -109,7 +109,7 @@ func TestCreateOrValidateClusterForGoogleStorage_FailsOnErrorGettingCluster(t *t }, }, }, func(ctx context.Context, client *common.DatabricksClient) { - d := ResourceMount().TestResourceData() + d := ResourceMount().ToResource().TestResourceData() err := createOrValidateClusterForGoogleStorage(ctx, client, d, "my-cluster", "service-account") assert.EqualError(t, err, "cannot get mounting cluster: Server error") }) diff --git a/storage/mounts.go b/storage/mounts.go index 667d44c321..9c75f29c67 100644 --- a/storage/mounts.go +++ b/storage/mounts.go @@ -3,6 +3,7 @@ package storage import ( "context" "encoding/json" + "errors" "fmt" "log" "reflect" @@ -14,7 +15,6 @@ import ( "github.com/databricks/terraform-provider-databricks/clusters" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -101,22 +101,22 @@ func (mp MountPoint) Mount(mo Mount, client *common.DatabricksClient) (source st return result.Text(), result.Err() } -func commonMountResource(tpl Mount, s map[string]*schema.Schema) *schema.Resource { - resource := &schema.Resource{ +func commonMountResource(tpl Mount, s map[string]*schema.Schema) common.Resource { + resource := common.Resource{ SchemaVersion: 2, Schema: s, + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, } // nolint should be a bigger context-aware refactor - resource.CreateContext = mountCreate(tpl, resource) - resource.ReadContext = mountRead(tpl, resource) - resource.DeleteContext = mountDelete(tpl, resource) - resource.Importer = &schema.ResourceImporter{ - StateContext: schema.ImportStatePassthroughContext, - } + resource.Create = mountCreate(tpl, resource) + resource.Read = mountRead(tpl, resource) + resource.Delete = mountDelete(tpl, resource) return resource } -func deprecatedMountTesource(r *schema.Resource) *schema.Resource { +func deprecatedMountResource(r common.Resource) common.Resource { r.DeprecationMessage = "Resource is deprecated and will be removed in further versions. " + "Please rewrite configuration using `databricks_mount` resource. More info at " + "https://registry.terraform.io/providers/databricks/databricks/latest/docs/" + @@ -161,6 +161,10 @@ func getCommonClusterObject(clustersAPI clusters.ClustersAPI, clusterName string func getOrCreateMountingCluster(clustersAPI clusters.ClustersAPI) (string, error) { cluster, err := clustersAPI.GetOrCreateRunningCluster("terraform-mount", getCommonClusterObject(clustersAPI, "terraform-mount")) if err != nil { + // Do not treat missing cluster like a missing resource. + if apierr.IsMissing(err) { + err = errors.New(err.Error()) + } return "", fmt.Errorf("failed to get mouting cluster: %w", err) } return cluster.ClusterID, nil @@ -188,11 +192,10 @@ func getMountingClusterID(ctx context.Context, client *common.DatabricksClient, } func mountCluster(ctx context.Context, tpl any, d *schema.ResourceData, - m any, r *schema.Resource) (Mount, MountPoint, error) { + client *common.DatabricksClient, r common.Resource) (Mount, MountPoint, error) { var mountPoint MountPoint var mountConfig Mount - client := m.(*common.DatabricksClient) mountPoint.Exec = client.CommandExecutor(ctx) clusterID := d.Get("cluster_id").(string) @@ -205,7 +208,7 @@ func mountCluster(ctx context.Context, tpl any, d *schema.ResourceData, mountType := reflect.TypeOf(tpl) mountTypePointer := reflect.New(mountType) mountReflectValue := mountTypePointer.Elem() - common.DataToReflectValue(d, r, mountReflectValue) + common.DataToReflectValue(d, r.Schema, mountReflectValue) mountInterface := mountReflectValue.Interface() mountConfig = mountInterface.(Mount) @@ -227,17 +230,16 @@ func mountCluster(ctx context.Context, tpl any, d *schema.ResourceData, } // returns resource create mount for object store on workspace -func mountCreate(tpl any, r *schema.Resource) func(context.Context, *schema.ResourceData, any) diag.Diagnostics { - return func(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { - mountConfig, mountPoint, err := mountCluster(ctx, tpl, d, m, r) +func mountCreate(tpl any, r common.Resource) func(context.Context, *schema.ResourceData, *common.DatabricksClient) error { + return func(ctx context.Context, d *schema.ResourceData, client *common.DatabricksClient) error { + mountConfig, mountPoint, err := mountCluster(ctx, tpl, d, client, r) if err != nil { - return diag.FromErr(err) + return err } - client := m.(*common.DatabricksClient) log.Printf("[INFO] Mounting %s at /mnt/%s", mountConfig.Source(), d.Id()) source, err := mountPoint.Mount(mountConfig, client) if err != nil { - return diag.FromErr(err) + return err } d.Set("source", source) return readMountSource(ctx, mountPoint, d) @@ -245,7 +247,7 @@ func mountCreate(tpl any, r *schema.Resource) func(context.Context, *schema.Reso } // reads and sets source of the mount -func readMountSource(ctx context.Context, mp MountPoint, d *schema.ResourceData) diag.Diagnostics { +func readMountSource(ctx context.Context, mp MountPoint, d *schema.ResourceData) error { source, err := mp.Source() if err != nil { if err.Error() == "Mount not found" { @@ -253,33 +255,33 @@ func readMountSource(ctx context.Context, mp MountPoint, d *schema.ResourceData) d.SetId("") return nil } - return diag.FromErr(err) + return err } d.Set("source", source) return nil } // return resource reader function -func mountRead(tpl any, r *schema.Resource) func(context.Context, *schema.ResourceData, any) diag.Diagnostics { - return func(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { +func mountRead(tpl any, r common.Resource) func(context.Context, *schema.ResourceData, *common.DatabricksClient) error { + return func(ctx context.Context, d *schema.ResourceData, m *common.DatabricksClient) error { _, mp, err := mountCluster(ctx, tpl, d, m, r) if err != nil { - return diag.FromErr(err) + return err } return readMountSource(ctx, mp, d) } } // returns delete resource function -func mountDelete(tpl any, r *schema.Resource) func(context.Context, *schema.ResourceData, any) diag.Diagnostics { - return func(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { +func mountDelete(tpl any, r common.Resource) func(context.Context, *schema.ResourceData, *common.DatabricksClient) error { + return func(ctx context.Context, d *schema.ResourceData, m *common.DatabricksClient) error { _, mp, err := mountCluster(ctx, tpl, d, m, r) if err != nil { - return diag.FromErr(err) + return err } log.Printf("[INFO] Unmounting /mnt/%s", d.Id()) if err = mp.Delete(); err != nil { - return diag.FromErr(err) + return err } return nil } diff --git a/storage/mounts_test.go b/storage/mounts_test.go index 4053d11fa2..c07f8d2af7 100644 --- a/storage/mounts_test.go +++ b/storage/mounts_test.go @@ -334,20 +334,22 @@ func TestMountCRD(t *testing.T) { }, }, func(ctx context.Context, client *common.DatabricksClient) { r := ResourceMount() - d := r.TestResourceData() + d := r.ToResource().TestResourceData() + d.Set("name", "a name") + d.Set("uri", "a uri") client.WithCommandMock(func(commandStr string) common.CommandResults { return common.CommandResults{} }) - diags := mountCreate(nil, r)(ctx, d, client) - assert.True(t, diags.HasError()) - assert.Equal(t, "failed to get mouting cluster: nope", diags[0].Summary) + diags := r.Create(ctx, d, client) + assert.NotNil(t, diags) + assert.EqualError(t, diags, "failed to get mouting cluster: nope") - diags = mountRead(nil, r)(ctx, d, client) - assert.True(t, diags.HasError()) - assert.Equal(t, "failed to get mouting cluster: nope", diags[0].Summary) + diags = r.Read(ctx, d, client) + assert.NotNil(t, diags) + assert.EqualError(t, diags, "failed to get mouting cluster: nope") - diags = mountDelete(nil, r)(ctx, d, client) - assert.True(t, diags.HasError()) - assert.Equal(t, "failed to get mouting cluster: nope", diags[0].Summary) + diags = r.Delete(ctx, d, client) + assert.NotNil(t, diags) + assert.EqualError(t, diags, "failed to get mouting cluster: nope") }) } diff --git a/storage/resource_dbfs_file.go b/storage/resource_dbfs_file.go index 45ec8bfbbe..bb44f63dbf 100644 --- a/storage/resource_dbfs_file.go +++ b/storage/resource_dbfs_file.go @@ -11,7 +11,7 @@ import ( ) // ResourceDbfsFile manages files on DBFS -func ResourceDbfsFile() *schema.Resource { +func ResourceDbfsFile() common.Resource { return common.Resource{ SchemaVersion: 1, Schema: workspace.FileContentSchema(map[string]*schema.Schema{ @@ -57,5 +57,5 @@ func ResourceDbfsFile() *schema.Resource { Upgrade: workspace.MigrateV0, }, }, - }.ToResource() + } } diff --git a/storage/resource_mount.go b/storage/resource_mount.go index 7756448531..32ef44f0ea 100644 --- a/storage/resource_mount.go +++ b/storage/resource_mount.go @@ -7,33 +7,32 @@ import ( "github.com/databricks/databricks-sdk-go/apierr" "github.com/databricks/terraform-provider-databricks/clusters" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -type mountCallback func(tpl any, r *schema.Resource) func(context.Context, - *schema.ResourceData, any) diag.Diagnostics +type mountCallback func(tpl any, r common.Resource) func(context.Context, + *schema.ResourceData, *common.DatabricksClient) error -func (cb mountCallback) preProcess(r *schema.Resource) func( +func (cb mountCallback) preProcess(r common.Resource) func( ctx context.Context, d *schema.ResourceData, - m any) diag.Diagnostics { + m *common.DatabricksClient) error { tpl := GenericMount{} return func(ctx context.Context, d *schema.ResourceData, - m any) diag.Diagnostics { + m *common.DatabricksClient) error { var gm GenericMount scm := r.Schema common.DataToStructPointer(d, scm, &gm) // TODO: propagate ctx all the way down to GetAzureJwtProperty() - err := gm.ValidateAndApplyDefaults(d, m.(*common.DatabricksClient)) + err := gm.ValidateAndApplyDefaults(d, m) if err != nil { - return diag.FromErr(err) + return err } common.StructToData(gm, scm, d) if err := preprocessS3MountGeneric(ctx, scm, d, m); err != nil { - return diag.FromErr(err) + return err } if err := preprocessGsMount(ctx, scm, d, m); err != nil { - return diag.FromErr(err) + return err } return cb(tpl, r)(ctx, d, m) } @@ -59,8 +58,8 @@ func (cb mountCallback) preProcess(r *schema.Resource) func( // in the terraform state. If the cluster_id is invalid then there is no way to update // it using native terraform apply workflows. The only workaround is to manually edit the // tfstate file replacing the existing invalid cluster_id with a new valid one. -func removeFromStateIfClusterDoesNotExist(cb func(context.Context, *schema.ResourceData, any) diag.Diagnostics) func(context.Context, *schema.ResourceData, any) diag.Diagnostics { - return func(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { +func removeFromStateIfClusterDoesNotExist(cb func(context.Context, *schema.ResourceData, *common.DatabricksClient) error) func(context.Context, *schema.ResourceData, *common.DatabricksClient) error { + return func(ctx context.Context, d *schema.ResourceData, m *common.DatabricksClient) error { clusterId := d.Get("cluster_id").(string) if clusterId != "" { clustersAPI := clusters.NewClustersAPI(ctx, m) @@ -96,12 +95,12 @@ func ResourceDatabricksMountSchema() map[string]*schema.Schema { } // ResourceMount mounts using given configuration -func ResourceMount() *schema.Resource { +func ResourceMount() common.Resource { tpl := GenericMount{} r := commonMountResource(tpl, ResourceDatabricksMountSchema()) - r.CreateContext = mountCallback(mountCreate).preProcess(r) - r.ReadContext = removeFromStateIfClusterDoesNotExist(mountCallback(mountRead).preProcess(r)) - r.DeleteContext = removeFromStateIfClusterDoesNotExist(mountCallback(mountDelete).preProcess(r)) + r.Create = mountCallback(mountCreate).preProcess(r) + r.Read = removeFromStateIfClusterDoesNotExist(mountCallback(mountRead).preProcess(r)) + r.Delete = removeFromStateIfClusterDoesNotExist(mountCallback(mountDelete).preProcess(r)) r.Importer = nil r.Timeouts = &schema.ResourceTimeout{ Default: schema.DefaultTimeout(20 * time.Minute), diff --git a/storage/s3_test.go b/storage/s3_test.go index 1fe7162098..9356f85aff 100644 --- a/storage/s3_test.go +++ b/storage/s3_test.go @@ -21,7 +21,7 @@ func TestPreprocessS3MountOnDeletedClusterNoInstanceProfileSpecifiedError(t *tes }, }, func(ctx context.Context, client *common.DatabricksClient) { r := ResourceMount() - d := r.TestResourceData() + d := r.ToResource().TestResourceData() d.Set("uri", "s3://bucket") d.Set("cluster_id", "removed-cluster") err := preprocessS3MountGeneric(ctx, r.Schema, d, client) @@ -92,7 +92,7 @@ func TestPreprocessS3MountOnDeletedClusterWorks(t *testing.T) { }, }, func(ctx context.Context, client *common.DatabricksClient) { r := ResourceMount() - d := r.TestResourceData() + d := r.ToResource().TestResourceData() d.MarkNewResource() common.StructToData(GenericMount{ URI: "s3://bucket", diff --git a/tokens/resource_obo_token.go b/tokens/resource_obo_token.go index ef994e0d31..72361f7e21 100644 --- a/tokens/resource_obo_token.go +++ b/tokens/resource_obo_token.go @@ -37,7 +37,7 @@ func (a TokenManagementAPI) Read(tokenID string) (ti TokenResponse, err error) { return } -func ResourceOboToken() *schema.Resource { +func ResourceOboToken() common.Resource { oboTokenSchema := common.StructToSchema(OboToken{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { m["token_value"] = &schema.Schema{ @@ -70,5 +70,5 @@ func ResourceOboToken() *schema.Resource { Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { return NewTokenManagementAPI(ctx, c).Delete(d.Id()) }, - }.ToResource() + } } diff --git a/tokens/resource_service_principal_secret.go b/tokens/resource_service_principal_secret.go index e3be4aa8e1..bdea3b6439 100644 --- a/tokens/resource_service_principal_secret.go +++ b/tokens/resource_service_principal_secret.go @@ -48,7 +48,7 @@ func (a ServicePrincipalSecretAPI) deleteServicePrincipalSecret(spnID, secretID return a.client.Delete(a.context, path, nil) } -func ResourceServicePrincipalSecret() *schema.Resource { +func ResourceServicePrincipalSecret() common.Resource { spnSecretSchema := common.StructToSchema(ServicePrincipalSecret{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { m["id"].Computed = true @@ -118,5 +118,5 @@ func ResourceServicePrincipalSecret() *schema.Resource { spnID := d.Get("service_principal_id").(string) return api.deleteServicePrincipalSecret(spnID, d.Id()) }, - }.ToResource() + } } diff --git a/tokens/resource_token.go b/tokens/resource_token.go index 022f3c8471..72626e40c0 100644 --- a/tokens/resource_token.go +++ b/tokens/resource_token.go @@ -96,7 +96,7 @@ func (a TokensAPI) Delete(tokenID string) error { } // ResourceToken refreshes token in case it's expired -func ResourceToken() *schema.Resource { +func ResourceToken() common.Resource { s := map[string]*schema.Schema{ "lifetime_seconds": { Type: schema.TypeInt, @@ -152,5 +152,5 @@ func ResourceToken() *schema.Resource { Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { return NewTokensAPI(ctx, c).Delete(d.Id()) }, - }.ToResource() + } } diff --git a/workspace/data_directory.go b/workspace/data_directory.go index 8aac815d96..e099facb5f 100644 --- a/workspace/data_directory.go +++ b/workspace/data_directory.go @@ -2,13 +2,14 @@ package workspace import ( "context" + "fmt" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/databricks/terraform-provider-databricks/common" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) // DataSourceDirectory ... -func DataSourceDirectory() *schema.Resource { +func DataSourceDirectory() common.Resource { s := map[string]*schema.Schema{ "path": { Type: schema.TypeString, @@ -25,17 +26,17 @@ func DataSourceDirectory() *schema.Resource { Computed: true, }, } - return &schema.Resource{ + return common.Resource{ Schema: s, - ReadContext: func(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { + Read: func(ctx context.Context, d *schema.ResourceData, m *common.DatabricksClient) error { notebooksAPI := NewNotebooksAPI(ctx, m) path := d.Get("path").(string) data, err := notebooksAPI.Read(path) if err != nil { - return diag.FromErr(err) + return err } if data.ObjectType != Directory { // should we support Repos as well? - return diag.Errorf("'%s' isn't a directory", path) + return fmt.Errorf("'%s' isn't a directory", path) } d.SetId(data.Path) d.Set("object_id", data.ObjectID) diff --git a/workspace/data_notebook.go b/workspace/data_notebook.go index d06f0fac8a..2ae68651cd 100644 --- a/workspace/data_notebook.go +++ b/workspace/data_notebook.go @@ -4,13 +4,12 @@ import ( "context" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) // DataSourceNotebook ... -func DataSourceNotebook() *schema.Resource { +func DataSourceNotebook() common.Resource { s := map[string]*schema.Schema{ "path": { Type: schema.TypeString, @@ -47,26 +46,26 @@ func DataSourceNotebook() *schema.Resource { Computed: true, }, } - return &schema.Resource{ + return common.Resource{ Schema: s, - ReadContext: func(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { + Read: func(ctx context.Context, d *schema.ResourceData, m *common.DatabricksClient) error { notebooksAPI := NewNotebooksAPI(ctx, m) path := d.Get("path").(string) format := d.Get("format").(string) notebookContent, err := notebooksAPI.Export(path, format) if err != nil { - return diag.FromErr(err) + return err } d.SetId(path) // nolint d.Set("content", notebookContent) objectStatus, err := notebooksAPI.Read(d.Id()) if err != nil { - return diag.FromErr(err) + return err } err = common.StructToData(objectStatus, s, d) if err != nil { - return diag.FromErr(err) + return err } return nil }, diff --git a/workspace/data_notebook_paths.go b/workspace/data_notebook_paths.go index dc70c9a3a3..cf897284e4 100644 --- a/workspace/data_notebook_paths.go +++ b/workspace/data_notebook_paths.go @@ -3,19 +3,19 @@ package workspace import ( "context" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/databricks/terraform-provider-databricks/common" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) // DataSourceNotebookPaths ... -func DataSourceNotebookPaths() *schema.Resource { - return &schema.Resource{ - ReadContext: func(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics { +func DataSourceNotebookPaths() common.Resource { + return common.Resource{ + Read: func(ctx context.Context, d *schema.ResourceData, m *common.DatabricksClient) error { path := d.Get("path").(string) recursive := d.Get("recursive").(bool) notebookList, err := NewNotebooksAPI(ctx, m).List(path, recursive, false) if err != nil { - return diag.FromErr(err) + return err } d.SetId(path) var notebookPathList []map[string]string diff --git a/workspace/resource_directory.go b/workspace/resource_directory.go index 95c595e754..44e8200e23 100644 --- a/workspace/resource_directory.go +++ b/workspace/resource_directory.go @@ -14,7 +14,7 @@ func directoryPathSuppressDiff(k, old, new string, d *schema.ResourceData) bool } // ResourceDirectory manages directories -func ResourceDirectory() *schema.Resource { +func ResourceDirectory() common.Resource { s := map[string]*schema.Schema{ "path": { Type: schema.TypeString, @@ -73,5 +73,5 @@ func ResourceDirectory() *schema.Resource { Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { return NewNotebooksAPI(ctx, c).Delete(d.Id(), d.Get("delete_recursive").(bool)) }, - }.ToResource() + } } diff --git a/workspace/resource_global_init_script.go b/workspace/resource_global_init_script.go index 3b78b1f0fd..f8b3fe7edd 100644 --- a/workspace/resource_global_init_script.go +++ b/workspace/resource_global_init_script.go @@ -18,7 +18,7 @@ const ( ) // ResourceGlobalInitScript manages notebooks -func ResourceGlobalInitScript() *schema.Resource { +func ResourceGlobalInitScript() common.Resource { extra := map[string]*schema.Schema{ "enabled": { Type: schema.TypeBool, @@ -97,5 +97,5 @@ func ResourceGlobalInitScript() *schema.Resource { Schema: s, SchemaVersion: 1, Timeouts: &schema.ResourceTimeout{}, - }.ToResource() + } } diff --git a/workspace/resource_notebook.go b/workspace/resource_notebook.go index 0be41d4988..b6dd39b38c 100644 --- a/workspace/resource_notebook.go +++ b/workspace/resource_notebook.go @@ -200,7 +200,7 @@ func (a NotebooksAPI) Delete(path string, recursive bool) error { } // ResourceNotebook manages notebooks -func ResourceNotebook() *schema.Resource { +func ResourceNotebook() common.Resource { s := FileContentSchema(map[string]*schema.Schema{ "language": { Type: schema.TypeString, @@ -332,7 +332,7 @@ func ResourceNotebook() *schema.Resource { objType := d.Get("object_type") return NewNotebooksAPI(ctx, c).Delete(d.Id(), !(objType == Notebook || objType == File)) }, - }.ToResource() + } } func isParentDoesntExistError(err error) bool { diff --git a/workspace/resource_notebook_test.go b/workspace/resource_notebook_test.go index ff48ff9608..2d06bda4e5 100644 --- a/workspace/resource_notebook_test.go +++ b/workspace/resource_notebook_test.go @@ -481,7 +481,7 @@ func TestResourceNotebookUpdate_DBC(t *testing.T) { func TestNotebookLanguageSuppressSourceDiff(t *testing.T) { r := ResourceNotebook() - d := r.TestResourceData() + d := r.ToResource().TestResourceData() d.Set("source", "this.PY") suppress := r.Schema["language"].DiffSuppressFunc assert.True(t, suppress("language", Python, Python, d)) diff --git a/workspace/resource_workspace_conf.go b/workspace/resource_workspace_conf.go index b8fd13c7b6..95fa4712c8 100644 --- a/workspace/resource_workspace_conf.go +++ b/workspace/resource_workspace_conf.go @@ -86,7 +86,7 @@ func updateWorkspaceConf(ctx context.Context, d *schema.ResourceData, c *common. } // ResourceWorkspaceConf maintains workspace configuration for specified keys -func ResourceWorkspaceConf() *schema.Resource { +func ResourceWorkspaceConf() common.Resource { return common.Resource{ Create: applyWorkspaceConf, Update: updateWorkspaceConf, @@ -146,5 +146,5 @@ func ResourceWorkspaceConf() *schema.Resource { Optional: true, }, }, - }.ToResource() + } } diff --git a/workspace/resource_workspace_file.go b/workspace/resource_workspace_file.go index 22158e2b89..a4ba5f1dd5 100644 --- a/workspace/resource_workspace_file.go +++ b/workspace/resource_workspace_file.go @@ -13,7 +13,7 @@ import ( ) // ResourceWorkspaceFile manages files in workspace -func ResourceWorkspaceFile() *schema.Resource { +func ResourceWorkspaceFile() common.Resource { s := FileContentSchema(map[string]*schema.Schema{ "url": { Type: schema.TypeString, @@ -104,5 +104,5 @@ func ResourceWorkspaceFile() *schema.Resource { } return client.Workspace.Delete(ctx, ws_api.Delete{Path: d.Id(), Recursive: false}) }, - }.ToResource() + } } From 95a4999cb4a299ed37c4204814e7cce23dd15d9d Mon Sep 17 00:00:00 2001 From: Miles Yucht Date: Wed, 31 Jan 2024 22:11:30 +0100 Subject: [PATCH 4/8] A better way --- clusters/data_spark_version.go | 4 +-- clusters/resource_cluster.go | 1 - common/resource.go | 29 +++++++++++---------- mws/data_mws_credentials.go | 4 ++- mws/data_mws_workspaces.go | 4 ++- mws/resource_mws_credentials.go | 1 + mws/resource_mws_customer_managed_keys.go | 1 + mws/resource_mws_log_delivery.go | 1 + mws/resource_mws_networks.go | 1 + mws/resource_mws_permission_assignment.go | 1 + mws/resource_mws_private_access_settings.go | 1 + mws/resource_mws_storage_configurations.go | 1 + mws/resource_mws_vpc_endpoint.go | 1 + mws/resource_mws_workspaces.go | 1 + settings/generic_setting_test.go | 2 +- 15 files changed, 32 insertions(+), 21 deletions(-) diff --git a/clusters/data_spark_version.go b/clusters/data_spark_version.go index 4da5babc29..163c1cc0fb 100644 --- a/clusters/data_spark_version.go +++ b/clusters/data_spark_version.go @@ -8,7 +8,6 @@ import ( "strings" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "golang.org/x/mod/semver" ) @@ -131,7 +130,6 @@ func DataSourceSparkVersion() common.Resource { s["photon"].Deprecated = "Specify runtime_engine=\"PHOTON\" in the cluster configuration" s["graviton"].Deprecated = "Not required anymore - it's automatically enabled on the Graviton-based node types" - common.AddWorkspaceIdField(s) return s }) @@ -140,7 +138,7 @@ func DataSourceSparkVersion() common.Resource { Read: func(ctx context.Context, d *schema.ResourceData, m *common.DatabricksClient) error { c, err := m.InConfiguredWorkspace(ctx, d) if err != nil { - return diag.FromErr(err) + return err } var this SparkVersionRequest common.DataToStructPointer(d, s, &this) diff --git a/clusters/resource_cluster.go b/clusters/resource_cluster.go index 4761e68d2c..3450970415 100644 --- a/clusters/resource_cluster.go +++ b/clusters/resource_cluster.go @@ -166,7 +166,6 @@ func (ClusterResourceProvider) CustomizeSchema(s map[string]*schema.Schema) map[ Schema: common.StructToSchema(MountInfo{}, nil), }, }) - common.AddWorkspaceIdField(s) return s } diff --git a/common/resource.go b/common/resource.go index 00d4d63b93..815b1ad195 100644 --- a/common/resource.go +++ b/common/resource.go @@ -14,18 +14,6 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -// Wrapper of the underlying Terraform resource. Needed as some resources are implemented directly -// with *schema.Resource rather than the Resource type in this package. -type DatabricksTerraformResource struct { - // The underlying TF resource - Resource *schema.Resource - - // Whether the resource is available at the workspace-level. If true, - // generated resources will have a `workspace_id` field for use when - // an account-level provider is used. - IsWorkspaceLevel bool -} - // Resource aims to simplify things like error & deleted entities handling type Resource struct { Create func(ctx context.Context, d *schema.ResourceData, c *DatabricksClient) error @@ -39,6 +27,12 @@ type Resource struct { Timeouts *schema.ResourceTimeout DeprecationMessage string Importer *schema.ResourceImporter + + // Set to true for account-level resources that are never managed at the + // workspace level, like workspaces and OAuth. If false, the resource + // will have a `workspace_id` attribute that allows the user to use an + // account-level provider to manage workspace-level resources. + IsAccountLevelOnly bool } func nicerError(ctx context.Context, err error, action string) error { @@ -208,6 +202,9 @@ func (r Resource) ToResource() *schema.Resource { Timeouts: r.Timeouts, DeprecationMessage: r.DeprecationMessage, } + if r.IsAccountLevelOnly { + r.Schema = AddWorkspaceIdField(r.Schema) + } if resource.Importer == nil { resource.Importer = &schema.ResourceImporter{ StateContext: func(ctx context.Context, d *schema.ResourceData, @@ -336,9 +333,11 @@ func WorkspaceDataWithParams[T, P any](read func(context.Context, P, *databricks // ... // }) 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 { + resource := genericDatabricksData((*DatabricksClient).AccountClient, func(ctx context.Context, s struct{}, t *T, ac *databricks.AccountClient) error { return read(ctx, t, ac) }, false) + resource.IsAccountLevelOnly = true + return resource } // AccountDataWithParams defines a data source that can be used to read data from the workspace API. @@ -373,7 +372,7 @@ 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 { + resource := 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 @@ -381,6 +380,8 @@ func AccountDataWithParams[T, P any](read func(context.Context, P, *databricks.A *s = *res return nil }, true) + resource.IsAccountLevelOnly = true + return resource } // genericDatabricksData is generic and common way to define both account and workspace data and calls their respective clients. diff --git a/mws/data_mws_credentials.go b/mws/data_mws_credentials.go index aa757fd858..53294efcab 100755 --- a/mws/data_mws_credentials.go +++ b/mws/data_mws_credentials.go @@ -11,7 +11,7 @@ func DataSourceMwsCredentials() common.Resource { type mwsCredentialsData struct { Ids map[string]string `json:"ids,omitempty" tf:"computed"` } - return common.DataResource(mwsCredentialsData{}, func(ctx context.Context, e any, c *common.DatabricksClient) error { + resource := common.DataResource(mwsCredentialsData{}, func(ctx context.Context, e any, c *common.DatabricksClient) error { data := e.(*mwsCredentialsData) if c.Config.AccountID == "" { return fmt.Errorf("provider block is missing `account_id` property") @@ -26,4 +26,6 @@ func DataSourceMwsCredentials() common.Resource { } return nil }) + resource.IsAccountLevelOnly = true + return resource } diff --git a/mws/data_mws_workspaces.go b/mws/data_mws_workspaces.go index da5eabb2c5..21ae197f25 100755 --- a/mws/data_mws_workspaces.go +++ b/mws/data_mws_workspaces.go @@ -11,7 +11,7 @@ func DataSourceMwsWorkspaces() common.Resource { type mwsWorkspacesData struct { Ids map[string]int64 `json:"ids,omitempty" tf:"computed"` } - return common.DataResource(mwsWorkspacesData{}, func(ctx context.Context, e any, c *common.DatabricksClient) error { + resource := common.DataResource(mwsWorkspacesData{}, func(ctx context.Context, e any, c *common.DatabricksClient) error { data := e.(*mwsWorkspacesData) if c.Config.AccountID == "" { return fmt.Errorf("provider block is missing `account_id` property") @@ -26,4 +26,6 @@ func DataSourceMwsWorkspaces() common.Resource { } return nil }) + resource.IsAccountLevelOnly = true + return resource } diff --git a/mws/resource_mws_credentials.go b/mws/resource_mws_credentials.go index b70a1e0ca1..b7c228f808 100644 --- a/mws/resource_mws_credentials.go +++ b/mws/resource_mws_credentials.go @@ -110,5 +110,6 @@ func ResourceMwsCredentials() common.Resource { s["account_id"].Deprecated = "`account_id` should be set as part of the Databricks Config, not in the resource." return s }), + IsAccountLevelOnly: true, } } diff --git a/mws/resource_mws_customer_managed_keys.go b/mws/resource_mws_customer_managed_keys.go index 1163ef39c5..2f400c24a5 100644 --- a/mws/resource_mws_customer_managed_keys.go +++ b/mws/resource_mws_customer_managed_keys.go @@ -113,6 +113,7 @@ func ResourceMwsCustomerManagedKeys() common.Resource { Upgrade: migrateResourceCustomerManagedKeyV0, }, }, + IsAccountLevelOnly: true, } } diff --git a/mws/resource_mws_log_delivery.go b/mws/resource_mws_log_delivery.go index 34514440fb..5026816301 100644 --- a/mws/resource_mws_log_delivery.go +++ b/mws/resource_mws_log_delivery.go @@ -119,5 +119,6 @@ func ResourceMwsLogDelivery() common.Resource { } return NewLogDeliveryAPI(ctx, c).Patch(accountID, configID, "DISABLED") }, + IsAccountLevelOnly: true, } } diff --git a/mws/resource_mws_networks.go b/mws/resource_mws_networks.go index 56cb98bb98..8fada6c5b9 100644 --- a/mws/resource_mws_networks.go +++ b/mws/resource_mws_networks.go @@ -115,5 +115,6 @@ func ResourceMwsNetworks() common.Resource { } return NewNetworksAPI(ctx, c).Delete(accountID, networkID) }, + IsAccountLevelOnly: true, } } diff --git a/mws/resource_mws_permission_assignment.go b/mws/resource_mws_permission_assignment.go index aa561933a5..436ca4ee5b 100644 --- a/mws/resource_mws_permission_assignment.go +++ b/mws/resource_mws_permission_assignment.go @@ -137,5 +137,6 @@ func ResourceMwsPermissionAssignment() common.Resource { } return NewPermissionAssignmentAPI(ctx, c).Remove(workspaceId, principalId) }, + IsAccountLevelOnly: true, } } diff --git a/mws/resource_mws_private_access_settings.go b/mws/resource_mws_private_access_settings.go index 67e807dcf5..4eb6f2fc0c 100644 --- a/mws/resource_mws_private_access_settings.go +++ b/mws/resource_mws_private_access_settings.go @@ -74,5 +74,6 @@ func ResourceMwsPrivateAccessSettings() common.Resource { } return a.PrivateAccess.DeleteByPrivateAccessSettingsId(ctx, pasID) }, + IsAccountLevelOnly: true, } } diff --git a/mws/resource_mws_storage_configurations.go b/mws/resource_mws_storage_configurations.go index 2b979cf448..1f5904cb5b 100644 --- a/mws/resource_mws_storage_configurations.go +++ b/mws/resource_mws_storage_configurations.go @@ -113,5 +113,6 @@ func ResourceMwsStorageConfigurations() common.Resource { Computed: true, }, }, + IsAccountLevelOnly: true, } } diff --git a/mws/resource_mws_vpc_endpoint.go b/mws/resource_mws_vpc_endpoint.go index fd10d8cfaf..2983a0f47c 100644 --- a/mws/resource_mws_vpc_endpoint.go +++ b/mws/resource_mws_vpc_endpoint.go @@ -115,5 +115,6 @@ func ResourceMwsVpcEndpoint() common.Resource { } return NewVPCEndpointAPI(ctx, c).Delete(accountID, vpcEndpointID) }, + IsAccountLevelOnly: true, } } diff --git a/mws/resource_mws_workspaces.go b/mws/resource_mws_workspaces.go index 5f4d442bf0..084b8811b5 100644 --- a/mws/resource_mws_workspaces.go +++ b/mws/resource_mws_workspaces.go @@ -613,6 +613,7 @@ func ResourceMwsWorkspaces() common.Resource { Read: schema.DefaultTimeout(DefaultProvisionTimeout), Update: schema.DefaultTimeout(DefaultProvisionTimeout), }, + IsAccountLevelOnly: true, } } diff --git a/settings/generic_setting_test.go b/settings/generic_setting_test.go index e5644cf5a0..4a273c90c0 100644 --- a/settings/generic_setting_test.go +++ b/settings/generic_setting_test.go @@ -12,7 +12,7 @@ import ( ) // Choose an arbitrary setting to test. -var testSetting = AllSettingsResources()["default_namespace"].Resource +var testSetting = AllSettingsResources()["default_namespace"] func TestQueryCreateDefaultNameSetting(t *testing.T) { d, err := qa.ResourceFixture{ From 06c507a76b7a724e8c3fae35b4e813cb35518f60 Mon Sep 17 00:00:00 2001 From: Miles Yucht Date: Wed, 31 Jan 2024 22:14:25 +0100 Subject: [PATCH 5/8] comments --- common/resource.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/resource.go b/common/resource.go index 815b1ad195..6dab233f71 100644 --- a/common/resource.go +++ b/common/resource.go @@ -29,7 +29,7 @@ type Resource struct { Importer *schema.ResourceImporter // Set to true for account-level resources that are never managed at the - // workspace level, like workspaces and OAuth. If false, the resource + // workspace level, like workspaces and networks. If false, the resource // will have a `workspace_id` attribute that allows the user to use an // account-level provider to manage workspace-level resources. IsAccountLevelOnly bool From bddf47f595a7c2964ff92b191f06c04d91f1d0b9 Mon Sep 17 00:00:00 2001 From: Miles Yucht Date: Wed, 31 Jan 2024 22:15:12 +0100 Subject: [PATCH 6/8] booleans are hard --- common/resource.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/resource.go b/common/resource.go index 6dab233f71..afd17d2740 100644 --- a/common/resource.go +++ b/common/resource.go @@ -202,7 +202,7 @@ func (r Resource) ToResource() *schema.Resource { Timeouts: r.Timeouts, DeprecationMessage: r.DeprecationMessage, } - if r.IsAccountLevelOnly { + if !r.IsAccountLevelOnly { r.Schema = AddWorkspaceIdField(r.Schema) } if resource.Importer == nil { From e66364d7946d8e194b33e46cf3120b9232b4c712 Mon Sep 17 00:00:00 2001 From: Miles Yucht Date: Wed, 31 Jan 2024 22:18:07 +0100 Subject: [PATCH 7/8] set original workspace id --- common/resource.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/common/resource.go b/common/resource.go index afd17d2740..57284c24fa 100644 --- a/common/resource.go +++ b/common/resource.go @@ -174,6 +174,9 @@ func (r Resource) ToResource() *schema.Resource { err = nicerError(ctx, err, "read") return diag.FromErr(err) } + if workspaceId, ok := d.GetOk("workspace_id"); ok && !r.IsAccountLevelOnly { + d.Set("original_workspace_id", workspaceId) + } return nil }, ReadContext: generateReadFunc(true), From 2260dc45ccd86e45f806d5662f75831ea0f6f572 Mon Sep 17 00:00:00 2001 From: Miles Yucht Date: Wed, 31 Jan 2024 22:23:19 +0100 Subject: [PATCH 8/8] fix tests --- qa/testing.go | 20 ++++++++++---------- qa/testing_test.go | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/qa/testing.go b/qa/testing.go index 1d3c8d2c38..71710104c2 100644 --- a/qa/testing.go +++ b/qa/testing.go @@ -123,10 +123,10 @@ type ResourceFixture struct { } // wrapper type for calling resource methords -type resourceCRUD func(context.Context, *schema.ResourceData, *common.DatabricksClient) error +type resourceCRUD func(context.Context, *schema.ResourceData, any) diag.Diagnostics func (cb resourceCRUD) before(before func(d *schema.ResourceData)) resourceCRUD { - return func(ctx context.Context, d *schema.ResourceData, i *common.DatabricksClient) error { + return func(ctx context.Context, d *schema.ResourceData, i any) diag.Diagnostics { before(d) return cb(ctx, d, i) } @@ -138,13 +138,13 @@ func (cb resourceCRUD) withId(id string) resourceCRUD { }) } -func (f ResourceFixture) prepareExecution() (resourceCRUD, error) { +func (f ResourceFixture) prepareExecution(r *schema.Resource) (resourceCRUD, error) { switch { case f.Create: if f.ID != "" { return nil, fmt.Errorf("ID is not available for Create") } - return resourceCRUD(f.Resource.Create).before(func(d *schema.ResourceData) { + return resourceCRUD(r.CreateContext).before(func(d *schema.ResourceData) { d.MarkNewResource() }), nil case f.Read: @@ -153,7 +153,7 @@ func (f ResourceFixture) prepareExecution() (resourceCRUD, error) { } preRead := f.State f.State = nil - return resourceCRUD(f.Resource.Read).before(func(d *schema.ResourceData) { + return resourceCRUD(r.ReadContext).before(func(d *schema.ResourceData) { if f.New { d.MarkNewResource() } @@ -165,12 +165,12 @@ func (f ResourceFixture) prepareExecution() (resourceCRUD, error) { if f.ID == "" { return nil, fmt.Errorf("ID must be set for Update") } - return resourceCRUD(f.Resource.Update).withId(f.ID), nil + return resourceCRUD(r.UpdateContext).withId(f.ID), nil case f.Delete: if f.ID == "" { return nil, fmt.Errorf("ID must be set for Delete") } - return resourceCRUD(f.Resource.Delete).withId(f.ID), nil + return resourceCRUD(r.DeleteContext).withId(f.ID), nil } return nil, fmt.Errorf("no `Create|Read|Update|Delete: true` specificed") } @@ -286,11 +286,11 @@ func (f ResourceFixture) Apply(t *testing.T) (*schema.ResourceData, error) { f.State = fixHCL(out).(map[string]any) } resourceConfig := terraform.NewResourceConfigRaw(f.State) - execute, err := f.prepareExecution() + resource := f.Resource.ToResource() + execute, err := f.prepareExecution(resource) if err != nil { return nil, err } - resource := f.Resource.ToResource() if f.State != nil { diags := resource.Validate(resourceConfig) if diags.HasError() { @@ -326,7 +326,7 @@ func (f ResourceFixture) Apply(t *testing.T) (*schema.ResourceData, error) { // this is a bit strange, but we'll fix it later diags := execute(ctx, resourceData, client) if diags != nil { - return resourceData, fmt.Errorf(diagsToString(diag.FromErr(diags))) + return resourceData, fmt.Errorf(diagsToString(diags)) } } if resourceData.Id() == "" && !f.Removed { diff --git a/qa/testing_test.go b/qa/testing_test.go index 9229561b54..76a9762a48 100644 --- a/qa/testing_test.go +++ b/qa/testing_test.go @@ -105,7 +105,7 @@ var noopContextResource = common.Resource{ } func TestResourceFixture_ID(t *testing.T) { - _, err := ResourceFixture{}.prepareExecution() + _, err := ResourceFixture{}.prepareExecution(nil) assert.EqualError(t, err, "no `Create|Read|Update|Delete: true` specificed") f := ResourceFixture{