From 48f8ce03ec392a70b2a0e785e78d4db5704050c3 Mon Sep 17 00:00:00 2001 From: Liran Bareket Date: Fri, 30 Aug 2024 02:58:03 -0400 Subject: [PATCH 01/54] [Doc] Update aws_unity_catalog_assume_role_policy.md (#3968) Closes #3966 Fixed example issue. ## Changes Fixed example --- docs/data-sources/aws_unity_catalog_assume_role_policy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/data-sources/aws_unity_catalog_assume_role_policy.md b/docs/data-sources/aws_unity_catalog_assume_role_policy.md index 348e06fcf6..c5f66ddec9 100644 --- a/docs/data-sources/aws_unity_catalog_assume_role_policy.md +++ b/docs/data-sources/aws_unity_catalog_assume_role_policy.md @@ -30,7 +30,7 @@ resource "aws_iam_policy" "unity_metastore" { resource "aws_iam_role" "metastore_data_access" { name = "${var.prefix}-uc-access" - assume_role_policy = data.aws_iam_policy_document.this.json + assume_role_policy = data.databricks_aws_unity_catalog_assume_role_policy.this.json managed_policy_arns = [aws_iam_policy.unity_metastore.arn] } ``` From f7760acc53b6045e4bbacc71e238660d43490146 Mon Sep 17 00:00:00 2001 From: Georgi Slavov Date: Fri, 30 Aug 2024 09:58:37 +0300 Subject: [PATCH 02/54] [Doc] Update metastore_assignment.md to properly reflect possible usage (#3967) ## Changes Update metastore_assignment.md to properly reflect possible usage. Related to #3963 ## Tests - [ ] `make test` run locally - [X] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [ ] using Go SDK --- docs/resources/metastore_assignment.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/resources/metastore_assignment.md b/docs/resources/metastore_assignment.md index c278721408..14edd3d60c 100644 --- a/docs/resources/metastore_assignment.md +++ b/docs/resources/metastore_assignment.md @@ -3,7 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_metastore_assignment (Resource) --> **Note** This resource could be only used with account-level provider! +-> **Note** This resource could be used with account or workspace-level provider. A single [databricks_metastore](metastore.md) can be shared across Databricks workspaces, and each linked workspace has a consistent view of the data and a single set of access policies. You can only create a single metastore for each region in which your organization operates. From f626169ec8a30c34a0c12fd96a0639ba977688ac Mon Sep 17 00:00:00 2001 From: sergiumpopa <31008027+sergiumpopa@users.noreply.github.com> Date: Fri, 30 Aug 2024 14:33:03 +0200 Subject: [PATCH 03/54] [Doc] Adopt official naming of Mosaic AI Vector Search (#3971) ## Changes Changed Vector Search naming to official naming "Mosaic AI Vector Search", addressing #3280. This does not cover instances of the term for the following cases: - [ ] resource names - [ ] error messages - [ ] usages of the general term, rather than the product - such as in "The **Mosaic AI Vector Search** Endpoint is used to create and access **vector search** indexes." ## Tests - [ ] `make test` run locally - [x] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [ ] using Go SDK Co-authored-by: Sergiu Popa --- docs/resources/vector_search_endpoint.md | 10 +++++----- docs/resources/vector_search_index.md | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/resources/vector_search_endpoint.md b/docs/resources/vector_search_endpoint.md index 24f77e12d1..adb3319264 100644 --- a/docs/resources/vector_search_endpoint.md +++ b/docs/resources/vector_search_endpoint.md @@ -1,11 +1,11 @@ --- -subcategory: "Vector Search" +subcategory: "Mosaic AI Vector Search" --- # databricks_vector_search_endpoint Resource -> **Note** This resource could be only used on Unity Catalog-enabled workspace! -This resource allows you to create [Vector Search Endpoint](https://docs.databricks.com/en/generative-ai/vector-search.html) in Databricks. Vector Search is a serverless similarity search engine that allows you to store a vector representation of your data, including metadata, in a vector database. The Vector Search Endpoint is used to create and access vector search indexes. +This resource allows you to create [Mosaic AI Vector Search Endpoint](https://docs.databricks.com/en/generative-ai/vector-search.html) in Databricks. Mosaic AI Vector Search is a serverless similarity search engine that allows you to store a vector representation of your data, including metadata, in a vector database. The Mosaic AI Vector Search Endpoint is used to create and access vector search indexes. ## Example Usage @@ -20,8 +20,8 @@ resource "databricks_vector_search_endpoint" "this" { The following arguments are supported (change of any parameter leads to recreation of the resource): -* `name` - (Required) Name of the Vector Search Endpoint to create. -* `endpoint_type` (Required) Type of Vector Search Endpoint. Currently only accepting single value: `STANDARD` (See [documentation](https://docs.databricks.com/api/workspace/vectorsearchendpoints/createendpoint) for the list of currently supported values). +* `name` - (Required) Name of the Mosaic AI Vector Search Endpoint to create. +* `endpoint_type` (Required) Type of Mosaic AI Vector Search Endpoint. Currently only accepting single value: `STANDARD` (See [documentation](https://docs.databricks.com/api/workspace/vectorsearchendpoints/createendpoint) for the list of currently supported values). ## Attribute Reference @@ -40,7 +40,7 @@ In addition to all the arguments above, the following attributes are exported: ## Import -The resource can be imported using the name of the Vector Search Endpoint +The resource can be imported using the name of the Mosaic AI Vector Search Endpoint ```bash terraform import databricks_vector_search_endpoint.this diff --git a/docs/resources/vector_search_index.md b/docs/resources/vector_search_index.md index 46286aeaf7..74d02e746e 100644 --- a/docs/resources/vector_search_index.md +++ b/docs/resources/vector_search_index.md @@ -1,11 +1,11 @@ --- -subcategory: "Vector Search" +subcategory: "Mosaic AI Vector Search" --- # databricks_vector_search_index Resource -> **Note** This resource could be only used on Unity Catalog-enabled workspace! -This resource allows you to create [Vector Search Index](https://docs.databricks.com/en/generative-ai/create-query-vector-search.html) in Databricks. Vector Search is a serverless similarity search engine that allows you to store a vector representation of your data, including metadata, in a vector database. The Vector Search Index provides the ability to search data in the linked Delta Table. +This resource allows you to create [Mosaic AI Vector Search Index](https://docs.databricks.com/en/generative-ai/create-query-vector-search.html) in Databricks. Mosaic AI Vector Search is a serverless similarity search engine that allows you to store a vector representation of your data, including metadata, in a vector database. The Mosaic AI Vector Search Index provides the ability to search data in the linked Delta Table. ## Example Usage @@ -30,10 +30,10 @@ resource "databricks_vector_search_index" "sync" { The following arguments are supported (change of any parameter leads to recreation of the resource): -* `name` - (required) Three-level name of the Vector Search Index to create (`catalog.schema.index_name`). -* `endpoint_name` - (required) The name of the Vector Search Endpoint that will be used for indexing the data. +* `name` - (required) Three-level name of the Mosaic AI Vector Search Index to create (`catalog.schema.index_name`). +* `endpoint_name` - (required) The name of the Mosaic AI Vector Search Endpoint that will be used for indexing the data. * `primary_key` - (required) The column name that will be used as a primary key. -* `index_type` - (required) Vector Search index type. Currently supported values are: +* `index_type` - (required) Mosaic AI Vector Search index type. Currently supported values are: * `DELTA_SYNC`: An index that automatically syncs with a source Delta Table, automatically and incrementally updating the index as the underlying data in the Delta Table changes. * `DIRECT_ACCESS`: An index that supports the direct read and write of vectors and metadata through our REST and SDK APIs. With this model, the user manages index updates. * `delta_sync_index_spec` - (object) Specification for Delta Sync Index. Required if `index_type` is `DELTA_SYNC`. @@ -72,7 +72,7 @@ In addition to all arguments above, the following attributes are exported: ## Import -The resource can be imported using the name of the Vector Search Index +The resource can be imported using the name of the Mosaic AI Vector Search Index ```bash terraform import databricks_vector_search_index.this From f4687d60ed95f41ce28f94a9c724d552d3eb2a55 Mon Sep 17 00:00:00 2001 From: Tanmay Rustagi <88379306+tanmay-db@users.noreply.github.com> Date: Fri, 30 Aug 2024 15:10:47 +0200 Subject: [PATCH 04/54] [Internal] Added `databricks_quality_monitor` resource and `databricks_volumes` data source to plugin framework (#3958) ## Changes Add support for Quality Monitor resource and Volumes data source in plugin framework. Also add utility method to get workspace and account client with diagnostics. Subpart of: https://github.com/databricks/terraform-provider-databricks/pull/3751 + Addressed comments from: https://github.com/databricks/terraform-provider-databricks/pull/3893/files#diff-8edec0f6289f63bfb61c7c6fb76fc1a61eec69c33fc2ba3a4ee6e77a8103f85b Note: The changes for flipping `databricks_quality_monitor_pluginframework` -> `databricks_quality_monitor` in pluginframework along with making this legacy for sdkv2 i.e. `databricks_quality_monitor` -> `databricks_quality_monitor_legacy` will be done in separate PR. Same for `databricks_volumes` ## Tests Existing unit tests. Integration and Unit tests for this resource will be merged after this PR is merged. - [ ] `make test` run locally - [ ] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [ ] using Go SDK --------- Co-authored-by: Miles Yucht --- CONTRIBUTING.md | 48 +++- common/client.go | 21 ++ internal/providers/pluginfw/common/common.go | 39 ++++ internal/providers/pluginfw/pluginfw.go | 10 +- .../resource_quality_monitor.go | 216 ++++++++++++++++++ .../pluginfw/resources/volume/data_volumes.go | 78 +++++++ 6 files changed, 409 insertions(+), 3 deletions(-) create mode 100644 internal/providers/pluginfw/common/common.go create mode 100644 internal/providers/pluginfw/resources/qualitymonitor/resource_quality_monitor.go create mode 100644 internal/providers/pluginfw/resources/volume/data_volumes.go diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ac42672749..d4718029d7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -109,13 +109,59 @@ provider_installation { After installing the necessary software for building provider from sources, you should be able to run `make coverage` to run the tests and see the coverage. -## Package organization for Providers +## Developing Resources or Data Sources using Plugin Framework + +### Package organization for Providers We are migrating the resource from SDKv2 to Plugin Framework provider and hence both of them exist in the codebase. For uniform code convention, readability and development, they are organized in the `internal/providers` directory under root as follows: - `providers`: Contains the changes that `depends` on both internal/providers/sdkv2 and internal/providers/pluginfw packages, eg: `GetProviderServer`. - `common`: Contains the changes `used by` both internal/providers/sdkv2 and internal/providers/pluginfw packages, eg: `ProviderName`. - `pluginfw`: Contains the changes specific to Plugin Framework. This package shouldn't depend on sdkv2 or common. - `sdkv2`: Contains the changes specific to SDKv2. This package shouldn't depend on pluginfw or common. +### Migrating resource to plugin framework +Ideally there shouldn't be any behaviour change when migrating a resource or data source to either Go SDk or Plugin Framework. +- Please make sure there are no breaking differences due to changes in schema by running: `make diff-schema`. +- Integration tests shouldn't require any major changes. + + +### Code Organization +Each resource and data source should be defined in package `internal/providers/pluginfw/resources/`, e.g.: `internal/providers/pluginfw/resources/volume` package will contain both resource, data sources and other utils specific to volumes. Tests (both unit and integration tests) will also remain in this package. + +Note: Only Docs will stay under root docs/ directory. + + +### Code Conventions +1. Make sure the resource or data source implemented is of the right type: + ```golang + var _ resource.ResourceWithConfigure = &QualityMonitorResource{} + var _ datasource.DataSourceWithConfigure = &VolumesDataSource{} + ``` +2. To get the databricks client, `func (*common.DatabricksClient).GetWorkspaceClient()` or `func (*common.DatabricksClient).GetAccountClient()` will be used instead of directly using the underlying `WorkspaceClient()`, `AccountClient()` functions respectively. +3. Any method that returns only diagnostics should be called inline while appending diagnostics in response. Example: + ```golang + resp.Diagnostics.Append(req.Plan.Get(ctx, &monitorInfoTfSDK)...) + if resp.Diagnostics.HasError() { + return + } + ``` + is preferred over the following: + ```golang + diags := req.Plan.Get(ctx, &monitorInfoTfSDK) + if diags.HasError() { + resp.Diagnostics.Append(diags...) + return + } + ``` +4. Any method returning an error should directly be followed by appending that to the diagnostics. + ```golang + err := method() + if err != nil { + resp.Diagnostics.AddError("message", err.Error()) + return + } + ``` +5. Any method returning a value alongside Diagnostics should also directly be followed by appending that to the diagnostics. + ## Debugging diff --git a/common/client.go b/common/client.go index 661a2d9ff5..18ab283585 100644 --- a/common/client.go +++ b/common/client.go @@ -13,6 +13,7 @@ import ( "github.com/databricks/databricks-sdk-go/config" "github.com/databricks/databricks-sdk-go/service/iam" "github.com/golang-jwt/jwt/v4" + "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -56,6 +57,16 @@ type DatabricksClient struct { mu sync.Mutex } +// GetWorkspaceClient returns the Databricks WorkspaceClient or a diagnostics if that fails. +// This is used by resources and data sources that are developed over plugin framework. +func (c *DatabricksClient) GetWorkspaceClient() (*databricks.WorkspaceClient, diag.Diagnostics) { + w, err := c.WorkspaceClient() + if err != nil { + return nil, diag.Diagnostics{diag.NewErrorDiagnostic("Failed to get workspace client", err.Error())} + } + return w, nil +} + func (c *DatabricksClient) WorkspaceClient() (*databricks.WorkspaceClient, error) { c.mu.Lock() defer c.mu.Unlock() @@ -99,6 +110,16 @@ func (c *DatabricksClient) setAccountId(accountId string) error { return nil } +// GetAccountClient returns the Databricks Account client or a diagnostics if that fails. +// This is used by resources and data sources that are developed over plugin framework. +func (c *DatabricksClient) GetAccountClient() (*databricks.AccountClient, diag.Diagnostics) { + a, err := c.AccountClient() + if err != nil { + return nil, diag.Diagnostics{diag.NewErrorDiagnostic("Failed to get account client", err.Error())} + } + return a, nil +} + func (c *DatabricksClient) AccountClient() (*databricks.AccountClient, error) { c.mu.Lock() defer c.mu.Unlock() diff --git a/internal/providers/pluginfw/common/common.go b/internal/providers/pluginfw/common/common.go new file mode 100644 index 0000000000..f200aab720 --- /dev/null +++ b/internal/providers/pluginfw/common/common.go @@ -0,0 +1,39 @@ +package common + +import ( + "fmt" + + "github.com/databricks/terraform-provider-databricks/common" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/resource" +) + +// ConfigureDataSource is a helper function for configuring a general data source. +// It returns the DatabricksClient if it can be successfully fetched from the ProviderData in the request; +// otherwise, the error is appended to the diagnostics of the response. +func ConfigureDataSource(req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) *common.DatabricksClient { + client, ok := req.ProviderData.(*common.DatabricksClient) + if !ok { + resp.Diagnostics.AddError( + "Unexpected Data Source Configure Type", + fmt.Sprintf("Expected *common.DatabricksClient, got: %T. Please report this issue to the provider developers.", req.ProviderData), + ) + return nil + } + return client +} + +// ConfigureDataSource is a helper function for configuring a general resource. +// It returns the DatabricksClient if it can be successfully fetched from the ProviderData in the request; +// otherwise, the error is appended to the diagnostics of the response. +func ConfigureResource(req resource.ConfigureRequest, resp *resource.ConfigureResponse) *common.DatabricksClient { + client, ok := req.ProviderData.(*common.DatabricksClient) + if !ok { + resp.Diagnostics.AddError( + "Unexpected Resource Configure Type", + fmt.Sprintf("Expected *common.DatabricksClient, got: %T. Please report this issue to the provider developers.", req.ProviderData), + ) + return nil + } + return client +} diff --git a/internal/providers/pluginfw/pluginfw.go b/internal/providers/pluginfw/pluginfw.go index 77de6d0b3c..80ba2288cf 100644 --- a/internal/providers/pluginfw/pluginfw.go +++ b/internal/providers/pluginfw/pluginfw.go @@ -16,6 +16,8 @@ import ( "github.com/databricks/terraform-provider-databricks/commands" "github.com/databricks/terraform-provider-databricks/common" providercommon "github.com/databricks/terraform-provider-databricks/internal/providers/common" + "github.com/databricks/terraform-provider-databricks/internal/providers/pluginfw/resources/qualitymonitor" + "github.com/databricks/terraform-provider-databricks/internal/providers/pluginfw/resources/volume" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/diag" @@ -38,11 +40,15 @@ type DatabricksProviderPluginFramework struct { var _ provider.Provider = (*DatabricksProviderPluginFramework)(nil) func (p *DatabricksProviderPluginFramework) Resources(ctx context.Context) []func() resource.Resource { - return []func() resource.Resource{} + return []func() resource.Resource{ + qualitymonitor.ResourceQualityMonitor, + } } func (p *DatabricksProviderPluginFramework) DataSources(ctx context.Context) []func() datasource.DataSource { - return []func() datasource.DataSource{} + return []func() datasource.DataSource{ + volume.DataSourceVolumes, + } } func (p *DatabricksProviderPluginFramework) Schema(ctx context.Context, req provider.SchemaRequest, resp *provider.SchemaResponse) { diff --git a/internal/providers/pluginfw/resources/qualitymonitor/resource_quality_monitor.go b/internal/providers/pluginfw/resources/qualitymonitor/resource_quality_monitor.go new file mode 100644 index 0000000000..da58260a93 --- /dev/null +++ b/internal/providers/pluginfw/resources/qualitymonitor/resource_quality_monitor.go @@ -0,0 +1,216 @@ +package qualitymonitor + +import ( + "context" + "fmt" + "time" + + "github.com/databricks/databricks-sdk-go" + "github.com/databricks/databricks-sdk-go/apierr" + "github.com/databricks/databricks-sdk-go/retries" + "github.com/databricks/databricks-sdk-go/service/catalog" + "github.com/databricks/terraform-provider-databricks/common" + pluginfwcommon "github.com/databricks/terraform-provider-databricks/internal/providers/pluginfw/common" + "github.com/databricks/terraform-provider-databricks/internal/providers/pluginfw/converters" + "github.com/databricks/terraform-provider-databricks/internal/providers/pluginfw/tfschema" + "github.com/databricks/terraform-provider-databricks/internal/service/catalog_tf" + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +const qualityMonitorDefaultProvisionTimeout = 15 * time.Minute + +var _ resource.ResourceWithConfigure = &QualityMonitorResource{} + +func ResourceQualityMonitor() resource.Resource { + return &QualityMonitorResource{} +} + +func waitForMonitor(ctx context.Context, w *databricks.WorkspaceClient, monitor *catalog.MonitorInfo) diag.Diagnostics { + updatedMonitor, err := retries.Poll[catalog.MonitorInfo](ctx, qualityMonitorDefaultProvisionTimeout, func() (*catalog.MonitorInfo, *retries.Err) { + newMonitor, err := w.QualityMonitors.GetByTableName(ctx, monitor.TableName) + if err != nil { + return nil, retries.Halt(fmt.Errorf("failed to get monitor: %s", err)) + } + + switch newMonitor.Status { + case catalog.MonitorInfoStatusMonitorStatusActive: + return newMonitor, nil + case catalog.MonitorInfoStatusMonitorStatusError, catalog.MonitorInfoStatusMonitorStatusFailed: + return nil, retries.Halt(fmt.Errorf("monitor status returned %s for monitor: %s", newMonitor.Status, newMonitor.TableName)) + } + return nil, retries.Continue(fmt.Errorf("monitor %s is still pending", newMonitor.TableName)) + }) + if err != nil { + return diag.Diagnostics{diag.NewErrorDiagnostic("failed to get monitor", err.Error())} + } + *monitor = *updatedMonitor + return nil +} + +type MonitorInfoExtended struct { + catalog_tf.MonitorInfo + WarehouseId types.String `tfsdk:"warehouse_id" tf:"optional"` + SkipBuiltinDashboard types.Bool `tfsdk:"skip_builtin_dashboard" tf:"optional"` +} + +type QualityMonitorResource struct { + Client *common.DatabricksClient +} + +func (r *QualityMonitorResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = "databricks_quality_monitor_pluginframework" +} + +func (r *QualityMonitorResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Description: "Terraform schema for Databricks Quality Monitor", + Attributes: tfschema.ResourceStructToSchemaMap(MonitorInfoExtended{}, func(c tfschema.CustomizableSchema) tfschema.CustomizableSchema { + c.SetRequired("assets_dir") + c.SetRequired("output_schema_name") + c.SetRequired("table_name") + c.SetReadOnly("monitor_version") + c.SetReadOnly("drift_metrics_table_name") + c.SetReadOnly("profile_metrics_table_name") + c.SetReadOnly("status") + c.SetReadOnly("dashboard_id") + c.SetReadOnly("schedule", "pause_status") + return c + }), + } +} + +func (d *QualityMonitorResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { + if d.Client == nil { + d.Client = pluginfwcommon.ConfigureResource(req, resp) + } +} + +func (r *QualityMonitorResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + w, diags := r.Client.GetWorkspaceClient() + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + var monitorInfoTfSDK MonitorInfoExtended + resp.Diagnostics.Append(req.Plan.Get(ctx, &monitorInfoTfSDK)...) + if resp.Diagnostics.HasError() { + return + } + + var createMonitorGoSDK catalog.CreateMonitor + resp.Diagnostics.Append(converters.TfSdkToGoSdkStruct(ctx, monitorInfoTfSDK, &createMonitorGoSDK)...) + if resp.Diagnostics.HasError() { + return + } + monitor, err := w.QualityMonitors.Create(ctx, createMonitorGoSDK) + if err != nil { + resp.Diagnostics.AddError("failed to get created monitor", err.Error()) + return + } + resp.Diagnostics.Append(waitForMonitor(ctx, w, monitor)...) + if resp.Diagnostics.HasError() { + return + } + + var newMonitorInfoTfSDK MonitorInfoExtended + resp.Diagnostics.Append(converters.GoSdkToTfSdkStruct(ctx, monitor, &newMonitorInfoTfSDK)...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, newMonitorInfoTfSDK)...) +} + +func (r *QualityMonitorResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + w, diags := r.Client.GetWorkspaceClient() + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + var getMonitor catalog_tf.GetQualityMonitorRequest + resp.Diagnostics.Append(req.State.GetAttribute(ctx, path.Root("table_name"), &getMonitor.TableName)...) + if resp.Diagnostics.HasError() { + return + } + endpoint, err := w.QualityMonitors.GetByTableName(ctx, getMonitor.TableName.ValueString()) + if err != nil { + if apierr.IsMissing(err) { + resp.State.RemoveResource(ctx) + return + } + resp.Diagnostics.AddError("failed to get monitor", err.Error()) + return + } + var monitorInfoTfSDK MonitorInfoExtended + resp.Diagnostics.Append(converters.GoSdkToTfSdkStruct(ctx, endpoint, &monitorInfoTfSDK)...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, monitorInfoTfSDK)...) +} + +func (r *QualityMonitorResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + w, diags := r.Client.GetWorkspaceClient() + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + var monitorInfoTfSDK MonitorInfoExtended + resp.Diagnostics.Append(req.Plan.Get(ctx, &monitorInfoTfSDK)...) + if resp.Diagnostics.HasError() { + return + } + // Plan is not adding `dashboard_id`, but it is in the state. + resp.Diagnostics.Append(req.State.GetAttribute(ctx, path.Root("dashboard_id"), &monitorInfoTfSDK.DashboardId)...) + if resp.Diagnostics.HasError() { + return + } + + var updateMonitorGoSDK catalog.UpdateMonitor + resp.Diagnostics.Append(converters.TfSdkToGoSdkStruct(ctx, monitorInfoTfSDK, &updateMonitorGoSDK)...) + if resp.Diagnostics.HasError() { + return + } + monitor, err := w.QualityMonitors.Update(ctx, updateMonitorGoSDK) + if err != nil { + resp.Diagnostics.AddError("failed to update monitor", err.Error()) + return + } + resp.Diagnostics.Append(waitForMonitor(ctx, w, monitor)...) + if resp.Diagnostics.HasError() { + return + } + + var newMonitorInfoTfSDK MonitorInfoExtended + resp.Diagnostics.Append(converters.GoSdkToTfSdkStruct(ctx, monitor, &newMonitorInfoTfSDK)...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, newMonitorInfoTfSDK)...) +} + +func (r *QualityMonitorResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + w, diags := r.Client.GetWorkspaceClient() + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + var deleteRequest catalog_tf.DeleteQualityMonitorRequest + resp.Diagnostics.Append(req.State.GetAttribute(ctx, path.Root("table_name"), &deleteRequest.TableName)...) + if resp.Diagnostics.HasError() { + return + } + err := w.QualityMonitors.DeleteByTableName(ctx, deleteRequest.TableName.ValueString()) + if err != nil && !apierr.IsMissing(err) { + resp.Diagnostics.AddError("failed to delete monitor", err.Error()) + } +} diff --git a/internal/providers/pluginfw/resources/volume/data_volumes.go b/internal/providers/pluginfw/resources/volume/data_volumes.go new file mode 100644 index 0000000000..c843e0a1fa --- /dev/null +++ b/internal/providers/pluginfw/resources/volume/data_volumes.go @@ -0,0 +1,78 @@ +package volume + +import ( + "context" + "fmt" + + "github.com/databricks/databricks-sdk-go/apierr" + "github.com/databricks/databricks-sdk-go/service/catalog" + "github.com/databricks/terraform-provider-databricks/common" + pluginfwcommon "github.com/databricks/terraform-provider-databricks/internal/providers/pluginfw/common" + "github.com/databricks/terraform-provider-databricks/internal/providers/pluginfw/converters" + "github.com/databricks/terraform-provider-databricks/internal/providers/pluginfw/tfschema" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +func DataSourceVolumes() datasource.DataSource { + return &VolumesDataSource{} +} + +var _ datasource.DataSourceWithConfigure = &VolumesDataSource{} + +type VolumesDataSource struct { + Client *common.DatabricksClient +} + +type VolumesList struct { + CatalogName types.String `tfsdk:"catalog_name"` + SchemaName types.String `tfsdk:"schema_name"` + Ids []types.String `tfsdk:"ids" tf:"computed,optional"` +} + +func (d *VolumesDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = "databricks_volumes_pluginframework" +} + +func (d *VolumesDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: tfschema.DataSourceStructToSchemaMap(VolumesList{}, nil), + } +} + +func (d *VolumesDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { + if d.Client == nil { + d.Client = pluginfwcommon.ConfigureDataSource(req, resp) + } +} + +func (d *VolumesDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + w, diags := d.Client.GetWorkspaceClient() + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + var volumesList VolumesList + diags = req.Config.Get(ctx, &volumesList) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + var listVolumesRequest catalog.ListVolumesRequest + converters.TfSdkToGoSdkStruct(ctx, volumesList, &listVolumesRequest) + volumes, err := w.Volumes.ListAll(ctx, listVolumesRequest) + if err != nil { + if apierr.IsMissing(err) { + resp.State.RemoveResource(ctx) + return + } + resp.Diagnostics.AddError(fmt.Sprintf("Failed to get volumes for the catalog:%s and schema%s", listVolumesRequest.CatalogName, listVolumesRequest.SchemaName), err.Error()) + return + } + for _, v := range volumes { + volumesList.Ids = append(volumesList.Ids, types.StringValue(v.FullName)) + } + resp.State.Set(ctx, volumesList) +} From 6678e1e0e6695b7f5db17a337f1accd3f21f25c5 Mon Sep 17 00:00:00 2001 From: Alex Ott Date: Sat, 31 Aug 2024 11:36:33 +0200 Subject: [PATCH 05/54] [Fix] Add suppress diff for `azure_attributes.spot_bid_max_price` in `databricks_instance_pool` (#3970) ## Changes Resolves #3969 ## Tests - [x] `make test` run locally - [ ] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [ ] using Go SDK --- pools/resource_instance_pool.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pools/resource_instance_pool.go b/pools/resource_instance_pool.go index a96c455f4f..b748d3cb94 100644 --- a/pools/resource_instance_pool.go +++ b/pools/resource_instance_pool.go @@ -197,6 +197,11 @@ func ResourceInstancePool() common.Resource { clusters.AzureAvailabilityOnDemand, }, false) } + if v, err := common.SchemaPath(s, "azure_attributes", "spot_bid_max_price"); err == nil { + v.DiffSuppressFunc = func(k, oldValue, newValue string, d *schema.ResourceData) bool { + return oldValue != "0" && newValue == "0" + } + } if v, err := common.SchemaPath(s, "gcp_attributes", "gcp_availability"); err == nil { v.Default = clusters.GcpAvailabilityOnDemand v.ValidateFunc = validation.StringInSlice([]string{ From 570d3466ca4b379d6a6ab110bd24ed8c90263123 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20G=C3=B3mez=20Moreno?= <69928678+dgomez04@users.noreply.github.com> Date: Sat, 31 Aug 2024 03:39:15 -0600 Subject: [PATCH 06/54] [Doc] Resolves #3127: Remove deprecated account_id field from mws_credentials resource (#3974) ## Changes Updated **`docs/resources/mws_credentials.md`** to reflect that `account_id` is deprecated from the `mws_credentials` resource and should be specifically added under a provider instance where `host = "https://accounts.cloud.databricks.com"`. Additionally, updated the code example to reflect this change. Ran `make fmt-docs`. Closes [#3217](https://github.com/databricks/terraform-provider-databricks/issues/3217) ## Tests - [ ] `make test` run locally - [x] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [ ] using Go SDK --- docs/resources/dashboard.md | 24 +++++----- docs/resources/job.md | 12 ++--- docs/resources/mws_credentials.md | 4 +- docs/resources/notification_destination.md | 54 +++++++++++----------- docs/resources/permissions.md | 4 +- 5 files changed, 49 insertions(+), 49 deletions(-) diff --git a/docs/resources/dashboard.md b/docs/resources/dashboard.md index e1215bd515..c466e07800 100644 --- a/docs/resources/dashboard.md +++ b/docs/resources/dashboard.md @@ -11,15 +11,15 @@ Dashboard using `serialized_dashboard` attribute: ```hcl data "databricks_sql_warehouse" "starter" { - name = "Starter Warehouse" + name = "Starter Warehouse" } resource "databricks_dashboard" "dashboard" { - display_name = "New Dashboard" - warehouse_id = data.databricks_sql_warehouse.starter.id - serialized_dashboard = "{\"pages\":[{\"name\":\"new_name\",\"displayName\":\"New Page\"}]}" - embed_credentials = false // Optional - parent_path = "/Shared/provider-test" + display_name = "New Dashboard" + warehouse_id = data.databricks_sql_warehouse.starter.id + serialized_dashboard = "{\"pages\":[{\"name\":\"new_name\",\"displayName\":\"New Page\"}]}" + embed_credentials = false // Optional + parent_path = "/Shared/provider-test" } ``` @@ -27,15 +27,15 @@ Dashboard using `file_path` attribute: ```hcl data "databricks_sql_warehouse" "starter" { - name = "Starter Warehouse" + name = "Starter Warehouse" } resource "databricks_dashboard" "dashboard" { - display_name = "New Dashboard" - warehouse_id = data.databricks_sql_warehouse.starter.id - file_path = "${path.module}/dashboard.json" - embed_credentials = false // Optional - parent_path = "/Shared/provider-test" + display_name = "New Dashboard" + warehouse_id = data.databricks_sql_warehouse.starter.id + file_path = "${path.module}/dashboard.json" + embed_credentials = false // Optional + parent_path = "/Shared/provider-test" } ``` diff --git a/docs/resources/job.md b/docs/resources/job.md index 4b9270fc29..3a7043f1f0 100644 --- a/docs/resources/job.md +++ b/docs/resources/job.md @@ -302,13 +302,13 @@ This block describes [an Environment](https://docs.databricks.com/en/compute/ser * `dependencies` - (list of strings) List of pip dependencies, as supported by the version of pip in this environment. Each dependency is a pip requirement file line. See [API docs](https://docs.databricks.com/api/workspace/jobs/create#environments-spec-dependencies) for more information. ```hcl - environment { - spec { - dependencies = ["foo==0.0.1", "-r /Workspace/test/requirements.txt"] - client = "1" - } - environment_key = "Default" +environment { + spec { + dependencies = ["foo==0.0.1", "-r /Workspace/test/requirements.txt"] + client = "1" } + environment_key = "Default" +} ``` #### depends_on Configuration Block diff --git a/docs/resources/mws_credentials.md b/docs/resources/mws_credentials.md index 2eb597b17c..7271ee6a68 100644 --- a/docs/resources/mws_credentials.md +++ b/docs/resources/mws_credentials.md @@ -37,7 +37,6 @@ resource "aws_iam_role_policy" "this" { resource "databricks_mws_credentials" "this" { provider = databricks.mws - account_id = var.databricks_account_id credentials_name = "${local.prefix}-creds" role_arn = aws_iam_role.cross_account_role.arn } @@ -47,7 +46,7 @@ resource "databricks_mws_credentials" "this" { The following arguments are required: -* `account_id` - (Optional) Account Id that could be found in the top right corner of [Accounts Console](https://accounts.cloud.databricks.com/) +* `account_id` - **(Deprecated)** Maintained for backwards compatibility and will be removed in a later version. It should now be specified under a provider instance where `host = "https://accounts.cloud.databricks.com"` * `credentials_name` - (Required) name of credentials to register * `role_arn` - (Required) ARN of cross-account role @@ -77,3 +76,4 @@ The following resources are used in the same context: * [databricks_mws_networks](mws_networks.md) to [configure VPC](https://docs.databricks.com/administration-guide/cloud-configurations/aws/customer-managed-vpc.html) & subnets for new workspaces within AWS. * [databricks_mws_storage_configurations](mws_storage_configurations.md) to configure root bucket new workspaces within AWS. * [databricks_mws_workspaces](mws_workspaces.md) to set up [AWS and GCP workspaces](https://docs.databricks.com/getting-started/overview.html#e2-architecture-1). + diff --git a/docs/resources/notification_destination.md b/docs/resources/notification_destination.md index 7a5273d039..2c2bba0c23 100644 --- a/docs/resources/notification_destination.md +++ b/docs/resources/notification_destination.md @@ -11,62 +11,62 @@ This resource allows you to manage [Notification Destinations](https://docs.data ```hcl resource "databricks_notification_destination" "ndresource" { - display_name = "Notification Destination" - config { - email { - addresses = ["abc@gmail.com"] - } + display_name = "Notification Destination" + config { + email { + addresses = ["abc@gmail.com"] } + } } ``` `Slack` notification destination: ```hcl resource "databricks_notification_destination" "ndresource" { - display_name = "Notification Destination" - config { - slack { - url = "https://hooks.slack.com/services/..." - } + display_name = "Notification Destination" + config { + slack { + url = "https://hooks.slack.com/services/..." } + } } ``` `PagerDuty` notification destination: ```hcl resource "databricks_notification_destination" "ndresource" { - display_name = "Notification Destination" - config { - pagerduty { - integration_key = "xxxxxx" - } + display_name = "Notification Destination" + config { + pagerduty { + integration_key = "xxxxxx" } + } } ``` `Microsoft Teams` notification destination: ```hcl resource "databricks_notification_destination" "ndresource" { - display_name = "Notification Destination" - config { - microsoft_teams { - url = "https://outlook.office.com/webhook/..." - } + display_name = "Notification Destination" + config { + microsoft_teams { + url = "https://outlook.office.com/webhook/..." } + } } ``` `Generic Webhook` notification destination: ```hcl resource "databricks_notification_destination" "ndresource" { - display_name = "Notification Destination" - config { - generic_webhook { - url = "https://example.com/webhook" - username = "username" // Optional - password = "password" // Optional - } + display_name = "Notification Destination" + config { + generic_webhook { + url = "https://example.com/webhook" + username = "username" // Optional + password = "password" // Optional } + } } ``` diff --git a/docs/resources/permissions.md b/docs/resources/permissions.md index 2070731c7e..ef5e1c4de8 100644 --- a/docs/resources/permissions.md +++ b/docs/resources/permissions.md @@ -749,8 +749,8 @@ resource "databricks_group" "eng" { } resource "databricks_dashboard" "dashboard" { - display_name = "TF New Dashboard" - # ... + display_name = "TF New Dashboard" + # ... } From f316f41493e0b683f8c8466f1495e27a5fd086c7 Mon Sep 17 00:00:00 2001 From: Edward Feng <67326663+edwardfeng-db@users.noreply.github.com> Date: Mon, 2 Sep 2024 10:28:34 +0200 Subject: [PATCH 07/54] [Internal] Add integration tests for volumes and quality monitor plugin framework (#3975) ## Changes - Add integration tests for resource and data source introduced [here](https://github.com/databricks/terraform-provider-databricks/pull/3958) - Small updates to `ConfigureDataSource` function to handle nil case - In `data_volumes`, we don't support `computed` tf tag yet, so we need to do that in customizable schema ## Tests - [x] `make test` run locally - [x] relevant change in `docs/` folder - [x] covered with integration tests in `internal/acceptance` - [x] relevant acceptance tests are passing - [x] using Go SDK --- internal/acceptance/data_volumes_test.go | 48 ++++++++ internal/acceptance/quality_monitor_test.go | 104 ++++++++++++++++++ internal/providers/pluginfw/common/common.go | 8 ++ .../resource_quality_monitor.go | 5 +- .../pluginfw/resources/volume/data_volumes.go | 7 +- 5 files changed, 167 insertions(+), 5 deletions(-) diff --git a/internal/acceptance/data_volumes_test.go b/internal/acceptance/data_volumes_test.go index af15dad148..968ab4a29c 100644 --- a/internal/acceptance/data_volumes_test.go +++ b/internal/acceptance/data_volumes_test.go @@ -58,3 +58,51 @@ func TestUcAccDataSourceVolumes(t *testing.T) { Check: checkDataSourceVolumesPopulated(t), }) } + +func checkDataSourceVolumesPluginFrameworkPopulated(t *testing.T) func(s *terraform.State) error { + return func(s *terraform.State) error { + _, ok := s.Modules[0].Resources["data.databricks_volumes_pluginframework.this"] + require.True(t, ok, "data.databricks_volumes_pluginframework.this has to be there") + num_volumes, _ := strconv.Atoi(s.Modules[0].Outputs["volumes"].Value.(string)) + assert.GreaterOrEqual(t, num_volumes, 1) + return nil + } +} + +func TestUcAccDataSourceVolumesPluginFramework(t *testing.T) { + unityWorkspaceLevel(t, step{ + Template: ` + resource "databricks_catalog" "sandbox" { + name = "sandbox{var.RANDOM}" + comment = "this catalog is managed by terraform" + properties = { + purpose = "testing" + } + } + + resource "databricks_schema" "things" { + catalog_name = databricks_catalog.sandbox.id + name = "things{var.RANDOM}" + comment = "this database is managed by terraform" + properties = { + kind = "various" + } + } + resource "databricks_volume" "this" { + name = "volume_data_source_test" + catalog_name = databricks_catalog.sandbox.name + schema_name = databricks_schema.things.name + volume_type = "MANAGED" + } + data "databricks_volumes_pluginframework" "this" { + catalog_name = databricks_catalog.sandbox.name + schema_name = databricks_schema.things.name + depends_on = [ databricks_volume.this ] + } + output "volumes" { + value = length(data.databricks_volumes_pluginframework.this.ids) + } + `, + Check: checkDataSourceVolumesPluginFrameworkPopulated(t), + }) +} diff --git a/internal/acceptance/quality_monitor_test.go b/internal/acceptance/quality_monitor_test.go index 9b9da2c91c..8a65e9a1c9 100644 --- a/internal/acceptance/quality_monitor_test.go +++ b/internal/acceptance/quality_monitor_test.go @@ -149,3 +149,107 @@ func TestUcAccUpdateQualityMonitor(t *testing.T) { `, }) } + +func TestUcAccQualityMonitorPluginFramework(t *testing.T) { + if os.Getenv("GOOGLE_CREDENTIALS") != "" { + t.Skipf("databricks_quality_monitor resource is not available on GCP") + } + unityWorkspaceLevel(t, step{ + Template: commonPartQualityMonitoring + ` + + resource "databricks_quality_monitor_pluginframework" "testMonitorInference" { + table_name = databricks_sql_table.myInferenceTable.id + assets_dir = "/Shared/provider-test/databricks_quality_monitoring/${databricks_sql_table.myInferenceTable.name}" + output_schema_name = databricks_schema.things.id + inference_log = { + granularities = ["1 day"] + timestamp_col = "timestamp" + prediction_col = "prediction" + model_id_col = "model_id" + problem_type = "PROBLEM_TYPE_REGRESSION" + } + } + + resource "databricks_sql_table" "myTimeseries" { + catalog_name = databricks_catalog.sandbox.id + schema_name = databricks_schema.things.name + name = "bar{var.STICKY_RANDOM}_timeseries" + table_type = "MANAGED" + data_source_format = "DELTA" + + column { + name = "timestamp" + type = "int" + } + } + + resource "databricks_quality_monitor_pluginframework" "testMonitorTimeseries" { + table_name = databricks_sql_table.myTimeseries.id + assets_dir = "/Shared/provider-test/databricks_quality_monitoring/${databricks_sql_table.myTimeseries.name}" + output_schema_name = databricks_schema.things.id + time_series = { + granularities = ["1 day"] + timestamp_col = "timestamp" + } + } + + resource "databricks_sql_table" "mySnapshot" { + catalog_name = databricks_catalog.sandbox.id + schema_name = databricks_schema.things.name + name = "bar{var.STICKY_RANDOM}_snapshot" + table_type = "MANAGED" + data_source_format = "DELTA" + + column { + name = "timestamp" + type = "int" + } + } + + resource "databricks_quality_monitor_pluginframework" "testMonitorSnapshot" { + table_name = databricks_sql_table.mySnapshot.id + assets_dir = "/Shared/provider-test/databricks_quality_monitoring/${databricks_sql_table.myTimeseries.name}" + output_schema_name = databricks_schema.things.id + snapshot = { + } + } + `, + }) +} + +func TestUcAccUpdateQualityMonitorPluginFramework(t *testing.T) { + if os.Getenv("GOOGLE_CREDENTIALS") != "" { + t.Skipf("databricks_quality_monitor resource is not available on GCP") + } + unityWorkspaceLevel(t, step{ + Template: commonPartQualityMonitoring + ` + resource "databricks_quality_monitor_pluginframework" "testMonitorInference" { + table_name = databricks_sql_table.myInferenceTable.id + assets_dir = "/Shared/provider-test/databricks_quality_monitoring/${databricks_sql_table.myInferenceTable.name}" + output_schema_name = databricks_schema.things.id + inference_log = { + granularities = ["1 day"] + timestamp_col = "timestamp" + prediction_col = "prediction" + model_id_col = "model_id" + problem_type = "PROBLEM_TYPE_REGRESSION" + } + } + `, + }, step{ + Template: commonPartQualityMonitoring + ` + resource "databricks_quality_monitor_pluginframework" "testMonitorInference" { + table_name = databricks_sql_table.myInferenceTable.id + assets_dir = "/Shared/provider-test/databricks_quality_monitoring/${databricks_sql_table.myInferenceTable.name}" + output_schema_name = databricks_schema.things.id + inference_log = { + granularities = ["1 hour"] + timestamp_col = "timestamp" + prediction_col = "prediction" + model_id_col = "model_id" + problem_type = "PROBLEM_TYPE_REGRESSION" + } + } + `, + }) +} diff --git a/internal/providers/pluginfw/common/common.go b/internal/providers/pluginfw/common/common.go index f200aab720..4351a5416c 100644 --- a/internal/providers/pluginfw/common/common.go +++ b/internal/providers/pluginfw/common/common.go @@ -12,6 +12,10 @@ import ( // It returns the DatabricksClient if it can be successfully fetched from the ProviderData in the request; // otherwise, the error is appended to the diagnostics of the response. func ConfigureDataSource(req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) *common.DatabricksClient { + // Nil case for acceptance tests. + if req.ProviderData == nil { + return nil + } client, ok := req.ProviderData.(*common.DatabricksClient) if !ok { resp.Diagnostics.AddError( @@ -27,6 +31,10 @@ func ConfigureDataSource(req datasource.ConfigureRequest, resp *datasource.Confi // It returns the DatabricksClient if it can be successfully fetched from the ProviderData in the request; // otherwise, the error is appended to the diagnostics of the response. func ConfigureResource(req resource.ConfigureRequest, resp *resource.ConfigureResponse) *common.DatabricksClient { + // Nil case for acceptance tests. + if req.ProviderData == nil { + return nil + } client, ok := req.ProviderData.(*common.DatabricksClient) if !ok { resp.Diagnostics.AddError( diff --git a/internal/providers/pluginfw/resources/qualitymonitor/resource_quality_monitor.go b/internal/providers/pluginfw/resources/qualitymonitor/resource_quality_monitor.go index da58260a93..20d86a0426 100644 --- a/internal/providers/pluginfw/resources/qualitymonitor/resource_quality_monitor.go +++ b/internal/providers/pluginfw/resources/qualitymonitor/resource_quality_monitor.go @@ -71,7 +71,6 @@ func (r *QualityMonitorResource) Schema(ctx context.Context, req resource.Schema Attributes: tfschema.ResourceStructToSchemaMap(MonitorInfoExtended{}, func(c tfschema.CustomizableSchema) tfschema.CustomizableSchema { c.SetRequired("assets_dir") c.SetRequired("output_schema_name") - c.SetRequired("table_name") c.SetReadOnly("monitor_version") c.SetReadOnly("drift_metrics_table_name") c.SetReadOnly("profile_metrics_table_name") @@ -84,7 +83,7 @@ func (r *QualityMonitorResource) Schema(ctx context.Context, req resource.Schema } func (d *QualityMonitorResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { - if d.Client == nil { + if d.Client == nil && req.ProviderData != nil { d.Client = pluginfwcommon.ConfigureResource(req, resp) } } @@ -108,7 +107,7 @@ func (r *QualityMonitorResource) Create(ctx context.Context, req resource.Create } monitor, err := w.QualityMonitors.Create(ctx, createMonitorGoSDK) if err != nil { - resp.Diagnostics.AddError("failed to get created monitor", err.Error()) + resp.Diagnostics.AddError("failed to create monitor", err.Error()) return } resp.Diagnostics.Append(waitForMonitor(ctx, w, monitor)...) diff --git a/internal/providers/pluginfw/resources/volume/data_volumes.go b/internal/providers/pluginfw/resources/volume/data_volumes.go index c843e0a1fa..cf9101b52e 100644 --- a/internal/providers/pluginfw/resources/volume/data_volumes.go +++ b/internal/providers/pluginfw/resources/volume/data_volumes.go @@ -28,7 +28,7 @@ type VolumesDataSource struct { type VolumesList struct { CatalogName types.String `tfsdk:"catalog_name"` SchemaName types.String `tfsdk:"schema_name"` - Ids []types.String `tfsdk:"ids" tf:"computed,optional"` + Ids []types.String `tfsdk:"ids" tf:"optional"` } func (d *VolumesDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { @@ -37,7 +37,10 @@ func (d *VolumesDataSource) Metadata(ctx context.Context, req datasource.Metadat func (d *VolumesDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { resp.Schema = schema.Schema{ - Attributes: tfschema.DataSourceStructToSchemaMap(VolumesList{}, nil), + Attributes: tfschema.DataSourceStructToSchemaMap(VolumesList{}, func(c tfschema.CustomizableSchema) tfschema.CustomizableSchema { + c.SetComputed("ids") + return c + }), } } From e4c36c844331ab9c6c42246ee5050ec75c97ad9f Mon Sep 17 00:00:00 2001 From: Andrew Nester Date: Mon, 2 Sep 2024 14:59:14 +0200 Subject: [PATCH 08/54] [Feature] Added `no_wait` option for clusters to skip waiting to start on cluster creation (#3953) ## Changes Added no_wait option for clusters to skip waiting to start on cluster creation Fixes https://github.com/databricks/terraform-provider-databricks/issues/3837 Also required for https://github.com/databricks/cli/pull/1698 ## Tests - [x] `make test` run locally - [x] relevant change in `docs/` folder - [x] covered with integration tests in `internal/acceptance` - [x] relevant acceptance tests are passing - [x] using Go SDK Manually run the following configuration to confirm everything works ``` data "databricks_node_type" "smallest" { local_disk = true } data "databricks_spark_version" "latest_lts" { long_term_support = true } resource "databricks_cluster" "shared_autoscaling" { cluster_name = "Andrew Nester TF Test" spark_version = data.databricks_spark_version.latest_lts.id node_type_id = data.databricks_node_type.smallest.id autotermination_minutes = 20 autoscale { min_workers = 1 max_workers = 50 } no_wait = true library { pypi { package = "fbprophet==0.6" } } } ``` --------- Co-authored-by: Pieter Noordhuis Co-authored-by: Miles Yucht --- clusters/resource_cluster.go | 35 +++++-- clusters/resource_cluster_test.go | 155 ++++++++++++++++++++++++++++ docs/resources/cluster.md | 1 + internal/acceptance/cluster_test.go | 21 ++++ 4 files changed, 206 insertions(+), 6 deletions(-) diff --git a/clusters/resource_cluster.go b/clusters/resource_cluster.go index bc7c08f08d..de7332fbcb 100644 --- a/clusters/resource_cluster.go +++ b/clusters/resource_cluster.go @@ -309,6 +309,17 @@ func (ClusterSpec) CustomizeSchemaResourceSpecific(s *common.CustomizableSchema) return old == new }, }) + s.AddNewField("no_wait", &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Default: false, + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + if old == "" && new == "false" { + return true + } + return old == new + }, + }) s.AddNewField("state", &schema.Schema{ Type: schema.TypeString, Computed: true, @@ -414,11 +425,8 @@ func resourceClusterCreate(ctx context.Context, d *schema.ResourceData, c *commo if err != nil { return err } - clusterInfo, err := clusterWaiter.GetWithTimeout(timeout) - if err != nil { - return err - } - d.SetId(clusterInfo.ClusterId) + + d.SetId(clusterWaiter.ClusterId) d.Set("cluster_id", d.Id()) isPinned, ok := d.GetOk("is_pinned") if ok && isPinned.(bool) { @@ -437,6 +445,20 @@ func resourceClusterCreate(ctx context.Context, d *schema.ResourceData, c *commo }); err != nil { return err } + } + + // If there is a no_wait flag set to true, don't wait for the cluster to be created + noWait, ok := d.GetOk("no_wait") + if ok && noWait.(bool) { + return nil + } + + clusterInfo, err := clusterWaiter.GetWithTimeout(timeout) + if err != nil { + return err + } + + if len(cluster.Libraries) > 0 { _, err := libraries.WaitForLibrariesInstalledSdk(ctx, w, compute.Wait{ ClusterID: d.Id(), IsRunning: clusterInfo.IsRunningOrResizing(), @@ -508,7 +530,7 @@ func resourceClusterRead(ctx context.Context, d *schema.ResourceData, c *common. func hasClusterConfigChanged(d *schema.ResourceData) bool { for k := range clusterSchema { // TODO: create a map if we'll add more non-cluster config parameters in the future - if k == "library" || k == "is_pinned" { + if k == "library" || k == "is_pinned" || k == "no_wait" { continue } if d.HasChange(k) { @@ -551,6 +573,7 @@ func resourceClusterUpdate(ctx context.Context, d *schema.ResourceData, c *commo for k := range clusterSchema { if k == "library" || k == "is_pinned" || + k == "no_wait" || k == "num_workers" || k == "autoscale" { continue diff --git a/clusters/resource_cluster_test.go b/clusters/resource_cluster_test.go index 53c693810a..b5af784be5 100644 --- a/clusters/resource_cluster_test.go +++ b/clusters/resource_cluster_test.go @@ -432,6 +432,161 @@ func TestResourceClusterCreatePhoton(t *testing.T) { assert.Equal(t, "abc", d.Id()) } +func TestResourceClusterCreateNoWait_WithLibraries(t *testing.T) { + d, err := qa.ResourceFixture{ + Fixtures: []qa.HTTPFixture{ + { + Method: "POST", + Resource: "/api/2.1/clusters/create", + ExpectedRequest: compute.ClusterSpec{ + NumWorkers: 100, + SparkVersion: "7.1-scala12", + NodeTypeId: "i3.xlarge", + AutoterminationMinutes: 60, + }, + Response: compute.ClusterDetails{ + ClusterId: "abc", + State: compute.StateUnknown, + }, + }, + { + Method: "GET", + ReuseRequest: true, + Resource: "/api/2.1/clusters/get?cluster_id=abc", + Response: compute.ClusterDetails{ + ClusterId: "abc", + NumWorkers: 100, + SparkVersion: "7.1-scala12", + NodeTypeId: "i3.xlarge", + AutoterminationMinutes: 15, + State: compute.StateUnknown, + }, + }, + { + Method: "POST", + Resource: "/api/2.1/clusters/events", + ExpectedRequest: compute.GetEvents{ + ClusterId: "abc", + Limit: 1, + Order: compute.GetEventsOrderDesc, + EventTypes: []compute.EventType{compute.EventTypePinned, compute.EventTypeUnpinned}, + }, + Response: compute.GetEventsResponse{ + Events: []compute.ClusterEvent{}, + TotalCount: 0, + }, + }, + { + Method: "POST", + Resource: "/api/2.0/libraries/install", + ExpectedRequest: compute.InstallLibraries{ + ClusterId: "abc", + Libraries: []compute.Library{ + { + Pypi: &compute.PythonPyPiLibrary{ + Package: "seaborn==1.2.4", + }, + }, + }, + }, + }, + { + Method: "GET", + Resource: "/api/2.0/libraries/cluster-status?cluster_id=abc", + Response: compute.ClusterLibraryStatuses{ + LibraryStatuses: []compute.LibraryFullStatus{ + { + Library: &compute.Library{ + Pypi: &compute.PythonPyPiLibrary{ + Package: "seaborn==1.2.4", + }, + }, + Status: compute.LibraryInstallStatusPending, + }, + }, + }, + }, + }, + Create: true, + Resource: ResourceCluster(), + HCL: `num_workers = 100 + spark_version = "7.1-scala12" + node_type_id = "i3.xlarge" + no_wait = true + + library { + pypi { + package = "seaborn==1.2.4" + } + }`, + }.Apply(t) + assert.NoError(t, err) + assert.Equal(t, "abc", d.Id()) +} + +func TestResourceClusterCreateNoWait(t *testing.T) { + d, err := qa.ResourceFixture{ + Fixtures: []qa.HTTPFixture{ + { + Method: "POST", + Resource: "/api/2.1/clusters/create", + ExpectedRequest: compute.ClusterSpec{ + NumWorkers: 100, + ClusterName: "Shared Autoscaling", + SparkVersion: "7.1-scala12", + NodeTypeId: "i3.xlarge", + AutoterminationMinutes: 15, + }, + Response: compute.ClusterDetails{ + ClusterId: "abc", + State: compute.StateUnknown, + }, + }, + { + Method: "GET", + ReuseRequest: true, + Resource: "/api/2.1/clusters/get?cluster_id=abc", + Response: compute.ClusterDetails{ + ClusterId: "abc", + NumWorkers: 100, + ClusterName: "Shared Autoscaling", + SparkVersion: "7.1-scala12", + NodeTypeId: "i3.xlarge", + AutoterminationMinutes: 15, + State: compute.StateUnknown, + }, + }, + { + Method: "POST", + Resource: "/api/2.1/clusters/events", + ExpectedRequest: compute.GetEvents{ + ClusterId: "abc", + Limit: 1, + Order: compute.GetEventsOrderDesc, + EventTypes: []compute.EventType{compute.EventTypePinned, compute.EventTypeUnpinned}, + }, + Response: compute.GetEventsResponse{ + Events: []compute.ClusterEvent{}, + TotalCount: 0, + }, + }, + }, + Create: true, + Resource: ResourceCluster(), + State: map[string]any{ + "autotermination_minutes": 15, + "cluster_name": "Shared Autoscaling", + "spark_version": "7.1-scala12", + "node_type_id": "i3.xlarge", + "num_workers": 100, + "is_pinned": false, + "no_wait": true, + }, + }.Apply(t) + assert.NoError(t, err) + assert.Equal(t, "abc", d.Id()) +} + func TestResourceClusterCreate_Error(t *testing.T) { d, err := qa.ResourceFixture{ Fixtures: []qa.HTTPFixture{ diff --git a/docs/resources/cluster.md b/docs/resources/cluster.md index 2de0b6ff05..c68cc8aa81 100644 --- a/docs/resources/cluster.md +++ b/docs/resources/cluster.md @@ -51,6 +51,7 @@ resource "databricks_cluster" "shared_autoscaling" { * `custom_tags` - (Optional) Additional tags for cluster resources. Databricks will tag all cluster resources (e.g., AWS EC2 instances and EBS volumes) with these tags in addition to `default_tags`. If a custom cluster tag has the same name as a default cluster tag, the custom tag is prefixed with an `x_` when it is propagated. * `spark_conf` - (Optional) Map with key-value pairs to fine-tune Spark clusters, where you can provide custom [Spark configuration properties](https://spark.apache.org/docs/latest/configuration.html) in a cluster configuration. * `is_pinned` - (Optional) boolean value specifying if the cluster is pinned (not pinned by default). You must be a Databricks administrator to use this. The pinned clusters' maximum number is [limited to 100](https://docs.databricks.com/clusters/clusters-manage.html#pin-a-cluster), so `apply` may fail if you have more than that (this number may change over time, so check Databricks documentation for actual number). +* `no_wait` - (Optional) If true, the provider will not wait for the cluster to reach `RUNNING` state when creating the cluster, allowing cluster creation and library installation to continue asynchronously. Defaults to false (the provider will wait for cluster creation and library installation to succeed). The following example demonstrates how to create an autoscaling cluster with [Delta Cache](https://docs.databricks.com/delta/optimizations/delta-cache.html) enabled: diff --git a/internal/acceptance/cluster_test.go b/internal/acceptance/cluster_test.go index 892ab3104c..45749a8a40 100644 --- a/internal/acceptance/cluster_test.go +++ b/internal/acceptance/cluster_test.go @@ -108,3 +108,24 @@ func TestAccClusterResource_CreateAndUpdateAwsAttributes(t *testing.T) { }) } } + +func TestAccClusterResource_CreateAndNoWait(t *testing.T) { + workspaceLevel(t, step{ + Template: `data "databricks_spark_version" "latest" { + } + resource "databricks_cluster" "this" { + cluster_name = "nowait-{var.RANDOM}" + spark_version = data.databricks_spark_version.latest.id + instance_pool_id = "{env.TEST_INSTANCE_POOL_ID}" + num_workers = 1 + autotermination_minutes = 10 + spark_conf = { + "spark.databricks.cluster.profile" = "serverless" + } + custom_tags = { + "ResourceClass" = "Serverless" + } + no_wait = true + }`, + }) +} From a4b02256e80cc6b8a33160d63aca9363d20ed4ea Mon Sep 17 00:00:00 2001 From: Miles Yucht Date: Mon, 2 Sep 2024 11:42:08 -0400 Subject: [PATCH 09/54] [Fix] Correctly send workload_type fields in `databricks_cluster` to allow users to disable usage in certain contexts (#3972) ## Changes Migration of the `databricks_cluster` resource to use the Go SDK introduced a regression in the handling of the `workload_type` attribute, used to control what use-cases are permitted for a cluster. This occurred because when moving to the Go SDK, by default, falsy values (e.g. `jobs = false` in `workload_type`) are not serialized when sent to the REST API. This PR fixes this by setting ForceSendFields in the nested `Client` structure whenever `workload_type` is specified. Ultimate behavior should be: ``` (no workload_type block) # -> usable in both jobs and notebooks workload_type { client { jobs = true notebook = true } } # -> usable in both jobs and notebooks workload_type { client { jobs = false } } # -> not usable in jobs because disabled, usable in notebooks because omitted and true by default ``` Fixes #3689. ## Tests Added an integration test to verify this behavior. I paused the integration test after disabling usage in jobs & notebooks, and I verified I wasn't able to attach the cluster to a notebook. - [ ] `make test` run locally - [ ] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [ ] using Go SDK --- clusters/resource_cluster.go | 22 ++++++++-- internal/acceptance/cluster_test.go | 67 +++++++++++++++++++++++++++++ internal/acceptance/init_test.go | 2 +- 3 files changed, 86 insertions(+), 5 deletions(-) diff --git a/clusters/resource_cluster.go b/clusters/resource_cluster.go index de7332fbcb..6595b92a9f 100644 --- a/clusters/resource_cluster.go +++ b/clusters/resource_cluster.go @@ -270,14 +270,31 @@ func FixInstancePoolChangeIfAny(d *schema.ResourceData, cluster any) error { func SetForceSendFieldsForCluster(cluster any, d *schema.ResourceData) error { switch c := cluster.(type) { case *compute.ClusterSpec: + // Used in jobs. if c.Autoscale == nil { c.ForceSendFields = append(c.ForceSendFields, "NumWorkers") } + // Workload type is not relevant in jobs clusters. return nil case *compute.CreateCluster: if c.Autoscale == nil { c.ForceSendFields = append(c.ForceSendFields, "NumWorkers") } + // If workload type is set by the user, the fields within Clients should always be sent. + // These default to true if not set. + if c.WorkloadType != nil { + c.WorkloadType.Clients.ForceSendFields = []string{"Jobs", "Notebooks"} + } + return nil + case *compute.EditCluster: + if c.Autoscale == nil { + c.ForceSendFields = append(c.ForceSendFields, "NumWorkers") + } + // If workload type is set by the user, the fields within Clients should always be sent. + // These default to true if not set. + if c.WorkloadType != nil { + c.WorkloadType.Clients.ForceSendFields = []string{"Jobs", "Notebooks"} + } return nil default: return fmt.Errorf(unsupportedExceptCreateEditClusterSpecErr, cluster, "*", "*", "*") @@ -626,10 +643,7 @@ func resourceClusterUpdate(ctx context.Context, d *schema.ResourceData, c *commo Autoscale: cluster.Autoscale, }) } else { - if err != nil { - return err - } - cluster.ForceSendFields = []string{"NumWorkers"} + SetForceSendFieldsForCluster(&cluster, d) err = retry.RetryContext(ctx, 15*time.Minute, func() *retry.RetryError { _, err = clusters.Edit(ctx, cluster) diff --git a/internal/acceptance/cluster_test.go b/internal/acceptance/cluster_test.go index 45749a8a40..4dad55c9f7 100644 --- a/internal/acceptance/cluster_test.go +++ b/internal/acceptance/cluster_test.go @@ -3,6 +3,8 @@ package acceptance import ( "fmt" "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" ) func TestAccClusterResource_CreateClusterWithLibraries(t *testing.T) { @@ -129,3 +131,68 @@ func TestAccClusterResource_CreateAndNoWait(t *testing.T) { }`, }) } + +func TestAccClusterResource_WorkloadType(t *testing.T) { + workspaceLevel(t, step{ + Template: testAccClusterResourceWorkloadTypeTemplate(""), + }, step{ + Template: testAccClusterResourceWorkloadTypeTemplate(` + workload_type { + clients { + jobs = true + notebooks = true + } + }`), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("databricks_cluster.this", "workload_type.0.clients.0.jobs", "true"), + resource.TestCheckResourceAttr("databricks_cluster.this", "workload_type.0.clients.0.notebooks", "true"), + ), + }, step{ + Template: testAccClusterResourceWorkloadTypeTemplate(` + workload_type { + clients { + jobs = false + notebooks = false + } + }`), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("databricks_cluster.this", "workload_type.0.clients.0.jobs", "false"), + resource.TestCheckResourceAttr("databricks_cluster.this", "workload_type.0.clients.0.notebooks", "false"), + ), + }, step{ + Template: testAccClusterResourceWorkloadTypeTemplate(` + workload_type { + clients { } + }`), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("databricks_cluster.this", "workload_type.0.clients.0.jobs", "true"), + resource.TestCheckResourceAttr("databricks_cluster.this", "workload_type.0.clients.0.notebooks", "true"), + ), + }, step{ + Template: testAccClusterResourceWorkloadTypeTemplate(``), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("databricks_cluster.this", "workload_type.0.clients.0.jobs", "true"), + resource.TestCheckResourceAttr("databricks_cluster.this", "workload_type.0.clients.0.notebooks", "true"), + ), + }) +} + +func testAccClusterResourceWorkloadTypeTemplate(workloadType string) string { + return fmt.Sprintf(` +data "databricks_spark_version" "latest" {} +resource "databricks_cluster" "this" { + cluster_name = "workload-{var.RANDOM}" + spark_version = data.databricks_spark_version.latest.id + instance_pool_id = "{env.TEST_INSTANCE_POOL_ID}" + autotermination_minutes = 10 + num_workers = 0 + spark_conf = { + "spark.databricks.cluster.profile" = "singleNode" + "spark.master" = "local[*]" + } + custom_tags = { + "ResourceClass" = "SingleNode" + } + %s +}`, workloadType) +} diff --git a/internal/acceptance/init_test.go b/internal/acceptance/init_test.go index 9bcbb8efab..fb13d01567 100644 --- a/internal/acceptance/init_test.go +++ b/internal/acceptance/init_test.go @@ -166,7 +166,7 @@ func run(t *testing.T, steps []step) { if s.Template != "" { stepConfig = environmentTemplate(t, s.Template, vars) } - stepNum := i + stepNum := i + 1 thisStep := s stepCheck := thisStep.Check stepPreConfig := s.PreConfig From 00d8fa89ae9e2365fd547b0a191fe56082220cb5 Mon Sep 17 00:00:00 2001 From: Alex Ott Date: Tue, 3 Sep 2024 08:19:41 +0200 Subject: [PATCH 10/54] [Fix] Force send fields for settings resources (#3978) ## Changes There was a problem that `databricks_automatic_cluster_update_setting` wasn't applied because `minutes` attribute was set to 0, and it wasn't sent in the JSON payload because it's marked as `omitempty` in the API. After analysis, it was found that there are other places where we need to send data but the corresponding fields were marked as `omitempty`. This PR includes following changes: - in 3 resources force sending of boolean and numeric fields with 0 values - add customize schema for `databricksenhanced_security_monitoring_setting`, `databricks_automatic_cluster_update_setting` and `databricks_enhanced_security_monitoring_setting` as fields are declared as required in documentation/API, but not enforced in Terraform because they are marked as `omitempty` - expand documentation to include necessary blocks Resolves #3976 ## Tests - [x] `make test` run locally - [x] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [x] using Go SDK --- .../automatic_cluster_update_setting.md | 21 +++++++-------- .../compliance_security_profile_setting.md | 5 ++-- .../enhanced_security_monitoring_setting.md | 3 ++- ...source_automatic_cluster_update_setting.go | 21 +++++++++++++-- ...e_automatic_cluster_update_setting_test.go | 23 +++++++++++----- ...rce_compliance_security_profile_setting.go | 8 ++++++ ...ompliance_security_profile_setting_test.go | 5 ++++ ...ce_enhanced_security_monitoring_setting.go | 10 ++++++- ...hanced_security_monitoring_setting_test.go | 27 ++++++++++++------- 9 files changed, 90 insertions(+), 33 deletions(-) diff --git a/docs/resources/automatic_cluster_update_setting.md b/docs/resources/automatic_cluster_update_setting.md index d3a3b77292..0a5ce409d0 100644 --- a/docs/resources/automatic_cluster_update_setting.md +++ b/docs/resources/automatic_cluster_update_setting.md @@ -33,17 +33,16 @@ resource "databricks_automatic_cluster_update_workspace_setting" "this" { The resource supports the following arguments: -* `enabled` - (Required) The configuration details. -* `restart_even_if_no_updates_available` - (Optional) To force clusters and other compute resources to restart during the maintenance window regardless of the availability of a new update. - -A `maintenance_window` block that defines the maintenance frequency with the following arguments - -* A `week_day_based_schedule` block with the following arguments - * `day_of_week` - the day of the week in uppercase, e.g. `MONDAY` or `SUNDAY` - * `frequency` - one of the `FIRST_OF_MONTH`, `SECOND_OF_MONTH`, `THIRD_OF_MONTH`, `FOURTH_OF_MONTH`, `FIRST_AND_THIRD_OF_MONTH`, `SECOND_AND_FOURTH_OF_MONTH`, `EVERY_WEEK`. - * A `window_start_time` block that defines the time of your maintenance window. The default timezone is UTC and cannot be changed. - * `hours` - * `minutes` +- `automatic_cluster_update_workspace` (Required) block with following attributes + - `enabled` - (Required) The configuration details. + - `restart_even_if_no_updates_available` - (Optional) To force clusters and other compute resources to restart during the maintenance window regardless of the availability of a new update. + - `maintenance_window` block that defines the maintenance frequency with the following arguments + - `week_day_based_schedule` block with the following arguments + - `day_of_week` - the day of the week in uppercase, e.g. `MONDAY` or `SUNDAY` + - `frequency` - one of the `FIRST_OF_MONTH`, `SECOND_OF_MONTH`, `THIRD_OF_MONTH`, `FOURTH_OF_MONTH`, `FIRST_AND_THIRD_OF_MONTH`, `SECOND_AND_FOURTH_OF_MONTH`, `EVERY_WEEK`. + - `window_start_time` block that defines the time of your maintenance window. The default timezone is UTC and cannot be changed. + - `hours` - hour to perform update: 0-23 + - `minutes` - minute to perform update: 0-59 ## Import diff --git a/docs/resources/compliance_security_profile_setting.md b/docs/resources/compliance_security_profile_setting.md index 0794ace4f6..a507243418 100644 --- a/docs/resources/compliance_security_profile_setting.md +++ b/docs/resources/compliance_security_profile_setting.md @@ -27,8 +27,9 @@ resource "databricks_compliance_security_profile_workspace_setting" "this" { The resource supports the following arguments: -* `is_enabled` - (Required) Enable the Compliance Security Profile on the workspace -* `compliance_standards` - (Required) Enable one or more compliance standards on the workspace, e.g. `HIPAA`, `PCI_DSS`, `FEDRAMP_MODERATE` +- `compliance_security_profile_workspace` block with following attributes: + - `is_enabled` - (Required) Enable the Compliance Security Profile on the workspace + - `compliance_standards` - (Required) Enable one or more compliance standards on the workspace, e.g. `HIPAA`, `PCI_DSS`, `FEDRAMP_MODERATE` ## Import diff --git a/docs/resources/enhanced_security_monitoring_setting.md b/docs/resources/enhanced_security_monitoring_setting.md index ce8b4f25d9..7447b7ad34 100644 --- a/docs/resources/enhanced_security_monitoring_setting.md +++ b/docs/resources/enhanced_security_monitoring_setting.md @@ -25,7 +25,8 @@ resource "databricks_enhanced_security_monitoring_workspace_setting" "this" { The resource supports the following arguments: -* `is_enabled` - (Required) Enable the Enhanced Security Monitoring on the workspace + - `enhanced_security_monitoring_workspace` block with following attributes: + - `is_enabled` - (Required) Enable the Enhanced Security Monitoring on the workspace ## Import diff --git a/settings/resource_automatic_cluster_update_setting.go b/settings/resource_automatic_cluster_update_setting.go index 726ae9d244..1926303363 100644 --- a/settings/resource_automatic_cluster_update_setting.go +++ b/settings/resource_automatic_cluster_update_setting.go @@ -19,10 +19,20 @@ var automaticClusterUpdateFieldMask = strings.Join([]string{ "automatic_cluster_update_workspace.maintenance_window.week_day_based_schedule.window_start_time.hours", "automatic_cluster_update_workspace.maintenance_window.week_day_based_schedule.window_start_time.minutes", }, ",") + var automaticClusterUpdateSetting = workspaceSetting[settings.AutomaticClusterUpdateSetting]{ settingStruct: settings.AutomaticClusterUpdateSetting{}, customizeSchemaFunc: func(s map[string]*schema.Schema) map[string]*schema.Schema { - common.MustSchemaPath(s, "automatic_cluster_update_workspace", "enablement_details").Computed = true + common.CustomizeSchemaPath(s, "automatic_cluster_update_workspace", "enablement_details").SetReadOnly() + common.CustomizeSchemaPath(s, "automatic_cluster_update_workspace", "enabled").SetRequired() + common.CustomizeSchemaPath(s, "automatic_cluster_update_workspace", "maintenance_window", + "week_day_based_schedule", "window_start_time", "hours").SetRequired() + common.CustomizeSchemaPath(s, "automatic_cluster_update_workspace", "maintenance_window", + "week_day_based_schedule", "day_of_week").SetRequired() + common.CustomizeSchemaPath(s, "automatic_cluster_update_workspace", "maintenance_window", + "week_day_based_schedule", "frequency").SetRequired() + common.CustomizeSchemaPath(s, "automatic_cluster_update_workspace", "maintenance_window", + "week_day_based_schedule", "window_start_time", "minutes").SetRequired() return s }, readFunc: func(ctx context.Context, w *databricks.WorkspaceClient, etag string) (*settings.AutomaticClusterUpdateSetting, error) { @@ -32,6 +42,12 @@ var automaticClusterUpdateSetting = workspaceSetting[settings.AutomaticClusterUp }, updateFunc: func(ctx context.Context, w *databricks.WorkspaceClient, t settings.AutomaticClusterUpdateSetting) (string, error) { t.SettingName = "default" + t.AutomaticClusterUpdateWorkspace.ForceSendFields = []string{"Enabled", "RestartEvenIfNoUpdatesAvailable"} + if t.AutomaticClusterUpdateWorkspace.MaintenanceWindow != nil && + t.AutomaticClusterUpdateWorkspace.MaintenanceWindow.WeekDayBasedSchedule != nil && + t.AutomaticClusterUpdateWorkspace.MaintenanceWindow.WeekDayBasedSchedule.WindowStartTime != nil { + t.AutomaticClusterUpdateWorkspace.MaintenanceWindow.WeekDayBasedSchedule.WindowStartTime.ForceSendFields = []string{"Hours", "Minutes"} + } res, err := w.Settings.AutomaticClusterUpdate().Update(ctx, settings.UpdateAutomaticClusterUpdateSettingRequest{ AllowMissing: true, Setting: t, @@ -49,7 +65,8 @@ var automaticClusterUpdateSetting = workspaceSetting[settings.AutomaticClusterUp Etag: etag, SettingName: "default", AutomaticClusterUpdateWorkspace: settings.ClusterAutoRestartMessage{ - Enabled: false, + Enabled: false, + ForceSendFields: []string{"Enabled"}, }, }, FieldMask: automaticClusterUpdateFieldMask, diff --git a/settings/resource_automatic_cluster_update_setting_test.go b/settings/resource_automatic_cluster_update_setting_test.go index 79a9fbea41..ea065936e2 100644 --- a/settings/resource_automatic_cluster_update_setting_test.go +++ b/settings/resource_automatic_cluster_update_setting_test.go @@ -23,7 +23,8 @@ func TestQueryCreateAutomaticClusterUpdateSetting(t *testing.T) { Setting: settings.AutomaticClusterUpdateSetting{ Etag: "", AutomaticClusterUpdateWorkspace: settings.ClusterAutoRestartMessage{ - Enabled: true, + Enabled: true, + ForceSendFields: []string{"Enabled", "RestartEvenIfNoUpdatesAvailable"}, }, SettingName: "default", }, @@ -44,7 +45,8 @@ func TestQueryCreateAutomaticClusterUpdateSetting(t *testing.T) { Setting: settings.AutomaticClusterUpdateSetting{ Etag: "etag1", AutomaticClusterUpdateWorkspace: settings.ClusterAutoRestartMessage{ - Enabled: true, + Enabled: true, + ForceSendFields: []string{"Enabled", "RestartEvenIfNoUpdatesAvailable"}, }, SettingName: "default", }, @@ -150,14 +152,16 @@ func TestQueryUpdateAutomaticClusterUpdateSetting(t *testing.T) { Etag: "etag1", AutomaticClusterUpdateWorkspace: settings.ClusterAutoRestartMessage{ Enabled: true, + ForceSendFields: []string{"Enabled", "RestartEvenIfNoUpdatesAvailable"}, RestartEvenIfNoUpdatesAvailable: true, MaintenanceWindow: &settings.ClusterAutoRestartMessageMaintenanceWindow{ WeekDayBasedSchedule: &settings.ClusterAutoRestartMessageMaintenanceWindowWeekDayBasedSchedule{ DayOfWeek: "MONDAY", Frequency: "EVERY_WEEK", WindowStartTime: &settings.ClusterAutoRestartMessageMaintenanceWindowWindowStartTime{ - Hours: 1, - Minutes: 0, + Hours: 1, + Minutes: 0, + ForceSendFields: []string{"Hours", "Minutes"}, }, }, }, @@ -238,6 +242,7 @@ func TestQueryUpdateAutomaticClusterUpdateSettingWithConflict(t *testing.T) { AutomaticClusterUpdateWorkspace: settings.ClusterAutoRestartMessage{ Enabled: true, RestartEvenIfNoUpdatesAvailable: true, + ForceSendFields: []string{"Enabled", "RestartEvenIfNoUpdatesAvailable"}, }, SettingName: "default", }, @@ -260,6 +265,7 @@ func TestQueryUpdateAutomaticClusterUpdateSettingWithConflict(t *testing.T) { AutomaticClusterUpdateWorkspace: settings.ClusterAutoRestartMessage{ Enabled: true, RestartEvenIfNoUpdatesAvailable: true, + ForceSendFields: []string{"Enabled", "RestartEvenIfNoUpdatesAvailable"}, }, SettingName: "default", }, @@ -312,7 +318,8 @@ func TestQueryDeleteAutomaticClusterUpdateSetting(t *testing.T) { Etag: "etag1", SettingName: "default", AutomaticClusterUpdateWorkspace: settings.ClusterAutoRestartMessage{ - Enabled: false, + Enabled: false, + ForceSendFields: []string{"Enabled"}, }, }, }).Return(&settings.AutomaticClusterUpdateSetting{ @@ -347,7 +354,8 @@ func TestQueryDeleteAutomaticClusterUpdateSettingWithConflict(t *testing.T) { Etag: "etag1", SettingName: "default", AutomaticClusterUpdateWorkspace: settings.ClusterAutoRestartMessage{ - Enabled: false, + Enabled: false, + ForceSendFields: []string{"Enabled"}, }, }, }).Return(nil, &apierr.APIError{ @@ -368,7 +376,8 @@ func TestQueryDeleteAutomaticClusterUpdateSettingWithConflict(t *testing.T) { Etag: "etag2", SettingName: "default", AutomaticClusterUpdateWorkspace: settings.ClusterAutoRestartMessage{ - Enabled: false, + Enabled: false, + ForceSendFields: []string{"Enabled"}, }, }, }).Return(&settings.AutomaticClusterUpdateSetting{ diff --git a/settings/resource_compliance_security_profile_setting.go b/settings/resource_compliance_security_profile_setting.go index 779bf78708..153bcfede5 100644 --- a/settings/resource_compliance_security_profile_setting.go +++ b/settings/resource_compliance_security_profile_setting.go @@ -6,7 +6,9 @@ import ( "github.com/databricks/databricks-sdk-go" "github.com/databricks/databricks-sdk-go/service/settings" + "github.com/databricks/terraform-provider-databricks/common" "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) // Enhanced Security Monitoring setting @@ -16,6 +18,11 @@ var complianceSecurityProfileFieldMask = strings.Join([]string{ }, ",") var complianceSecurityProfileSetting = workspaceSetting[settings.ComplianceSecurityProfileSetting]{ settingStruct: settings.ComplianceSecurityProfileSetting{}, + customizeSchemaFunc: func(s map[string]*schema.Schema) map[string]*schema.Schema { + common.CustomizeSchemaPath(s, "compliance_security_profile_workspace", "compliance_standards").SetRequired() + common.CustomizeSchemaPath(s, "compliance_security_profile_workspace", "is_enabled").SetRequired() + return s + }, readFunc: func(ctx context.Context, w *databricks.WorkspaceClient, etag string) (*settings.ComplianceSecurityProfileSetting, error) { return w.Settings.ComplianceSecurityProfile().Get(ctx, settings.GetComplianceSecurityProfileSettingRequest{ Etag: etag, @@ -23,6 +30,7 @@ var complianceSecurityProfileSetting = workspaceSetting[settings.ComplianceSecur }, updateFunc: func(ctx context.Context, w *databricks.WorkspaceClient, t settings.ComplianceSecurityProfileSetting) (string, error) { t.SettingName = "default" + t.ComplianceSecurityProfileWorkspace.ForceSendFields = []string{"IsEnabled"} res, err := w.Settings.ComplianceSecurityProfile().Update(ctx, settings.UpdateComplianceSecurityProfileSettingRequest{ AllowMissing: true, Setting: t, diff --git a/settings/resource_compliance_security_profile_setting_test.go b/settings/resource_compliance_security_profile_setting_test.go index 2abd08ca05..409e5e3206 100644 --- a/settings/resource_compliance_security_profile_setting_test.go +++ b/settings/resource_compliance_security_profile_setting_test.go @@ -25,6 +25,7 @@ func TestQueryCreateComplianceSecurityProfileSettingWithNoneStandard(t *testing. ComplianceSecurityProfileWorkspace: settings.ComplianceSecurityProfile{ IsEnabled: true, ComplianceStandards: []settings.ComplianceStandard{"NONE"}, + ForceSendFields: []string{"IsEnabled"}, }, SettingName: "default", }, @@ -47,6 +48,7 @@ func TestQueryCreateComplianceSecurityProfileSettingWithNoneStandard(t *testing. ComplianceSecurityProfileWorkspace: settings.ComplianceSecurityProfile{ IsEnabled: true, ComplianceStandards: []settings.ComplianceStandard{"NONE"}, + ForceSendFields: []string{"IsEnabled"}, }, SettingName: "default", }, @@ -136,6 +138,7 @@ func TestQueryUpdateComplianceSecurityProfileSetting(t *testing.T) { ComplianceSecurityProfileWorkspace: settings.ComplianceSecurityProfile{ IsEnabled: true, ComplianceStandards: []settings.ComplianceStandard{"HIPAA", "PCI_DSS"}, + ForceSendFields: []string{"IsEnabled"}, }, SettingName: "default", }, @@ -192,6 +195,7 @@ func TestQueryUpdateComplianceSecurityProfileSettingWithConflict(t *testing.T) { ComplianceSecurityProfileWorkspace: settings.ComplianceSecurityProfile{ IsEnabled: true, ComplianceStandards: []settings.ComplianceStandard{"HIPAA"}, + ForceSendFields: []string{"IsEnabled"}, }, SettingName: "default", }, @@ -214,6 +218,7 @@ func TestQueryUpdateComplianceSecurityProfileSettingWithConflict(t *testing.T) { ComplianceSecurityProfileWorkspace: settings.ComplianceSecurityProfile{ IsEnabled: true, ComplianceStandards: []settings.ComplianceStandard{"HIPAA"}, + ForceSendFields: []string{"IsEnabled"}, }, SettingName: "default", }, diff --git a/settings/resource_enhanced_security_monitoring_setting.go b/settings/resource_enhanced_security_monitoring_setting.go index 602855b92e..d61dc96ecb 100644 --- a/settings/resource_enhanced_security_monitoring_setting.go +++ b/settings/resource_enhanced_security_monitoring_setting.go @@ -6,6 +6,8 @@ import ( "github.com/databricks/databricks-sdk-go" "github.com/databricks/databricks-sdk-go/service/settings" + "github.com/databricks/terraform-provider-databricks/common" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) // Enhanced Security Monitoring setting @@ -14,6 +16,10 @@ var enhancedSecurityMonitoringFieldMask = strings.Join([]string{ }, ",") var enhancedSecurityMonitoringSetting = workspaceSetting[settings.EnhancedSecurityMonitoringSetting]{ settingStruct: settings.EnhancedSecurityMonitoringSetting{}, + customizeSchemaFunc: func(s map[string]*schema.Schema) map[string]*schema.Schema { + common.CustomizeSchemaPath(s, "enhanced_security_monitoring_workspace", "is_enabled").SetRequired() + return s + }, readFunc: func(ctx context.Context, w *databricks.WorkspaceClient, etag string) (*settings.EnhancedSecurityMonitoringSetting, error) { return w.Settings.EnhancedSecurityMonitoring().Get(ctx, settings.GetEnhancedSecurityMonitoringSettingRequest{ Etag: etag, @@ -21,6 +27,7 @@ var enhancedSecurityMonitoringSetting = workspaceSetting[settings.EnhancedSecuri }, updateFunc: func(ctx context.Context, w *databricks.WorkspaceClient, t settings.EnhancedSecurityMonitoringSetting) (string, error) { t.SettingName = "default" + t.EnhancedSecurityMonitoringWorkspace.ForceSendFields = []string{"IsEnabled"} res, err := w.Settings.EnhancedSecurityMonitoring().Update(ctx, settings.UpdateEnhancedSecurityMonitoringSettingRequest{ AllowMissing: true, Setting: t, @@ -38,7 +45,8 @@ var enhancedSecurityMonitoringSetting = workspaceSetting[settings.EnhancedSecuri Etag: etag, SettingName: "default", EnhancedSecurityMonitoringWorkspace: settings.EnhancedSecurityMonitoring{ - IsEnabled: false, + IsEnabled: false, + ForceSendFields: []string{"IsEnabled"}, }, }, FieldMask: enhancedSecurityMonitoringFieldMask, diff --git a/settings/resource_enhanced_security_monitoring_setting_test.go b/settings/resource_enhanced_security_monitoring_setting_test.go index c09bb1804e..4c2c3a3e65 100644 --- a/settings/resource_enhanced_security_monitoring_setting_test.go +++ b/settings/resource_enhanced_security_monitoring_setting_test.go @@ -23,7 +23,8 @@ func TestQueryCreateEnhancedSecurityMonitoringSetting(t *testing.T) { Setting: settings.EnhancedSecurityMonitoringSetting{ Etag: "", EnhancedSecurityMonitoringWorkspace: settings.EnhancedSecurityMonitoring{ - IsEnabled: true, + IsEnabled: true, + ForceSendFields: []string{"IsEnabled"}, }, SettingName: "default", }, @@ -44,7 +45,8 @@ func TestQueryCreateEnhancedSecurityMonitoringSetting(t *testing.T) { Setting: settings.EnhancedSecurityMonitoringSetting{ Etag: "etag1", EnhancedSecurityMonitoringWorkspace: settings.EnhancedSecurityMonitoring{ - IsEnabled: true, + IsEnabled: true, + ForceSendFields: []string{"IsEnabled"}, }, SettingName: "default", }, @@ -123,14 +125,16 @@ func TestQueryUpdateEnhancedSecurityMonitoringSetting(t *testing.T) { Setting: settings.EnhancedSecurityMonitoringSetting{ Etag: "etag1", EnhancedSecurityMonitoringWorkspace: settings.EnhancedSecurityMonitoring{ - IsEnabled: true, + IsEnabled: true, + ForceSendFields: []string{"IsEnabled"}, }, SettingName: "default", }, }).Return(&settings.EnhancedSecurityMonitoringSetting{ Etag: "etag2", EnhancedSecurityMonitoringWorkspace: settings.EnhancedSecurityMonitoring{ - IsEnabled: true, + IsEnabled: true, + ForceSendFields: []string{"IsEnabled"}, }, SettingName: "default", }, nil) @@ -173,7 +177,8 @@ func TestQueryUpdateEnhancedSecurityMonitoringSettingWithConflict(t *testing.T) Setting: settings.EnhancedSecurityMonitoringSetting{ Etag: "etag1", EnhancedSecurityMonitoringWorkspace: settings.EnhancedSecurityMonitoring{ - IsEnabled: true, + IsEnabled: true, + ForceSendFields: []string{"IsEnabled"}, }, SettingName: "default", }, @@ -194,7 +199,8 @@ func TestQueryUpdateEnhancedSecurityMonitoringSettingWithConflict(t *testing.T) Setting: settings.EnhancedSecurityMonitoringSetting{ Etag: "etag2", EnhancedSecurityMonitoringWorkspace: settings.EnhancedSecurityMonitoring{ - IsEnabled: true, + IsEnabled: true, + ForceSendFields: []string{"IsEnabled"}, }, SettingName: "default", }, @@ -244,7 +250,8 @@ func TestQueryDeleteEnhancedSecurityMonitoringSetting(t *testing.T) { Etag: "etag1", SettingName: "default", EnhancedSecurityMonitoringWorkspace: settings.EnhancedSecurityMonitoring{ - IsEnabled: false, + IsEnabled: false, + ForceSendFields: []string{"IsEnabled"}, }, }, }).Return(&settings.EnhancedSecurityMonitoringSetting{ @@ -279,7 +286,8 @@ func TestQueryDeleteEnhancedSecurityMonitoringSettingWithConflict(t *testing.T) Etag: "etag1", SettingName: "default", EnhancedSecurityMonitoringWorkspace: settings.EnhancedSecurityMonitoring{ - IsEnabled: false, + IsEnabled: false, + ForceSendFields: []string{"IsEnabled"}, }, }, }).Return(nil, &apierr.APIError{ @@ -300,7 +308,8 @@ func TestQueryDeleteEnhancedSecurityMonitoringSettingWithConflict(t *testing.T) Etag: "etag2", SettingName: "default", EnhancedSecurityMonitoringWorkspace: settings.EnhancedSecurityMonitoring{ - IsEnabled: false, + IsEnabled: false, + ForceSendFields: []string{"IsEnabled"}, }, }, }).Return(&settings.EnhancedSecurityMonitoringSetting{ From 661e682383ad70f71a0a64ba997b8eb214e5dd4c Mon Sep 17 00:00:00 2001 From: Omer Lachish <289488+rauchy@users.noreply.github.com> Date: Tue, 3 Sep 2024 11:26:12 +0200 Subject: [PATCH 11/54] [Internal] Migrate Share resource to Go SDK (#3916) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Changes This PR is my first attempt at migrating the Share resource from using hand-crafted API calls to the Databricks Go SDK. I’ve updated the `Read` function to use the SDK’s `Get` method. Next, I’ll work on migrating the remaining CRUD operations. I’ve run the existing tests to ensure everything is still working as expected. Update: also included Create & Update here, which makes the Share resource go through the Go SDK for all CRUD operations. ## Tests - [ ] `make test` run locally - [ ] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [ ] using Go SDK --------- Co-authored-by: Omer Lachish --- common/resource.go | 45 +-- exporter/importables_test.go | 36 +-- sharing/data_share.go | 48 +++- sharing/data_share_test.go | 11 +- sharing/data_shares_test.go | 22 +- sharing/resource_share.go | 209 +++++++------- sharing/resource_share_test.go | 499 +++++++++++++++++---------------- 7 files changed, 464 insertions(+), 406 deletions(-) diff --git a/common/resource.go b/common/resource.go index 79a1264086..77ba894853 100644 --- a/common/resource.go +++ b/common/resource.go @@ -381,30 +381,31 @@ func genericDatabricksData[T, P, C any]( var dummy T var other P otherFields := StructToSchema(other, nil) - s := StructToSchema(dummy, func(m map[string]*schema.Schema) map[string]*schema.Schema { - // For WorkspaceData and AccountData, a single data type is used to represent all of the fields of - // the resource, so its configuration is correct. For the *WithParams methods, the SdkType parameter - // is copied directly from the resource definition, which means that all fields from that type are - // computed and optional, and the fields from OtherFields are overlaid on top of the schema generated - // by SdkType. - if hasOther { - for k := range m { - m[k].Computed = true - m[k].Required = false - m[k].Optional = true - } - for k, v := range otherFields { - m[k] = v - } + + s := StructToSchema(dummy, nil) + // For WorkspaceData and AccountData, a single data type is used to represent all of the fields of + // the resource, so its configuration is correct. For the *WithParams methods, the SdkType parameter + // is copied directly from the resource definition, which means that all fields from that type are + // computed and optional, and the fields from OtherFields are overlaid on top of the schema generated + // by SdkType. + if hasOther { + for k := range s { + s[k].Computed = true + s[k].Required = false + s[k].Optional = true } - // `id` attribute must be marked as computed, otherwise it's not set! - if v, ok := m["id"]; ok { - v.Computed = true - v.Required = false + for k, v := range otherFields { + s[k] = v } - // allow c - return customizeSchemaFunc(m) - }) + } + // `id` attribute must be marked as computed, otherwise it's not set! + if v, ok := s["id"]; ok { + v.Computed = true + v.Required = false + } + // allow c + s = customizeSchemaFunc(s) + return Resource{ Schema: s, Read: func(ctx context.Context, d *schema.ResourceData, client *DatabricksClient) (err error) { diff --git a/exporter/importables_test.go b/exporter/importables_test.go index e18d9d163e..b503117595 100644 --- a/exporter/importables_test.go +++ b/exporter/importables_test.go @@ -1828,23 +1828,25 @@ func TestImportShare(t *testing.T) { d := tfsharing.ResourceShare().ToResource().TestResourceData() scm := tfsharing.ResourceShare().Schema share := tfsharing.ShareInfo{ - Name: "stest", - Objects: []tfsharing.SharedDataObject{ - { - DataObjectType: "TABLE", - Name: "ctest.stest.table1", - }, - { - DataObjectType: "MODEL", - Name: "ctest.stest.model1", - }, - { - DataObjectType: "VOLUME", - Name: "ctest.stest.vol1", - }, - { - DataObjectType: "NOTEBOOK", - Name: "Test", + ShareInfo: sharing.ShareInfo{ + Name: "stest", + Objects: []sharing.SharedDataObject{ + { + DataObjectType: "TABLE", + Name: "ctest.stest.table1", + }, + { + DataObjectType: "MODEL", + Name: "ctest.stest.model1", + }, + { + DataObjectType: "VOLUME", + Name: "ctest.stest.vol1", + }, + { + DataObjectType: "NOTEBOOK", + Name: "Test", + }, }, }, } diff --git a/sharing/data_share.go b/sharing/data_share.go index 0542956d6a..1e15176112 100644 --- a/sharing/data_share.go +++ b/sharing/data_share.go @@ -3,20 +3,48 @@ package sharing import ( "context" + "github.com/databricks/databricks-sdk-go" + "github.com/databricks/databricks-sdk-go/service/sharing" "github.com/databricks/terraform-provider-databricks/common" ) -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"` - CreatedAt int64 `json:"created_at,omitempty" tf:"computed"` - CreatedBy string `json:"created_by,omitempty" tf:"computed"` +type ShareDetail struct { + Name string `json:"name,omitempty" tf:"computed"` + Objects []sharing.SharedDataObject `json:"objects,omitempty" tf:"computed,slice_set,alias:object"` + CreatedAt int64 `json:"created_at,omitempty" tf:"computed"` + CreatedBy string `json:"created_by,omitempty" tf:"computed"` +} + +func (ShareDetail) CustomizeSchema(s *common.CustomizableSchema) *common.CustomizableSchema { + s.SchemaPath("name").SetComputed() + s.SchemaPath("object", "added_at").SetComputed() + s.SchemaPath("object", "added_by").SetComputed() + s.SchemaPath("object", "data_object_type").SetRequired() + s.SchemaPath("object", "status").SetComputed() + s.SchemaPath("object", "partition", "value", "op").SetRequired() + s.SchemaPath("object", "partition", "value", "name").SetRequired() + s.SchemaPath("object", "partition", "value").SetMinItems(1) + + return s +} + +func (ShareDetail) Aliases() map[string]map[string]string { + return map[string]map[string]string{ + "sharing.SharedDataObject": { + "partitions": "partition", + }, + "sharing.Partition": { + "values": "value", + }, } - return common.DataResource(ShareDetail{}, func(ctx context.Context, e any, c *common.DatabricksClient) error { - data := e.(*ShareDetail) - sharesAPI := NewSharesAPI(ctx, c) - share, err := sharesAPI.get(data.Name) +} + +func DataSourceShare() common.Resource { + return common.WorkspaceData(func(ctx context.Context, data *ShareDetail, client *databricks.WorkspaceClient) error { + share, err := client.Shares.Get(ctx, sharing.GetShareRequest{ + Name: data.Name, + IncludeSharedData: true, + }) if err != nil { return err } diff --git a/sharing/data_share_test.go b/sharing/data_share_test.go index 8211d145a5..5cda61ea7a 100644 --- a/sharing/data_share_test.go +++ b/sharing/data_share_test.go @@ -3,6 +3,7 @@ package sharing import ( "testing" + "github.com/databricks/databricks-sdk-go/service/sharing" "github.com/databricks/terraform-provider-databricks/qa" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/stretchr/testify/assert" @@ -14,21 +15,21 @@ func TestShareData(t *testing.T) { { Method: "GET", Resource: "/api/2.1/unity-catalog/shares/a?include_shared_data=true", - Response: ShareInfo{ + Response: sharing.ShareInfo{ Name: "a", - Objects: []SharedDataObject{ + Objects: []sharing.SharedDataObject{ { Name: "a", DataObjectType: "TABLE", Comment: "c", - CDFEnabled: false, + CdfEnabled: false, StartVersion: 0, SharedAs: "", AddedAt: 0, AddedBy: "", HistoryDataSharingStatus: "DISABLED", Status: "ACTIVE", - Partitions: []Partition{}, + Partitions: []sharing.Partition{}, }, }, CreatedBy: "bob", @@ -52,10 +53,12 @@ func TestShareData(t *testing.T) { "added_at": 0, "added_by": "", "comment": "c", + "content": "", "data_object_type": "TABLE", "name": "a", "shared_as": "", "start_version": 0, + "string_shared_as": "", "cdf_enabled": false, "status": "ACTIVE", "history_data_sharing_status": "DISABLED", diff --git a/sharing/data_shares_test.go b/sharing/data_shares_test.go index dce65b0c82..8afddc0b33 100644 --- a/sharing/data_shares_test.go +++ b/sharing/data_shares_test.go @@ -3,6 +3,7 @@ package sharing import ( "testing" + "github.com/databricks/databricks-sdk-go/service/sharing" "github.com/databricks/terraform-provider-databricks/qa" ) @@ -15,17 +16,18 @@ func TestSharesData(t *testing.T) { Response: Shares{ Shares: []ShareInfo{ { - Name: "a", - Objects: []SharedDataObject{ - { - Name: "a", - DataObjectType: "TABLE", - Comment: "c", + sharing.ShareInfo{ + Name: "a", + Objects: []sharing.SharedDataObject{ + { + Name: "a", + DataObjectType: "TABLE", + Comment: "c", + }, }, - }, - CreatedAt: 0, - CreatedBy: "", - }, + CreatedAt: 0, + CreatedBy: "", + }}, }, }, }, diff --git a/sharing/resource_share.go b/sharing/resource_share.go index e2953068e9..f45aa6a0fb 100644 --- a/sharing/resource_share.go +++ b/sharing/resource_share.go @@ -11,68 +11,53 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -type SharesAPI struct { - client *common.DatabricksClient - context context.Context -} - -func NewSharesAPI(ctx context.Context, m any) SharesAPI { - return SharesAPI{m.(*common.DatabricksClient), context.WithValue(ctx, common.Api, common.API_2_1)} -} - -const ( - ShareAdd = "ADD" - ShareRemove = "REMOVE" - ShareUpdate = "UPDATE" -) - type ShareInfo struct { - Name string `json:"name" tf:"force_new"` - Owner string `json:"owner,omitempty" tf:"suppress_diff"` - Objects []SharedDataObject `json:"objects,omitempty" tf:"alias:object"` - CreatedAt int64 `json:"created_at,omitempty" tf:"computed"` - CreatedBy string `json:"created_by,omitempty" tf:"computed"` + sharing.ShareInfo } -type SharedDataObject struct { - Name string `json:"name"` - DataObjectType string `json:"data_object_type"` - Comment string `json:"comment,omitempty"` - SharedAs string `json:"shared_as,omitempty" tf:"suppress_diff"` - CDFEnabled bool `json:"cdf_enabled,omitempty" tf:"suppress_diff"` - StartVersion int64 `json:"start_version,omitempty" tf:"suppress_diff"` - HistoryDataSharingStatus string `json:"history_data_sharing_status,omitempty" tf:"suppress_diff"` - Partitions []Partition `json:"partitions,omitempty" tf:"alias:partition"` - Status string `json:"status,omitempty" tf:"computed"` - AddedAt int64 `json:"added_at,omitempty" tf:"computed"` - AddedBy string `json:"added_by,omitempty" tf:"computed"` -} +func (ShareInfo) CustomizeSchema(s *common.CustomizableSchema) *common.CustomizableSchema { + s.SchemaPath("name").SetRequired() + s.SchemaPath("name").SetForceNew() + s.SchemaPath("name").SetCustomSuppressDiff(common.EqualFoldDiffSuppress) + s.SchemaPath("owner").SetSuppressDiff() + s.SchemaPath("created_at").SetComputed() + s.SchemaPath("created_by").SetComputed() + s.SchemaPath("updated_at").SetComputed() + s.SchemaPath("updated_by").SetComputed() + + s.SchemaPath("object").SetMinItems(1) + s.SchemaPath("object", "data_object_type").SetRequired() + s.SchemaPath("object", "shared_as").SetSuppressDiff() + s.SchemaPath("object", "cdf_enabled").SetSuppressDiff() + s.SchemaPath("object", "start_version").SetSuppressDiff() + s.SchemaPath("object", "history_data_sharing_status").SetSuppressDiff() + s.SchemaPath("object", "status").SetComputed() + s.SchemaPath("object", "added_at").SetComputed() + s.SchemaPath("object", "added_by").SetComputed() + s.SchemaPath("object", "partition", "value", "op").SetRequired() + s.SchemaPath("object", "partition", "value", "name").SetRequired() -type ShareDataChange struct { - Action string `json:"action"` - DataObject SharedDataObject `json:"data_object"` + return s } -type ShareUpdates struct { - Owner string `json:"owner,omitempty"` - Updates []ShareDataChange `json:"updates"` +func (ShareInfo) Aliases() map[string]map[string]string { + return map[string]map[string]string{ + "sharing.ShareInfo": { + "objects": "object", + }, + "sharing.SharedDataObject": { + "partitions": "partition", + }, + "sharing.Partition": { + "values": "value", + }, + } } type Shares struct { Shares []ShareInfo `json:"shares"` } -type Partition struct { - Values []PartitionValue `json:"values" tf:"alias:value"` -} - -type PartitionValue struct { - Name string `json:"name"` - Op string `json:"op"` - RecipientPropertyKey string `json:"recipient_property_key,omitempty"` - Value string `json:"value,omitempty"` -} - func (si *ShareInfo) sortSharesByName() { sort.Slice(si.Objects, func(i, j int) bool { return si.Objects[i].Name < si.Objects[j].Name @@ -83,70 +68,58 @@ func (si *ShareInfo) suppressCDFEnabledDiff() { //suppress diff for CDF Enabled if HistoryDataSharingStatus is enabled , as API does not accept both fields to be set for i := range si.Objects { if si.Objects[i].HistoryDataSharingStatus == "ENABLED" { - si.Objects[i].CDFEnabled = false + si.Objects[i].CdfEnabled = false } } } -func (a SharesAPI) get(name string) (si ShareInfo, err error) { - err = a.client.Get(a.context, "/unity-catalog/shares/"+name+"?include_shared_data=true", nil, &si) - si.sortSharesByName() - si.suppressCDFEnabledDiff() - return -} - -func (a SharesAPI) update(name string, su ShareUpdates) error { - if len(su.Updates) == 0 { - return nil - } - return a.client.Patch(a.context, "/unity-catalog/shares/"+name, su) -} - -func (si ShareInfo) shareChanges(action string) ShareUpdates { - var changes []ShareDataChange +func (si ShareInfo) shareChanges(action string) sharing.UpdateShare { + var changes []sharing.SharedDataObjectUpdate for _, obj := range si.Objects { - changes = append(changes, ShareDataChange{ - Action: action, - DataObject: obj, - }) + changes = append(changes, sharing.SharedDataObjectUpdate{ + Action: sharing.SharedDataObjectUpdateAction(action), + DataObject: &obj, + }, + ) } - return ShareUpdates{ + return sharing.UpdateShare{ Updates: changes, } } -func (si ShareInfo) resourceShareMap() map[string]SharedDataObject { - m := make(map[string]SharedDataObject, len(si.Objects)) +func (si ShareInfo) resourceShareMap() map[string]sharing.SharedDataObject { + m := make(map[string]sharing.SharedDataObject, len(si.Objects)) for _, sdo := range si.Objects { m[sdo.Name] = sdo } return m } -func (sdo SharedDataObject) Equal(other SharedDataObject) bool { +func Equal(this sharing.SharedDataObject, other sharing.SharedDataObject) bool { if other.SharedAs == "" { - other.SharedAs = sdo.SharedAs + other.SharedAs = this.SharedAs } //don't compare computed fields - other.AddedAt = sdo.AddedAt - other.AddedBy = sdo.AddedBy - other.Status = sdo.Status - return reflect.DeepEqual(sdo, other) + other.AddedAt = this.AddedAt + other.AddedBy = this.AddedBy + other.Status = this.Status + other.ForceSendFields = this.ForceSendFields // TODO: is this the right thing to do? + return reflect.DeepEqual(this, other) } -func (beforeSi ShareInfo) Diff(afterSi ShareInfo) []ShareDataChange { +func (beforeSi ShareInfo) Diff(afterSi ShareInfo) []sharing.SharedDataObjectUpdate { beforeMap := beforeSi.resourceShareMap() afterMap := afterSi.resourceShareMap() - changes := []ShareDataChange{} + changes := []sharing.SharedDataObjectUpdate{} // not in after so remove for _, beforeSdo := range beforeSi.Objects { _, exists := afterMap[beforeSdo.Name] if exists { continue } - changes = append(changes, ShareDataChange{ - Action: ShareRemove, - DataObject: beforeSdo, + changes = append(changes, sharing.SharedDataObjectUpdate{ + Action: sharing.SharedDataObjectUpdateActionRemove, + DataObject: &beforeSdo, }) } @@ -155,29 +128,26 @@ func (beforeSi ShareInfo) Diff(afterSi ShareInfo) []ShareDataChange { for _, afterSdo := range afterSi.Objects { beforeSdo, exists := beforeMap[afterSdo.Name] if exists { - if !beforeSdo.Equal(afterSdo) { + if !Equal(beforeSdo, afterSdo) { // do not send SharedAs afterSdo.SharedAs = "" - changes = append(changes, ShareDataChange{ - Action: ShareUpdate, - DataObject: afterSdo, + changes = append(changes, sharing.SharedDataObjectUpdate{ + Action: sharing.SharedDataObjectUpdateActionUpdate, + DataObject: &afterSdo, }) } continue } - changes = append(changes, ShareDataChange{ - Action: ShareAdd, - DataObject: afterSdo, + changes = append(changes, sharing.SharedDataObjectUpdate{ + Action: sharing.SharedDataObjectUpdateActionAdd, + DataObject: &afterSdo, }) } return changes } func ResourceShare() common.Resource { - shareSchema := common.StructToSchema(ShareInfo{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { - m["name"].DiffSuppressFunc = common.EqualFoldDiffSuppress - return m - }) + shareSchema := common.StructToSchema(ShareInfo{}, nil) return common.Resource{ Schema: shareSchema, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { @@ -195,9 +165,10 @@ func ResourceShare() common.Resource { //can only create empty share, objects & owners have to be added using update API var si ShareInfo common.DataToStructPointer(d, shareSchema, &si) - shareChanges := si.shareChanges(ShareAdd) + shareChanges := si.shareChanges(string(sharing.SharedDataObjectUpdateActionAdd)) + shareChanges.Name = si.Name shareChanges.Owner = si.Owner - if err := NewSharesAPI(ctx, c).update(si.Name, shareChanges); err != nil { + if _, err := w.Shares.Update(ctx, shareChanges); err != nil { //delete orphaned share if update fails if d_err := w.Shares.DeleteByName(ctx, si.Name); d_err != nil { return d_err @@ -208,28 +179,47 @@ func ResourceShare() common.Resource { return nil }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - si, err := NewSharesAPI(ctx, c).get(d.Id()) + client, err := c.WorkspaceClient() if err != nil { return err } + + shareInfo, err := client.Shares.Get(ctx, sharing.GetShareRequest{ + Name: d.Id(), + IncludeSharedData: true, + }) + var si = ShareInfo{*shareInfo} + si.sortSharesByName() + si.suppressCDFEnabledDiff() + if err != nil { + return err + } + return common.StructToData(si, shareSchema, d) }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - beforeSi, err := NewSharesAPI(ctx, c).get(d.Id()) + client, err := c.WorkspaceClient() if err != nil { return err } - var afterSi ShareInfo - common.DataToStructPointer(d, shareSchema, &afterSi) - changes := beforeSi.Diff(afterSi) - w, err := c.WorkspaceClient() + si, err := client.Shares.Get(ctx, sharing.GetShareRequest{ + Name: d.Id(), + IncludeSharedData: true, + }) if err != nil { return err } + var beforeSi = ShareInfo{*si} + beforeSi.sortSharesByName() + beforeSi.suppressCDFEnabledDiff() + var afterSi ShareInfo + common.DataToStructPointer(d, shareSchema, &afterSi) + changes := beforeSi.Diff(afterSi) + if d.HasChange("owner") { - _, err = w.Shares.Update(ctx, sharing.UpdateShare{ + _, err = client.Shares.Update(ctx, sharing.UpdateShare{ Name: afterSi.Name, Owner: afterSi.Owner, }) @@ -242,14 +232,19 @@ func ResourceShare() common.Resource { return nil } - err = NewSharesAPI(ctx, c).update(d.Id(), ShareUpdates{ + if len(changes) == 0 { + return nil + } + + _, err = client.Shares.Update(ctx, sharing.UpdateShare{ + Name: d.Id(), Updates: changes, }) if err != nil { if d.HasChange("owner") { // Rollback old, new := d.GetChange("owner") - _, rollbackErr := w.Shares.Update(ctx, sharing.UpdateShare{ + _, rollbackErr := client.Shares.Update(ctx, sharing.UpdateShare{ Name: beforeSi.Name, Owner: old.(string), }) diff --git a/sharing/resource_share_test.go b/sharing/resource_share_test.go index 7d03f76089..73a6a27289 100644 --- a/sharing/resource_share_test.go +++ b/sharing/resource_share_test.go @@ -12,160 +12,166 @@ import ( func TestDiffShareInfo(t *testing.T) { empty := ShareInfo{ - Name: "b", - Objects: []SharedDataObject{}, + ShareInfo: sharing.ShareInfo{ + Name: "b", + Objects: []sharing.SharedDataObject{}, + }, } firstShare := ShareInfo{ - Name: "b", - Objects: []SharedDataObject{ - { - Name: "main.b", - DataObjectType: "TABLE", - Comment: "c", - }, - { - Name: "main.a", - DataObjectType: "TABLE", - Comment: "c", - }, - }, + ShareInfo: sharing.ShareInfo{ + Name: "b", + Objects: []sharing.SharedDataObject{ + { + Name: "main.b", + DataObjectType: "TABLE", + Comment: "c", + }, + { + Name: "main.a", + DataObjectType: "TABLE", + Comment: "c", + }, + }}, } secondShare := ShareInfo{ - Name: "b", - Objects: []SharedDataObject{ - { - Name: "main.c", - DataObjectType: "TABLE", - Comment: "d", - }, - { - Name: "main.a", - DataObjectType: "TABLE", - Comment: "c", - }, - }, + ShareInfo: sharing.ShareInfo{ + Name: "b", + Objects: []sharing.SharedDataObject{ + { + Name: "main.c", + DataObjectType: "TABLE", + Comment: "d", + }, + { + Name: "main.a", + DataObjectType: "TABLE", + Comment: "c", + }, + }}, } thirdShare := ShareInfo{ - Name: "b", - Objects: []SharedDataObject{ - { - Name: "main.c", - DataObjectType: "TABLE", - Comment: "d", - }, - { - Name: "main.b", - DataObjectType: "TABLE", - Comment: "d", - }, - }, + ShareInfo: sharing.ShareInfo{ + Name: "b", + Objects: []sharing.SharedDataObject{ + { + Name: "main.c", + DataObjectType: "TABLE", + Comment: "d", + }, + { + Name: "main.b", + DataObjectType: "TABLE", + Comment: "d", + }, + }}, } fourthShare := ShareInfo{ - Name: "d", - Objects: []SharedDataObject{ - { - Name: "main.b", - DataObjectType: "TABLE", - Comment: "d", - }, - { - Name: "main.a", - DataObjectType: "TABLE", - Comment: "c", - }, - }, + ShareInfo: sharing.ShareInfo{ + Name: "d", + Objects: []sharing.SharedDataObject{ + { + Name: "main.b", + DataObjectType: "TABLE", + Comment: "d", + }, + { + Name: "main.a", + DataObjectType: "TABLE", + Comment: "c", + }, + }}, } - diffAdd := []ShareDataChange{ + diffAdd := []sharing.SharedDataObjectUpdate{ { - Action: ShareAdd, - DataObject: SharedDataObject{ + Action: sharing.SharedDataObjectUpdateActionAdd, + DataObject: &sharing.SharedDataObject{ Name: "main.b", DataObjectType: "TABLE", Comment: "c", }, }, { - Action: ShareAdd, - DataObject: SharedDataObject{ + Action: sharing.SharedDataObjectUpdateActionAdd, + DataObject: &sharing.SharedDataObject{ Name: "main.a", DataObjectType: "TABLE", Comment: "c", }, }, } - diffRemove := []ShareDataChange{ + diffRemove := []sharing.SharedDataObjectUpdate{ { - Action: ShareRemove, - DataObject: SharedDataObject{ + Action: sharing.SharedDataObjectUpdateActionRemove, + DataObject: &sharing.SharedDataObject{ Name: "main.b", DataObjectType: "TABLE", Comment: "c", }, }, { - Action: ShareRemove, - DataObject: SharedDataObject{ + Action: sharing.SharedDataObjectUpdateActionRemove, + DataObject: &sharing.SharedDataObject{ Name: "main.a", DataObjectType: "TABLE", Comment: "c", }, }, } - diff12 := []ShareDataChange{ + diff12 := []sharing.SharedDataObjectUpdate{ { - Action: ShareRemove, - DataObject: SharedDataObject{ + Action: sharing.SharedDataObjectUpdateActionRemove, + DataObject: &sharing.SharedDataObject{ Name: "main.b", DataObjectType: "TABLE", Comment: "c", }, }, { - Action: ShareAdd, - DataObject: SharedDataObject{ + Action: sharing.SharedDataObjectUpdateActionAdd, + DataObject: &sharing.SharedDataObject{ Name: "main.c", DataObjectType: "TABLE", Comment: "d", }, }, } - diff13 := []ShareDataChange{ + diff13 := []sharing.SharedDataObjectUpdate{ { - Action: ShareRemove, - DataObject: SharedDataObject{ + Action: sharing.SharedDataObjectUpdateActionRemove, + DataObject: &sharing.SharedDataObject{ Name: "main.a", DataObjectType: "TABLE", Comment: "c", }, }, { - Action: ShareAdd, - DataObject: SharedDataObject{ + Action: sharing.SharedDataObjectUpdateActionAdd, + DataObject: &sharing.SharedDataObject{ Name: "main.c", DataObjectType: "TABLE", Comment: "d", }, }, { - Action: ShareUpdate, - DataObject: SharedDataObject{ + Action: sharing.SharedDataObjectUpdateActionUpdate, + DataObject: &sharing.SharedDataObject{ Name: "main.b", DataObjectType: "TABLE", Comment: "d", }, }, } - diff14 := []ShareDataChange{ + diff14 := []sharing.SharedDataObjectUpdate{ { - Action: ShareUpdate, - DataObject: SharedDataObject{ + Action: sharing.SharedDataObjectUpdateActionUpdate, + DataObject: &sharing.SharedDataObject{ Name: "main.b", DataObjectType: "TABLE", Comment: "d", }, }, } - assert.Equal(t, firstShare.Diff(firstShare), []ShareDataChange{}, "Should not have difference") + assert.Equal(t, firstShare.Diff(firstShare), []sharing.SharedDataObjectUpdate{}, "Should not have difference") assert.Equal(t, empty.Diff(firstShare), diffAdd, "Should have 2 ADDs") assert.Equal(t, firstShare.Diff(empty), diffRemove, "Should have 2 REMOVEs") assert.Equal(t, firstShare.Diff(secondShare), diff12, "Should have 1 ADD and 1 REMOVE") @@ -184,21 +190,24 @@ func TestCreateShare(t *testing.T) { Method: "POST", Resource: "/api/2.1/unity-catalog/shares", ExpectedRequest: ShareInfo{ - Name: "a", + ShareInfo: sharing.ShareInfo{ + Name: "a", + }, }, Response: ShareInfo{ - Name: "a", - }, + ShareInfo: sharing.ShareInfo{ + Name: "a", + }}, }, { Method: "PATCH", Resource: "/api/2.1/unity-catalog/shares/a", - ExpectedRequest: ShareUpdates{ + ExpectedRequest: sharing.UpdateShare{ Owner: "admin", - Updates: []ShareDataChange{ + Updates: []sharing.SharedDataObjectUpdate{ { Action: "ADD", - DataObject: SharedDataObject{ + DataObject: &sharing.SharedDataObject{ Name: "main.a", DataObjectType: "TABLE", Comment: "c", @@ -206,7 +215,7 @@ func TestCreateShare(t *testing.T) { }, { Action: "ADD", - DataObject: SharedDataObject{ + DataObject: &sharing.SharedDataObject{ Name: "main.b", DataObjectType: "TABLE", Comment: "c", @@ -215,27 +224,30 @@ func TestCreateShare(t *testing.T) { }, }, Response: ShareInfo{ - Name: "a", + ShareInfo: sharing.ShareInfo{ + Name: "a", + }, }, }, { Method: "GET", Resource: "/api/2.1/unity-catalog/shares/a?include_shared_data=true", Response: ShareInfo{ - Name: "a", - Owner: "admin", - Objects: []SharedDataObject{ - { - Name: "main.a", - DataObjectType: "TABLE", - Comment: "c", - }, - { - Name: "main.b", - DataObjectType: "TABLE", - Comment: "c", - }, - }, + ShareInfo: sharing.ShareInfo{ + Name: "a", + Owner: "admin", + Objects: []sharing.SharedDataObject{ + { + Name: "main.a", + DataObjectType: "TABLE", + Comment: "c", + }, + { + Name: "main.b", + DataObjectType: "TABLE", + Comment: "c", + }, + }}, }, }, }, @@ -265,17 +277,18 @@ func TestUpdateShare(t *testing.T) { Method: "GET", Resource: "/api/2.1/unity-catalog/shares/abc?include_shared_data=true", Response: ShareInfo{ - Name: "abc", - Objects: []SharedDataObject{ - { - Name: "d", - DataObjectType: "TABLE", - Comment: "d", - SharedAs: "", - AddedAt: 0, - AddedBy: "", - }, - }, + ShareInfo: sharing.ShareInfo{ + Name: "abc", + Objects: []sharing.SharedDataObject{ + { + Name: "d", + DataObjectType: "TABLE", + Comment: "d", + SharedAs: "", + AddedAt: 0, + AddedBy: "", + }, + }}, }, }, { @@ -288,11 +301,11 @@ func TestUpdateShare(t *testing.T) { { Method: "PATCH", Resource: "/api/2.1/unity-catalog/shares/abc", - ExpectedRequest: ShareUpdates{ - Updates: []ShareDataChange{ + ExpectedRequest: sharing.UpdateShare{ + Updates: []sharing.SharedDataObjectUpdate{ { Action: "REMOVE", - DataObject: SharedDataObject{ + DataObject: &sharing.SharedDataObject{ Comment: "d", DataObjectType: "TABLE", Name: "d", @@ -300,7 +313,7 @@ func TestUpdateShare(t *testing.T) { }, { Action: "ADD", - DataObject: SharedDataObject{ + DataObject: &sharing.SharedDataObject{ Comment: "c", DataObjectType: "TABLE", Name: "a", @@ -308,7 +321,7 @@ func TestUpdateShare(t *testing.T) { }, { Action: "ADD", - DataObject: SharedDataObject{ + DataObject: &sharing.SharedDataObject{ Comment: "c", DataObjectType: "TABLE", Name: "b", @@ -321,26 +334,27 @@ func TestUpdateShare(t *testing.T) { Method: "GET", Resource: "/api/2.1/unity-catalog/shares/abc?include_shared_data=true", Response: ShareInfo{ - Name: "abc", - Owner: "admin", - Objects: []SharedDataObject{ - { - Name: "a", - DataObjectType: "TABLE", - Comment: "c", - SharedAs: "", - AddedAt: 0, - AddedBy: "", - }, - { - Name: "b", - DataObjectType: "TABLE", - Comment: "c", - SharedAs: "", - AddedAt: 0, - AddedBy: "", - }, - }, + sharing.ShareInfo{ + Name: "abc", + Owner: "admin", + Objects: []sharing.SharedDataObject{ + { + Name: "a", + DataObjectType: "TABLE", + Comment: "c", + SharedAs: "", + AddedAt: 0, + AddedBy: "", + }, + { + Name: "b", + DataObjectType: "TABLE", + Comment: "c", + SharedAs: "", + AddedAt: 0, + AddedBy: "", + }, + }}, }, }, }, @@ -375,17 +389,18 @@ func TestUpdateShareRollback(t *testing.T) { Method: "GET", Resource: "/api/2.1/unity-catalog/shares/abc?include_shared_data=true", Response: ShareInfo{ - Name: "abc", - Objects: []SharedDataObject{ - { - Name: "d", - DataObjectType: "TABLE", - Comment: "d", - SharedAs: "", - AddedAt: 0, - AddedBy: "", - }, - }, + sharing.ShareInfo{ + Name: "abc", + Objects: []sharing.SharedDataObject{ + { + Name: "d", + DataObjectType: "TABLE", + Comment: "d", + SharedAs: "", + AddedAt: 0, + AddedBy: "", + }, + }}, }, }, { @@ -398,11 +413,11 @@ func TestUpdateShareRollback(t *testing.T) { { Method: "PATCH", Resource: "/api/2.1/unity-catalog/shares/abc", - ExpectedRequest: ShareUpdates{ - Updates: []ShareDataChange{ + ExpectedRequest: sharing.UpdateShare{ + Updates: []sharing.SharedDataObjectUpdate{ { Action: "REMOVE", - DataObject: SharedDataObject{ + DataObject: &sharing.SharedDataObject{ Comment: "d", DataObjectType: "TABLE", Name: "d", @@ -410,7 +425,7 @@ func TestUpdateShareRollback(t *testing.T) { }, { Action: "ADD", - DataObject: SharedDataObject{ + DataObject: &sharing.SharedDataObject{ Comment: "c", DataObjectType: "TABLE", Name: "a", @@ -418,7 +433,7 @@ func TestUpdateShareRollback(t *testing.T) { }, { Action: "ADD", - DataObject: SharedDataObject{ + DataObject: &sharing.SharedDataObject{ Comment: "c", DataObjectType: "TABLE", Name: "b", @@ -443,26 +458,27 @@ func TestUpdateShareRollback(t *testing.T) { Method: "GET", Resource: "/api/2.1/unity-catalog/shares/abc?include_shared_data=true", Response: ShareInfo{ - Name: "abc", - Owner: "admin", - Objects: []SharedDataObject{ - { - Name: "a", - DataObjectType: "TABLE", - Comment: "c", - SharedAs: "", - AddedAt: 0, - AddedBy: "", - }, - { - Name: "b", - DataObjectType: "TABLE", - Comment: "c", - SharedAs: "", - AddedAt: 0, - AddedBy: "", - }, - }, + sharing.ShareInfo{ + Name: "abc", + Owner: "admin", + Objects: []sharing.SharedDataObject{ + { + Name: "a", + DataObjectType: "TABLE", + Comment: "c", + SharedAs: "", + AddedAt: 0, + AddedBy: "", + }, + { + Name: "b", + DataObjectType: "TABLE", + Comment: "c", + SharedAs: "", + AddedAt: 0, + AddedBy: "", + }, + }}, }, }, }, @@ -499,35 +515,38 @@ func TestUpdateShare_NoChanges(t *testing.T) { Method: "GET", Resource: "/api/2.1/unity-catalog/shares/abc?include_shared_data=true", Response: ShareInfo{ - Name: "abc", - Objects: []SharedDataObject{ - { - Name: "d", - DataObjectType: "TABLE", - Comment: "c", - SharedAs: "", - AddedAt: 0, - AddedBy: "", + sharing.ShareInfo{ + Name: "abc", + Objects: []sharing.SharedDataObject{ + { + Name: "d", + DataObjectType: "TABLE", + Comment: "c", + SharedAs: "", + AddedAt: 0, + AddedBy: "", + ForceSendFields: []string{"Name", "Comment", "DataObjectType"}, + }, }, - }, - }, + }}, }, { Method: "GET", Resource: "/api/2.1/unity-catalog/shares/abc?include_shared_data=true", Response: ShareInfo{ - Name: "abc", - Objects: []SharedDataObject{ - { - Name: "d", - DataObjectType: "TABLE", - Comment: "c", - SharedAs: "", - AddedAt: 0, - AddedBy: "", + sharing.ShareInfo{ + Name: "abc", + Objects: []sharing.SharedDataObject{ + { + Name: "d", + DataObjectType: "TABLE", + Comment: "c", + SharedAs: "", + AddedAt: 0, + AddedBy: "", + }, }, - }, - }, + }}, }, }, ID: "abc", @@ -555,7 +574,9 @@ func TestCreateShare_ThrowError(t *testing.T) { Method: "POST", Resource: "/api/2.1/unity-catalog/shares", ExpectedRequest: ShareInfo{ - Name: "a", + sharing.ShareInfo{ + Name: "a", + }, }, Response: common.APIErrorBody{ ErrorCode: "INVALID_REQUEST", @@ -591,20 +612,24 @@ func TestCreateShareButPatchFails(t *testing.T) { Method: "POST", Resource: "/api/2.1/unity-catalog/shares", ExpectedRequest: ShareInfo{ - Name: "a", + sharing.ShareInfo{ + Name: "a", + }, }, Response: ShareInfo{ - Name: "a", + sharing.ShareInfo{ + Name: "a", + }, }, }, { Method: "PATCH", Resource: "/api/2.1/unity-catalog/shares/a", - ExpectedRequest: ShareUpdates{ - Updates: []ShareDataChange{ + ExpectedRequest: sharing.UpdateShare{ + Updates: []sharing.SharedDataObjectUpdate{ { Action: "ADD", - DataObject: SharedDataObject{ + DataObject: &sharing.SharedDataObject{ Name: "main.a", DataObjectType: "TABLE", Comment: "c", @@ -612,7 +637,7 @@ func TestCreateShareButPatchFails(t *testing.T) { }, { Action: "ADD", - DataObject: SharedDataObject{ + DataObject: &sharing.SharedDataObject{ Name: "main.b", DataObjectType: "TABLE", Comment: "c", @@ -659,27 +684,28 @@ func TestUpdateShareComplexDiff(t *testing.T) { Method: "GET", Resource: "/api/2.1/unity-catalog/shares/abc?include_shared_data=true", Response: ShareInfo{ - Name: "abc", - Objects: []SharedDataObject{ - { - Name: "a", - DataObjectType: "TABLE", - Comment: "c", - SharedAs: "b", - AddedAt: 0, - AddedBy: "", - }, - }, + sharing.ShareInfo{ + Name: "abc", + Objects: []sharing.SharedDataObject{ + { + Name: "a", + DataObjectType: "TABLE", + Comment: "c", + SharedAs: "b", + AddedAt: 0, + AddedBy: "", + }, + }}, }, }, { Method: "PATCH", Resource: "/api/2.1/unity-catalog/shares/abc", - ExpectedRequest: ShareUpdates{ - Updates: []ShareDataChange{ + ExpectedRequest: sharing.UpdateShare{ + Updates: []sharing.SharedDataObjectUpdate{ { Action: "ADD", - DataObject: SharedDataObject{ + DataObject: &sharing.SharedDataObject{ Comment: "c", DataObjectType: "TABLE", Name: "b", @@ -692,25 +718,26 @@ func TestUpdateShareComplexDiff(t *testing.T) { Method: "GET", Resource: "/api/2.1/unity-catalog/shares/abc?include_shared_data=true", Response: ShareInfo{ - Name: "abc", - Objects: []SharedDataObject{ - { - Name: "a", - DataObjectType: "TABLE", - Comment: "c", - SharedAs: "", - AddedAt: 0, - AddedBy: "", - }, - { - Name: "b", - DataObjectType: "TABLE", - Comment: "c", - SharedAs: "", - AddedAt: 0, - AddedBy: "", - }, - }, + sharing.ShareInfo{ + Name: "abc", + Objects: []sharing.SharedDataObject{ + { + Name: "a", + DataObjectType: "TABLE", + Comment: "c", + SharedAs: "", + AddedAt: 0, + AddedBy: "", + }, + { + Name: "b", + DataObjectType: "TABLE", + Comment: "c", + SharedAs: "", + AddedAt: 0, + AddedBy: "", + }, + }}, }, }, }, From c1fa1c9ef090bdc0c5022e5b2736e442dfd30a7b Mon Sep 17 00:00:00 2001 From: Mikhail Kulikov Date: Tue, 3 Sep 2024 12:01:21 +0200 Subject: [PATCH 12/54] [Fix] Make subscriptions optional for SqlAlertTask (#3983) ## Changes Make subscriptions optional for SqlAlertTask since it is optional in our API. ## Tests - [x] `make test` run locally - [x] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [ ] using Go SDK --- docs/resources/job.md | 2 +- jobs/resource_job.go | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/docs/resources/job.md b/docs/resources/job.md index 3a7043f1f0..e8e3c9cdc2 100644 --- a/docs/resources/job.md +++ b/docs/resources/job.md @@ -231,7 +231,7 @@ One of the `query`, `dashboard` or `alert` needs to be provided. * `pause_subscriptions` - (Optional) flag that specifies if subscriptions are paused or not. * `alert` - (Optional) block consisting of following fields: * `alert_id` - (Required) (String) identifier of the Databricks SQL Alert. - * `subscriptions` - (Required) a list of subscription blocks consisting out of one of the required fields: `user_name` for user emails or `destination_id` - for Alert destination's identifier. + * `subscriptions` - (Optional) a list of subscription blocks consisting out of one of the required fields: `user_name` for user emails or `destination_id` - for Alert destination's identifier. * `pause_subscriptions` - (Optional) flag that specifies if subscriptions are paused or not. * `file` - (Optional) block consisting of single string fields: * `source` - (Optional) The source of the project. Possible values are `WORKSPACE` and `GIT`. diff --git a/jobs/resource_job.go b/jobs/resource_job.go index 4f00e3bc95..be2b982a79 100644 --- a/jobs/resource_job.go +++ b/jobs/resource_job.go @@ -83,7 +83,7 @@ type SqlDashboardTask struct { type SqlAlertTask struct { AlertID string `json:"alert_id"` - Subscriptions []SqlSubscription `json:"subscriptions"` + Subscriptions []SqlSubscription `json:"subscriptions,omitempty"` PauseSubscriptions bool `json:"pause_subscriptions,omitempty"` } @@ -624,9 +624,6 @@ func (JobSettingsResource) CustomizeSchema(s *common.CustomizableSchema) *common s.SchemaPath("task", "python_wheel_task", "package_name").SetOptional() s.SchemaPath("task", "for_each_task", "task", "python_wheel_task", "package_name").SetOptional() - s.SchemaPath("task", "sql_task", "alert", "subscriptions").SetRequired() - s.SchemaPath("task", "for_each_task", "task", "sql_task", "alert", "subscriptions").SetRequired() - s.SchemaPath("task", "new_cluster", "cluster_id").SetOptional() s.SchemaPath("task", "for_each_task", "task", "new_cluster", "cluster_id").SetOptional() From 20541ff5c20f9b8420170cfa7b4e239ea573fad3 Mon Sep 17 00:00:00 2001 From: Alex Ott Date: Tue, 3 Sep 2024 15:21:43 +0200 Subject: [PATCH 13/54] [Fix] Handle cluster deletion in `databricks_library` read (#3909) ## Changes We now don't return an error when reading a library that belongs to the cluster deleted outside of the Terraform. Resolves #3679 ## Tests - [x] `make test` run locally - [ ] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [ ] using Go SDK --- clusters/resource_library.go | 6 ++++++ clusters/resource_library_test.go | 22 ++++++++++++++++++++++ common/util.go | 18 ++++++++++++++++++ common/util_test.go | 15 +++++++++++++++ permissions/resource_permissions.go | 21 +++------------------ 5 files changed, 64 insertions(+), 18 deletions(-) diff --git a/clusters/resource_library.go b/clusters/resource_library.go index d3b2d0fcbc..86d2528444 100644 --- a/clusters/resource_library.go +++ b/clusters/resource_library.go @@ -3,6 +3,7 @@ package clusters import ( "context" "fmt" + "log" "strings" "github.com/databricks/databricks-sdk-go/apierr" @@ -79,6 +80,11 @@ func ResourceLibrary() common.Resource { IsRefresh: true, }, d.Timeout(schema.TimeoutRead)) if err != nil { + err = common.IgnoreNotFoundError(err) + if err == nil { + log.Printf("[WARN] %s is not found, ignoring it", clusterID) + d.SetId("") + } return err } for _, v := range cll.LibraryStatuses { diff --git a/clusters/resource_library_test.go b/clusters/resource_library_test.go index f156d9e9bb..c5849ddf10 100644 --- a/clusters/resource_library_test.go +++ b/clusters/resource_library_test.go @@ -3,6 +3,7 @@ package clusters import ( "testing" + "github.com/databricks/databricks-sdk-go/apierr" "github.com/databricks/databricks-sdk-go/service/compute" "github.com/databricks/terraform-provider-databricks/qa" ) @@ -103,3 +104,24 @@ func TestLibraryDelete(t *testing.T) { ID: "abc/whl:foo.whl", }.ApplyNoError(t) } + +func TestLibraryDeleteClusterNotFound(t *testing.T) { + qa.ResourceFixture{ + Resource: ResourceLibrary(), + Fixtures: []qa.HTTPFixture{ + { + Method: "GET", + Resource: "/api/2.1/clusters/get?cluster_id=abc", + ReuseRequest: true, + Response: apierr.APIError{ + ErrorCode: "NOT_FOUND", + Message: "Cluster does not exist", + }, + Status: 404, + }, + }, + Delete: true, + Removed: true, + ID: "abc/whl:foo.whl", + }.ApplyNoError(t) +} diff --git a/common/util.go b/common/util.go index 62b2ab56b2..293af66727 100644 --- a/common/util.go +++ b/common/util.go @@ -4,6 +4,7 @@ import ( "bufio" "context" "crypto/md5" + "errors" "fmt" "io" "log" @@ -12,6 +13,8 @@ import ( "strconv" "strings" + "github.com/databricks/databricks-sdk-go/apierr" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -87,3 +90,18 @@ func ReadSerializedJsonContent(jsonStr, filePath string) (serJSON string, md5Has md5Hash = CalculateMd5Hash(content) return string(content), md5Hash, nil } + +// Suppress the error if it is 404 +func IgnoreNotFoundError(err error) error { + var apiErr *apierr.APIError + if !errors.As(err, &apiErr) { + return err + } + if apiErr.StatusCode == 404 { + return nil + } + if strings.Contains(apiErr.Message, "does not exist") { + return nil + } + return err +} diff --git a/common/util_test.go b/common/util_test.go index 01e6e17966..b587250029 100644 --- a/common/util_test.go +++ b/common/util_test.go @@ -8,6 +8,7 @@ import ( "os" "testing" + "github.com/databricks/databricks-sdk-go/apierr" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/stretchr/testify/assert" ) @@ -67,3 +68,17 @@ func TestReadSerializedJsonContent(t *testing.T) { assert.Equal(t, fmt.Sprintf("%x", md5.Sum([]byte("hello"))), md5Hash) assert.NoError(t, err) } + +func TestIgnoreNotFoundError(t *testing.T) { + err := IgnoreNotFoundError(nil) + assert.NoError(t, err) + + err = IgnoreNotFoundError(fmt.Errorf("error")) + assert.EqualError(t, err, "error") + + err = IgnoreNotFoundError(apierr.NotFound("error")) + assert.NoError(t, err) + + err = IgnoreNotFoundError(apierr.ReadError(403, fmt.Errorf("cluster xyz does not exist"))) + assert.NoError(t, err) +} diff --git a/permissions/resource_permissions.go b/permissions/resource_permissions.go index 897a8f2d57..fb0b24eebf 100644 --- a/permissions/resource_permissions.go +++ b/permissions/resource_permissions.go @@ -137,21 +137,6 @@ func isOwnershipWorkaroundNecessary(objectID string) bool { return strings.HasPrefix(objectID, "/jobs") || strings.HasPrefix(objectID, "/pipelines") || strings.HasPrefix(objectID, "/sql/warehouses") } -// Suppress the error if it is 404 -func ignoreNotFound(err error) error { - var apiErr *apierr.APIError - if !errors.As(err, &apiErr) { - return err - } - if apiErr.StatusCode == 404 { - return nil - } - if strings.Contains(apiErr.Message, "does not exist.") { - return nil - } - return err -} - func (a PermissionsAPI) getObjectCreator(objectID string) (string, error) { w, err := a.client.WorkspaceClient() if err != nil { @@ -164,19 +149,19 @@ func (a PermissionsAPI) getObjectCreator(objectID string) (string, error) { } job, err := w.Jobs.GetByJobId(a.context, jobId) if err != nil { - return "", ignoreNotFound(err) + return "", common.IgnoreNotFoundError(err) } return job.CreatorUserName, nil } else if strings.HasPrefix(objectID, "/pipelines") { pipeline, err := w.Pipelines.GetByPipelineId(a.context, strings.ReplaceAll(objectID, "/pipelines/", "")) if err != nil { - return "", ignoreNotFound(err) + return "", common.IgnoreNotFoundError(err) } return pipeline.CreatorUserName, nil } else if strings.HasPrefix(objectID, "/sql/warehouses") { warehouse, err := w.Warehouses.GetById(a.context, strings.ReplaceAll(objectID, "/sql/warehouses/", "")) if err != nil { - return "", ignoreNotFound(err) + return "", common.IgnoreNotFoundError(err) } return warehouse.CreatorName, nil } From fdf541bafb1ffd3269e280fa93f673c739935a1f Mon Sep 17 00:00:00 2001 From: Alex Ott Date: Tue, 3 Sep 2024 16:46:39 +0200 Subject: [PATCH 14/54] [Doc] Update resources diagram to include newer resources (#3962) ## Changes ## Tests - [ ] `make test` run locally - [x] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [ ] using Go SDK --- docs/resources.png | Bin 555140 -> 605893 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/resources.png b/docs/resources.png index 925a0fa1dc6642f008cfac648e181b0695c57ce3..6609b2ef9e69d3ac781a701b54422d515164bd24 100644 GIT binary patch literal 605893 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

Ii@VK#1#UF2z_~Db%uTQI&Q*f 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

`}qdqXdJ!b%+)m?ll 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
W^J$j`+i69D(&u6*I$ka zbsY!{O&dBlbv?cUrQ{823;jom26_R!K13AsTu!W?z4>mjgn;!P8RK2Z3!4f7xmtf1 z)j?6*JlfBcGBf+&WKx`_Dzl;2#i@1~jGS1>oP{lAGy(Yg840T!$YC!B*J7to@z8TL z9s#Xqg7Q5e+YO|&s`hrck2P4kb&grPW~je==O%nXU+>!-VtE~E1}%BEfQtW!HLkTc?c<0L`gK2hE!2AFI z+Wa8*B@ub;+S;1UQYe3>QlvkSH7Y?gjS|5%fxtQ^q!szcf!;7sa*?ST^h~$YMJcY= zGGXA^z~zpa_)T2V*6(8miwliok(UCa8Da5DkNV&G&mJeHcy?6zqY>!sG6VJUw4s=S1i8;W8 zFk}HXFv7mId{4}#QVG>p5=c@(&pA9Y0i?Ob^(9!70{66S@|~j6@21!w;qKG?6$3w^ zF$g7J^Z+EPXiN_pj8KNl$aqgA`k4xET8WeAz>%XUaXhe3=O(vk;B8X=3Xs9l1FYq% z6-`^(wx(rK)ETR>I*OL%nDZu}`ha*BXqbx za!97z(7jP~JM!j)-&?ccRztb40;hycZbLd=?{J(0J zL?B}(mVrplhL539|!481pNbZ>i{sf z26`IueSbCd{|Jo!D-9YB`o@9Xo3N zUL;opNGkHw=3OM{V+Ls~zu%8tDUdrLAM6Zvq#DMV`V$})4%$kA zD++XA6Dos?W8Hc<{?^ySmT1C5?|7+wdqFzb~I-4%q5PGTf3kH{6`estToqMV~%m(_iyq9SluFE z0Sr5Ru&n-hLx4!QUqFwBOy!>YKAKX57?Ymx5GJQMKmzS*Z+~d_4(cv#pOpOY9sdx-sAGn)JD5S3B3EXVAJGI0WnC4Tm99V zQQjFJ*q<<$`g6(lj8y&)C#7vcG#hpOY_0CV!GnGD%M(NSW{%6{-VB$(laGeRk+L?7 zdN9A5B9iAHh)v(0O~MHskSd7(gH7@NuhI>e8Nnx}!6eub>^8IJf<9x2dN!Kavajf3 z7%~$Ps!@Ym{}U?&(x3dC|TNN#iUtE&Ji+<5Q0xw0~cJ9pk z%|AA6%EdI2TTEViNU-cGs!{IyeQ?EwF!0~Xe_zW)i;oE#P&j?K6{t!zcD44cu%MR~ z)m#u>@0CezrmFuYgO3c${M@U<^xJx7@vXVt-K?+;OvKp!6DHChvy4g!Hs3roU&)vu z!@{H~qKH<#2xe;+a*YmNQ~CV0xvh`bD~rY!To1FNPnC#;D#cLvll3}qelS^@`Me(F z>iO&a{3lT2vM#kJY9zE6M?~s`-G&@mv4U6B5~p1)wk(;tuR>we6`In4|7E`__&N~~ zfp+{W%p`6H93}bge=0b;Ucv9r2>vrHy?=sUMaw88{Z@(4 zY^(FHR*c(kp1-dloHDqG!&=hRu}UB=A6_r+#WxCWEonq##LuCV${1H_GkSe|rOm{M zfpjv=+WY{6IbnrgIfQjy_#!_$iRRE+_Is0d-hHepM?Q z`e9SV53TEXE_!Am5yA^vRaX)J!O>JdoQ0CCow18GxP|m8s=g$wuzHdF4s5h{@DiSt z{93zyn8mU;-`5Tbgx~fdrw05?o3H-WN;aEsH$Ll!9bV(ExsXm%nQ;1S_N!k(h*U|9 z454}0w0SVIDt#Y)SYHKte82z6i48CjARV?o3jFHt2lfYOg)++e&mQ&>IF_Jx_5UHp zoYj>;iIwv|-{^zu11F_dC7d+@69pn7i9kY2#tVXA(Es`eZ`Bb6WVpMft*IOnOg=mWe=^W5n%+wnK|pgzrV(QyPa^^Ax&Qh1 zns*8h7_^Gqg|TRlaXuG*5cvhp{(J{5%2OZ$ zmQqBMAx9RMT>|XDzdGlq^u)|y5I7K!_VU*4?(D(!Xm$dtA~iVHfQ^X0kJ`Ix+ga!a z5+_MV(`U?0E^@4FP4Sl`s5@@_ck2X6iKx*APk9~ofXp2M0>tQ0D#&==`yx>iH;&vY z!Hb%CJAHCIcTLIf(PG2webh?p)KwZba1}OYQLl-yM`L?`OUBYb9Ld-YObos+{JEt; zTbN4iTB?K-{*-@)t@dYrH{%zGT-&OyikmzLD3S<(SWO&w$rvGv+bal{OT*=ESpPJ1#0zAnE#O zKw9{U3#9N8RDSs_laE#nSF-Np8Z9zNyRVEV@)(d>I6bXZPEDg!oT&#ZYWne(VERW@ z5hT`=1XGNTh?8R9y(n5%dI>DM4&gys@K*W=lY=3>-n$=60b#SLiMCRx#4~y`*MjAI z`VBtdNCw}X{b1(;J{H?C<)pMUhyROhOLP#G+U)EP$o>-+8pqp)?;l{sq|y&$+dfTe znd{F@$cTr6gFw^qTwsQ&tI1Ll`Sovkoy!Kz!V*m{gtl&lXB*wA>V1- zKHbyqbo~LSuOjWIz_V{EF$nkUGm~i|Eb#Z~s@-w=a5Q%DfGlyK^A~6pAUb+Rbo4UR zGp{TWBg*}rp5(0y^RN>tNbJO>)9ic`8=Jl?ZdA8sGOfe$9Y|%4<+!EjKvEVFi#yZ5 z)24sw&nSF*;B$ch$1@D=$Fuk!>?fJcr3mzknS6uVbE%{Xl`lE0shZRfu)pgs6+g)I3M=!)2l2QqU%LHI2L(z4(RxCKR{uhj2db*H?1Es-Uv8K@MkB`}Sz!@ZxsT zO-Wh+yEtXmy{n)FKPtH`C^R;$`S<>+-?#@1`eOjDI=y#}MP&3E45SG~2(&b#DLHPE z_D>hew7+M)e0(2GUj*1o42j+a^4}(5eyuiL@86Qh@EyNqWJjkgRzdqQHht*8&zF`M zj|O~Jfq>1ZH&bN{;DJS*!D!*#sNq`qbPSU!v=%z=&;U@5!vf%X_E#MZGRZX>MhoNt zL+|sIR`7Joa~lt-UnjTsI9%-Y^A=`PWiWtYw^Na1+48BFPF+(IBc@L*n9vU$BF9FA zUV-Tol?qRb#n+e`=-5l~DG+SK%@u>y5cN62<>|0q;5GtOl6tAzi$&~MxE%y3u*Wm2 z*XV4I=AeYGo^6joUFJ-lun2G-MpeI%2*CW8N;#g+?f`ikt3HR+#uVdfZo5cS8U@U_ zK~o(}pG6c-L^>;3`89yZ)%Bnr$#k;BfJ{cDs^wG^UcC@ZEmSmmjT`h)q1AzdKFhAA z%D399vQou*Zi#P9(V;Zbc?AU`a&j2oXr7BkF!giWN*HGW2o9Vks!CWtz#;$}y7#Ij z=9~l%&eHkUKA2==_?(|6rA_azRl(!-$*9V!X8$sLEx=`2kknEM_nF(pR171v(M)Yt zM3!+WGENJ*We~1>?7HT@>iFi278bqv8y^_x&gWi@?2fo(y8nelchz2lKwwCOc*$}< z7u9n1&Z;R|hdpY-#rYZA2I{$_bhH%!@saWqi;73HfgF94Oent;vVMmMf%?ccGsd<9 z#5g3jZi9?$*}$^(*w?#{Uc22hc<3vo8q|zEx&ja$-P=IL`R;%C7vn#`JcXeBuB{XX z0>Tt=K2*RLy34QKWk(;aey9Jpg$SP2gjynS=7h%c7q+f&O*Ol}i6(bu+eQAH3#C{t4Kfy_3h3BuD$OA$T{K4q6u7=MC z^mKo6cz}0SG@d0ya0fPM?7(YSr9J4JY(e`#Fic!kBRuBEkj`Gh2!9DhEFbbsvQ?A) z%e8>j@s<#DwTI3ppw)l^m6<}oj4r_c5kueyJTX-Z#f}RwCmi4Gmi~Y?o>r;wp$W48 z``j;8^5TV9{Z*4eKY@~xk`TT)I!Tk}f?zJs0Bqusx4Hi4>E#iCFpo)DRLU!>_3z~b)GZtl=4x~6k zNR8x`jURoy>2Jvm9$hpHb&mcwy^!1KNT*ai5WGWyql^cIR^3jStkdi@_yus0AB$Cx zebN`6nsZj%-*TzMYdSpri)zHmAfP4-a?x*TCWBi4LH;Qn6}(B|5&)Y~!t>i{rn90m zw!n?aEr#+)`&XgedjOV4SGIJ_ipuo{AhQ`68w&$!=nF>1<6=v9+57t!$gsei1s3^x zMMYR)Y--THRDea0b_UH0Tn`bh4AW^)m| z0m=j3p(r0~3$x?_{kH;7D@OUg`gwX|QJmD2bj3vQPkh1Wm{X zR7=s(6rn?wg_y2YXL0~AGcgERpi$S?*Vow@&p*0$i=sgRK248SZDyWD_UR5lqg}SL zYy3Sh@OI1Y4Zy7;`#^yGvRP}Wi8uh%0N_8INE3hG1$LhI3JPBHjgEjink$C(bpbcG ztn`7B?1ld-w(^sGtj^CSR5Pl;Atny&Y7rEIn1P+%0L*JPTZ17R$Fx1RcnNrvP%ogl zIrE$a7fZudW{_BLMFj^$2>8UH)Qgxt{NtPLvFX<5DAHewBl#h#{8&DfJ+& zGM)a>&5|z`8*nAR`(7(GGe zTd$;>#QX~c@;&Vq>}Yj$jo&psMWcHA9TCbjfcyiaGzFbINbDclb^cC!ABwDrdPfe^l*-bJ4^Vq`R!=ob@0F+DeH;j2EP;bm zJ)BE}pdk@}STwrdjR9Z|Nj}05`RR0WC=eS^X5AVEy!Y(v8iznQ=f|&rTLXct#nEw3 z^5qN$9%MQLN@3vK95M(YKRR3t6`DR4pg_~@VcObc4p8zSwpsslb+I25Cits7w5D{K zy|6dk{1H%Jp52)WJ=~>M+0^Zlri2J zitTQsz4t+&%GUNdkN}qLG~-vVWBU9^EP^bR1NCu@7=YiL7|7_!|B-Ux_;_&LNiM)Z zko8y*Y*xAAl*&menxh4uX7nax=i)q*fGDuESb)L= z`2E}R-e)0d_CtVKOrb&?{Mf)Me>|b8Z7;(azz3t*7cr*a(U0M08Z(v}bSO^8sf`|lQ zu7v`-^FRDh0IpzY7!lZytoc>$yFs>2|1)_gB@`m%x%Ua6qwMPsz-$?({4L1n0Tkcu zYk)oEc6@((Q}Y&tyR-vHB3Pq<^MSpALwba?JlSy;wbljrqXR1&r9-o?MWj z0vIz!569+SlW_Y-Uw51m&vZ?g2IC*_kCRVx1Q~*nk_kX+H542=&Mvb1FQm62frfbi z>kbhl=4@!<<#q}l|W&CFK15xmbmt1x=09IhsWN$5oE84Z2xz7j*Ur1-c zB7=jJJsgPJqeB3>3pRjJwXONU9;|Z&=zs6wcNhcEsF3%I+vge1P`=`;PvZ2cs9?}y zG#c0rI3%xhpD9N(bpXoX+XOZkfFJCh)b_+EoeTxwI}vPn`xI3zX9NgP@}L1cF+=d@ zi2~(;mDc-<*=L_={m#gsLoy!^La;2L!v+P=24i`!j6{3n+3H5)`mng4+I5p7R zYB>U-))~8r57FHakc9y9R7=)WKqUf!oI9ELjptEIPJwp~U~TPaom+tS zTKuz&Bhmq0Dg!CJwf*{`4=dd7c>rp1k&V-J#a>kH;q6| z1*v)-0!T?md=&37IxT7oZ{HXWCX=gs0V<$|)3SeFe!eh>w*haU(;-1YJtJWmWTOSDD+gS@m3d_PyY|fh8O@Q zI0*_9b#P>quvzQTjTavoKroPyUb#cTA05E=OD+|_>WyjjI&PQ+#Ueb&y}v3K$9cjG zSr=(_+@;I85taQg?!F#M2M(mrlEdYc0*aRdECncMNmC`PjPId02tIW9jj^L((SbY^ z_AtD!gr_pf;^B0-1Vy^G(wmRp!Wr@V2Kpnh|UU4L3Itwnh#6l12v#I5eD=(9a?7eZia& zg74BSK+V29CNJ0xikM})H|3_2EYO0~RsLFXJJX$pB-|ElwuCyQO8tnMT zcl$3s1oV_LdU_=E^=Y&_G})GX=d6kzNkBRa1Q`*k*YEJ79k!bB!#ezLNhz)nN13vK z`nHw1LQsCZK9o1YlHZIKP>V;3T~NwC4RIfxBUIJrzxl(o3t!{m=FoM@xp=PK9f73kVE_gvTkSsXNK~Fl~U41o2AmEv6#|G$4Q~ z93E0fe>~U+=~dWfvNqu5CR|diNDc>uXso|tmIK=y09->EY04|~->37V{lJ>6(|*(j zp0;UVNJsS0*rWk^|-my>Y-!?kg&J8P(Pg7*YY;f=NcYW+>S7ks|Umf;$n2yUgk(np(=jO?sE%n8~z3H#2r zSb>ww4hNzVB&*7h!wrG{6Zsb|(EF2*oWLr)cuBO$Kf3+u2JO(BTaQ-b@KIwv7wnBh z8+Uxv?47{94eSoZbPf6hwj|^_)8i`nQ%fyc z%jo3N^&J)jl3~OEnqR85PZP0#qjV*9cllw9-Ch7f>)hpNr}u+r0(>V_fr!ytc#5-f zcPV2}lCkNRnKQpIhi(4I+e3^7I=(xken(lXKGw%CO-9A8>UEm#jP2cbJyU|5Snd~| zfo7fZWZdn4f0`=ec1!ENgMuvhW>B z)To}Bxit1-qlcEhzhtH{vOH*zLrzz*1(+JD6h7SJWcPE=_KS`;V8#AL7Sm35-g~lk zH0qiD(Dyw+{*YT331^Oi0YT*BX$OlJN&p8X1E7F;0o;p_MNy#Zs``mA>JxQJ5zUTIQ>fiK-U+QikhiC45I$l4t1o#Kgy>GI> zQU!10XIlk^ zTy|pr7N`JG2=2B*p$7k)>XqZT7DUT!(_ueNv&(%~lm?X0i7u$~ zdLr~3d;@l#U`To)`9UN(T$-bIgWM*t^1cN!UY`;~V2y?2OM8TgJKWznMR318-Sq8e zf`ytY9*{w`>izhW*92EQNW)W1jv5(doJ@F^q<8bQy5WTWNt2u-}M3l;o#s{I=z0Q zJhPoo8~_l|KYw~n1K#=P_U|tZ#|fyRH4M*YvM(r{%Ti)3W+3ocRdd6vEo#M9%YY3( zSQdv1MX}-mr1tw+NdP^;0Ly%0|5!YRmzEcv>_Y1>1h857OFE}H^inewaxe$uP{xV{ z!-}q!&eN}ZYxDQtL%cxk3%);qrD#;tGH>Dq1YWb*RGkDjH8z7iVW##wJKxUDAYp6` zD`0=lUhd}}wu9P0!E>UhBu2DjFn*YQFWhKCFk0H){?&^YFNVQS28J-u`UnRF-|K`I z^q#V^v*CRx?PR#O4w{*yaU;k+6f8ziEV_Sw&!N`p!OzlsrU+CjqKW@=X!(oT-U^9- zkEI3T7{1{0B+&O#GaU0p{tZh50YbPv|3(S|0|Jn$2W^&YJqEZ$0l;%#M}?b5!uU6geX!i_=n~-lbah|Y*osxS4BgyJ| zx6Dd!tA)40gabT3vx$#zo{wbu0WxVR6Cwn@pcR(OK`U*8v8f^eh(ISo2*7FoT`*e4 zFP!90*Bq0ccY=^u8Ok_bK_3Y=YVOTVz#xKp)qye;#IT4dMX)j59VSFm>#O=UJZ7L$ zET2Bjngnp+SL@M z4jpQMGKX8M6%kw#C%`8G;uiFdLS4U^OrT!^RWTui^8Y$$*}ba)$wQiSI@~Gm+>W~m zKQ`DgB%HWV0v2kEj@u8K;0R?@C@}mF`Jif=>Wov6%d5W3AMl9QgPB1!BtV~Y1jwv3 zXe`aP>iqN9gtgDL{HlK)c{Z2IH3rVYNee}<;UjN26e49iH|Yag!}YB9ZXk=8Y}bM75NmR%*)YR0^L|S68RFDAUPFcf(u&75vqZFsoJ_PrXYu-qOD< zb2cJp6oy|VyTzT=UZw(U z&J!~D%hC|xctvVH1=lkE3ly0Sc*6mqn@a}?vtCDi- zb?$?xt@(7HKo$CimIVlOmEsW$P!<$(PS6DbFyw)g6ieWe1nPX)9xw#YL385l0a)ZF zi<5XsRMoWIMq%H9f)U7fb>DJHf@fG5?E+RZtFA)O|j%@HtF zt>A<$N&faLeUK8{B?Kb~8iFjz$R6lPU0WNgaUK)2%_COF#lpZ*fA~@;xa@8$7@0~YA-#EjAHqwW9b2gSf7G1UJbzx&SW?p8u)xI9 zAS+x%jr;=j7Xv+l43<& zqd*{mLK9|IQr0_!kzvWNeq+8xfKa@xm30Cc|)&7u*4HC!(VsV&=;=~?&# zz8cRDX*~CfdguXpX`m(XK1M$ShbG9lQbgcgoj{diZyC4wA=fA-J5L}#0j^q$zRC`x zH~uT{_Oq;SWsjExSELhGht9sVpSv`iE*N zJ#HxkE3|Y2EaAviGDll4bgf+au^Qr7J-#)p?(fO>&&SJjO2_Tt!UnGU~a!{#oXF3bnxsBE{Rs#*Gq3(3vJsW1P2N!d2lf6>h8|S$beC= zwGh|PAO+KB(A=X!775(lJ~#QUm^Bh~byZ`&f-mkpwvFBZ>5thB4QD!TJDD?OwtijP zcXYb9*iF7mCnvgsG@CxIl6AZ;Sb<6yOkpPaJ6d)k+iydL2>iy^R2C+AcTsQkO8rCK z{o5p6)jOJVlw)#%X1hXtyr+M=NSctJ$L`ZcK}2U_NsaroO`Pl8;R z7^-Eu#ch{n)Y_s+&MHsR)4maM8eY_DZ`(XU6WsJ%^tKq~L_Q9d`dH1dReke=0)lTD zczlh=>31d8^=Qiv$s4LJU|W&r#96`9bv~$0Pk_VY;p45Xrg7&SQr`cKwsdoc=g_21 zL1H;Q5+qj!@hU8BX}BcWriO}UgF-_)oi|gELc2$|7coSTwHtU&JE5ZwprqKgWnf^~ zr~3pyYQ%ZxsvMnXx3XrepX^FLn4Awc>LdwbXR}MM@t@jk6X={&L`C40VC~OSp%60- zR9HP#=RLtqu)IZFh*@lRw_=u6GrGBvAC~(#qx(cOjk>etLIq-ifZ(|sbfaqPs!=V( z3< zmd8qmHM5$>T#Dko^Vjo8r=NWMw}`Rieri)1zCa(1u~J^xl8 z^t}?fr(4h$I}LerM%l`}yxiPBTxBP%i7ljQ+c!cM3C z-@~a~w0SZTW4(_UiL(KQlZ$(Z6sL+sE{PCxrtDVuUb-g9Um+TmHAyz|!X$#*jc*fFT8@%giEm$55qhQX3i9 zr_JzC@#<$?OXjVz8!^MuKBUWx<)s$P+SvsSq2rE=!reEEj>3D&utCH?Zg{$ewR#r( z`gB!$sD9_rJmQmUze|6J+C`~yXuMF13yF#4U7CZ>QAedMiP?TKTFM~Rc035A6oVVe zja+Ixw`jwifvT;oGWylVix*13?*IJNtLiZm0$(I7@?rPgw=OVrzsiH8d?Y$~LHaQY zBN${r6=aS?x~s*Eftyk=T@1B;cF9)mMu%9*B#-gcNyA^5{J;ZR*ZRois>yr90r5&m zXiqi0IpHyq9K!5ot2-@PJ>r&-C}4@fKai+$(&PhmT1j=dBlk4L$n^1)0~Nu zh?=T#i!k99aD_cN-aq0onc}#puI;evE^Ll~rj~9qgI5M<++)tspp9~=(S9@<0v^eM-ew}-N%k`Npkv-~G2C&{J>HRCclmDRsg&s8I+?`yFf#62)jN#y$2xcc z$ya=Ve-LP&5V2~vs0G+KFZUzTuUz}Vg)zE0segUTn(~tD zhK2598IR!OYl1@8Ark0=gZ}bBk6AQ!NAyVL;J|*s{e3q$WrCl!(e3g z>FB&ngr~!ABky2*XwN1MpbK!B;RZi-cWPn=&biGCBTJzs#zGds_1eXA!^NqG^jr2leNqqkzZo(*>$Zi%BY!b`G za~Rq&7%Ne>RG2)qa@`1>1A*y7TBPG49d2WYPKB85>h8!hBk|?-D{)2MD|yPj;Us@> zBYAj?lJ@yoiSV#(mok&?@t2F~TKdU7Jf39w@|&fCB8fxpjAN>8)HOCn@v_pPQt32F6R9d~&*!)pPd z#3WuYye;ilgWuokUjmolvkhh;Y-W;G^Gsq64`%oKS&M;`-?B>{7vfK_z-0uNBXdOE zve_R9R`t%dMw&#aX!PxDHv$cyCw(CQ=OC*_FaO8{*Px6XY=&3y^7zM-q2;eghbz#d zQk23lGWM#Z|38-xQ+ilOH!f#(*SMVkL-prI?!qR5pW0?#2e&Pb zc9v#Y^A>Vvj1Xs#IZH=wKp^;%7;fZ-gnziIZryg*Lee)s3^q(VY|?I>V{SB^x7az% z-IzQg=!rDWjvy;4gso8O1#U`9o{oOA4TY`+=sh*Q+lOOYxFFUvS5{C$~>!a(?CYADSa3}w>CRa5Qj|4h6>3^~{ntcIh7 zehBbMI+6^>B#-7@xO7nVxq-5{ZrFf%N7+*yl+43g{n%+kgine^{<8^2(@-%phdUCP z8;c=ZcS3}i!&%bqOGX4pX0V42+LU(~U7E<+i?oc+oRg1uOrLo!(!w!*SV+33!x2&( z(stk@c?TsLag4&;YyKOrL% zA$X9blA%p9mdX3)|9)hVOaxG#YW&n??;*=T zpkC)m(4yo177yER^^x6sI=6%p7rdEq4ag49Cc{G*+0e~5LeczEV4+(YW}8 zgsWY_ctDWbJfi~ixCbq_7EQMYjZKb>Ov!2dDB*t~493)l3R1BdNhtr^c&e{^aq1S{ zl*mn;lr-7@-2xCFlv!}U@`5q;3*_&CElNcia>xb4aztZMgw6C>G zFYx2ZJAYQ$It7jyqF0i83m86~MC&`)SVOM2;X2&j!p&*%=_XZ-hKXy$wBx<@vwJHw zpo2n?T45f==!irnpZ47Co6b$NVEM{axt_3cx=a6mPdhN-5O#sH;13%U2-roU&WGkv zy4Gq7z&j^pC!2~gP7X;lfe}+tylngNzA$Nf!0RA9@aucA4jzRj;YBK7X%UO>JG)?yD9I$;vR_D+QJY8Gjx zm%sUFDMRhAXQFxOm z1cJPQ-!)K&<)t>$A{q@dGh&-g=8R(ZJ#=a2{>@wRCx2a(XXonWltvs!P zL!UZv$>D8Lv%gkmkiA0syz;T`q8Uzpm&_N5kA@P@M3UGkX1>O^ZRYvA*-)%iurAyFad;!y5X>baGpK93 zX8T7(FG#ial?i55etnUg-wz`_g=9@CI{5&P6%2?PuGpQPi)rZc%!8p3`Z3#}D-2}# z>^yC%sj@Rh0BvSGH2rr1R$3O~!83%YNOuIw({7K|rYBJn8hI?dDF zC~T-y4+1WyRE^xZa-tGo_P6SX5wi%%n)Ha`LH1L{?inZTVbDx{}B?Zf5q8P=ZD&1S*NhkLHKtw@8VT3g2tj`5lF z^eIft19d~nN1%BOwusz5cR7x4y~~l@y^w6_YxOQI!9Ay1SPamgv`Cjj3PM-BmynQlkva(kpfz{-P z6{xLEL@L4QwLAP`u_IjEa0C<(gSMkAD`j_Fiw>kZt7I}$31_fxWA$*p!iNVqBC`#u z!)Si#Z}oi$?K3wL>tg-{H_N9aEo_vanDewo6fae^ssK{{LL9->oe#~QLeFERp zTz^(!wrUN(aX5uNR7(_$G9lK7ty{a={15endGHqN49YZFh)+ z!8#QM-E)|%-!fvR}KoO9j|a8F3zA$o%t-quvzKMHRwTlb39pY zpgu&xOMrB`Y*NwgdUG3hx)X4h?tGR;_;6alduK}*UdLwi(BS$I)E9%}IPWSvd%;?o zR)!BsXvE)=y9RD@_IuW2@k8yC(k)_h;S@EEk6_t&nck)~RzJ=!pZ~gA5_|;4njzLQ z5DQ!)xoccKLtZ-TxsS2G@wjQSRJh;dSRuOGvPvdw7Yv#X!x^I1?FfVlU>Gd6-a5t7 z4e@;mmPDhS?~HUoly3~ZAF^>w4$k-^?9;%SDyHM!IfY!6CacN(V8U_50O&GkzS${E z;CFp35lQ}=7hmLtAJjb>SA3XPeD9EZ;1@EmMLODmnzVHC87=L}FO$Gut&TiL$5<>y zP1bDSMa1aPn6i5Xp1nrwJ%(At&7MbpItQY+Xxb)~MX&V){`uj4CL$Sk5Kw@M44F!~dC10azo@pdFjf~9)eDon{}l?|IdnHf zO+L5P6;6xW5UAU7c(vMyO5On_NrA}JMn3O<4Jv*f zf?Du_tPWjkCGT?(VxAC-!tQ7ZP$=$%S)>U*gfN9Pqh8oMwz=LQIkceBG5Yz9KzC~H zA2S0bv`47HPt7kD*)}hS!Fpx8PmNNk!WKsfC1efgTowW*iI&F)*D13a3-i@K>Hs5L zr>v}82kMC9gT})E{Z?wZ)tg323?4%E50+@#+=eXVSf@KaK_(=MTAMwoGUx9;nUH{L z4yP*(9Xr8l*&e3mnb#@)uu^DV>k`YBcS5_6M!^k5x=I1^+iYa47f7jm>Ds-lQaPo!8Sb!$ufp zJeI$8U-eNNeriO)e0Yrp7F4z_Ui#3dTouycAajuLKBNkHc2r*-Xdp*|R&_Be;;JZ@-`)B&`}fE`5>Oj&FO;n}IXIYHP2znZGHbOqJN;7C}bwc)cnAWecS@z;(&? zPsfLZp$LQcL5jY%jT+-#*`oOn+y0oMiV%l0jk+7kUKP;i}G^j%m44JM|8Rai~J{}c~OCan1GPV@eJIj?Sx0z z#yliM!vYjSp)*aZ$sm(Lj826sCcSi=bCaBqwh-*EiusvC7xl{BXueN^q?HO&oit5y zLVH$Y?Vue@d1w!6f5EKA`Sgp~LeuyAB1q%=jpQtfaB(Lqpe4Xk*K8-F7x( z2?9I`UYUqz(5CB(Dzw!~Wu;pi(OcvuW$F)dW6Eouy7#(ZBi$b@m zyUHQTgrXwzpwFcuV-fM-IJ8kTf$dkP8}!|pqRX#bxR~+H3aH=tG5H+tszymhh2XXZ+L?v$Ss@f=_88dW zga8J0NZH9p3%hjqg<%KgRH}_b<-R`S?fuZFiL4j4pd$DQ4j$#^vo)10@hK_4d6h(N zl>Xb5>O4{7j6kS*$K9K*2?ey zDFWUr6vhhR92w-6=BJ>-Rp5memWT|5-Ks^Syj3AG6vSlU39K$RikHx5euMA&WRE0H zv@E+~)&9@$Oz@9J^Qk6ff1{fVOY>B$-quTg9#5BO{qd*WS_qqee$?-Q8F*~$5?~f_ zJM0nZf5P1U2!^Qu@%ZlJ1tV_4!zPwV=7%8h&y7(r80032ERcQ~Iuox2{scRQzRz7jI8CCo+49c+Px+?#hkC1`!NEJ|X!+EI zQuV<5-ZyC*j+BaD2R~6q4DXQb%{nN}S*CpgqM4!P+(UrP)#L{$-br>jw+T$QMBpa*6g zQ?vx?|LRO{eJ_VI(mxv_t_R=T6}QtFZFfr*Gsachz-t%m?xJiz%DPZAH>kM-P*0b6&Zy3K`YF|3@{(mW!pBtiZbrJfA-OWqeSuf5KdL=en8{xl!7Fh; zZ2MbGn5G?gsyZ1wO{%dFb9Uz8BbSe?DfhT{ky5-A?CI|91&K?PMIg|Atz7u9ywl@F z)h#bZ8wku<#yn2Jna?1?gX|JPf)ZEdu7IVDh{uM;ok~`UBEP7}uYcXAbJ=UeNGZ)s z)0~Y(xfp`uM75CSv}~-zsO6-2*8*_bUMvK|SQhz8FzHnwLbXn;>?W`HLN?9-5ReeT zcp30E-9AT(d7t9PAfuaFFs^VTjFYFwL1}=4GSM{X#GH9!f3nqzYa|!hu|=Tmz?D<( zrBm)k_g-3*v|KXQ_UhGAKvk5&Dz?`MkQ>}~VqZpC$gm4u&AQd$pb;YW5a7&=aO9>^ zR#OW(JF~lTb8CrGG>ItdWhY#~0DGhmsSOKgh>m>u#QvW731dPLb_^Y?k?}bsZ=ZY4 zbC8+O8+i*uWX9VL;r9LIVv{QvdcU3Wb&! z2CyuIM+%yye*S!i{P+0ACuW+P*mW`;qd;1H^oR7z1jCX&QgN=_Z-YK8?>-K2Twb>3 zqTc9eRF81)_-H?EVMXz=Gny&PHZ1^L0O$$Sd}d%nao~49*#ZQ#4(#^^#ET_p3$%p})0B2e&@ zg;0S5a)-N)-0%bMYyO$dV#7Nz>5f>24>|xCrlB#nO-M%eozK~(b}~Odzx`PxpHJ(< zc`4O&sZ`ed1${aR{E#1ozgv-QWyKN+N6{t8&a+n*IJCc?tUrId^;waeYJRPi=x#k; zy920?GDBH9mfC%t1I49URaA0YBKhri@JGkSc(oLa&Xr39k2B9rBR+W5O3Sq!HNbQi z)9GHF*WCx@uJfC`rA`k=u(NJgez61xk7Cfvc=V&S1yTGM+VS+s_hqR9j$D(Um`EBd zgur<--5K<{7>^~|Fn?%*Q~}QnG^C<1p~_vg-=9HxOOq%~_Rx3oYdCn>Ex|0sXoTgC z4`&Q~-ATHMkFe0AgFrW0&W4oJ0X&_b7-kwF=x%sjZ>EXr1ts&^i0U3bh^#T!p?2r= zvT^JumqnJ2tCn@anVYaMIg%-)S#GkpKayQSu)!e zFz?4AT<4jqLhH%r*AY4u9d7-bMa<9zwqwg>E(A^%(@x+3fsCT}@hwxteCfH9XNtB! z=oG~xoKIhfaIGiFS)%)XFO|^$j*%mukQ;h)!52pW*YZW%9j~?0MwI{blOZ?DJJS{iCIJ?#H`R>xb*j z&Sfj0Y=B?%eB?KKtsehJUPfl;A^~h7kN1b3$7zpu&$Dj{7>M=Iu~%_*x7s!A10C&Q z;CB^_sJBYeXdtvm<~ys{hl0Uc54NV@u3nvu$(Ms74}5g4hh}O&cx#XzU}OY=B=b2} zoYI6|An)Jtj%$ef(CXM#X}In^AJ0aIVC$*XOeC(rq@yfY2yu8Zxn|HC%9{zgU9mxg zvPP_opHCmc(`ld&ny4T9i6IK3%h-YDtk&Qk4*j`0>%Z%0dt(4hc^W8fS}>^n#Nfjz zJIc4;FX&>6I7Ovc?K|VKZ$82jn_nKJAIiT=<_izA9qRo4(q4!-jfi+55epm%!{P;C z!r5V<1D@*JS6!To)rX~nOBOA*+Jd?aYpdGOqXcL&LthinHd0lQUMK$^59G)>xy;j! z^=x`lB&`x1oYi%ngn;wI*7Jq7xEMx9Fg^V>4?WN--Y^kuKEOa06_YD?16OV23yF z@c-!`W~DL~;|jtKOw6%LShxEsXpU`=Y+V!Sq=@hfe)K?U)K zn`F3D_oE;tVtRFF$AmrvR(LC`byZWY2w8vUb9CzPtx60_d?;<=jhg^ihSAYX4ZgTc z)N!$2F|L;cz$)RO+%{Z4#>~+EN`nGusog-uHRGQ0V)Uzb-f=C+w7ImT^s8$w?CC93 zc^zzW;CrpqN9{AMHGtVb3C>0Wfw*u#SP@Y&!yW18scF8nxs3&sh1UX;2s+st{LVlu ztl5Op)=EUz)>{}ZtxLcP<7}BXzz52Ic?yfMU%+J>BWD7V54HC5saK;u6Pyy<}*Ot^I3Ww+Q+v-K4qXI7g|t^fz}CO?Mm@(2B&Iof4i zxe7eC$4&{Vgknk+;?5}~t}iBVkI*WanmVc8e|~(p=XN=x_c+URaVQoa3(->FDEnWYqCp^B%=NfH@Nnx79YF+Acp#gs zOKqZ|#49|c*pz4@fLZ$Sg187GDf|DS>np&j+_tqB64I%HbYqZ8NvD8HtArqBAT1!> zjnon)q!AR95R?Y#5Rq0X=~iHYbpPW6_lf)8yPvb4XCFlP);H%IbByuEcp`{*_~c1{ z%W$zJHAsLFhGKzN@PH09I}099HVb#&;XY&FzF1tPp3@CBcv@82Q0b z2G9iorv=^5AHrb)$G^SRwx;B*_;T-(qN*Qm*Uyb+&30(Zze1$;D-C4QV_|&NwTje+ zjpFojJ25*uJ83vXC{XFslB=AN57u94OC9Z>zXWyxP{!<#UQVCoE-j~ia0SXay z{wF7YI&=c!pokH7dqrK)$pQh}CHRaz#A(vtjP_Mf2E%X03y`gGCwRD|OKkKB zHeWFYWoAqf$?b?AmH1tyX&G1Z0*KVRvyeU%2He+>&M#m2 zMm5Q9&~$;VZU=PyXpCqsd<;YgBg9OZlZXj6npf)-E+A>vDbD2v*6;2RD==_8STC}t zW_flsM7MPniW&ls;7d{FLmd#GUgZgumn{oS4^e z@9DdD@4N<9B{k&D*ql5nsZn;COE>49)P?#4lQG#iO9CHLFP0^6JnXTYoN9=Az;t;Z zaLo`R4zLB8nZ#y& zmA9aXW5=0k^awq>lMJZZV!WFdDWUKb8_P&Nd}w@vuO*>zt;z?` zeg?NpK5~|fxatoi-^P}f)e&5|opAD0W$G{jmY=WRy!r4{6FOwG45TdkjKd>x2%hTq z=zs{G3wE9Wp{g>uHS&z0SqI7A(N_yXOKRMo=3oK+#;t}0`7jEn6z2u8;7KT-zFH=| zd{4{*W|>N*lC?xJ%`&jEus?-C*Dsv$0|J^L|LSDq;s~tXVPnBYgp&v?3h*?tci8X! z5aVqy6pH#o>R*IJD|mshgUKm{yEmLW;rg^&bPqis8X$m^1oh zX9uFbORzG2C?yb<6=9$@{6vB<*!%Js-Ns#MvIy{=iNMXe!9gBKuff3OsZ`+VM=n=n zt|>d=;;>Oj6|PQt*%}Q76r2G8et%mcM^q=+xxWz(NI-xAFuqB?DfoBj2X47aFv7Jn zl1?f23h9Z0q#nbs9I#rtHTdx%8Aij6hlhs*IK4Aq{>8$<`C5ieh2?1KDV!3@TmO+o zAg7$1l28hFWUwo4j|5q0^l7FU7?5rf8wjV6Tuuxq>Xo{^FMSj4b;o#~^Z||k3TX`a zrCM-10h&50xm1Al9&>AZyCO{JL_Yc3%hXZ9n+kJ>`AR=T-+5*{FANlDt2?E+DX*h6a5VjH#e~kP;aE&7lAAGI^QS3 zxhtBdTrpr7=_77Gh41dM&@YggsnD_OMyYpnbp%M6WnvTw<}V}B53Th^=Gx066qMlX z-#{)q$YL&7B@cVDAo}l4#HV{b&MtA^NT%ok0zLypA)~CUtgUU(N|=~|Rxj^ug~go4 zMX&8ux*>^C%^rNiHCVnoP-?sX{Ej2qQ~F}iLR2KzSIadCUU5LU%`e3+Vp`(i%tx>s zp5f3+q#miT-=bC5dId9cYxVz^7z`UxHzqcg70$X;YSe!+f{uI|gI=BMns-zN8x*&Z zMJMoVkjv`Dy=AxTB2gvJ8Gy!Wg)c5TeN6R~VuG#XD8_*4dgW(ek3-UVzyvI2WXDb! z+=08Z9?jl3vX0MjC&1SgQfJFKsu<8Q*da_A^_2%lJQ6sC!03C;vgWzau%7-&Jcz8P z5NyZD`x(yle#%d-*-4A$wiR`NF1dk*cWx8|Td-%$Dm^SluB;;QZ|H-?RgV0ed z$dOR|;YsviqT#2&1K^_`t)ub_OLMEntW?iXb?IHoe4olD0v2{koD#wn@yD!dp@ZEW z#jlY83Xa-U+3s_~=Ze3-Fs6`0Fa}KMQ*_i3)>xNB3_Uq#n#|O0)hdc+*Nb2$y-FHL zj7pbEMFMXNH{YKT)t<F6)Jh6Nw`iQs$y*Cg0Ovc}& zgD!|$5c`+p<4CJ(RB$#T;^zHOa>^?UPVO2xQ&kod?ZE2yIUiD4LPq562kr z=CS|T+tTx#K$1C7V5=A1eGFNfYzE1Ga_FMwuZza+UZ(&K^2_2+-3&*M;5TgFJC%TD z9(2K+e-zBFqKqJ?u(bkIi}r`L>4kh0KD{7778#$#`t+GIPFwom5rkRB6Py;jMZ|)G zGD!8V7su&2$(mDgK9u%&H_IU>>lEd+Xsn&{rM2!B(o@kq418G>EbQSyf*uzXuG1n% zN~#(g{e8g%%9>1QkvA1XHs5snNAw)?S!U8JaXf5HyM!ZD?pQ`#dWF$gL1#DXJYBHi zqV-GZgDM2I;0k{c{x858{&%&1`C|-DJ?DaETkY(-U@ZrnYYnX(W+>*@oqkts@lY12^#D#NBvNQ2e|W!(go90PJ(R!J;cHM%XTL3?Vb#(vX2=n*&CIDzO55wL=Hj)Lw(r^X%}Mo8RW()pFWQt zR0oCDB(mv|RbsDq{Bb4|ZZ-k}NbTs+26qTuV2ViN@^^%}E+3*k#qh=F-d#gfotWSh zGDCd4{!Td^uZQJilkSu~FY@u8;u+ z0hJ>PTACXb-jyZw9x|6|?fZPktaprz1WMX*A4afXA@qgzJ9W)}ZlA6Pe)qZc(|~?0 z2=y)X>2Yt6wE2E9To8inO_us6iGvrJwS`TWZvOE5hVtoF(%EzTq_aAF1-g^5xdaJh zht)$O+!!ZZlEa_niG4&#O3o%ypqXIZXyJMNmbe$AIs56&Idh}^Nm@Qnzos)=9$y2U z<)OU*ziJ$sYJ;V9yMYpL+htzpq~>w9w9#I!F@Ci{v>o0vpTG}l1Q^TlpQiJ7a;6u1 zgAB5K zc1I8@N*7R8R@-I)W5p|W(14D1SdXfa)XBb)()8|@!dUi^Rd1~B1On)sba$yGMuV&Z zE0r49BOwH40PLsJJ@2!@^{I&K)ET;rTI3YPC&(Bu0~Wzp-cQ`lbTX6pZFEJA*=*gw zJ2_u8f6%QcXziVhxJXP}$GDqd1pq!mD?WycohrXy?eY@Q!COfg>}=k=%@nl1596JB zLWo%6bB}0A8`2H?`?TiT4lEI68laW!!0yr-mxt{T8MWk3E)pIwF1gJBuq647+v~bl zEXE`Yso}Gm53W!O>dQwBrflKfey(A4pIcM$Mgl&7*grNJkEkuwSWcXM-l(Lt)lp%-#@ls?vu^4VGoAWb6gL(bw`5iPAHN@5TAX*(;z(=N+F zmkoe{2?kzBGGTerDV`WKGyc8K)n)tRXC%qW*TT?I4l@%g{O@`3hZragAAhK8xS*#2 z30?qsifII1I72cis_S71wogx)Tcp5bna0I-1dWMOWA^TJ<#e{#R@JJ?ae2Ztl+D z-ZnID8_Mz1zvW^{Dqr;AU7N6uyz%>6r&HGbiVt5&q0T)_;Jdq3m0UtVVAToS?~AhU z%Qrs}EoNUqxEPQ!07TF+=ys0eQ>AX&w^KrghstdNS1O)K#zuLQK;(~Q9# zY1Q}OezUqHgv=Pb0EiZRQ(60tTzx!gCl_X(Nk8^uQo}|YwBZ0I1+o))aPrC5>91`w zw6t;H=(oQF;+}i^Il(&J0~U072uD6nL|^OnY2EeL&|k(){s`opGSG;?vqG3hdg$LQ z*hk;{W|^~n9w4AqjfKqxIh}G3E##=7+n+vCrj+WdI`kwq``^Swq zX{Nn^P9mUB=!TKYSYM<-{;tRG65&whVM@F7>Wcy=Ioa_2d-W=bF|C-f^9RHzW|CCG zNBuY`jf>9&S5M8HES`e98UdO7Z4OHs&Rj60h-W_GY?j!khfCrflaSQ&OFClY=SuT^ zu0&@bo^uejPLF2a;zgNj^Z5ySysL=1KZHu9mNU?*bSU}p_^i#)i;f8kLxQH_LnFh% zhrRW2gY?cVN}GjeSS$?6;flvXy6 zHuLfD1ilF)c!2He(54OH>gYv6a3rUc1@ncj*VDg#LwN^oMVZw9DxQ&s8+3q!vRp3T z`bd-JM@fBR>BOc{IN7}E`m6YDG86PziS~2$p^-_&Kx^ z_X`2ptaLlPHn>!_a`?@Qc&O{K?_6_i1OZy*W0;{J^lVO4$=I zS8Df-&*p3?BeTWV?^N7*g+&(>Ae0DYck=nNv9js?j7~|hz@*N~%Qobq-*E|(9UMW5#;6>6SNPs8u z-PNtfFD=H^#qfLFUH7n+Qd*<3HD0k$>Ld_LRqlM0NdpWu*+(CWhtz;uQ6cADm%K14 zLn&2#w@CN*yQ4y5+}|~vLMd>Hlm+ga2%CsMc${9?85XiS|zc|_9I{)Xy}fHx~I%=)9J>H`0hA+|Tg zH+jwT?b56bpH?P+Av?H6=xc_1+hi`XmS_P6T;3?2Md8M&R`{lL&Ng<{ z04-1a{6+8EcZyMx?{s@^E%{r17s!2SmA|(#$5-}oczZQf9i`huSW?se{leZYUYzGK zpE%>Zd#j?K--_vqs)=N{UKiaF&3)qHb4P?f47bIYjan?6y5J^8mq`3(mv#E>+}Dy3 z#wsKOd!(nJW2jkRL(-$A$u?n>f`6kuBk%xIwtvEQ*gQ2 zSKavgN16uoIUR@QAm`hM)R^1@K3clU+p1{D8DHn*$?XvmRc;zGo^?5viJp9{tX10g zJ)Wnl^Q(WC|C1&b6|05nkkM2Z^86?67wl?;1cnbK-nS=oajjm(3p#GxK&#gA%uOir zS>m6waLg`~`Uiw;PB||WLezHYJXEZVIq%V-?~+3ZNdx@Pr1}XRyoy_FDAcMd9g=a5 zpC7~rib>tQz(?cP(Qq@gaFG>S&%^#p6sTF;DYcPrNL=l=hx_1h-=~)5_0<=i>D5cw ziz6Lh)PV9#3aB*A8wKJ0LlnvfrJ^8va};|xzA9~Tuy15={M|;>QsDL*61Zh(W~E2~ z!~syWuz&qZo8N|Fq0YMK+02%f54V~^Yb{Ru7P{sT`p$@7jk(MLH0#fll#tFbb4K28 zrHNFH3gRBA&7@xCNj=H%5FWQLvgU-$?rbmoz?6QvB1!LJ!nD_40#mg-LnNIRy+}aY z5c1=O?vfY^F!FrCsHSN~CZCQ@{|-o@quUEX2xS7ffs6Vf3TRkZMUqNL!Fd1kjB{GN z*Z9p-2g`9EI1Av}@h({x<=<7B3+oJ1XtHyT?$xFo9D<I`&e4doCL_4)gR#e`>TVeR|xehqrO z)Qb?50LO#mJ)!!5Y9gPAmv6d%?HqzeLYfIg_jSx64wQw6fD-l&%3>X%Ba2FHlOQj_ zX=MbV!Xz>&0b>FpCbCgxAF6-YV22ou=0AfFa&FL#ETzW1{n6;J;p!y|42=wHP`4k*`1V~xjozv|>jZq2GY zmAFgQ%?83p410MiN5&y0Y{nk5bbC=0S{K0lX0!|gxSK-z7JmDIcluIS@Iul8Z|cW0 zk?m0paJfI>O}x{F5cBr8enTqbPidHBBsG-b5bvnQmTemsP{(Fcwcy+}muY)e_N!9D5zno#7-N(?W%6TWVmtO1QI7W8>P zdLfLcR-jV+cPj*))Zq#kbLdY`db^}0{>%o$#xk6_qS(u$%5I7X=`1BwLeEfq+1SgL z8j5WuCrfQ{{XtYiEAJ7-r+{t2di5aziD$8z(V}gfG9CoRb0l01DF)rnRIG9#ba<&P z138mJ+UcUrh64{(zcTNYa-RH)L8a5R!5CSKUBU8tdrUX~jTaWf6;I06daj!Y(l!V` zc=YHzkU=tj<=apWv$C|x#ok9uRuV;QXCxU|X6?%hY=*@QJlDTh$(y`d#N0)g!p$5F z{Hr1?46|RGCfV|%0d`Eh0MNh&W;E*QQ^KifP1n1x>_zGOiyl#-iri=U2}%GPy?Oh# zX-}pK(z3(Y?KE~rn{BOLe2Q_uw&HQG4lZ||`@Wd+QO-{R(| zC*MeFOk7+B=(&ImqpYk9)-V zh)vQd(HM<)BJS;7(bEE}`Em=3WG7GywlybaPudn{`j+jc`gz@Eggy`~wD0&+j$dx8 zTx=^1hKn7Q@nW=(HxEg*c4#(|92PJ18+k_V|9oI58?YTJEidwj7W&som^RJ z8S6<;w)t@uO2K|nNK?*x{shg8A%kEfm>$p`Zg3}x92#uRwmY`j3p3@-@@U~S-`I)W zRKP`87@1u^5)c552*leiPert&6;I9m3S1w#>w{?xT+=Y{!1OAd7#Oe#Z=NA!dN?__ zD|}djCuLi?o0jNe7N?Kb8dEtwvU@u!n9SWzaaAgqCq2{OA;8h*zvwmeBjeZhGh-QC*;gD$PeZK$Z8UYwW_<(&wiKOj-=2k)y z98_EmUD3XLKUk42)r6q%2YokyA@bzC>v9lc7rBI$XL!$Sb17F~xP9JXI z8%f)1i3-6Rjof9i99Gbo{$F`kBE^EX$&)c5^S1`AVvX4a*H(Za`z zwl(#XEE9|_g!Yd#UL&VC>|9?^0y~qCw;AxDzOX@FfJH?sOWv&N+q@vK4}gs+ zD{e#i>kt$7DJ*!6ZoJ}bQ1v<+M4~tIZL<|cNfY?q(;@kP=y%BNR|YT-He9pUap&E+ z)KacCm(PxWeJREq;Vc*skaE>B;3{3Ug}~wf94(lGr=g+2KZdc-&(?T8`ZO#I0mMhf z6*$hHKdJGPg^A0+`Kn{^Un<3;F^_o_{Q1LEif1*b%^+nZraxSjKJ;f(iUc}Pz^#Lv z+}uWR^9D0ImtblEV04i(NreOQfQ^Fi01NdDjqa+kDN0;g$0u(qk1ix9w$lhRxsPi@?Iqyl__^lgFwj@6prv9N3HCto!FqEi5g}Sy_ z(R0Dzka5a?cPvjLsDFqlU_NMQ%wS(%<2nTjtQIs?S;-Y{zm&bkggs~G_wEunb=U#z z0DL<%?>u*81`8Ls8N+v!FgU2&>8wk>S!09MuT_grBF|$%RI=;!g_0{X+)CIP93&`I ze~hZU3dQ+ES0tz+51~sVi^pTA~&GVAftSuknbm6c2X0bOM6L&o=To+F5@Hn zLYCevq;w+>xcjK-hH{yd%}NR~@i#Yktc=8SmeM3`39lEJdu&H>w_>4?*ZVyZS=l8& zJv-~K!S0<-Kk73|Pf!V;XxUiU$1|6b(z@!@Wr-R)m|y6lQPYLB@xH7>cp?c6ver`- zX3JxBT^7ZF_?_e7QFL>2!-x#3w|@9JeLp8BN7FE`Bn6CJAbFby_j@g z(P5BX4~J9B1)I_GBWLaDbd@t5Z#Z2fcpNN4y5(~g_jWUP@Z7WBw4Q`Hr%@8o-EWjEKA9#XdZwyKJLetuq4yS=^`!vHXe%!ber1eY!BIHv(u`veee3iR`i z@Me}b=LmtH0X){Pyl&4^G*96s3R_Pw;E9|G1HGe=pkNx<2LVqb=u~^`W=%-S6&Swfr-Vxl>~K^taYmaF9Z*S{xg!$tS2NE@Lhf zlLV*c5EPdhU_H8rS45R1m+F2#b4>t2P3@*5?DBWq-$zE(XkGn%n~ByxRC41syzi7| zE0gbnjVvk)uIf4W!j)IPNb8ikF7<@*)y8YSP0rt3O6ah?S8?zQm%rtuTT#S|%=FLn z&m%SG*>>&^Ngpe0SeUX7+lkMTLy@68TZe&6=Y$zC#Dl7e*E}X+}2Qu zbpwna0ynZwAh+P3Mc>ndAqV2i?INQf2Mom*OD2WUZrOplna{$=3R`^hq#d>SK$W-M zeR`pA)xR_?NeXMR@oln=5mlc-yF8PB*~t{G7Vax2IyXflh#jV8X1mi2pCzop zTpldqUY#=?sdBAq7=Hst4929)Z@7hqhSCU_;^f}G2w4(lSX5kx3X(^N4i?2hWwNL) zo9pC#C91iUf!oh!$8*H7_j9Xa*KPGkG4oXLVvRe`QXdjm2f3A%*!mjS2i$VyA9iCZ znpHKqbqOUDnz58V_U_DMG6`H3SDei8M_rv?u+umntrd|dY1f?$`Lr)P2i{yi_toq6 z+o^M-gDkJhCYI27MR>c%MliYev1K3D7|GF!llpt@vZ9J70zIb*@mtyYtHlrZ-QJT$ zL5;K_dXW0Nd+QHVdV4~xsisBF_`oL^GVFg?K?|puAffaJj}mLQwFn>S{2#;NtEzb< zF0CrvqJ)o$`g7yrV7zWYsK}6>}T8XbZ-*^YQHOIwd~b^GYEZs3$?Ft zE?@t!0)a>TO-ic2AIY|INGb3U&;@o(UxW7>+{?m&&U{$e?l3()4O3B=XZ7aYf!}1i zx&4Dj!3CiCFc2A{z%~RMq=9ZV=^wL=l1{$t^o}0e4~8NjO_Ix@P=3tD zFy<&;@DU{?6_tBU9pk(F{ASS86+G(Y^!U@twIIh%kbE_mDmd(#U0F5`Z)vczXaKP} zT>dakt?T#tXCV4qy^05m=aV_h#$~1i#5&x*`-?h*+_MM2E^p{UEg|TSmjRuJZ0{W`ln*4B4Stqb zO<@&>mHv{{o3+~HcqCV~Wv|~-2m0dJwhfnsZMk0r2c)JpJ-D)FKcL{*`FUOMl@F8~ zzfyHaCOxeOm!*&@=XD9~j-G37MUd7Vl3hCQc{_v;ftYYDR(d^P1mCT?a;IBeUOPii zKXWLJ?UxbdZXI|k;(^5+J=SCKlCauYp)Wj-nxgGBzQJtbN43~ z0hK2Q%ZT5~Y-HWKPW!`7>){O^3C5Ss<`ls;wk!t9=ONL*F@8ju2-h_CqmXR7z?sgW zLV0wX%PQaOFEEj>?5qKWvTmWNqDbkP@>7bkz>}YSqVJRxgVPx4Q={QD>W*99!I0~sFMVJkRq=zI3;N0r4NJjRZCNNg=Gtj@ zY*g*RF9*9lOOD1DH_f@!0<~Nv%ttHyi*G+_0uw7(Vh#c zQKz*N(TqJ790qPHxczI}PB)W8aUVV>(&u@78t2sj(DVN3U;tCfGH>#dmAzU^7=bz* z$s(;I(a>6UMNT3)BOxJS7yPqiiTSiS;&bf-6qKgU62-T*wEVzI*nWQkQVofB2TSGP zM)Bx#IjB;l?|s|A@QDHplFF`PFlhd={Q=NsGpef@5eq_jdF+ja0e={}vzmekS5L>a zHN9JfX$T|ZYvRzwAl=c+=w`lnG0a()LJ3ssLPDoiR8+u0?9-?*PBhsPkwx72pnjJV ziw+fH@8??aDQs(zXEvv_csPH8M8D<AtTU!b3;~64%9cSSHVdQB9Z{4b1*hyWE}0Kd_yHrlzl$8 zZF?vdWnmfhBSr{+o>$;J2lr%G7C!V&1MJ3YdRc!mecNC-r!Z2Vqp9zd1oI(pc9}%9`T; zDd)ULia{;byGxR+h)_?I@_NH0V@Of8e;L2*rW{;ch_AG8Vnj5z+`SMXMxs9tuu-OF z^OtFmhUB1*Wa?n)vxCroA=Qw(b%o1Og_}dl4DWaa2D`83w!t6;e1x@xaLR1ngD1^i zZX3K35Tn}VJb+vgMw#yJ8#udqt1ksNM}I*|9u|tPriCaJOsjDXzGU3g)I9OwI&d$K z{K9}NOzv`0=GF7ke0qD_;c->`vt|E5=WUp`TPF2IV_~3}Rga5xpNtT32_CeBk8h~I zWW}Q>cYbg%rfj1cNDk{&4P*7$ucNk($u>yuhpu$EiU#?2MwAMpQDL<_yW61kI#t4zQrvl|(GM4ZE;wS8WzWxUeNZ{MTcI-W{Pj4Ms!h z1S`&u*GPzwxBco`PXWv4&d!#xI>;n}5BiU@MLhfulS4v7AFWCdFg@yb)u2@m@;I{OBmMWrC9fZTt9{Ewx(0=^>y5rhK{w>RXarOx;Cimgm63mKMMs0flC0P(3ar#P=TiY|mJX)Xjl`aZmSLcoUL|Fj z@+#sdlh%)KfrYGZ{+!T#>bublUP zNZBkDhejp)4mQ&$p8S7XEcC9w^e9v8y9`*@BhnoR_g8@+Ezf3=4q80mGa{^T6V7;T zM4Bi2aEjrY@~srni16H%?6<{`)}af4I6pCX0Z62)=a+v3RU0ZF9p9>FVtz+H6$lmg zL6l7aV$YkJja`c;6!Ioq@wsU;7!Zn!EewXwV ztL^yrb3EdRqN2Wj_OZ<4Z_A|EYFW>n@!78_w`wzkG0fl968(91>P@rhKiqMoq^XA- z9D7XwVNE#pKFhc-YF|XmsD97$u>0jsldHx%H889~Uh%(Z;tXB*tR8noCcLy{PV?Z; zr(Y2;nhV z2=E9qn#LqU8lzu3O!Mb)J;F}5NWN=z(Xz3^Ul{R!!4I{U&t1_)i_k$NV-t2V*13+5 zv4na)6C*#FA~P4rl5-zaQ*B$`be1*@OieIcYfRUFb%cgxzBmt`D!D5}Ool1A?DvR& z=?wnQV5tDpi<1mzSoWLKW)4|j+Wh>EaA&x3Y|(;#pT*hbKBK;W`xXE}7=~r70OZ&D zAsnVSBMcK#4vAfNduhSgn~3-ipGA|0SNKev;U)hg;Q?#NcKSn&-RG`86VpKI+{0%z z#cUakXriTL5OmJg@QOzS*ZFSN`fZFkHB~e7%$||LcLsF8+K+@!HXa^b{xy7|Ki?71 zsxYk`nwyjkxdQw1+W>g6r?}3Xotm9R;733vKs_R9G13M)8eDK>Gu*i`k{*z(dA;ev zU$*Zv6_B6+43KfqEq=b+Pk|$1zz?eHpchg>&gZZP$2vEIkNgDlw+Zj!K9s7a#fa}0>NW*;i{O?6VKxUk4;KR zgA#uy1;-9dI&%$z*S|~$~^CIpf*9-}hRFd=Oc@)2E><3#)!=m$_Jb-W1P=rrj|k93gx5w9IQbN zh2btWK?Z$;paP_$r)=M_15h4H`GI?Ks`a^b%12#p>m~Zjv=JduQDl1DF1so_FT6#p-UBi#VxAgtH4w6ua%&gALk-5wb~ zin#%&ICRlV&_Htu?y~-Sc|Vg&#FK^B0*9O63QVmXtMwJW?}laEnIb7Gt)46yepN!?b0etea76w!{c*J|IJr(a%?Qmkg3_wB%cM(TNtr^bc5s50VObv!QskL|4{*5R8;hl z_xXz#jpARiIF5rSHUv;?w`4GUINq3R=l|a44ff7wSpt?njLT4Yt)_x^sKTj_13%|~ zgR3YAr$}At)q?#uZ<13!L7-qABhMIT8qJ*J)-mEo{RW6v#giN(CUz9I3v!L4AgKH=Fa2OmF1S!}5gjZd6bW%CiDfA)EClKJ-%k_`aH_`#`ah4eyP1&} zTmJxn6R>pAt$d#hV;4>4eUk*O@c*o?3b-s^8tIk&SEhKiTIB|aFaL>sFM|I3(>*+u zz`r;2{Z=vQ*`Y7ASU!|I&{vO{nz~0XYM0i~hvU1X`1^WG+r^b7cS|f(Dfb<}02d;N zeeihMAG{B}poxwr8JCdoG)nqFbgo=8<7(jR3jX=jUvvw|(M%t$GRi;NkACP;8mcR! zc+av~IcH_~xghUB3Y)u5#JsIttE6lby4Swv?OaYFw}5ivpHkvSpy^*7geJdhu*g`Ms~FzNs?f| zbdZag@)GAKpGMtZVIv95_%y;+x{0%%Qbxf9G@h!l_g}=u{z)N(RB*mGYX!Pu@R2MA z7M+fKPaE**5H-Ti!6=d&kyH9YBX`hK${HgIo6vGN@e7Oh<$J8Ofy_y@wE6` z_8`x3&65Lk_(#uN4+XcJ#=wqU33T!QUHFe^!ycRaaOSb~X*uQoZLndMALV67F7$?M zszUxYzd*e+$W5ZG0D`*E(7I3;;6hY2AQmt91fkGCEGZx0>4Hh6psG|(T}{dMQID0E zIvzQ|!k){nLU^Htt^-=01sEBYKWFYn^n93vO^hypJ6(fb$iNJE6*4e~81ptnpYu5Z z3?Lq7xZ2-1#qH0#JBW@tnnIxY8(p}RM)HrWio$a0^D|lLI}pFYh!Pecpb^a??`Pv= z2};Tc=a7K4^8dSFvD83^ar`sC6iUlZZN>b(LlvNo@bMNiD&oH;G`h`<}wJOG{PO zXOVxo{pUUk!11p4XU2!2)eFn(N3NNaJ+_)4){&zZqz7&|k~k`V27gORv$uS1O5A6N z+Fp@91gU|BSnCL9KtMC>!$KHI4$+RMa+vX!%9$l>%ejwGo1;lpq65GV2PI=_YN|_B zoe`?WWpZ=p3Qdd`slv0Fcvzb8`_PtLlp59hgUd3tFvq|Gf&teD-WMUK?qGKT}gaV7tXcp^~UUNanQyg38)*Sf7_UX-w_h)y5>QXVm@h>R< zJZ1+?;H&3aMg-vMyY}4X$iA9f4H~Uo{r$?$krb4s|0BOdLTd+v<<*hz!r@{RM-Btf ztqGY`Ut@$Bk4GY0_}$mYaS+8K02wBo+a6Nv92_g85o_3S?G5VFL|f)x@wOS9&2p(-_Nu93z`{A2<2oYt1JcB+&|^^y{z`DrGTU%uYr!M{NKR0Z2}knltX&kp8!9rQIn*@l zI&_J+B%bYpRF9{CfPmw398hCwXIzaSy!HV)g8%`;!D44W&On)`zH_tA4lz^S0{e3) zxIhbdZdSX>rw=zm*sb~|%eX`PJ+}OpH)d}?1h{6+&9lEH*?r)~*H2cQm|-r8#@Tfl zHqxJDvB%?L5UyHT6TewAvDMGAXPY+_cyhi!Ju;|=qDwUyt1kM?-%mx)80d_jNqs5{ z+b`X_+WYI*ubC+wnWGT5Zv?;JmS8mB*$zCZsA>Fh02vhwwGpqtREjhys=&Rk^r4|s z?;BMEQ}*FFKo@dzbF;5$vBK;DUMVR?==#}|(xDI@0UX;N%s(fAMli{lhW*<1DLz3z z{Ov8Lzec(;Zz?TSM(xiD*zK4i(nioz&ifdvVL29tymX@ji{btnvP=wg>i#1U28%(< zzWgS{Z(ICDf%#xLC8!UL^|vTtm&{Y9wvb>#!F6QIwyb9R1W>Q4zmzw zp&F-FU4!cst9%b4*Oel_zpr!J6*AX9WaQ8#uYdV|1aEqc02zt|<4@}Q`cX!!45|Bp z;08C-o`{8tGju{s9e_u0zRqtgq1!xQz^WNCYypRv8}w2hGyr29h4&ss*qEkKJZBIG z0fLusg2}Fb*K~7MEz|gQ5&Vlmt{!?xY5+Gi2kQx6DjBdvp~{1Voq6Po;gO|7IQpMf zhu!M=OH(~Oe+$L`yjRe?7A`X;@T|!YozWX*33f9ZmSYZL-<&e`eYo5DE1q0LNLXJMJv7=4M&A$wnLwg23bKFTVm{H;sb zO|W{`Y%6JPJPLyC9Yj$Aq~+9>I`J1$)2pJOJaq~71uK^k76l%dfWdJ+7H(-PQ~Ow1 z>BY$Z?e^)Y@0$t$Pz)LH14W-Q7gV?3_Az`rs!bmu6$R-wi@10qZweY678Rug_nOnv z&sO+Gh?g&tlU4H!T77hCM9Hpwe+v?1ObG!s3wEm83nyf>k{UDYtB{a^hPBhU5I$i<0R0aoww!tS^VhG-H>QiR*0<2zj=45U$r zvR4uKqDf3u2p>h68gLcnIQn_&@7xH{3i_YWcVT}TP9tyvI^XN->qz2C-h&H^@Aute z8U)EoQp10Qkbjd@RiWGzrNp3=9Vt(eoWvu62{6cG6RWR0gwUtinBG`BA13Q(jwo3( z=@90*Wu(jvng;O~Sko}w&E;@^^YQLtDbl`x%nAm(oq++`lE9V)OEQw8*{?`KootU8 zz$%-&enD<0?2R9p@y>vx53l`2eNlP~A>m(zYV|77?ChMJ;ATw)F%ywstx-uuo%A82 z%_Cis6d%hGZxGMS9PE5$Be6hL#ysuf z>o|Ec{($4Q*5}jW$M;ewC9Q1cg){8A!ouyfoU@Ma9>^+7PYrI8nm&*~$%^n_ z&_C{i8JLNJf0WeD9NV=IW0~*X5nhkujev<3>f0jALNoH>7EXU_&=3)Yr6y_0@M>kw zOz+3utGEbq=}coNXDz2(76I=+OHJ|i6FxcRsXyh0%PF}&`%HYbAHAtL7@ude+*g%B zh=`9BXa%(nuNBSNnlia_0w7XpQy+MIn*t<#s$1C&oCuD@Im*&wmhUDR&N^13+(CL{>$L-jue3ZS*#>$B$2w1E+IXKdp>XT@)S)?0p*6kh9=#Kot76*q4<>hqyLE(>X3+~kx;d*>YyCkKEkrk_jN?fqu@ z$8;c=T{)7&_`mN+DN|j4;&w_yBB5Ud0aEM7?7Vdy{-|yx)%OFXsln zOU62G)?kzGS^;zBOZy$1DYK@k2AYDRxVxkgb>x4JX7;e?ECg6~CL&oo8m$M063*Wx zj(`b>#*D0V|UvPQ329_jst_EGj_=?oc#M z++}A5a|uvB$k3;uGGOBu)|4@!#*S&FZbb~|El&^=<>R6RkJVL@`XWiYjLwJJC{$;i zC*0C^`4)kRYGq-q;bX8g|l!JAj6D(O)CBs5*0094Lr-?g;+K)q{a3+4oC_ zGA^_taT0PL#Hr}>qmP_2(ih2qI3cNTBz+l}<-sl%;r`q z#;2Hiy?v!_3O*oOyS&Q0X6mKV;3SZU&KM!oFGAN#C;x6KV!^^FN$fgGIFm=C ztiI{U<^P0!Ob;29z(|Jx5Uzw5m;Sb-&;{N2ltpHxB5AI=r7FfA%^nhi`*BZ{bhYz@&Iml~1nlB-bg08gv+^&n8Ub zd;C1_d872=m8}+wk9SuOl=Y}ko;RXqYd#8Km%5ic4q#DP)Olw<^01*Q=lgWDQjxe3 z2sg~Lrb@(vnynsPK6x1;ZGX-`;Tk)5?*78!;kLm-lvC2Qomiht0V=UIL2*+ z9`ET(c4Z=7_^G`V$EDKo=^|h_MhwbJEUy1=)iPq~2I@}GwY}M-`yBvBrmLe2ht~hu zChz5cw}tR%U}qvY1kllu0f^)3>N0O7Mx1126@I=?HSfg(lFjLb_fjWOA&0X&X?+ui z<&60}xaKY!CNLU{*lp)D{Kfv?Kx;(i*A*A14fg}fI;8T@85oQ*yjT31~~hE?d~%MOps{0Jp1Nu5Tp2%#6$aT#dIW<2i>n^ggbbySI*BFU6e%W$e9s z8cA5m72;F3F2hVdT%L<@^uCLIZ73b>(nx=AqrKJBTLv)OvjN8EeT|anY$i%__70y3 zPVpsAr70SQ-xdTs;x+28gztDwfol)HB%(da>%rZ`Uu=*SbS;0C2QncF1!pyt;qce? zbN?UDK$LM1IxV|;j#$NSo~wpX?BP#$r!>Gyu$tOBE?Rfs^7B+aPo~R@dZJS-#RW{5 zf-8?~6Ja~=gw58MZ9SA-{n1@L$7hIwh4+trVtrm_ax~?>!>LEW4!VDz0|oO6R!M`8 z))np5elTSVLNJs-<7l4-2hfb;ldwU4ik#%s!ee`!dQn?N-InhUcumcSW?nGbwusu| z4ykz$Y$`hku4q@qFXKSCy>b!eOL#>UzYMD=wlUf#VNIU~e;@D-C~ro`!~|xgdL{gi z>W)E(4hHW)inIH?#@AH5!QI*aIF#XUJwLfeT`D=c*qAn2-EWga23+6%CVOCG^!{uOZJ6RNuZYZm{! zXE?2;_$`7PrQFiH9ly-TYwUTh7uZ2khl1}n@p4oQKFtpshr6!6+$ko(xLbnhAmC^` zqoq!vXnT~zXjY4g^h1gXoqUpac4lR!D%ZcC1S`&hf|`9oaZ-dq2*(#$4bP311<+|2 zJ*NWxcADAJC^fh;$;POhcYa9!bqTtN6mf(^@}d-$$UQH4_o@F(*7x4xWFU*9L>KsTl7NeswCGQ z4#mo$0U08$0C){v%MjCkt_02d%Gc^q&PE>wtQHd<0}e7&;E%DkFp z1Qbro9;MIodf`8i($X>q`M%wu_s9YHZb8-#XU*br3VCV>kj%Q_o3cN-V!7X?jp<(c z02DkLs6Cx@pUH`PUAit;FubY#?QoP&6NYa767FrOE!fJk{?Q%JL$g*HhssttyAi_! ze$IW_E4vp>K)^%_KR`E+zEGgX()xOZGGK{THFqImvqO*kO@u@0 zZ6twpi@B=hsU|?R*`KDL#;%S%<*?E->VtfgQ0Jzl##(fAre{?%Xa&Lj%nypbVY zD%6K_jGYqBBM7DM_$#?D=TgHhBCaIFI#UfJT<+Zl%SGQS1?yIAo=-LC;$K}#h{ z6%qw`-wcOpcm-^8ph@RQ?)%M8x_RPO^9%Y&w6iBIX%V^vq&^`stBkmP9J z^Do3xueTvr+xGVAj({Uy{g~zy`(qAl0u&nOW!x<4>>|k8cwX*&$MO6W6?-;Yd-eGI zkZZNft8XvaJw0Ur_I?(0vDnky_k4di@d>iMaZLje1|;)R*A;EJ2_TC>dpz&cb3!7h zP#2|)#DG8olbki})5zEb2T|%Gh?6iVExLkAcrIu9oiAJrG9rqHkFG!b|LUmW>g5ch zuR~!;o)m=Y{YE#yZkc>jycj0a8|>2S;;yz93Y>Ws(NSBpO&2s=5dAR^Hyr;^+F5i1 z0|X7{c(&yJrL!?$ziqO&^TI#yRtPYqrMe@!5?EoRKrm_SNC0<~tXmg>prN@;i133Y|HPw+oYR2*q ziJu<&dB4>E8J%whW$$_8k4Nodj}*vvQuzIDiV>|lG^(R&0xjDiDL>3+#!#ntJzD$y zw?#PLZ=Et>EDocDO=pJ_(lOeUyXMzJ{u!yrvR9Ayhz32!`!Bx&P6P{BV*v>K)r2MF zn5OB~c|F_c6?rh;!v%KNh-+G8PPbvuKgURPO0pz)VZ9~Omjr<(hXGltGWzNxLPBTX zKK?APzH@AFDCkZe0*_}j%|+NGXUAb&8zRT{Iia6Xm|X)2kR`yB?727V13{K`G%8{^ z*>XIMijZ5X#CrHZB5b(bBYfksS}CcvZ6h1fD0+X`L`j&|oaT+C5upcv4J zZq~mx{tRfr)+*|QdhqG-n%pxJVxcvyUAbE)Fx22Jp=_}v7>#>cVbap?{qz(769AQa z{24`bM-6Dt9|^V?#Y>u|dvn$f6WmXZnQyxxewLqY-_NMUMFT!w&iQYT)hxeHeumli z#%~)30lr$+M~j!hS*gGL>|1ESF!i@9V9jIF@A(w~>!1`Git4ul&H?+i zfG)aML$1eSMpkW}y z?a>KVK>EFEh}2W}jH#l%vq`Y4A)2TuL^}upc|B&)4u3H*=X8_#20+;Z<8{!al&jw1 z(Q8FKvOlVkE0Z2xRQ@PaV6hiSjCvOz$Fd^eVisrd0&)xj_ji#W2ECojGFOqPn`|&$ z82b{flmjghtVQd4exkpk^O}4&MYRiYpxQu~H>9`~*IY*TPT*iZ6b z;`4&5{pvdx1oX!US^jN7=ZJ5tB0J}p-0A%Eck|ZI*ZuY_JVvg4TQMhf+kb@^Bp8am zCV^*?@bO1J(K)t#Rrn&o=9<>%68^c|-a0!u#3*b?L0Dm<O_f)0?t&}J(jjdX;-&3Ap?ygL6V%dJEN!O z8DmGf8m|mp?ZWx=j@mWVk&XFG!n)WfW4L-kTNF>yh}F^pCwlzonprOP3U9J&%r@sA4b@dg5041fo$hrJ+Flv2vu=!}u84cTw z!~H!1tI`^VhEXt^5ydQ-rKTwr1f~TCXI{HLpL3)F18XTNOZM6wX0{qs(ON!hbg zDCtTkDl1y|ok74LJX^65N?wVKwmFGJj;(t`?&eY#AV2-9cK_+U)obfk<2NQ84KngA zAt!6SzF{LI>|0=vJok+;a;C5vn~~t$`w%5V6OXn1iZ>u86xOVv$WIdLqC(_^-@su+ z!ivzKUBdypfwm|Ib%CYZMXtxf8!{^gyEnF>ob<>zn9HepwZf-2a?+MPdffk6C?bdi zUBCj_wv7~NBC{rq`#-%C)(I;2<{w6>v0y1v7KxN%zW^3|W|CuIM9@XlF&cY;jx6F8 z71}kS8^}*Xk)1L6;Lx&)Sp?2nXoCWv#2`Lj|9C1a1Kx}{iRqUe*L)cfXbcD#zZ@or zAa>1s@9q5X?c!IcBiJ5&j-7DJdMdzLHnsSG9#)UtowGcj>0B;%1y?7!GuNvbfWzc> zp>SB;64)|%yW1CQT5i_AHYI&sPwyM7ew9{uWH*^^Ux?N>{$?T!$YHImoQ@ zSVeQQod^tiA+$jcZBp=Dr>VUP2Z0taVX4K1>3E^9Eb=P^jE{5ZXWzbMcOr`b1c53P zJn6t&v>d+)0R>Q&Fwu$q((UXNoM-xJ27|Bw^3rbnniK05GZ(OaB;MGOJUu_8tWgEH zTAT6iMKn6`AfO8$JPgY%!IYt^R|c*La36EB48S{+|9Dww4j^o;{Js16M|gV6^wq$&ENhk{OJuanPxCAxA}EE`DlDg=U}sB1vPeDbtfAf%lk&b z;1fKbo)SkpXRm)erR9c2fYD!D@qeX~0`u0$|25xn@eNFgy^f1DNB#jctax3if`Z!t zuP%(M`bo(9Xp)XUr0l=nWofc1qJ19dbH#f&D0nfxt|0p)!Y9}I{CHdaezsp~{MhgJ zX3KAr;~UO?B5JA~eh)O>xe!l?g}h?rLr5<9E4Yost@)&`smjP|XiDR}%}MAU`Y)`d zTxSoT5Lg;}?_2g1)UYc1+vE2@b_2072R69=&=T-G7l$c-rlwS$zKObc>6wedpR81c& zJYVd68CmO$V!M3#!sCy%eY0!>uV9Z20f8&#a2wTX9hI4{CViAJoD>d@3|nCGu;XZZ zLC465ac_Mh62{ADvXN&ZG0c)o-!s^8PWR;Y8Y>{td}LC~#{KNG8clp#mX1x~v&EE1 zz4C%*Wu9}fXth{;`1|)!sGQOILgMldDa8+<=Q+YJ*|+SwznG#&F}u&bUbgq>FM^_pj%?H4 zu2C1Ro%UxM3Vy^{6G`XzFosoIpV*Fr2(e8r>oi-o))v3dFM>JlBT1Bg8EF{-n{-$l z79${K!-lH%#AIx8`P|Hy=I3Ey$e_&@D;hBP_x5md`x+jq-nI8_dY_#{{V@FM`uaWe z;iYL14T7aSh!!8s8DMWxD%%oG_K@~w1EuXJFe2!(p41Xkcy*pXzby<4&Q{s2PxntN zTJdQurgPB@7HAfj_B%r9|6QE!h0*4Y4#1#bx^j$N9{@eKtKU;6)c3eqc=5WGMOK1A zah!71=j~RU)qwmr2RF1Yn!Jj%q&7aiN|e6y82zY$`ybGLGT!5z;nO03SyaAEympnI z26<0Ep1i7gfFW{38~=(34xPD}tq$oI_d{nGk}t<17|vs}r>QIDWj?2aF^ieEzk&;{ zWnVxXh>16?WNIpyX@)6Zi1Z=+k2yVVN-cf{wMf*cMis9@PCzGW2o3rb{kPgI6C6!d*wZ=Vn?i zdrZ8K2yapf+#mF9J3C-ruGRF>E$YAkP@~W-Me`QT=aYvh!A-+N&E8PBIN<5@vzFoQ zD;|EMOS-IWP9^%idJxJ_8ae5Y8^|CIeWfTuQol6F4tZDmDR?d+bnKxjntmENUx|rd#*?YH?HJF`oD7 z3#jkcI9JKOn_y4+FoRUfP7@{gmD2(CG)Q6v598q#5pCJ;^Bzg zmg_dMuI3Ac^uTfBEZwJBbjj^nbL}G{72#hU!y|oP15r>DQIP~4*0>>w)@l@& z?^F)?=#Nf6bxGjIRZ1)^F~oo^@(dFIyXcq{O7vvi_*SQXwXEKUpwODFjjP3F#iu_@ z7`r8>`RVcEJ)IobJ&z=T|9a`$wQ^*38NJvHdEp}08R1BW_nu{=ra{ko*i)VZ1ezEC z?}G&h|M2+x`1dvb+`wR!AOn_GMY~uaelgmS6&}hG=UI6O-8VbUN7S)h*J7VcDDr#>&b{$J>L; z%B`V=Q)J00DLAJL3L2C*g@p173NHHTUnz18h(P*$93^};5C+B^h`Zk2$Kti8SA|bj zc3`~`EVZhts9^jhp4~Nd6=+2#xEv9YCj62E!upt-W>Oj}*3(kJC*M}O*mtW^rPhY_PZ|32GnZlD- zdcil&y-eYfnj+_}*}dn&(!L3GG%Li$p*E1zGAvh^>I%23$S}fx!1a8j)l;9;3E6E< zPX zk~z3v05r5r39`gQv*RIG#Ne>c*}gs8!L0yhf)fze#_P*uAwHW|EVcWu$~n$=Ltpt* zhYFT6;1=j8U;7o(Ml!S?_$iZMX0(FAF=Dt1_ zY0HCYY$b38Uo9)yvdFMZI>P6U(YLyfA~m4G3n_2vNT7}2fTB7-C+ev+Hf53qj>eF>MvhB1YEu95`ic5r z*&QBEi!nZWaUZ~-fDZgCAg)>}-a0#cYUp|iIO4tUEzyAH;sYUWjb;b)AB3=Yy-}Jj zSBFaIqaQ5DyOmwo_@fq1o>Eyd0A`}A-#=R=Lmu{xsZ+G4?z^h*%u4X@aDs+b+Uehg zv${*+HMDD^?`h=~V{b9n)!7sRrs|?X(qBl z)ZmZ=4t+V6!1*U|V=JArGI7H}Z|>#YN;u{BjIn>ZT^;%s%ULjgo}pL(J$MI8)0`Z7 zj+$Cp!LOB5bNt+Xm!Igvq5Q9PNhCVIgNF*{R<7TwcZ3kQh(@m4NF>#uP3x3>hoqz`{kGos7yz5u z&g4##9jM2m29R!ME8Cr3^+8u3>?7SiyRY?tKu+)}a0r^$=@MrS-EufO6w6F?1R=~< zgYCap7gs2UI5>RuWC(w3!<1|=j_u~JBMiu)vYiCS9t4Yk02$260lxuETkM6==)$KH zpDyu_oLg=5&Sk#eINfS;DlbXsdU~C(m#~~DhE3TYKZ2@~Qr*i-ia>u^v)0C-LEH9t z=)G16Y*X7^YbY`v9Ltm58rv%m)78L8iI8)2G&QA3qfHGSz0qYMqIcgH8RX5G*2R~m z@~4Y^12s3(s^a9-d+hB*9>498y>DQ#5+3~Hw=7HpH4O_uyl<~~(tx77BP#lAwhgbM zx_aNBv)*GHux+1{3ECz9p}b^2c)@}nkR-_FE@G8@a=J*gHgRFJ@yx4cC+&VLM(gTGW^};OG*LQ z0pUDkE#&OdNjHA_zC1Q!(RE_Imc>wstvpqBU1HOsDTr?9!(oFKm$bmk!h_DLp*KBw z%kh)TLo+1??&D&+uXUPrv@q7H9W3^Pxio{A-6Gym?_rTy;uf6~u5WKhjX8F@y{uA5jblNKXCuQTLu3 zk5NWdySvk<%^v61gg|VP=U$H^^MO&D#T)nO{STTLq@z`Bd*3ZD+hdSPlrg7&BdM%e zI(84+Z!=KuYZS>-4cjkt(@P>4N_*ENiLoLyp-q%3_2zar(t%Rw&s5#5qI zoyuK?PxVFHYsY%n7o@VO1$u{x76LgdO7r7yoQM6g{~6@XeaPbEf5yd&BWjOj?jY}3 zF-+ZT*&)Y3;bTsx708kOW&ZlfO17EjwUACmJBFZNPd?1zAclR}%|3=aYmK=zID9co zA}d#kY$jnf{steOO=_nJUq$4))do&l)qc?9rPNjBXOkSw`N@mdbjcH)#{Pr_32c-# zm5=9E3Fk)eebE0R?2Fe~?4_s0LY|*`ojL-~8D_8)zJH;#;qG=&ICvhv`%0V&Un<1* z>o=Hod!_oPwQ@nO=In@Pkbpn5sgkzw0aw5!>?8IYy2u@)FOgh0B^}2u*F=BYG;BQ9 z-eqyo95~wvBrSI)a}){SdLt)1R+5I(Ug7j*CuCZ&#W~?SV`0kO0zA%3iW5d3T#BpT zv+2ssHoT0>7QQkoGLTG!Dtd1ktN2Lg}>2W)N8#-n5gl^O{aq(Oprav>3clpRm zhJjGxz!c&||7liXN%vc(GqUayhb*_lB?IvG`-M&)agD#45bi&XiSBDTM5VA~s}nA? zZ%>PQ5H>EqIxP;{9vQ(>CUUDNA5r;LO`p}8Eq%)tgWe6{xN$^K$j|2LhE4G}FUods zEBR!Vy)p0UV@I~U;)3%ohXF>hi`8cs5liZjkP;F>M~;MF*dzg_=%n zV%4?uA1|Oziz%@Y8_lsZ;s*j2oHrhRq>>eX?q_O{z8S%1;o|!IdAUV+ON%rtIL&@} zak+GS4Lz~?=g%KD9(}~;MxSGKV`Jjj&On%hM)PK1CawmyG%*l>EwaL+3JwnD=H~tk z3rcz%5$bu;3hvS}6<7p{@tXjMNZ`=rGpome$2%R-C_M-#>bkmL$a(H(-u5p+o~{7>E*Mx0E2(!} zdBE5At&!CI4vFl((3luv?a|;i`PZ6|$AWR>%*Q^7KtujmXZY~y4#xK!AcX|9})ko z$?cCA_clb_SxXRSM|4618-?N`77Mr@x`kS@{A5W~2O+^|SoFn8k@RVV@ z={w!}iC(GdSKOwi;3g`crjc&K4lw9AGt$)%bc_#HaWJhG4<(U(SVvxpr>w^Ix$Y(&YU7b7eKwK)g)jz=&O%sa|CQm`p%E9qP_ zZIzh%>KvqMm+-$-gxkH5hw(g8L6sSb?mxet@M*9PMzCh)?Kla&ph@3Mpzi%WqHV!4 z)=pBcIH8Ui;Mp9TD=v)3l=OZ-Qo(&3_Z+wQZ2#r&wMfp?)}!m)^QZc1rE3+8p>u25 zrP>$Ac$pqw1wJZ)!_VDTU%ArZ)aVk_$BFH3+{+TsT=2^&Dt~{9YR)KS%n%Uwd$Oc)iL^t zN#$Cu-D}}$@&AGqx;b)N`ZLM+IiH`3t-tp#IrSu?&b^O{md-DpEZlFI3Y@vbFI|5NY1MTx zu=3$n){!40LBOF{m7#l!nixafda&6qmA6(?guAO5tV~B2*bU4}?bODf!KY|-_CB88 z*!5#JYhP(r;zRKiBAWYB8pCyG-!uh7z+P>jvGK?=Ix$sZejs*GM^CyW(tT@yjf)Fs zVWDfqOO5UKuIC5ihC64MqRHO>9+5uz)2D7y!;?F%I2^mDd(*|svF3`d=gau3-{Y2I zxKsElg=C_f;s;Hbed6mk@P_<)@R3s#P4SY;L%tXpw`SWc+!=Cp^Ri0UD4eHIVS$iMOJS%s0ht;|X;OVyDVz!G2|=c)EV%U2Q-i=2_%DbK#ODRuK3gYL)g zc|!Odyw?wwsx$Q|20pQCUtp3XyRghu|7%Zuj&h|jo{XS!3gH(JfC;=J!{?)xj&*?) zca<#9-z&p)e8_VN2zlTmS*a=w5m1Ip|0`ze> zO(gZT^^_ffM0I-doa&Y~7|Yia`~s_M8pg&ky}kF7P0QT3%#z(-q@;wRCBQuHmd77= zZ663)ex-zfgozMiA{iSWADEmZ&hEpBY{!h22Mcu0`)G~M$2E9YPx za!cl5#Wu&dK2Zxr7qR7UTIcZYBjfO~{Y6>fC`q6Aq8oIq!rASVS?px*^=C@X@gu%p zX;u13Dmf9UK6cj~Q=0qHpn(>dN(_-&-ff*8-b4no`r}7Gvmpv3pEP3)p_u%=&8|F5 zF>HSC|1RZ&pKW*KWgk6S%h7LPO|87k!8({2i1xz<6k{uI!pF}w$ z7UbB7y-%U!u!wo{d^mXR)b@K!Y{&qb-!tfN*oYIBZXKi(d7l{e@7EHNy2@hMupgN>vh931GUb^j}p|jZ*tPhDQEqsE?`JjL^4~H?G{PQY`hH_ z^u_GmN8(Kg`_g{k)~FLwucLBH=p#3z2>e^zu$=eRS{g>mM^%+I)uJC#ll>-ALeBBo;|uV!DRSm z{Dvvv3`O5e=L2_a%9W5mVX_20BWFaD>84@>F`^4QwyddE1GqmSBl(rFU^)q`K7zB|^TKox%V4mq>y?m*0175GxN9TSMm7ppW=KA`yZ^wZA zZ8tM2>Nj3nBx)va?gtLoj-oHyDxu|lMD^qj6JkHy`&kBNaiXQxUN%PWeu`TE^d zna;{;a74U5ILztK5NTh7{qmukRQW~a8IM?pSOrP~ll!jCOBD{A@C7*Z)II&SGh!EX zT4@^?PGNGE=EHyc{ETJVS?czPl4ALA>(q|OvDj9oa(Ns|HT3Zr2?k;vc}6lGW15ce zm|@`NGQ!x39GP}FV#wN~hb10@wz%Tu9y4T5*Bl~g;Ky0`eX&iLsU$%BikzP|qSt|z+K z*xA|nJhz3oD{Bz%C?X=Fu|eWcsR4*w=KySki;GL?IPB~ra@4txI4*@c@On4F;$qvU zBTl^_u27ZC+b=kRV0yy_Px_)o_4ug38|^}9m@+*3@L~q-uVh#}eHf(o@$nWh*E_Jn zR1TxS!T|eNpr8np+{;zZ0Z=U-8yHi>!w}}qk^W<=6baixXy*UqQ zYP?u{qmr*H&q1@r+G*pA*Y?pH?hHH=E$pC^t$w~!VuKE36*8DHt?L{4Cz)`%_Z}(I zC)eGH4ZT{6)G3ob8)#wd7dOc^Qla!&m5O@Qd)FA>s0#+|cTYO!uDXi4Wwf74Z3bxc zaWR)ZGrM$UFg#V8zJI>d&vMV6(LJh9 zRg5>1x&_{#LND?2U$>{uIlR`SI|Cums8stPpfsv%53;bez+;}7`&Q+~eITbOfg#x@gS6<9 zf{@DkW1)1U=UK6ntb3kr#e%%;H*{9wJ6aN`c=JbctCzQz>^RBxL=xHYii0SVN(b&* zOyP~$8>9$je*Cr28N*<*p&i@64U?TJCB?M4P+4m`yLLcUl{qaevG2zHtf;J<$?{t7 zN|hzp_eaf$ZsQU1nnWWlgW`6C6kZbvddp~a;Zpl9uqdhpuuQL*oZs178}EFtfj(YA zLAI%+(=qn2Y?6)KT&9vYcevvC<_8{}#Th*zK%(PY795ygTqNeD&4u4h;8cyMC6~3b z`q@s3is#G2b1)!hQad<%4rRvsOYA?tV&DB{hp*t!q5%#M01cBezby@!!bQ>(20X2w zU0C#HHz(%dS%d_>RWZ<_{?2%+@J;A`U0?{099x3!)pG?75TYB<@8cUhKt)Xr- z$YXD#y2TSYkF7Rl$(w6j!=5)5Y&)Jzwo$xtZX9Ye?9Hw8=JTKLRbf7rlBeo}R8Q`f zUJZLbsst~T%H&P=a?0f5yH`o=#c=A1g_4vC(cHbh#ir4AiVU6U&Biu~v^xLXA)1dm zG%53WcJjN)tMkCkVCL76Q)%!-tt`>*g0dccY`?C1AuOq52NAKumm}`WW8;LI7Rnw1o@YkEsKTf~J{I!-K z)W|=YJ;bT2n&pShoXG&`l8Jsx@EaRZ28UBo^ln$0`FImH*Cqn@NDQ6Xo}te4Dkdo$ z%DU90vT@30U4IJk%l2hVnRml|e*uwMclJ^>wXnd1p!p`oI`V|NPOYHZ-+ZK@wCNK= zZ_|0Ec#}goa=asWGxHatfQH?a;GZr&Cj zN~-QaN})>r=ef7|_?!N=XVyM5IzPE0Q5G9r54DRhUnEQ;JQEZ#eQ#Ht(r5H1p;V!~ zoIHx1Ia?YHLp7`z2X%gMBVm$he++-Y=Xx5e!=1!-0#=c+>7#k!&4)YpgK8&Fkz}0- z^VWglU)vg+es7yPb%^9XOJ=ZhY&`FlI4+MVQoD7k|0S`R_uTH9(Zvz2CjWVB^MqgU zDg)cq9X9M)-r9LDLDSp#iEKCQdZ|%5@eWoJCk#$6SIw>F9uvt2u(@Rhv6XKOM zxX_}Dp}txw>Ob|rNnNOF_9QUSQVgDUZlAxk;qmY*ltXpdd|LmrS$KyHMK>^gT_n#d zzpO27_rt3}V~9bbQC4&8_0bBOA1pN~*8}lX3(U z=h}spQ-5Z3ltQ_#Lj|A^AEYKpbl(r2akIle3pFQyy7lN|tRM0W`Nh&k%k$}#2b~&e zka@W#ZHABZYfa^zI^TH-94_#BZ*OlWi4_&N~R0N@!-dCcgAPj*RWkCTxCiHWx02T7sEz`ACmQ;HO)@8lS9^+6yNAx z1J6RuFfX@P+sT*6j-PnVcRp2-UfE%gK&+fr=WQQ%vyltmK{_&iVr~#+d(v8INAO{P z3jf$SmhjX0x)IWUkXEJm=HxbR&amI6x%+rDw03ROnAwn3tE4 zX~X1C<@&AiG_I@SRz=b*yJ)8#+D#+J!Yl)Y1^HnsI9xlgQBL*u3rh~0*dbC z)k}dcCdaQuwhJ}7;Dh4R?c{JUG4dgee3S=un>VNK+;q?g6#IkkdHLeHnf&rjsU zAGdVgS@n=%GznZgjw@-8yFf3aa)GbAgYD$tH}6-kvZ>RVKFR8$M-4cXD9%l9{=2!s zhwG+DE!1(7MUiocXqH9_twmEPg~8w{{ru_B{`L(zs1x+GsNhLvzD=gg85(y(q~>Kz zy1z*_&6PJM1ZzoZ(&`#RMFW2T$TRc%O?C&Il^&t-jy*j+w;iVuji+nCd<=e9SSSN0 zoZ!M6lfD>c)_!NIjv)uMBl=tR6pENB2}O!;K~b!bQ|cOz(w;|{K<7p1x=EwA$k^DJ z?xo0nEGH`~E{U_6ef)ui?i3kPEa1FcK!A?+(}CegLK|AVU%yT}6nbng%2h1UMD(Fr z0bR;iCK=EE2+(El?90D;!4Yr*ka8T-r=sc)A7TOAZ1txAWCHR}>vD7bjij0^y2!PS zE{~n&IzRSFSvXAZ^juYp#{ytTK>?=_6>Hbno6TnoJ=?Ke&lkVZdIP)~;nyBXy>BZi zbFtd0k7<~RU6wz^e6)N<=c+0W46NuEQH_p{BK)8+F|#!Aimbc+L0R6${C?@%TXFAh z$yCqcs#-^0R{kEJ_6>LE=dqR&%^E6d?2I^+B{VLB)a|~UuE%59&lwdlL)q>r-I1KNbKj)25(JNy8 zPBQmD?}eL}x?&r?#3j7$cIT)01v{&^G&oTcsE9j{c&=qqyhs%w1+^W{IE@izS4qsX zrLri~?4zQO8&3FF6B7bCR_Cp{St>3`iHIL1RZOP4UFOUR^(M;WyP=zjp~D3gXQ&}a zFyg;-FVe5%?%9=g;waU}Q4?>>N4xnA3kfjt(u{gN>p#XB)ehV8a@egJ9Cf|sy~`|B zy(-*LNNn3I@M|mTlS;O({9MEBpU1YPouJ9bq3)aGQNa;`Q{qCgd9UI(>%ie(8H%7i zsP>l`xWxS)d6mwtW^By#cdPvod-UVI9zTBJ^<6>^^uaLDzt%j%$%U9s7rgOzE6swX zWTcz3XJutY1LW6uPBu zCKpN7PH6?MC-<|&@H8kjG&KAjyyxg!Z3Hl}xM-D?l{Mi00~y%`a=~G4#C5N|r&Y1? zugCz*0x6)ps;X+61YNZJ{6e(ZaR;Tat{FCM?dDhJi-G=bx6SXn2Lx*u%IWFRa;nfA zWh!tE*i?e@O!HEkrHp(6myk<}rI$V61^cZiCAKz&eYe}}$iaN7o`@B_g|KEwv+}fK zY4#T9iqgsEbO~2>Y1VdMBrdqmqORLb5QzYw&m}+8n}ZUiAC#NEkcbgK0e z4k=ts=-GHg(K0gYY?yK3AmgHOa#Ym(D%S0aR7IhYdwribuU)%vLQYHw}Sio%I-f9K)igGSR6Rk zN#$Os7SKn_CnhD8$%bq??MxjFS38~@JcH*^x=7o+BZ`)rj}MDf#TqS&zb`Drz@ngr zO1_ha5g?Gwz;v7oUlXok!A%u)<42pRgyn_Jb;fokQi=iVC$;A>8aCh1@Nx|;%U|Zf zHtU0BmIvP@dxPSPTWgOb7J{{~9F^#5FzM#M z6xF{{k_^;RRJaUcP^mq4=<|WoxZj>7l#a+fY3V}YP48=-F%F^ogE+WhLI-_J;YF@^ zicgA)ihedBCAEtUyF?SC;3|Z8t=HlJP<@e6NzIY;6S0B>US`|{uT^(bl4DX18`Tk;}Id%j+}P79!7TB?P32dRP~PH$1r=4v)? zF$Fd4(hPnahGT+Mntax1pRFGC35(u|3B`y{+wIK{31+isMEvd0#wlj{frL^i_~O*MAZ~^tL`w$KDPtzs182yedg5 zMH*6{?g??olh36I8pJX(t);VkJUn!J&qM2w_`z&8Y)Tc!p*N_+;E|0{YL8HpI1Jh^ zCXIjQa>q!?x0qD=ivkUk&z&pdxoB%73)_H_-=u%JrK~~hsb(#P#YNJ%ib82Qev9$P zlR8PZ%0YKe`0w@L;L5i<-dkK!W-ExopkxT zu6s)`cZ9W#jr6}qZ=?V3Zoho+XHi6a+Pt3J!>V-B_~Fd>i;TX1uN^x_MOD=-xaiC? z%6Hh<+IGKXC)jUJF-0!$z~HAKOPc8r~6<= z89HD+4}4?zpx+b!)r}O5jA*Fl0Ue37SbaE}=n#K>;}i9az{)>NAXFSs9Xdzng6m9% z(14qyF#|D9)zeW}HqPIwekk3*vUPruYvrC7Uk7ax@L5{(p*B^Ag<~mPT28qx3k7~I z_~vQ1xo7@zHNzkOO;y`;R9-!24I=0o#xnWA`qruljYURpJ?cMDNmahorXY`}AWla7WG=O+m&|n&qB!Zs2Ki!Gu6A=dP)m2LsXaj;Wu7X^t z1{#Oa)>r=CRD%MwJ7New%_}IzucaQ7J_KLobnYfk?-j!n`1gt{&~3X3v-CSB+vdsL zzfTOx=zj^MDmC09zT`^L2aR}>G{Q|-wC02SwE z){#bRa{>`Hu7WDdQ3_WP`jt4bofm2iiEnXSBA0G4^f(;x2qnGoUw0XWcVh_JaC|=a zV{YRCCw!IC3N0XP2NH?I!p9+%o_4r{1>$Z^hx-5ZMgv7XQ*>SF;5mcZ2}68k1f_LaA2K}MFH=fJ?fi9i0{N{|CGzUO$QMU8M1h8Xw<-||MuT#H9Q!|K1Qt8=jT%w@5X`b^>9LB4zY;ud{`2*|J2A80`OcMt`w#yRN5(~Q+(^&SYs7~y zl69I4khcnBPPK+h%gfRR2J{?Sr12OQJhyHtH(l881vdg|g|Gd^pJ)Yb`VvUr7bbIA zqGS7i?yLl>OBi}`Fv`IG#3BH5Opb*8-(5tIP5F7~fr>isTk8c~wg>MJi1&KiWZc=& zpNB@ah_5_;UPr{ALVtL8ST8fvi`tiw(jp1zxuzIL@NPGaBXebf@4a zDCO%1Ec3CUgJa)-D^^1RGYcAbfNuJv5LJegQ-?y4eoGFrM{|__VpJ5(8#@9wtC<2l zhxP3R=I7^g>gzN2)h#}N-AVn~(Mo-*0*%_xURcv5ITM-B*Y@g6u3w6=>25(s@^-zt z6s_`_f^XkM83Zu}Uy}>Ij(4LG5H;Gq1m+H96*WO_+=io1g+SNOsi;VF<2LUYE#Rc2 zq`Z4S{7O(h2Qb@$g0R>nzcoz;6^rVyntuEPJPdmnQ9%F1Zwes-%8cb3Wc6B9~;^4wX`=Lh?v;vZ|xuAjuwEF@BeD$av+;%EOyW8=T`EOPk|?nGw= zeW8Z;z1m;BO1F6Nfq4y5tyiyJU4T|$K6@k$h@?`0{Y87Sa0kU{kUN+K57`8ltF=7R z)*jC3(tY{zrA+aN8LgPW@W%eDx;oL~UBU|DBqi)3ZDl-5_E%k4BBs~bjt|e}Q2WW4 z@!4()LF_N{o^qGTk5u|D2q-g>uGhPZ)f=saW_UGX*qLlHh5ZR0U zE{ZtuqLGyXno${wk}mRkwzj-zW^od)&L3iq%P>f;%GRd*K2LM~ zPW+)+(tyJX9np~y8A>@g%~FA=Ka($((v1xx5?~7gVV#`_&Wya;T9NgLOE8{xy3Tv; z8uLvlkZqrT*(FZ0nAtv@HSSYiK|4`EqjrvtS-L|oO&X6Ts*a&?W~t5tE(GE zUWS`>5PJ+usF}XVV2UyJnrk6h+(~o(D*>~5Id!&(%?G~_Sjk+!ObczsB2LjzFj ztH)>dkALGkNO#l#qMRnWqh>rXRi(f;8z+E;@F;V2^`I#MFMxF4^P>Je9UW>vQ?>{= zH+_A5e{GQqrq4TxROs6^@d$>qJm3a@6PfBi#}LqPHjKE~ufQpUphZNz!y-VueJ4(Y zNEJr0S$E3EU_aF1K(W!oHxOijm1c+yZGoAwYTqvjn{dVnrb-i7rdQtlpWyJwLWyyH zjz8plmHGnztMuJdjVb$b--^x_E^NnLN{T^z*0UrsX*08rqd(VR>RTm4DB4Zo%2iU_ zoXX0i(}{rrsf3uIe2gM(f+Fq6mX;Q>Y9f)1`t2O;Li4e8$meHcjNU!$Xvp#(hAW`~ zBjIp^+_37sODXr>T1pc>ZOow$^|dtlZm()QMY=RWAO1x;0#7C{#3wIb;^wE}NXx*S z8`py3qR2MAauY((@B{Zyf%o3gIIK*QZMQ-)GZ_+7QqZ{&IAPuV@V(PK z?QwG~V)V04AUBt<&tUcF_RkA(A7u8=?-zW0e(lWndkCYJHt>YwpQWd#|FqMf92ia0 z&n9`-G2PEh7ti%76!GK10wJwZen@vVOG0e{L|UL=1D7{y{B;5ps&Z1~3@ z{vN;IP)+7oOa3pd;pQ^ITf0O82dM>3njzjA$2l>GJ%CIR{0vb9xU_L)vYerNe?oIV zZH83XT*5^B8}BnT|6k2gO>Ro=D^~zRY_|U_E}0eD!t)-lka8aI6;Vicglw`$S|bw_ za=#z4@~1>{GT^N!6u z>Dh(M@7D(X&3#to{18uan`>2tGkkS~@y7X(}C}Q9<~XgyHhHw!s~V zO!|A~kKaMu5oG&AP$0&$Pv*YPZ!D6QKH@Zn9Pa`5%q;pcRXq72_+Bec^IhBEy9fWO zrTkl`t!h%&t+>2J(~|g=G((_o010iV@1X;nX@cr^|HvSFHb^&bPoM2nkgvgx0h$Dzr$L*;osP2`JQWPRE=&nw3nz|^x8%~sx9J1k#a(XF z^+zE55Q?%=5C6MzL05BLw-xAq@EwpbjGq;m$Po+;UcwtSM&I>$+{(eNs`nuiihl-u z7n0)flJxKXN*KH$3^^d}Yf$G$e&U{4Uy zH5a6kdlB)4l5TQ_JxZ()_X`gi#fnE=WErMnr=(Cw%Hjb6%1i=gjb{X&4fe}=F7~wE zEOGkXv#~LKrSdSdoP0`%zwl2{GEXE~{F4?6{=diW>;T;N{S({HxQlIPRImO%Oq_3B zfFSsV=A(HhF^G2NZ7@IAu6nSaEgsWHg6#6r`7X~wdiTKtierZlqz^xt&Kjj}L&fOs zPBB7*9+d+>PA_gjZRoZ`H2|G_N5R*`0k!P25<~6698bN(W5p3&V_ja=moqE9w)PW* zR^OJR<;W-q`u&rWOuJ>E-W_;LOtKbGHcgS#O-M}74GN-5ASlHK%N{S_f6%MNym*%m9J*vN@E~Qk)5Z zTECL`Bl%thA(>Mzijka^y$6n8qN4)B0j#7;L7Z3cp?7-p1YU+=8araYy5BDu&e1jjMj z+?R!P8WM6v)@zwW&27Smum4tAb}e6%cs)pP6rBV3anzSFN-n%l6PD&=U*~f8e?1@? z%PT85KJ{?U!Q2Br_RD~6&xTf|9BT&$^m*qwY&KvpAY$VLus0hkX16C4Z#w5egFM7?lGpqj|$$&*LbqId4FN!UuS z+@c`_yGs~l2e$r>ek_?&Z6nf67FQwsurMwT4sNCLyQR|Yj!>U0<1t?jmi7lVYUX6SuM>_p zbqx&+1X`zpQ8$I5hw?9AkQE>%@c6^Q$P&Q@qAWfE0od2iYbbhh^DJkxuWcVrZ@KFR zM?tO!Y7N@?7=d^-fD5Z(|0emCT<%QD{52$qcbVLulsBCa_Y)}_&vh6HB3PK`&E+=! zf|fEAQ?;C3bZ>>;x6Wq+_Pc0M#pQ&qrF=X5gr};Tw-{&tPl@Bd9^Lshhh7Worb8EL zga3!FuYjtm-MT)Mbc={|DTR zVGvo1R*n7OFuwZw;)@0=DvF-|{u_$tSkGGBfT7GUA^sp}B#ae=fgmD~umCdS8YIFI zk{%4dN|JC#z-R7HCTl+{_!3kU_arg^F@jg`qEVqX3k83YDkmg+VA%@Gseyv`@slU~ zpk#n@L#+pg*-Tm>fe4;E*EAH=L<=?|Q?eiWWIkl@ZUYBmj*Pv$8e{gtEEJWV3eQn6 z&AUzHzmZ0b`}c!jiDHX*9phkPzCm69V)YD zv}Ol;8@Z4kIXrePNaPy;zlB9#UVa{Ko=Sy3PO>U)vTDmn6trZ)4Fc+_$(7;a%$yu- z6l~A*f&#urArOgbF{2pQU730EQ^gzU+b7{an>YrXiG>nV z4szv_^?PLBhw&#!Jfm6kT(e3W+?PBT;!a=y6ohlKDy}it`S{?t+PGcs?}|2hs+@3Z z6uC}OFxfnQxGAR4j*2mR^<0*+%Q=Y9mR@U9L@#FLW{QflcF5j*yA=6Gg~*!o z_G?*g*vS83q-P-1JU`!9r!MdT&zEoV^$H;7b9s;FZ-3GtaZT0Z>0Hp_YCCJi4)aF| zfI$NST+@kKPY7EVd3c&3gS{#+m2Thk;^$Aj?@6LpbE8PHWqg`Uo;R7)L*5263A%fF zd_kvK+8N^@qu_?8;MIyPx^hPf+i}7Uu~9y?r>gcN>Du7OaxtOw$ z^8J570JZ$cbPTq4t&9HTZG8V97yydPNASusP`gRP^G-qAq5VJDF!58p>=GWP z)zXEF^}c2=i*5D0mOs}^mLSvOY2<)^KtMnMnkW>^GNj-E&a+NHXmxe<=Xi&*VVi}8 zh2TtWa-|&C`D7OeR01sZ>AWQm=J`Yq!uh2TZ}*Q+7J?*~A4!rN~Q8k(VC*enl2lOP7uvC+wq#^)UUzg`kG#wxgxS z9T#B!D4PzPiG?tZCr7U$%H<->Cm5gvQ4$XuQ*rb|`)b-bX119m+ttR|C|Mr_+A-Cb z@F#@D1%cD!aH9p~1FH!}1e3t|2y-Ydr9Nd=q=1QCT|a-mgo7wJ{roHVE}6jCfQgd8 zd8$kI(xDV+MGiG7;W-@;deuti_PLK^3|I)jVGq6CcV(l zp|!7m6~%q?E)$v01RB@pW%cjN{cZmn0SG0U+EKPdFTs=nX2p4jihEvPUy;cMDyOM^ zF)4%>pjdQ3ae#)pi2F7-*JVFS*R+h#oE&a23yaBgh65DNi3=AlKy=1NLE_c)J>e>@ z4NlL<2mwk2X3aKp>iFaNqC%T|5#b5M8Yd^GoXVz{OZWI3r{(uog=OJe!wB2fA3vI* zqIM0E>rs&Y-Eh!k;WLXss%G(eqovZtn}$sH0Q-*8()b%k63LJ_BJiSjF0k7yaA89_ z7cwf&E4xQt&L%|#k!Ul?#XF}F1`uPjc(rLN=7bNuRzXcRV7CmLObmkm10{th?6T1? z;LgK{tjWJ>8tL^NpL!!7gM5os;ir|28pW%$w{G16e`fz~%SH$(z_Fh;*8C~*#>h7zToiR~BJ(5MeOO^;AzJB~T!`9(0V+AzarX z{_=D0e<~NRkMI7KF-1s9`2Ra&;;vK*$&fOfk=fOakdd&yQijwge8yj~$K_rXBCRxC z-NetUZF86~(hfa#>Tc)@H~aK(3rbHn63B;S2g=wEb3d?Ofqc7bj9zD$OIVmX>q*EO z4i3)IfVkRYKaivME@G3}oDB8$Hc)WME|+L?!=ro{LSHE2wt2DY2rLcmMm3?ZWsFwM zKjt8_H=cTZIr=h8@5?1{+!O?@v4hlcW>Amo<>h;6JM592zU?!-ZU?f#N+{(S;q6J21Y`3Ug`f&SO( zPQ1p`%rYt~#o+j5kxunSDn`X3wSGbrIX*drsFiJ?hx1wdpo1O8xws)HBqYlbU5HkM z{bSLY(gf+fNW{+}NaB$9C=~!h4MEWVg&MLp))B~>%zqjoY0*7_Nvu(_kPnOG%t63@ zNd?)-?%sqA807cMGQ zKrHLz`=U8v8iMtAa_l$e$Rq&;D>eNRIsw~h-p!BpQvQ)Kd`TgF+Oe$u89}fL;d2vL zs_as!!NeM9$f>EswLi;R(D* zSN@7mjX)PXK`?lvDZb;EOuqIeR%0;E9CeKi53{Ja*qHA;9M7$9fs5bjx%_0dc1slgQ*o?xyb4!p7O!hW_?5jv4t;vmPmjP%D}%`3P2I$|FeKkfq)HL9a)8IGrx=YmwnrE zSg=WxwZz48okjHQ#v5MotDK=X*XN@d*11*z4X1=}fJK)b%#S7|Ouj8*h zqByN$Wff!}Y3Y&9+)4HSZU)SWoBYR{ZJ(8@74T$8kbg99+Nx%yp+x8k$d8Tlt;5U8 z6o8*G_j1&J6Dc8tPI`>vO!Ey}8d>P@x9LIY4VZzdg&E_-tIq@&sE_T$@7jpEXP!TJ zKV9SQ&z6LsXX)Oz@IyF+#Y0{2GVN`q=w+MR+WG$=GbZsYY;A2L+syp5G$fubboo$Y zL4>C9XF{md7$`dLeS2)1fs7!g5}|jVdvxQhulRtw=?fxPmbGZ=JAwPZ->*1QBttWT zmJ^zAsEm`1s7L<+tQ8lW0c<6UQimOue*ERV7S#BqP|VRuxP6}RWGzI$>vUMA-%0P(O8J)ZGUF>h;cwkl|`2oCD(h*=pVGCaie~}21s11CAYOV{4r5J4Re9*>@0&( zI6>`U+dtNVTSmmISO*f4ANsVtwTRde(Q^n*k!iUIZ>Ry!D;w|huv=wg7}jOMOx!?d`x;|b;B!vMSr+#+gmwbT-3ug4PB8 zh0pO~qPvN=bJc&7d`tzJ5$PKv3~b$T*jg7~f1;K`G8hoopgl;{duf6hYsJ?e`_lam zd9Mc0@VBA_2k!#Hab79h#z}kj8^bCWc~b_fM%XX=F8?e`w7tdu=t2y2r=QVx-`%OI z_2f)!wv)Goi*+aOCW|zwUXdnScTVPJ`KV+ErJD&H=60+ni(zc}whx=CThF3z!R1;z zOET8AG^K$fc>N3t*z(K^VJOr_Z%w@?$tWY}b|KlpGt?(Ow6Fq}p7hy=SJP@Yxyp~x zPQdW}m-2h;$;|l|6B8pupwsCKjgu8b_XIoQO9(}+l8Ojf5!2p>>%q6d^&LMi+U$Eh zzSUt-)33G`Se}-3o~C_+f+PHI4ID(z_I?{Kmk&)?EoKVZ4%GE)F<2-O6XsdUhOr>6 zp`AexSBzH1^syLt(>CsRRGl5qA_zV>`N8fOOq7cBGqhbujZ{~VMeUG=kk*<2qLNXM zgqjBYZYwJ*hdiMuVL)QdkAKJX1e34+_(xIP0E^uE%u|!HKM?($qH)e+9#mH<(jRh9EevUkcf=TVu*&_yA zA6Tt;>Zs^YLLJOAsM-1WSE;5qw>|}ChMYr!m829d3YNJsKkaZS>Whg`in|KV>h3s~ z%Ibo7M8NSGUwk}I(}MW0bvI8D=OTt4RJ81{&KVWD)Rt}b7!kfM*IDyKhr{fv{52p7 zVPW~zW&2)00-3=)+$0>Ku=`b1-kDTzT>fWJ1hhDiOypZO>Be%?x9K5l~ks3Eqs%D zzzXgD{jgh|f9gy$DFT(@t-Y*u=F7bXWf!K$$094MhC~9QxMgR!*T#t5HE~7<$!4(b z6t$QP*B&28y>LC+4-boc-BHT!ANI`hrQqefptZo!A?utPJHd<}&LRf;PWI_xOhNE@ zi#!P?I*)OE&NNpsh6gLcM@Lu^GfgM{b+sQRTt$*e%#K>n+C(=|;Hto6RDAPgbox_* zm!#M64|+-KX@vr(T0&u62hV5n8WJEH9r&t~Bfm{l@_7}du30PMDT?0vpc1m{4wJi( z$$RD`cV*o>TZ>*RdZ)!QGb_EP00y7@^6$L`CuX+c{})_umxfIkr`y=QBu1B;=cmq$ zE=w}VHpa&(W#Hrr_Y4>yxr{2156)X-fM1(-iayW}YPe-R2}6rgtMLBJC;EDIVmP-x-81-6OW~@GFdv zvkr3lQV1X%cYS)^6wF%74bc|jbT>Px4SEUjcVXjg)~{<~x!b`T8?K(@`R`@TSL+wa33N;pXat5`qmulgwh&TUK%1v0zUIzo!<$ZF?W_omEgb-QGx~fm| zDp9D5yl)7ZMAC9k>T3#ey;0NSPpIgWK1!b)F>Zxk`AnM9fICUgR`})cCu15Az0@tl z5hSW}3d=?}E$h5zTPSD4;R+)Pm1nCvG+PN|2<2c9Q~2gp*%>Wg{keA)OgmaOA7sYm z7%fxotOWw}!`%MOybaH9vHBs-sPh6k<>VR1ht)(_=zVd#^xH%JoF%)ui5Mkk0>!=0 zfF@&L3N#k=QM4)=YPgqqxIVlt_Wa$SV%8$_`AEY+B#2!bHdy*WcNGRgse!c3dy}!D zJ&t8r$_saXAa1x2AN6J~dp|6CejVfKcoB>CA`1Z`x#X5b6AzYNsX5?jl~IpAp8CiX zUksUh7DCe;Sb4tFchJRqLX1{ZAo$kS7P6c8ARw~P^8R~TG#%we&kn^&#Ip~0_B0fo zRKw{D3>#1IX+qW0e6^jN1chuz{1G+>1Bt-RM}1t*RiECMy_dhIjQfL^=cV?*)Z>}; z?h6-ZF|%ilR@aObFQhrsV2O?nP~|wMX%wt#+e&m<_3_a>C0`~M?d>Co7{rYj3@TpL zj~9_7ReF!5u(C zD7bx$9tK4^RtzsVmUs1!`Q@#>DL0Jky`Ae&{*z3CL8#UspES$@8Y`>%V@R$8RL$nA zyxck*eK#AY9=~fJXy6L;Pm$7_!jCb?k687d85Yv2_?qVYNE-h zcd{b}KW^)L^QFuX#6UQgRy8H0wZ~lDb7PRyUiypqLn<0r91j)GdpeCdVP)Ge&F@<3^?C47BMYPf2;`dshs3`4?%Om@efUaGY%ScSa#8dqy4lxdGI)BHsjNM)M za7(b@XqpFaZ^loP#^gHgr)ncD2mR#LoX7sF)Go}B`3HIA^^Lrg)@Bc`UA-1aAt{uW zMJX3XjQVVNHKGLb?vGW8oxZ)Jhd#4GWm%Z9_nptQSod55M-@NHPWYHKh$a zyyP{>P+fY3FT-l!!Z?Oipj+B_&gs`q@Y^d_LAIsPeV*24<#W5%*OIxWU`K+dF2rK0 z7~P-}(vog%3#uz*z(}Mz?)|7O5d3%>)0r;1FTK+08CViQaUU7;PVFMh?=&uX@JSOw z2EILwy0-TD`4PM}Iw-6J*h_d>OcQ1DAC}4Gvh9zPSO_dcCO>>>NleZXM|w2&81U;& zG21>aQeUP`>nr32_~5EiH2NT{a-#8Ajq+&fVCiuP`GHv1abVfqjXl;oe0zr!wORJy zZZi@Qb6b*By5L*O@W7993R2k(f6n9~dLCz8B3eSGcshy;z3X$RFErJ7XP4)x;XXVqhE;Ce&{%R@-^>#sJ)_8Yf z)M7jQhelokHq0ze{o9f9Z3Ws9Hop+ckc_~A&E;y1|SpD zV0iNmsv5GJxmt3cG%&veBTYCx8AERc^9>E#c>@{lQ$v!u|H2RySzFCS^7$AcZom;K zmMaubw4aGj-EG;&HK3JI(m?RBJDWq&9 zRQm*z0-9`06iGPzkXQf53+j1a!)IgC2Q{9 zMb={mn<`dg4Ad4Xt)@V@=6wI$zOvIM`gr5>+aDMJ`hl zk0x8IquaQjuJW_-3_8z1ch|G!n6 zAizXJQtH_fezx1&!AFy#!c%#JkM^&KZ|H#?LSKqq;8{Fro;cDsX5Vs&$+1JATm+e03(2ZUiMfznh-3!AqZO@*hsT zpr2Yb`Dzbh7zCG@o&hhceoX(L9$Glkl6JCn55rufi0Y#VL6SX2I{qB?;!)+nL5XXy zQY0&KxK8RV2i@`_Qt;9?@U-~yaZ^7Z*u*e@S)2$(Cgl;Q`2m`5Q&Mpm;L1h>v~bYp zFqM?uyxs!3#zxYK0BHC~-xb3_Tv|rnVBcRNDJ@j9ej9&{c!X-OctgX`O|$PDZMWYO zxh0z*qqfyS683IQZpdX-Mia~VhK4rh#*glwUpu5heL4Qgip3G{pQXGxmLKfTh@Bk| z8G$TZdz=+lhwybhq@!XvbAfU-<-#{d_i-n)vwXm0OWhzs<8jLs;dO*ULhSYR#+POP z*_BE9n-4bjJRWT^qM$WL8O7!p@$lNopM#);3Z>@jK^N0%I0X&Sg@?6V7cWZ7$jIm| z<6*O{j2=kN`hM~B4*a7d0%BSa$`NGue*?~E`qI+U`bu#ptRevxXfOZ(0<)ZzT?t7- zhp}I)V}v~j@cp^s)ovx2RWNF`P;%iVp)Sw01YX6OTsGNdax;P0w`q~>Y3f`MzJo1k zDXtWndU%nXeT?Cjdj_g}lrR3dDO>J9Wddw%u!qN~0LVhE6({L_JZb1~FmmPPt%IXT zOpI%#pNo%v{18Claoqi0X(RwBQo`80!#0OzFhi%q*9(Hs);(vM$4=<061c*RRdl<4 zsM>&0S-Wsc1ms34&2tas^84RrWHRNg9(dGDbP_x+W`4P`104%8+2(V1&u#$bJp)WL z=&oakLPm_EnbsVLthcJK3yt`r|`d5!V%!*AdyB7n*S zg+d-bP>E5}#nW!*z4zHRm)C+KUlT*+?shz%Furl|Wv)^gU1zN*7Tkx`JbUpDlhJUa6)G9>o27|DVkFy@t};ExONOD9z`H zg~xFRNg2whc^}R&xLvtf`r3UbWAGHIv#W4O6eEnDu`kf{Ny@t}dUWgPob<13<#* z%w7_(GiZOm8BZjp$5(^EirU*Lbzya%D>&=iRP-kQt3!uXH_H9QHRKP)3s*A~j;Bl%pDuu zM~fUiqE6B^40lrrLEBkqUjE*B#!%UCRdHJqfi)Z|cAT5(uoSufvLvC>X+1ypxT0%h zIR{Q*NwBD=k71f6`# z61#(q$2mwZQ7AA$5x8xyD}#RJw{TeRw9X)k$0Sle22KSH_VwfeU@}%OA6Zky%CTI< zSVLQz^#UW6vqY$vU%lfEDWC!C42S0>I!|7NDOy53zbox>Hqhg*ik%X`QBZ-NVn?DL~q3-Je`u&JLrV3T`#G9ARt{MFFV59*PE7i?gPMh4aU zljZiiJD*IqD1(L7NqtxsM)8 z-nP7U0qiNpjW=ih>}fxYL}Yzak&^0D?#N7uagRS8FEh=$f#J|8bwYPpD+idB_itq{ zYq#Ud3Mc}u4zX|Cm`xu>u>ujG;OSxy3v~ylnERijhjuRA7Ghak+@lc%+i{_eRK(-bb-5 ze?raS67W`}J$WIZcIOT$yLLtbbc7M6Iw%C{1fm4~CbhMkTAq@Ou)AGJacFKp8~{TC zj_42|i8W?qWU#GLa?9V92eAa^bCh{!O4z`F7LX0WZ?kpo_pUG*E_CT&U>g`IuQPB& zr3WUSC(9aU69iIZ@WSkU?2!h{M&7_LmJ(^y?)!<+q?JW)uW*6 zu5#{+Q+q82%0Y~N{Q%)hby@mSQh{OMsxx#dji8fhX+=;P3X&g$9(X|HST$DgAa{45 ztTq5{G|=E=-*uZE&Y!38Ousk{q=@yso1El2e;H$+yIhL95zZwrE5LIh6@*K~!XeD# zWo!FvMr@#`|p3vv}Br2tLGi0?cT-lyTM+ff-YVPWg{fT}@ED>R8v3FyCN z5@KU6EG~liVnq1_@R7}n;pLeBpdU_qXmVv)$)C}f7?N$HWaEG|1H=*JlsA;#M|qyh z(%=G1m++@sh%hwpulN-BrNAsT|B(~|oKX-DyaX0PlIRojJ`Ng1t5p0fE~joqqin3>r*a0IsrI&o(rAWDK61_?S+;f(|MCk2%x z^^M_pn@Yq`cLV^ktWo?+ZtEa-#nBOM=UR7o{e$g+YV!H*ZG1(}eMB;->Ji`w1+t#2 z^|k}AuEekyUEC#bZ*FT+_~5K(|B zu)RdA63_C^UXX)>4cOiw1C<4GAq?h3)hpfrKV070UCcOrXByz0g3buqE|ICJcTRp# z%J%qz0HeR>(0P(=K3v_azReRcqzIjsynE%kzS5ASPuJzkDUlk6&mYL_kcdyVR5BUWC z8PI%n-&tz{gKlliI5tJZ{tH$(Wz;O$_!=3WR_9Qyr?^(`1Dv~OryN9pCTvtZyii6Q zl6dh2cfD+yn$c3tedU2agrs!1 z#*SUM4mh1r>p5WXluu&9XpiZxG&z(HFjJ;|33(>z8QRpQYsbLY8KJtNeBO-oqI{k` z;qi5TnY6b0ANKmFusVP$rg)k~3icp41uf{q_rl=gA@1+>RE!>$DEO$tS(c{$34#er z-bf5I+f!6_4vzdd@Y?2nW86^yTJ!GFF-B_Qw^4?rBe9{^`B7}d+Ez4pDI(j+L!w4F zh4S{|8WqN{RA4~NYNl=C{4!PT#MIpTclrUB@i3ve-Ze1LoHt37EAHWOvnZmlQ3pH| z@&`xlzXw%jxn&Mo7C3VFZ@!rSW0%>P)2)4rJCzfqO$!|L^G;RZ0+N2Q$m(30Q%hxX z?ex)4mCZlzYJLFcP#y-3z&uabTv7`b=GCbcA(B6C&g=ns2#2hCN$gPj{8CB8&QM#U zDKFdj3`gv|c(N+0K8p+l3}Gc7{|D-X?ag@cwNh}ph|#pK9#4=#eh?fw9p<5K?0XKE z8;G9T1WLBZhM0H)hsd?Y00cy!i#R98#Tfd@gAUV=QTfy1p74cK&ot~{d`b@al@^6? zYQ-q<+yOJ&;sby>n@zaA*P5zUUBlxbc*388s{o06N4Y3?Ui)@)U5SP;a1?#3(KTUT zD&0{}Ov(_n_Ma0Np%SSpajCwEdZjCPD@gOnuKudPP{c!73U(MbP@;;*uIt}xRnq!{ zp*$eG!`$@#>l@K8;A-NLMLg%A-R|Q@RI|8p91{0!^ET4t}1$Napu8 z7%Vmr=4YPL5R#1mXs0vg?azMS3j)4$FV-KJdjEzD?#28JmI!Mm)*8o=B!sr1NC84&<_uC9!vvHHVYuP zu=q!wb*k(Qx?}xmpQw!+v;q)3;6V24w#-n}`U*U*sd`+-S>SyH$2JP}$z!0^_aF*s z7Z}O(l+N!ccUfh6^D{51T;d z+nA`aKLU2k!Cz)9{mF|!X+%dg{zd{THkSj)Q4Vhh{9M9AwAJ3|NMzz;_}=%t^jZmo zs_`jt$;lE6{X%|sFP?3vO~2A#O5gd!No*`qA|30mDmu7arJ z{pVfSMhGP*3R^dmNNdaT?R-ns(bS8b^E7LJN*-L%Y5BOtb@1=7+zyVALwiF8d5t_x5Vi4XbN*a!`l6E#w-@>`YBbf=p zuY=+{WY}k^sj*O2R#w`VDFnpej0Zg|hELd4=rl2w15)9VSn=xBtx)alOTtK?Sin&(Ce)iFJEkJ z&@c0j0G6V|M-481rzH&}pF<%~!oa`)e3wuCR^Q(U5()|m!r=@?3Ye&EZ;C{h@n@XV z_6aICsWS1H6kW5rd`2kDJ$A#1fdK`E%*u&_*mOh@!81U&oX*RN~Z$f9W>P+{o}} zV2tcH0U}6#&xvHGU%+AZ?}LK0w7K)ddL%CNm~x=1xzLEDsYrsm1v_@-jTH7dc*CtT(X)HlBGg_@V#+aScKltUB;L zK40SWMuh_@n5$yXfvri)Q|K|Y_Fb^d*X=kZc>^nn`JS3?NjC?h6o$Z!=}wt$9iG4N ze^30WK`^C+e}r1dp|2jH{^FgUa5lxhGvMNKrmOp5(^?%G2c=hb$aS8`6wRdo@hx<= zDS9eDACX;}U5q*ZnomDYAFp>{EHZ+zrm@*_!3Oo8T}2;WcARWY1nPu$ZcXPxZX?nR z-2i!3ydq=Xs*|&WYC*XN`}SWa+<^LeL?_ZA?)zN^9~pMQm)#%e%^>CrKbYM!bD$aV zH}m%y^vl`mlrt9q8$L3D^D-p84JRQ!w`S?_L$H#`ne;Nh*XUkn6pUe5@n zTZrw~zX;l3sq=f!BQraDhQ7Jr+OUs{YI7M$+wgOr!Gv|~_rtA(bTSL`XvA8 z{fjlS0k>TA$uFax3`KbEj}$&=$e8o7EZ^tF^i6UR@sG5`7FCHjIrj~e3?J10gavvj)}u15-0a5*TUK*n1L;Dj1DO^LrW{$xkUfp=~AW-ZAe z?wv2X#X&oH4&7#i;S(W3doIV;IzVFu7?5cOCLs359 zDP;_s0(d$9mI?|60#E?y>Td=Dfio-l#K(1q^gqu5@`r^pVkDD_NU_1$Ry(M@0 z!SJSJKB&tXXkh*+27?GNy8J^DvN^T4A~(()$wp4VDf_IR8z9zOUzRbL{8U7pDY$K% zaZz914u&VhCj8!Ld!(ZR*%Ew9MPsPtoPkIFvlXck#6WN=z*dF#Id%DW zVcog%LyvKCVjgh53To%Y@Rl01dS7~Vx6H#P=>(yA!)JO~w63TJbOMlr?Vk@DlwVrA zu=j-hl87-+9ME3)yWYpT1? zXx--j-utL#5cyWzCrbn;wt+nTc0`R09BIHr(0qZL&*adn&K7)&UqyVkGup%kqPO08 zmM>N9pGaH^a?yZKB%tY)f^#|63kzk$r}mW>Hiy87f6gmSH9NaUa(5yq@BQHYRYU0i z^3i_>cr5TP1C!*la3DK?)goeFA~7&FMhs*AU{t~yWcZ-|#r45JcXo6H=<(p95Y-6O zhA1D%Ti?B9DivtQvgOTq|2{y%obUWl5lFN^B?}jYpwpP6Q>?AxS@QWal&><`{mpcY z%&3A>#X|-x!Z_IC-GjU`(0W4C16*R`MI5JnQu+PO-hd~^smAF%O*<&Gfw#}j z&R#7?qmikp&^k}dnr+T3D$aDz>S~^E`}3=>ycw@m%%Eo<1Gm?YH?^PA=}U_OiUwMrbC%A_W?C7^QY&FOtPwOn!Y& zaGeg}M4`Zsuz4mziUfr;$4~10vV3RQ9UW(oa>5^ef^5?Fxu`tGy-4^($ zh?df8uiY>mJpXL}yt>6;oT@9m{^!w5bC~PzHcr;<3be&nU=y@Ii1v41`t*?xTmrp# z&oN(0&&nbI2?!UWpF@oIPQj&~m^^dxaV|Eqj4N__jMp*dGVIMX)XNMpj~&H+*UE)` zc_A?V>Ms%w`<6!(j>)hj&v8uRSm`&-cSqYLg46-D;e#>jS ze^O6?zQt3uA^_4_O5@l6YiR_jzkiF<(9z3Mrd1O7nc(?Z0 zD-C)2RYoNbHhw+3fjY((FYG%l0cUto@e3z9v zr{w{_N77+IK+hQEn~I-?oeLs}Sfjh@>b}|ewQoF~CAa$S@w2~bnuaBO6Aa~0r=J8) z)ke=jeHVHdsvzH^UA=?xrPOwm#eg-afj?^pY!3=&-hmcw#mFt>vWBE=E z?*RY!-ZReGa#Tu3V$jx4`IqiYWM3>&J)5^pKetFcHLNzZ5lZ9-FUpww-N~Nw=kMYJYfo3J4&wK7g*6@W7{`x&cn>_@(@%p;ex2V$pL~(UEvG zPHk4pN=T&t0M1N1V=j!S0)I@{K5*+vVAnQ|lvwk_Y?x9HcXx5nXAaFygRls38U^=Q z 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

V!MsUOu+M&K3aG)^mt;D~wx1VU` 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 Fd@N0nbiT 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ⅇ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 g?8brim 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 literal 555140 zcmd43g0NOyw@QqtW+ch{VI^!J@} zz29GO#!KaThI!(Sz1LoA?TOS-lYfXoh5>;<9x5uxXh9%ost^dOE*c6ra^~0l82m?L zp`Zm0`Y=KuK_L*xH8>Qs34yqCK_J_v5QuOp1VZAJ(Wog3-as)|mY0FR;D0{16eNKo z=uQeRTpD@Xn6w}uboHXPQk1qgnhJCsbEEqt5MsdBJ%Z~6NAtlzG(o4Dm`B&$uD zZ9a1vCW|ujXSU9EEUc=#dr~M@*FZ%q#mAwWv*RA8LD#Gk|12RI9;nEoym_TQ8x7rm zUpD4n%u%1o{P#tV!l;Ui_n(($Qui11|9+ItCNY&)^1q*yQN>SUjQH=XP|LM2+Za8!^}GL`Eh3Hn|2H@Hvj;mULX>rDteh+RhIsFH;8Nm& zSIB7~#LQmUrxd2uLIuTvg~XREKGsi*mO#wUTOEFchGs*1J{nQc-1Q6H85)7V_spXC)+Rnb`G*4}CAxoVHzQe_?5|_xl1T$N1FTa>vQqGJ$K5X-*D2oaV zmo2Z{|KKgTI!W+i`>jSb)%yw#X6!9_IW6m_a0}?7%8_z+@88x&H5tU-Uer!Gi8fmob;$#B@>`3 zYcdY<2OaA{4_~4zq^w)FO zDMx1Zp5#BMOG(!f)jy(wziJ16z>~=73&Jy3r~S{COL)fN0g=)6-)N?H8}KEmKju)9 z%8Q@dH4eeP#C#`h@Bs3%=HQ*~UXvh2lFt#Z(vYK6`ffIEz9K55ekk>OyTFZ}+u%Ks z;Ny<74bNwPHpD|tv!dFUaDS}3xNW-@bm5@{Bc!P9hqAa6yfj>ltqsdn8vJi;pyvSl zmhaibR{^$o1$r(Mb(!uMo(e-RN`|+13g?f)u>UNC*2Uo@avB9~ZHidwc;T`~xl+Vd z!M3LwR)rv#x2|!WoKQ6S0us9ZHWG}Ns;7%h&rU6^rF+5Xo+FC?#-}p~2zF#Nw(BU+@^$K_S*Tma9e3id zIM>a#cl_tG^lblEcs#@U`}>|mkAF#c)D4Y0TgI?R49cEhSU7uA{affHY(2t+fmhtT zaVp_QD(|M2|F@GhANToO{qO4Z!qFpWU9FkJt(DKFbT8*9n0r-%hMu3$*iI|$;{GqR z6ykxXtNDOFLBX_AKcjW#yurp`+Sw9SJ0K%^!@;7`{_)=ny7YN5BFIJ?zhmH>w9Ymg z@*q983wOC@yAJAIGaRh56J-z)A%9smVeKoO2^||7^TBIs z@_vYp{`O@VF(3cmQ|4|j9aG3W#7%+zjqtg>?H{}!hH{EUc0xDM&XAYGtbbKs=bes;LY(-927 zXVr9mue-BJBS!WyBF~dX?~~V+1yO&uVBt%UkH#R=ECL^3FYhax{J+Jr+G<}pbEN5! zVzU0rXbED3F(C0s$Xyqi)G}X^%8Jpb2l5VDs2uP;q0& zTPq>R7xGe}(>$(}csr>fh8nr20F->UwGM z3VTXE3;9X}Pd`cRTK^mCgctASKG;Rc-d}cb?M`#pU3{v;MIc|zA$3Xl!~OkZ*;3P* z(PdyIIvAmefMXZU(;?_*?^nVqdWqds#3S|>_csSkbFHs_;**jqt`q%RFO^&%L2l>c zBSrsvK0fQP$EX@kfxJxA{I9{RuGqnGS}K%Tqc z^Tw&kkBp|64Gt0bM#LD~*|E{%NB(IW8`G|owmsGTX1L{HB5m+G!uOA22e$PY{mNhzR66fmLrE29V2XU+x^ft@Zl?V zgYkODNJH#{EpD_qZ>(QiRUvx}*?}SNJ`rd(ieM9Sym%J#PGdulwmm@XH1SW{jfRW zksy^VuZ;O4sqFQeT9IrH8jO?~*uzJwp1IHC5X{x7|Hh?pgy@lo6;27cjt_WX9bmVo zvE>+7V}X@GdoVs}0ZqIt{G3(?xnJB1YKBoxoIuy5Zh8?3=cw7wwQ;@Qzbuo})WrM9 zVH8zS!8MR6LV}7z)qOG~!TJ9#!mQ?VBV0|RBOElDA(4Uyso2py@A{cmmp#{QFW>AU zs`x+#btoxVB)kN=YKZ?V&EL>gZ_SbW8)iJN*6|Igy=Dz+%l)DsUL8V-rgTNNU3zDk z{CM|<)00ZEDptXPo8Y&vy0p~}8ZU|O=)ch#gl}GlGvCgq6p*F6sj9=QBd3~_f0fv%$S%YGM-2Lo8xn;RsQsGF^+Kl^*?Ouga;Me<6;K1wg{$&=0PCX15j( z5LG9g9`71gQ+wfz*_gzgIr5SvxUpgXzQ4uBFQO2b6%YC$NkEhIlO{o7xB;gB8Kyrs z(DJr)buqW=_irxC47XjG;%AapybiT#QP{!xpR3~3lZOuW@}yF7E)b*-q&+sWhcgVr zbthZh9hjf5$W3XdHj0H{YjzFi8P;I_-CH(uyGcZLgcgkL&?4`emtlF0Yc1EE2UQ2A zYRX}y7GJu=K`4PZ*dC+&FWvBo!k-{)j{MUPQ34$I4dd!DN_l-v6gFZ^dVKV;Ne@XE zA905eoKE*18ZS@Mm{>7XNtUt&7Qs(}#=SAFzQdw#sMFRdr9w1WwVl!GYl*HG{hfK- zNL_B_=)T-oh1Bi5f8D`8yu053*;u(ACq%j_M1UmthviknysNP=%dN=!;V53A6V&888TMk)?7&% zKXtdrsUsMmE;EKk1Tv74I85Qvc!Czc_zHHs`IKUuHld#qpOH=OG1iR-d__Wnz$VM> zk^5g(I>Q06k4018iQuPvpp1Sm&SAeu6n0&0`rZs$zbqHpJZ=4lzN+)Q6)!ZHws05x>~a)XRYcec zyW~^Er=`RH^n|@<*|+D1)em8JJP|fX(DDxitHl?)6^0Q)tPko{6$#|>@SsE4eV=&V zgxI(EoJrL=%+sVSF4UQBugvwuQo1(W%{91MEw=iXt+x4`v0zh+@8SlAV^ew@j9KlAdn_SAy*E=M{puCHl$4aijrU%5U(xe|h1$wDZ{9q9@&w)5+8TRy$ECC; zQjC=q^UYvJN2NvIaD(d`BxL0A=^?Ve>yJ;|k4RD*-97>3brFe6awaZr29B~ZJ{$2) z3|XWMopxFU3e<=>`26I_69qLjIb&n0f!91z($XVel}V~?beixR$zo8z zZN@8o-5e`QnyoA-D0s}ti6bc~Y4s=H2b~nW4ZrW0ok`6v<8*?|XzX2GBUNwInF*t2 zB(BD_4GrIa_&`XCg>rdwlV?9$8~^iF&Gz$>@s(f6tl(!5XM&=L#3Bk?E9Vb61FIxN zI8QU|GNk)e5dD}HHmb5%tG6h)YXxG`T!P^ai&$w+w>FMU$c|jucST+n_mvTq} zsjwM#e{;E>ViKR4x>;-F=EiGoVIk(jb3O2h=W@4d$i~efGToBMzFdOU=J~=G#Uw+A zY#~=ha|>2And;w*-~r}q(J?W*3N`a8%zH4xxx2f&O}oM#s_i}3(z5x`jYm!%4d7Md z?wr$onU~y&p9i#I*F1)|I^a|&%{Spao2JAM$v**b|wIen)`mKIK z;`f&puPiNfruf;|u*zGnS*ZL^M`jc2&3MVU%{r07k7h)?4r#(3l5Y^glGMdtET0e% z6NkOY@*b31X!QP<-$~4 z(5?xjC7-Q`mL4PJuCJ?ZRiS#1A1!m&A=QA5*ih6TskOD$YP^yJ6jlj>Ze)T~c=Oi} z=C3jB%T1I!e)AZN5|*1GSF62bgo53txT zdKJ8(gPC1B$|hZEO|Daz*bcFM)V^4pzhNSNetw4M&d>_lAEj%mbiQUeIT4FDn9VIM zndb~y;xQK~Fw|Mk{b!1bkriU}^hh`ow`j(xA~*;L2pl&?CtC&jO&&3a{#MZ%w+98k zxk$0REVi^t?{0Z=)IX_&F=crnI=0-Yl_haUMA&qH@l=WZp$2gi2ud`3mTo*MT z$d&Rt`7Xnfs@B$(wX%~Ha_E3^S%a+2{tKUFKn_A|I}TD5p5mH|S4<{S&!Hysy&J=6 z`b1Y^3g#X;CXE5iJCkD^fVyCZo~HoNb4GJAlN#skhXwrciOW9d!jb640@+FF01W9sN6 zryudx3btOZVBVhoQLky`&IWO8b8{0T$yn5Ew$|S3_Nb3l^<%|P@L6!3AQEFQ1fDm8 z-D!Nbq8~#vl0qW44Ox{xvUT)P2fmLX7Z5&^{+mPAqPkbMV;|#5QeV)kkOYSCyAe86 zr-gakF?CE19rbz^8OQY(1iWqFB3Ra3#T}!YE6P6o@|^37omBtn?+U^%t2PIoxR34# zAh(hq6MvXB0i3R(<`3D}-5DOJCx?6nAl2A{X?%?ru}nAG_n>8RPj&GZ z9D(+yaC#chmgg#=*R=dJo^G(!vhJkx)WQ8;RfR`D@O<^EYQEd^g5pDVTU4%dWAtX` zU|~6weA0eBUaaGFe+9MW^Z19-ZsC*=9WjAl`N3OZRw}_efjP9zXty>IykT#o8JY9& z(OL3&)HqMUHJfeAS0>_NK^Z0^-w$!qNQ|pmx7JpEGr~DAELm)2ulna8b8TIyb|pLx z?;kvPy@fM7IcaS09u%xAty_PL&aD^wc9c`-XqUhI5zi^_i5||A$7#O)B~@o16&1y0 zJE1}$=0O3{BsTQrQO6CuvSoQc8L(K68rV~%4kLoqZSd4N>sey&&Q9HI_j4ZBr5K0& zG(2))7jT$szXKQkSmwMrk|+PQvh>a_CZ21#cqlt?0nAXpR-TNTZ)(g01C3I2(CPdH zJ-X4EBi*olew+23UMj|y2SH;mBk3v#h8>#Eygw+E!6G8IQ%fybFFCwPdT(A!)!i;~ zF)(#_tuXWQ?1z~TAQhSfJjACSViS48O=dP#N6@VBj&EVvOm9MRa_Dkb_~d5q z?L?Wu(MG!C#P)6SQTLg-#DroJ<2Va?4kJ3j^z<~JS}Npk7BgG#n;>;kvd_o+&DwfuG%Q-}vNcK_K=k_ULz)-;V70aRv_t--Rc zI)V%1s-6Y@a+L2}&vR$jzgpo5pfF^+Np?=)gr2`yZId~Ioju!}z}rl$CY5~A6f`Oo z-pa~CRdt{4=yZ8VTX1r|GmGO&6@V0cK)UjDfwS$hdGu;z%k6SA567t2{3b0aJ=m8~ zT}D#!?JR#Seegls-NdpeGBUE)#k^-mtnKu7hS$H-V!*H9u_#SloXuY>E(4U1EYap* zUg@t>q>ZhJ5qNuqYV7Bn70+d6OM;L8j@A<^w7k4rda=Q~A(ih$a`Wt3sXVyGR-%NL zvFu~^A!F{WOcGXx@x$BNu|{nq0!A{llQN_zucal4x5|qTdZz0>9@5Y?-VI!NtIhte zj)8CJL>k*3QBaHjpq3zINH;g*p4j*NaHN8Wk)4VFQb|Y%x;IP&PKOk3u-CJr69k?8 zIjcL7tD8L{iy;+oFwD%J{9}|V@#0*xwI@mdZgiBC&=xo6=36`hOSVE~|n=k-9L zv*@@gm_qN9jfOoQVPUeJ$?`r>?&A>?Z`97$JFi}nrTxVrEI?(*Rhoh`I2cJ(Io_7a zhNL{|?Jg%uU;7kaxzySJa;)0?{?;};#Q)>_yb40g`natLi-tM(Pvfev+09|&uUcmP zAIqk0`U6V!EAd4<_d7d7%Z1Opw@-_dpnX=nApDww(0Ms~+qRk@Peqi7wY$p3!h#5S zPcA~GE^)`!`##n~=wrxpbZqF0n`yF5H{tLTwT3q=v9JLA5{YZloz^Q9)Bv%Npdbje zb+_1LYIphulizWA`}CmW6E_Fc{VH%VTuJ9VeRHd_;abK&x3QpAwaO zkpt!`&&|`YW(XecJ5#b`mR(&TiSZp@oDm_3Phhy0MM;dKOm{E zPpVt?GPJu}hLDH|U2z%CE`TD&)_uQj!Kb7%eb>y)OusEaOiN44l#3K_i}8tx@9OIX z2Qq}Jnyi#jn1| zo1+0(3{W(;>&C!K9g+-*z<}g$Dd5r|KS&qerlzJw=#=ORG0@7$%dZ}<_p2%E>dLAT zFhWd0N#zhX-Qp`?Zf;)Tb!7hP^=mqg!Lx%T%{)1w=InohmNpfjAd5qq)UOSwn;Z;A zoX-WOjV`uYpURG#yR;CZL0(zD7OKt`w0^oz#@(5tI#Bw;>t;`Y@_NjQm-)$)w{>-% zp_OjCQ+Up^9_{`8jURmq1`{qPOE5E6G6W7}+5GPw=EQCN$u}EX0PtMcsItpjOY3>& z#Dr0ePfb_4f|$=~`@E-myXT_+&TvYJK-Bfw4z!vb6m;qQ_e+EaEf;Fw=`D9EKYsXN zI$JAP&|p$=NMvSY8W4WrbesGSMc? zGQ7VjTsrx|b4VtE+>`w+2>gQnu}hA>1%lEuvzzj$ZFikv4X~o~d(;JKvkNSm};T74zk%0wM3EjsU4$ z3aLZ6@5O#HRmr#wx9vo!%~19oX>T00$qsjYmCZPd=-ufbqQT|0pGotvwBq7am6eqd zkewlV-hrFveVcJ|}xdr)K-JE0SMPDTU13}lSq5sE9L#zM-?cgkP0bv z)Tobg9qft|Jarx#D@u;_UH_$1?{tKJe&+&_u)C$^zdK+;LP8R(!NkESAEo&ChClrX zp7A?Oodm_f$U3&3)k@FS*O!6y=`1J@h|&>21B81#K*4rPD@bBeqY)68%rUz1Do|}w z2Nw(qxVyo0Jf51--~EV8OLv^=fP=suj;JNOcSGm=Bpty%_igQnxxAE&s>V+!HM$P{ zFU}5H+i8qe<%LifNjlArsp|Gq2Bw_D1|jB`*H2YGO=etI0gO0J7=3#b4CtU{YF}am z^4bpDUHXC$^#6}rm+B0mXC`euC=HvOQsg7klTD_Ahn1HMl}Cl9^Mv{>f819q^3f)i^36>#sM_YQxuv5!|Cv5Gk_-1|H>h=c^ad<9ikYjcD;;5nNSSwlm_6N_C9&v> z?EytUL_djgbab@B^MI=KW}7ub)HzqlRevFH!50S==YHF5Zl=cMvkq(DaVv4(^vYT4aL~~^z=D|H zhjsQOz9&*tQ7N6cVs+gfds6pP%oRFV#--Rn)L_V=)QJSCQ>2fKj1+X+jPLh%X`o=$ zEiF73{HuW#TCV~fN_7mdbBAY*<%j*8ZA-tB`>9^+(=s#HE7=!6N9ZKVR12R1OOM@w z6(smMd!qNnN(u_?ptxDB_TL`!&HTuT5G3(uG@}+71x46CNr4^>4egnlT5Q+(+8Qg- zkY?5EL4QSCfj2TTIxZ*g&azns(nLobTity<5aT_mhF>E#l0)?O@{QwJAnvT~0u*Tb zW=3Io+7Dh)A#ijf_HG9XCq)$2`lU2u{@G>v>~BG<@>5ZY2)!p2{m|Qn>J>XBL1Ig< z+B@?xuMd7z0Hp>ZL53Y);@st*#k)s@JP}f~V%@<-KbvLEyoQwi#1Hcq$uYR2V)M34 zo`-ME1s*C7rEi7b0C7}z18A#~c@q!}xjgshFj6!srW@T$tf1!~K+N=Z!y;f(>jueq zp3z)e2W%>1@AYIGY7zp1V9wUdPD`owjo;}d8A#vVwzNV*LdI;c*8O337Y==me%|x+ zQ_2KH_tI?AaKjpaEkYHEiN~xcL@mcc!J}*O6|mc0`%~m3nslw!!wsMxaiwk-mOJ-GUzhIe)1< z0M^5;-y6yS6^Xqu5R3P5y@C=BlIs?XH;z+xCaW?Ab6if)Q^6fSW@75g@z>RT9cppW zQX``jdV)lkJFAd_Oz()27+9;zina*}!LC^NfLbcBf%#3J;E9q0;#cILR)|V|z3LZ? zXUmv{QV0h$?QLSXqjh$H9*9nNo=c;0&jO$CT17^Lu;71fS`DE`0T3Fl<*c8+0Q2@u z8b4Tu1HNzCeS5oxTW``dXgfc0!F8$Y?DD2Ed^6D`$oz4j2)%y2@@QdES2#}7oHzhM zWQ(T(TVGR(Kh)D~G>9?K(srz$gK#zBg@sANQR+V04M32swk$%$U{1*wh-W0?w}EVl zHr=D9m3?o2pkLXF>Z()cIb zSepWIje+dXF@>U{VgwZr23bsRk^Mm-^Xc|H>hCnZu3tpdV^-d=$9Cus`5q;)#z|bG zdF(B$yBS(pF^A!_5dhk{4-}uEEXq;3`R=_})1%PlGhTEDLK=;z=-fKDTwdjja?n(r z0O@;&3!R2+mds?Z-UlX-FpP-fy?4T5zQ36Mee>Dj*)#d}{}Bx<3WQq8?7>v zhq6J_H0MFvObul5-Uv?_K0BcQ@Gp(T!*G9*ivh9Xfy}$_%)O>SiK=>`3Peyo10wXh zjf2p2K06)yvFMMIa5mRNz?ngu#rA7d!G>g$69?E`9JAA@Ps=4Q_HBXw%VL)Vwvo+! z8x4@&ELDi}Ml4PE_`HwT$fym*)%##aebl*`v(M)k0wEn_nw(cM+ElU0UF^@# z?<=dSmbt|OUVF>qDsnc*aj~`L;LFF?gBdUOEP1j5uB}0e>fOWV3vzFWg_B^M&4-BK z-AHJbZ*0HoU)f8u1_-!?_*vh0X%l|Uo$omqoS7#+qf2TK-9I>ip~T3oI?c_mGMOIP zmggAMIY5GLZ~aOQk0fJQR6js%RCF?-$Kr-H7)`65BGngXXFX9wC0u*0HzBQyw-@As zE^AK7EUMl1^HC2yY)58hB+kZ6oS{bhlfu|G#A}3(k^yh~YZ;TKt^HW2vu$GLEe&w- zB4q-rO4B6s=O5x)^7N(OOU{=H+%?tfzYzn1%3R}gxgzrWo{7F*b6c&Tn4;=s24v=b z_R6)z*4;|aiW(Qxr3_rN=i*yyqrG85I5K0eUPQU8>CiV9^gRR`Z|E?rP<1e;FfnHYc&f=aJZ7zgwbtS!N97F9JN0@~g3pd=Ut!0rXye zYM=kT;;}a~f9|^IARUffc2sFoLk3EcAHRMTJ5z%n_{3{#Bbh+@E*n4k_Ug@>rg@S_ zk6y%NImA6A=hqg=k>p5u3_v3{H@8ls@m`5~cVA!C@jrW-4mw=HTHaD3z%LrJC-gV1@LXyd$ZLJF;k9h?h3C99nPW}3wg}|O}*dLpJDEE^1IG?@pKE@ z-qppm#I4nK^4oHGpg%ri)pX8Kt^JJYPg`Zp1b#pZ9VT>PL+ibHhAd}yGwceE+_%RX zepz^ms3+Ib(-m9P%3#cwk&}E{7uU2Y$%hCs;v>1U`j%oKk1ZE|@E;9jMPb*te6!bU zL7l?N7dif!T{(=4*nofzqPt9!E5`t=6kZbNY|U>ZURV>MD;sk}-Ct3>qNK|S@csHn zi)@_$uHY%Pz6eenl5m;Y=W(R{@SNJoASUs?pvN_>+2i3MMIv8FT!$j=?eCE-u#wRQo?vyZMA%^njzkDv($9Z z>OS=`?c>UrTEQP$SpLb(v1W^JG*5zzjQLZW{$hq#vv&^FI=W7Z7|ahc1ZJ6x>di~s zG|6k%P&^$n+)AU&^4ieBUCHq|BDe*`r)nHu$q&O$Gy8wx)Ux3B@}M)nJjG}8ZU9`E zB+se?+-qaAfT-{wm?9RirChtS==0kbraxJ4d`*P>iT$$Dc52CFj|y0G7OSbUmiB8p zKmfPVafX+yeB!zTuD-u&Y$t8_!e(@T75;ikwy*u+vj$O3nbwNZ&P3V#ev{9cO(sYG z$~O!JU0q^OEXQYMVSDp^`~|QqkjuF@hO*;8LPm6Ky?ULD|2hnZIu?xk?9;`6gqRly zC)>zX93)}U&RnlELPVRXKlnr2z4kme)%_npG|oRg^e#adW-1NlUVSxh*Dv}Iy>uLZ zfEe?OhY34z^jXq<%wL`vjll{P^#=QNamU)I*Q2$74NMRf2(GMfEd zw1)aMggB4tqk;Xdg|nb>PT1Eq#%f;^ybV3Etp{HW8^0XyS8P^vQn;TS z4``s*b?KpSgBiscKkedF-U~Vp;N4$ zX_N3)M+wrtDe?y0^|gpNgAnqgM~~1Hy!56nn)IrlH^p!K9;tIQFU=Q zlpFE25l7TTi`m_ypDnw?>PM}UIS-G5eMV8S_w0u93Thj!y-U?+9VQPDZn816HKS>C zkSAyD>sHAMafa+=XSY{i@2(H$8fQ`3S0zpupVQHSeA@*?R!+nc?>f13z*PY z^g>u^-s&ji*w`Phf}0AC@j$r_u^pA|$l9AwBI2P6>y}@yC=GM6gNc0hx#BDMMHs}_ zA=P%}OIYqTYt{s~+i)9#aXzm@)0Ejj*qx_JhG39^f5y|}h#+m7t+>_-oSbGxjTxgkGZx`lU(RH)Uypp&EJ8$z?ZR;&JT zjZR#JfIr1vg< zH#L;=*->4n6nSt*kott*@^J6@Wl5KJ{p$Xw&XWg4b3(>CuFO(p(B$jzCZnvbs|Hoq z2AR;khQn5G>~^(+RO}3;-pg~abU(7+Uws?EtdYBk0TH^KYxgSIZ7)&33tt{VyAGco5C zBn7~8-fAuWsnEZ7vwG|}JtQoEL7hX{jDuLOIg$TcgSk^WV|IR}$o^XZ)y|*V*)!kv z05v;_#WVL=`v#Ql4p)Pb+Q!Sa&*GwW?%of7%wi+(In+Yyb70xDy^A5^GZW7OHpq|p zmTbtI$GC_LWq)?Sp7HIoD-aIqpcXnz6)TX&QUsl6_E_rBQ)OcRt5&k4bK$5L)cYD( z)S-z7t@t13D|CwEQBXwal>y@@#RoHqZ+h_(P?8zX`7ma^5yn`o>A1Lt*Uy2c&+KR= zje#l)Fv&`La|{$?Jq;zr-^q{n6V>1XI5a!3wHI1imMP*nA$atvE!rlQ-<;zHh(>Ux zvS1HDBUzxEXLcWM=Ec$dqoCj{CE(fD#~4ArFK@f|i77X0e_58NS8fasq@Wst6G16I z3E=f(;Js+c{~Uq__|bQi61l>!xXE*_+(GaPEK zk-%;jun>5;aq#ww_5)zdqKEz5JXxEB1o7--$@T3Xl>S6B4yY&N!jLr^v6}Uyc$Z#R z=!8Wsa392!?KPK^`&Ndo<8Gno=&vVOeSYhf(zCG7lTt0?jG{BH~T~ zD$moW!z~6R1*x4<(nrS_cBl_t$zBkO|w z)Nf#C)SNH^IOPRt7g+QQhGzTrE_+ExNQhp{ootSNWj#NDA)A!nU@%s_*fhw|FonGh z-kc~aeRV5c^~Pdnf*l(=-E7G!_nvf_OP+x7eP2RXcqo5l$g@a`U_9#y?WP-5pie;4W>iurtl56*f(G&o;wRNE<70_kcbH*{yx5NH$S z=fAChubkh0rvA>&Pe~~%KE!Erm==_^&4YtRBeODqbL4Og(j%6aJs}|>(c9}r2Fw$H zMLO2^5E@3tUdtM6J^PZ}+#|R=3g;wF=f=exf&K*mP)6-gh7bWbL+1r`z$LA**D`X7 zzn9M^3{MNzKrvu=#R2M>+qArDR-h+vd|zK296YuD!YIM|FT=Yj*e)V#{w6#K#QeUI zpn)BryQ{&no~K2-J@{mkstV&5)6mj(A+>YO@2+^}2b42JNT*%vg*c{uZ0PpXut#?V zg9P}D)iZRrNBt&7KgX4 zLn~uN&nGNJnp-kixb)eGDF8=MWTHnz7veRqo#ym4mw$PAnN<81#LA~t-w#KXPjGo$ z!{WIRJ|xrE9Jm4oEIF(Ewl>Nf7zc>MuqpQ|$}1{x`$58&r}if`3AhRc>e$ZeqGR(` zJeOv2Ws|*uwenwtDP0UI?N-huo)w)+=^O)455n!nEZqBCS~9=0=`qD`qa{jDwBg=Md97M<(om9%fN=8){5~n zXz1w94FeEUfBX2%Orx@UaZp^daK?=ks8iS7fVcxzgh82W+u4Kxl}Q?0y&&2LycW<` zQv3ar7*&hUZ(ELku~LzDfk853^JLe}&rLr7Zm4x zy(`(Pr!Q(&bc?jT))M+y>?d<&F?S`LaOayYoTkJre`z-#7kfEMwcTHnA08hUSI=W| z4s@;bC{xtBZ%*O)p5L#0_iqchI~qd9JX+T?vGBY#rVw|*0`iOLnS8eCxwPwWv$tzX zpCUcJ-`#J4&EZOm7aySrtMEKIEdAr{Cqs{Y6 zzYJPr97eG>=Ks9i5Xk>z4~+e|FyOR*9thyo^2M|#+$Jm@C%XE9&FslU4&Xa;J~`J( z>tLMaTEZ7bPkd9xb@kd@;hCVs_2%Qco7}v-1fY0+4FCycUKi0x7Fb(>N5SD@5wM6l zO2S-ZF_(v3I6(eLRGMvEb@-GRCvjgtntlW-#Im#7>E5MpHj=9JjEv?$EZ0#I=O&9u z6>y|lSzR^SkBf>r)*lZ^vsr8v1H{3WiwUR+7*$d=*6E21zIWzGhuaV(8FKUi;c|`N z`8ANu94uyP?a61Vt%F}wy{2VlE$OTcs#*EUO2m-#&t?l6s$|T5wW9rrag8s2*Mt34 zxA}w8a^*$Y@%OZMe)PNdC@G);hJo5s?s8$v%J)u00V`C>zyKKqxFk{^T79Z|ScU_7 zR$#JAL!9|57ugH)8`*jpgJ!ULM&rB5Hm<Qqka5$%{!hMH7Bs?6`U-gp<=LYPKS}@a# z*!SY@T_~nWN6W=R^xFrhxj;^W3sPWLhT=#V#(YuMJ8YvCSbh5l$NX?fgu)yH8@u-- zyMZ(8F7Rz!+zBbL>%!HkujOrT)hGQnj)jg+PTYkDbzCA+QbyP7;q>wk%`Iw)b|<0M zb4tzRPor8asv%A~vYm-3(V)%Y^Wj$}vtP{{!^U(eBJ9g%++=XG`PC|F-rC7`Bov^= z$u13AaFl53N4djw6^!ik=R3~WWFlfzgX8;&lgYL~*vq(%WI%j;1{Cj9 zt$q3|Kj>iCTx<&rMJG=ea6I?2;s+)?kRuLN+-)rrXhK>NfMu-UOdMed@eeSXkH` z&Ix|r1at$byb-j;@Q@I+pQPs;#?5F+Kk5BI(d}EPJ-9>h;F**ZVl2!9%iCLEq*#X) zi-H#okVNh_o|ho6KN7B1!^h$!dsu5X{T>We&X;;pAY#_rb}PIm<16l5bra6)Vk&<1 z^iiYR*2)+MC+E;|Ozw{#3TBV+>FDDA15dOIs+~EdM$CAd8&&Z{J}`EH?iV1mIu%~i z90a0jbG8BNqpsQ>`#&Fb-L)8qL!o=1F=6Rs%&_1UI)sZt2(l*)}!RXNOS_gdb;UCTK7yP!sgnB@MV*CjqfU_evC4b%FD^rK=VY z@%5@16#}jsDp-`lgurVw)#%O&lvlm7uWT$n=|8M^rE)a1h0lTK7y}x(-vH&Zo8r=h zaxyZa0FkEf_=xXQ*H`5fb70t4o1M>`9d|WM_~%5ee?P8+C}U@5myGYW3%v%3s@`e& z-E4!f*Wu?wLtWn5vz^H%qs~{ry9L^25@+>202Z}|om*rB!MD-#AQmv+tC^k)&c2zz z`r8`D2qHKgT^(rS$+dc~NI;^#AD$x<9Z@KfbACopyHhQDdD7`@^*pv+0w(w}nNdp1 zg@Cw-nw83JSXkO+(q##O66w#DF9atREWn^WA zbjE4uYzR|%M+8AIOe0;bS)>IeC)?+msT^J*K==%^!vp|P+{q8>8jZHww0?SI(6N!| zI3cJV1A%0FW9DRBL+D+EKw}OZPD*Ekh8+z~AM)?92^^~cSU^9-Yihoeb@#tq4zK$< z^H$7LU<~>@9Xj&$iDA*MeeO0R&4;$P#^dQ%HJY%L|Yw`_qrj8B`(dQV9+@>Bt&L!x(j zgd`-<%Yv4H@E7( z>vR!M4uCgxcLIO_MpWm_{^GlgK86fP>Z`pmHNtw@+Ju1KG%gYUr=T2xMxjV4;$gC5 z-3Q&+tLGJ|roRNk)BQ{d)-;09vdyD5Bo-BSJKgf-j-!`Qvqx+eeoa2#q5HVYxUsR}X^R>0v$ z#Ko1TptHlDSVp@IFq$%E&F3Pg=sVrmU8|r$ZPgj~ z`)}WxsKerB^5&Prm$I)PYb0`>YEGnl5vCnujj=z=wmfK#E_!~@vmGZMrou=dLIDpp zE*+`P_^(yNrp$P~@u`XYsJu}?=M`?T!vEmm{~9s>HR!?C8G$Upq+JXjaio1w6i_D6 zJn>xpqg5(>ltL{H_+irX5B`bGxk#AmWB_q+n6$nJqp5q93XDv&{QR{O0?tfo84+-* zTn7&@6fN?D_T;{XhK6O=o8u)UqksOC@C7QTaP)xqESB~~BT0tP0Ka3UCz`zb;T2fL zz?7w9`^|pUur0v9jKJOyu);*TqK}@wLId?Hf_`~2{LCh-a05l%|2u*TY%zP^82Qk? zLhIV&n@P46sUs+(`snX38HE{O1*0B%zHPxjHVYt-#`WZs8kOVh_u}dS?B|EYyHIw6 z!(r)(Gi!CGEZHWHy>4uPeTui2B)VgR9Kx3mA}J9xGe>({&}73$4!8MbcQt;*ZYkkc zJF*e7NJ4@D@dz48ht|J8BF@A6NcZr|TS<_!fii4;PMm< zxD^Zl?BwnBPB~ZtsHSDRTyC2ha4SVZLV}urlZAza(Yb*8wszt8HcPe$FjD!R?>hVL zi~C;-oas762#4i(k5I3_RLhY@-IoCFf7oTp;PX?adH9K*4GUHb)i} z3}=Db?ST=nCO{?kDCNfIYJ;Mf$?Vx#N`R1TiR!a*XOYZT@&~S_6 zHQ(X#z`$j}n=g^l;c?~{-;992g68z=S5jUlnk>KVaOA zTYG=Y^Da0T4(m-jBuwONY{>STT?Mmz?~w~!*$gWn*49N{(D{psH|nCTH~R*sJG0cl z2K8|`ACLj*0t)&-Y&HG;>+?Xs@%7}#NGt(M3D>9JR`bPt`SYIC z0CDW|l7!<>c4oEsI_=HyF}F11PJhMBS8JJEH^jyBMoMBNV`5a*Ag}=OhQ8G-9=V!W zgwQ3&&6C2dWHFe5Q*UbHfBlWgiIkwNQKNd3A$*lpsg)-8*Vp`fz&wUTqWq0pW3T>J zS}gS#%9_M$Whn3+HwINAkbvFtP^D2mDAJB%{aIu+G2pY%6^?DT(%pmrG4X4_{*$jt z5c^5gnhu-lmMFXIj^bhwMnX?dZ+h+jC;rXF2ED23F{pwTJ6(q)9K}+MMrE?a{hfd{ zCj9*E?=-WEeX-5ChN`af(NV2Ai92x$!3yeiWF(}eg5MH(K%nld1!bq%Xh>5++Q;p& z`^vto_Q1u!w%rVb07#I#iGK`JmLCN$J6X-vvf~fkzMbago+7*80j)0yiPub^FD7I) zF)3-J+|lv!@{)$(Or6cJ9^7{;FIc&J?2uS91y#z0L;gWEQx>nFizh;d@qgn(=o6 zz(4y6;0rp^7+*ZwkxS;%T#Nx454bjHV*|UFpf+3B|D~7TarZ%|Mbgg@K%#;@Wjc^* zwYI*#%z3dG-rQ^mwl1Z_eKqn;fKU)Zl@}c?yJp02>ADj((yq zAQ~8V*A|;21z>lL&u0%>?}$;ccf(UsNQgP~BeMA&JED?H;M{4=u)~svpjBvr3C1bMVqa0WP=;WxUv*+ zYd@Ww{AJEw&$0hy&fp!+_a+YJo&V>XV8+wnUCKJyM>7Xp^Ma_Bi$dn%E1E>?Rc3AF zem7CECrH2r`<_CG?C7Ye!oC0X9B|P>g7W0CG41Wp5g`?hi{c;`noSLxSxuBa`pDt` zP)JB9VsjXwX?1lO`lf7d80dS1*3pOab&KX_+c-x(DJDW0p1{*}G}4z1zQf0J|NZT4 zy4U{nn~F1Nc0yLxe#JmHXuCj$%mu2_Q+oU>rub={k_Nkb2vJ_U+UxeJkNb!_jR4ud7c+JP>;mNJsFN4>@rpQ zG-7j85m*RbxNu=@y`8Z5=9HpZPJc?tn#V*;2;nh4GWd>*k?qnWs&BP({l*Pj3v0td z`_Ah#m+wwc;~_ii?QYM#S8DrZ+a_YBnnEXmkTqE6K*y<>5`KK-Aps?-_tvin)9P*c zH~N^!a^*A$)oI%jt2y_4vqKip>xU?X<#(zmhmq{u+iYu;;L@(cqvRST781hIkCr7je`J3~0vv8sz{RH@onZl{(!Bn{6UO?3^{5^RrljfT zR2LkEeL?amoTNF(cxLYWH&7ShuVKgoui(+4JN-T>y)u-O7zk)1&w;X9HHH>e*r4?G z0UmI-KCp1;wS?mLZJ zT3Q0@Q6w7(G>=%j7zbMa8_LSaDOTEG25jq2--;gWkUEB zApor<@Fkwx_;|M1Xp-z{!FeSY_4ByIjQn3`U&hKT>+m$%d}E9KaZ3^NTlzj05LOj| z*Gor@d<#A+9xvn-?j8#Q`qyudp;--Cq<#IHuKZZKfV$A-3?xozMsd+`a(I zPo^k-3k)&cnja1b>aCztdq8_j;JV~rdyDXJM^a9$IPP0hhs>L#XQYT?s~HkF+4VZ9 zf^8wh02Kp-ewXQG?~{4^^1#Y#jjg9s&pC4?O*$~$e>ht3v1#1Xrw_lSvUb1HqPunL zR>S>;t2wv7vH$q`LOJoUeb$90M)kGBED%Z2Eg~e|X|az*`c>XWm2=#CVFCz2C>@wr z-xlPCo_j@|lLgl8@P=5aSMU%uEiDzWVHr6$@}s1~dVh;ta71QjQuAP;&rnBSKbW{= zp~UmEeYoi{F%tCmlL;S*9O}%|V$KNBJAL3OM6@%j9ge_+Pb(6tG?yasW(C;tNAQ>L% zQ^S!o1tEoPymL>TBHtIc&7NOV2)V5E;?T|BDP%a^##B(90bkAAJI!h zH`sIt-a z1gZmRfVs20RV2y)+69$9ahlh%1gMk=+0%BhENv4ZkioBsaD^>IIXEqkMuMHmw~4bf2&1P zCr5U*XCq_e9>m7a+(H`SSd>DhaY^ZeQ>)!A2OcqaE|#=0?2Ya; zk$SFwZtH&S!F1p39l z*uhINymL`FIQZqBN3XaRM^Fkw?Dypiu5RdYFYr5~;Dr3vrjuaRdrbXC_ z46;-^M@FjE{cryb7vu)PKpABG?)zP1=iP$mt@N>wfKer|2&18XNdlY%>L`^RyUspY zeD=8aOA#7oRvFPWvCA^J-u$g`ab!faA~bEW$GAYYz`(-8-(RlTxN`Sk%14czA~+-@ z6OO&cIU$B7$k!^qRwC-p(7lZ2J^3P@B}?fo(5iG zobwVbB=!jMTx>};I5br9Ju#tu#KxI#(?hS1BU_3DS~3(KPR`DT0KjcEQeJ=rCX;dUvv`u79H`?|7b%H4mz?68wv;8hotB>H{dgz1kCdeIYkhj%~u4GKAL%Y z@xhERymk1sf*aFoTxr4TIf@6%W1b5g{#ZyTaRp~taCz~!4)gQ}n8$t#0;9g$*xU)~ z^b#)EK=+VCa@RYISuvBuoy=x|9{fhVUI^A55w23go(K(*fgN}=+!Ud;7f}sS)GgS8 zbNEw72M&^}&kHr7NaF;bUPF<6@vP^X$5HSUI?Mw5HY8U*ym-`EVbfa+xtKC51k5 zE_{(bVh5P1D=VZ3TE;;RKQi0V5gvYOajb%=!%={bf@Ttq9+dPlN?XK-a^x6&n~e|I znVFH#Jhmk1d!Pb1v(_?a-(6;Jhzi6JvI;joo6bkhXWMSu%e5VDAFJ#f^%~204XUJ_hnt{XF( z49@l2?u~MMjO&i18HaIr2x6Q5NXcT*Xvc#owmda!p8eUMKlexdCqz8=J*`HzQgz<; zHP+RS$}t!gntbF+KVX9FbMgM7Q2jyB;NWKEgWnWHIXS1C`e>(D>gd3Kqd3ka4lWCr zvGm%~YwX#2JpF#4_@w(nyMdBEbfo)_!mBAS&x(tkKOb{02; z04~Io{*jfKwLXi-hopy7Zo69v`B>RcSb29lRRhUreH5)F}k(VC><^`H4`xF@; zYSot*schAgC6}0*;xd&|zm@pzyFb`o!Ufi4gJn5$zV$`Ui3?}n*>t$81wloy1NdBt z$BLPW)-fd@5CV;jC=w~XH8_36RYCb1t?PGXFUi!xFXE*Rmnk5=e*0_~!(!W5B-6Do zv0&wZ8|R9vlNJ_>NKS5`mR?L!Nd&4G(i8uG&MA>J^9ym^JvMq}?EWGwJ z$Exw0@0_5IS#!EpQpi-|FTT3>CcVg-c6hU=x2-dsX<+2m5-Tcktu#G3?V(-r+%e^0 z=?Z;`(i_St2UfE2pSFm$)Lp0T-a^UP93UTFbU*M&-1i%-eA8%k=@ESdltb5~`&aMP z?9JB)ubkn3kn^Pkq@YAXhYqr4dm{(DWh>n;@y7j+AF7Wy00&C_aCdKy)p6e)1g=0q zcz*0LM;8g2%;tbVgBz;WjluZOg)J0wmJSXN*LEniCm|x|t{;%=_84@pGo62-sTQBR ze4de5@3n1zQ4a0opD^oo=YzAPqiac<&hprCB+S_!*Bh1nDDJrnblHe>E%&c$F12Fb z9tf9VjlIg70JS+No`d7$!BAnge3(*K$?EGx{0I-`t}pKnlQuS(*EYi>WQbqAr}89b zz_`3YjUZmP#MKT9B0e%sy!wNScoGY|ea_i0HsW4Vak;56WH+zf!EOD)z=nNJoe7p0 z2GHo-9w}?Q!?~nI@oUrDq?@kWV8%X2uqb_RwK_A?OwP@jxHoEoxW-Sp7T5Ezcf&ql zK)d!Z`K7KYpWB1O@WblB0qw&F0zF-Y>91t{Dn{nJJ0of2$a zd4UFB+cF2ALgn|afH3uM@>@epP_l%hm z?E*H;rLMiXV>t@HUKAVpnbPC0y+2Da`k%X^oCa4nH8&RqB_6<|fNY=Kjoimi06hW& z(I-CznC*YR*u4G%I`?th`f=PlxTq_hSJGKEPbM8PEaN|TN!z>{89HHDGK>|1RgY6A z>j;JXGkQcOf8fd|a%=@C-%giT=p}>xrb2&Kb=woJ=-c`ALTJ?}Bf^>&EMS}U<{gJL zEm7#OhbnQBVrD>kIuoGM$?l?(=zXxeuYOd4VWxBmx`njm-#2dDR2wJU%qDFn34u$c zWjoYjmKon8)ywGkRhmaxa7mI&%Otw&=xPYY;m;eC{F0+sDW+^&YT>y_P&BZtkzh-2 zBwhC;Cjrk|U76S2cUA%ZW#;0-Q_s;eDh*C5gc||ppCTxQL63T8ppfAy*U2q00Y%+O zg-hZh+Qm=Hl==Q7Z^$jX_UzNeQ^BNo zm}~{Uv}KmD(eOsOia_7E=(EMo%EktrRZ?(8i(;VYql8)rZIl6986YTO;PZ1{L1|sO z59fR*G}V$SR*n3D_=ldntsl9te^FTZj@F#H_p_%o81D_{sb6<|^E-+;_1}MJPol>_ z1i}!mW5VYefdM4_4mq>{Vu{NCTXjbMX@2BalxJ+u2$?BEX9z5yLNhX$OPVshRe2Lw z0mBIl3>>WYmxBgSSelGaBm*`2sdWoHz0Vq;6)aV17K@X(=AtnAVb1X!^n6$hEl6r+ zD7sF`gfz4-_dI(uQeb`@jhA%k`nK2Zjgb+J3AQcxySUIR@hq1UYzNqX5W3Ef0nq_e zPCiF3f`O#Z3Q8C7fN3~7+|LBhAaZgRceN9=U-Vij5B2&dM@FBC(6T`_DvA&Sz0(8z z=pNBNk9Ec>P_AE+Q)3XAuV?!Y#h>O+(3SPiQA8c$mLEVP__~Uw=6DNDe4bObJ|2V1ZzRX;_Ku0kl z9J@L9`^=QGa+;+u&E(vi;p`TyIMB6&L4vBWG3_7k+Ce4e$53#yNK4aaW@ZBE;vv`q zN1}|lT#GoLN>=V;3Qk>aNfo7W$LE6IM5Y)+yL?+%@>ld#%h1Lg$SMG$NtxPQ>R zz<}ljwG=t{+lOSC2^PBHwK|xO=8wnqvD0H zlBT~x5>?f|Ns7!f>8X>echh>^GX<5@>c&PBz=kce(x2e2q4ZGHtOVM(7R}-0CgmsW znR%J%p{sFwcnG6+eQ41WH7aP5%hPRV{m-?dN9jAxCfCDM864MVb9*4Y*8n#|=sYVx zfpW43HREo;QVfrdZic;Db)OL33ZfDZa!wWq`bY06Qz#JNyFiC0q~y%igZ~YLCj>wo z&%bqa8ht9aWcJ~y)EUE-!YfO)>2@zG+)JN)IqmvWT&#I~fRLg<08rirGj*`OLu8nl znQ6Eq@{fJ<_y&+z!N1{)>tTcpvt81E??QM$k00j+$qc8DD%o36koSoeTqDfU!%tA> zaOds~fC!`XMxRw&{0ux+%ditiwi&(8uZ%viReLS^(xIE0o!~S(LERlLxVAh(SQs|% zuEPeOR|csRi_?W(t3J*@QswfD-Q=Z$GR=&%eQ|&lq9`FzmgMW6-(>VAhsx(`&0-f9 z??S^Hpt1-VB8osbV1X+FUNQi4kkQb5nl(LHrDo^SWN_a2BVea)_X+IC16jO;dY{UY zNl~5L86iGCjYYEX`75!n3(TEHS2g_)msjulvlCRAkeHjB`~65uqBl36;H}WQd|3fj zE^w^6fjhjjyIb;Ip7Jytv>>Df5(Pt5RTcPP!n0Ebfa8VqNx2#GpCJZG;U_f{^M|GX z<@Bwo`J?{P16|~+v{IKBGj)lfi3v#&v^M|RS1PeS4rid&MN623@^i@@mG^&BJbCg2 z?MDILpddJRBUH;2w0NO?18=x!^pA9O%1?>ybA z0FVp=83$A@pe#Zxl$M7A6Z9i3EiJ_`uK>z+A++#?MF}zaW+S$N+8cdK*jj3E&p|Zt z*SuVp@?S7zT!;k<13`o$&Kq8%lY;?WlHIMf;Se;X`^~|J8d$Pd7A+o!0g8mkL*E~~ zfg`@%5n%sI^dDPSBcUIX?30EKcSFZ_bHH(0p0*;Rt;#MBp*NKW2*PD zCAOpM2L#1Ye~E6Q7HAcef14?Glk1ERq~9m6v>zAj$k_?to3FvbnIflRu!)s*{UW%r zSxe-q!f%gDPmcw!v;Vw_F6>vCVJ5!6C+5@zyT|_%ci0SYl(KZZ3hNt~)gDL>Fp=x} z>O!Rn^>#^92CiDcHCHbZG)hnyz$OJ>kCSkIvPZLdp9R4AkY~R0+TtafVHC>I>G}U} zGa9APSGPdxyVp0reSzHJ!R?g)dk2S}$H<5IG(QTGRwq!F!Fo=N0yO`5={ubaz<}*K zkMV~76cdTa3Rd=A442Mz8y_VOLoCQImRhlFD47!?82e*0x;5XCu@ReF(gS2kit?p-OwO;W+k#0qFogHFmWK;)tdvM;F>vR2oO{DH^M ztm_>m!;jtp^z}hy{B6*oI5GQ6y1`&V@{%Q)Fut}}>m6oYRQrvXA> z-tf=RvrHC`#rEq~VBJPAQ!ydh-coNh>9|(I0hBK(KKZzub`!e-s&PvU^L7$-E$8${# zWcPAE!RhjBf(GN9MpbaK;2{e{6B4E`@%?t>^4Il(CFylSo{5UnVMKj4R!}r{T(+($ zJTX;4V{^D&6znKvW#Zr#%fM@IRV*x6_^G1?r$o5DYt0tP<~jDg9-kPc1gIN4RM#n= zmHt8){ob#P!vI-!`ZGeoe|Pp+}1Ek$LQ4cO)S#s(PTPOYr041F8ppc{P0VT1&<5MjG{bjMaEoaV<( zU6^gr6nx^6N6YtCh0H4j^v`kJ52XA5&vRG;)wlF8tlIyou!^6nvpn|t81I9>*Rx~H@JRBAaDXIWa>1uwYiGZ zztv(bNc@bA^VS;!!8~?valRxIosi4(6kUbsVgI!jmZ$`L&qAHk0FFzsf7)PSgeYga z9A54Kz2dV5lQ@#4*x080Do&UI^H}Y!+;Pt9x=?9L_6M&EPD`PFgLk=SEA{@^hpPBFT4c|^_mh)_73xyPxV+K7Hm)lVwRb zgKDjXrW~%?EqPmV&7m_b|0&90N#=gm>$rh{74FF?(>tSfiy;1B3m=N+PXdP}vCNPA zVy*GPQhAU?htlT!+Oc}_lb1{c{=m<7I1NP5ya0IMI`<>D{uMs|LR=XeF;Ng`tE-Nh z8OcPopsZd!Tc-AYBiVHaUl;ySOYnEX8#m7-L^9wLh3@ID1tq=uuD9loJC6k)`f5MV z)c*G#XhlVY^MY7hDQk5y%7zq8PmHfnO1*VWFHD4}h!JaNDhwibu5kY8}D8do@)7ED7=DiTs~ zqyfBQGW10A2dq%i8Ultc^oRS~Xa4eLS@UqO{T<=t^77z2y;u&uc?1LMM6UZZE-^6- z%!K5N2BH|gIOO#Fz6Zp6fDI!4o}9Y1=-C)K^%4$%e^WWC{yx@#mYL!)lU1&-A56NR z(Xp{^|4+`NzdcJeJ%r3^!U2H4ztFF> z$a3uyb+snv+wL_m8vFF=lRPk}(8HgR1P!XXwVcF%7AL-8P{0Rg0pK7&^o@MMHA9~vQUoB~lZFX49$wSHz!|+at{7%8)CtmJ=%2_7 zf?|l=Wpm!Z;sIc}z}|wk=P3dL3QNN``Z~M`BvzyZ1VK;+mk<5K3@8>55FkeG9qze> z?P4O3TSHb0a6B6*pn*--SQlCdBuPN!EyGR{TVhQ}vZh4uV*_z~UClpcy2#${9-7rh zhL(wOz>N_VpngaG${rm3gtT@dAu>&N1 z+=7Cwzk6PX>L~z@?}prAyq|{ZGubZ97ivPWye69 z^9R^Vk~lya0#cR`Y{DDT&|d%+?nASpOP-z=;h_clmai+ zyZJAe{k=Ie&v-WC-E2w3?`qsX!Bl1+G0LFYYP13$eD>rC=F9G1rM~d&0h0+?VFO^M z!fC=Tbptr2B>1#jZA{QTgNi7ejfDjRQsRze@k`3e*ob{d7+kHyW^#Ny`=5n{g&Vf? zkbk#;D+qd%SaeZ?f53ELF}u**h7Sz)luy63m_rk46^pJ6g~qjVPr69>CfB?o!{K5{&#AcVEoaVT!n_~AdO(F!jQ+K!Az8G(dPq;sB)pOnmIuoZ52=W z?Gqz$0EBjR>Ac?JO(1X>eoxNJ_ujUr)wU}7%iyybSYs$F2$E%>?L)VR;aNp-nf-W; z1X%ZCB0AhuilX?bSLW_7D}b$a^vLP`$kXs1AAwy0dByH7N)4vDedkWDjsj>1On<$E z1{!=1#1$g2K>$O8o&RAQPQ&h=F4q+AgDOmq7twYb8gqaeV-~j z#Ru7W--Z9l{{C)8{j$45dPYARJ3F-p9pOwJkpLaRBN?A92s~Ec9(@O{xv{a4jFC}L z|1NAIZhn63n+1**JutHX1c@yU6CXc*GGr1|y(&+DBSw!^-Xz}D#ZSijl8VPZ)l&an+)KRxvMc zFZm}pF?;RJb)(xSclm6LYW%Zjkqn`iynMuKZV8qd3rH8fr8|PB0VekpdB#xFqgW#> z6BU>V0g^N5)=i&pjTCVjAI;QLvBt#0VyGh}AyHLT4UNm6dZf?W0;Ggu`vF0upF4{GS5&&$10G=Ie){?~|4-|EC2F|Q?x#d8MQ9fm zO#nnd2PFXsCho-x9{wu0qTojiQj+W<5S|D%te$t+#K*@Y#exEs>Fl~=$tAE!&+Osk zU&fX1OOpez&u6&`52`Onmw;b#9zGM0Iv%H|ujnwm6oeZH{QW^Td{TJg)Ye4Gkn<;~ zzqcPCf&P8rnFw&>)0aDuja1T;Dy^I4a`~R*9=**8@$nfM8A!k;rIlN);3~+|FpT5` zXvoNzx9;oU+{)DDmN}+8sY>Q0K-mbVAQW2!z1i!RU>lY3>H~!f`0@&G`@pw?3_j!P z_I4O}85WWP8wK!DNE?`;0Sio2;p7gWBmOJ>5d`Yv0Kn~H+LED333w?0$H02QA2H>S z9^`UFaR~UV&`3vj9vs3k@Lr2U?=Jl^%+JOLnap^t4;ut}z=X?;ZCW53^1$Wkb z$npOE?rtUs2;f}GdpFBG{{9&@&KF z5}@ZdZCYqtJVi=+35=ZJ!2)kkh(Fz8#4tG+KiRa}9iT;%UuTL1dqCSoZVQ{(#l;11 zJ4`s;;1hu%GulE$P^KRkfw5e;aP=Z;wv{C(2cVh)a1kN<)SJeR1Z|RTn?g*iSy3B& zauoRc@xu}f8pnOY{iGsWVoWQL9{OayAcDa1_rzHcBqu9qa zFS6Nv<>x@*j<`>!0oJw*yDIeNr$B)6?<#9Tx^KtW%9{bb^`{}(2a-s8HHMY5fKR@p zilM!i#k-%hnrFG}`Xfg1BCmj7&#P!kVf#YS@DlO+#5T)z&c1_8_Hq`8MjiYqof4AmKaN3U9>v_37>PlK@R?Dj|V4n{?ag;9%;uQ1B?mply@G?mO zdyHP%lPn}8q*1ORN%-8IF6K-JIO0&eKkAGSE4U}JSY$yUDr39^OlJ%Po-5@yCh+Qy zi|#HmmjgdfLa+qyf~^4SEa2MP(-b^+@tMkH7kad0wV{#Zg+f%FX)@$AG~uwDAhOB7 z?Dk~Gh@=&RO%Bf!+-@hKj}90d8V&6o%~YNP#*FjdEs^zg4cD>DCxVCBG?=aLl zc(YZD_#2$hK-xuB;2?EHN#9Z!Fq zWs&e;we`2ndi^M+FmxW7z{7)tkx+d^j}Q81urq~Kj*W}^Azz=IiYk~zDHKjaLJjYDxkLdHLybLy_oN6K zU;x*IKwNF22cR!HjsYf4kW53!;qu;EgyS8=4>h>D5-kRpDxiG=o9DqyUCN#hZuXf! zGy$ZC3ixKd$W?cD_u4B-#qm^4_jaWtp9zKTs@gznA`AE9)<)q(J=SpNcvxq2TSnU9 z`$3C7zW)zCu{ihZ<~b_yD(%~Q9YeTpB%7yxUNSwuu%0nyQ>$=w+U~Tn!L2VBSxlU4 zOw(ZH+d}nv(QTdzyW_XM+ zwkI5DSm;zCnv3_C_x}98`ZDJ{;L;Qn6lg$1!wF;!%HTYKW@J+_J=(In%6IDT4xI<< z90o`L1i;z>g3(B>R!9hB^!Ya`NFckuf=^RkH9uU&$Elshe|G{j)nHsV`F_mr+Xwe0 z0y(*Q-j0|<=?U=LI?-Vt+#Rnu3zp#b!i(Sp0(lrYg*q^_g2D1*`ZHI0ez&W_H+D0> zMynMT*G&4=;GPxn`nGMt*c?9#BtPAIo6+&m>v3MbQyib9iq!kEGNJkcPG955Qf3Eg z4DfqveXpdMmce<6Zkv^gLDgq*c>7P(J=PDt>KYmt2u$WNFs=)f*5FN$9Q*1~)-mQ@ zWwKoE668Aq3HUW0#{C&g0M7mWk9o(04R{kAi_#;XoX&gl39?30PR+se>a3#$pVDBy zEqp2%O9bjF6~NRfxpTh(qK#HJFbfg(KM=9=F5T6*kdvM5nVr|Qbn{$%<2_mOq!uB> z<|&}TkBz=^QaKrc4V}!+MZPPeoM`<;BiPpTA5o(E?2N2|`89b~tXpP+BO1vbf%*)3 zyH%Pw0XdQWhyj-vB23+M&q9MiYqVg;F?HZ2`}sMEyya1YhrRWEOGQs~`gY##rx)b-Q6iB{0YALA_v9<&x9m4Cc^Oj9^Ki|J$T+aioG2-j?zwpO{#`#S6lb6y%=T zBVg2GlF(la0MiGHYJrH4?$Jy3Ks=N^{ByOUPZ;g4;t*1wnk(+ug!f+qX`iHYELaCU zm-adjPB0H)HHPhgxjHzIM20bXtHo#Ik8u6r^}bq}SyCi|fj}Fy6loJLw8kh%edL9_;W)>u7g26qE5k%fuaC*0FO$a=S-(#o$>^K;s~e9( zh%>^67SfN=$NTaUllVJCzT~0rmAJ=iyBw~n4DhVZJIhfm0nwJoHcV%)O_fDKL3GX6 z(@kJM`^Mx%p;6+{;1&h*V+Dzw>z;0Pbfs~H2y*yYNH^(yhp%Y(jW+cCa?X@z%uM+bUt9HW^zPAo=g3-vCqrCRcr{~eivrHyU|$IH66`u^u$a6X{aFZq6DSR{7)843 z)~pa4MUEMsirc})@4En(k#RWj5+Dc>rdNxE!mpTA){ZLjQhRUmX_W@nWDb0NaOWu~&y~i`9I%63DZU8A)1)XEk4RS~fkh@GAYYIi36U zq_Rrp*a(&1en8V^LCrLdMfz&ZC*O=;BGltp#{}2a3}4$baPJTC`uoy+C&713I`+#} zN;&eEA$TK+4Ihj9U~kLcQUqpcfldyp9;o&lHOj^X!KW%S4j}_CXqc}s)geBi3|3Z9 z@rB_rJs<@%bqi9CT-QHV4enwf^JJ@1DUr-|DNU!ysFm-dUR_ z!N)Jhj!gn96S|+@QVAhN2Qy7pn4bqCp(2-Ag8dn){on{NBw>Tk0Q=-qXJ=a&lOMPK ze6gX9PJng$Gkn)QFmfl{uRA{Sv4}>kc)HN7d+x!`J=CQJk{;?OMt3_sKn$d7h-w=^ zRFafL03Lu)F^839(Mj&BQxXUAXA|mEj)xu1%s~u8TeUBNfe-G#BqFmMSZ^C;1A~6K zyBK~9&8;)1(_=av>2E9qY#jac=UUtkwohX_4YIkjZw8@8qVa&^Rr?(m$%C+6n+!8e zLhyl*JtO`x7fD0B@5eUc=4COlo8)W?KiWjw? zXsSIIwtts7c3{|G>5@cxbqfdVCkdRXj`cR_a<^`Me7u@kUcR^=SE!?XNM&PMNLHlJ zfVtVcU9genm6z|}=|9C;bNJxYNMLDj;*4*9Rr21Ou6{9G*m=xO7qFAcUfP*&%Cjm> zYFuutD4!b_!%g)-)U|ybe7~`&N=BP@TT`HyeLdN9x+hV4X6@`6K@HwfpY@GRU-MHN zSO|rIFksdp*OOx!-6;7q^Ggi9y=(6kw2zRuX(s)W(RgnE?q^a@C$o-w!GgBm@B0j& zM~DJzI>@HxvSvOJu-II0mu;+CRIV4AxZpd40&SUgmSy@3pqt6b*=xxAY?AweC`CI}^^Xpi}*J6r0Y72tG zKHs9qvjnpR)XNCO8ZlkwAgNxsrF8`=Pbhy_1Oz%P7}i>IALK-YHbABcmLOV>{%;pU zw+D`M=T4dJaI`xrs*{7?cC+p=54tWpjYM{Zk6sXYjgVM|u}a!z+~%X#XhAV==mhjG zFO2)WJrt32V{Wx@DIj(2W-C4r2K3Bmo-+K+BYD<`$ zd^hwi?s-+Tm#8OukUOTGVLC$JJQLah{Tmf@xJBdVzTtW8D*8^GQEXJ6`VgT=5$NFS zhH&qAG85FNVULXu=s zhre_;y)dEdm*Cg3Lw5+yQ$|-?@jo^06Lyw4uGn)QcvFZhaAy5!q^9YKJ$2X{ns3cC zRRTZhdLT)(%jfgVRH~MdKY7{lYDim>8)fEhy;R1?zVU2(t$xE+3f*^-%*pA%u6zcZ ztBy}xm8xRn9%RVva;zI}1v@6X4IvP2ON(=P(|hz%xY!wop0Fcr%D9IwoC-Ev-gnaz+Ucz?V`U?O_(0p4cxVFP%oWd+v^28< zKS4A8w`x}P_dmhL5w>hT6-{%lk%xQ+V!fiJax9|^ecls#8E<{hgDxdfi!bp!&&3>) zx{kngR+Q1z4FGr)P(OE$T*`eBrGYu`uFtBb3wOtzEjlED&J;j!`nR+5ZmLnG@fGl) z?VHzr3G*j(^sLr)ORW9$W35ru$*)SUGdzgs}#YVer?;L28jPvh_q%H=Fu2E&QvGdMRPw z<-`a^)E^auUU%(~Y`t+yp`S?VhLl$_OaI(-e~0UcmjB2G8{vx3*Tn0t#INY)g1t5w z59n+5q_N|v6)Fx_y2gxuW|uEI%_OGn4I6hf8Syvs!&ZsVj#Em3%<7cJ!@zMkq=LeF$lJfP%dF3b#EC;it&c^Ko@8M1`od1a zAtM%Ial>vB%%xxvGfAu6T^q_`vW*EPG+&HUdMT?%F=yiuz9J4B$Yi24T$ zuu34DqV*=M;>@1kd8v1G9s_g^wke>crukj1G{p#HM-}_Sf(E)xbg{9yPRpX_{abn#rkqJ*y_PTskb~`coG7Q_61YP?|v& z`NsEBh3B5iMHJ*F*Hz*7mQnZLH#k|6rBrs!B$>KD*6G;^nr1y|o^1Dz*il9bK1CXA zB}jlJI0q(%M1Joo^li@)8JY+v={#QVL!y6Qn(T9nY=Tj-<;kt5ON#E?Oh34Jqr7qU zU@%pKc62DS;N0w)U)p~7*7cWyt<~?kz8QH}*@}<1)fvL`dXaMU6`i%Xu7=QEXHUOi zjv5y~I+B82yk-8h z$-30ux-81QFJmb)S1^x1YlWLXkm>t9^4xT`(hW$q6FYsZ?_Oq|?Y!+=G8&dOmfC1F z@|||8MskAqu-m{u*5mh3O#d!6^q^^>TTNZ40RP6G^`WU7AtbC}vu2BJI!Cmkub5n= z6USVbOP~4Ptb3t%t@}r>cwd^hAr$h!KDe}pncwa?$cy*s*7;ohJmXEL^Dl~_f=Bx4 zmYixVO#5$vO8SZeOxTHrmd-TDrqM@*wB-?Q_3_;8geOSDhnaA#fx<`i)1*-D)gO-;Uw@sQ-Ta0k^l+V{eD(^m zaGt3=J0AQSB>B@%3dz0sx1N(2_NOz!RF@JgVX+a^t_n5-vU;%5Iq+qvFY4r2VaWfWLK+n@a9N>%akNItXXs5B~R z=sp{E|r+6ZCmrwRUA))XM!P%&gTcp-Scovm3Tqgb;m#&?1xVvHXr7qyf z^zoduf8i7FF9wf_spbyle72b;^nF)I4-%d}O<{NFp&$s+<5$Uu&%}w$62|d2!wuj5 zQW&{0km5R@VkkD}ZY{~xQ~lOaGBx??+zPSv{B~qRB`*Ol0TIs~q57O_83(^ezh`TC zuTRhHU-FjK8h)=e()F~wXl{DS%GTxET#a11>zAYyk8vkw{)J$#9|v|?qNkXK()26y z^0G2BF*0>>JvNpxRCI5a8IzyF_Lf$4a41k~ymRM{ysPU4@Gjy{!^#q0+gM+3?l6+E zU@cElwzcJPUmRqi;QDrv&3NeN+oHP0g`)aLptB+qAG=Rkw^`tnSy@Q~b4(noshK|y z!ibr1pA{K>1A{3TaoYw*xiie3fq7o1ojKA7;~r7H;8#_l*z@zZ&ZxDy;gupRuJI)O=1o;L$MWq)nP+9QfO3yIhW!}0w=>- z0~YBdT#+J7VN%2Gw!VG4$>!Y@m)tJC-~PzN5A<3Ay%zS_x{I3BEt&c4TJv8o#V#u= z^W2^NRgZt=H6?t8t0p})A|~Y1=g$g2k^XAq8q2Ez%_&GSK2F_Ze^B@K z@WY1p$V^J1S?9NJp)HmXQnyWO9SLr`?Rbw!4BsuUr1{`o`&Od$Xxu%q>=sKt2cb`m z+(~RdiSLrm2W_1edUtD?a&Z6*p*Xd8gV3j4%jJ{1^Mz|g`WY97On=UAzl)6 zvPu3b&rVcz=h0w){geW>M^UtWYFzlZo#N{iCdnP!*q?ch{wnNZYTtB!*u3}sCL=6i z623D(WnRzknEtB5F^I<%yR^^*gU5;{{%l370bN|FD)aq&7Zei~rf$5$-jdi3|3a|- z-1UdCZOUD575tI2a!8l4mZG+|&XsCCeWp`Phtf8gOX2U|i|dNZV0@NPXMcB5u##y! zac-Np@Mnj1qw|q(cW~gd1&nYf19Dv%dG_dg9gfe#w1T~U1y}BP^SY<~oO)`^=R(9V zvG+hD>gnW>hjLjc`lk=s)3FdWSEX2ro4pR5AN4L0{4m$D z=A+CkhM0?vnkw;v1G_yFmncPEnF{@UUH(4vGTi%*(B%Yr5k;M&ShCauEko1P2iG4Y zcZ5RM->Bf)IY;mZ`@Ub10Q3`R=Twe4K7f%(SwSDQ#K+hj2hl^m4Q7DR8yaASYfE>% z)oFf2sLZD;A|iqyFs$cy-DOCV! z^b`&^i`VaJfe#^pW5tbT#%eK!GR)nd;`I?=9)o4>yLlR2z?Se=oiEb>;$mU);}r6^ z@^NY^Y!XOc!eK<{E5ihylq+2DrLL|%x#kIjm!`5Q!Fl8Yz?Z`^LhUY%b5}Pd0|d=I zs!W^{IG%XP+|Mfeu57q3MgPb>f?~|8c8R_^N&7ad0u!r(|Gu(J76xx$-{N`y-MH?* zGY;YO$fD7E^mhAU^P}5;g74fbea5dj(hm|;*{u-I#mXH8wW^kTUwz*9L=yE!5L$c_ zdiYX{52L*~B;YgsfbmCTZ-eTYQ?RrGB~oABW<58E}KThS$dD(E@+ zFs(!Mr>fh}AL7ij)J>AJwA?*~VQxPZgC8xc)tGPIKJ|X|Yk6l4nPj}}sNq71HpAHh>(jOb=>Vs42w97@m!5H#+ zIr7@AJDGlKb}Q4vJ;P_D7UmNy$2QsN3*O*n7G;%$k~mV7*qFYf?dKV2*sV=Vbz-g~ zj&f)vwRllU=F&}nQSeBs+M(?EHSV($dkkN9t&6Wz;SN$n(AA0Q$`0#O=wD9yZi*E zrZU5mI{u*kTn(0WVEb%iI62#-OH~H9x_WEhA;4mnY;E7;bU^V{Y}rD9#znc^&)Ud) zPVDC$KPzXD+9YhU2|HGII^YdSt<+EwQuCv1t!AwQ)c5OtkJebB3u+w)9?*g@-3**vXkFNGD9o)tgcNn9UC1S zeAf`d2? zRMgHk#lgb#%#%~P**1}p;%@yur)75=V{YP%gF&~VlX<424@RBab|f#!b;H7deUI0X zOT7+44Kw#XdM(kencUn~$KI|VX?jYo+LOdl+*wDb*IHcZ+$35(T{k=N?D(OzrNena zUs?#GFV|ugCTrYdp8Je$rAzl0@M65_DvwdU`#sd}QQ)(AtUX$%Beogc+sY%7%_;uO zNngnZ*DB1~POl9pjcsAZ+YU5I-?glE+b*a!WG5GK@}uAk<4bzpqnG*-&I_Z~v@>UJ zc!(5S4~q7RZB2cBvrkpm?d4MW){sY(y@=p9|IrtJ&V|I8e>FWbdVJ-;OS057g=zn* zlyVtiMvj)6=J`u=gbbk{ri(0(?{zFU7s%{A2bTxvkkgakvHza=DRd=C1Rr20rHk~B z-tNH>yXbzI7+P?*O@aa(VXYWdonNcR0ZK^a?^nqP($UcYeeZio$c*S z5W<7)i)zc8Zk>8J#7`k`g|im31^RtcYo0o$rZLdoYnr306sKkj>{q8$b*Ua3taN6B zQAz&akBM34V-J}4A6hT&^4M!k?;kqdOqHPPkMcIOMU{3ZukXP5_(b;caD~Nl^6*cA z82Nfrg$;i1Qjz=%7tzK|JhIVa63u>1sYZDO0j%dWSQ*jt4W z*SrQdsq;A!v%K1`I*Z4#Dbx>^FLg{kG9z3zi`JvM{V&C6TI@}YEO~JJO(g%6U%Ymu2R7(Mh)TfVr5+imk1kdTazh5Rd z_uXd?SEH#D)tK~|b2Q@er*k*w|-wpjMEi5jmBVcYN7j0J`s z10o4?%n5yLdMsjriUtO#1!zJ-0@iY<-v|AquD9PS$Cj_$2tLu=oFs6%1De2Nx4cg# zvV-kjAi{6UTI|E|!2TIcEw=LI3v-DIE})CZqUuOaS8g^Z{VYN7jZO|5Qiyuez$GC% z2Akn8A8bUwHgPK2=LOFFzJ8gjwz<&R$+OmM@NPL{g>dfMw-593d_UMIe}GU3TZ(ao zi6Dfz9gFLd_=F7S%9Co-N41Kdx-Q1j;8=ryshfQtrcC+D23kbnROI)B+-T;1lStt)uPcwnUyo zncf)&Jqrv(uxf_lWmBfe2Bhv-h+ySpkeTn%W4ok@uvc7+0Us<1x-+wJMuOTccz9Iq z4UmWw8F%kvJiX=elX(MA4hPvWERer5@Q5*nEit~aZqfw_*q+LfN%GO&64hHwp*ubh zW(7}H7GiFf%RDLVN66kST#HH5+T$iXJj9vx<#z+sHvrWk2{ST){2k#9`P`kv+M8T#`DL~Z5LiJ_N{1RqIteID2F*! zC2WyPZC=rcpKhuuO>+Jb?qk}84zqS`rdSrm@t3xiZ&kHBIr4N}RcxKHCn}JCcam;h z&@(Ue;6ma4pDTF_srH^H;;T=A^;Kv+!$ZkaFIxTE!2P|Io)CGD=*zW$P>7v#Og;|O zo+PBu7FRrB9DC{Eb5dMX)p~wyi9@(j%-#6+q&(rwJl7svkycq3r#m)QISyZ&q9a$o zI$!U7FZxbL0oKHWbyilF!*}hr_-ta#jEE#&Lsr!#KE$T&ec{yJghT@Ecvv05lpp6D zKUIh|%PI|$O^PggsTPvsGyDD}PY6EaA;CADf#inG-O)lBg5&Ma8Wn^IaNAQEa(?wA z+r7fBI*d@@CFL3|#hbtESRqDD)C1@0`2m?xGt>KUfy;oN=5^bM;*9x2^iUWHA%2=@ zqFiD0SsEToQjX`wa@T6ribbAqp-cNuk85m!7?&(nU zt61M3o6PG=KTMb?B4CJ4Kf_$_+mK0g39oKhr5l%BmWsRTDG?Pq=E2O(BN93xDmO0= zRG)$Y_^c9T?s6Gf;~I|FF&wMGheVZD(%tJe*tId%Mw_T}lfv{(LGK0^DFoP1Y&R>( zGz6ue{_1%S8=zr*@9c8C>nw3avdPIsg==Z{w@+JdshE#=lfAoP8De+hPXcyptC%#J zNDGX%z7fTGJ78Tsx2Z9tBuIM~t<{KsMsF9_ddyw=f`F8O2KUYMqY?~0yza^iG*!EA6 zj}sQJ8Wpq;y!5!>_6_)h8NDrR8p)~MzpMEnq~}QI%Dj<9q^nDDDllrGN542CG#6$H z_c~Nn5eYc3pJNcjDR{|HH3KXw=dc)_QvxGR08{8|^%A#tHIMRE?AM9~vB--Q@Fe-Q zv=6Z!=7+ORaz*T2e}k*M^ZShR-Un8B3)DAbP*L>lk6CHN_t)oP{ysfg%pkh=t-^^Y zXm7dHO7|qHHL((lhpHL4`s_RFf#qxGmq8fxLIUGB<;gWCVf()oB;|%WXDNB&jUSzj z|BCwL-7k9gN?NPeUFqGd@U-vA;pVPY_Nc^7*{6R^WJu?_={sj_nw;R1*mgf>OEUFN ze81Z6U_w6i&3O@n5+IHiCQvxo(jSuisyL3E8^@7DbT#t!Pup{{U-BdOyP67(V&c`J zyX(vkR?=c_owUe0;$j}nS!h_;DX0dd0d91zqM!CTe%wu7B8z|QNp~6mkpNASk(+x8 zRJafVGXQRWJ6?W9`W#Mcj=?+2HXQOArxC}^wh)gYCz_K1uWp^0-6`#4&`h1_w@O!7 z7&J&1Oc5oR4Juu_^6@6uEj-!LQ;QAPaM0%%1M+Io6|>jy+~?(1b7_|HJy>8I3=`?g z0`C_wQkgxDC)UM{Pvx{Z3ANk{r+DzgQ=ygR1Z+jQJSmoZw6@NGeL?HV(~aXhix+%v zJ!ZNiTgeJDUuaTw=BZr@M}_OXy$Y~%r)Uq#Up3V2#l52Y&M_nRz7f?zJor)ZqJ@R~ z91~i4fwY$-OoQwG)~G&zQ61;>fKjgu+`hJBO9L6f@Y zbi7n`;(rXSU*s2y{rmROB68vbO3lq$J&6$#+f0MW`W<<)>&g*`JF4+^xWOGVPHd* z>Vfl`QmuJVjFj}wXy@_%fNa4CmyWE40hXCM-H<*q8c5AoQEkY)HoPrQ+^gVBdBi4TqkoT=nbd!zFlo%RZ3wUQ=PT;y2QThZ>Tt zymEm@MqA0|GS2E!(V}!jv+w4Hp)X%9{F7193l>jNKCs>JGAVL&Fc?b%$4V>b$Y)E~hB2qV z8a~%lt*g17e&S_yk$lw>$7#Q!tUus2y@nSSVACDt!AAEym|ytZ1=2&Cj?XL4-xg{n z;aIdAYV&h|*-hSk?ILO4W#cyTvFEZ4hSv~-reR&HSYOv!zYX=K_YbjK8!bYp^Vu3U zuSF;xfBaRze768y!%feOBGH5x{qy1HOBqMhf30e$} z*4eu%^g=(CX%alnNUrHt+i@Pe(QFR$7y|23U8AJ&UYeW5a(LY|;Usaxhri8^qmOX+ z90cgbzkyYGv@0`w-mk-F%C+pPn@p}k(JoL4^&Kiy3&?&xZvk@ z_?ETy$F{zw41XLW1+d$XjB}&tTL)5NI z6XS&WLzzl=Re20de77!tYd6B7U6Z=pa;TOY=Ewgy#Dgipu@l@~Dzof~8?QbLUzxn| zC9Jt9lxdP8KcyM3++hamvTtKd045!;g_up>j?;bJ@~hE4z3u4>4s{(XmgtAU;0ABM z=?JT3i!;!F7Q^mhN*15&jkn&r7k*m{Y%Ni5QT5$(RKdbR%D*;7Vvwhl^6*VXd;E*)#f@Dc4pS&D1ge=<*4 zk~sZJw9sKuOz9*_=a45cBu9{0%8fYw4gC>|Tl=+Nio?myuH4_*WO8vbbPCC~qkf!a zxRs7DA@^LcaRrb2OO-0Tuk4Vc-zHTV{wNfF* zKU<|s)coTGE5*x8F%r(~uVczgf=v!7UcpU2o=zl&9q;|-wsj-!Mj3?+bPcVCY$D>h7E1nkynZKVuJ=U9 z$nB1*Ih=spT59nn*UxqdjrUq!o^GZYRrv7%lWxC!a;)-QH46&m@oN9}&~(SgKbD0t zG3nbrhsu8)k|c4#usM$Poa64iSJ0bJ1UKI2>>uGrYX$O&IZ=koBEy zIjJWN1q5f&xg7HTuNOD#t}cy}dCFct-9Jr){Y6c*Lr%2AE)m3V#4^;@f&57+m@Oyw z)Q5iJJCiA^XuE%H;Vrv*2y;J4I*Y-TpW1cfj+Y(b(xddMDh4U{g+{;>2-yvYTuy2q zA=5A7Z7SMB@{i|r1 z&suj{{;7_5-AX{wy78VbKFGzFNiAJ>kn5|3~zSkLa^Z9y{H4m2fqx;m>7OB7K=v@kY6$ zz}BZ%)uxVl`4Z8lP7t%3-SD>cutxz=(juS4<$sU;H%x1A|^&^hq8vw zy_{oHqj+eM!plsgAW6aakJ^PcX3P7K5l{Aj%>sE`VhW<2)a_Yfi883He`-vSLw8F= zkD;NWL5+3rqo5B|rCL5g^Ijouw`=+$3I#X4frRfxu*M}5hoze8 zm=x1|&*hAWijXx&vg=AY&WE2cOnB+Y!(_dF&3T469qJWPjf=OkqH=Q`tA}&mzJ1y| zr)XzqhxyXd))x5lfg&{K0EYR?MKX==6xH7&+M^C!haxhK_Vey*KOhsS**0RM6q97) zP*c#c7lM)t12ewww1y2-#~ou2jkQNxzkd&CF~21Ftb{VhgZbfS;@DssMrO70+t+C8 z^@}@?9*M6_Jz1I_D2)GHj}{E2bO`+EnQzr)Su+gTi$kWVZDd5Es|zxFfgllh7uZ6e zF#t~(c;0>A>0L+f0BvqBd)s-*%D~ntCNDP zYBL^t*W&S+qnk({b-VBh+Xq(75M?y5r;Bj@q2*j1HMz>g6wqQTB*}!5gAUT{>@#a? zw7(uu{;=$sN#GpPa?e7$Qit`KvfmY$2$dIUO2Hc4ygEj07k)YbExaof`U-(`#v!w_ z4{ZC3PXb0Cpi~Trn%UU2_0vV6lu-Oa`KG6HfBeEaK`Yx8c~Bgcj!S={mB(p zX%;ewsDt2qqvQaU15_;`xQ-|JNDzaeQ^Z|HJ&c5>I%CuSDYz~2jJjp3D4IS?kReu2 zWaIdpXcF}9oE}?xpjlK`w!qVLzB7_8d{n$STCwUpaFK3ez67O8wi*=;4b9hY->6uV z-M>tiS)si&R)2mrFKRGXZA+NESx3anp(YLiJ}@Q#y7TF^iFYX6X2^Do%XAW7eEYIv z3c2-5TUYm_t}ddF0=JBB-bwd6|IJY{3BC|fY8ViVW_E54fhb3!k#`|9>4}NL{i8d} zNcd_;5Al2AKA6>5d8>T^0xCVnkRxH_my8Hy4RH}tsF0fqB$JI+U!$;=KGmj27OF4kf?Iy-T<2mhEnzvdl87575-6Hot#Ay{HH~eccKL66B7RhU&4?a$tkl(qH`R zfBucdXVhLfvr$^ob_uyrWNJKm}{F!ix}j zFsxid-81V>Vb%L=&mE#RdIlZpNKh3MQP-Z4a_2iG;g{chxwvq;_&h=n1llCZ_c~wq zybw~;Nl9^7ySWq4F~u0e`qzy>mQTajCtt+O#Xtli=GhcVZY|{IBIvOOfBSPu@?&%X zoIKdkIRyop)wz_z6bW)dPGe|55>oGOE-EW3o&+xHMYq4VYb}o=Zg1Yz*JN2P(%x#C zK@o}D5v$oqw5eU!JIpx3f*}CF*(d(&#JeujyhfLqlBY+{jWXYC{E@3t*0S<+y(b$+IKR z1d&ESZZ4>ToI}BN)-zer}%blC?c+THJTzmg?E#QJgz= zl*{AI84wyFllbV71WckMY`af0E)2|fG22hBAoM|iBm-=($5)-u`rC|4*|ngS)>e7Q zFkv_JES`NpPC>#2&$`R4S6{bBpP>LIt}!#0Z*x4_&nu-GHI_^B1g=U% zLJn%h&(KGNT{J3qaL^+{A}T7195R>-u*gCP=SR=(s#cH$FcuKA@VBoB7lkYn6c2UGq1Wz2G><>c%|)fR zP~l2gb1;!|GLhnj+)4yUiCH-5Z0WzIde!$}gA_WHchsRQP}X2s^U-T5eg+c(KmVU7wI2lRzOqs1Dt_7YK`MhM zN(!;R$+hFJw^tJKJPyK|5v%y`4g<^!%l2^ME5))$YWZ}hf%9};6P#STMAv4xxC+a(Bx5D^ccf4r8%LBYij$nCj6!zJFX9vWXp^vZK`bNzC2 z;mQGq7yx3X=~1?HbSUfUzO)+rJVC^fUTdL44Mi0ET^jL14FU=rR7}5fBveX60^(Fo zqW%l0h}k7p*{8H11LR1*s_4*`#`sl0a;=9+vTn2^ljvybj>|q8U-p`HB#n>4EE1O@ zBI@`zpXc40OFyH05mOFeof#K-?UBS zVH^i;?w6Sg`)!R_vMVd;q2B|-{{Fplf$){ihtOM~clz5!GL8?cP<%cEKv_VbxeC?} zya{hR4b;v^n(KV%HXti4-=hzx9m36DsKByQXtPEHkp@E^fm8z{O+QULc4@9Ad^1au zNKmEfu3Kirz!97SnB;siV~&92K-na8KDqo%FA|0~-F5Nk#@q>;qGvuq!Hra7p!1kg zTqg3*s9K88NAZE3fTmN>b-n;OHWUcKm|hHd^M+^nKvBzgI_x+WfHW2?9=9*G!Zz}rXeB#1E`7G`NvHhsI zL7_eRU@%@`%B>oj0G2Ku{4e>e<$aQ242+*;Y`Wfbp&{()8Y~t-q-nB*@4RCFc8Tdl z_f5j|XfRdCmD@`m(n!HbWLm}Tz=s=aT8|EGZ;8&9V~9+tT81zkelN)|H`i@z{v9p> zDRE9Fk;V^lVtlIFp6+hE>>t)HA>EkuUNtIM<8G&^p5&L6(WYIu`n0x5f+x8!|Am&h+W`6*=~8`AUQT$njmdKPcoh2}o(i(9 z5h5>b(i;m)F{L+N9wiPdIWyPa7~8mjzOTQ$GVDE9S68Lr*h@z1QVTh*1lpI*H?6W^ zB$^?tN1yu|AfJ|5Mxy87U$sw@p};dM3~i;zR6&dJz*;`#t*>So*+(LqNMtGyKWg~G zv1udbIr7Ztir?h&!Q~K4Lsr*&$A)wmY}GSTVQxvAwltdu4=zcn&o=u#?qOT|sjL)? zgUZRt`2@cIIjKLN00cXL``XkIJ3h3?Y(SXeNq?ra;_WDro`b^Dr`_{Z8fcd&*PeI< z@$337F7RKvP&7Gduo;pBz20HJwk(~YFilaWh$s~uz0#kelci5~h3vrt9_gOo-qu5o zUYeq^9*wArE%vHRmi+-|y>b~Nvr>7H00W5_G?P`@yKAg9*ApE7{WG)7gXwu}DPp1) zV|4189Hc2JlAeI_-wfIhmKh9V$8^MF5GlzRb_S#ugeFcMMXh-2F_*?~#bzFC zPC3Kea6DJO^E({>IWz?NX^kw_VvxiJdGRSthd+#kzLNCAn`&R?d{TD0eA)gn7n;Qj zH!)`j1tghBm8++Q?A`09LOtb&_msb8e^(E$Giz;ajT(7nhqWpsVjeklW0ElT!)YC1 z<1i${Jbq~}iqusyLA(lT%lnMb7(=_Pz}++INem{*xez-(e-1a@-NpOsR*hw+Tt5ee zHn3(H_C6S8M2NBOpO`SP;pAu^t zsrizp%HIxq{7WG_bs@A$XkGUHJ7DmEOL3M%Keld_If7T~sR)Ox>o~m(BC0qmW&EBF zZm*SmP8ygqstU1wZf?D;81GM=U}SWWtJzl{zFE?6{%>Ti%4l6P9cnyxTSe0!o_KYA zK_PW5(}f|^T$lQV*)a43H(pV_$n!=;w~-=^!CU%80##?T#h-cv7YAm z(;IF9ix)RdC?|v--S_E;F16!@%zl@YYmR{7qLekXwu9r4v%(vFX}rff&V#&Q1mAV{ z+);uKrv*|6KG$(C?H5at4N6+!M^lC$r}BZdEzcx)YJ^qD%+KoLk9sTP(i2cp4h+d< zVAdG0@^+S}ry0B<#)8e)334$OPZ(0gyF@fo_s=Na-+P?&vCshhWXrot6W8?tt)c4c$hjfql^-;g%)WH zKGc$~{`x^iPPF8F5Y6s&WjpICw_yzlr1G2J9Be2l*7YD>LZKA3e<7``;G86t%c$u7 zu+GmKgx=d19T4e?|w73`4oXf0h`$dYkUkXt@K{+N)?G@taDd{z{D-BC32 zLmKNw|CHIszjW>F<@P$Qk33Ua{uAoI6DFyV>=1d)s-->=MnDG0r-gb95qf!{R`~Bd zCv9>pQ`CbPzif(4L8bl4*Xfm-pV3&=d<-4?a|h` zkJd-iw!Hx9n{xVi`JteTpwPftLz!p))f?;M^2XJB_cCB?u8^vb<_-*us%uk!PnKbf zYD`pBV~vam`*m;_2v{2=Q1(_IUc>udP*nJ=`poZpG#4#i_)1i>ao-EB{TyHIWc2)RIpjg7{2Z z*z+l*{;qPT3w;!i{bQ6o&5*qLcoPX*`|Z5k+3|!JOM5R7)TY2IFoGs-Fi0^%7>RF@ z9#Bv&zV_Dnt%?d!@4Ww{su8^?2g65>1J3{(HwBiKTMWnvLteOX(vMDMQoP;WO944D zv?`>aTX_xD2wOSgD>XowEC;fHV2|^rI%+BWp3@ZL7bj7&`W@QO-qYxAU;KoNJ0_!m#{0bC@O0=POuCAxLm@) zqudyoxUBF=@zd-1Qc=wGL(g2k<&G;k`)N`9R4fI z9na8A;JgIbj9EKE77td~YY@$JXH8DtU%o6X{NuPg@Q>ZDYAXBn@V1&74hrho8~sii z?M&tezu?~I!(1A|`2lQ((?pa`ADtm7$_mab^sB99-8t9q*GzNW0AxpSh>gy0VVOa7 zFospg6W{vku_x|+4k%&Bf~d+Sp)$;&=D@?v$a7=%;QqD$R)7;e69L?$T884b{;ecr zmF=3(B=~>fHu1)L3guBKPpQp=9Pv3tUcE1_<)6K0?k+pKNAo~^JY*{#RoyWC_Dt)4 zK~=!S_uxd?w&RLoh?Q?7vR-c%{Qduno@O1?VUWY?D8PaIo;T}KaCn>0!?`tl5{1g& zsK8#6?-q`_!=(_R81u7&?k3wKt_dlSFy(j)?MjVm*M zx6#W9i4qal)CQaT8rEm|@b?qHa%cJ8opY?~JCpUBlgfV3?R&tK*1XRFok0rz4A z5sEX(XD;(iX#W7eeLPz7HfKVLMQtPyxnz8tB}iF}8Y0Wh!6DfXo5uWLNtT`NxpK}! zR)&&~*8XK;$!{DcCF!C1| z1j~qY7yJ(w1zq|ceuBPpf1NjF)H%JzH|2k?x5xV*H?3Ip&$9ITxZ|AX&T^8qX~v)l zZrT=_xRF4sUE)GeP_@HC2{(d(IrDzzWp?_iMj?w_35V}y`Q{1z%Wv1kE$)Z9I*&f` zk2Trw*9t8S^SUxuKwy?6sqpR`HRJj0m+a#^tfdA}_^*=#G{Eb*pV$Gi?QxrY=Lgoh zQP9RmpToT9xd^bgz)O}FN_OYluz*mx?fXLZJw{}16)8;7zU-7dD84B}t{$X;J-cHy z7JSLlUT1k4y!LJ3?e4MZ=rDl`LZ2@E`96)?a{fjC-skw~q4(7!{dJy(Ts6~92yzEt zS5zz?^0weW7db#@U4$spLSW5C0Z>Qqh|4y8lhSGhh7+}w6qEHgnwW$EeQ~FJl#1@! zUsoDvDz>}~|8C$-tLOE(c58P`pG0?oYTROE<%3mIIBol5?_l^L{&9B`CgJbv3qjDG zRn;vDN%5sGpz96E33@ZVHM>BZVd6HwiYH)zW4mzmq zyD7eQ3l>ft{TK8JQG^Qv>|Z*2m1N7iy;dgpBa|kxZKeO!8pryY=@hd|+}M00@n5v2 z$un2-p=rFTiSE|~1uqQN;X^2djQqXL6W*=`1uS#TlCKIHx;H3+QXe4SA%{$nZiZ zy-3Sy@en79e&ZS)ZU}5ihiaY1wD;HQ#m*+ZdkttJcCA{T+{ZA)$eegH%pJ~6tpepA zKQO-<^YuRMcIxCT7T}$K<<`7%rG$E6umHX9x{6K@Q)$&kyi=o*9(<2_cQ)S`6=F^Y zTe!mEkW_PT=~U$9-ye6=tQbj~cqlJ29IlP#)Y%*Fxw;LMWOfjt08FX)GbG4lgmlwR z?@NBZHwk=ayg=Y+Q2SCGZ@J3al-_-Mv+g+RX0aw+@?B9Y9SPnK>gw3a?4CS{%h|X( z{7+o?#`gcjn!~%n$N2J`b2=MVDz}tdzkCp=YMtgkKA+qgb#aV*qv!R{p{4Bu&Tcm8 zO8U|U0dyAHvZlrTW-LZ{kG@~FS}%<-tSn3%dGy$Iev1N|4u!?@Jjd+?rm>?ErJb7Z>TJL;x8-d=3;QTVmU_1KF}3SP_i>%wIW9h8raGk z?^!Unm_7F11H6ex-ee(^M~vhThPe%Sf6;(P1nuinrl%k}sSG0M;Z`s*1y2*d-0 z>M1`Zzwok#G(+n-e@=8&dTa2VhUHvVxdINVWB=ONWEX%>(De!czw`BJn-KnaV_zTbXbaj&T$nE#xC z;pon~EkD0q?@ESndOd;fuQCm6k=wjgF9)X>zx=yATG}aHEo1BI$=TpVRLDX5Nr25+ zv=42KN~y(l(*3#khg9p16mk^}J9siE)s5^vJ&uCzqT`1NcjwI7FQ~NqpLEcrOXa?k zvviju$3hkY-?1N2Yf!FV-^&e9;C9Z?i<8kSskEX~+lX-MI9c|DdehmGhyg%!ZjYYq z-}iFYXPTbltbE8$r}g3*vM_{zzXX(t5J2_P1N{+j+~T6cYrL+w&XL1#152k5K8uG} z_os)ag}%^+hv9o#oEm(zs^2?>w)=iJu*tK3%B$Mwt_sX+2Ym=nP9qP!RWk-T01(Ld zTDAGTIz|56XJ@gIh)5t*5JkT1*?4a?M?OH>9zqVYudF6>E?#%3`2B>YQuF&-`8_Sd zZUgLZIJd_%Wplnlbl$Q0)dN<$_xVe`1p4=`MSM)>Jv+0i)=e9%lL3)HVS8d5)LuvH zNrK6(rCX0~rI@8SYIRxRdjO1B?(3*!bD8=x@9?XuOiC3yACgHp2F>W{ygo1$91zD( zIo8EWk+9WN;8%Z3G{JA7_rhfys#(d@(pY7ZZ+t9bp-OdBC3CqHD9_&g^XG3+|6B5` zfiIj#H-9;$hI1vyG6ILxKkOM2taZG?uEs|CT#b#P_c|Gw++WmxoyG+_7R3yi7mj8=tiHks1_E z+nhuXT5}~@5-f8WhQA7US%B9n-XQ6!RBdyOVPHU0G4D!jx6oU_rT=g01^e8y5!$cM z9%02dk}W&tH%LsPhfhW~jbt!3?Kt69>(vAJo~Y$F{x(szNybKK~+RM4i*0D&7O$3zCSdl~1DnNxoZL%U94;|D44}N0Y=IK3CX99WAQY1B^0T5e&+rgE zg>ekkNtJH;ulr8sDgTJKdgF!3(RLtjza{$G$TSVyY^Qxd;HG4|Ds$72JDB0hym z@6y0-yZ+d5yZ1+Wg$bbOr(QXz+x2pAcXjiXAz=2*J*-pFIp_3VG=Q_m;<3?ZkYP3h zpfntPvL;;xoUHPXb6Qs~oZ&23M&hX6+)QEcn;dsIcYC$!HwR2i`T1$4zV0pwQW_iV zxa~M8yxb)pxPhHtm3w>7z(rTB`PwkADteghza|;fy0pw6my3z_8!=yTU=b?{Pih;M zG8Vt5@D=lG;U(dMaliOW4)saW-V8m;wn6h32kw;90xZN%lv6K@@42}$ZYGD3@KmV)vl+3nzzK7W8g_`$>k1y?B-P`T1|L zlCEdra2J9ohE@E17ZteGiU^Qx$Q+{NE-+w_Exy@ zgY*H1P2Y^&{c?QoNA|L|ikQok(bPRCLWt7N#B$g zBT3yy=F-<~lpS-u=Bu-H;Wj^!g2j`ZhbD%1LpFb#gk%!S%qWhfOrGzd6fEaTt88u*JU{}66RF`Q$bAfMN-XwtR#~+xg+FVj;ECH&y&RG5O&QCJ+dade)}zNy9WX8vJSDrPaX} zMI;`(gfc?BMy1b_O;BWAe`ADsBYKUz;Nbj1X94%ne1G|1e0$;r%cj_$T_3k~Y^V6p?#>P3_ySDtHtz-7 zO{pKZGW(ww*0D_f^<&BRF=%txBUuTc1naAx{AcojKwZP!yT-+4f+8>qx(!Uh>ymu=dswshrH*q68LzP@W z{HqpZNU^rqMz{P8k2R&$VR41zC6a);E56XOxSoI<-$HdMz@y$0AxizjQ=EJm2c_RY z1i9WR6k&{meB*e~q0hl7-~$X@kt-PssLk(jSgZtV zUo_mfYqGjCH~Cr2fdW#DFs-r9ddU1(CdOK@a}U}W@6JO2SvxGTBG(3|WJ&2Xn) zm3Pnt0#e7R#qn>Z)mH5F%4D1+n}?DbVKeF#4`d;27Cnepy=byOaOoI6TW@n(<%yT; z+7rvEXI0t9@iWQl*X}1RaD9e(h+_jgngMgk$u9>t^15(IkpFe}J(@HHgVdi3GyADf z&yGsW0J<=1*$0Qb(nl9dJQLRFWN)N?{zXivg%zD~G zq{hh(qZ#^W8qeHtB{LTDs1FVQ!zE83OH*`>zG1A#2*|B5Lc}2ZkseCQ<2)q&=f?do zJiw%<(~CS^oaZauG9JvZj+6ZmQ4b#-ZN5fPK8`bM1lrz@+Zk%p8B za-0~x!1-saA+!AO`;prYK2LX-TR2+kAN^3GNC7*7KoAW-RR6fV)|dpW(?e6YZ?+gUL;0^t+#$y)QtEQk9Uk4V|aWa5i6L$5cvskGbrLf;|gK0qQj z7KX#`e7Fw{yqy3zbXUA20p0Z#7#!)|a#G%SZF#pE_uuj4TqhqW#Z40vpXX$8uV(B5 z^!Vp|#z7{op@Yg-_nLIX-`Qw>MN~(PmEcA&{Ccw5lD2jlX@4C7AR$yT{agv9m`|+LS$ZPPpRswB3bgd1Bt#v-p;ii{Gh7Y?LJ44>h0edr8ntE}EDT+8@F0h8 zeBPb?lRx;%aKPRGlxp@;q=UX3Zpwg!LO5F8?RACIJCIvgQ0Dz~*mCc#PmP+K!3zf& zj@mzqUe?Jf9M|8B@|7)r6d}`aFboHOl&(v@=PG00i|lPcX8-nna_NM?=*H_yL5fsT z#_F?mqWB1 z+};N~YMf~yU|9*DyBgt{hj9{BT z?7FebFIE@l+^$i0Jx7?nk2Z#^D4*3PQ%#l*8iTe?{NeUg#oS5M1Qtsf7v&riq6LZ$ z(pt*V8dV&V`)lti9?h*{n+f!NMx{HF&qWEXJ#vv4t-nL4>)^kOC331uXq}i|j5*jP zLg(pJ__#mlwYw4$f*&f!wj&<@&6QH$k-`mTapZ+NniZkWc?uX(Q5Q{@k62I@=(Au>2MJ*h67}4|L}yGn0i!Y zheCu_96t-eSz`hYGb`9D%tKuEE_0v}P+F!CF&~kbk@|BU_mt&lI7;endfB=}jpEbT zhpSg?0=70j>g+J*BqUpvW4u?z4EO0zKn5!5l$I0Ic}wrGteFRuGnkCaVFquJGi^38 zE9Po{Rc^9ol21hS-k3$a?npi;_?g2#DMSxQ!69bIv1jlxqP(C=0&A|Ao>FTMjY&k~ z=yNV6RlVA{@hn{;5!=q;qcVEgXUW(4Nv%~PF9+Q!m$g3+0Rv%mo&0ns?bd;lCFa0K zXLutq!PiS~ zm?$E(q5mp!u>auld!u__m;Y!BjfP+aMk?gg=uTJ>?O-Biu)*L{vOyR++r)D zl*!hk>I|GC3$Yu#cWriM>r&;rQ}ie^*8SixF|D8>V8LwV*%g;#(yt z?f#t#dy^sQ5~`PXlhYawZHM1-S7uk=%@d!VH@-X5d&@TQsh1FI57+I}z>(A+$5a+n zg$Zuxhc%Wo6j3MpgLKT;z-i_^5%0R#Q+HOT>5a;oLS=e)JYcg$Kd}5k!T(rD07%0G1h$hW-&zME(5jjD%N=AHGflE*nDHb3!x8>9e%bp1 z$oBs<7n9eqJPbMNQS_iRgCMT7rS#`n0`A$rr~X+$APDSw8!2vHUwHIzCK=ZBT>)4Zuk@!RVgBxV?SIV*!v_x`27lYlJ4awtyef zbCWYl96a4weWmFWgCoq8f~zP+rUE*6cbE^w&w zZ2hTr+VxD9p{w0oqylUP;(l*`;qE<=?pk;e{s0OU)3w;B>$c>x=U8tfnY)71m@?J3 zI(j3%yfoVaY^q3UNp$GGAmuZyXPra3NiXOh8#Nt_xb%xP#>Y95)GxgEji_rFCE>R* zpYvAh9lbI??fy}mqs=~mku=NpRjRodNS|3BC@?ExazQEL}MU>?1dItWuqecORy%pKujX (<@Rd3%`YXl#F|Y})z9itdeMjMbGf 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

(4MRGL1=p&7a`S`& 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 Date: Tue, 3 Sep 2024 16:46:54 +0200 Subject: [PATCH 15/54] [Exporter] Don't generate instance pools if the pool name is empty (#3960) ## Changes Resolves #3485 ## Tests - [x] `make test` run locally - [ ] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [ ] using Go SDK --- exporter/importables.go | 19 ++++++++++--------- exporter/util.go | 4 ++-- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/exporter/importables.go b/exporter/importables.go index 2dd8bb2542..88a90e3bcd 100644 --- a/exporter/importables.go +++ b/exporter/importables.go @@ -243,6 +243,7 @@ var resourcesMap map[string]importable = map[string]importable{ "inst_pool_"+ic.Importables["databricks_instance_pool"].Name(ic, r.Data)) return nil }, + Ignore: generateIgnoreObjectWithEmptyAttributeValue("databricks_instance_pool", "instance_pool_name"), }, "databricks_instance_profile": { Service: "access", @@ -1724,7 +1725,7 @@ var resourcesMap map[string]importable = map[string]importable{ "sql_query_"+ic.Importables["databricks_sql_query"].Name(ic, r.Data)) return nil }, - Ignore: generateIgnoreObjectWithoutName("databricks_sql_query"), + Ignore: generateIgnoreObjectWithEmptyAttributeValue("databricks_sql_query", "name"), Depends: []reference{ {Path: "data_source_id", Resource: "databricks_sql_endpoint", Match: "data_source_id"}, {Path: "parameter.query.query_id", Resource: "databricks_sql_query", Match: "id"}, @@ -1770,7 +1771,7 @@ var resourcesMap map[string]importable = map[string]importable{ } return nil }, - Ignore: generateIgnoreObjectWithoutName("databricks_sql_endpoint"), + Ignore: generateIgnoreObjectWithEmptyAttributeValue("databricks_sql_endpoint", "name"), ShouldOmitField: func(ic *importContext, pathString string, as *schema.Schema, d *schema.ResourceData) bool { switch pathString { case "enable_serverless_compute": @@ -1978,7 +1979,7 @@ var resourcesMap map[string]importable = map[string]importable{ "sql_alert_"+ic.Importables["databricks_sql_alert"].Name(ic, r.Data)) return nil }, - Ignore: generateIgnoreObjectWithoutName("databricks_sql_alert"), + Ignore: generateIgnoreObjectWithEmptyAttributeValue("databricks_sql_alert", "name"), Depends: []reference{ {Path: "query_id", Resource: "databricks_sql_query", Match: "id"}, {Path: "parent", Resource: "databricks_directory", Match: "object_id", @@ -2605,7 +2606,7 @@ var resourcesMap map[string]importable = map[string]importable{ } return shouldOmitForUnityCatalog(ic, pathString, as, d) }, - Ignore: generateIgnoreObjectWithoutName("databricks_catalog"), + Ignore: generateIgnoreObjectWithEmptyAttributeValue("databricks_catalog", "name"), Depends: []reference{ {Path: "connection_name", Resource: "databricks_connection", Match: "name"}, {Path: "storage_root", Resource: "databricks_external_location", Match: "url", MatchType: MatchLongestPrefix}, @@ -2711,7 +2712,7 @@ var resourcesMap map[string]importable = map[string]importable{ return nil }, ShouldOmitField: shouldOmitForUnityCatalog, - Ignore: generateIgnoreObjectWithoutName("databricks_schema"), + Ignore: generateIgnoreObjectWithEmptyAttributeValue("databricks_schema", "name"), Depends: []reference{ {Path: "catalog_name", Resource: "databricks_catalog"}, {Path: "storage_root", Resource: "databricks_external_location", Match: "url", MatchType: MatchLongestPrefix}, @@ -2739,7 +2740,7 @@ var resourcesMap map[string]importable = map[string]importable{ } return shouldOmitForUnityCatalog(ic, pathString, as, d) }, - Ignore: generateIgnoreObjectWithoutName("databricks_volume"), + Ignore: generateIgnoreObjectWithEmptyAttributeValue("databricks_volume", "name"), Depends: []reference{ {Path: "catalog_name", Resource: "databricks_catalog"}, {Path: "schema_name", Resource: "databricks_schema", Match: "name", @@ -2763,7 +2764,7 @@ var resourcesMap map[string]importable = map[string]importable{ // TODO: emit owner? See comment in catalog resource return nil }, - Ignore: generateIgnoreObjectWithoutName("databricks_sql_table"), + Ignore: generateIgnoreObjectWithEmptyAttributeValue("databricks_sql_table", "name"), ShouldOmitField: func(ic *importContext, pathString string, as *schema.Schema, d *schema.ResourceData) bool { switch pathString { case "storage_location": @@ -3080,7 +3081,7 @@ var resourcesMap map[string]importable = map[string]importable{ } return shouldOmitForUnityCatalog(ic, pathString, as, d) }, - Ignore: generateIgnoreObjectWithoutName("databricks_registered_model"), + Ignore: generateIgnoreObjectWithEmptyAttributeValue("databricks_registered_model", "name"), Depends: []reference{ {Path: "catalog_name", Resource: "databricks_catalog"}, {Path: "schema_name", Resource: "databricks_schema", Match: "name", @@ -3483,7 +3484,7 @@ var resourcesMap map[string]importable = map[string]importable{ // TODO: emit owner? See comment in catalog resource return nil }, - Ignore: generateIgnoreObjectWithoutName("databricks_online_table"), + Ignore: generateIgnoreObjectWithEmptyAttributeValue("databricks_online_table", "name"), ShouldOmitField: shouldOmitForUnityCatalog, Depends: []reference{ {Path: "catalog_name", Resource: "databricks_catalog"}, diff --git a/exporter/util.go b/exporter/util.go index 2d06c119fc..6687f4dc8f 100644 --- a/exporter/util.go +++ b/exporter/util.go @@ -487,9 +487,9 @@ func isMatchingAllowListArtifact(ic *importContext, res *resource, ra *resourceA return ok && matchType.(string) == "PREFIX_MATCH" && (artifactType == "LIBRARY_JAR" || artifactType == "INIT_SCRIPT") } -func generateIgnoreObjectWithoutName(resourceType string) func(ic *importContext, r *resource) bool { +func generateIgnoreObjectWithEmptyAttributeValue(resourceType, attrName string) func(ic *importContext, r *resource) bool { return func(ic *importContext, r *resource) bool { - res := (r.Data != nil && r.Data.Get("name").(string) == "") + res := (r.Data != nil && r.Data.Get(attrName).(string) == "") if res { ic.addIgnoredResource(fmt.Sprintf("%s. id=%s", resourceType, r.ID)) } From 560e03cb1428505caa3a87c17bb49a0a2a450750 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20G=C3=B3mez=20Moreno?= <69928678+dgomez04@users.noreply.github.com> Date: Tue, 3 Sep 2024 11:07:12 -0600 Subject: [PATCH 16/54] [Doc] Reimplement Azure Databricks deployment guide to use VNet injection & NPIP (#3986) ## Changes Updated the Azure Databricks deployment guide to implement VNet injection and secure cluster connectivity, following best practices. Ran `make fmt-docs` and tested the deployment myself. Closes #2093 ## Tests - [ ] `make test` run locally - [x] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [ ] using Go SDK --- docs/guides/azure-workspace.md | 87 +++++++++++++++++++++++++++++++++- 1 file changed, 85 insertions(+), 2 deletions(-) diff --git a/docs/guides/azure-workspace.md b/docs/guides/azure-workspace.md index 303160f9ef..9374416cbf 100644 --- a/docs/guides/azure-workspace.md +++ b/docs/guides/azure-workspace.md @@ -13,8 +13,8 @@ The following sample configuration assumes you have been authorized with `az log ```hcl terraform { required_providers { - azurerm = "~> 2.33" - random = "~> 2.2" + azurerm = "~> 4.0" + random = "~> 3.6" } } @@ -26,6 +26,17 @@ variable "region" { type = string default = "westeurope" } +variable "cidr" { + type = string + default = "10.179.0.0/20" + description = "Network range for created virtual network." +} + +variable "no_public_ip" { + type = bool + default = true + description = "Defines whether Secure Cluster Connectivity (No Public IP) should be enabled." +} resource "random_string" "naming" { special = false @@ -54,6 +65,69 @@ resource "azurerm_resource_group" "this" { tags = local.tags } +resource "azurerm_virtual_network" "this" { + name = "${local.prefix}-vnet" + resource_group_name = azurerm_resource_group.this.name + location = azurerm_resource_group.this.location + address_space = [var.cidr] + tags = local.tags +} + +resource "azurerm_network_security_group" "this" { + name = "${local.prefix}-nsg" + resource_group_name = azurerm_resource_group.this.name + location = azurerm_resource_group.this.location + tags = local.tags +} + +resource "azurerm_subnet" "public" { + name = "${local.prefix}-public" + resource_group_name = azurerm_resource_group.this.name + virtual_network_name = azurerm_virtual_network.this.name + address_prefixes = [cidrsubnet(var.cidr, 3, 0)] + + delegation { + name = "databricks" + service_delegation { + name = "Microsoft.Databricks/workspaces" + actions = [ + "Microsoft.Network/virtualNetworks/subnets/action", + "Microsoft.Network/virtualNetworks/subnets/prepareNetworkPolicies/action", + "Microsoft.Network/virtualNetworks/subnets/unprepareNetworkPolicies/action" + ] + } + } +} + +resource "azurerm_subnet_network_security_group_association" "public" { + subnet_id = azurerm_subnet.public.id + network_security_group_id = azurerm_network_security_group.this.id +} + +resource "azurerm_subnet" "private" { + name = "${local.prefix}-private" + resource_group_name = azurerm_resource_group.this.name + virtual_network_name = azurerm_virtual_network.this.name + address_prefixes = [cidrsubnet(var.cidr, 3, 1)] + + delegation { + name = "databricks" + service_delegation { + name = "Microsoft.Databricks/workspaces" + actions = [ + "Microsoft.Network/virtualNetworks/subnets/action", + "Microsoft.Network/virtualNetworks/subnets/prepareNetworkPolicies/action", + "Microsoft.Network/virtualNetworks/subnets/unprepareNetworkPolicies/action" + ] + } + } +} + +resource "azurerm_subnet_network_security_group_association" "private" { + subnet_id = azurerm_subnet.private.id + network_security_group_id = azurerm_network_security_group.this.id +} + resource "azurerm_databricks_workspace" "this" { name = "${local.prefix}-workspace" resource_group_name = azurerm_resource_group.this.name @@ -61,6 +135,15 @@ resource "azurerm_databricks_workspace" "this" { sku = "premium" managed_resource_group_name = "${local.prefix}-workspace-rg" tags = local.tags + + custom_parameters { + no_public_ip = var.no_public_ip + virtual_network_id = azurerm_virtual_network.this.id + private_subnet_name = azurerm_subnet.private.name + public_subnet_name = azurerm_subnet.public.name + public_subnet_network_security_group_association_id = azurerm_subnet_network_security_group_association.public.id + private_subnet_network_security_group_association_id = azurerm_subnet_network_security_group_association.private.id + } } output "databricks_host" { From a9c20018d8c8ee901a8dd1bf889000e4872b6214 Mon Sep 17 00:00:00 2001 From: Miles Yucht Date: Tue, 3 Sep 2024 14:18:17 -0400 Subject: [PATCH 17/54] [Fix] Fix `TestAccClusterResource_WorkloadType` (#3989) ## Changes `TestAccClusterResource_WorkloadType` merged with a small bug that caused it to fail deterministically, asserting that the workload_type had a clients block in state even when it wasn't specified in the config, which is not expected. This PR changes the assertion on state to verify that the block is not present in state when removed from the config. ## Tests - [ ] `make test` run locally - [ ] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [ ] using Go SDK --- internal/acceptance/cluster_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/internal/acceptance/cluster_test.go b/internal/acceptance/cluster_test.go index 4dad55c9f7..dd5b2164f8 100644 --- a/internal/acceptance/cluster_test.go +++ b/internal/acceptance/cluster_test.go @@ -171,8 +171,7 @@ func TestAccClusterResource_WorkloadType(t *testing.T) { }, step{ Template: testAccClusterResourceWorkloadTypeTemplate(``), Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr("databricks_cluster.this", "workload_type.0.clients.0.jobs", "true"), - resource.TestCheckResourceAttr("databricks_cluster.this", "workload_type.0.clients.0.notebooks", "true"), + resource.TestCheckResourceAttr("databricks_cluster.this", "workload_type.#", "0"), ), }) } From bb871e11e7fcaa76451ddadbf3f71364174a8a7d Mon Sep 17 00:00:00 2001 From: Edward Feng <67326663+edwardfeng-db@users.noreply.github.com> Date: Wed, 4 Sep 2024 15:28:56 +0200 Subject: [PATCH 18/54] [Internal] Make test utils public and move integration test for quality monitor (#3993) ## Changes - Make `Step`, `WorkspaceLevel`, `AccountLevel`, `UnityWorkspaceLevel`, `UnityAccountLevel` public - Rename `init_test.go` to `init.go` because variables exported from files ending with `_test` cannot be imported - Moved integration test for quality monitor next to the resource definition ## Tests - [x] `make test` run locally - [x] relevant change in `docs/` folder - [x] covered with integration tests in `internal/acceptance` - [x] relevant acceptance tests are passing - [x] using Go SDK --- CONTRIBUTING.md | 2 +- internal/acceptance/acceptance_test.go | 2 +- internal/acceptance/account_rule_set_test.go | 4 +- .../acceptance/artifact_allowlist_test.go | 2 +- internal/acceptance/catalog_test.go | 16 +- internal/acceptance/cluster_policy_test.go | 8 +- internal/acceptance/cluster_test.go | 22 +-- internal/acceptance/connection_test.go | 10 +- internal/acceptance/dashboard_test.go | 28 ++-- .../data_aws_crossaccount_policy_test.go | 2 +- internal/acceptance/data_catalog_test.go | 2 +- internal/acceptance/data_cluster_test.go | 2 +- internal/acceptance/data_clusters_test.go | 4 +- .../acceptance/data_current_config_test.go | 12 +- .../acceptance/data_current_metastore_test.go | 2 +- .../data_external_locations_test.go | 2 +- internal/acceptance/data_group_test.go | 4 +- .../acceptance/data_instance_profiles_test.go | 2 +- internal/acceptance/data_job_test.go | 2 +- internal/acceptance/data_metastore_test.go | 2 +- internal/acceptance/data_metastores_test.go | 2 +- .../acceptance/data_mlflow_experiment_test.go | 8 +- internal/acceptance/data_mlflow_model_test.go | 6 +- .../acceptance/data_mws_credentials_test.go | 2 +- .../acceptance/data_mws_workspaces_test.go | 2 +- internal/acceptance/data_pipelines_test.go | 2 +- internal/acceptance/data_schema_test.go | 2 +- internal/acceptance/data_schemas_test.go | 2 +- .../data_service_principals_test.go | 6 +- internal/acceptance/data_shares_test.go | 2 +- .../acceptance/data_sql_warehouse_test.go | 2 +- .../data_storage_credential_test.go | 2 +- .../data_storage_credentials_test.go | 2 +- internal/acceptance/data_table_test.go | 2 +- internal/acceptance/data_tables_test.go | 2 +- internal/acceptance/data_user_test.go | 4 +- internal/acceptance/data_volume_test.go | 2 +- internal/acceptance/data_volumes_test.go | 4 +- internal/acceptance/dbfs_file_test.go | 6 +- internal/acceptance/default_namespace_test.go | 4 +- internal/acceptance/directory_test.go | 2 +- internal/acceptance/entitlements_test.go | 18 +-- internal/acceptance/external_location_test.go | 12 +- internal/acceptance/file_test.go | 28 ++-- internal/acceptance/git_credential_test.go | 2 +- .../acceptance/global_init_script_test.go | 2 +- internal/acceptance/grant_test.go | 12 +- internal/acceptance/grants_test.go | 12 +- internal/acceptance/group_member_test.go | 4 +- internal/acceptance/group_role_test.go | 2 +- internal/acceptance/group_test.go | 16 +- internal/acceptance/{init_test.go => init.go} | 12 +- internal/acceptance/instance_profile_test.go | 8 +- internal/acceptance/ip_access_list_test.go | 4 +- internal/acceptance/job_test.go | 30 ++-- .../acceptance/metastore_assignment_test.go | 6 +- .../acceptance/metastore_data_access_test.go | 4 +- internal/acceptance/metastore_test.go | 8 +- internal/acceptance/mlflow_experiment_test.go | 2 +- internal/acceptance/mlflow_model_test.go | 2 +- internal/acceptance/model_serving_test.go | 14 +- internal/acceptance/mounts_test.go | 10 +- internal/acceptance/mws_credentials_test.go | 2 +- .../mws_customer_managed_keys_test.go | 4 +- internal/acceptance/mws_log_delivery_test.go | 2 +- .../mws_network_connectivity_config_test.go | 8 +- internal/acceptance/mws_networks_test.go | 4 +- .../mws_permissionassignments_test.go | 8 +- .../mws_private_access_settings_test.go | 4 +- .../mws_storage_configurations_test.go | 2 +- internal/acceptance/mws_vpc_endpoint_test.go | 4 +- internal/acceptance/mws_workspaces_test.go | 22 +-- internal/acceptance/notebook_test.go | 4 +- .../notification_destination_test.go | 24 +-- internal/acceptance/obo_token_test.go | 2 +- internal/acceptance/online_table_test.go | 2 +- internal/acceptance/permissions_test.go | 12 +- internal/acceptance/pipeline_test.go | 12 +- internal/acceptance/provider_test.go | 2 +- internal/acceptance/quality_monitor_test.go | 110 +------------ internal/acceptance/recipient_test.go | 12 +- internal/acceptance/registered_model_test.go | 8 +- .../restrict_workspace_admins_test.go | 4 +- internal/acceptance/schema_test.go | 10 +- internal/acceptance/secret_acl_test.go | 4 +- internal/acceptance/secret_scope_test.go | 6 +- internal/acceptance/secret_test.go | 2 +- internal/acceptance/service_principal_test.go | 24 +-- internal/acceptance/share_test.go | 10 +- internal/acceptance/sql_alert_test.go | 4 +- internal/acceptance/sql_dashboard_test.go | 2 +- internal/acceptance/sql_endpoint_test.go | 4 +- internal/acceptance/sql_global_config_test.go | 8 +- internal/acceptance/sql_permissions_test.go | 2 +- internal/acceptance/sql_query_test.go | 2 +- internal/acceptance/sql_table_test.go | 64 ++++---- .../acceptance/storage_credential_test.go | 6 +- internal/acceptance/system_schema_test.go | 2 +- internal/acceptance/token_test.go | 2 +- internal/acceptance/user_role_test.go | 2 +- internal/acceptance/user_test.go | 24 +-- internal/acceptance/vector_search_test.go | 2 +- internal/acceptance/volume_test.go | 14 +- internal/acceptance/workspace_binding_test.go | 2 +- internal/acceptance/workspace_conf_test.go | 8 +- internal/acceptance/workspace_file_test.go | 10 +- .../resource_quality_monitor_test.go | 153 ++++++++++++++++++ internal/tfreflect/reflect_utils.go | 4 +- 108 files changed, 539 insertions(+), 488 deletions(-) rename internal/acceptance/{init_test.go => init.go} (97%) create mode 100644 internal/providers/pluginfw/resources/qualitymonitor/resource_quality_monitor_test.go diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d4718029d7..4062159c53 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -333,7 +333,7 @@ func TestExampleResourceCreate(t *testing.T) { ```go func TestAccSecretAclResource(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` resource "databricks_group" "ds" { display_name = "data-scientists-{var.RANDOM}" diff --git a/internal/acceptance/acceptance_test.go b/internal/acceptance/acceptance_test.go index a86f6e9eb2..590bac94fa 100644 --- a/internal/acceptance/acceptance_test.go +++ b/internal/acceptance/acceptance_test.go @@ -50,7 +50,7 @@ func TestRunningRealTerraformWithFixtureBackend(t *testing.T) { t.Setenv("DATABRICKS_HOST", client.Config.Host) t.Setenv("DATABRICKS_TOKEN", client.Config.Token) - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: `resource "databricks_token" "this" { lifetime_seconds = 6000 comment = "Testing token" diff --git a/internal/acceptance/account_rule_set_test.go b/internal/acceptance/account_rule_set_test.go index c95e70d139..a134cdf667 100644 --- a/internal/acceptance/account_rule_set_test.go +++ b/internal/acceptance/account_rule_set_test.go @@ -32,7 +32,7 @@ func getServicePrincipalResource(t *testing.T) string { func TestMwsAccAccountServicePrincipalRuleSetsFullLifeCycle(t *testing.T) { loadAccountEnv(t) spResource := getServicePrincipalResource(t) - accountLevel(t, step{ + AccountLevel(t, Step{ Template: spResource + ` resource "databricks_group" "this" { display_name = "Group {var.RANDOM}" @@ -69,7 +69,7 @@ func TestMwsAccAccountServicePrincipalRuleSetsFullLifeCycle(t *testing.T) { func TestMwsAccAccountGroupRuleSetsFullLifeCycle(t *testing.T) { username := qa.RandomEmail() - accountLevel(t, step{ + AccountLevel(t, Step{ Template: ` resource "databricks_user" "this" { user_name = "` + username + `" diff --git a/internal/acceptance/artifact_allowlist_test.go b/internal/acceptance/artifact_allowlist_test.go index 271e9179ab..aeb1347285 100644 --- a/internal/acceptance/artifact_allowlist_test.go +++ b/internal/acceptance/artifact_allowlist_test.go @@ -5,7 +5,7 @@ import ( ) func TestUcAccArtifactAllowlistResourceFullLifecycle(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` resource "databricks_artifact_allowlist" "init" { artifact_type = "INIT_SCRIPT" diff --git a/internal/acceptance/catalog_test.go b/internal/acceptance/catalog_test.go index edae3560a4..3b1278c36e 100644 --- a/internal/acceptance/catalog_test.go +++ b/internal/acceptance/catalog_test.go @@ -7,7 +7,7 @@ import ( func TestUcAccCatalog(t *testing.T) { loadUcwsEnv(t) - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: fmt.Sprintf(` resource "databricks_catalog" "sandbox" { name = "sandbox{var.RANDOM}" @@ -21,7 +21,7 @@ func TestUcAccCatalog(t *testing.T) { } func TestUcAccCatalogIsolated(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` resource "databricks_catalog" "sandbox" { name = "sandbox{var.STICKY_RANDOM}" @@ -30,7 +30,7 @@ func TestUcAccCatalogIsolated(t *testing.T) { purpose = "testing" } }`, - }, step{ + }, Step{ Template: ` resource "databricks_catalog" "sandbox" { name = "sandbox{var.STICKY_RANDOM}" @@ -40,7 +40,7 @@ func TestUcAccCatalogIsolated(t *testing.T) { purpose = "testing" } }`, - }, step{ + }, Step{ Template: ` resource "databricks_catalog" "sandbox" { name = "sandbox{var.STICKY_RANDOM}" @@ -55,7 +55,7 @@ func TestUcAccCatalogIsolated(t *testing.T) { func TestUcAccCatalogUpdate(t *testing.T) { loadUcwsEnv(t) - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: fmt.Sprintf(` resource "databricks_catalog" "sandbox" { name = "sandbox{var.STICKY_RANDOM}" @@ -65,7 +65,7 @@ func TestUcAccCatalogUpdate(t *testing.T) { } %s }`, getPredictiveOptimizationSetting(t, true)), - }, step{ + }, Step{ Template: fmt.Sprintf(` resource "databricks_catalog" "sandbox" { name = "sandbox{var.STICKY_RANDOM}" @@ -76,7 +76,7 @@ func TestUcAccCatalogUpdate(t *testing.T) { %s owner = "account users" }`, getPredictiveOptimizationSetting(t, true)), - }, step{ + }, Step{ Template: fmt.Sprintf(` resource "databricks_catalog" "sandbox" { name = "sandbox{var.STICKY_RANDOM}" @@ -87,7 +87,7 @@ func TestUcAccCatalogUpdate(t *testing.T) { %s owner = "{env.TEST_DATA_ENG_GROUP}" }`, getPredictiveOptimizationSetting(t, true)), - }, step{ + }, Step{ Template: fmt.Sprintf(` resource "databricks_catalog" "sandbox" { name = "sandbox{var.STICKY_RANDOM}" diff --git a/internal/acceptance/cluster_policy_test.go b/internal/acceptance/cluster_policy_test.go index 3d7ac40177..8de58a9206 100644 --- a/internal/acceptance/cluster_policy_test.go +++ b/internal/acceptance/cluster_policy_test.go @@ -5,7 +5,7 @@ import ( ) func TestAccClusterPolicyResourceFullLifecycle(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: `resource "databricks_cluster_policy" "external_metastore" { name = "Terraform policy {var.RANDOM}" definition = jsonencode({ @@ -15,7 +15,7 @@ func TestAccClusterPolicyResourceFullLifecycle(t *testing.T) { } }) }`, - }, step{ + }, Step{ // renaming to a new random name Template: `resource "databricks_cluster_policy" "external_metastore" { name = "Terraform policy {var.RANDOM}" @@ -30,7 +30,7 @@ func TestAccClusterPolicyResourceFullLifecycle(t *testing.T) { } func TestAccClusterPolicyResourceOverrideBuiltIn(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: `resource "databricks_cluster_policy" "personal_vm" { name = "Personal Compute" policy_family_id = "personal-vm" @@ -46,7 +46,7 @@ func TestAccClusterPolicyResourceOverrideBuiltIn(t *testing.T) { } func TestAccClusterPolicyResourceOverrideNew(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: `resource "databricks_cluster_policy" "policyoverrideempty" { policy_family_id = "personal-vm" name = "Policy Override {var.RANDOM}" diff --git a/internal/acceptance/cluster_test.go b/internal/acceptance/cluster_test.go index dd5b2164f8..f399eece3f 100644 --- a/internal/acceptance/cluster_test.go +++ b/internal/acceptance/cluster_test.go @@ -8,7 +8,7 @@ import ( ) func TestAccClusterResource_CreateClusterWithLibraries(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: `data "databricks_spark_version" "latest" { } resource "databricks_cluster" "this" { @@ -73,9 +73,9 @@ func singleNodeClusterTemplate(autoTerminationMinutes string) string { } func TestAccClusterResource_CreateSingleNodeCluster(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: singleNodeClusterTemplate("10"), - }, step{ + }, Step{ Template: singleNodeClusterTemplate("20"), }) } @@ -103,16 +103,16 @@ func awsClusterTemplate(availability string) string { func TestAccClusterResource_CreateAndUpdateAwsAttributes(t *testing.T) { loadWorkspaceEnv(t) if isAws(t) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: awsClusterTemplate("SPOT"), - }, step{ + }, Step{ Template: awsClusterTemplate("SPOT_WITH_FALLBACK"), }) } } func TestAccClusterResource_CreateAndNoWait(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: `data "databricks_spark_version" "latest" { } resource "databricks_cluster" "this" { @@ -133,9 +133,9 @@ func TestAccClusterResource_CreateAndNoWait(t *testing.T) { } func TestAccClusterResource_WorkloadType(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: testAccClusterResourceWorkloadTypeTemplate(""), - }, step{ + }, Step{ Template: testAccClusterResourceWorkloadTypeTemplate(` workload_type { clients { @@ -147,7 +147,7 @@ func TestAccClusterResource_WorkloadType(t *testing.T) { resource.TestCheckResourceAttr("databricks_cluster.this", "workload_type.0.clients.0.jobs", "true"), resource.TestCheckResourceAttr("databricks_cluster.this", "workload_type.0.clients.0.notebooks", "true"), ), - }, step{ + }, Step{ Template: testAccClusterResourceWorkloadTypeTemplate(` workload_type { clients { @@ -159,7 +159,7 @@ func TestAccClusterResource_WorkloadType(t *testing.T) { resource.TestCheckResourceAttr("databricks_cluster.this", "workload_type.0.clients.0.jobs", "false"), resource.TestCheckResourceAttr("databricks_cluster.this", "workload_type.0.clients.0.notebooks", "false"), ), - }, step{ + }, Step{ Template: testAccClusterResourceWorkloadTypeTemplate(` workload_type { clients { } @@ -168,7 +168,7 @@ func TestAccClusterResource_WorkloadType(t *testing.T) { resource.TestCheckResourceAttr("databricks_cluster.this", "workload_type.0.clients.0.jobs", "true"), resource.TestCheckResourceAttr("databricks_cluster.this", "workload_type.0.clients.0.notebooks", "true"), ), - }, step{ + }, Step{ Template: testAccClusterResourceWorkloadTypeTemplate(``), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("databricks_cluster.this", "workload_type.#", "0"), diff --git a/internal/acceptance/connection_test.go b/internal/acceptance/connection_test.go index 7cf6ec5093..fade7f3d5f 100644 --- a/internal/acceptance/connection_test.go +++ b/internal/acceptance/connection_test.go @@ -49,19 +49,19 @@ func connectionTemplateWithoutOwner() string { ` } func TestUcAccConnectionsResourceFullLifecycle(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: connectionTemplateWithOwner("test.mysql.database.azure.com", "account users"), - }, step{ + }, Step{ Template: connectionTemplateWithOwner("test.mysql.database.aws.com", "account users"), - }, step{ + }, Step{ Template: connectionTemplateWithOwner("test.mysql.database.azure.com", "{env.TEST_METASTORE_ADMIN_GROUP_NAME}"), }) } func TestUcAccConnectionsWithoutOwnerResourceFullLifecycle(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: connectionTemplateWithoutOwner(), - }, step{ + }, Step{ Template: connectionTemplateWithoutOwner(), }) } diff --git a/internal/acceptance/dashboard_test.go b/internal/acceptance/dashboard_test.go index bb56147cdd..5fbf28b03a 100644 --- a/internal/acceptance/dashboard_test.go +++ b/internal/acceptance/dashboard_test.go @@ -89,7 +89,7 @@ func (t *templateStruct) SetAttributes(mapper map[string]string) templateStruct func TestAccBasicDashboard(t *testing.T) { var template templateStruct displayName := fmt.Sprintf("Test Dashboard - %s", qa.RandomName()) - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: makeTemplate(template.SetAttributes(map[string]string{ "display_name": displayName, "warehouse_id": "{env.TEST_DEFAULT_WAREHOUSE_ID}", @@ -119,7 +119,7 @@ func TestAccBasicDashboard(t *testing.T) { func TestAccDashboardWithSerializedJSON(t *testing.T) { var template templateStruct displayName := fmt.Sprintf("Test Dashboard - %s", qa.RandomName()) - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: makeTemplate(template.SetAttributes(map[string]string{ "display_name": displayName, "warehouse_id": "{env.TEST_DEFAULT_WAREHOUSE_ID}", @@ -142,7 +142,7 @@ func TestAccDashboardWithSerializedJSON(t *testing.T) { require.NoError(t, err) return nil }), - }, step{ + }, Step{ Template: makeTemplate(template.SetAttributes(map[string]string{ "serialized_dashboard": `{\"pages\":[{\"name\":\"new_name\",\"displayName\":\"New Page Modified\"}]}`, "embed_credentials": "true", @@ -174,7 +174,7 @@ func TestAccDashboardWithFilePath(t *testing.T) { fileName := tmpDir + "/Dashboard.json" var template templateStruct displayName := fmt.Sprintf("Test Dashboard - %s", qa.RandomName()) - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ PreConfig: func() { os.Mkdir(tmpDir, 0755) os.WriteFile(fileName, []byte("{\"pages\":[{\"name\":\"new_name\",\"displayName\":\"New Page\"}]}"), 0644) @@ -200,7 +200,7 @@ func TestAccDashboardWithFilePath(t *testing.T) { require.NoError(t, err) return nil }), - }, step{ + }, Step{ PreConfig: func() { os.WriteFile(fileName, []byte("{\"pages\":[{\"name\":\"new_name\",\"displayName\":\"New Page Modified\"}]}"), 0644) }, @@ -231,7 +231,7 @@ func TestAccDashboardWithNoChange(t *testing.T) { initial_update_time := "" var template templateStruct displayName := fmt.Sprintf("Test Dashboard - %s", qa.RandomName()) - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: makeTemplate(template.SetAttributes(map[string]string{ "display_name": displayName, "warehouse_id": "{env.TEST_DEFAULT_WAREHOUSE_ID}", @@ -254,7 +254,7 @@ func TestAccDashboardWithNoChange(t *testing.T) { initial_update_time = dashboard.UpdateTime return nil }), - }, step{ + }, Step{ Template: makeTemplate(template), Check: resourceCheck("databricks_dashboard.d1", func(ctx context.Context, client *common.DatabricksClient, id string) error { w, err := client.WorkspaceClient() @@ -284,7 +284,7 @@ func TestAccDashboardWithRemoteChange(t *testing.T) { etag := "" var template templateStruct displayName := fmt.Sprintf("Test Dashboard - %s", qa.RandomName()) - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: makeTemplate(template.SetAttributes(map[string]string{ "display_name": displayName, "warehouse_id": "{env.TEST_DEFAULT_WAREHOUSE_ID}", @@ -310,7 +310,7 @@ func TestAccDashboardWithRemoteChange(t *testing.T) { etag = dashboard.Etag return nil }), - }, step{ + }, Step{ PreConfig: func() { w, err := databricks.NewWorkspaceClient(&databricks.Config{}) require.NoError(t, err) @@ -355,7 +355,7 @@ func TestAccDashboardTestAll(t *testing.T) { fileName := tmpDir + "/Dashboard.json" var template templateStruct displayName := fmt.Sprintf("Test Dashboard - %s", qa.RandomName()) - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ PreConfig: func() { os.Mkdir(tmpDir, 0755) os.WriteFile(fileName, []byte("{\"pages\":[{\"name\":\"new_name\",\"displayName\":\"New Page in file\"}]}"), 0644) @@ -388,7 +388,7 @@ func TestAccDashboardTestAll(t *testing.T) { require.Equal(t, publish_dash.EmbedCredentials, false) return nil }), - }, step{ + }, Step{ PreConfig: func() { os.WriteFile(fileName, []byte("{\"pages\":[{\"name\":\"new_name\",\"displayName\":\"New Page Modified\"}]}"), 0644) }, @@ -414,7 +414,7 @@ func TestAccDashboardTestAll(t *testing.T) { assert.NotEqual(t, "", dashboard.SerializedDashboard) return nil }), - }, step{ + }, Step{ PreConfig: func() { w, err := databricks.NewWorkspaceClient(&databricks.Config{}) require.NoError(t, err) @@ -444,7 +444,7 @@ func TestAccDashboardTestAll(t *testing.T) { require.NoError(t, err) return nil }), - }, step{ + }, Step{ Template: makeTemplate(template.SetAttributes(map[string]string{ "embed_credentials": "true", "parent_path": "/Shared/Teams", @@ -466,7 +466,7 @@ func TestAccDashboardTestAll(t *testing.T) { assert.NotEqual(t, "", dashboard.SerializedDashboard) return nil }), - }, step{ + }, Step{ PreConfig: func() { os.WriteFile(fileName, []byte("{\"pages\":[{\"name\":\"new_name\",\"displayName\":\"New Page Modified again\"}]}"), 0644) }, diff --git a/internal/acceptance/data_aws_crossaccount_policy_test.go b/internal/acceptance/data_aws_crossaccount_policy_test.go index 76e263ff7f..c40e8e505b 100644 --- a/internal/acceptance/data_aws_crossaccount_policy_test.go +++ b/internal/acceptance/data_aws_crossaccount_policy_test.go @@ -9,7 +9,7 @@ import ( func TestMwsAccDataSourceAwsCrossaccountPolicy(t *testing.T) { GetEnvOrSkipTest(t, "TEST_ROOT_BUCKET") // marker for AWS test env - accountLevel(t, step{ + AccountLevel(t, Step{ Template: ` data "databricks_aws_crossaccount_policy" "this" { }`, diff --git a/internal/acceptance/data_catalog_test.go b/internal/acceptance/data_catalog_test.go index 591eacc162..83a57ff7d6 100644 --- a/internal/acceptance/data_catalog_test.go +++ b/internal/acceptance/data_catalog_test.go @@ -8,7 +8,7 @@ import ( ) func TestUcAccDataSourceCatalog(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` resource "databricks_catalog" "sandbox" { name = "sandbox{var.RANDOM}" diff --git a/internal/acceptance/data_cluster_test.go b/internal/acceptance/data_cluster_test.go index 108c46c465..9fa9407bb3 100644 --- a/internal/acceptance/data_cluster_test.go +++ b/internal/acceptance/data_cluster_test.go @@ -5,7 +5,7 @@ import ( ) func TestAccDataSourceCluster(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` data "databricks_cluster" "this" { cluster_id = "{env.TEST_DEFAULT_CLUSTER_ID}" diff --git a/internal/acceptance/data_clusters_test.go b/internal/acceptance/data_clusters_test.go index 968f3dc0d7..45d578873d 100644 --- a/internal/acceptance/data_clusters_test.go +++ b/internal/acceptance/data_clusters_test.go @@ -5,7 +5,7 @@ import ( ) func TestAccDataSourceClustersNoFilter(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` data "databricks_clusters" "this" { } `, @@ -13,7 +13,7 @@ func TestAccDataSourceClustersNoFilter(t *testing.T) { } func TestAccDataSourceClustersWithFilter(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` data "databricks_clusters" "this" { cluster_name_contains = "Default" diff --git a/internal/acceptance/data_current_config_test.go b/internal/acceptance/data_current_config_test.go index 84a1f0fe98..25fcce48e4 100644 --- a/internal/acceptance/data_current_config_test.go +++ b/internal/acceptance/data_current_config_test.go @@ -24,17 +24,17 @@ func checkCurrentConfig(t *testing.T, cloudType string, isAccount string) func(s func TestAccDataCurrentConfig(t *testing.T) { loadWorkspaceEnv(t) if isAws(t) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: `data "databricks_current_config" "this" {}`, Check: checkCurrentConfig(t, "aws", "false"), }) } else if isAzure(t) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: `data "databricks_current_config" "this" {}`, Check: checkCurrentConfig(t, "azure", "false"), }) } else if isGcp(t) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: `data "databricks_current_config" "this" {}`, Check: checkCurrentConfig(t, "gcp", "false"), }) @@ -44,17 +44,17 @@ func TestAccDataCurrentConfig(t *testing.T) { func TestMwsAccDataCurrentConfig(t *testing.T) { loadAccountEnv(t) if isAws(t) { - accountLevel(t, step{ + AccountLevel(t, Step{ Template: `data "databricks_current_config" "this" {}`, Check: checkCurrentConfig(t, "aws", "true"), }) } else if isAzure(t) { - accountLevel(t, step{ + AccountLevel(t, Step{ Template: `data "databricks_current_config" "this" {}`, Check: checkCurrentConfig(t, "azure", "true"), }) } else if isGcp(t) { - accountLevel(t, step{ + AccountLevel(t, Step{ Template: `data "databricks_current_config" "this" {}`, Check: checkCurrentConfig(t, "gcp", "true"), }) diff --git a/internal/acceptance/data_current_metastore_test.go b/internal/acceptance/data_current_metastore_test.go index 363154b1d3..38766c19a8 100644 --- a/internal/acceptance/data_current_metastore_test.go +++ b/internal/acceptance/data_current_metastore_test.go @@ -8,7 +8,7 @@ import ( ) func TestUcAccDataSourceCurrentMetastore(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` data "databricks_current_metastore" "this" { }`, diff --git a/internal/acceptance/data_external_locations_test.go b/internal/acceptance/data_external_locations_test.go index eb42a96af2..89776a05ba 100644 --- a/internal/acceptance/data_external_locations_test.go +++ b/internal/acceptance/data_external_locations_test.go @@ -8,7 +8,7 @@ import ( ) func TestUcAccDataSourceExternalLocations(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` data "databricks_external_locations" "this" { }`, diff --git a/internal/acceptance/data_group_test.go b/internal/acceptance/data_group_test.go index 8713f82fd9..664dec2fd4 100644 --- a/internal/acceptance/data_group_test.go +++ b/internal/acceptance/data_group_test.go @@ -59,7 +59,7 @@ func checkGroupDataSourcePopulated(t *testing.T) func(s *terraform.State) error func TestMwsAccGroupDataSplitMembers(t *testing.T) { GetEnvOrSkipTest(t, "ARM_CLIENT_ID") - accountLevel(t, step{ + AccountLevel(t, Step{ Template: groupDataSourceTemplate, Check: checkGroupDataSourcePopulated(t), }) @@ -67,7 +67,7 @@ func TestMwsAccGroupDataSplitMembers(t *testing.T) { func TestAccGroupDataSplitMembers(t *testing.T) { GetEnvOrSkipTest(t, "ARM_CLIENT_ID") - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: groupDataSourceTemplate, Check: checkGroupDataSourcePopulated(t), }) diff --git a/internal/acceptance/data_instance_profiles_test.go b/internal/acceptance/data_instance_profiles_test.go index e5e9544f4e..a1a1f453c1 100644 --- a/internal/acceptance/data_instance_profiles_test.go +++ b/internal/acceptance/data_instance_profiles_test.go @@ -6,7 +6,7 @@ import ( func TestAccDataSourceInstanceProfiles(t *testing.T) { GetEnvOrSkipTest(t, "TEST_EC2_INSTANCE_PROFILE") - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` data "databricks_instance_profiles" "this" { } diff --git a/internal/acceptance/data_job_test.go b/internal/acceptance/data_job_test.go index 9ca495ad98..69aed60607 100755 --- a/internal/acceptance/data_job_test.go +++ b/internal/acceptance/data_job_test.go @@ -5,7 +5,7 @@ import ( ) func TestAccDataSourceJob(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` data "databricks_current_user" "me" {} data "databricks_spark_version" "latest" {} diff --git a/internal/acceptance/data_metastore_test.go b/internal/acceptance/data_metastore_test.go index b823890ae5..092965c499 100644 --- a/internal/acceptance/data_metastore_test.go +++ b/internal/acceptance/data_metastore_test.go @@ -8,7 +8,7 @@ import ( ) func TestUcAccDataSourceMetastore(t *testing.T) { - accountLevel(t, step{ + AccountLevel(t, Step{ Template: ` data "databricks_metastore" "this" { metastore_id = "{env.TEST_METASTORE_ID}" diff --git a/internal/acceptance/data_metastores_test.go b/internal/acceptance/data_metastores_test.go index 436a9f687c..ea5b7ac782 100644 --- a/internal/acceptance/data_metastores_test.go +++ b/internal/acceptance/data_metastores_test.go @@ -8,7 +8,7 @@ import ( ) func TestUcAccDataSourceMetastores(t *testing.T) { - accountLevel(t, step{ + AccountLevel(t, Step{ Template: ` data "databricks_metastores" "this" { }`, diff --git a/internal/acceptance/data_mlflow_experiment_test.go b/internal/acceptance/data_mlflow_experiment_test.go index c2d0571877..f165a328ed 100644 --- a/internal/acceptance/data_mlflow_experiment_test.go +++ b/internal/acceptance/data_mlflow_experiment_test.go @@ -8,8 +8,8 @@ import ( ) func TestAccDataSourceMlflowExperiment(t *testing.T) { - workspaceLevel(t, - step{ + WorkspaceLevel(t, + Step{ Template: ` data "databricks_current_user" "me" {} @@ -19,7 +19,7 @@ func TestAccDataSourceMlflowExperiment(t *testing.T) { description = "My MLflow experiment description" }`, }, - step{ + Step{ Template: ` data "databricks_current_user" "me" {} @@ -51,7 +51,7 @@ func TestAccDataSourceMlflowExperiment(t *testing.T) { return nil }, }, - step{ + Step{ Template: ` data "databricks_current_user" "me" {} diff --git a/internal/acceptance/data_mlflow_model_test.go b/internal/acceptance/data_mlflow_model_test.go index 8e5d3aa9b2..3f911ab962 100644 --- a/internal/acceptance/data_mlflow_model_test.go +++ b/internal/acceptance/data_mlflow_model_test.go @@ -8,8 +8,8 @@ import ( ) func TestAccDataMlflowModel(t *testing.T) { - workspaceLevel(t, - step{ + WorkspaceLevel(t, + Step{ Template: ` resource "databricks_mlflow_model" "this" { name = "model-{var.RANDOM}" @@ -26,7 +26,7 @@ func TestAccDataMlflowModel(t *testing.T) { } }`, }, - step{ + Step{ Template: ` resource "databricks_mlflow_model" "this" { name = "model-{var.RANDOM}" diff --git a/internal/acceptance/data_mws_credentials_test.go b/internal/acceptance/data_mws_credentials_test.go index 882a889566..eb39e1b7b1 100755 --- a/internal/acceptance/data_mws_credentials_test.go +++ b/internal/acceptance/data_mws_credentials_test.go @@ -8,7 +8,7 @@ import ( ) func TestAccDataSourceMwsCredentials(t *testing.T) { - accountLevel(t, step{ + AccountLevel(t, Step{ Template: ` data "databricks_mws_credentials" "this" { }`, diff --git a/internal/acceptance/data_mws_workspaces_test.go b/internal/acceptance/data_mws_workspaces_test.go index d3a39b7e6b..9c80cf4ded 100755 --- a/internal/acceptance/data_mws_workspaces_test.go +++ b/internal/acceptance/data_mws_workspaces_test.go @@ -9,7 +9,7 @@ import ( ) func TestAccDataSourceMwsWorkspaces(t *testing.T) { - accountLevel(t, step{ + AccountLevel(t, Step{ Template: ` data "databricks_mws_workspaces" "this" { }`, diff --git a/internal/acceptance/data_pipelines_test.go b/internal/acceptance/data_pipelines_test.go index fc194dc0d5..ee487c54a2 100755 --- a/internal/acceptance/data_pipelines_test.go +++ b/internal/acceptance/data_pipelines_test.go @@ -48,7 +48,7 @@ var ( ) func TestAccDataSourcePipelines(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` locals { name = "pipeline-ds-acceptance-{var.RANDOM}" diff --git a/internal/acceptance/data_schema_test.go b/internal/acceptance/data_schema_test.go index 4024d6c40e..7a3ad79bb9 100644 --- a/internal/acceptance/data_schema_test.go +++ b/internal/acceptance/data_schema_test.go @@ -15,7 +15,7 @@ func checkDataSourceSchema(t *testing.T) func(s *terraform.State) error { } } func TestUcAccDataSourceSchema(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` resource "databricks_catalog" "sandbox" { name = "sandbox{var.RANDOM}" diff --git a/internal/acceptance/data_schemas_test.go b/internal/acceptance/data_schemas_test.go index 6258d0a07e..ff88d166db 100755 --- a/internal/acceptance/data_schemas_test.go +++ b/internal/acceptance/data_schemas_test.go @@ -20,7 +20,7 @@ func checkSchemasDataSourcePopulated(t *testing.T) func(s *terraform.State) erro } } func TestUcAccDataSourceSchemas(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` resource "databricks_catalog" "sandbox" { name = "sandbox{var.RANDOM}" diff --git a/internal/acceptance/data_service_principals_test.go b/internal/acceptance/data_service_principals_test.go index ac35f4bf11..aff919908c 100644 --- a/internal/acceptance/data_service_principals_test.go +++ b/internal/acceptance/data_service_principals_test.go @@ -28,21 +28,21 @@ data databricks_service_principals "this" { func TestAccDataSourceSPNsOnAWS(t *testing.T) { GetEnvOrSkipTest(t, "TEST_EC2_INSTANCE_PROFILE") - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: spns, }) } func TestAccDataSourceSPNsOnGCP(t *testing.T) { GetEnvOrSkipTest(t, "GOOGLE_CREDENTIALS") - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: spns, }) } func TestAccDataSourceSPNsOnAzure(t *testing.T) { GetEnvOrSkipTest(t, "ARM_CLIENT_ID") - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: azureSpns, }) } diff --git a/internal/acceptance/data_shares_test.go b/internal/acceptance/data_shares_test.go index 9f7d940132..01d64784ff 100644 --- a/internal/acceptance/data_shares_test.go +++ b/internal/acceptance/data_shares_test.go @@ -19,7 +19,7 @@ func checkSharesDataSourcePopulated(t *testing.T) func(s *terraform.State) error } } func TestUcAccDataSourceShares(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` resource "databricks_catalog" "sandbox" { name = "sandbox{var.RANDOM}" diff --git a/internal/acceptance/data_sql_warehouse_test.go b/internal/acceptance/data_sql_warehouse_test.go index 32a575ee9f..04114f5a16 100644 --- a/internal/acceptance/data_sql_warehouse_test.go +++ b/internal/acceptance/data_sql_warehouse_test.go @@ -5,7 +5,7 @@ import ( ) func TestAccDataSourceWarehouse(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` data "databricks_sql_warehouse" "this" { id = "{env.TEST_DEFAULT_WAREHOUSE_ID}" diff --git a/internal/acceptance/data_storage_credential_test.go b/internal/acceptance/data_storage_credential_test.go index a6f39d8d53..10d978e8ff 100755 --- a/internal/acceptance/data_storage_credential_test.go +++ b/internal/acceptance/data_storage_credential_test.go @@ -20,7 +20,7 @@ func checkStorageCredentialDataSourcePopulated(t *testing.T) func(s *terraform.S } } func TestUcAccDataSourceStorageCredential(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` resource "databricks_storage_credential" "external" { name = "cred-{var.RANDOM}" diff --git a/internal/acceptance/data_storage_credentials_test.go b/internal/acceptance/data_storage_credentials_test.go index e29f388acf..17d3ac290f 100644 --- a/internal/acceptance/data_storage_credentials_test.go +++ b/internal/acceptance/data_storage_credentials_test.go @@ -8,7 +8,7 @@ import ( ) func TestUcAccDataSourceStorageCredentials(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` data "databricks_storage_credentials" "this" { }`, diff --git a/internal/acceptance/data_table_test.go b/internal/acceptance/data_table_test.go index 2167c7ac7e..09285149bb 100644 --- a/internal/acceptance/data_table_test.go +++ b/internal/acceptance/data_table_test.go @@ -15,7 +15,7 @@ func checkTableDataSourcePopulated(t *testing.T) func(s *terraform.State) error } } func TestUcAccDataSourceTable(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` resource "databricks_catalog" "sandbox" { name = "sandbox{var.RANDOM}" diff --git a/internal/acceptance/data_tables_test.go b/internal/acceptance/data_tables_test.go index 4057828af7..9f81f206d9 100644 --- a/internal/acceptance/data_tables_test.go +++ b/internal/acceptance/data_tables_test.go @@ -25,7 +25,7 @@ func checkTablesDataSourcePopulated(t *testing.T) func(s *terraform.State) error } } func TestUcAccDataSourceTables(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` resource "databricks_catalog" "sandbox" { name = "sandbox{var.RANDOM}" diff --git a/internal/acceptance/data_user_test.go b/internal/acceptance/data_user_test.go index fc46bf1ad3..e7d50d8889 100644 --- a/internal/acceptance/data_user_test.go +++ b/internal/acceptance/data_user_test.go @@ -26,14 +26,14 @@ func checkUserDataSourcePopulated(t *testing.T) func(s *terraform.State) error { } func TestMwsAccUserData(t *testing.T) { - accountLevel(t, step{ + AccountLevel(t, Step{ Template: userDataSourceTemplate, Check: checkUserDataSourcePopulated(t), }) } func TestAccUserData(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: userDataSourceTemplate, Check: checkUserDataSourcePopulated(t), }) diff --git a/internal/acceptance/data_volume_test.go b/internal/acceptance/data_volume_test.go index 8f65c44f2e..6679da99c0 100644 --- a/internal/acceptance/data_volume_test.go +++ b/internal/acceptance/data_volume_test.go @@ -15,7 +15,7 @@ func checkDataSourceVolume(t *testing.T) func(s *terraform.State) error { } } func TestUcAccDataSourceVolume(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` resource "databricks_catalog" "sandbox" { name = "sandbox{var.RANDOM}" diff --git a/internal/acceptance/data_volumes_test.go b/internal/acceptance/data_volumes_test.go index 968ab4a29c..67581ea3fe 100644 --- a/internal/acceptance/data_volumes_test.go +++ b/internal/acceptance/data_volumes_test.go @@ -19,7 +19,7 @@ func checkDataSourceVolumesPopulated(t *testing.T) func(s *terraform.State) erro } } func TestUcAccDataSourceVolumes(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` resource "databricks_catalog" "sandbox" { name = "sandbox{var.RANDOM}" @@ -70,7 +70,7 @@ func checkDataSourceVolumesPluginFrameworkPopulated(t *testing.T) func(s *terraf } func TestUcAccDataSourceVolumesPluginFramework(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` resource "databricks_catalog" "sandbox" { name = "sandbox{var.RANDOM}" diff --git a/internal/acceptance/dbfs_file_test.go b/internal/acceptance/dbfs_file_test.go index 939422a352..c9ffcd88ee 100644 --- a/internal/acceptance/dbfs_file_test.go +++ b/internal/acceptance/dbfs_file_test.go @@ -5,12 +5,12 @@ import ( ) func TestAccDatabricksDBFSFile_CreateViaContent(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: `resource "databricks_dbfs_file" "this" { content_base64 = base64encode("{var.RANDOM}") path = "/tmp/tf-test/{var.RANDOM}.bin" }`, - }, step{ + }, Step{ Template: `resource "databricks_dbfs_file" "this" { content_base64 = base64encode("{var.RANDOM}-changed") path = "/tmp/tf-test/{var.RANDOM}.bin" @@ -19,7 +19,7 @@ func TestAccDatabricksDBFSFile_CreateViaContent(t *testing.T) { } func TestAccDatabricksDBFSFile_CreateViaSource(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: `resource "databricks_dbfs_file" "file_1" { source = "{var.CWD}/../../storage/testdata/tf-test-python.py" path = "/tmp/tf-test/file-source-{var.RANDOM}" diff --git a/internal/acceptance/default_namespace_test.go b/internal/acceptance/default_namespace_test.go index 83476fbecd..a2f4402c4e 100644 --- a/internal/acceptance/default_namespace_test.go +++ b/internal/acceptance/default_namespace_test.go @@ -21,7 +21,7 @@ func TestAccDefaultNamespaceSetting(t *testing.T) { } } ` - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: template, Check: resourceCheckWithState("databricks_default_namespace_setting.this", func(ctx context.Context, client *common.DatabricksClient, state *terraform.InstanceState) error { @@ -39,7 +39,7 @@ func TestAccDefaultNamespaceSetting(t *testing.T) { return nil }), }, - step{ + Step{ Template: template, Destroy: true, Check: resourceCheck("databricks_default_namespace_setting.this", func(ctx context.Context, client *common.DatabricksClient, id string) error { diff --git a/internal/acceptance/directory_test.go b/internal/acceptance/directory_test.go index 0de7924f93..d80e250d85 100644 --- a/internal/acceptance/directory_test.go +++ b/internal/acceptance/directory_test.go @@ -5,7 +5,7 @@ import ( ) func TestAccDirectoryResource(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: `resource "databricks_directory" "this" { path = "/Shared/provider-test/dir_{var.RANDOM}" } diff --git a/internal/acceptance/entitlements_test.go b/internal/acceptance/entitlements_test.go index 49d5c2a88a..2aeb4e2d0b 100644 --- a/internal/acceptance/entitlements_test.go +++ b/internal/acceptance/entitlements_test.go @@ -21,13 +21,13 @@ func (e entitlement) String() string { return fmt.Sprintf("%s = %t", e.name, e.value) } -func entitlementsStepBuilder(t *testing.T, r entitlementResource) func(entitlements []entitlement) step { - return func(entitlements []entitlement) step { +func entitlementsStepBuilder(t *testing.T, r entitlementResource) func(entitlements []entitlement) Step { + return func(entitlements []entitlement) Step { entitlementsBuf := strings.Builder{} for _, entitlement := range entitlements { entitlementsBuf.WriteString(fmt.Sprintf("%s\n", entitlement.String())) } - return step{ + return Step{ Template: fmt.Sprintf(` %s resource "databricks_entitlements" "entitlements_users" { @@ -56,10 +56,10 @@ func entitlementsStepBuilder(t *testing.T, r entitlementResource) func(entitleme } } -func makeEntitlementsSteps(t *testing.T, r entitlementResource, entitlementsSteps [][]entitlement) []step { +func makeEntitlementsSteps(t *testing.T, r entitlementResource, entitlementsSteps [][]entitlement) []Step { r.setDisplayName(RandomName("entitlements-")) makeEntitlementsStep := entitlementsStepBuilder(t, r) - steps := make([]step, len(entitlementsSteps)) + steps := make([]Step, len(entitlementsSteps)) for i, entitlements := range entitlementsSteps { steps[i] = makeEntitlementsStep(entitlements) } @@ -114,7 +114,7 @@ func TestAccEntitlementsAddToEmpty(t *testing.T) { {"databricks_sql_access", true}, }, }) - workspaceLevel(t, steps...) + WorkspaceLevel(t, steps...) }) } @@ -135,7 +135,7 @@ func TestAccEntitlementsSetExplicitlyToFalse(t *testing.T) { {"databricks_sql_access", false}, }, }) - workspaceLevel(t, steps...) + WorkspaceLevel(t, steps...) }) } @@ -150,7 +150,7 @@ func TestAccEntitlementsRemoveExisting(t *testing.T) { }, {}, }) - workspaceLevel(t, steps...) + WorkspaceLevel(t, steps...) }) } @@ -164,6 +164,6 @@ func TestAccEntitlementsSomeTrueSomeFalse(t *testing.T) { {"databricks_sql_access", true}, }, }) - workspaceLevel(t, steps...) + WorkspaceLevel(t, steps...) }) } diff --git a/internal/acceptance/external_location_test.go b/internal/acceptance/external_location_test.go index fd8f497750..a7b0074cf6 100644 --- a/internal/acceptance/external_location_test.go +++ b/internal/acceptance/external_location_test.go @@ -44,7 +44,7 @@ func storageCredentialTemplateWithOwner(comment, owner string) string { } func TestUcAccExternalLocation(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` resource "databricks_storage_credential" "external" { name = "cred-{var.RANDOM}" @@ -64,7 +64,7 @@ func TestUcAccExternalLocation(t *testing.T) { } func TestUcAccExternalLocationForceDestroy(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` resource "databricks_storage_credential" "external" { name = "cred-{var.RANDOM}" @@ -85,19 +85,19 @@ func TestUcAccExternalLocationForceDestroy(t *testing.T) { } func TestUcAccExternalLocationUpdate(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: storageCredentialTemplateWithOwner("Managed by TF", "account users") + externalLocationTemplateWithOwner("Managed by TF", "account users") + grantsTemplateForExternalLocation, - }, step{ + }, Step{ Template: storageCredentialTemplateWithOwner("Managed by TF -- Updated Comment", "account users") + externalLocationTemplateWithOwner("Managed by TF -- Updated Comment", "account users") + grantsTemplateForExternalLocation, - }, step{ + }, Step{ Template: storageCredentialTemplateWithOwner("Managed by TF -- Updated Comment", "{env.TEST_DATA_ENG_GROUP}") + externalLocationTemplateWithOwner("Managed by TF -- Updated Comment", "{env.TEST_DATA_ENG_GROUP}") + grantsTemplateForExternalLocation, - }, step{ + }, Step{ Template: storageCredentialTemplateWithOwner("Managed by TF -- Updated Comment 2", "{env.TEST_METASTORE_ADMIN_GROUP_NAME}") + externalLocationTemplateWithOwner("Managed by TF -- Updated Comment 2", "{env.TEST_METASTORE_ADMIN_GROUP_NAME}") + grantsTemplateForExternalLocation, diff --git a/internal/acceptance/file_test.go b/internal/acceptance/file_test.go index d821d05b73..54f05032cd 100644 --- a/internal/acceptance/file_test.go +++ b/internal/acceptance/file_test.go @@ -18,7 +18,7 @@ import ( func TestUcAccFileDontUpdateIfNoChange(t *testing.T) { createdTime := "" - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` resource "databricks_schema" "this" { name = "schema-{var.STICKY_RANDOM}" @@ -50,7 +50,7 @@ func TestUcAccFileDontUpdateIfNoChange(t *testing.T) { createdTime = m.LastModified return nil }), - }, step{ + }, Step{ Template: ` resource "databricks_schema" "this" { name = "schema-{var.STICKY_RANDOM}" @@ -86,7 +86,7 @@ func TestUcAccFileDontUpdateIfNoChange(t *testing.T) { func TestUcAccFileUpdateOnLocalContentChange(t *testing.T) { createdTime := "" - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` resource "databricks_schema" "this" { name = "schema-{var.STICKY_RANDOM}" @@ -118,7 +118,7 @@ func TestUcAccFileUpdateOnLocalContentChange(t *testing.T) { createdTime = m.LastModified return nil }), - }, step{ + }, Step{ Template: ` resource "databricks_schema" "this" { name = "schema-{var.STICKY_RANDOM}" @@ -174,7 +174,7 @@ func TestUcAccFileUpdateOnLocalFileChange(t *testing.T) { source = "%s" path = "/Volumes/${databricks_volume.this.catalog_name}/${databricks_volume.this.schema_name}/${databricks_volume.this.name}/abcde" }`, fileName) - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ PreConfig: func() { os.Mkdir(tmpDir, 0755) os.WriteFile(fileName, []byte("abc\n"), 0644) @@ -193,7 +193,7 @@ func TestUcAccFileUpdateOnLocalFileChange(t *testing.T) { createdTime = m.LastModified return nil }), - }, step{ + }, Step{ PreConfig: func() { os.WriteFile(fileName, []byte("def\n"), 0644) }, @@ -235,7 +235,7 @@ func TestUcAccFileNoUpdateIfFileDoesNotChange(t *testing.T) { source = "%s" path = "/Volumes/${databricks_volume.this.catalog_name}/${databricks_volume.this.schema_name}/${databricks_volume.this.name}/abcde" }`, fileName) - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ PreConfig: func() { os.Mkdir(tmpDir, 0755) os.WriteFile(fileName, []byte("abc\n"), 0644) @@ -254,7 +254,7 @@ func TestUcAccFileNoUpdateIfFileDoesNotChange(t *testing.T) { createdTime = m.LastModified return nil }), - }, step{ + }, Step{ Template: template, Check: resourceCheck("databricks_file.this", func(ctx context.Context, client *common.DatabricksClient, id string) error { w, err := client.WorkspaceClient() @@ -273,7 +273,7 @@ func TestUcAccFileNoUpdateIfFileDoesNotChange(t *testing.T) { func TestUcAccFileUpdateServerChange(t *testing.T) { createdTime := "" - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` resource "databricks_schema" "this" { name = "schema-{var.STICKY_RANDOM}" @@ -314,7 +314,7 @@ func TestUcAccFileUpdateServerChange(t *testing.T) { return nil }), }, - step{ + Step{ Template: ` resource "databricks_schema" "this" { name = "schema-{var.STICKY_RANDOM}" @@ -356,7 +356,7 @@ func TestUcAccFileUpdateServerChange(t *testing.T) { } func TestUcAccFileFullLifeCycle(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` resource "databricks_schema" "this" { name = "schema-{var.STICKY_RANDOM}" @@ -375,7 +375,7 @@ func TestUcAccFileFullLifeCycle(t *testing.T) { source = "{var.CWD}/../../storage/testdata/tf-test-python.py" path = "/Volumes/${databricks_volume.this.catalog_name}/${databricks_volume.this.schema_name}/${databricks_volume.this.name}/abcde" }`, - }, step{ + }, Step{ Template: ` resource "databricks_schema" "this" { name = "schema-{var.STICKY_RANDOM}" @@ -398,7 +398,7 @@ func TestUcAccFileFullLifeCycle(t *testing.T) { } func TestUcAccFileBase64FullLifeCycle(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` resource "databricks_schema" "this" { name = "schema-{var.STICKY_RANDOM}" @@ -417,7 +417,7 @@ func TestUcAccFileBase64FullLifeCycle(t *testing.T) { content_base64 = "YWJjCg==" path = "/Volumes/${databricks_volume.this.catalog_name}/${databricks_volume.this.schema_name}/${databricks_volume.this.name}/abcde" }`, - }, step{ + }, Step{ Template: ` resource "databricks_schema" "this" { name = "schema-{var.STICKY_RANDOM}" diff --git a/internal/acceptance/git_credential_test.go b/internal/acceptance/git_credential_test.go index 4cae7b2c84..7d418ebbf1 100644 --- a/internal/acceptance/git_credential_test.go +++ b/internal/acceptance/git_credential_test.go @@ -9,7 +9,7 @@ import ( ) func TestAccGitCredentials(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: `resource "databricks_git_credential" "this" { git_username = "test" git_provider = "gitHub" diff --git a/internal/acceptance/global_init_script_test.go b/internal/acceptance/global_init_script_test.go index 626fa757a7..3f6c1c2cdf 100644 --- a/internal/acceptance/global_init_script_test.go +++ b/internal/acceptance/global_init_script_test.go @@ -5,7 +5,7 @@ import ( ) func TestAccGlobalInitScriptResource_Create(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` resource "databricks_global_init_script" "this" { name = "init-{var.RANDOM}" diff --git a/internal/acceptance/grant_test.go b/internal/acceptance/grant_test.go index f0da0e8f77..de0e83d32f 100644 --- a/internal/acceptance/grant_test.go +++ b/internal/acceptance/grant_test.go @@ -99,11 +99,11 @@ resource "databricks_grant" "some" { }` func TestUcAccGrant(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: strings.ReplaceAll(grantTemplate, "%s", "{env.TEST_DATA_ENG_GROUP}"), - }, step{ + }, Step{ Template: strings.ReplaceAll(grantTemplate, "%s", "{env.TEST_DATA_SCI_GROUP}"), - }, step{ + }, Step{ Template: strings.ReplaceAll(strings.ReplaceAll(grantTemplate, "ALL_PRIVILEGES", "ALL PRIVILEGES"), "%s", "{env.TEST_DATA_ENG_GROUP}"), }) } @@ -127,11 +127,11 @@ func grantTemplateForNamePermissionChange(suffix string, permission string) stri } func TestUcAccGrantForIdChange(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: grantTemplateForNamePermissionChange("-old", "ALL_PRIVILEGES"), - }, step{ + }, Step{ Template: grantTemplateForNamePermissionChange("-new", "ALL_PRIVILEGES"), - }, step{ + }, Step{ Template: grantTemplateForNamePermissionChange("-fail", "abc"), ExpectError: regexp.MustCompile(`cannot create grant: Privilege ABC is not applicable to this entity`), }) diff --git a/internal/acceptance/grants_test.go b/internal/acceptance/grants_test.go index 251ccb94f3..43fc09d650 100644 --- a/internal/acceptance/grants_test.go +++ b/internal/acceptance/grants_test.go @@ -105,11 +105,11 @@ resource "databricks_grants" "some" { }` func TestUcAccGrants(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: strings.ReplaceAll(grantsTemplate, "%s", "{env.TEST_DATA_ENG_GROUP}"), - }, step{ + }, Step{ Template: strings.ReplaceAll(grantsTemplate, "%s", "{env.TEST_DATA_SCI_GROUP}"), - }, step{ + }, Step{ Template: strings.ReplaceAll(strings.ReplaceAll(grantsTemplate, "ALL_PRIVILEGES", "ALL PRIVILEGES"), "%s", "{env.TEST_DATA_ENG_GROUP}"), }) } @@ -135,11 +135,11 @@ func grantsTemplateForNamePermissionChange(suffix string, permission string) str } func TestUcAccGrantsForIdChange(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: grantsTemplateForNamePermissionChange("-old", "ALL_PRIVILEGES"), - }, step{ + }, Step{ Template: grantsTemplateForNamePermissionChange("-new", "ALL_PRIVILEGES"), - }, step{ + }, Step{ Template: grantsTemplateForNamePermissionChange("-fail", "abc"), ExpectError: regexp.MustCompile(`Error: cannot create grants: Privilege ABC is not applicable to this entity`), }) diff --git a/internal/acceptance/group_member_test.go b/internal/acceptance/group_member_test.go index dabbce3842..abaf921bd0 100644 --- a/internal/acceptance/group_member_test.go +++ b/internal/acceptance/group_member_test.go @@ -29,7 +29,7 @@ resource "databricks_group_member" "rs" { }` func TestMwsAccGroupMemberResource(t *testing.T) { - accountLevel(t, step{ + AccountLevel(t, Step{ Template: groupMemberTest, Check: resourceCheck("databricks_group.root", func(ctx context.Context, client *common.DatabricksClient, id string) error { @@ -44,7 +44,7 @@ func TestMwsAccGroupMemberResource(t *testing.T) { } func TestAccGroupMemberResource(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: groupMemberTest, Check: resourceCheck("databricks_group.root", func(ctx context.Context, client *common.DatabricksClient, id string) error { diff --git a/internal/acceptance/group_role_test.go b/internal/acceptance/group_role_test.go index 7ba0c167df..8c6a929501 100644 --- a/internal/acceptance/group_role_test.go +++ b/internal/acceptance/group_role_test.go @@ -5,7 +5,7 @@ import ( ) func TestAccGroupRole(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` resource "databricks_group" "this" { display_name = "tf-{var.RANDOM}" diff --git a/internal/acceptance/group_test.go b/internal/acceptance/group_test.go index 95ead635cf..285a0f1952 100644 --- a/internal/acceptance/group_test.go +++ b/internal/acceptance/group_test.go @@ -16,7 +16,7 @@ import ( func TestMwsAccGroupsExternalIdAndScimProvisioning(t *testing.T) { name := qa.RandomName("tfgroup") - accountLevel(t, step{ + AccountLevel(t, Step{ Template: `resource "databricks_group" "this" { display_name = "` + name + `" }`, @@ -33,7 +33,7 @@ func TestMwsAccGroupsExternalIdAndScimProvisioning(t *testing.T) { return groupsAPI.UpdateNameAndEntitlements( id, group.DisplayName, qa.RandomName("ext-id"), group.Entitlements) }), - }, step{ + }, Step{ Template: `resource "databricks_group" "this" { display_name = "` + name + `" }`, @@ -43,7 +43,7 @@ func TestMwsAccGroupsExternalIdAndScimProvisioning(t *testing.T) { // https://github.com/databricks/terraform-provider-databricks/issues/1099 func TestAccGroupsExternalIdAndScimProvisioning(t *testing.T) { name := qa.RandomName("tfgroup") - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: `resource "databricks_group" "this" { display_name = "` + name + `" allow_cluster_create = true @@ -63,7 +63,7 @@ func TestAccGroupsExternalIdAndScimProvisioning(t *testing.T) { id, group.DisplayName, qa.RandomName("ext-id"), group.Entitlements) }), ), - }, step{ + }, Step{ Template: `resource "databricks_group" "this" { display_name = "` + name + `" allow_cluster_create = true @@ -74,7 +74,7 @@ func TestAccGroupsExternalIdAndScimProvisioning(t *testing.T) { func TestMwsAccGroupsUpdateDisplayName(t *testing.T) { nameInit := qa.RandomName("tfgroup") nameUpdate := qa.RandomName("tfgroup") - accountLevel(t, step{ + AccountLevel(t, Step{ Template: `resource "databricks_group" "this" { display_name = "` + nameInit + `" }`, @@ -91,7 +91,7 @@ func TestMwsAccGroupsUpdateDisplayName(t *testing.T) { return nil }), ), - }, step{ + }, Step{ Template: `resource "databricks_group" "this" { display_name = "` + nameUpdate + `" }`, @@ -113,7 +113,7 @@ func TestMwsAccGroupsUpdateDisplayName(t *testing.T) { func TestAccGroupsUpdateDisplayName(t *testing.T) { nameInit := qa.RandomName("tfgroup") nameUpdate := qa.RandomName("tfgroup") - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: `resource "databricks_group" "this" { display_name = "` + nameInit + `" }`, @@ -130,7 +130,7 @@ func TestAccGroupsUpdateDisplayName(t *testing.T) { return nil }), ), - }, step{ + }, Step{ Template: `resource "databricks_group" "this" { display_name = "` + nameUpdate + `" }`, diff --git a/internal/acceptance/init_test.go b/internal/acceptance/init.go similarity index 97% rename from internal/acceptance/init_test.go rename to internal/acceptance/init.go index fb13d01567..704964b710 100644 --- a/internal/acceptance/init_test.go +++ b/internal/acceptance/init.go @@ -36,28 +36,28 @@ func init() { dbproviderlogger.SetTfLogger(dbproviderlogger.NewTfLogger(context.Background())) } -func workspaceLevel(t *testing.T, steps ...step) { +func WorkspaceLevel(t *testing.T, steps ...Step) { loadWorkspaceEnv(t) run(t, steps) } -func accountLevel(t *testing.T, steps ...step) { +func AccountLevel(t *testing.T, steps ...Step) { loadAccountEnv(t) run(t, steps) } -func unityWorkspaceLevel(t *testing.T, steps ...step) { +func UnityWorkspaceLevel(t *testing.T, steps ...Step) { loadUcwsEnv(t) run(t, steps) } -func unityAccountLevel(t *testing.T, steps ...step) { +func UnityAccountLevel(t *testing.T, steps ...Step) { loadUcacctEnv(t) run(t, steps) } // A step in a terraform acceptance test -type step struct { +type Step struct { // Terraform HCL for resources to materialize in this test step. Template string @@ -132,7 +132,7 @@ func environmentTemplate(t *testing.T, template string, otherVars ...map[string] // Test wrapper over terraform testing framework. Multiple steps share the same // terraform state context. -func run(t *testing.T, steps []step) { +func run(t *testing.T, steps []Step) { cloudEnv := os.Getenv("CLOUD_ENV") if cloudEnv == "" { t.Skip("Acceptance tests skipped unless env 'CLOUD_ENV' is set") diff --git a/internal/acceptance/instance_profile_test.go b/internal/acceptance/instance_profile_test.go index b5ddb13600..f663c17d43 100644 --- a/internal/acceptance/instance_profile_test.go +++ b/internal/acceptance/instance_profile_test.go @@ -7,9 +7,9 @@ import ( // "databricks_instance_profile" is a singleton. To avoid multiple tests using this resource // from interfering with each other, we run them in sequence as steps of a single test. func TestAccInstanceProfileIntegrationSuite(t *testing.T) { - workspaceLevel(t, + WorkspaceLevel(t, // Assign instance profile to group - step{ + Step{ Template: ` resource "databricks_instance_profile" "this" { instance_profile_arn = "{env.DUMMY_EC2_INSTANCE_PROFILE}" @@ -22,7 +22,7 @@ func TestAccInstanceProfileIntegrationSuite(t *testing.T) { instance_profile_id = databricks_instance_profile.this.id }`}, // Assign instance profile to mount - step{ + Step{ Template: ` resource "databricks_instance_profile" "this" { instance_profile_arn = "{env.DUMMY_EC2_INSTANCE_PROFILE}" @@ -37,7 +37,7 @@ func TestAccInstanceProfileIntegrationSuite(t *testing.T) { }`, }, // ServicePrincipal resource on Aws with role - step{ + Step{ Template: ` resource "databricks_service_principal" "this" { display_name = "SPN {var.RANDOM}" diff --git a/internal/acceptance/ip_access_list_test.go b/internal/acceptance/ip_access_list_test.go index 4910e3b2ab..bfd1802193 100644 --- a/internal/acceptance/ip_access_list_test.go +++ b/internal/acceptance/ip_access_list_test.go @@ -5,7 +5,7 @@ import ( ) func TestAccIPACLListsResourceFullLifecycle(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` resource "databricks_ip_access_list" "this" { label = "tf-{var.RANDOM}" @@ -15,7 +15,7 @@ func TestAccIPACLListsResourceFullLifecycle(t *testing.T) { "10.0.10.0/24" ] }`, - }, step{ + }, Step{ Template: ` resource "databricks_ip_access_list" "this" { label = "tf-{var.RANDOM}" diff --git a/internal/acceptance/job_test.go b/internal/acceptance/job_test.go index ddf0d74325..b28b5a6bb9 100644 --- a/internal/acceptance/job_test.go +++ b/internal/acceptance/job_test.go @@ -16,7 +16,7 @@ import ( ) func TestAccJobTasks(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` data "databricks_current_user" "me" {} data "databricks_spark_version" "latest" {} @@ -120,7 +120,7 @@ func TestAccJobTasks(t *testing.T) { func TestAccForEachTask(t *testing.T) { t.Skip("Skipping this test because feature not enabled in Prod") - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` data "databricks_current_user" "me" {} data "databricks_spark_version" "latest" {} @@ -282,19 +282,19 @@ func TestAccJobControlRunState(t *testing.T) { } randomName1 := RandomName("notebook-") randomName2 := RandomName("updated-notebook-") - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ // A new continuous job with empty block should be started automatically Template: getJobTemplate(randomName1, ``), Check: resourceCheck("databricks_job.this", waitForRunToStart), - }, step{ + }, Step{ // Updating the notebook should cancel the existing run Template: getJobTemplate(randomName2, ``), Check: resourceCheck("databricks_job.this", waitForRunToStart), - }, step{ + }, Step{ // Marking the job as paused should cancel existing run and not start a new one Template: getJobTemplate(randomName2, `pause_status = "PAUSED"`), Check: resourceCheck("databricks_job.this", waitForAllRunsToEnd), - }, step{ + }, Step{ // No pause status should be the equivalent of unpaused Template: getJobTemplate(randomName2, `pause_status = "UNPAUSED"`), Check: resourceCheck("databricks_job.this", waitForRunToStart), @@ -346,7 +346,7 @@ func runAsTemplate(runAs string) string { } func TestAccJobRunAsUser(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` resource "databricks_user" "this" { user_name = "` + qa.RandomEmail() + `" @@ -358,7 +358,7 @@ func TestAccJobRunAsUser(t *testing.T) { func TestUcAccJobRunAsServicePrincipal(t *testing.T) { loadUcwsEnv(t) spId := GetEnvOrSkipTest(t, "ACCOUNT_LEVEL_SERVICE_PRINCIPAL_ID") - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: runAsTemplate(`service_principal_name = "` + spId + `"`), }) } @@ -378,18 +378,18 @@ func TestUcAccJobRunAsMutations(t *testing.T) { // Note: the attribute must match the type of principal that the test is run as. ctx := context.Background() attribute := getRunAsAttribute(t, ctx) - unityWorkspaceLevel( + UnityWorkspaceLevel( t, // Provision job with service principal `run_as` - step{ + Step{ Template: runAsTemplate(`service_principal_name = "` + spId + `"`), }, // Update job to a user `run_as` - step{ + Step{ Template: runAsTemplate(attribute + ` = data.databricks_current_user.me.user_name`), }, // Update job back to a service principal `run_as` - step{ + Step{ Template: runAsTemplate(`service_principal_name = "` + spId + `"`), }, ) @@ -397,7 +397,7 @@ func TestUcAccJobRunAsMutations(t *testing.T) { func TestAccRemoveWebhooks(t *testing.T) { skipf(t)("There is no API to create notification destinations. Once available, add here and enable this test.") - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` resource databricks_job test { webhook_notifications { @@ -407,7 +407,7 @@ func TestAccRemoveWebhooks(t *testing.T) { } } `, - }, step{ + }, Step{ Template: ` resource databricks_job test {} `, @@ -415,7 +415,7 @@ func TestAccRemoveWebhooks(t *testing.T) { } func TestAccPeriodicTrigger(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` resource "databricks_job" "this" { name = "{var.RANDOM}" diff --git a/internal/acceptance/metastore_assignment_test.go b/internal/acceptance/metastore_assignment_test.go index 8b0b6d3dbd..415f79fb8c 100644 --- a/internal/acceptance/metastore_assignment_test.go +++ b/internal/acceptance/metastore_assignment_test.go @@ -15,7 +15,7 @@ func lockForTest(t *testing.T) func() { } func TestUcAccMetastoreAssignment(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ PreConfig: lockForTest(t), Template: `resource "databricks_metastore_assignment" "this" { metastore_id = "{env.TEST_METASTORE_ID}" @@ -25,13 +25,13 @@ func TestUcAccMetastoreAssignment(t *testing.T) { } func TestUcAccAccountMetastoreAssignment(t *testing.T) { - unityAccountLevel(t, step{ + UnityAccountLevel(t, Step{ PreConfig: lockForTest(t), Template: `resource "databricks_metastore_assignment" "this" { metastore_id = "{env.TEST_METASTORE_ID}" workspace_id = {env.DUMMY_WORKSPACE_ID} }`, - }, step{ + }, Step{ Template: `resource "databricks_metastore_assignment" "this" { metastore_id = "{env.TEST_METASTORE_ID}" workspace_id = {env.DUMMY2_WORKSPACE_ID} diff --git a/internal/acceptance/metastore_data_access_test.go b/internal/acceptance/metastore_data_access_test.go index b9c6f6046d..34a3b5032a 100644 --- a/internal/acceptance/metastore_data_access_test.go +++ b/internal/acceptance/metastore_data_access_test.go @@ -5,7 +5,7 @@ import ( ) func TestUcAccAccountMetastoreDataAccessOnAws(t *testing.T) { - unityAccountLevel(t, step{ + UnityAccountLevel(t, Step{ Template: ` resource "databricks_metastore" "this" { name = "primary-{var.RANDOM}" @@ -24,7 +24,7 @@ func TestUcAccAccountMetastoreDataAccessOnAws(t *testing.T) { } func TestUcAccMetastoreDataAccessOnAws(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` resource "databricks_metastore_data_access" "this" { metastore_id = "{env.TEST_METASTORE_ID}" diff --git a/internal/acceptance/metastore_test.go b/internal/acceptance/metastore_test.go index 5ef31beb6a..a430b91839 100644 --- a/internal/acceptance/metastore_test.go +++ b/internal/acceptance/metastore_test.go @@ -87,7 +87,7 @@ func getTemplateFromExtraAttributes(t *testing.T, extraAttributes map[string]any func runMetastoreTest(t *testing.T, extraAttributes map[string]any) { template := getTemplateFromExtraAttributes(t, extraAttributes) - unityAccountLevel(t, step{ + UnityAccountLevel(t, Step{ Template: fmt.Sprintf(`resource "databricks_metastore" "this" { name = "{var.RANDOM}" force_destroy = true @@ -98,21 +98,21 @@ func runMetastoreTest(t *testing.T, extraAttributes map[string]any) { func runMetastoreTestWithOwnerUpdates(t *testing.T, extraAttributes map[string]any) { template := getTemplateFromExtraAttributes(t, extraAttributes) - unityAccountLevel(t, step{ + UnityAccountLevel(t, Step{ Template: fmt.Sprintf(`resource "databricks_metastore" "this" { name = "{var.STICKY_RANDOM}" force_destroy = true owner = "account users" %s }`, template), - }, step{ + }, Step{ Template: fmt.Sprintf(`resource "databricks_metastore" "this" { name = "{var.STICKY_RANDOM}" force_destroy = true owner = "{env.TEST_DATA_ENG_GROUP}" %s }`, template), - }, step{ + }, Step{ Template: fmt.Sprintf(`resource "databricks_metastore" "this" { name = "{var.STICKY_RANDOM}-updated" force_destroy = true diff --git a/internal/acceptance/mlflow_experiment_test.go b/internal/acceptance/mlflow_experiment_test.go index 2a6f76c98f..024f03fda8 100644 --- a/internal/acceptance/mlflow_experiment_test.go +++ b/internal/acceptance/mlflow_experiment_test.go @@ -5,7 +5,7 @@ import ( ) func TestAccMLflowExperiment(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` resource "databricks_mlflow_experiment" "e1" { name = "/Shared/tf-{var.RANDOM}" diff --git a/internal/acceptance/mlflow_model_test.go b/internal/acceptance/mlflow_model_test.go index db3d597273..6dc2e47c9d 100644 --- a/internal/acceptance/mlflow_model_test.go +++ b/internal/acceptance/mlflow_model_test.go @@ -5,7 +5,7 @@ import ( ) func TestAccMLflowModel(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` resource "databricks_mlflow_model" "m1" { name = "tf-{var.RANDOM}" diff --git a/internal/acceptance/model_serving_test.go b/internal/acceptance/model_serving_test.go index f0bafb7368..fdc00a920f 100644 --- a/internal/acceptance/model_serving_test.go +++ b/internal/acceptance/model_serving_test.go @@ -15,7 +15,7 @@ func TestAccModelServing(t *testing.T) { name := fmt.Sprintf("terraform-test-model-serving-%s", acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)) - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: fmt.Sprintf(` resource "databricks_model_serving" "endpoint" { name = "%s" @@ -57,7 +57,7 @@ func TestAccModelServing(t *testing.T) { } `, name), }, - step{ + Step{ Template: fmt.Sprintf(` resource "databricks_model_serving" "endpoint" { name = "%s" @@ -90,7 +90,7 @@ func TestUcAccModelServingProvisionedThroughput(t *testing.T) { name := fmt.Sprintf("terraform-test-model-serving-pt-%s", acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)) - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: fmt.Sprintf(` resource "databricks_model_serving" "endpoint" { name = "%s" @@ -111,7 +111,7 @@ func TestUcAccModelServingProvisionedThroughput(t *testing.T) { } } `, name), - }, step{ + }, Step{ Template: fmt.Sprintf(` resource "databricks_model_serving" "endpoint" { name = "%s" @@ -132,7 +132,7 @@ func TestUcAccModelServingProvisionedThroughput(t *testing.T) { } } `, name), - }, step{ + }, Step{ Template: fmt.Sprintf(` resource "databricks_model_serving" "endpoint" { name = "%s" @@ -167,7 +167,7 @@ func TestAccModelServingExternalModel(t *testing.T) { acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)) scope_name := fmt.Sprintf("terraform-test-secret-scope-%s", acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)) - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: fmt.Sprintf(` resource "databricks_secret_scope" "scope" { name = "%s" @@ -203,7 +203,7 @@ func TestAccModelServingExternalModel(t *testing.T) { } `, scope_name, name), }, - step{ + Step{ Template: fmt.Sprintf(` resource "databricks_secret_scope" "scope" { name = "%s" diff --git a/internal/acceptance/mounts_test.go b/internal/acceptance/mounts_test.go index 0a7270563c..9b5401b163 100644 --- a/internal/acceptance/mounts_test.go +++ b/internal/acceptance/mounts_test.go @@ -38,8 +38,8 @@ resource "databricks_mount" "my_mount" { }` func TestAccCreateDatabricksMount(t *testing.T) { - workspaceLevel(t, - step{ + WorkspaceLevel(t, + Step{ Template: mountHcl, }) } @@ -48,9 +48,9 @@ func TestAccCreateDatabricksMountIsFineOnClusterRecreate(t *testing.T) { clusterId1 := "" clusterId2 := "" - workspaceLevel(t, + WorkspaceLevel(t, // Step 1 creates the cluster and mount. - step{ + Step{ Template: mountHcl, Check: func(s *terraform.State) error { resources := s.RootModule().Resources @@ -72,7 +72,7 @@ func TestAccCreateDatabricksMountIsFineOnClusterRecreate(t *testing.T) { }, // Step 2: Manually delete the cluster, and then reapply the config. The mount // will be recreated in this case. - step{ + Step{ PreConfig: func() { w, err := databricks.NewWorkspaceClient(&databricks.Config{}) require.NoError(t, err) diff --git a/internal/acceptance/mws_credentials_test.go b/internal/acceptance/mws_credentials_test.go index 3c57a957fb..7f2c82e1de 100644 --- a/internal/acceptance/mws_credentials_test.go +++ b/internal/acceptance/mws_credentials_test.go @@ -5,7 +5,7 @@ import ( ) func TestMwsAccCredentials(t *testing.T) { - accountLevel(t, step{ + AccountLevel(t, Step{ Template: `resource "databricks_mws_credentials" "this" { account_id = "{env.DATABRICKS_ACCOUNT_ID}" credentials_name = "creds-test-{var.RANDOM}" diff --git a/internal/acceptance/mws_customer_managed_keys_test.go b/internal/acceptance/mws_customer_managed_keys_test.go index e78f181b39..a1485d81ee 100644 --- a/internal/acceptance/mws_customer_managed_keys_test.go +++ b/internal/acceptance/mws_customer_managed_keys_test.go @@ -5,7 +5,7 @@ import ( ) func TestMwsAccAwsCustomerManagedKeys(t *testing.T) { - accountLevel(t, step{ + AccountLevel(t, Step{ Template: `resource "databricks_mws_customer_managed_keys" "this" { account_id = "{env.DATABRICKS_ACCOUNT_ID}" aws_key_info { @@ -18,7 +18,7 @@ func TestMwsAccAwsCustomerManagedKeys(t *testing.T) { } func TestMwsAccGcpCustomerManagedKeysForStorage(t *testing.T) { - accountLevel(t, step{ + AccountLevel(t, Step{ Template: `resource "databricks_mws_customer_managed_keys" "this" { account_id = "{env.DATABRICKS_ACCOUNT_ID}" gcp_key_info { diff --git a/internal/acceptance/mws_log_delivery_test.go b/internal/acceptance/mws_log_delivery_test.go index 943e739e4a..ac49aafc68 100644 --- a/internal/acceptance/mws_log_delivery_test.go +++ b/internal/acceptance/mws_log_delivery_test.go @@ -5,7 +5,7 @@ import ( ) func TestMwsAccLogDelivery(t *testing.T) { - accountLevel(t, step{ + AccountLevel(t, Step{ Template: `resource "databricks_mws_credentials" "ld" { account_id = "{env.DATABRICKS_ACCOUNT_ID}" credentials_name = "tf-acceptance-logdelivery-{var.RANDOM}" diff --git a/internal/acceptance/mws_network_connectivity_config_test.go b/internal/acceptance/mws_network_connectivity_config_test.go index 1e19e657fd..d7fbf5d8f8 100644 --- a/internal/acceptance/mws_network_connectivity_config_test.go +++ b/internal/acceptance/mws_network_connectivity_config_test.go @@ -6,7 +6,7 @@ import ( func TestMwsAccNetworkConnectivityConfig(t *testing.T) { if isAzure(t) { - accountLevel(t, step{ + AccountLevel(t, Step{ Template: ` resource "databricks_mws_network_connectivity_config" "this" { name = "tf-{var.RANDOM}" @@ -19,7 +19,7 @@ func TestMwsAccNetworkConnectivityConfig(t *testing.T) { group_id = "blob" } `, - }, step{ + }, Step{ Template: ` resource "databricks_mws_network_connectivity_config" "this" { name = "tf-{var.RANDOM}" @@ -35,7 +35,7 @@ func TestMwsAccNetworkConnectivityConfig(t *testing.T) { }) } if isAws(t) { - accountLevel(t, step{ + AccountLevel(t, Step{ Template: ` resource "databricks_mws_network_connectivity_config" "this" { account_id = "{env.DATABRICKS_ACCOUNT_ID}" @@ -43,7 +43,7 @@ func TestMwsAccNetworkConnectivityConfig(t *testing.T) { region = "{env.AWS_REGION}" } `, - }, step{ + }, Step{ Template: ` resource "databricks_mws_network_connectivity_config" "this" { account_id = "{env.DATABRICKS_ACCOUNT_ID}" diff --git a/internal/acceptance/mws_networks_test.go b/internal/acceptance/mws_networks_test.go index e2b1f49832..c28641a1fb 100644 --- a/internal/acceptance/mws_networks_test.go +++ b/internal/acceptance/mws_networks_test.go @@ -6,7 +6,7 @@ import ( func TestMwsAccNetworks(t *testing.T) { GetEnvOrSkipTest(t, "TEST_ROOT_BUCKET") // marker for AWS test env - accountLevel(t, step{ + AccountLevel(t, Step{ Template: ` resource "databricks_mws_networks" "my_network" { account_id = "{env.DATABRICKS_ACCOUNT_ID}" @@ -24,7 +24,7 @@ func TestMwsAccNetworks(t *testing.T) { } func TestMwsAccGcpPscNetworks(t *testing.T) { - accountLevel(t, step{ + AccountLevel(t, Step{ Template: ` resource "databricks_mws_networks" "my_network" { account_id = "{env.DATABRICKS_ACCOUNT_ID}" diff --git a/internal/acceptance/mws_permissionassignments_test.go b/internal/acceptance/mws_permissionassignments_test.go index e63fceaa35..a251b98560 100644 --- a/internal/acceptance/mws_permissionassignments_test.go +++ b/internal/acceptance/mws_permissionassignments_test.go @@ -5,7 +5,7 @@ import ( ) func TestUcAccAssignGroupToWorkspace(t *testing.T) { - unityAccountLevel(t, step{ + UnityAccountLevel(t, Step{ Template: ` resource "databricks_group" "this" { display_name = "TF {var.RANDOM}" @@ -15,7 +15,7 @@ func TestUcAccAssignGroupToWorkspace(t *testing.T) { principal_id = databricks_group.this.id permissions = ["USER"] }`, - }, step{ + }, Step{ Template: ` resource "databricks_group" "this" { display_name = "TF {var.RANDOM}" @@ -25,7 +25,7 @@ func TestUcAccAssignGroupToWorkspace(t *testing.T) { principal_id = databricks_group.this.id permissions = ["ADMIN"] }`, - }, step{ + }, Step{ Template: ` resource "databricks_group" "this" { display_name = "TF {var.RANDOM}" @@ -39,7 +39,7 @@ func TestUcAccAssignGroupToWorkspace(t *testing.T) { } func TestAccAssignSpnToWorkspace(t *testing.T) { - unityAccountLevel(t, step{ + UnityAccountLevel(t, Step{ Template: ` resource "databricks_service_principal" "this" { display_name = "TF {var.RANDOM}" diff --git a/internal/acceptance/mws_private_access_settings_test.go b/internal/acceptance/mws_private_access_settings_test.go index 62c97a30d6..7a4199d2ce 100644 --- a/internal/acceptance/mws_private_access_settings_test.go +++ b/internal/acceptance/mws_private_access_settings_test.go @@ -6,7 +6,7 @@ import ( func TestMwsAccPrivateAccessSettings(t *testing.T) { t.SkipNow() - accountLevel(t, step{ + AccountLevel(t, Step{ Template: ` resource "databricks_mws_private_access_settings" "this" { account_id = "{env.DATABRICKS_ACCOUNT_ID}" @@ -19,7 +19,7 @@ func TestMwsAccPrivateAccessSettings(t *testing.T) { func TestMwsGcpAccPrivateAccessSettings(t *testing.T) { t.Skipf("skipping until feature is disabled") - accountLevel(t, step{ + AccountLevel(t, Step{ Template: ` resource "databricks_mws_private_access_settings" "this" { account_id = "{env.DATABRICKS_ACCOUNT_ID}" diff --git a/internal/acceptance/mws_storage_configurations_test.go b/internal/acceptance/mws_storage_configurations_test.go index 400e2e0f61..800db474ba 100644 --- a/internal/acceptance/mws_storage_configurations_test.go +++ b/internal/acceptance/mws_storage_configurations_test.go @@ -6,7 +6,7 @@ import ( func TestMwsAccStorageConfigurations(t *testing.T) { GetEnvOrSkipTest(t, "TEST_ROOT_BUCKET") // marker for AWS test env - accountLevel(t, step{ + AccountLevel(t, Step{ Template: ` resource "databricks_mws_storage_configurations" "this" { account_id = "{env.DATABRICKS_ACCOUNT_ID}" diff --git a/internal/acceptance/mws_vpc_endpoint_test.go b/internal/acceptance/mws_vpc_endpoint_test.go index 4dedcd4bc2..59b7ef2d06 100644 --- a/internal/acceptance/mws_vpc_endpoint_test.go +++ b/internal/acceptance/mws_vpc_endpoint_test.go @@ -6,7 +6,7 @@ import ( func TestMwsAccVpcEndpoint(t *testing.T) { t.SkipNow() - accountLevel(t, step{ + AccountLevel(t, Step{ Template: ` resource "databricks_mws_vpc_endpoint" "this" { account_id = "{env.DATABRICKS_ACCOUNT_ID}" @@ -19,7 +19,7 @@ func TestMwsAccVpcEndpoint(t *testing.T) { } func TestMwsAccVpcEndpoint_GCP(t *testing.T) { - accountLevel(t, step{ + AccountLevel(t, Step{ Template: ` resource "databricks_mws_vpc_endpoint" "this" { account_id = "{env.DATABRICKS_ACCOUNT_ID}" diff --git a/internal/acceptance/mws_workspaces_test.go b/internal/acceptance/mws_workspaces_test.go index 4dddcd146c..07d5279874 100644 --- a/internal/acceptance/mws_workspaces_test.go +++ b/internal/acceptance/mws_workspaces_test.go @@ -22,7 +22,7 @@ import ( ) func TestMwsAccWorkspaces(t *testing.T) { - accountLevel(t, step{ + AccountLevel(t, Step{ Template: ` resource "databricks_mws_credentials" "this" { account_id = "{env.DATABRICKS_ACCOUNT_ID}" @@ -76,7 +76,7 @@ func TestMwsAccWorkspaces(t *testing.T) { } func TestMwsAccWorkspacesTokenUpdate(t *testing.T) { - accountLevel(t, step{ + AccountLevel(t, Step{ Template: ` resource "databricks_mws_credentials" "this" { account_id = "{env.DATABRICKS_ACCOUNT_ID}" @@ -136,7 +136,7 @@ func TestMwsAccWorkspacesTokenUpdate(t *testing.T) { return nil }), }, - step{ + Step{ Template: ` resource "databricks_mws_credentials" "this" { account_id = "{env.DATABRICKS_ACCOUNT_ID}" @@ -199,7 +199,7 @@ func TestMwsAccWorkspacesTokenUpdate(t *testing.T) { } func TestMwsAccGcpWorkspaces(t *testing.T) { - accountLevel(t, step{ + AccountLevel(t, Step{ Template: ` resource "databricks_mws_workspaces" "this" { account_id = "{env.DATABRICKS_ACCOUNT_ID}" @@ -218,7 +218,7 @@ func TestMwsAccGcpWorkspaces(t *testing.T) { func TestMwsAccGcpByovpcWorkspaces(t *testing.T) { t.Skip() // FIXME: flaky with `Secondary IP range (pods, svc) is already in use by another GKE cluster` - accountLevel(t, step{ + AccountLevel(t, Step{ Template: ` resource "databricks_mws_networks" "this" { account_id = "{env.DATABRICKS_ACCOUNT_ID}" @@ -255,7 +255,7 @@ func TestMwsAccGcpByovpcWorkspaces(t *testing.T) { } func TestMwsAccGcpPscWorkspaces(t *testing.T) { - accountLevel(t, step{ + AccountLevel(t, Step{ Template: ` resource "databricks_mws_networks" "this" { account_id = "{env.DATABRICKS_ACCOUNT_ID}" @@ -374,7 +374,7 @@ func TestMwsAccAwsChangeToServicePrincipal(t *testing.T) { return providers.GetProviderServer(context.Background(), providers.WithSdkV2Provider(pr)) }, } - accountLevel(t, step{ + AccountLevel(t, Step{ Template: workspaceTemplate(`token { comment = "Test {var.STICKY_RANDOM}" }`) + servicePrincipal, Check: func(s *terraform.State) error { spId := s.RootModule().Resources["databricks_service_principal.this"].Primary.ID @@ -412,20 +412,20 @@ func TestMwsAccAwsChangeToServicePrincipal(t *testing.T) { } return nil }, - }, step{ + }, Step{ // Tolerate existing token Template: workspaceTemplate(`token { comment = "Test {var.STICKY_RANDOM}" }`) + servicePrincipal, ProtoV6ProviderFactories: providerFactory, - }, step{ + }, Step{ // Allow the token to be removed Template: workspaceTemplate(``) + servicePrincipal, ProtoV6ProviderFactories: providerFactory, - }, step{ + }, Step{ // Fail when adding the token back Template: workspaceTemplate(`token { comment = "Test {var.STICKY_RANDOM}" }`) + servicePrincipal, ProtoV6ProviderFactories: providerFactory, ExpectError: regexp.MustCompile(`cannot create token: the principal used by Databricks \(client ID .*\) is not authorized to create a token in this workspace`), - }, step{ + }, Step{ // Use the original provider for a final step to clean up the newly created service principal Template: workspaceTemplate(``) + servicePrincipal, }) diff --git a/internal/acceptance/notebook_test.go b/internal/acceptance/notebook_test.go index dfe3f66286..9df1973ddf 100644 --- a/internal/acceptance/notebook_test.go +++ b/internal/acceptance/notebook_test.go @@ -5,12 +5,12 @@ import ( ) func TestAccNotebookResourceScalability(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: `resource "databricks_notebook" "this" { source = "{var.CWD}/../../storage/testdata/tf-test-python.py" path = "/Shared/provider-test/xx_{var.RANDOM}" }`, - }, step{ + }, Step{ Template: `resource "databricks_notebook" "this" { source = "{var.CWD}/../../storage/testdata/tf-test-python.py" path = "/Shared/provider-test/xx_{var.RANDOM}_renamed" diff --git a/internal/acceptance/notification_destination_test.go b/internal/acceptance/notification_destination_test.go index 309ed39d5e..78d0474e0c 100644 --- a/internal/acceptance/notification_destination_test.go +++ b/internal/acceptance/notification_destination_test.go @@ -33,7 +33,7 @@ func checkND(t *testing.T, display_name string, config_type settings.Destination func TestAccNDEmail(t *testing.T) { display_name := "Email Notification Destination - " + qa.RandomName() - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` resource "databricks_notification_destination" "this" { display_name = "` + display_name + `" @@ -44,7 +44,7 @@ func TestAccNDEmail(t *testing.T) { } } `, - }, step{ + }, Step{ Template: ` resource "databricks_notification_destination" "this" { display_name = "` + display_name + `" @@ -61,7 +61,7 @@ func TestAccNDEmail(t *testing.T) { func TestAccNDSlack(t *testing.T) { display_name := "Notification Destination - " + qa.RandomName() - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` resource "databricks_notification_destination" "this" { display_name = "` + display_name + `" @@ -73,7 +73,7 @@ func TestAccNDSlack(t *testing.T) { } `, Check: checkND(t, display_name, settings.DestinationTypeSlack), - }, step{ + }, Step{ Template: ` resource "databricks_notification_destination" "this" { display_name = "` + display_name + `" @@ -90,7 +90,7 @@ func TestAccNDSlack(t *testing.T) { func TestAccNDMicrosoftTeams(t *testing.T) { display_name := "Notification Destination - " + qa.RandomName() - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` resource "databricks_notification_destination" "this" { display_name = "` + display_name + `" @@ -101,7 +101,7 @@ func TestAccNDMicrosoftTeams(t *testing.T) { } } `, - }, step{ + }, Step{ Template: ` resource "databricks_notification_destination" "this" { display_name = "` + display_name + `" @@ -118,7 +118,7 @@ func TestAccNDMicrosoftTeams(t *testing.T) { func TestAccNDPagerduty(t *testing.T) { display_name := "Notification Destination - " + qa.RandomName() - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` resource "databricks_notification_destination" "this" { display_name = "` + display_name + `" @@ -129,7 +129,7 @@ func TestAccNDPagerduty(t *testing.T) { } } `, - }, step{ + }, Step{ Template: ` resource "databricks_notification_destination" "this" { display_name = "` + display_name + `" @@ -146,7 +146,7 @@ func TestAccNDPagerduty(t *testing.T) { func TestAccNDGenericWebhook(t *testing.T) { display_name := "Notification Destination - " + qa.RandomName() - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` resource "databricks_notification_destination" "this" { display_name = "` + display_name + `" @@ -158,7 +158,7 @@ func TestAccNDGenericWebhook(t *testing.T) { } } `, - }, step{ + }, Step{ Template: ` resource "databricks_notification_destination" "this" { display_name = "` + display_name + `" @@ -176,7 +176,7 @@ func TestAccNDGenericWebhook(t *testing.T) { func TestAccConfigTypeChange(t *testing.T) { display_name := "Notification Destination - " + qa.RandomName() - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` resource "databricks_notification_destination" "this" { display_name = "` + display_name + `" @@ -188,7 +188,7 @@ func TestAccConfigTypeChange(t *testing.T) { } `, Check: checkND(t, display_name, settings.DestinationTypeSlack), - }, step{ + }, Step{ Template: ` resource "databricks_notification_destination" "this" { display_name = "` + display_name + `" diff --git a/internal/acceptance/obo_token_test.go b/internal/acceptance/obo_token_test.go index 1ce50ff815..43374e8e38 100644 --- a/internal/acceptance/obo_token_test.go +++ b/internal/acceptance/obo_token_test.go @@ -7,7 +7,7 @@ import ( func TestAccAwsOboTokenResource(t *testing.T) { // running this test temporarily on the UC WS level // until infrastructure gets AWS specific markers - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` // dummy: {env.TEST_GLOBAL_METASTORE_ID} resource "databricks_service_principal" "this" { diff --git a/internal/acceptance/online_table_test.go b/internal/acceptance/online_table_test.go index b7d9aefc81..390a3e86ed 100644 --- a/internal/acceptance/online_table_test.go +++ b/internal/acceptance/online_table_test.go @@ -82,5 +82,5 @@ func TestUcAccOnlineTable(t *testing.T) { if os.Getenv("GOOGLE_CREDENTIALS") != "" { t.Skipf("databricks_online_table resource is not available on GCP") } - unityWorkspaceLevel(t, step{Template: onlineTableHcl}) + UnityWorkspaceLevel(t, Step{Template: onlineTableHcl}) } diff --git a/internal/acceptance/permissions_test.go b/internal/acceptance/permissions_test.go index 788340d606..5d803bd451 100644 --- a/internal/acceptance/permissions_test.go +++ b/internal/acceptance/permissions_test.go @@ -19,7 +19,7 @@ import ( func TestAccDatabricksPermissionsResourceFullLifecycle(t *testing.T) { randomName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: fmt.Sprintf(` resource "databricks_notebook" "this" { content_base64 = base64encode("# Databricks notebook source\nprint(1)") @@ -49,7 +49,7 @@ func TestAccDatabricksPermissionsResourceFullLifecycle(t *testing.T) { return nil }), ), - }, step{ + }, Step{ Template: fmt.Sprintf(` resource "databricks_notebook" "this" { content_base64 = base64encode("# Databricks notebook source\nprint(1)") @@ -87,7 +87,7 @@ func TestAccDatabricksPermissionsResourceFullLifecycle(t *testing.T) { func TestAccDatabricksReposPermissionsResourceFullLifecycle(t *testing.T) { randomName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: fmt.Sprintf(` resource "databricks_repo" "this" { url = "https://github.com/databrickslabs/tempo.git" @@ -199,8 +199,8 @@ func TestAccDatabricksPermissionsForSqlWarehouses(t *testing.T) { } }`, randomName) - workspaceLevel(t, - step{ + WorkspaceLevel(t, + Step{ Template: config1, Check: resource.ComposeTestCheckFunc( checkObjectType, @@ -211,7 +211,7 @@ func TestAccDatabricksPermissionsForSqlWarehouses(t *testing.T) { }, ), }, - step{ + Step{ Template: config2, Check: func(s *terraform.State) error { id := getPermissionId(s) diff --git a/internal/acceptance/pipeline_test.go b/internal/acceptance/pipeline_test.go index 7b78e2c23c..d56f651cac 100644 --- a/internal/acceptance/pipeline_test.go +++ b/internal/acceptance/pipeline_test.go @@ -50,7 +50,7 @@ var ( ) func TestAccPipelineResource_CreatePipeline(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` locals { name = "pipeline-acceptance-{var.RANDOM}" @@ -95,7 +95,7 @@ func TestAccPipelineResource_CreatePipeline(t *testing.T) { } func TestAccAwsPipelineResource_CreatePipeline(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` locals { name = "pipeline-acceptance-aws-{var.STICKY_RANDOM}" @@ -135,7 +135,7 @@ func TestAccAwsPipelineResource_CreatePipeline(t *testing.T) { continuous = false } ` + dltNotebookResource, - }, step{ + }, Step{ Template: ` locals { name = "pipeline-acceptance-aws-{var.STICKY_RANDOM}" @@ -179,7 +179,7 @@ func TestAccAwsPipelineResource_CreatePipeline(t *testing.T) { } func TestAccPipelineResource_CreatePipelineWithoutWorkers(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` locals { name = "pipeline-acceptance-{var.RANDOM}" @@ -232,7 +232,7 @@ func TestAccPipelineResource_CreatePipelineWithoutWorkers(t *testing.T) { func TestAccPipelineResourcLastModified(t *testing.T) { var lastModified int64 - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` locals { name = "pipeline-acceptance-{var.STICKY_RANDOM}" @@ -284,7 +284,7 @@ func TestAccPipelineResourcLastModified(t *testing.T) { lastModified = pipeline.LastModified return nil }), - }, step{ + }, Step{ Template: ` locals { name = "pipeline-acceptance-{var.STICKY_RANDOM}" diff --git a/internal/acceptance/provider_test.go b/internal/acceptance/provider_test.go index d794bf6c2c..1b735d4d41 100644 --- a/internal/acceptance/provider_test.go +++ b/internal/acceptance/provider_test.go @@ -5,7 +5,7 @@ import ( ) func TestUcAccCreateProviderDb2Open(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` resource "databricks_provider" "this" { name = "terraform-test-provider" diff --git a/internal/acceptance/quality_monitor_test.go b/internal/acceptance/quality_monitor_test.go index 8a65e9a1c9..d9e8a62c51 100644 --- a/internal/acceptance/quality_monitor_test.go +++ b/internal/acceptance/quality_monitor_test.go @@ -50,7 +50,7 @@ func TestUcAccQualityMonitor(t *testing.T) { if os.Getenv("GOOGLE_CREDENTIALS") != "" { t.Skipf("databricks_quality_monitor resource is not available on GCP") } - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: commonPartQualityMonitoring + ` resource "databricks_quality_monitor" "testMonitorInference" { @@ -117,7 +117,7 @@ func TestUcAccUpdateQualityMonitor(t *testing.T) { if os.Getenv("GOOGLE_CREDENTIALS") != "" { t.Skipf("databricks_quality_monitor resource is not available on GCP") } - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: commonPartQualityMonitoring + ` resource "databricks_quality_monitor" "testMonitorInference" { table_name = databricks_sql_table.myInferenceTable.id @@ -132,7 +132,7 @@ func TestUcAccUpdateQualityMonitor(t *testing.T) { } } `, - }, step{ + }, Step{ Template: commonPartQualityMonitoring + ` resource "databricks_quality_monitor" "testMonitorInference" { table_name = databricks_sql_table.myInferenceTable.id @@ -149,107 +149,3 @@ func TestUcAccUpdateQualityMonitor(t *testing.T) { `, }) } - -func TestUcAccQualityMonitorPluginFramework(t *testing.T) { - if os.Getenv("GOOGLE_CREDENTIALS") != "" { - t.Skipf("databricks_quality_monitor resource is not available on GCP") - } - unityWorkspaceLevel(t, step{ - Template: commonPartQualityMonitoring + ` - - resource "databricks_quality_monitor_pluginframework" "testMonitorInference" { - table_name = databricks_sql_table.myInferenceTable.id - assets_dir = "/Shared/provider-test/databricks_quality_monitoring/${databricks_sql_table.myInferenceTable.name}" - output_schema_name = databricks_schema.things.id - inference_log = { - granularities = ["1 day"] - timestamp_col = "timestamp" - prediction_col = "prediction" - model_id_col = "model_id" - problem_type = "PROBLEM_TYPE_REGRESSION" - } - } - - resource "databricks_sql_table" "myTimeseries" { - catalog_name = databricks_catalog.sandbox.id - schema_name = databricks_schema.things.name - name = "bar{var.STICKY_RANDOM}_timeseries" - table_type = "MANAGED" - data_source_format = "DELTA" - - column { - name = "timestamp" - type = "int" - } - } - - resource "databricks_quality_monitor_pluginframework" "testMonitorTimeseries" { - table_name = databricks_sql_table.myTimeseries.id - assets_dir = "/Shared/provider-test/databricks_quality_monitoring/${databricks_sql_table.myTimeseries.name}" - output_schema_name = databricks_schema.things.id - time_series = { - granularities = ["1 day"] - timestamp_col = "timestamp" - } - } - - resource "databricks_sql_table" "mySnapshot" { - catalog_name = databricks_catalog.sandbox.id - schema_name = databricks_schema.things.name - name = "bar{var.STICKY_RANDOM}_snapshot" - table_type = "MANAGED" - data_source_format = "DELTA" - - column { - name = "timestamp" - type = "int" - } - } - - resource "databricks_quality_monitor_pluginframework" "testMonitorSnapshot" { - table_name = databricks_sql_table.mySnapshot.id - assets_dir = "/Shared/provider-test/databricks_quality_monitoring/${databricks_sql_table.myTimeseries.name}" - output_schema_name = databricks_schema.things.id - snapshot = { - } - } - `, - }) -} - -func TestUcAccUpdateQualityMonitorPluginFramework(t *testing.T) { - if os.Getenv("GOOGLE_CREDENTIALS") != "" { - t.Skipf("databricks_quality_monitor resource is not available on GCP") - } - unityWorkspaceLevel(t, step{ - Template: commonPartQualityMonitoring + ` - resource "databricks_quality_monitor_pluginframework" "testMonitorInference" { - table_name = databricks_sql_table.myInferenceTable.id - assets_dir = "/Shared/provider-test/databricks_quality_monitoring/${databricks_sql_table.myInferenceTable.name}" - output_schema_name = databricks_schema.things.id - inference_log = { - granularities = ["1 day"] - timestamp_col = "timestamp" - prediction_col = "prediction" - model_id_col = "model_id" - problem_type = "PROBLEM_TYPE_REGRESSION" - } - } - `, - }, step{ - Template: commonPartQualityMonitoring + ` - resource "databricks_quality_monitor_pluginframework" "testMonitorInference" { - table_name = databricks_sql_table.myInferenceTable.id - assets_dir = "/Shared/provider-test/databricks_quality_monitoring/${databricks_sql_table.myInferenceTable.name}" - output_schema_name = databricks_schema.things.id - inference_log = { - granularities = ["1 hour"] - timestamp_col = "timestamp" - prediction_col = "prediction" - model_id_col = "model_id" - problem_type = "PROBLEM_TYPE_REGRESSION" - } - } - `, - }) -} diff --git a/internal/acceptance/recipient_test.go b/internal/acceptance/recipient_test.go index e59bf90d1c..8afa234eee 100644 --- a/internal/acceptance/recipient_test.go +++ b/internal/acceptance/recipient_test.go @@ -6,7 +6,7 @@ import ( ) func TestUcAccCreateRecipientDb2Open(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` resource "databricks_recipient" "db2open" { name = "{var.RANDOM}-terraform-db2open-recipient" @@ -22,7 +22,7 @@ func TestUcAccCreateRecipientDb2Open(t *testing.T) { } func TestUcAccCreateRecipientDb2DbAws(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` resource "databricks_metastore" "recipient_metastore" { name = "{var.RANDOM}-terraform-recipient-metastore" @@ -46,13 +46,13 @@ func TestUcAccCreateRecipientDb2DbAws(t *testing.T) { } func TestUcAccUpdateRecipientDb2Open(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: recipientTemplateWithOwner("made by terraform", "account users"), - }, step{ + }, Step{ Template: recipientTemplateWithOwner("made by terraform -- updated comment", "account users"), - }, step{ + }, Step{ Template: recipientTemplateWithOwner("made by terraform -- updated comment", "{env.TEST_DATA_ENG_GROUP}"), - }, step{ + }, Step{ Template: recipientTemplateWithOwner("made by terraform -- updated comment 2", "{env.TEST_METASTORE_ADMIN_GROUP_NAME}"), }) } diff --git a/internal/acceptance/registered_model_test.go b/internal/acceptance/registered_model_test.go index 9da0873aa2..f4293b3f98 100644 --- a/internal/acceptance/registered_model_test.go +++ b/internal/acceptance/registered_model_test.go @@ -5,8 +5,8 @@ import ( ) func TestUcAccRegisteredModel(t *testing.T) { - unityWorkspaceLevel(t, - step{ + UnityWorkspaceLevel(t, + Step{ Template: ` resource "databricks_registered_model" "model" { name = "terraform-test-registered-model-{var.STICKY_RANDOM}" @@ -24,7 +24,7 @@ func TestUcAccRegisteredModel(t *testing.T) { } `, }, - step{ + Step{ Template: ` resource "databricks_registered_model" "model" { name = "terraform-test-registered-model-{var.STICKY_RANDOM}" @@ -34,7 +34,7 @@ func TestUcAccRegisteredModel(t *testing.T) { } `, }, - step{ + Step{ Template: ` resource "databricks_registered_model" "model" { name = "terraform-test-registered-model-update-{var.STICKY_RANDOM}" diff --git a/internal/acceptance/restrict_workspace_admins_test.go b/internal/acceptance/restrict_workspace_admins_test.go index 3f6f7b4edd..fff187c66a 100644 --- a/internal/acceptance/restrict_workspace_admins_test.go +++ b/internal/acceptance/restrict_workspace_admins_test.go @@ -21,7 +21,7 @@ func TestAccRestrictWorkspaceAdminsSetting(t *testing.T) { } } ` - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: template, Check: resourceCheckWithState("databricks_restrict_workspace_admins_setting.this", func(ctx context.Context, client *common.DatabricksClient, state *terraform.InstanceState) error { @@ -39,7 +39,7 @@ func TestAccRestrictWorkspaceAdminsSetting(t *testing.T) { return nil }), }, - step{ + Step{ Template: template, Destroy: true, Check: resourceCheck("databricks_restrict_workspace_admins_setting.this", diff --git a/internal/acceptance/schema_test.go b/internal/acceptance/schema_test.go index eb4d59374c..e257597237 100644 --- a/internal/acceptance/schema_test.go +++ b/internal/acceptance/schema_test.go @@ -16,7 +16,7 @@ const catalogTemplate = ` ` func TestUcAccSchema(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: catalogTemplate + ` data "databricks_catalogs" "all" { depends_on = [databricks_catalog.sandbox] @@ -102,13 +102,13 @@ func getPredictiveOptimizationSetting(t *testing.T, enabled bool) string { func TestUcAccSchemaUpdate(t *testing.T) { loadUcwsEnv(t) - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: catalogTemplate + schemaTemplateWithOwner(t, "this database is managed by terraform", "account users"), - }, step{ + }, Step{ Template: catalogTemplate + schemaTemplateWithOwner(t, "this database is managed by terraform -- updated comment", "account users"), - }, step{ + }, Step{ Template: catalogTemplate + schemaTemplateWithOwner(t, "this database is managed by terraform -- updated comment", "{env.TEST_DATA_ENG_GROUP}"), - }, step{ + }, Step{ Template: catalogTemplate + schemaTemplateWithOwner(t, "this database is managed by terraform -- updated comment 2", "{env.TEST_METASTORE_ADMIN_GROUP_NAME}"), }) } diff --git a/internal/acceptance/secret_acl_test.go b/internal/acceptance/secret_acl_test.go index cec49c6c95..9ba29433bc 100644 --- a/internal/acceptance/secret_acl_test.go +++ b/internal/acceptance/secret_acl_test.go @@ -13,7 +13,7 @@ import ( ) func TestAccSecretAclResource(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` resource "databricks_group" "ds" { display_name = "data-scientists-{var.RANDOM}" @@ -52,7 +52,7 @@ func TestAccSecretAclResource(t *testing.T) { } func TestAccSecretAclResourceDefaultPrincipal(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` resource "databricks_secret_scope" "app" { name = "app-{var.RANDOM}" diff --git a/internal/acceptance/secret_scope_test.go b/internal/acceptance/secret_scope_test.go index f743317822..fe3c11eb74 100644 --- a/internal/acceptance/secret_scope_test.go +++ b/internal/acceptance/secret_scope_test.go @@ -18,7 +18,7 @@ import ( func TestAccSecretScopeResource(t *testing.T) { scope := qa.RandomName("tf-") - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: fmt.Sprintf(` resource "databricks_secret_scope" "my_scope" { name = "%s" @@ -45,7 +45,7 @@ func TestAccSecretScopeResource(t *testing.T) { }), ), ExpectNonEmptyPlan: true, - }, step{ + }, Step{ Template: fmt.Sprintf(` resource "databricks_secret_scope" "my_scope" { name = "%s" @@ -63,7 +63,7 @@ func TestAccSecretScopeResourceAkvWithSp(t *testing.T) { t.Skipf("service principal isn't defined") } - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` resource "databricks_secret_scope" "my_scope" { name = "tf-{var.RANDOM}" diff --git a/internal/acceptance/secret_test.go b/internal/acceptance/secret_test.go index c77874568e..7daca20a61 100644 --- a/internal/acceptance/secret_test.go +++ b/internal/acceptance/secret_test.go @@ -5,7 +5,7 @@ import ( ) func TestAccSecretResource(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` resource "databricks_secret_scope" "this" { name = "tf-scope-{var.RANDOM}" diff --git a/internal/acceptance/service_principal_test.go b/internal/acceptance/service_principal_test.go index b1acad6b95..d1b75198e8 100644 --- a/internal/acceptance/service_principal_test.go +++ b/internal/acceptance/service_principal_test.go @@ -33,13 +33,13 @@ func TestAccServicePrincipalHomeDeleteSuccess(t *testing.T) { force_delete_home_dir = true }` var spId string - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: template, Check: func(s *terraform.State) error { spId = s.RootModule().Resources["databricks_service_principal.a"].Primary.Attributes["application_id"] return nil }, - }, step{ + }, Step{ Template: template, Destroy: true, Check: func(s *terraform.State) error { @@ -69,13 +69,13 @@ func TestAccServicePrinicpalHomeDeleteNotDeleted(t *testing.T) { force_delete_home_dir = false }` var appId string - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: template, Check: func(s *terraform.State) error { appId = s.RootModule().Resources["databricks_service_principal.a"].Primary.Attributes["application_id"] return provisionHomeFolder(context.Background(), s, "databricks_service_principal.a", appId) }, - }, step{ + }, Step{ Template: template, Destroy: true, Check: func(s *terraform.State) error { @@ -93,9 +93,9 @@ func TestAccServicePrinicpalHomeDeleteNotDeleted(t *testing.T) { func TestMwsAccServicePrincipalResourceOnAzure(t *testing.T) { GetEnvOrSkipTest(t, "ARM_CLIENT_ID") azureSpnRenamed := strings.ReplaceAll(azureSpn, `"SPN `, `"SPN Renamed `) - accountLevel(t, step{ + AccountLevel(t, Step{ Template: azureSpn, - }, step{ + }, Step{ Template: azureSpnRenamed, }) } @@ -103,9 +103,9 @@ func TestMwsAccServicePrincipalResourceOnAzure(t *testing.T) { func TestAccServicePrincipalResourceOnAzure(t *testing.T) { GetEnvOrSkipTest(t, "ARM_CLIENT_ID") azureSpnRenamed := strings.ReplaceAll(azureSpn, `"SPN `, `"SPN Renamed `) - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: azureSpn, - }, step{ + }, Step{ Template: azureSpnRenamed, }) } @@ -113,9 +113,9 @@ func TestAccServicePrincipalResourceOnAzure(t *testing.T) { func TestMwsAccServicePrincipalResourceOnAws(t *testing.T) { GetEnvOrSkipTest(t, "TEST_ROOT_BUCKET") awsSpnRenamed := strings.ReplaceAll(awsSpn, `"SPN `, `"SPN Renamed `) - accountLevel(t, step{ + AccountLevel(t, Step{ Template: awsSpn, - }, step{ + }, Step{ Template: awsSpnRenamed, }) } @@ -123,9 +123,9 @@ func TestMwsAccServicePrincipalResourceOnAws(t *testing.T) { func TestAccServicePrincipalResourceOnAws(t *testing.T) { GetEnvOrSkipTest(t, "TEST_EC2_INSTANCE_PROFILE") awsSpnRenamed := strings.ReplaceAll(awsSpn, `"SPN `, `"SPN Renamed `) - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: awsSpn, - }, step{ + }, Step{ Template: awsSpnRenamed, }) } diff --git a/internal/acceptance/share_test.go b/internal/acceptance/share_test.go index afc3667ca4..b4a4034667 100644 --- a/internal/acceptance/share_test.go +++ b/internal/acceptance/share_test.go @@ -71,7 +71,7 @@ const preTestTemplateUpdate = ` ` func TestUcAccCreateShare(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: preTestTemplate + ` resource "databricks_share" "myshare" { name = "{var.STICKY_RANDOM}-terraform-delta-share" @@ -125,13 +125,13 @@ func shareTemplateWithOwner(comment string, owner string) string { } func TestUcAccUpdateShare(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: preTestTemplate + preTestTemplateUpdate + shareTemplateWithOwner("c", "account users"), - }, step{ + }, Step{ Template: preTestTemplate + preTestTemplateUpdate + shareTemplateWithOwner("e", "account users"), - }, step{ + }, Step{ Template: preTestTemplate + preTestTemplateUpdate + shareTemplateWithOwner("e", "{env.TEST_DATA_ENG_GROUP}"), - }, step{ + }, Step{ Template: preTestTemplate + preTestTemplateUpdate + shareTemplateWithOwner("f", "{env.TEST_METASTORE_ADMIN_GROUP_NAME}"), }) } diff --git a/internal/acceptance/sql_alert_test.go b/internal/acceptance/sql_alert_test.go index 5bf58752a3..612df0653e 100644 --- a/internal/acceptance/sql_alert_test.go +++ b/internal/acceptance/sql_alert_test.go @@ -5,7 +5,7 @@ import ( ) func TestAccAlert(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` resource "databricks_sql_query" "this" { data_source_id = "{env.TEST_DEFAULT_WAREHOUSE_DATASOURCE_ID}" @@ -31,7 +31,7 @@ func TestAccAlert(t *testing.T) { muted = false } }`, - }, step{ + }, Step{ Template: ` resource "databricks_sql_query" "this" { data_source_id = "{env.TEST_DEFAULT_WAREHOUSE_DATASOURCE_ID}" diff --git a/internal/acceptance/sql_dashboard_test.go b/internal/acceptance/sql_dashboard_test.go index c3ddf5f492..5c69b8331b 100644 --- a/internal/acceptance/sql_dashboard_test.go +++ b/internal/acceptance/sql_dashboard_test.go @@ -5,7 +5,7 @@ import ( ) func TestAccDashboard(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` resource "databricks_sql_dashboard" "d1" { name = "tf-{var.RANDOM}-dashboard" diff --git a/internal/acceptance/sql_endpoint_test.go b/internal/acceptance/sql_endpoint_test.go index 53496e8f2b..53d678c2ed 100644 --- a/internal/acceptance/sql_endpoint_test.go +++ b/internal/acceptance/sql_endpoint_test.go @@ -11,7 +11,7 @@ import ( ) func TestAccSQLEndpoint(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` resource "databricks_sql_endpoint" "this" { name = "tf-{var.RANDOM}" @@ -25,7 +25,7 @@ func TestAccSQLEndpoint(t *testing.T) { } } }`, - }, step{ + }, Step{ Template: ` resource "databricks_sql_endpoint" "that" { name = "tf-{var.RANDOM}" diff --git a/internal/acceptance/sql_global_config_test.go b/internal/acceptance/sql_global_config_test.go index 6bea052860..03c67e356e 100644 --- a/internal/acceptance/sql_global_config_test.go +++ b/internal/acceptance/sql_global_config_test.go @@ -38,7 +38,7 @@ resource "databricks_sql_global_config" "this" { func TestAccSQLGlobalConfig(t *testing.T) { loadWorkspaceEnv(t) - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ PreConfig: func() { ctx := context.Background() _, err := lock.Acquire(ctx, getSqlGlobalConfigLockable(t), lock.InTest(t)) @@ -64,7 +64,7 @@ func TestAccSQLGlobalConfigServerless(t *testing.T) { } } - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ PreConfig: func() { ctx := context.Background() _, err := lock.Acquire(ctx, getSqlGlobalConfigLockable(t), lock.InTest(t)) @@ -72,10 +72,10 @@ func TestAccSQLGlobalConfigServerless(t *testing.T) { }, Template: makeSqlGlobalConfig("enable_serverless_compute = true"), Check: checkServerlessEnabled(true), - }, step{ + }, Step{ Template: makeSqlGlobalConfig(""), Check: checkServerlessEnabled(true), - }, step{ + }, Step{ Template: makeSqlGlobalConfig("enable_serverless_compute = false"), Check: checkServerlessEnabled(false), }) diff --git a/internal/acceptance/sql_permissions_test.go b/internal/acceptance/sql_permissions_test.go index 057e537516..23aa37a51f 100644 --- a/internal/acceptance/sql_permissions_test.go +++ b/internal/acceptance/sql_permissions_test.go @@ -36,7 +36,7 @@ func TestAccTableACL(t *testing.T) { require.NoError(t, err) require.False(t, cr.Failed(), cr.Error()) }) - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` resource "databricks_sql_permissions" "this" { table = "` + tableName + `" diff --git a/internal/acceptance/sql_query_test.go b/internal/acceptance/sql_query_test.go index b106593c32..bc49c9ee6f 100644 --- a/internal/acceptance/sql_query_test.go +++ b/internal/acceptance/sql_query_test.go @@ -5,7 +5,7 @@ import ( ) func TestAccQuery(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` resource "databricks_sql_query" "q1" { data_source_id = "{env.TEST_DEFAULT_WAREHOUSE_DATASOURCE_ID}" diff --git a/internal/acceptance/sql_table_test.go b/internal/acceptance/sql_table_test.go index e6c1cc918f..0f0a87dec9 100644 --- a/internal/acceptance/sql_table_test.go +++ b/internal/acceptance/sql_table_test.go @@ -14,7 +14,7 @@ func TestUcAccResourceSqlTable_Managed(t *testing.T) { if os.Getenv("GOOGLE_CREDENTIALS") != "" { skipf(t)("databricks_sql_table resource not available on GCP") } - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` resource "databricks_schema" "this" { name = "{var.STICKY_RANDOM}" @@ -42,7 +42,7 @@ func TestUcAccResourceSqlTable_Managed(t *testing.T) { comment = "this table is managed by terraform" owner = "account users" }`, - }, step{ + }, Step{ Template: ` resource "databricks_schema" "this" { name = "{var.STICKY_RANDOM}" @@ -73,7 +73,7 @@ func TestUcAccResourceSqlTable_Managed(t *testing.T) { } func TestUcAccResourceSqlTable_External(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` resource "databricks_storage_credential" "external" { name = "cred-{var.RANDOM}" @@ -113,7 +113,7 @@ func TestUcAccResourceSqlTable_View(t *testing.T) { if os.Getenv("GOOGLE_CREDENTIALS") != "" { skipf(t)("databricks_sql_table resource not available on GCP") } - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` resource "databricks_schema" "this" { name = "{var.STICKY_RANDOM}" @@ -164,7 +164,7 @@ func TestUcAccResourceSqlTable_WarehousePartition(t *testing.T) { if os.Getenv("GOOGLE_CREDENTIALS") != "" { skipf(t)("databricks_sql_table resource not available on GCP") } - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` resource "databricks_sql_endpoint" "this" { name = "tf-{var.RANDOM}" @@ -215,7 +215,7 @@ func TestUcAccResourceSqlTable_Liquid(t *testing.T) { if os.Getenv("GOOGLE_CREDENTIALS") != "" { skipf(t)("databricks_sql_table resource not available on GCP") } - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` resource "databricks_schema" "this" { name = "{var.STICKY_RANDOM}" @@ -246,7 +246,7 @@ func TestUcAccResourceSqlTable_Liquid(t *testing.T) { cluster_keys = ["id"] comment = "this table is managed by terraform" }`, - }, step{ + }, Step{ Template: ` resource "databricks_schema" "this" { name = "{var.STICKY_RANDOM}" @@ -320,9 +320,9 @@ func TestUcAccResourceSqlTable_RenameColumn(t *testing.T) { skipf(t)("databricks_sql_table resource not available on GCP") } tableName := RandomName() - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: constructManagedSqlTableTemplate(tableName, []catalog.SqlColumnInfo{{Name: "name", Type: "string", Nullable: true, Comment: "comment"}}), - }, step{ + }, Step{ Template: constructManagedSqlTableTemplate(tableName, []catalog.SqlColumnInfo{{Name: "new_name", Type: "string", Nullable: true, Comment: "comment"}}), }) } @@ -346,7 +346,7 @@ func TestUcAccResourceSqlTable_ColumnTypeSuppressDiff(t *testing.T) { } tableName := RandomName() columnName := RandomName() - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: constructManagedSqlTableTemplateWithColumnTypeUpdates(tableName, columnName, "0", []string{ "integer", "long", @@ -357,7 +357,7 @@ func TestUcAccResourceSqlTable_ColumnTypeSuppressDiff(t *testing.T) { "dec", "numeric", }), - }, step{ + }, Step{ Template: constructManagedSqlTableTemplateWithColumnTypeUpdates(tableName, columnName, "1", []string{ "INTEGER", "LONG", @@ -368,7 +368,7 @@ func TestUcAccResourceSqlTable_ColumnTypeSuppressDiff(t *testing.T) { "DEC", "NUMERIC", }), - }, step{ + }, Step{ Template: constructManagedSqlTableTemplateWithColumnTypeUpdates(tableName, columnName, "2", []string{ "int", "bigint", @@ -387,9 +387,9 @@ func TestUcAccResourceSqlTable_AddColumnComment(t *testing.T) { skipf(t)("databricks_sql_table resource not available on GCP") } tableName := RandomName() - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: constructManagedSqlTableTemplate(tableName, []catalog.SqlColumnInfo{{Name: "name", Type: "string", Nullable: true, Comment: "comment"}}), - }, step{ + }, Step{ Template: constructManagedSqlTableTemplate(tableName, []catalog.SqlColumnInfo{{Name: "name", Type: "string", Nullable: true, Comment: "new comment"}}), }) } @@ -399,9 +399,9 @@ func TestUcAccResourceSqlTable_DropColumnNullable(t *testing.T) { skipf(t)("databricks_sql_table resource not available on GCP") } tableName := RandomName() - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: constructManagedSqlTableTemplate(tableName, []catalog.SqlColumnInfo{{Name: "name", Type: "string", Nullable: true, Comment: "comment"}}), - }, step{ + }, Step{ Template: constructManagedSqlTableTemplate(tableName, []catalog.SqlColumnInfo{{Name: "name", Type: "string", Nullable: false, Comment: "comment"}}), }) } @@ -411,9 +411,9 @@ func TestUcAccResourceSqlTable_MultipleColumnUpdates(t *testing.T) { skipf(t)("databricks_sql_table resource not available on GCP") } tableName := RandomName() - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: constructManagedSqlTableTemplate(tableName, []catalog.SqlColumnInfo{{Name: "name", Type: "string", Nullable: true, Comment: "comment"}}), - }, step{ + }, Step{ Template: constructManagedSqlTableTemplate(tableName, []catalog.SqlColumnInfo{{Name: "name", Type: "string", Nullable: false, Comment: "new comment"}}), }) } @@ -424,9 +424,9 @@ func TestUcAccResourceSqlTable_ChangeColumnTypeThrows(t *testing.T) { } tableName := RandomName() - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: constructManagedSqlTableTemplate(tableName, []catalog.SqlColumnInfo{{Name: "name", Type: "string", Nullable: true, Comment: "comment"}}), - }, step{ + }, Step{ Template: constructManagedSqlTableTemplate(tableName, []catalog.SqlColumnInfo{{Name: "name", Type: "int", Nullable: true, Comment: "comment"}}), ExpectError: typeUpdateErrorRegex, }) @@ -437,12 +437,12 @@ func TestUcAccResourceSqlTable_DropColumn(t *testing.T) { skipf(t)("databricks_sql_table resource not available on GCP") } tableName := RandomName() - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: constructManagedSqlTableTemplate(tableName, []catalog.SqlColumnInfo{ {Name: "name", Type: "string", Nullable: true, Comment: "comment"}, {Name: "nametwo", Type: "string", Nullable: true, Comment: "comment"}, }), - }, step{ + }, Step{ Template: constructManagedSqlTableTemplate(tableName, []catalog.SqlColumnInfo{{Name: "name", Type: "string", Nullable: true, Comment: "comment"}}), }) } @@ -452,13 +452,13 @@ func TestUcAccResourceSqlTable_DropMultipleColumns(t *testing.T) { skipf(t)("databricks_sql_table resource not available on GCP") } tableName := RandomName() - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: constructManagedSqlTableTemplate(tableName, []catalog.SqlColumnInfo{ {Name: "name", Type: "string", Nullable: true, Comment: "comment"}, {Name: "nametwo", Type: "string", Nullable: true, Comment: "comment"}, {Name: "namethree", Type: "string", Nullable: true, Comment: "comment"}, }), - }, step{ + }, Step{ Template: constructManagedSqlTableTemplate(tableName, []catalog.SqlColumnInfo{{Name: "name", Type: "string", Nullable: true, Comment: "comment"}}), }) } @@ -468,9 +468,9 @@ func TestUcAccResourceSqlTable_AddColumn(t *testing.T) { skipf(t)("databricks_sql_table resource not available on GCP") } tableName := RandomName() - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: constructManagedSqlTableTemplate(tableName, []catalog.SqlColumnInfo{{Name: "name", Type: "string", Nullable: true, Comment: "comment"}}), - }, step{ + }, Step{ Template: constructManagedSqlTableTemplate(tableName, []catalog.SqlColumnInfo{ {Name: "name", Type: "string", Nullable: true, Comment: "comment"}, {Name: "nametwo", Type: "string", Nullable: true, Comment: "comment"}, @@ -483,9 +483,9 @@ func TestUcAccResourceSqlTable_AddMultipleColumns(t *testing.T) { skipf(t)("databricks_sql_table resource not available on GCP") } tableName := RandomName() - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: constructManagedSqlTableTemplate(tableName, []catalog.SqlColumnInfo{{Name: "name", Type: "string", Nullable: true, Comment: "comment"}}), - }, step{ + }, Step{ Template: constructManagedSqlTableTemplate(tableName, []catalog.SqlColumnInfo{ {Name: "name", Type: "string", Nullable: true, Comment: "comment"}, {Name: "nametwo", Type: "string", Nullable: true, Comment: "comment"}, @@ -500,9 +500,9 @@ func TestUcAccResourceSqlTable_AddColumnAndUpdateThrows(t *testing.T) { } tableName := RandomName() - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: constructManagedSqlTableTemplate(tableName, []catalog.SqlColumnInfo{{Name: "name", Type: "string", Nullable: true, Comment: "comment"}}), - }, step{ + }, Step{ Template: constructManagedSqlTableTemplate(tableName, []catalog.SqlColumnInfo{ {Name: "name", Type: "string", Nullable: false, Comment: "new comment"}, {Name: "nametwo", Type: "string", Nullable: true, Comment: "comment"}, @@ -517,12 +517,12 @@ func TestUcAccResourceSqlTable_DropColumnAndUpdateThrows(t *testing.T) { } tableName := RandomName() - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: constructManagedSqlTableTemplate(tableName, []catalog.SqlColumnInfo{ {Name: "name", Type: "string", Nullable: true, Comment: "comment"}, {Name: "nametwo", Type: "string", Nullable: true, Comment: "comment"}, }), - }, step{ + }, Step{ Template: constructManagedSqlTableTemplate(tableName, []catalog.SqlColumnInfo{{Name: "name", Type: "string", Nullable: false, Comment: "new comment"}}), ExpectError: inlineAndMembershipChangeErrorRegex, }) diff --git a/internal/acceptance/storage_credential_test.go b/internal/acceptance/storage_credential_test.go index 92b5ff5871..c78598f729 100644 --- a/internal/acceptance/storage_credential_test.go +++ b/internal/acceptance/storage_credential_test.go @@ -7,7 +7,7 @@ import ( func TestUcAccStorageCredential(t *testing.T) { loadUcwsEnv(t) if isAws(t) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` resource "databricks_storage_credential" "external" { name = "cred-{var.RANDOM}" @@ -29,7 +29,7 @@ func TestUcAccStorageCredential(t *testing.T) { }`, }) } else if isGcp(t) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` resource "databricks_storage_credential" "external" { name = "cred-{var.RANDOM}" @@ -42,7 +42,7 @@ func TestUcAccStorageCredential(t *testing.T) { } func TestAccStorageCredentialOwner(t *testing.T) { - unityAccountLevel(t, step{ + UnityAccountLevel(t, Step{ Template: ` resource "databricks_service_principal" "test_acc_storage_credential_owner" { display_name = "test_acc_storage_credential_owner {var.RANDOM}" diff --git a/internal/acceptance/system_schema_test.go b/internal/acceptance/system_schema_test.go index ceef68e502..89474a6853 100644 --- a/internal/acceptance/system_schema_test.go +++ b/internal/acceptance/system_schema_test.go @@ -9,7 +9,7 @@ func TestUcAccResourceSystemSchema(t *testing.T) { if os.Getenv("GOOGLE_CREDENTIALS") != "" { t.Skipf("databricks_system_schema resource not available on GCP") } - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: ` resource "databricks_system_schema" "this" { schema = "access" diff --git a/internal/acceptance/token_test.go b/internal/acceptance/token_test.go index 0a594aecc2..2673400caf 100644 --- a/internal/acceptance/token_test.go +++ b/internal/acceptance/token_test.go @@ -5,7 +5,7 @@ import ( ) func TestAccTokenResource(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: `resource "databricks_token" "this" { lifetime_seconds = 6000 comment = "Testing token" diff --git a/internal/acceptance/user_role_test.go b/internal/acceptance/user_role_test.go index 9828b1c050..9e10cd72b3 100644 --- a/internal/acceptance/user_role_test.go +++ b/internal/acceptance/user_role_test.go @@ -5,7 +5,7 @@ import ( ) func TestAccUserRole(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: ` resource "databricks_user" "this" { user_name = "{var.RANDOM}@example.com" diff --git a/internal/acceptance/user_test.go b/internal/acceptance/user_test.go index 9368bb88bf..07e74f1ad7 100644 --- a/internal/acceptance/user_test.go +++ b/internal/acceptance/user_test.go @@ -20,7 +20,7 @@ import ( // https://github.com/databricks/terraform-provider-databricks/issues/1097 func TestAccForceUserImport(t *testing.T) { username := qa.RandomEmail() - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: `data "databricks_current_user" "me" {}`, Check: func(s *terraform.State) error { w, err := databricks.NewWorkspaceClient() @@ -40,7 +40,7 @@ func TestAccForceUserImport(t *testing.T) { } return nil }, - }, step{ + }, Step{ Template: `resource "databricks_user" "this" { user_name = "` + username + `" force = true @@ -50,13 +50,13 @@ func TestAccForceUserImport(t *testing.T) { func TestAccUserHomeDeleteHasNoEffectInAccount(t *testing.T) { username := qa.RandomEmail() - accountLevel(t, step{ + AccountLevel(t, Step{ Template: ` resource "databricks_user" "first" { user_name = "` + username + `" force_delete_home_dir = true }`, - }, step{ + }, Step{ Template: ` resource "databricks_user" "second" { user_name = "{var.RANDOM}@example.com" @@ -71,9 +71,9 @@ func TestAccUserHomeDelete(t *testing.T) { user_name = "` + username + `" force_delete_home_dir = true }` - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: template, - }, step{ + }, Step{ Template: template, Destroy: true, Check: func(s *terraform.State) error { @@ -115,12 +115,12 @@ func TestAccUserHomeDeleteNotDeleted(t *testing.T) { resource "databricks_user" "a" { user_name = "` + username + `" }` - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: template, Check: func(s *terraform.State) error { return provisionHomeFolder(context.Background(), s, "databricks_user.a", username) }, - }, step{ + }, Step{ Template: template, Destroy: true, Check: func(s *terraform.State) error { @@ -154,7 +154,7 @@ func TestAccUserResource(t *testing.T) { allow_instance_pool_create = true } ` - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: differentUsers, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("databricks_user.first", "allow_cluster_create", "false"), @@ -164,7 +164,7 @@ func TestAccUserResource(t *testing.T) { resource.TestCheckResourceAttr("databricks_user.third", "allow_cluster_create", "false"), resource.TestCheckResourceAttr("databricks_user.third", "allow_instance_pool_create", "true"), ), - }, step{ + }, Step{ Template: differentUsers, }) } @@ -174,12 +174,12 @@ func TestAccUserResourceCaseInsensitive(t *testing.T) { csUser := `resource "databricks_user" "first" { user_name = "` + username + `" }` - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: csUser, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("databricks_user.first", "user_name", strings.ToLower(username)), ), - }, step{ + }, Step{ Template: csUser, }) } diff --git a/internal/acceptance/vector_search_test.go b/internal/acceptance/vector_search_test.go index 084891c5d0..2442d0fa05 100644 --- a/internal/acceptance/vector_search_test.go +++ b/internal/acceptance/vector_search_test.go @@ -15,7 +15,7 @@ func TestUcAccVectorSearchEndpoint(t *testing.T) { name := fmt.Sprintf("terraform-test-vector-search-%[1]s", acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)) - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: fmt.Sprintf(` resource "databricks_vector_search_endpoint" "this" { name = "%s" diff --git a/internal/acceptance/volume_test.go b/internal/acceptance/volume_test.go index 8ffa282358..4b6380460b 100644 --- a/internal/acceptance/volume_test.go +++ b/internal/acceptance/volume_test.go @@ -26,7 +26,7 @@ resource "databricks_external_location" "some" { }` func TestUcAccVolumesResourceWithoutInitialOwnerAWSFullLifecycle(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: prefixTestTemplate + ` resource "databricks_volume" "this" { name = "name-abc" @@ -36,7 +36,7 @@ func TestUcAccVolumesResourceWithoutInitialOwnerAWSFullLifecycle(t *testing.T) { volume_type = "EXTERNAL" storage_location = databricks_external_location.some.url }`, - }, step{ + }, Step{ Template: prefixTestTemplate + ` resource "databricks_volume" "this" { name = "name-abc" @@ -46,7 +46,7 @@ func TestUcAccVolumesResourceWithoutInitialOwnerAWSFullLifecycle(t *testing.T) { volume_type = "EXTERNAL" storage_location = databricks_external_location.some.url }`, - }, step{ + }, Step{ Template: prefixTestTemplate + ` resource "databricks_volume" "this" { name = "name-abc" @@ -57,7 +57,7 @@ func TestUcAccVolumesResourceWithoutInitialOwnerAWSFullLifecycle(t *testing.T) { volume_type = "EXTERNAL" storage_location = databricks_external_location.some.url }`, - }, step{ + }, Step{ Template: prefixTestTemplate + ` resource "databricks_volume" "this" { name = "name-def" @@ -72,7 +72,7 @@ func TestUcAccVolumesResourceWithoutInitialOwnerAWSFullLifecycle(t *testing.T) { } func TestUcAccVolumesResourceWithInitialOwnerAWSFullLifecycle(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: prefixTestTemplate + ` resource "databricks_volume" "this" { name = "name-abc" @@ -83,7 +83,7 @@ func TestUcAccVolumesResourceWithInitialOwnerAWSFullLifecycle(t *testing.T) { volume_type = "EXTERNAL" storage_location = databricks_external_location.some.url }`, - }, step{ + }, Step{ Template: prefixTestTemplate + ` resource "databricks_volume" "this" { name = "name-abc" @@ -94,7 +94,7 @@ func TestUcAccVolumesResourceWithInitialOwnerAWSFullLifecycle(t *testing.T) { volume_type = "EXTERNAL" storage_location = databricks_external_location.some.url }`, - }, step{ + }, Step{ Template: prefixTestTemplate + ` resource "databricks_volume" "this" { name = "name-def" diff --git a/internal/acceptance/workspace_binding_test.go b/internal/acceptance/workspace_binding_test.go index 24fcd5bb01..f55f4ebd72 100644 --- a/internal/acceptance/workspace_binding_test.go +++ b/internal/acceptance/workspace_binding_test.go @@ -65,7 +65,7 @@ func workspaceBindingTemplateWithWorkspaceId(workspaceId string) string { } func TestUcAccWorkspaceBindingToOtherWorkspace(t *testing.T) { - unityWorkspaceLevel(t, step{ + UnityWorkspaceLevel(t, Step{ Template: workspaceBindingTemplateWithWorkspaceId("{env.DUMMY_WORKSPACE_ID}"), }) } diff --git a/internal/acceptance/workspace_conf_test.go b/internal/acceptance/workspace_conf_test.go index 5e91bcb285..f0468ea6b2 100644 --- a/internal/acceptance/workspace_conf_test.go +++ b/internal/acceptance/workspace_conf_test.go @@ -24,7 +24,7 @@ func assertEnableIpAccessList(t *testing.T, expected string) { } func TestAccWorkspaceConfFullLifecycle(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: `resource "databricks_workspace_conf" "this" { custom_config = { "enableIpAccessLists": true @@ -34,7 +34,7 @@ func TestAccWorkspaceConfFullLifecycle(t *testing.T) { assertEnableIpAccessList(t, "true") return nil }, - }, step{ + }, Step{ // Set enableIpAccessLists to false Template: `resource "databricks_workspace_conf" "this" { custom_config = { @@ -50,7 +50,7 @@ func TestAccWorkspaceConfFullLifecycle(t *testing.T) { assert.Equal(t, "false", conf.Primary.Attributes["custom_config.enableIpAccessLists"]) return nil }, - }, step{ + }, Step{ // Set invalid configuration Template: `resource "databricks_workspace_conf" "this" { custom_config = { @@ -59,7 +59,7 @@ func TestAccWorkspaceConfFullLifecycle(t *testing.T) { }`, // Assert on server side error returned ExpectError: regexp.MustCompile(`cannot update workspace conf: Invalid keys`), - }, step{ + }, Step{ // Set enableIpAccessLists to true with strange case and maxTokenLifetimeDays to verify // failed deletion case Template: `resource "databricks_workspace_conf" "this" { diff --git a/internal/acceptance/workspace_file_test.go b/internal/acceptance/workspace_file_test.go index ada1782612..9a9a57c8e0 100644 --- a/internal/acceptance/workspace_file_test.go +++ b/internal/acceptance/workspace_file_test.go @@ -5,12 +5,12 @@ import ( ) func TestAccWorkspaceFile(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: `resource "databricks_workspace_file" "this" { source = "{var.CWD}/../../storage/testdata/tf-test-python.py" path = "/Shared/provider-test/xx_{var.RANDOM}" }`, - }, step{ + }, Step{ Template: `resource "databricks_workspace_file" "this" { source = "{var.CWD}/../../storage/testdata/tf-test-python.py" path = "/Shared/provider-test/xx_{var.RANDOM}_renamed" @@ -19,7 +19,7 @@ func TestAccWorkspaceFile(t *testing.T) { } func TestAccWorkspaceFileEmptyFile(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: `resource "databricks_workspace_file" "empty" { source = "{var.CWD}/../../workspace/acceptance/testdata/empty_file" path = "/Shared/provider-test/empty_{var.RANDOM}" @@ -28,12 +28,12 @@ func TestAccWorkspaceFileEmptyFile(t *testing.T) { } func TestAccWorkspaceFileBase64(t *testing.T) { - workspaceLevel(t, step{ + WorkspaceLevel(t, Step{ Template: `resource "databricks_workspace_file" "this2" { content_base64 = "YWJjCg==" path = "/Shared/provider-test/xx2_{var.RANDOM}" }`, - }, step{ + }, Step{ Template: `resource "databricks_workspace_file" "this2" { content_base64 = "YWJjCg==" path = "/Shared/provider-test/xx2_{var.RANDOM}_renamed" diff --git a/internal/providers/pluginfw/resources/qualitymonitor/resource_quality_monitor_test.go b/internal/providers/pluginfw/resources/qualitymonitor/resource_quality_monitor_test.go new file mode 100644 index 0000000000..41039b1d13 --- /dev/null +++ b/internal/providers/pluginfw/resources/qualitymonitor/resource_quality_monitor_test.go @@ -0,0 +1,153 @@ +package qualitymonitor_test + +import ( + "os" + "testing" + + "github.com/databricks/terraform-provider-databricks/internal/acceptance" +) + +var commonPartQualityMonitoring = `resource "databricks_catalog" "sandbox" { + name = "sandbox{var.STICKY_RANDOM}" + comment = "this catalog is managed by terraform" + properties = { + purpose = "testing" + } + force_destroy = true +} + +resource "databricks_schema" "things" { + catalog_name = databricks_catalog.sandbox.id + name = "things{var.STICKY_RANDOM}" + comment = "this database is managed by terraform" + properties = { + kind = "various" + } +} + +resource "databricks_sql_table" "myInferenceTable" { + catalog_name = databricks_catalog.sandbox.id + schema_name = databricks_schema.things.name + name = "bar{var.STICKY_RANDOM}_inference" + table_type = "MANAGED" + data_source_format = "DELTA" + + column { + name = "model_id" + type = "int" + } + column { + name = "timestamp" + type = "int" + } + column { + name = "prediction" + type = "int" + } +} + +` + +func TestUcAccQualityMonitorPluginFramework(t *testing.T) { + if os.Getenv("GOOGLE_CREDENTIALS") != "" { + t.Skipf("databricks_quality_monitor resource is not available on GCP") + } + acceptance.UnityWorkspaceLevel(t, acceptance.Step{ + Template: commonPartQualityMonitoring + ` + + resource "databricks_quality_monitor_pluginframework" "testMonitorInference" { + table_name = databricks_sql_table.myInferenceTable.id + assets_dir = "/Shared/provider-test/databricks_quality_monitoring/${databricks_sql_table.myInferenceTable.name}" + output_schema_name = databricks_schema.things.id + inference_log = { + granularities = ["1 day"] + timestamp_col = "timestamp" + prediction_col = "prediction" + model_id_col = "model_id" + problem_type = "PROBLEM_TYPE_REGRESSION" + } + } + + resource "databricks_sql_table" "myTimeseries" { + catalog_name = databricks_catalog.sandbox.id + schema_name = databricks_schema.things.name + name = "bar{var.STICKY_RANDOM}_timeseries" + table_type = "MANAGED" + data_source_format = "DELTA" + + column { + name = "timestamp" + type = "int" + } + } + + resource "databricks_quality_monitor_pluginframework" "testMonitorTimeseries" { + table_name = databricks_sql_table.myTimeseries.id + assets_dir = "/Shared/provider-test/databricks_quality_monitoring/${databricks_sql_table.myTimeseries.name}" + output_schema_name = databricks_schema.things.id + time_series = { + granularities = ["1 day"] + timestamp_col = "timestamp" + } + } + + resource "databricks_sql_table" "mySnapshot" { + catalog_name = databricks_catalog.sandbox.id + schema_name = databricks_schema.things.name + name = "bar{var.STICKY_RANDOM}_snapshot" + table_type = "MANAGED" + data_source_format = "DELTA" + + column { + name = "timestamp" + type = "int" + } + } + + resource "databricks_quality_monitor_pluginframework" "testMonitorSnapshot" { + table_name = databricks_sql_table.mySnapshot.id + assets_dir = "/Shared/provider-test/databricks_quality_monitoring/${databricks_sql_table.myTimeseries.name}" + output_schema_name = databricks_schema.things.id + snapshot = { + } + } + `, + }) +} + +func TestUcAccUpdateQualityMonitorPluginFramework(t *testing.T) { + if os.Getenv("GOOGLE_CREDENTIALS") != "" { + t.Skipf("databricks_quality_monitor resource is not available on GCP") + } + acceptance.UnityWorkspaceLevel(t, acceptance.Step{ + Template: commonPartQualityMonitoring + ` + resource "databricks_quality_monitor_pluginframework" "testMonitorInference" { + table_name = databricks_sql_table.myInferenceTable.id + assets_dir = "/Shared/provider-test/databricks_quality_monitoring/${databricks_sql_table.myInferenceTable.name}" + output_schema_name = databricks_schema.things.id + inference_log = { + granularities = ["1 day"] + timestamp_col = "timestamp" + prediction_col = "prediction" + model_id_col = "model_id" + problem_type = "PROBLEM_TYPE_REGRESSION" + } + } + `, + }, acceptance.Step{ + Template: commonPartQualityMonitoring + ` + resource "databricks_quality_monitor_pluginframework" "testMonitorInference" { + table_name = databricks_sql_table.myInferenceTable.id + assets_dir = "/Shared/provider-test/databricks_quality_monitoring/${databricks_sql_table.myInferenceTable.name}" + output_schema_name = databricks_schema.things.id + inference_log = { + granularities = ["1 hour"] + timestamp_col = "timestamp" + prediction_col = "prediction" + model_id_col = "model_id" + problem_type = "PROBLEM_TYPE_REGRESSION" + } + } + `, + }) +} diff --git a/internal/tfreflect/reflect_utils.go b/internal/tfreflect/reflect_utils.go index e98fcae152..8df201ef32 100644 --- a/internal/tfreflect/reflect_utils.go +++ b/internal/tfreflect/reflect_utils.go @@ -1,6 +1,8 @@ package tfreflect -import "reflect" +import ( + "reflect" +) type Field struct { StructField reflect.StructField From 0cb0c8acc4fc954617b338cf9a749aa8a88724b5 Mon Sep 17 00:00:00 2001 From: Edward Feng <67326663+edwardfeng-db@users.noreply.github.com> Date: Wed, 4 Sep 2024 17:41:17 +0200 Subject: [PATCH 19/54] [Internal] Move volumes test next to plugin framework data source (#3995) ## Changes - Moving the test file to be next to the data source definition ## Tests - [x] `make test` run locally - [x] relevant change in `docs/` folder - [x] covered with integration tests in `internal/acceptance` - [x] relevant acceptance tests are passing - [x] using Go SDK --- internal/acceptance/data_volumes_test.go | 48 --------------- .../resources/volume/data_volumes_test.go | 59 +++++++++++++++++++ 2 files changed, 59 insertions(+), 48 deletions(-) create mode 100644 internal/providers/pluginfw/resources/volume/data_volumes_test.go diff --git a/internal/acceptance/data_volumes_test.go b/internal/acceptance/data_volumes_test.go index 67581ea3fe..8d78ef8afb 100644 --- a/internal/acceptance/data_volumes_test.go +++ b/internal/acceptance/data_volumes_test.go @@ -58,51 +58,3 @@ func TestUcAccDataSourceVolumes(t *testing.T) { Check: checkDataSourceVolumesPopulated(t), }) } - -func checkDataSourceVolumesPluginFrameworkPopulated(t *testing.T) func(s *terraform.State) error { - return func(s *terraform.State) error { - _, ok := s.Modules[0].Resources["data.databricks_volumes_pluginframework.this"] - require.True(t, ok, "data.databricks_volumes_pluginframework.this has to be there") - num_volumes, _ := strconv.Atoi(s.Modules[0].Outputs["volumes"].Value.(string)) - assert.GreaterOrEqual(t, num_volumes, 1) - return nil - } -} - -func TestUcAccDataSourceVolumesPluginFramework(t *testing.T) { - UnityWorkspaceLevel(t, Step{ - Template: ` - resource "databricks_catalog" "sandbox" { - name = "sandbox{var.RANDOM}" - comment = "this catalog is managed by terraform" - properties = { - purpose = "testing" - } - } - - resource "databricks_schema" "things" { - catalog_name = databricks_catalog.sandbox.id - name = "things{var.RANDOM}" - comment = "this database is managed by terraform" - properties = { - kind = "various" - } - } - resource "databricks_volume" "this" { - name = "volume_data_source_test" - catalog_name = databricks_catalog.sandbox.name - schema_name = databricks_schema.things.name - volume_type = "MANAGED" - } - data "databricks_volumes_pluginframework" "this" { - catalog_name = databricks_catalog.sandbox.name - schema_name = databricks_schema.things.name - depends_on = [ databricks_volume.this ] - } - output "volumes" { - value = length(data.databricks_volumes_pluginframework.this.ids) - } - `, - Check: checkDataSourceVolumesPluginFrameworkPopulated(t), - }) -} diff --git a/internal/providers/pluginfw/resources/volume/data_volumes_test.go b/internal/providers/pluginfw/resources/volume/data_volumes_test.go new file mode 100644 index 0000000000..89177583fb --- /dev/null +++ b/internal/providers/pluginfw/resources/volume/data_volumes_test.go @@ -0,0 +1,59 @@ +package volume_test + +import ( + "strconv" + "testing" + + "github.com/databricks/terraform-provider-databricks/internal/acceptance" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func checkDataSourceVolumesPluginFrameworkPopulated(t *testing.T) func(s *terraform.State) error { + return func(s *terraform.State) error { + _, ok := s.Modules[0].Resources["data.databricks_volumes_pluginframework.this"] + require.True(t, ok, "data.databricks_volumes_pluginframework.this has to be there") + num_volumes, _ := strconv.Atoi(s.Modules[0].Outputs["volumes"].Value.(string)) + assert.GreaterOrEqual(t, num_volumes, 1) + return nil + } +} + +func TestUcAccDataSourceVolumesPluginFramework(t *testing.T) { + acceptance.UnityWorkspaceLevel(t, acceptance.Step{ + Template: ` + resource "databricks_catalog" "sandbox" { + name = "sandbox{var.RANDOM}" + comment = "this catalog is managed by terraform" + properties = { + purpose = "testing" + } + } + + resource "databricks_schema" "things" { + catalog_name = databricks_catalog.sandbox.id + name = "things{var.RANDOM}" + comment = "this database is managed by terraform" + properties = { + kind = "various" + } + } + resource "databricks_volume" "this" { + name = "volume_data_source_test" + catalog_name = databricks_catalog.sandbox.name + schema_name = databricks_schema.things.name + volume_type = "MANAGED" + } + data "databricks_volumes_pluginframework" "this" { + catalog_name = databricks_catalog.sandbox.name + schema_name = databricks_schema.things.name + depends_on = [ databricks_volume.this ] + } + output "volumes" { + value = length(data.databricks_volumes_pluginframework.this.ids) + } + `, + Check: checkDataSourceVolumesPluginFrameworkPopulated(t), + }) +} From 90191742807029cfc2c9dfab1530608bc12ff7b5 Mon Sep 17 00:00:00 2001 From: Parth Bansal Date: Wed, 4 Sep 2024 17:43:30 +0200 Subject: [PATCH 20/54] [Doc] Update documentation regarding authentication with Azure-managed Service Principal using GITHUB OIDC (#3932) ## Changes Update documentation regarding authentication with Azure-managed Service Principal using GITHUB OIDC. ## Tests - [ ] `make test` run locally - [x] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [ ] using Go SDK --- docs/index.md | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/docs/index.md b/docs/index.md index 57349b07c7..05081f57ff 100644 --- a/docs/index.md +++ b/docs/index.md @@ -238,7 +238,7 @@ Alternatively, you can provide this value as an environment variable `DATABRICKS * `profile` - (optional) Connection profile specified within ~/.databrickscfg. Please check [connection profiles section](https://docs.databricks.com/dev-tools/cli/index.html#connection-profiles) for more details. This field defaults to `DEFAULT`. * `account_id` - (optional for workspace-level operations, but required for account-level) Account Id that could be found in the top right corner of [Accounts Console](https://accounts.cloud.databricks.com/). Alternatively, you can provide this value as an environment variable `DATABRICKS_ACCOUNT_ID`. Only has effect when `host = "https://accounts.cloud.databricks.com/"`, and is currently used to provision account admins via [databricks_user](resources/user.md). In the future releases of the provider this property will also be used specify account for `databricks_mws_*` resources as well. -* `auth_type` - (optional) enforce specific auth type to be used in very rare cases, where a single Terraform state manages Databricks workspaces on more than one cloud and `more than one authorization method configured` error is a false positive. Valid values are `pat`, `basic`, `oauth-m2m`, `azure-client-secret`, `azure-msi`, `azure-cli`, `google-credentials`, and `google-id`. +* `auth_type` - (optional) enforce specific auth type to be used in very rare cases, where a single Terraform state manages Databricks workspaces on more than one cloud and `more than one authorization method configured` error is a false positive. Valid values are `pat`, `basic`, `oauth-m2m`, `azure-client-secret`, `azure-msi`, `azure-cli`, `github-oidc-azure`, `google-credentials`, and `google-id`. ## Special configurations for Azure @@ -284,7 +284,7 @@ resource "databricks_user" "my-user" { } ``` -### Authenticating with Azure-managed Service Principal +### Authenticating with Azure-managed Service Principal using Client Secret ```hcl provider "azurerm" { @@ -326,6 +326,49 @@ There are `ARM_*` environment variables provide a way to share authentication co When a workspace is created using a service principal account, that service principal account is automatically added to the workspace as a member of the admins group. To add a new service principal account to an existing workspace, create a [databricks_service_principal](resources/service_principal.md). +### Authenticating with Azure-managed Service Principal using GITHUB OIDC + +```hcl +provider "azurerm" { + client_id = var.client_id + tenant_id = var.tenant_id + subscription_id = var.subscription_id + use_oidc = true +} + +resource "azurerm_databricks_workspace" "this" { + location = "centralus" + name = "my-workspace-name" + resource_group_name = var.resource_group + sku = "premium" +} + +provider "databricks" { + host = azurerm_databricks_workspace.this.workspace_url + auth_type = "github-oidc-azure" + azure_workspace_resource_id = azurerm_databricks_workspace.this.id + azure_client_id = var.client_id + azure_tenant_id = var.tenant_id +} + +resource "databricks_user" "my-user" { + user_name = "test-user@databricks.com" +} +``` + +Follow the [Configuring OpenID Connect in Azure](https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/configuring-openid-connect-in-azure). You can then use the Azure service principal to authenticate in databricks. + +* `azure_workspace_resource_id` - (optional) `id` attribute of [azurerm_databricks_workspace](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/databricks_workspace) resource. Combination of subscription id, resource group name, and workspace name. Required with `azure_use_msi` or `azure_client_secret`. + +* `azure_client_id` - (optional) This is the Azure Enterprise Application (Service principal) client id. This service principal requires contributor access to your Azure Databricks deployment. Alternatively, you can provide this value as an environment variable `ARM_CLIENT_ID`. +* `azure_tenant_id` - (optional) This is the Azure Active Directory Tenant id in which the Enterprise Application (Service Principal) +resides. Alternatively, you can provide this value as an environment variable `ARM_TENANT_ID`. +* `azure_environment` - (optional) This is the Azure Environment which defaults to the `public` cloud. Other options are `german`, `china` and `usgovernment`. Alternatively, you can provide this value as an environment variable `ARM_ENVIRONMENT`. +* `auth_type` - (required) This is the Authentication Type that is used for specifying the authenticate method. This is required for this authentication type. + +There are `ARM_*` environment variables provide a way to share authentication configuration using the `databricks` provider alongside the [`azurerm` provider](https://registry.terraform.io/providers/hashicorp/azurerm/latest). + +When a workspace is created using a service principal account, that service principal account is automatically added to the workspace as a member of the admins group. To add a new service principal account to an existing workspace, create a [databricks_service_principal](resources/service_principal.md). ## Special configurations for GCP The provider works with [Google Cloud CLI authentication](https://cloud.google.com/sdk/docs/authorizing) to facilitate local development workflows. For automated scenarios, a service principal auth is necessary using `google_service_account` parameter with [impersonation](https://cloud.google.com/docs/authentication#service-accounts) and Application Default Credentials. Alternatively, you could provide the service account key directly by passing it to `google_credentials` parameter (or `GOOGLE_CREDENTIALS` environment variable) From afc4764aebc2ef7d6e7437f65bef1d7134b421d5 Mon Sep 17 00:00:00 2001 From: Edward Feng <67326663+edwardfeng-db@users.noreply.github.com> Date: Thu, 5 Sep 2024 14:51:27 +0200 Subject: [PATCH 21/54] [Internal] Support import in acceptance test + adding import state for quality monitor (#3994) ## Changes - Add `ImportState` method for `quality monitor` resource - Make acceptance test infrastructure able to test importing behavior - Add integration test for import state for quality monitor ## Tests - [x] `make test` run locally - [x] relevant change in `docs/` folder - [x] covered with integration tests in `internal/acceptance` - [x] relevant acceptance tests are passing - [x] using Go SDK --- internal/acceptance/init.go | 59 +++++++++++++++---- .../resource_quality_monitor.go | 4 ++ .../resource_quality_monitor_test.go | 32 ++++++++++ 3 files changed, 82 insertions(+), 13 deletions(-) diff --git a/internal/acceptance/init.go b/internal/acceptance/init.go index 704964b710..604d7b636c 100644 --- a/internal/acceptance/init.go +++ b/internal/acceptance/init.go @@ -56,6 +56,27 @@ func UnityAccountLevel(t *testing.T, steps ...Step) { run(t, steps) } +// BuildImportStateIdFunc constructs a function that returns the id attribute of a target resouce from the terraform state. +// This is a helper function for conveniently constructing the ImportStateIdFunc field for a test step. +func BuildImportStateIdFunc(resourceId, attr string) func(*terraform.State) (string, error) { + return func(s *terraform.State) (string, error) { + // Find the resource in the Terraform state. + rs, ok := s.RootModule().Resources[resourceId] + if !ok { + return "", fmt.Errorf("resource not found in state: %s", resourceId) + } + + // Access the attribute directly from the state. + targetAttr := rs.Primary.Attributes[attr] + if targetAttr == "" { + return "", fmt.Errorf("attribute '%s' not found or empty in the resource", attr) + } + + // Return the found attribute or the ID needed for the import. + return targetAttr, nil + } +} + // A step in a terraform acceptance test type Step struct { // Terraform HCL for resources to materialize in this test step. @@ -74,9 +95,17 @@ type Step struct { PlanOnly bool PreventDiskCleanup bool PreventPostDestroyRefresh bool - ImportState bool - ImportStateVerify bool - ProtoV6ProviderFactories map[string]func() (tfprotov6.ProviderServer, error) + + // If true, will test the functionality of ImportState by importing the resource with ResourceName (must be set) and the ID of that resource. + // ID can be supplied with either ImportStateId or ImportStateIdFunc. + ImportState bool + ImportStateId string + ImportStateIdFunc func(*terraform.State) (string, error) + ImportStateVerify bool + ImportStateVerifyIdentifierAttribute string + ResourceName string + + ProtoV6ProviderFactories map[string]func() (tfprotov6.ProviderServer, error) } func createUuid() string { @@ -187,16 +216,20 @@ func run(t *testing.T, steps []Step) { stepPreConfig() } }, - Config: stepConfig, - Destroy: s.Destroy, - ExpectNonEmptyPlan: s.ExpectNonEmptyPlan, - PlanOnly: s.PlanOnly, - PreventDiskCleanup: s.PreventDiskCleanup, - PreventPostDestroyRefresh: s.PreventPostDestroyRefresh, - ImportState: s.ImportState, - ImportStateVerify: s.ImportStateVerify, - ExpectError: s.ExpectError, - ProtoV6ProviderFactories: providerFactoryForStep, + Config: stepConfig, + Destroy: s.Destroy, + ExpectNonEmptyPlan: s.ExpectNonEmptyPlan, + PlanOnly: s.PlanOnly, + PreventDiskCleanup: s.PreventDiskCleanup, + PreventPostDestroyRefresh: s.PreventPostDestroyRefresh, + ImportState: s.ImportState, + ImportStateId: s.ImportStateId, + ImportStateIdFunc: s.ImportStateIdFunc, + ImportStateVerify: s.ImportStateVerify, + ImportStateVerifyIdentifierAttribute: s.ImportStateVerifyIdentifierAttribute, + ResourceName: s.ResourceName, + ExpectError: s.ExpectError, + ProtoV6ProviderFactories: providerFactoryForStep, Check: func(state *terraform.State) error { if stepCheck != nil { return stepCheck(state) diff --git a/internal/providers/pluginfw/resources/qualitymonitor/resource_quality_monitor.go b/internal/providers/pluginfw/resources/qualitymonitor/resource_quality_monitor.go index 20d86a0426..4dd21b44da 100644 --- a/internal/providers/pluginfw/resources/qualitymonitor/resource_quality_monitor.go +++ b/internal/providers/pluginfw/resources/qualitymonitor/resource_quality_monitor.go @@ -88,6 +88,10 @@ func (d *QualityMonitorResource) Configure(ctx context.Context, req resource.Con } } +func (d *QualityMonitorResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("table_name"), req, resp) +} + func (r *QualityMonitorResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { w, diags := r.Client.GetWorkspaceClient() resp.Diagnostics.Append(diags...) diff --git a/internal/providers/pluginfw/resources/qualitymonitor/resource_quality_monitor_test.go b/internal/providers/pluginfw/resources/qualitymonitor/resource_quality_monitor_test.go index 41039b1d13..a2e391bda3 100644 --- a/internal/providers/pluginfw/resources/qualitymonitor/resource_quality_monitor_test.go +++ b/internal/providers/pluginfw/resources/qualitymonitor/resource_quality_monitor_test.go @@ -151,3 +151,35 @@ func TestUcAccUpdateQualityMonitorPluginFramework(t *testing.T) { `, }) } + +func TestUcAccQualityMonitorImportPluginFramework(t *testing.T) { + if os.Getenv("GOOGLE_CREDENTIALS") != "" { + t.Skipf("databricks_quality_monitor resource is not available on GCP") + } + acceptance.UnityWorkspaceLevel(t, + acceptance.Step{ + Template: commonPartQualityMonitoring + ` + + resource "databricks_quality_monitor_pluginframework" "testMonitorInference" { + table_name = databricks_sql_table.myInferenceTable.id + assets_dir = "/Shared/provider-test/databricks_quality_monitoring/${databricks_sql_table.myInferenceTable.name}" + output_schema_name = databricks_schema.things.id + inference_log = { + granularities = ["1 day"] + timestamp_col = "timestamp" + prediction_col = "prediction" + model_id_col = "model_id" + problem_type = "PROBLEM_TYPE_REGRESSION" + } + } + `, + }, + acceptance.Step{ + ImportState: true, + ResourceName: "databricks_quality_monitor_pluginframework.testMonitorInference", + ImportStateIdFunc: acceptance.BuildImportStateIdFunc("databricks_quality_monitor_pluginframework.testMonitorInference", "table_name"), + ImportStateVerify: true, + ImportStateVerifyIdentifierAttribute: "table_name", + }, + ) +} From ca5ea216d6e0e30e3af15460c91c2ea09963b415 Mon Sep 17 00:00:00 2001 From: Tanmay Rustagi <88379306+tanmay-db@users.noreply.github.com> Date: Mon, 9 Sep 2024 15:42:42 +0200 Subject: [PATCH 22/54] [Internal] Add support for `computed` tag in TfSDK Structs (#4005) ## Changes Added support for `computed` tag in TfSDK Structs making code easier to maintain and read, minimising the lines of code required in customizing the schema ## Tests Unit test - [x] `make test` run locally - [ ] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [ ] using Go SDK --- .../pluginfw/tfschema/struct_to_schema.go | 111 +++++++++++++++--- .../tfschema/struct_to_schema_test.go | 20 ++++ 2 files changed, 116 insertions(+), 15 deletions(-) diff --git a/internal/providers/pluginfw/tfschema/struct_to_schema.go b/internal/providers/pluginfw/tfschema/struct_to_schema.go index 471479676e..2ac1303e19 100644 --- a/internal/providers/pluginfw/tfschema/struct_to_schema.go +++ b/internal/providers/pluginfw/tfschema/struct_to_schema.go @@ -30,6 +30,7 @@ func typeToSchema(v reflect.Value) map[string]AttributeBuilder { continue } isOptional := fieldIsOptional(typeField) + isComputed := fieldIsComputed(typeField) kind := typeField.Type.Kind() value := field.Value typeFieldType := typeField.Type @@ -48,17 +49,44 @@ func typeToSchema(v reflect.Value) map[string]AttributeBuilder { } switch elemType { case reflect.TypeOf(types.Bool{}): - scm[fieldName] = ListAttributeBuilder{ElementType: types.BoolType, Optional: isOptional, Required: !isOptional} + scm[fieldName] = ListAttributeBuilder{ + ElementType: types.BoolType, + Optional: isOptional, + Required: !isOptional, + Computed: isComputed, + } case reflect.TypeOf(types.Int64{}): - scm[fieldName] = ListAttributeBuilder{ElementType: types.Int64Type, Optional: isOptional, Required: !isOptional} + scm[fieldName] = ListAttributeBuilder{ + ElementType: types.Int64Type, + Optional: isOptional, + Required: !isOptional, + Computed: isComputed, + } case reflect.TypeOf(types.Float64{}): - scm[fieldName] = ListAttributeBuilder{ElementType: types.Float64Type, Optional: isOptional, Required: !isOptional} + scm[fieldName] = ListAttributeBuilder{ + ElementType: types.Float64Type, + Optional: isOptional, + Required: !isOptional, + Computed: isComputed, + } case reflect.TypeOf(types.String{}): - scm[fieldName] = ListAttributeBuilder{ElementType: types.StringType, Optional: isOptional, Required: !isOptional} + scm[fieldName] = ListAttributeBuilder{ + ElementType: types.StringType, + Optional: isOptional, + Required: !isOptional, + Computed: isComputed, + } default: // Nested struct nestedScm := typeToSchema(reflect.New(elemType).Elem()) - scm[fieldName] = ListNestedAttributeBuilder{NestedObject: NestedAttributeObject{Attributes: nestedScm}, Optional: isOptional, Required: !isOptional} + scm[fieldName] = ListNestedAttributeBuilder{ + NestedObject: NestedAttributeObject{ + Attributes: nestedScm, + }, + Optional: isOptional, + Required: !isOptional, + Computed: isComputed, + } } } else if kind == reflect.Map { elemType := typeFieldType.Elem() @@ -70,28 +98,71 @@ func typeToSchema(v reflect.Value) map[string]AttributeBuilder { } switch elemType { case reflect.TypeOf(types.Bool{}): - scm[fieldName] = MapAttributeBuilder{ElementType: types.BoolType, Optional: isOptional, Required: !isOptional} + scm[fieldName] = MapAttributeBuilder{ + ElementType: types.BoolType, + Optional: isOptional, + Required: !isOptional, + Computed: isComputed, + } case reflect.TypeOf(types.Int64{}): - scm[fieldName] = MapAttributeBuilder{ElementType: types.Int64Type, Optional: isOptional, Required: !isOptional} + scm[fieldName] = MapAttributeBuilder{ + ElementType: types.Int64Type, + Optional: isOptional, + Required: !isOptional, + Computed: isComputed, + } case reflect.TypeOf(types.Float64{}): - scm[fieldName] = MapAttributeBuilder{ElementType: types.Float64Type, Optional: isOptional, Required: !isOptional} + scm[fieldName] = MapAttributeBuilder{ + ElementType: types.Float64Type, + Optional: isOptional, + Required: !isOptional, + Computed: isComputed, + } case reflect.TypeOf(types.String{}): - scm[fieldName] = MapAttributeBuilder{ElementType: types.StringType, Optional: isOptional, Required: !isOptional} + scm[fieldName] = MapAttributeBuilder{ + ElementType: types.StringType, + Optional: isOptional, + Required: !isOptional, + Computed: isComputed, + } default: // Nested struct nestedScm := typeToSchema(reflect.New(elemType).Elem()) - scm[fieldName] = MapNestedAttributeBuilder{NestedObject: NestedAttributeObject{Attributes: nestedScm}, Optional: isOptional, Required: !isOptional} + scm[fieldName] = MapNestedAttributeBuilder{ + NestedObject: NestedAttributeObject{ + Attributes: nestedScm, + }, + Optional: isOptional, + Required: !isOptional, + Computed: isComputed, + } } } else if kind == reflect.Struct { switch value.Interface().(type) { case types.Bool: - scm[fieldName] = BoolAttributeBuilder{Optional: isOptional, Required: !isOptional} + scm[fieldName] = BoolAttributeBuilder{ + Optional: isOptional, + Required: !isOptional, + Computed: isComputed, + } case types.Int64: - scm[fieldName] = Int64AttributeBuilder{Optional: isOptional, Required: !isOptional} + scm[fieldName] = Int64AttributeBuilder{ + Optional: isOptional, + Required: !isOptional, + Computed: isComputed, + } case types.Float64: - scm[fieldName] = Float64AttributeBuilder{Optional: isOptional, Required: !isOptional} + scm[fieldName] = Float64AttributeBuilder{ + Optional: isOptional, + Required: !isOptional, + Computed: isComputed, + } case types.String: - scm[fieldName] = StringAttributeBuilder{Optional: isOptional, Required: !isOptional} + scm[fieldName] = StringAttributeBuilder{ + Optional: isOptional, + Required: !isOptional, + Computed: isComputed, + } case types.List: panic(fmt.Errorf("types.List should never be used in tfsdk structs. %s", common.TerraformBugErrorMessage)) case types.Map: @@ -101,7 +172,12 @@ func typeToSchema(v reflect.Value) map[string]AttributeBuilder { elem := typeFieldType sv := reflect.New(elem) nestedScm := typeToSchema(sv) - scm[fieldName] = SingleNestedAttributeBuilder{Attributes: nestedScm, Optional: isOptional, Required: !isOptional} + scm[fieldName] = SingleNestedAttributeBuilder{ + Attributes: nestedScm, + Optional: isOptional, + Required: !isOptional, + Computed: isComputed, + } } } else { panic(fmt.Errorf("unknown type for field: %s. %s", typeField.Name, common.TerraformBugErrorMessage)) @@ -110,6 +186,11 @@ func typeToSchema(v reflect.Value) map[string]AttributeBuilder { return scm } +func fieldIsComputed(field reflect.StructField) bool { + tagValue := field.Tag.Get("tf") + return strings.Contains(tagValue, "computed") +} + func fieldIsOptional(field reflect.StructField) bool { tagValue := field.Tag.Get("tf") return strings.Contains(tagValue, "optional") diff --git a/internal/providers/pluginfw/tfschema/struct_to_schema_test.go b/internal/providers/pluginfw/tfschema/struct_to_schema_test.go index 7eca181b17..f566c5feab 100644 --- a/internal/providers/pluginfw/tfschema/struct_to_schema_test.go +++ b/internal/providers/pluginfw/tfschema/struct_to_schema_test.go @@ -24,6 +24,12 @@ type TestIntTfSdk struct { Workers types.Int64 `tfsdk:"workers" tf:"optional"` } +type TestComputedTfSdk struct { + ComputedTag types.String `tfsdk:"computedtag" tf:"computed"` + MultipleTags types.String `tfsdk:"multipletags" tf:"computed,optional"` + NonComputed types.String `tfsdk:"noncomputed" tf:"optional"` +} + type TestFloatTfSdk struct { Float types.Float64 `tfsdk:"float" tf:"optional"` } @@ -248,3 +254,17 @@ func TestStructToSchemaExpectedError(t *testing.T) { t.Run(test.name, func(t *testing.T) { testStructToSchemaPanics(t, test.testStruct, test.expectedError) }) } } + +func TestComputedField(t *testing.T) { + // Test that ComputedTag field is computed and required + scm := ResourceStructToSchema(TestComputedTfSdk{}, nil) + assert.True(t, scm.Attributes["computedtag"].IsComputed()) + assert.True(t, scm.Attributes["computedtag"].IsRequired()) + + // Test that MultipleTags field is computed and optional + assert.True(t, scm.Attributes["multipletags"].IsComputed()) + assert.True(t, scm.Attributes["multipletags"].IsOptional()) + + // Test that NonComputed field is not computed + assert.True(t, !scm.Attributes["noncomputed"].IsComputed()) +} From c35264d1c6598729e6821f5495da6c3023ba2957 Mon Sep 17 00:00:00 2001 From: Dustin Sollick Date: Tue, 10 Sep 2024 12:44:21 -0400 Subject: [PATCH 23/54] [Doc] Small Grammar Corrections in Docs (#4006) ## Changes Hey team, This PR fixes a bunch of small nits in the documentation around verb tense (specifically 'could' vs 'can') and adds indefinite articles ('a'/'an') before singular resource references. This brings it more in line with other documentation, and fixes grammatical errors. ## Tests - [ ] `make test` run locally - [x] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [ ] using Go SDK --- docs/data-sources/aws_crossaccount_policy.md | 2 +- docs/data-sources/catalog.md | 2 +- docs/data-sources/catalogs.md | 2 +- docs/data-sources/external_location.md | 2 +- docs/data-sources/external_locations.md | 2 +- docs/data-sources/metastore.md | 2 +- docs/data-sources/metastores.md | 2 +- docs/data-sources/schemas.md | 2 +- docs/data-sources/storage_credential.md | 2 +- docs/data-sources/storage_credentials.md | 2 +- docs/data-sources/table.md | 2 +- docs/data-sources/tables.md | 2 +- docs/data-sources/volumes.md | 2 +- docs/resources/access_control_rule_set.md | 2 +- docs/resources/artifact_allowlist.md | 2 +- docs/resources/automatic_cluster_update_setting.md | 2 +- docs/resources/catalog.md | 2 +- docs/resources/compliance_security_profile_setting.md | 2 +- docs/resources/connection.md | 2 +- docs/resources/default_namespace_setting.md | 2 +- docs/resources/enhanced_security_monitoring_setting.md | 2 +- docs/resources/external_location.md | 2 +- docs/resources/metastore.md | 2 +- docs/resources/metastore_assignment.md | 2 +- docs/resources/metastore_data_access.md | 2 +- docs/resources/online_table.md | 2 +- docs/resources/provider.md | 2 +- docs/resources/recipient.md | 2 +- docs/resources/registered_model.md | 2 +- docs/resources/restrict_workspace_admins_setting.md | 2 +- docs/resources/schema.md | 2 +- docs/resources/share.md | 2 +- docs/resources/storage_credential.md | 2 +- docs/resources/system_schema.md | 2 +- docs/resources/vector_search_endpoint.md | 2 +- docs/resources/vector_search_index.md | 2 +- docs/resources/volume.md | 2 +- docs/resources/workspace_binding.md | 2 +- 38 files changed, 38 insertions(+), 38 deletions(-) diff --git a/docs/data-sources/aws_crossaccount_policy.md b/docs/data-sources/aws_crossaccount_policy.md index c99876a7e0..715cf59b15 100644 --- a/docs/data-sources/aws_crossaccount_policy.md +++ b/docs/data-sources/aws_crossaccount_policy.md @@ -3,7 +3,7 @@ subcategory: "Deployment" --- # databricks_aws_crossaccount_policy Data Source --> **Note** This data source could be only used with account-level provider! +-> **Note** This data source can only be used with an account-level provider! This data source constructs necessary AWS cross-account policy for you, which is based on [official documentation](https://docs.databricks.com/administration-guide/account-api/iam-role.html#language-Your%C2%A0VPC,%C2%A0default). diff --git a/docs/data-sources/catalog.md b/docs/data-sources/catalog.md index f9851018dd..533f8eb60d 100644 --- a/docs/data-sources/catalog.md +++ b/docs/data-sources/catalog.md @@ -3,7 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_catalog Data Source --> **Note** This data source could be only used with workspace-level provider! +-> **Note** This data source can only be used with a workspace-level provider! -> **Note** If you have a fully automated setup with workspaces created by [databricks_mws_workspaces](../resources/mws_workspaces.md) or [azurerm_databricks_workspace](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/databricks_workspace), please make sure to add [depends_on attribute](../guides/troubleshooting.md#data-resources-and-authentication-is-not-configured-errors) in order to prevent _default auth: cannot configure default credentials_ errors. diff --git a/docs/data-sources/catalogs.md b/docs/data-sources/catalogs.md index 5c20123c89..4f9fc3e569 100644 --- a/docs/data-sources/catalogs.md +++ b/docs/data-sources/catalogs.md @@ -3,7 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_catalogs Data Source --> **Note** This data source could be only used with workspace-level provider! +-> **Note** This data source can only be used with a workspace-level provider! -> **Note** If you have a fully automated setup with workspaces created by [databricks_mws_workspaces](../resources/mws_workspaces.md) or [azurerm_databricks_workspace](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/databricks_workspace), please make sure to add [depends_on attribute](../guides/troubleshooting.md#data-resources-and-authentication-is-not-configured-errors) in order to prevent _default auth: cannot configure default credentials_ errors. diff --git a/docs/data-sources/external_location.md b/docs/data-sources/external_location.md index 78ecde2ca7..8a8e3cc90a 100644 --- a/docs/data-sources/external_location.md +++ b/docs/data-sources/external_location.md @@ -3,7 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_external_location Data Source --> **Note** This data source could be only used with workspace-level provider! +-> **Note** This data source can only be used with a workspace-level provider! Retrieves details about a [databricks_external_location](../resources/external_location.md) that were created by Terraform or manually. diff --git a/docs/data-sources/external_locations.md b/docs/data-sources/external_locations.md index fa4bdedd0c..c9472567df 100644 --- a/docs/data-sources/external_locations.md +++ b/docs/data-sources/external_locations.md @@ -3,7 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_external_locations Data Source --> **Note** This data source could be only used with workspace-level provider! +-> **Note** This data source can only be used with a workspace-level provider! Retrieves a list of [databricks_external_location](./external_location.md) objects, that were created by Terraform or manually, so that special handling could be applied. diff --git a/docs/data-sources/metastore.md b/docs/data-sources/metastore.md index 948a17ef21..db59fc7488 100644 --- a/docs/data-sources/metastore.md +++ b/docs/data-sources/metastore.md @@ -3,7 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_metastore Data Source --> **Note** This data source could be only used with account-level provider! +-> **Note** This data source can only be used with an account-level provider! Retrieves information about metastore for a given id of [databricks_metastore](../resources/metastore.md) object, that was created by Terraform or manually, so that special handling could be applied. diff --git a/docs/data-sources/metastores.md b/docs/data-sources/metastores.md index a6dbe45c84..ac002e16cd 100644 --- a/docs/data-sources/metastores.md +++ b/docs/data-sources/metastores.md @@ -3,7 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_metastores Data Source --> **Note** This data source could be only used with account-level provider! +-> **Note** This data source can only be used with an account-level provider! Retrieves a mapping of name to id of [databricks_metastore](../resources/metastore.md) objects, that were created by Terraform or manually, so that special handling could be applied. diff --git a/docs/data-sources/schemas.md b/docs/data-sources/schemas.md index 1128195989..aa0a589d40 100644 --- a/docs/data-sources/schemas.md +++ b/docs/data-sources/schemas.md @@ -3,7 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_schemas Data Source --> **Note** This data source could be only used with workspace-level provider! +-> **Note** This data source can only be used with a workspace-level provider! -> **Note** If you have a fully automated setup with workspaces created by [databricks_mws_workspaces](../resources/mws_workspaces.md) or [azurerm_databricks_workspace](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/databricks_workspace), please make sure to add [depends_on attribute](../guides/troubleshooting.md#data-resources-and-authentication-is-not-configured-errors) in order to prevent _default auth: cannot configure default credentials_ errors. diff --git a/docs/data-sources/storage_credential.md b/docs/data-sources/storage_credential.md index 631e264e66..0361bf523b 100644 --- a/docs/data-sources/storage_credential.md +++ b/docs/data-sources/storage_credential.md @@ -3,7 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_storage_credential Data Source --> **Note** This data source could be only used with workspace-level provider! +-> **Note** This data source can only be used with a workspace-level provider! Retrieves details about a [databricks_storage_credential](../resources/storage_credential.md) that were created by Terraform or manually. diff --git a/docs/data-sources/storage_credentials.md b/docs/data-sources/storage_credentials.md index a2d35bde7e..db22f74ae6 100644 --- a/docs/data-sources/storage_credentials.md +++ b/docs/data-sources/storage_credentials.md @@ -3,7 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_storage_credentials Data Source --> **Note** This data source could be only used with workspace-level provider! +-> **Note** This data source can only be used with a workspace-level provider! Retrieves a list of [databricks_storage_credential](./storage_credential.md) objects, that were created by Terraform or manually, so that special handling could be applied. diff --git a/docs/data-sources/table.md b/docs/data-sources/table.md index 3eb1ccf49e..408133b4f0 100644 --- a/docs/data-sources/table.md +++ b/docs/data-sources/table.md @@ -3,7 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_table Data Source --> **Note** This data source could be only used with workspace-level provider! +-> **Note** This data source can only be used with a workspace-level provider! -> **Note** If you have a fully automated setup with workspaces created by [databricks_mws_workspaces](../resources/mws_workspaces.md) or [azurerm_databricks_workspace](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/databricks_workspace), please make sure to add [depends_on attribute](../guides/troubleshooting.md#data-resources-and-authentication-is-not-configured-errors) in order to prevent _default auth: cannot configure default credentials_ errors. diff --git a/docs/data-sources/tables.md b/docs/data-sources/tables.md index fcb9516fc3..1a3f2cd4e0 100644 --- a/docs/data-sources/tables.md +++ b/docs/data-sources/tables.md @@ -3,7 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_tables Data Source --> **Note** This data source could be only used with workspace-level provider! +-> **Note** This data source can only be used with a workspace-level provider! -> **Note** If you have a fully automated setup with workspaces created by [databricks_mws_workspaces](../resources/mws_workspaces.md) or [azurerm_databricks_workspace](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/databricks_workspace), please make sure to add [depends_on attribute](../guides/troubleshooting.md#data-resources-and-authentication-is-not-configured-errors) in order to prevent _default auth: cannot configure default credentials_ errors. diff --git a/docs/data-sources/volumes.md b/docs/data-sources/volumes.md index 619e05c513..89ee190f39 100644 --- a/docs/data-sources/volumes.md +++ b/docs/data-sources/volumes.md @@ -3,7 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_volumes Data Source --> **Note** This data source could be only used with workspace-level provider! +-> **Note** This data source can only be used with a workspace-level provider! Retrieves a list of [databricks_volume](../resources/volume.md) ids (full names), that were created by Terraform or manually. diff --git a/docs/resources/access_control_rule_set.md b/docs/resources/access_control_rule_set.md index 44a6479651..3a7767c570 100644 --- a/docs/resources/access_control_rule_set.md +++ b/docs/resources/access_control_rule_set.md @@ -4,7 +4,7 @@ subcategory: "Security" # databricks_access_control_rule_set Resource --> **Note** This resource could be used with account or workspace-level provider. +-> **Note** This resource can be used with an account or workspace-level provider. This resource allows you to manage access rules on Databricks account level resources. For convenience we allow accessing this resource through the Databricks account and workspace. diff --git a/docs/resources/artifact_allowlist.md b/docs/resources/artifact_allowlist.md index 4973872a3c..a65fe6dd57 100644 --- a/docs/resources/artifact_allowlist.md +++ b/docs/resources/artifact_allowlist.md @@ -6,7 +6,7 @@ subcategory: "Unity Catalog" -> **Note** It is required to define all allowlist for an artifact type in a single resource, otherwise Terraform cannot guarantee config drift prevention. --> **Note** This resource could be only used with workspace-level provider! +-> **Note** This resource can only be used with a workspace-level provider! In Databricks Runtime 13.3 and above, you can add libraries and init scripts to the allowlist in UC so that users can leverage these artifacts on compute configured with shared access mode. diff --git a/docs/resources/automatic_cluster_update_setting.md b/docs/resources/automatic_cluster_update_setting.md index 0a5ce409d0..152a95b9ea 100644 --- a/docs/resources/automatic_cluster_update_setting.md +++ b/docs/resources/automatic_cluster_update_setting.md @@ -4,7 +4,7 @@ subcategory: "Settings" # databricks_automatic_cluster_update_workspace_setting Resource --> **Note** This resource could be only used with workspace-level provider! +-> **Note** This resource can only be used with a workspace-level provider! The `databricks_automatic_cluster_update_workspace_setting` resource allows you to control whether automatic cluster update is enabled for the current workspace. By default, it is turned off. Enabling this feature on a workspace requires that you add the Enhanced Security and Compliance add-on. diff --git a/docs/resources/catalog.md b/docs/resources/catalog.md index 1145837aa4..980c6c837d 100644 --- a/docs/resources/catalog.md +++ b/docs/resources/catalog.md @@ -3,7 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_catalog Resource --> **Note** This resource could be only used with workspace-level provider! +-> **Note** This resource can only be used with a workspace-level provider! Within a metastore, Unity Catalog provides a 3-level namespace for organizing data: Catalogs, Databases (also called Schemas), and Tables / Views. diff --git a/docs/resources/compliance_security_profile_setting.md b/docs/resources/compliance_security_profile_setting.md index a507243418..6bb5afc090 100644 --- a/docs/resources/compliance_security_profile_setting.md +++ b/docs/resources/compliance_security_profile_setting.md @@ -4,7 +4,7 @@ subcategory: "Settings" # databricks_compliance_security_profile_workspace_setting Resource --> **Note** This resource could be only used with workspace-level provider! +-> **Note** This resource can only be used with a workspace-level provider! -> **Note** This setting can NOT be disabled once it is enabled. diff --git a/docs/resources/connection.md b/docs/resources/connection.md index 5115f1ca1d..f7421bd5da 100644 --- a/docs/resources/connection.md +++ b/docs/resources/connection.md @@ -3,7 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_connection (Resource) --> **Note** This resource could be only used with workspace-level provider! +-> **Note** This resource can only be used with a workspace-level provider! Lakehouse Federation is the query federation platform for Databricks. Databricks uses Unity Catalog to manage query federation. To make a dataset available for read-only querying using Lakehouse Federation, you create the following: diff --git a/docs/resources/default_namespace_setting.md b/docs/resources/default_namespace_setting.md index 723937bd6e..cf3c5ee36a 100644 --- a/docs/resources/default_namespace_setting.md +++ b/docs/resources/default_namespace_setting.md @@ -4,7 +4,7 @@ subcategory: "Settings" # databricks_default_namespace_setting Resource --> **Note** This resource could be only used with workspace-level provider! +-> **Note** This resource can only be used with a workspace-level provider! The `databricks_default_namespace_setting` resource allows you to operate the setting configuration for the default namespace in the Databricks workspace. Setting the default catalog for the workspace determines the catalog that is used when queries do not reference diff --git a/docs/resources/enhanced_security_monitoring_setting.md b/docs/resources/enhanced_security_monitoring_setting.md index 7447b7ad34..64a18c9fcb 100644 --- a/docs/resources/enhanced_security_monitoring_setting.md +++ b/docs/resources/enhanced_security_monitoring_setting.md @@ -4,7 +4,7 @@ subcategory: "Settings" # databricks_enhanced_security_monitoring_workspace_setting Resource --> **Note** This resource could be only used with workspace-level provider! +-> **Note** This resource can only be used with a workspace-level provider! The `databricks_enhanced_security_monitoring_workspace_setting` resource allows you to control whether enhanced security monitoring is enabled for the current workspace. If the compliance security profile is enabled, this is automatically enabled. By default, diff --git a/docs/resources/external_location.md b/docs/resources/external_location.md index 933f863d67..59cc555685 100644 --- a/docs/resources/external_location.md +++ b/docs/resources/external_location.md @@ -3,7 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_external_location Resource --> **Note** This resource could be only used with workspace-level provider! +-> **Note** This resource can only be used with a workspace-level provider! To work with external tables, Unity Catalog introduces two new objects to access and work with external cloud storage: diff --git a/docs/resources/metastore.md b/docs/resources/metastore.md index d159f53037..6cd5a8417e 100644 --- a/docs/resources/metastore.md +++ b/docs/resources/metastore.md @@ -3,7 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_metastore Resource --> **Note** This resource could be used with account or workspace-level provider. +-> **Note** This resource can be used with an account or workspace-level provider. A metastore is the top-level container of objects in Unity Catalog. It stores data assets (tables and views) and the permissions that govern access to them. Databricks account admins can create metastores and assign them to Databricks workspaces in order to control which workloads use each metastore. diff --git a/docs/resources/metastore_assignment.md b/docs/resources/metastore_assignment.md index 14edd3d60c..6a336a312b 100644 --- a/docs/resources/metastore_assignment.md +++ b/docs/resources/metastore_assignment.md @@ -3,7 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_metastore_assignment (Resource) --> **Note** This resource could be used with account or workspace-level provider. +-> **Note** This resource can be used with an account or workspace-level provider. A single [databricks_metastore](metastore.md) can be shared across Databricks workspaces, and each linked workspace has a consistent view of the data and a single set of access policies. You can only create a single metastore for each region in which your organization operates. diff --git a/docs/resources/metastore_data_access.md b/docs/resources/metastore_data_access.md index 8b9334065b..290eb061cb 100644 --- a/docs/resources/metastore_data_access.md +++ b/docs/resources/metastore_data_access.md @@ -3,7 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_metastore_data_access (Resource) --> **Note** This resource could be used with account or workspace-level provider. +-> **Note** This resource can be used with an account or workspace-level provider. Optionally, each [databricks_metastore](metastore.md) can have a default [databricks_storage_credential](storage_credential.md) defined as `databricks_metastore_data_access`. This will be used by Unity Catalog to access data in the root storage location if defined. diff --git a/docs/resources/online_table.md b/docs/resources/online_table.md index bbfa9cafbd..66aa48025c 100644 --- a/docs/resources/online_table.md +++ b/docs/resources/online_table.md @@ -4,7 +4,7 @@ subcategory: "Unity Catalog" # databricks_online_table (Resource) --> **Note** This resource could be only used on Unity Catalog-enabled workspace! +-> **Note** This resource can only be used on a Unity Catalog-enabled workspace! This resource allows you to create [Online Table](https://docs.databricks.com/en/machine-learning/feature-store/online-tables.html) in Databricks. An online table is a read-only copy of a Delta Table that is stored in row-oriented format optimized for online access. Online tables are fully serverless tables that auto-scale throughput capacity with the request load and provide low latency and high throughput access to data of any scale. Online tables are designed to work with Databricks Model Serving, Feature Serving, and retrieval-augmented generation (RAG) applications where they are used for fast data lookups. diff --git a/docs/resources/provider.md b/docs/resources/provider.md index c6a834eae4..25ebe76601 100644 --- a/docs/resources/provider.md +++ b/docs/resources/provider.md @@ -3,7 +3,7 @@ subcategory: "Delta Sharing" --- # databricks_provider Resource --> **Note** This resource could be only used with workspace-level provider! +-> **Note** This resource can only be used with a workspace-level provider! In Delta Sharing, a provider is an entity that shares data with a recipient. Within a metastore, Unity Catalog provides the ability to create a provider which contains a list of shares that have been shared with you. diff --git a/docs/resources/recipient.md b/docs/resources/recipient.md index e6803b219a..6df597ea92 100644 --- a/docs/resources/recipient.md +++ b/docs/resources/recipient.md @@ -3,7 +3,7 @@ subcategory: "Delta Sharing" --- # databricks_recipient Resource --> **Note** This resource could be only used with workspace-level provider! +-> **Note** This resource can only be used with a workspace-level provider! In Delta Sharing, a recipient is an entity that receives shares from a provider. In Unity Catalog, a share is a securable object that represents an organization and associates it with a credential or secure sharing identifier that allows that organization to access one or more shares. diff --git a/docs/resources/registered_model.md b/docs/resources/registered_model.md index 5594309e92..44c583102b 100644 --- a/docs/resources/registered_model.md +++ b/docs/resources/registered_model.md @@ -3,7 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_registered_model Resource --> **Note** This resource could be only used with workspace-level provider! +-> **Note** This resource can only be used with a workspace-level provider! This resource allows you to create [Models in Unity Catalog](https://docs.databricks.com/en/mlflow/models-in-uc.html) in Databricks. diff --git a/docs/resources/restrict_workspace_admins_setting.md b/docs/resources/restrict_workspace_admins_setting.md index 8e88269caa..765825f866 100644 --- a/docs/resources/restrict_workspace_admins_setting.md +++ b/docs/resources/restrict_workspace_admins_setting.md @@ -4,7 +4,7 @@ subcategory: "Settings" # databricks_restrict_workspace_admins_setting Resource --> **Note** This resource could be only used with workspace-level provider! +-> **Note** This resource can only be used with a workspace-level provider! The `databricks_restrict_workspace_admins_setting` resource lets you control the capabilities of workspace admins. diff --git a/docs/resources/schema.md b/docs/resources/schema.md index 0ad1af4c6f..65a144c4e9 100644 --- a/docs/resources/schema.md +++ b/docs/resources/schema.md @@ -3,7 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_schema Resource --> **Note** This resource could be only used with workspace-level provider! +-> **Note** This resource can only be used with a workspace-level provider! Within a metastore, Unity Catalog provides a 3-level namespace for organizing data: Catalogs, Databases (also called Schemas), and Tables / Views. diff --git a/docs/resources/share.md b/docs/resources/share.md index 29f002f4ef..38252a8818 100644 --- a/docs/resources/share.md +++ b/docs/resources/share.md @@ -3,7 +3,7 @@ subcategory: "Delta Sharing" --- # databricks_share Resource --> **Note** This resource could be only used with workspace-level provider! +-> **Note** This resource can only be used with a workspace-level provider! In Delta Sharing, a share is a read-only collection of tables and table partitions that a provider wants to share with one or more recipients. If your recipient uses a Unity Catalog-enabled Databricks workspace, you can also include notebook files, views (including dynamic views that restrict access at the row and column level), Unity Catalog volumes, and Unity Catalog models in a share. diff --git a/docs/resources/storage_credential.md b/docs/resources/storage_credential.md index 40f452ff7a..b57120e8dd 100644 --- a/docs/resources/storage_credential.md +++ b/docs/resources/storage_credential.md @@ -3,7 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_storage_credential Resource --> **Note** This resource could be used with account or workspace-level provider. +-> **Note** This resource can be used with an account or workspace-level provider. To work with external tables, Unity Catalog introduces two new objects to access and work with external cloud storage: diff --git a/docs/resources/system_schema.md b/docs/resources/system_schema.md index 18c515de6e..80634f0859 100644 --- a/docs/resources/system_schema.md +++ b/docs/resources/system_schema.md @@ -5,7 +5,7 @@ subcategory: "Unity Catalog" -> **Public Preview** This feature is in [Public Preview](https://docs.databricks.com/release-notes/release-types.html). --> **Note** This resource could be only used with workspace-level provider! +-> **Note** This resource can only be used with a workspace-level provider! Manages system tables enablement. System tables are a Databricks-hosted analytical store of your account’s operational data. System tables can be used for historical observability across your account. System tables must be enabled by an account admin. diff --git a/docs/resources/vector_search_endpoint.md b/docs/resources/vector_search_endpoint.md index adb3319264..c90de0c25a 100644 --- a/docs/resources/vector_search_endpoint.md +++ b/docs/resources/vector_search_endpoint.md @@ -3,7 +3,7 @@ subcategory: "Mosaic AI Vector Search" --- # databricks_vector_search_endpoint Resource --> **Note** This resource could be only used on Unity Catalog-enabled workspace! +-> **Note** This resource can only be used on a Unity Catalog-enabled workspace! This resource allows you to create [Mosaic AI Vector Search Endpoint](https://docs.databricks.com/en/generative-ai/vector-search.html) in Databricks. Mosaic AI Vector Search is a serverless similarity search engine that allows you to store a vector representation of your data, including metadata, in a vector database. The Mosaic AI Vector Search Endpoint is used to create and access vector search indexes. diff --git a/docs/resources/vector_search_index.md b/docs/resources/vector_search_index.md index 74d02e746e..abf17447fb 100644 --- a/docs/resources/vector_search_index.md +++ b/docs/resources/vector_search_index.md @@ -3,7 +3,7 @@ subcategory: "Mosaic AI Vector Search" --- # databricks_vector_search_index Resource --> **Note** This resource could be only used on Unity Catalog-enabled workspace! +-> **Note** This resource can only be used on a Unity Catalog-enabled workspace! This resource allows you to create [Mosaic AI Vector Search Index](https://docs.databricks.com/en/generative-ai/create-query-vector-search.html) in Databricks. Mosaic AI Vector Search is a serverless similarity search engine that allows you to store a vector representation of your data, including metadata, in a vector database. The Mosaic AI Vector Search Index provides the ability to search data in the linked Delta Table. diff --git a/docs/resources/volume.md b/docs/resources/volume.md index a95fd5fac9..b116e42129 100644 --- a/docs/resources/volume.md +++ b/docs/resources/volume.md @@ -5,7 +5,7 @@ subcategory: "Unity Catalog" -> **Public Preview** This feature is in [Public Preview](https://docs.databricks.com/release-notes/release-types.html). --> **Note** This resource could be only used with workspace-level provider! +-> **Note** This resource can only be used with a workspace-level provider! Volumes are Unity Catalog objects representing a logical volume of storage in a cloud object storage location. Volumes provide capabilities for accessing, storing, governing, and organizing files. While tables provide governance over tabular datasets, volumes add governance over non-tabular datasets. You can use volumes to store and access files in any format, including structured, semi-structured, and unstructured data. diff --git a/docs/resources/workspace_binding.md b/docs/resources/workspace_binding.md index 94f33912c1..5a649bd9e4 100644 --- a/docs/resources/workspace_binding.md +++ b/docs/resources/workspace_binding.md @@ -3,7 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_workspace_binding Resource --> **Note** This resource could be only used with workspace-level provider! +-> **Note** This resource can only be used with a workspace-level provider! If you use workspaces to isolate user data access, you may want to limit access to catalog, external locations or storage credentials from specific workspaces in your account, also known as workspace binding From 620bb2703ca51483e63ec20c03c21d1d6797884d Mon Sep 17 00:00:00 2001 From: hectorcast-db Date: Wed, 11 Sep 2024 12:49:58 +0200 Subject: [PATCH 24/54] [Dependency] Update Go SDK to 0.46.0 (#4007) ## Changes ## Tests - [X] `make test` run locally - [ ] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [X] using Go SDK --- .codegen/_openapi_sha | 2 +- go.mod | 2 +- go.sum | 4 +- internal/service/catalog_tf/model.go | 23 ++++- internal/service/iam_tf/model.go | 14 +-- internal/service/jobs_tf/model.go | 100 +++++++++++++++++++++- internal/service/ml_tf/model.go | 7 +- internal/service/serving_tf/model.go | 6 +- internal/service/vectorsearch_tf/model.go | 5 ++ 9 files changed, 145 insertions(+), 18 deletions(-) diff --git a/.codegen/_openapi_sha b/.codegen/_openapi_sha index 8b01a2422a..4ceeab3d38 100644 --- a/.codegen/_openapi_sha +++ b/.codegen/_openapi_sha @@ -1 +1 @@ -3eae49b444cac5a0118a3503e5b7ecef7f96527a \ No newline at end of file +d05898328669a3f8ab0c2ecee37db2673d3ea3f7 \ No newline at end of file diff --git a/go.mod b/go.mod index 40a4bd7940..8f5de34e8d 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/databricks/terraform-provider-databricks go 1.22 require ( - github.com/databricks/databricks-sdk-go v0.45.0 + github.com/databricks/databricks-sdk-go v0.46.0 github.com/golang-jwt/jwt/v4 v4.5.0 github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 github.com/hashicorp/hcl v1.0.0 diff --git a/go.sum b/go.sum index 6eb1b4559f..9cace277b5 100644 --- a/go.sum +++ b/go.sum @@ -26,8 +26,8 @@ github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBS github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= -github.com/databricks/databricks-sdk-go v0.45.0 h1:wdx5Wm/ESrahdHeq62WrjLeGjV4r722LLanD8ahI0Mo= -github.com/databricks/databricks-sdk-go v0.45.0/go.mod h1:ds+zbv5mlQG7nFEU5ojLtgN/u0/9YzZmKQES/CfedzU= +github.com/databricks/databricks-sdk-go v0.46.0 h1:D0TxmtSVAOsdnfzH4OGtAmcq+8TyA7Z6fA6JEYhupeY= +github.com/databricks/databricks-sdk-go v0.46.0/go.mod h1:ds+zbv5mlQG7nFEU5ojLtgN/u0/9YzZmKQES/CfedzU= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/internal/service/catalog_tf/model.go b/internal/service/catalog_tf/model.go index a71e0fa77e..e84b479703 100755 --- a/internal/service/catalog_tf/model.go +++ b/internal/service/catalog_tf/model.go @@ -445,7 +445,9 @@ type CreateMetastore struct { } type CreateMetastoreAssignment struct { - // The name of the default catalog in the metastore. + // The name of the default catalog in the metastore. This field is + // depracted. Please use "Default Namespace API" to configure the default + // catalog for a Databricks workspace. DefaultCatalogName types.String `tfsdk:"default_catalog_name" tf:""` // The unique ID of the metastore. MetastoreId types.String `tfsdk:"metastore_id" tf:""` @@ -2105,6 +2107,21 @@ type ReadVolumeRequest struct { Name types.String `tfsdk:"-"` } +type RegenerateDashboardRequest struct { + // Full name of the table. + TableName types.String `tfsdk:"-"` + // Optional argument to specify the warehouse for dashboard regeneration. If + // not specified, the first running warehouse will be used. + WarehouseId types.String `tfsdk:"warehouse_id" tf:"optional"` +} + +type RegenerateDashboardResponse struct { + // Id of the regenerated monitoring dashboard. + DashboardId types.String `tfsdk:"dashboard_id" tf:"optional"` + // The directory where the regenerated dashboard is stored. + ParentFolder types.String `tfsdk:"parent_folder" tf:"optional"` +} + // Registered model alias. type RegisteredModelAlias struct { // Name of the alias, e.g. 'champion' or 'latest_stable' @@ -2510,7 +2527,9 @@ type UpdateMetastore struct { } type UpdateMetastoreAssignment struct { - // The name of the default catalog for the metastore. + // The name of the default catalog in the metastore. This field is + // depracted. Please use "Default Namespace API" to configure the default + // catalog for a Databricks workspace. DefaultCatalogName types.String `tfsdk:"default_catalog_name" tf:"optional"` // The unique ID of the metastore. MetastoreId types.String `tfsdk:"metastore_id" tf:"optional"` diff --git a/internal/service/iam_tf/model.go b/internal/service/iam_tf/model.go index 4274dfc1c7..0d056da55b 100755 --- a/internal/service/iam_tf/model.go +++ b/internal/service/iam_tf/model.go @@ -178,9 +178,10 @@ type GetPermissionRequest struct { // The id of the request object. RequestObjectId types.String `tfsdk:"-"` // The type of the request object. Can be one of the following: alerts, - // authorization, clusters, cluster-policies, dbsql-dashboards, directories, - // experiments, files, instance-pools, jobs, notebooks, pipelines, queries, - // registered-models, repos, serving-endpoints, or warehouses. + // authorization, clusters, cluster-policies, dashboards, dbsql-dashboards, + // directories, experiments, files, instance-pools, jobs, notebooks, + // pipelines, queries, registered-models, repos, serving-endpoints, or + // warehouses. RequestObjectType types.String `tfsdk:"-"` } @@ -609,9 +610,10 @@ type PermissionsRequest struct { // The id of the request object. RequestObjectId types.String `tfsdk:"-"` // The type of the request object. Can be one of the following: alerts, - // authorization, clusters, cluster-policies, dbsql-dashboards, directories, - // experiments, files, instance-pools, jobs, notebooks, pipelines, queries, - // registered-models, repos, serving-endpoints, or warehouses. + // authorization, clusters, cluster-policies, dashboards, dbsql-dashboards, + // directories, experiments, files, instance-pools, jobs, notebooks, + // pipelines, queries, registered-models, repos, serving-endpoints, or + // warehouses. RequestObjectType types.String `tfsdk:"-"` } diff --git a/internal/service/jobs_tf/model.go b/internal/service/jobs_tf/model.go index 0ea0d45f4a..d5a1b57f58 100755 --- a/internal/service/jobs_tf/model.go +++ b/internal/service/jobs_tf/model.go @@ -137,8 +137,10 @@ type BaseRun struct { // task starts executing, for example, if the job is scheduled to run on a // new cluster, this is the time the cluster creation call is issued. StartTime types.Int64 `tfsdk:"start_time" tf:"optional"` - // The current state of the run. + // Deprecated. Please use the `status` field instead. State *RunState `tfsdk:"state" tf:"optional"` + // The current status of the run + Status *RunStatus `tfsdk:"status" tf:"optional"` // The list of tasks performed by the run. Each task has its own `run_id` // which you can use to call `JobsGetOutput` to retrieve the run resutls. Tasks []RunTask `tfsdk:"tasks" tf:"optional"` @@ -1183,6 +1185,19 @@ type PythonWheelTask struct { Parameters []types.String `tfsdk:"parameters" tf:"optional"` } +type QueueDetails struct { + // The reason for queuing the run. * `ACTIVE_RUNS_LIMIT_REACHED`: The run + // was queued due to reaching the workspace limit of active task runs. * + // `MAX_CONCURRENT_RUNS_REACHED`: The run was queued due to reaching the + // per-job limit of concurrent job runs. * + // `ACTIVE_RUN_JOB_TASKS_LIMIT_REACHED`: The run was queued due to reaching + // the workspace limit of active run job tasks. + Code types.String `tfsdk:"code" tf:"optional"` + // A descriptive message with the queuing details. This field is + // unstructured, and its exact format is subject to change. + Message types.String `tfsdk:"message" tf:"optional"` +} + type QueueSettings struct { // If true, enable queueing for the job. This is a required field. Enabled types.Bool `tfsdk:"enabled" tf:""` @@ -1196,8 +1211,10 @@ type RepairHistoryItem struct { Id types.Int64 `tfsdk:"id" tf:"optional"` // The start time of the (repaired) run. StartTime types.Int64 `tfsdk:"start_time" tf:"optional"` - // The current state of the run. + // Deprecated. Please use the `status` field instead. State *RunState `tfsdk:"state" tf:"optional"` + // The current status of the run + Status *RunStatus `tfsdk:"status" tf:"optional"` // The run IDs of the task runs that ran as part of this repair history // item. TaskRunIds []types.Int64 `tfsdk:"task_run_ids" tf:"optional"` @@ -1500,8 +1517,10 @@ type Run struct { // task starts executing, for example, if the job is scheduled to run on a // new cluster, this is the time the cluster creation call is issued. StartTime types.Int64 `tfsdk:"start_time" tf:"optional"` - // The current state of the run. + // Deprecated. Please use the `status` field instead. State *RunState `tfsdk:"state" tf:"optional"` + // The current status of the run + Status *RunStatus `tfsdk:"status" tf:"optional"` // The list of tasks performed by the run. Each task has its own `run_id` // which you can use to call `JobsGetOutput` to retrieve the run resutls. Tasks []RunTask `tfsdk:"tasks" tf:"optional"` @@ -1905,6 +1924,17 @@ type RunState struct { UserCancelledOrTimedout types.Bool `tfsdk:"user_cancelled_or_timedout" tf:"optional"` } +// The current status of the run +type RunStatus struct { + // If the run was queued, details about the reason for queuing the run. + QueueDetails *QueueDetails `tfsdk:"queue_details" tf:"optional"` + // The current state of the run. + State types.String `tfsdk:"state" tf:"optional"` + // If the run is in a TERMINATING or TERMINATED state, details about the + // reason for terminating the run. + TerminationDetails *TerminationDetails `tfsdk:"termination_details" tf:"optional"` +} + // Used when outputting a child run, in GetRun or ListRuns. type RunTask struct { // The sequence number of this run attempt for a triggered job run. The @@ -2050,8 +2080,10 @@ type RunTask struct { // task starts executing, for example, if the job is scheduled to run on a // new cluster, this is the time the cluster creation call is issued. StartTime types.Int64 `tfsdk:"start_time" tf:"optional"` - // The current state of the run. + // Deprecated. Please use the `status` field instead. State *RunState `tfsdk:"state" tf:"optional"` + // The current status of the run + Status *RunStatus `tfsdk:"status" tf:"optional"` // A unique name for the task. This field is used to refer to this task from // other tasks. This field is required and must be unique within its parent // job. On Update or Reset, this field is used to reference the tasks to be @@ -2619,6 +2651,66 @@ type TaskNotificationSettings struct { NoAlertForSkippedRuns types.Bool `tfsdk:"no_alert_for_skipped_runs" tf:"optional"` } +type TerminationDetails struct { + // The code indicates why the run was terminated. Additional codes might be + // introduced in future releases. * `SUCCESS`: The run was completed + // successfully. * `CANCELED`: The run was canceled during execution by the + // Databricks platform; for example, if the maximum run duration was + // exceeded. * `SKIPPED`: Run was never executed, for example, if the + // upstream task run failed, the dependency type condition was not met, or + // there were no material tasks to execute. * `INTERNAL_ERROR`: The run + // encountered an unexpected error. Refer to the state message for further + // details. * `DRIVER_ERROR`: The run encountered an error while + // communicating with the Spark Driver. * `CLUSTER_ERROR`: The run failed + // due to a cluster error. Refer to the state message for further details. * + // `REPOSITORY_CHECKOUT_FAILED`: Failed to complete the checkout due to an + // error when communicating with the third party service. * + // `INVALID_CLUSTER_REQUEST`: The run failed because it issued an invalid + // request to start the cluster. * `WORKSPACE_RUN_LIMIT_EXCEEDED`: The + // workspace has reached the quota for the maximum number of concurrent + // active runs. Consider scheduling the runs over a larger time frame. * + // `FEATURE_DISABLED`: The run failed because it tried to access a feature + // unavailable for the workspace. * `CLUSTER_REQUEST_LIMIT_EXCEEDED`: The + // number of cluster creation, start, and upsize requests have exceeded the + // allotted rate limit. Consider spreading the run execution over a larger + // time frame. * `STORAGE_ACCESS_ERROR`: The run failed due to an error when + // accessing the customer blob storage. Refer to the state message for + // further details. * `RUN_EXECUTION_ERROR`: The run was completed with task + // failures. For more details, refer to the state message or run output. * + // `UNAUTHORIZED_ERROR`: The run failed due to a permission issue while + // accessing a resource. Refer to the state message for further details. * + // `LIBRARY_INSTALLATION_ERROR`: The run failed while installing the + // user-requested library. Refer to the state message for further details. + // The causes might include, but are not limited to: The provided library is + // invalid, there are insufficient permissions to install the library, and + // so forth. * `MAX_CONCURRENT_RUNS_EXCEEDED`: The scheduled run exceeds the + // limit of maximum concurrent runs set for the job. * + // `MAX_SPARK_CONTEXTS_EXCEEDED`: The run is scheduled on a cluster that has + // already reached the maximum number of contexts it is configured to + // create. See: [Link]. * `RESOURCE_NOT_FOUND`: A resource necessary for run + // execution does not exist. Refer to the state message for further details. + // * `INVALID_RUN_CONFIGURATION`: The run failed due to an invalid + // configuration. Refer to the state message for further details. * + // `CLOUD_FAILURE`: The run failed due to a cloud provider issue. Refer to + // the state message for further details. * `MAX_JOB_QUEUE_SIZE_EXCEEDED`: + // The run was skipped due to reaching the job level queue size limit. + // + // [Link]: https://kb.databricks.com/en_US/notebooks/too-many-execution-contexts-are-open-right-now + Code types.String `tfsdk:"code" tf:"optional"` + // A descriptive message with the termination details. This field is + // unstructured and the format might change. + Message types.String `tfsdk:"message" tf:"optional"` + // * `SUCCESS`: The run terminated without any issues * `INTERNAL_ERROR`: An + // error occurred in the Databricks platform. Please look at the [status + // page] or contact support if the issue persists. * `CLIENT_ERROR`: The run + // was terminated because of an error caused by user input or the job + // configuration. * `CLOUD_FAILURE`: The run was terminated because of an + // issue with your cloud provider. + // + // [status page]: https://status.databricks.com/ + Type types.String `tfsdk:"type" tf:"optional"` +} + // Additional details about what triggered the run type TriggerInfo struct { // The run id of the Run Job task run diff --git a/internal/service/ml_tf/model.go b/internal/service/ml_tf/model.go index 1d7a2d71fe..e8735e8d51 100755 --- a/internal/service/ml_tf/model.go +++ b/internal/service/ml_tf/model.go @@ -735,7 +735,12 @@ type JobSpecWithoutSecret struct { // Get all artifacts type ListArtifactsRequest struct { - // Token indicating the page of artifact results to fetch + // Token indicating the page of artifact results to fetch. `page_token` is + // not supported when listing artifacts in UC Volumes. A maximum of 1000 + // artifacts will be retrieved for UC Volumes. Please call + // `/api/2.0/fs/directories{directory_path}` for listing artifacts in UC + // Volumes, which supports pagination. See [List directory contents | Files + // API](/api/workspace/files/listdirectorycontents). PageToken types.String `tfsdk:"-"` // Filter artifacts matching this path (a relative path from the root // artifact directory). diff --git a/internal/service/serving_tf/model.go b/internal/service/serving_tf/model.go index 9022705a63..c40d18ee63 100755 --- a/internal/service/serving_tf/model.go +++ b/internal/service/serving_tf/model.go @@ -795,6 +795,10 @@ type ServedModelInput struct { // ARN of the instance profile that the served model will use to access AWS // resources. InstanceProfileArn types.String `tfsdk:"instance_profile_arn" tf:"optional"` + // The maximum tokens per second that the endpoint can scale up to. + MaxProvisionedThroughput types.Int64 `tfsdk:"max_provisioned_throughput" tf:"optional"` + // The minimum tokens per second that the endpoint can scale down to. + MinProvisionedThroughput types.Int64 `tfsdk:"min_provisioned_throughput" tf:"optional"` // The name of the model in Databricks Model Registry to be served or if the // model resides in Unity Catalog, the full name of model, in the form of // __catalog_name__.__schema_name__.__model_name__. @@ -817,7 +821,7 @@ type ServedModelInput struct { // "Medium" (8 - 16 provisioned concurrency), and "Large" (16 - 64 // provisioned concurrency). If scale-to-zero is enabled, the lower bound of // the provisioned concurrency for each workload size will be 0. - WorkloadSize types.String `tfsdk:"workload_size" tf:""` + WorkloadSize types.String `tfsdk:"workload_size" tf:"optional"` // The workload type of the served model. The workload type selects which // type of compute to use in the endpoint. The default value for this // parameter is "CPU". For deep learning workloads, GPU acceleration is diff --git a/internal/service/vectorsearch_tf/model.go b/internal/service/vectorsearch_tf/model.go index 3eb342a87f..494b51cbc6 100755 --- a/internal/service/vectorsearch_tf/model.go +++ b/internal/service/vectorsearch_tf/model.go @@ -97,6 +97,11 @@ type DeleteIndexResponse struct { } type DeltaSyncVectorIndexSpecRequest struct { + // [Optional] Select the columns to sync with the vector index. If you leave + // this field blank, all columns from the source table are synced with the + // index. The primary key column and embedding source column or embedding + // vector column are always synced. + ColumnsToSync []types.String `tfsdk:"columns_to_sync" tf:"optional"` // The columns that contain the embedding source. EmbeddingSourceColumns []EmbeddingSourceColumn `tfsdk:"embedding_source_columns" tf:"optional"` // The columns that contain the embedding vectors. The format should be From 375539af974e76224fd6da8a719218a8b95f7605 Mon Sep 17 00:00:00 2001 From: Alex Ott Date: Wed, 11 Sep 2024 12:51:47 +0200 Subject: [PATCH 25/54] [Doc] Update `databricks_vector_search_index` docs to match latest SDK (#4008) ## Changes Should be merged after #4007 ## Tests - [ ] `make test` run locally - [x] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [ ] using Go SDK --- docs/resources/vector_search_index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/resources/vector_search_index.md b/docs/resources/vector_search_index.md index abf17447fb..0de0ac2c1f 100644 --- a/docs/resources/vector_search_index.md +++ b/docs/resources/vector_search_index.md @@ -38,6 +38,7 @@ The following arguments are supported (change of any parameter leads to recreati * `DIRECT_ACCESS`: An index that supports the direct read and write of vectors and metadata through our REST and SDK APIs. With this model, the user manages index updates. * `delta_sync_index_spec` - (object) Specification for Delta Sync Index. Required if `index_type` is `DELTA_SYNC`. * `source_table` (required) The name of the source table. + * `columns_to_sync` - (optional) list of columns to sync. If not specified, all columns are syncronized. * `embedding_source_columns` - (required if `embedding_vector_columns` isn't provided) array of objects representing columns that contain the embedding source. Each entry consists of: * `name` - The name of the column * `embedding_model_endpoint_name` - The name of the embedding model endpoint From 2c6b876fd9f6c38dee8e465849003e758c70423d Mon Sep 17 00:00:00 2001 From: Edward Feng <67326663+edwardfeng-db@users.noreply.github.com> Date: Thu, 12 Sep 2024 13:16:04 +0200 Subject: [PATCH 26/54] [Internal] Add `AddPlanModifer` method for AttributeBuilder (#4009) ## Changes - Add `AddPlanModifier` methods for all AttributeBuilders so that we can do things equivalent to set supress diff or force new ## Tests - [x] `make test` run locally - [x] relevant change in `docs/` folder - [x] covered with integration tests in `internal/acceptance` - [x] relevant acceptance tests are passing - [x] using Go SDK --- .../pluginfw/tfschema/bool_attribute.go | 8 +++++ .../pluginfw/tfschema/customizable_schema.go | 32 +++++++++++++++++++ .../tfschema/customizable_schema_test.go | 10 ++++++ .../pluginfw/tfschema/float64_attribute.go | 8 +++++ .../pluginfw/tfschema/int64_attribute.go | 8 +++++ .../pluginfw/tfschema/list_attribute.go | 8 +++++ .../tfschema/list_nested_attribute.go | 8 +++++ .../pluginfw/tfschema/map_attribute.go | 8 +++++ .../pluginfw/tfschema/map_nested_attribute.go | 8 +++++ .../tfschema/single_nested_attribute.go | 8 +++++ .../pluginfw/tfschema/string_attribute.go | 8 +++++ 11 files changed, 114 insertions(+) diff --git a/internal/providers/pluginfw/tfschema/bool_attribute.go b/internal/providers/pluginfw/tfschema/bool_attribute.go index 1b9f6b8919..5dc4727293 100644 --- a/internal/providers/pluginfw/tfschema/bool_attribute.go +++ b/internal/providers/pluginfw/tfschema/bool_attribute.go @@ -3,6 +3,7 @@ package tfschema import ( dataschema "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" "github.com/hashicorp/terraform-plugin-framework/schema/validator" ) @@ -13,6 +14,7 @@ type BoolAttributeBuilder struct { Computed bool DeprecationMessage string Validators []validator.Bool + PlanModifiers []planmodifier.Bool } func (a BoolAttributeBuilder) BuildDataSourceAttribute() dataschema.Attribute { @@ -34,6 +36,7 @@ func (a BoolAttributeBuilder) BuildResourceAttribute() schema.Attribute { DeprecationMessage: a.DeprecationMessage, Computed: a.Computed, Validators: a.Validators, + PlanModifiers: a.PlanModifiers, } } @@ -90,3 +93,8 @@ func (a BoolAttributeBuilder) AddValidator(v validator.Bool) AttributeBuilder { a.Validators = append(a.Validators, v) return a } + +func (a BoolAttributeBuilder) AddPlanModifier(v planmodifier.Bool) AttributeBuilder { + a.PlanModifiers = append(a.PlanModifiers, v) + return a +} diff --git a/internal/providers/pluginfw/tfschema/customizable_schema.go b/internal/providers/pluginfw/tfschema/customizable_schema.go index 129d8b161a..4f29f7765e 100644 --- a/internal/providers/pluginfw/tfschema/customizable_schema.go +++ b/internal/providers/pluginfw/tfschema/customizable_schema.go @@ -5,6 +5,7 @@ import ( "reflect" "github.com/databricks/terraform-provider-databricks/common" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" "github.com/hashicorp/terraform-plugin-framework/schema/validator" ) @@ -72,6 +73,37 @@ func (s *CustomizableSchema) AddValidator(v any, path ...string) *CustomizableSc return s } +func (s *CustomizableSchema) AddPlanModifier(v any, path ...string) *CustomizableSchema { + cb := func(attr AttributeBuilder) AttributeBuilder { + switch a := attr.(type) { + case BoolAttributeBuilder: + return a.AddPlanModifier(v.(planmodifier.Bool)) + case Float64AttributeBuilder: + return a.AddPlanModifier(v.(planmodifier.Float64)) + case Int64AttributeBuilder: + return a.AddPlanModifier(v.(planmodifier.Int64)) + case ListAttributeBuilder: + return a.AddPlanModifier(v.(planmodifier.List)) + case ListNestedAttributeBuilder: + return a.AddPlanModifier(v.(planmodifier.List)) + case MapAttributeBuilder: + return a.AddPlanModifier(v.(planmodifier.Map)) + case MapNestedAttributeBuilder: + return a.AddPlanModifier(v.(planmodifier.Map)) + case SingleNestedAttributeBuilder: + return a.AddPlanModifier(v.(planmodifier.Object)) + case StringAttributeBuilder: + return a.AddPlanModifier(v.(planmodifier.String)) + default: + panic(fmt.Errorf("cannot add planmodifier, attribute builder type is invalid: %s. %s", reflect.TypeOf(attr).String(), common.TerraformBugErrorMessage)) + } + } + + navigateSchemaWithCallback(&s.attr, cb, path...) + + return s +} + func (s *CustomizableSchema) SetOptional(path ...string) *CustomizableSchema { cb := func(attr AttributeBuilder) AttributeBuilder { return attr.SetOptional() diff --git a/internal/providers/pluginfw/tfschema/customizable_schema_test.go b/internal/providers/pluginfw/tfschema/customizable_schema_test.go index fc8a2078fb..e134b47c2a 100644 --- a/internal/providers/pluginfw/tfschema/customizable_schema_test.go +++ b/internal/providers/pluginfw/tfschema/customizable_schema_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/stretchr/testify/assert" @@ -111,3 +112,12 @@ func TestCustomizeSchemaAddValidator(t *testing.T) { assert.True(t, len(scm.Attributes["description"].(schema.StringAttribute).Validators) == 1) } + +func TestCustomizeSchemaAddPlanModifier(t *testing.T) { + scm := ResourceStructToSchema(TestTfSdk{}, func(c CustomizableSchema) CustomizableSchema { + c.AddPlanModifier(stringplanmodifier.RequiresReplace(), "description") + return c + }) + + assert.True(t, len(scm.Attributes["description"].(schema.StringAttribute).PlanModifiers) == 1) +} diff --git a/internal/providers/pluginfw/tfschema/float64_attribute.go b/internal/providers/pluginfw/tfschema/float64_attribute.go index 43bfaf4830..913b747431 100644 --- a/internal/providers/pluginfw/tfschema/float64_attribute.go +++ b/internal/providers/pluginfw/tfschema/float64_attribute.go @@ -3,6 +3,7 @@ package tfschema import ( dataschema "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" "github.com/hashicorp/terraform-plugin-framework/schema/validator" ) @@ -13,6 +14,7 @@ type Float64AttributeBuilder struct { Computed bool DeprecationMessage string Validators []validator.Float64 + PlanModifiers []planmodifier.Float64 } func (a Float64AttributeBuilder) BuildDataSourceAttribute() dataschema.Attribute { @@ -34,6 +36,7 @@ func (a Float64AttributeBuilder) BuildResourceAttribute() schema.Attribute { DeprecationMessage: a.DeprecationMessage, Computed: a.Computed, Validators: a.Validators, + PlanModifiers: a.PlanModifiers, } } @@ -90,3 +93,8 @@ func (a Float64AttributeBuilder) AddValidator(v validator.Float64) AttributeBuil a.Validators = append(a.Validators, v) return a } + +func (a Float64AttributeBuilder) AddPlanModifier(v planmodifier.Float64) AttributeBuilder { + a.PlanModifiers = append(a.PlanModifiers, v) + return a +} diff --git a/internal/providers/pluginfw/tfschema/int64_attribute.go b/internal/providers/pluginfw/tfschema/int64_attribute.go index e9311c3a07..5c8bd9693e 100644 --- a/internal/providers/pluginfw/tfschema/int64_attribute.go +++ b/internal/providers/pluginfw/tfschema/int64_attribute.go @@ -3,6 +3,7 @@ package tfschema import ( dataschema "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" "github.com/hashicorp/terraform-plugin-framework/schema/validator" ) @@ -13,6 +14,7 @@ type Int64AttributeBuilder struct { Computed bool DeprecationMessage string Validators []validator.Int64 + PlanModifiers []planmodifier.Int64 } func (a Int64AttributeBuilder) BuildDataSourceAttribute() dataschema.Attribute { @@ -34,6 +36,7 @@ func (a Int64AttributeBuilder) BuildResourceAttribute() schema.Attribute { DeprecationMessage: a.DeprecationMessage, Computed: a.Computed, Validators: a.Validators, + PlanModifiers: a.PlanModifiers, } } @@ -90,3 +93,8 @@ func (a Int64AttributeBuilder) AddValidator(v validator.Int64) AttributeBuilder a.Validators = append(a.Validators, v) return a } + +func (a Int64AttributeBuilder) AddPlanModifier(v planmodifier.Int64) AttributeBuilder { + a.PlanModifiers = append(a.PlanModifiers, v) + return a +} diff --git a/internal/providers/pluginfw/tfschema/list_attribute.go b/internal/providers/pluginfw/tfschema/list_attribute.go index 5a822179ba..6e58165996 100644 --- a/internal/providers/pluginfw/tfschema/list_attribute.go +++ b/internal/providers/pluginfw/tfschema/list_attribute.go @@ -4,6 +4,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/attr" dataschema "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" "github.com/hashicorp/terraform-plugin-framework/schema/validator" ) @@ -16,6 +17,7 @@ type ListAttributeBuilder struct { Computed bool DeprecationMessage string Validators []validator.List + PlanModifiers []planmodifier.List } func (a ListAttributeBuilder) BuildDataSourceAttribute() dataschema.Attribute { @@ -39,6 +41,7 @@ func (a ListAttributeBuilder) BuildResourceAttribute() schema.Attribute { DeprecationMessage: a.DeprecationMessage, Computed: a.Computed, Validators: a.Validators, + PlanModifiers: a.PlanModifiers, } } @@ -95,3 +98,8 @@ func (a ListAttributeBuilder) AddValidator(v validator.List) AttributeBuilder { a.Validators = append(a.Validators, v) return a } + +func (a ListAttributeBuilder) AddPlanModifier(v planmodifier.List) AttributeBuilder { + a.PlanModifiers = append(a.PlanModifiers, v) + return a +} diff --git a/internal/providers/pluginfw/tfschema/list_nested_attribute.go b/internal/providers/pluginfw/tfschema/list_nested_attribute.go index ab0adb38d4..5d80ec8500 100644 --- a/internal/providers/pluginfw/tfschema/list_nested_attribute.go +++ b/internal/providers/pluginfw/tfschema/list_nested_attribute.go @@ -3,6 +3,7 @@ package tfschema import ( dataschema "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" "github.com/hashicorp/terraform-plugin-framework/schema/validator" ) @@ -15,6 +16,7 @@ type ListNestedAttributeBuilder struct { Computed bool DeprecationMessage string Validators []validator.List + PlanModifiers []planmodifier.List } func (a ListNestedAttributeBuilder) BuildDataSourceAttribute() dataschema.Attribute { @@ -38,6 +40,7 @@ func (a ListNestedAttributeBuilder) BuildResourceAttribute() schema.Attribute { DeprecationMessage: a.DeprecationMessage, Computed: a.Computed, Validators: a.Validators, + PlanModifiers: a.PlanModifiers, } } @@ -94,3 +97,8 @@ func (a ListNestedAttributeBuilder) AddValidator(v validator.List) AttributeBuil a.Validators = append(a.Validators, v) return a } + +func (a ListNestedAttributeBuilder) AddPlanModifier(v planmodifier.List) AttributeBuilder { + a.PlanModifiers = append(a.PlanModifiers, v) + return a +} diff --git a/internal/providers/pluginfw/tfschema/map_attribute.go b/internal/providers/pluginfw/tfschema/map_attribute.go index f02d1c55b8..3793b444bb 100644 --- a/internal/providers/pluginfw/tfschema/map_attribute.go +++ b/internal/providers/pluginfw/tfschema/map_attribute.go @@ -4,6 +4,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/attr" dataschema "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" "github.com/hashicorp/terraform-plugin-framework/schema/validator" ) @@ -16,6 +17,7 @@ type MapAttributeBuilder struct { Computed bool DeprecationMessage string Validators []validator.Map + PlanModifiers []planmodifier.Map } func (a MapAttributeBuilder) BuildDataSourceAttribute() dataschema.Attribute { @@ -39,6 +41,7 @@ func (a MapAttributeBuilder) BuildResourceAttribute() schema.Attribute { DeprecationMessage: a.DeprecationMessage, Computed: a.Computed, Validators: a.Validators, + PlanModifiers: a.PlanModifiers, } } @@ -95,3 +98,8 @@ func (a MapAttributeBuilder) AddValidator(v validator.Map) AttributeBuilder { a.Validators = append(a.Validators, v) return a } + +func (a MapAttributeBuilder) AddPlanModifier(v planmodifier.Map) AttributeBuilder { + a.PlanModifiers = append(a.PlanModifiers, v) + return a +} diff --git a/internal/providers/pluginfw/tfschema/map_nested_attribute.go b/internal/providers/pluginfw/tfschema/map_nested_attribute.go index 1c13bfc23e..bfcf5da968 100644 --- a/internal/providers/pluginfw/tfschema/map_nested_attribute.go +++ b/internal/providers/pluginfw/tfschema/map_nested_attribute.go @@ -3,6 +3,7 @@ package tfschema import ( dataschema "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" "github.com/hashicorp/terraform-plugin-framework/schema/validator" ) @@ -15,6 +16,7 @@ type MapNestedAttributeBuilder struct { Computed bool DeprecationMessage string Validators []validator.Map + PlanModifiers []planmodifier.Map } func (a MapNestedAttributeBuilder) BuildDataSourceAttribute() dataschema.Attribute { @@ -38,6 +40,7 @@ func (a MapNestedAttributeBuilder) BuildResourceAttribute() schema.Attribute { DeprecationMessage: a.DeprecationMessage, Computed: a.Computed, Validators: a.Validators, + PlanModifiers: a.PlanModifiers, } } @@ -94,3 +97,8 @@ func (a MapNestedAttributeBuilder) AddValidator(v validator.Map) AttributeBuilde a.Validators = append(a.Validators, v) return a } + +func (a MapNestedAttributeBuilder) AddPlanModifier(v planmodifier.Map) AttributeBuilder { + a.PlanModifiers = append(a.PlanModifiers, v) + return a +} diff --git a/internal/providers/pluginfw/tfschema/single_nested_attribute.go b/internal/providers/pluginfw/tfschema/single_nested_attribute.go index 95e0122167..ee234db903 100644 --- a/internal/providers/pluginfw/tfschema/single_nested_attribute.go +++ b/internal/providers/pluginfw/tfschema/single_nested_attribute.go @@ -3,6 +3,7 @@ package tfschema import ( dataschema "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" "github.com/hashicorp/terraform-plugin-framework/schema/validator" ) @@ -15,6 +16,7 @@ type SingleNestedAttributeBuilder struct { Computed bool DeprecationMessage string Validators []validator.Object + PlanModifiers []planmodifier.Object } func (a SingleNestedAttributeBuilder) BuildDataSourceAttribute() dataschema.Attribute { @@ -38,6 +40,7 @@ func (a SingleNestedAttributeBuilder) BuildResourceAttribute() schema.Attribute DeprecationMessage: a.DeprecationMessage, Computed: a.Computed, Validators: a.Validators, + PlanModifiers: a.PlanModifiers, } } @@ -94,3 +97,8 @@ func (a SingleNestedAttributeBuilder) AddValidator(v validator.Object) Attribute a.Validators = append(a.Validators, v) return a } + +func (a SingleNestedAttributeBuilder) AddPlanModifier(v planmodifier.Object) AttributeBuilder { + a.PlanModifiers = append(a.PlanModifiers, v) + return a +} diff --git a/internal/providers/pluginfw/tfschema/string_attribute.go b/internal/providers/pluginfw/tfschema/string_attribute.go index 7656f1a1a4..6b81b939f6 100644 --- a/internal/providers/pluginfw/tfschema/string_attribute.go +++ b/internal/providers/pluginfw/tfschema/string_attribute.go @@ -3,6 +3,7 @@ package tfschema import ( dataschema "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" "github.com/hashicorp/terraform-plugin-framework/schema/validator" ) @@ -13,6 +14,7 @@ type StringAttributeBuilder struct { Computed bool DeprecationMessage string Validators []validator.String + PlanModifiers []planmodifier.String } func (a StringAttributeBuilder) BuildDataSourceAttribute() dataschema.Attribute { @@ -34,6 +36,7 @@ func (a StringAttributeBuilder) BuildResourceAttribute() schema.Attribute { DeprecationMessage: a.DeprecationMessage, Computed: a.Computed, Validators: a.Validators, + PlanModifiers: a.PlanModifiers, } } @@ -90,3 +93,8 @@ func (a StringAttributeBuilder) AddValidator(v validator.String) AttributeBuilde a.Validators = append(a.Validators, v) return a } + +func (a StringAttributeBuilder) AddPlanModifier(v planmodifier.String) AttributeBuilder { + a.PlanModifiers = append(a.PlanModifiers, v) + return a +} From e8ce7e7e5f82d5cef5f02bac87dc5d50c744bd86 Mon Sep 17 00:00:00 2001 From: Edward Feng <67326663+edwardfeng-db@users.noreply.github.com> Date: Thu, 12 Sep 2024 18:19:02 +0200 Subject: [PATCH 27/54] [Feature] Library plugin framework migration (#3979) ## Changes - Add library resource to plugin framework, not officially migrating because it has suffix `_pluginframework` - Added integration test for creation and importing ## Tests - [x] `make test` run locally - [x] relevant change in `docs/` folder - [x] covered with integration tests in `internal/acceptance` - [x] relevant acceptance tests are passing - [x] using Go SDK --- internal/providers/pluginfw/pluginfw.go | 2 + .../resources/library/resource_library.go | 226 ++++++++++++++++++ .../library/resource_library_test.go | 92 +++++++ 3 files changed, 320 insertions(+) create mode 100644 internal/providers/pluginfw/resources/library/resource_library.go create mode 100644 internal/providers/pluginfw/resources/library/resource_library_test.go diff --git a/internal/providers/pluginfw/pluginfw.go b/internal/providers/pluginfw/pluginfw.go index 80ba2288cf..d09ec16e4a 100644 --- a/internal/providers/pluginfw/pluginfw.go +++ b/internal/providers/pluginfw/pluginfw.go @@ -16,6 +16,7 @@ import ( "github.com/databricks/terraform-provider-databricks/commands" "github.com/databricks/terraform-provider-databricks/common" providercommon "github.com/databricks/terraform-provider-databricks/internal/providers/common" + "github.com/databricks/terraform-provider-databricks/internal/providers/pluginfw/resources/library" "github.com/databricks/terraform-provider-databricks/internal/providers/pluginfw/resources/qualitymonitor" "github.com/databricks/terraform-provider-databricks/internal/providers/pluginfw/resources/volume" @@ -42,6 +43,7 @@ var _ provider.Provider = (*DatabricksProviderPluginFramework)(nil) func (p *DatabricksProviderPluginFramework) Resources(ctx context.Context) []func() resource.Resource { return []func() resource.Resource{ qualitymonitor.ResourceQualityMonitor, + library.ResourceLibrary, } } diff --git a/internal/providers/pluginfw/resources/library/resource_library.go b/internal/providers/pluginfw/resources/library/resource_library.go new file mode 100644 index 0000000000..2c452131a4 --- /dev/null +++ b/internal/providers/pluginfw/resources/library/resource_library.go @@ -0,0 +1,226 @@ +package library + +import ( + "context" + "fmt" + "time" + + "github.com/databricks/databricks-sdk-go/service/compute" + "github.com/databricks/terraform-provider-databricks/clusters" + "github.com/databricks/terraform-provider-databricks/common" + pluginfwcommon "github.com/databricks/terraform-provider-databricks/internal/providers/pluginfw/common" + "github.com/databricks/terraform-provider-databricks/internal/providers/pluginfw/converters" + "github.com/databricks/terraform-provider-databricks/internal/providers/pluginfw/tfschema" + "github.com/databricks/terraform-provider-databricks/internal/service/compute_tf" + "github.com/databricks/terraform-provider-databricks/libraries" + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/objectplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/types" + + "github.com/databricks/databricks-sdk-go" +) + +const libraryDefaultInstallationTimeout = 15 * time.Minute + +var _ resource.ResourceWithConfigure = &LibraryResource{} + +func ResourceLibrary() resource.Resource { + return &LibraryResource{} +} + +func readLibrary(ctx context.Context, w *databricks.WorkspaceClient, waitParams compute.Wait, libraryRep string, libraryExtended *LibraryExtended) diag.Diagnostics { + res, err := libraries.WaitForLibrariesInstalledSdk(ctx, w, waitParams, libraryDefaultInstallationTimeout) + if err != nil { + return diag.Diagnostics{diag.NewErrorDiagnostic("failed to wait for library installation", err.Error())} + } + + for _, v := range res.LibraryStatuses { + thisRep := v.Library.String() + if thisRep == libraryRep { + // This is not entirely necessary as we can directly write the fields in the config into the state, because there's no computed field. + diags := converters.GoSdkToTfSdkStruct(ctx, v.Library, libraryExtended) + + if diags.HasError() { + return diags + } + + libraryExtended.ClusterId = types.StringValue(waitParams.ClusterID) + + return nil + } + } + return diag.Diagnostics{diag.NewErrorDiagnostic("failed to find the installed library", fmt.Sprintf("failed to find %s on %s", libraryRep, waitParams.ClusterID))} +} + +type LibraryExtended struct { + compute_tf.Library + ClusterId types.String `tfsdk:"cluster_id"` +} + +type LibraryResource struct { + Client *common.DatabricksClient +} + +func (r *LibraryResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = "databricks_library_pluginframework" +} + +func (r *LibraryResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Description: "Terraform schema for Databricks Library", + Attributes: tfschema.ResourceStructToSchemaMap(LibraryExtended{}, func(c tfschema.CustomizableSchema) tfschema.CustomizableSchema { + // c.AddPlanModifier(stringplanmodifier.RequiresReplace(), "cluster_id") + // c.AddPlanModifier(objectplanmodifier.RequiresReplace(), "cran") + // c.AddPlanModifier(stringplanmodifier.RequiresReplace(), "egg") + // c.AddPlanModifier(stringplanmodifier.RequiresReplace(), "jar") + // c.AddPlanModifier(objectplanmodifier.RequiresReplace(), "maven") + // c.AddPlanModifier(objectplanmodifier.RequiresReplace(), "pypi") + // c.AddPlanModifier(stringplanmodifier.RequiresReplace(), "requirements") + // c.AddPlanModifier(stringplanmodifier.RequiresReplace(), "whl") + for field, attribute := range c.ToAttributeMap() { + switch attribute.(type) { + case tfschema.StringAttributeBuilder: + c.AddPlanModifier(stringplanmodifier.RequiresReplace(), field) + case tfschema.SingleNestedAttributeBuilder: + c.AddPlanModifier(objectplanmodifier.RequiresReplace(), field) + } + } + return c + }), + } +} + +func (r *LibraryResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { + if r.Client == nil { + r.Client = pluginfwcommon.ConfigureResource(req, resp) + } +} + +func (r *LibraryResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + w, diags := r.Client.GetWorkspaceClient() + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + var libraryTfSDK LibraryExtended + resp.Diagnostics.Append(req.Plan.Get(ctx, &libraryTfSDK)...) + if resp.Diagnostics.HasError() { + return + } + + var libGoSDK compute.Library + resp.Diagnostics.Append(converters.TfSdkToGoSdkStruct(ctx, libraryTfSDK, &libGoSDK)...) + if resp.Diagnostics.HasError() { + return + } + installLib := compute.InstallLibraries{ + Libraries: []compute.Library{libGoSDK}, + } + req.Plan.GetAttribute(ctx, path.Root("cluster_id"), &installLib.ClusterId) + err := w.Libraries.Install(ctx, installLib) + if err != nil { + resp.Diagnostics.AddError("failed to install library", err.Error()) + return + } + waitParams := compute.Wait{ + ClusterID: installLib.ClusterId, + IsRunning: true, + } + libraryRep := libGoSDK.String() + installedLib := LibraryExtended{} + + resp.Diagnostics.Append(readLibrary(ctx, w, waitParams, libraryRep, &installedLib)...) + + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, installedLib)...) +} + +func (r *LibraryResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + w, diags := r.Client.GetWorkspaceClient() + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + var libraryTfSDK LibraryExtended + resp.Diagnostics.Append(req.State.Get(ctx, &libraryTfSDK)...) + if resp.Diagnostics.HasError() { + return + } + var libGoSDK compute.Library + resp.Diagnostics.Append(converters.TfSdkToGoSdkStruct(ctx, libraryTfSDK, &libGoSDK)...) + if resp.Diagnostics.HasError() { + return + } + clusterId := libraryTfSDK.ClusterId.ValueString() + libraryRep := libGoSDK.String() + installedLib := LibraryExtended{} + waitParams := compute.Wait{ + ClusterID: clusterId, + IsRefresh: true, + } + + resp.Diagnostics.Append(readLibrary(ctx, w, waitParams, libraryRep, &installedLib)...) + + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, installedLib)...) +} + +func (r *LibraryResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + resp.Diagnostics.AddError("failed to update library", "updating library is not supported") +} + +func (r *LibraryResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + w, diags := r.Client.GetWorkspaceClient() + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + var libraryTfSDK LibraryExtended + resp.Diagnostics.Append(req.State.Get(ctx, &libraryTfSDK)...) + if resp.Diagnostics.HasError() { + return + } + clusterID := libraryTfSDK.ClusterId.ValueString() + var libGoSDK compute.Library + resp.Diagnostics.Append(converters.TfSdkToGoSdkStruct(ctx, libraryTfSDK, &libGoSDK)...) + if resp.Diagnostics.HasError() { + return + } + libraryRep := libGoSDK.String() + _, err := clusters.StartClusterAndGetInfo(ctx, w, clusterID) + if err != nil { + resp.Diagnostics.AddError("failed to start and get cluster", err.Error()) + return + } + cll, err := w.Libraries.ClusterStatusByClusterId(ctx, clusterID) + if err != nil { + resp.Diagnostics.AddError("failed to get libraries", err.Error()) + return + } + for _, v := range cll.LibraryStatuses { + if v.Library.String() != libraryRep { + continue + } + err := w.Libraries.Uninstall(ctx, compute.UninstallLibraries{ + ClusterId: clusterID, + Libraries: []compute.Library{*v.Library}, + }) + if err != nil { + resp.Diagnostics.AddError("failed to uninstall library", err.Error()) + } + return + } + // Keeping the implementation to be consistent with the sdk-v2 implementation. Eventually we should update this to be not + // an error, for cases such as the library being manually uninstalled. + resp.Diagnostics.AddError("failed to uninstall library", fmt.Sprintf("failed to find %s on %s", libraryRep, clusterID)) +} diff --git a/internal/providers/pluginfw/resources/library/resource_library_test.go b/internal/providers/pluginfw/resources/library/resource_library_test.go new file mode 100644 index 0000000000..96e699d85d --- /dev/null +++ b/internal/providers/pluginfw/resources/library/resource_library_test.go @@ -0,0 +1,92 @@ +package library_test + +import ( + "testing" + + "github.com/databricks/terraform-provider-databricks/internal/acceptance" +) + +func TestAccLibraryCreationPluginFramework(t *testing.T) { + acceptance.WorkspaceLevel(t, acceptance.Step{ + Template: `data "databricks_spark_version" "latest" { + } + resource "databricks_cluster" "this" { + cluster_name = "test-library-{var.RANDOM}" + spark_version = data.databricks_spark_version.latest.id + instance_pool_id = "{env.TEST_INSTANCE_POOL_ID}" + autotermination_minutes = 10 + num_workers = 0 + spark_conf = { + "spark.databricks.cluster.profile" = "singleNode" + "spark.master" = "local[*]" + } + custom_tags = { + "ResourceClass" = "SingleNode" + } + } + resource "databricks_library_pluginframework" "new_library" { + cluster_id = databricks_cluster.this.id + pypi = { + repo = "https://pypi.org/dummy" + package = "databricks-sdk" + } + } + `, + }) +} + +func TestAccLibraryUpdatePluginFramework(t *testing.T) { + acceptance.WorkspaceLevel(t, + acceptance.Step{ + Template: `data "databricks_spark_version" "latest" { + } + resource "databricks_cluster" "this" { + cluster_name = "cluster-{var.STICKY_RANDOM}" + spark_version = data.databricks_spark_version.latest.id + instance_pool_id = "{env.TEST_INSTANCE_POOL_ID}" + autotermination_minutes = 10 + num_workers = 0 + spark_conf = { + "spark.databricks.cluster.profile" = "singleNode" + "spark.master" = "local[*]" + } + custom_tags = { + "ResourceClass" = "SingleNode" + } + } + resource "databricks_library_pluginframework" "new_library" { + cluster_id = databricks_cluster.this.id + pypi = { + repo = "https://pypi.org/simple" + package = "databricks-sdk" + } + } + `, + }, + acceptance.Step{ + Template: `data "databricks_spark_version" "latest" { + } + resource "databricks_cluster" "this" { + cluster_name = "cluster-{var.STICKY_RANDOM}" + spark_version = data.databricks_spark_version.latest.id + instance_pool_id = "{env.TEST_INSTANCE_POOL_ID}" + autotermination_minutes = 10 + num_workers = 0 + spark_conf = { + "spark.databricks.cluster.profile" = "singleNode" + "spark.master" = "local[*]" + } + custom_tags = { + "ResourceClass" = "SingleNode" + } + } + resource "databricks_library_pluginframework" "new_library" { + cluster_id = databricks_cluster.this.id + pypi = { + package = "networkx" + } + } + `, + }, + ) +} From d3120159b2a19d00f26a37761463139ac4a623f2 Mon Sep 17 00:00:00 2001 From: Tanmay Rustagi <88379306+tanmay-db@users.noreply.github.com> Date: Fri, 13 Sep 2024 13:25:45 +0200 Subject: [PATCH 28/54] [Internal] Fix irregularities in plugin framework converter function errors (#4010) ## Changes I noticed few irregularities in converter functions while working on clusters plugin framework migration, creating a PR to address those: 1. Typo in error message -- in `GoSdkToTfSdkStruct` we say: `tfsdk to gosdk struct conversion failure`. It should be `gosdk to tfsdk struct conversion failure` 2. In `GoSdkToTfSdkStruct ` we don't specify destination value type but we do it in `TfSdkToGoSdkStruct`. 3. Abstract the error message out to reduce redundancy 4. Standardise similar types of error messages to be same so it's easier to maintain. ## Tests Added unit tests. - [ ] `make test` run locally - [ ] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [ ] using Go SDK --- .../pluginfw/converters/converters_test.go | 19 +++++++++++++++++++ .../providers/pluginfw/converters/go_to_tf.go | 13 ++++++++----- .../providers/pluginfw/converters/tf_to_go.go | 13 ++++++++----- 3 files changed, 35 insertions(+), 10 deletions(-) diff --git a/internal/providers/pluginfw/converters/converters_test.go b/internal/providers/pluginfw/converters/converters_test.go index 7b87cc8b5f..7758345ad1 100644 --- a/internal/providers/pluginfw/converters/converters_test.go +++ b/internal/providers/pluginfw/converters/converters_test.go @@ -6,6 +6,7 @@ import ( "reflect" "testing" + "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/stretchr/testify/assert" ) @@ -100,6 +101,24 @@ func RunConverterTest(t *testing.T, description string, tfSdkStruct DummyTfSdk, assert.True(t, reflect.DeepEqual(convertedTfSdkStruct, tfSdkStruct), fmt.Sprintf("gosdk to tfsdk conversion - %s", description)) } +func TestTfSdkToGoSdkStructConversionFailure(t *testing.T) { + tfSdkStruct := DummyTfSdk{} + goSdkStruct := DummyGoSdk{} + actualDiagnostics := TfSdkToGoSdkStruct(context.Background(), tfSdkStruct, goSdkStruct) + expectedDiagnostics := diag.Diagnostics{diag.NewErrorDiagnostic(tfSdkToGoSdkStructConversionFailureMessage, "please provide a pointer for the gosdk struct, got DummyGoSdk")} + assert.True(t, actualDiagnostics.HasError()) + assert.True(t, actualDiagnostics.Equal(expectedDiagnostics)) +} + +func TestGoSdkToTfSdkStructConversionFailure(t *testing.T) { + tfSdkStruct := DummyTfSdk{} + goSdkStruct := DummyGoSdk{} + actualDiagnostics := GoSdkToTfSdkStruct(context.Background(), goSdkStruct, tfSdkStruct) + expectedDiagnostics := diag.Diagnostics{diag.NewErrorDiagnostic(goSdkToTfSdkStructConversionFailureMessage, "please provide a pointer for the tfsdk struct, got DummyTfSdk")} + assert.True(t, actualDiagnostics.HasError()) + assert.True(t, actualDiagnostics.Equal(expectedDiagnostics)) +} + var tests = []struct { name string tfSdkStruct DummyTfSdk diff --git a/internal/providers/pluginfw/converters/go_to_tf.go b/internal/providers/pluginfw/converters/go_to_tf.go index ba924e5936..5e39086868 100644 --- a/internal/providers/pluginfw/converters/go_to_tf.go +++ b/internal/providers/pluginfw/converters/go_to_tf.go @@ -13,6 +13,9 @@ import ( "github.com/databricks/terraform-provider-databricks/internal/tfreflect" ) +const goSdkToTfSdkStructConversionFailureMessage = "gosdk to tfsdk struct conversion failure" +const goSdkToTfSdkFieldConversionFailureMessage = "gosdk to tfsdk field conversion failure" + // GoSdkToTfSdkStruct converts a gosdk struct into a tfsdk struct, with the folowing rules. // // string -> types.String @@ -38,12 +41,12 @@ func GoSdkToTfSdkStruct(ctx context.Context, gosdk interface{}, tfsdk interface{ } if destVal.Kind() != reflect.Ptr { - return diag.Diagnostics{diag.NewErrorDiagnostic("please provide a pointer for the tfsdk struct", "tfsdk to gosdk struct conversion failure")} + return diag.Diagnostics{diag.NewErrorDiagnostic(goSdkToTfSdkStructConversionFailureMessage, fmt.Sprintf("please provide a pointer for the tfsdk struct, got %s", destVal.Type().Name()))} } destVal = destVal.Elem() if srcVal.Kind() != reflect.Struct || destVal.Kind() != reflect.Struct { - return diag.Diagnostics{diag.NewErrorDiagnostic(fmt.Sprintf("input should be structs %s, %s", srcVal.Type().Name(), destVal.Type().Name()), "tfsdk to gosdk struct conversion failure")} + return diag.Diagnostics{diag.NewErrorDiagnostic(goSdkToTfSdkStructConversionFailureMessage, fmt.Sprintf("input should be structs %s, %s", srcVal.Type().Name(), destVal.Type().Name()))} } var forceSendFieldVal []string @@ -73,7 +76,7 @@ func GoSdkToTfSdkStruct(ctx context.Context, gosdk interface{}, tfsdk interface{ err := goSdkToTfSdkSingleField(ctx, srcField, destField, fieldInForceSendFields(srcFieldName, forceSendFieldVal)) if err != nil { - return diag.Diagnostics{diag.NewErrorDiagnostic(err.Error(), "gosdk to tfsdk field conversion failure")} + return diag.Diagnostics{diag.NewErrorDiagnostic(goSdkToTfSdkFieldConversionFailureMessage, err.Error())} } } return nil @@ -101,7 +104,7 @@ func goSdkToTfSdkSingleField(ctx context.Context, srcField reflect.Value, destFi // Recursively populate the nested struct. if GoSdkToTfSdkStruct(ctx, srcFieldValue, destField.Interface()).HasError() { - panic(fmt.Sprintf("Error converting gosdk to tfsdk struct. %s", common.TerraformBugErrorMessage)) + panic(fmt.Sprintf("%s. %s", goSdkToTfSdkStructConversionFailureMessage, common.TerraformBugErrorMessage)) } case reflect.Bool: boolVal := srcFieldValue.(bool) @@ -150,7 +153,7 @@ func goSdkToTfSdkSingleField(ctx context.Context, srcField reflect.Value, destFi } // resolve the nested struct by recursively calling the function if GoSdkToTfSdkStruct(ctx, srcFieldValue, destField.Addr().Interface()).HasError() { - panic(fmt.Sprintf("Error converting gosdk to tfsdk struct. %s", common.TerraformBugErrorMessage)) + panic(fmt.Sprintf("%s. %s", goSdkToTfSdkStructConversionFailureMessage, common.TerraformBugErrorMessage)) } case reflect.Slice: if srcField.IsNil() { diff --git a/internal/providers/pluginfw/converters/tf_to_go.go b/internal/providers/pluginfw/converters/tf_to_go.go index a3dc991320..6cf23decad 100644 --- a/internal/providers/pluginfw/converters/tf_to_go.go +++ b/internal/providers/pluginfw/converters/tf_to_go.go @@ -14,6 +14,9 @@ import ( "github.com/databricks/terraform-provider-databricks/internal/tfreflect" ) +const tfSdkToGoSdkStructConversionFailureMessage = "tfsdk to gosdk struct conversion failure" +const tfSdkToGoSdkFieldConversionFailureMessage = "tfsdk to gosdk field conversion failure" + // TfSdkToGoSdkStruct converts a tfsdk struct into a gosdk struct, with the folowing rules. // // types.String -> string @@ -37,12 +40,12 @@ func TfSdkToGoSdkStruct(ctx context.Context, tfsdk interface{}, gosdk interface{ } if destVal.Kind() != reflect.Ptr { - return diag.Diagnostics{diag.NewErrorDiagnostic(fmt.Sprintf("please provide a pointer for the gosdk struct, got %s", destVal.Type().Name()), "tfsdk to gosdk struct conversion failure")} + return diag.Diagnostics{diag.NewErrorDiagnostic(tfSdkToGoSdkStructConversionFailureMessage, fmt.Sprintf("please provide a pointer for the gosdk struct, got %s", destVal.Type().Name()))} } destVal = destVal.Elem() if srcVal.Kind() != reflect.Struct { - return diag.Diagnostics{diag.NewErrorDiagnostic(fmt.Sprintf("input should be structs, got %s,", srcVal.Type().Name()), "tfsdk to gosdk struct conversion failure")} + return diag.Diagnostics{diag.NewErrorDiagnostic(tfSdkToGoSdkStructConversionFailureMessage, fmt.Sprintf("input should be structs, got %s,", srcVal.Type().Name()))} } forceSendFieldsField := destVal.FieldByName("ForceSendFields") @@ -61,7 +64,7 @@ func TfSdkToGoSdkStruct(ctx context.Context, tfsdk interface{}, gosdk interface{ err := tfSdkToGoSdkSingleField(ctx, srcField, destField, srcFieldName, &forceSendFieldsField) if err != nil { - return diag.Diagnostics{diag.NewErrorDiagnostic(err.Error(), "tfsdk to gosdk field conversion failure")} + return diag.Diagnostics{diag.NewErrorDiagnostic(tfSdkToGoSdkFieldConversionFailureMessage, err.Error())} } } @@ -93,7 +96,7 @@ func tfSdkToGoSdkSingleField(ctx context.Context, srcField reflect.Value, destFi // Recursively populate the nested struct. if TfSdkToGoSdkStruct(ctx, srcFieldValue, destField.Interface()).HasError() { - panic(fmt.Sprintf("Error converting tfsdk to gosdk struct. %s", common.TerraformBugErrorMessage)) + panic(fmt.Sprintf("%s. %s", tfSdkToGoSdkStructConversionFailureMessage, common.TerraformBugErrorMessage)) } } else if srcField.Kind() == reflect.Struct { tfsdkToGoSdkStructField(srcField, destField, srcFieldName, forceSendFieldsField, ctx) @@ -199,7 +202,7 @@ func tfsdkToGoSdkStructField(srcField reflect.Value, destField reflect.Value, sr } // If it is a real stuct instead of a tfsdk type, recursively resolve it. if TfSdkToGoSdkStruct(ctx, srcFieldValue, destField.Addr().Interface()).HasError() { - panic(fmt.Sprintf("Error converting tfsdk to gosdk struct. %s", common.TerraformBugErrorMessage)) + panic(fmt.Sprintf("%s. %s", tfSdkToGoSdkStructConversionFailureMessage, common.TerraformBugErrorMessage)) } } } From 891e0aff45633be88a32415c68cc06afcfbf4696 Mon Sep 17 00:00:00 2001 From: Edward Feng <67326663+edwardfeng-db@users.noreply.github.com> Date: Fri, 13 Sep 2024 14:06:13 +0200 Subject: [PATCH 29/54] [Internal] Clean up comments in library resource (#4015) ## Changes - Clean up undeleted comments ## Tests - [x] `make test` run locally - [x] relevant change in `docs/` folder - [x] covered with integration tests in `internal/acceptance` - [x] relevant acceptance tests are passing - [x] using Go SDK --- .../pluginfw/resources/library/resource_library.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/internal/providers/pluginfw/resources/library/resource_library.go b/internal/providers/pluginfw/resources/library/resource_library.go index 2c452131a4..04b90f6298 100644 --- a/internal/providers/pluginfw/resources/library/resource_library.go +++ b/internal/providers/pluginfw/resources/library/resource_library.go @@ -73,14 +73,6 @@ func (r *LibraryResource) Schema(ctx context.Context, req resource.SchemaRequest resp.Schema = schema.Schema{ Description: "Terraform schema for Databricks Library", Attributes: tfschema.ResourceStructToSchemaMap(LibraryExtended{}, func(c tfschema.CustomizableSchema) tfschema.CustomizableSchema { - // c.AddPlanModifier(stringplanmodifier.RequiresReplace(), "cluster_id") - // c.AddPlanModifier(objectplanmodifier.RequiresReplace(), "cran") - // c.AddPlanModifier(stringplanmodifier.RequiresReplace(), "egg") - // c.AddPlanModifier(stringplanmodifier.RequiresReplace(), "jar") - // c.AddPlanModifier(objectplanmodifier.RequiresReplace(), "maven") - // c.AddPlanModifier(objectplanmodifier.RequiresReplace(), "pypi") - // c.AddPlanModifier(stringplanmodifier.RequiresReplace(), "requirements") - // c.AddPlanModifier(stringplanmodifier.RequiresReplace(), "whl") for field, attribute := range c.ToAttributeMap() { switch attribute.(type) { case tfschema.StringAttributeBuilder: From 1e62576102711c03453c716da156be3b7f19be66 Mon Sep 17 00:00:00 2001 From: Tanmay Rustagi <88379306+tanmay-db@users.noreply.github.com> Date: Fri, 13 Sep 2024 16:08:23 +0200 Subject: [PATCH 30/54] [Internal] Migrate `databricks_cluster` data source to plugin framework (#3988) ## Changes - Migrates `databricks_cluster` data source to plugin framework - Check for different int and float types in Go to Tf converter function - Use computed tag to simplify customize schema for volumes Note: The resource will be suffixed with `_pluginframework` and will be made default in another PR so the change is easily revertible. ## Tests - Added Integration tests - Added Unit tests All are passing - [x] `make test` run locally - [ ] relevant change in `docs/` folder - [x] covered with integration tests in `internal/acceptance` - [x] relevant acceptance tests are passing - [x] using Go SDK --- .../providers/pluginfw/converters/go_to_tf.go | 4 +- internal/providers/pluginfw/pluginfw.go | 2 + .../resources/cluster/data_cluster.go | 129 ++++++++++++++++++ .../cluster/data_cluster_acc_test.go | 28 ++++ .../resources/cluster/data_cluster_test.go | 39 ++++++ ...y_test.go => resource_library_acc_test.go} | 0 ...o => resource_quality_monitor_acc_test.go} | 4 +- .../pluginfw/resources/volume/data_volumes.go | 12 +- ...lumes_test.go => data_volumes_acc_test.go} | 6 +- 9 files changed, 209 insertions(+), 15 deletions(-) create mode 100644 internal/providers/pluginfw/resources/cluster/data_cluster.go create mode 100644 internal/providers/pluginfw/resources/cluster/data_cluster_acc_test.go create mode 100644 internal/providers/pluginfw/resources/cluster/data_cluster_test.go rename internal/providers/pluginfw/resources/library/{resource_library_test.go => resource_library_acc_test.go} (100%) rename internal/providers/pluginfw/resources/qualitymonitor/{resource_quality_monitor_test.go => resource_quality_monitor_acc_test.go} (97%) rename internal/providers/pluginfw/resources/volume/{data_volumes_test.go => data_volumes_acc_test.go} (88%) diff --git a/internal/providers/pluginfw/converters/go_to_tf.go b/internal/providers/pluginfw/converters/go_to_tf.go index 5e39086868..b86c32a21b 100644 --- a/internal/providers/pluginfw/converters/go_to_tf.go +++ b/internal/providers/pluginfw/converters/go_to_tf.go @@ -114,7 +114,7 @@ func goSdkToTfSdkSingleField(ctx context.Context, srcField reflect.Value, destFi } else { destField.Set(reflect.ValueOf(types.BoolNull())) } - case reflect.Int64: + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: // convert any kind of integer to int64 intVal := srcField.Convert(reflect.TypeOf(int64(0))).Int() // check if the value is non-zero or if the field is in the forceSendFields list @@ -123,7 +123,7 @@ func goSdkToTfSdkSingleField(ctx context.Context, srcField reflect.Value, destFi } else { destField.Set(reflect.ValueOf(types.Int64Null())) } - case reflect.Float64: + case reflect.Float32, reflect.Float64: // convert any kind of float to float64 float64Val := srcField.Convert(reflect.TypeOf(float64(0))).Float() // check if the value is non-zero or if the field is in the forceSendFields list diff --git a/internal/providers/pluginfw/pluginfw.go b/internal/providers/pluginfw/pluginfw.go index d09ec16e4a..71e91dccd8 100644 --- a/internal/providers/pluginfw/pluginfw.go +++ b/internal/providers/pluginfw/pluginfw.go @@ -16,6 +16,7 @@ import ( "github.com/databricks/terraform-provider-databricks/commands" "github.com/databricks/terraform-provider-databricks/common" providercommon "github.com/databricks/terraform-provider-databricks/internal/providers/common" + "github.com/databricks/terraform-provider-databricks/internal/providers/pluginfw/resources/cluster" "github.com/databricks/terraform-provider-databricks/internal/providers/pluginfw/resources/library" "github.com/databricks/terraform-provider-databricks/internal/providers/pluginfw/resources/qualitymonitor" "github.com/databricks/terraform-provider-databricks/internal/providers/pluginfw/resources/volume" @@ -49,6 +50,7 @@ func (p *DatabricksProviderPluginFramework) Resources(ctx context.Context) []fun func (p *DatabricksProviderPluginFramework) DataSources(ctx context.Context) []func() datasource.DataSource { return []func() datasource.DataSource{ + cluster.DataSourceCluster, volume.DataSourceVolumes, } } diff --git a/internal/providers/pluginfw/resources/cluster/data_cluster.go b/internal/providers/pluginfw/resources/cluster/data_cluster.go new file mode 100644 index 0000000000..9936df5fa2 --- /dev/null +++ b/internal/providers/pluginfw/resources/cluster/data_cluster.go @@ -0,0 +1,129 @@ +package cluster + +import ( + "context" + "fmt" + "strings" + + "github.com/databricks/databricks-sdk-go/apierr" + "github.com/databricks/databricks-sdk-go/service/compute" + "github.com/databricks/terraform-provider-databricks/common" + pluginfwcommon "github.com/databricks/terraform-provider-databricks/internal/providers/pluginfw/common" + "github.com/databricks/terraform-provider-databricks/internal/providers/pluginfw/converters" + "github.com/databricks/terraform-provider-databricks/internal/providers/pluginfw/tfschema" + "github.com/databricks/terraform-provider-databricks/internal/service/compute_tf" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +func DataSourceCluster() datasource.DataSource { + return &ClusterDataSource{} +} + +var _ datasource.DataSourceWithConfigure = &ClusterDataSource{} + +type ClusterDataSource struct { + Client *common.DatabricksClient +} + +type ClusterInfo struct { + ClusterId types.String `tfsdk:"cluster_id" tf:"optional,computed"` + Name types.String `tfsdk:"cluster_name" tf:"optional,computed"` + ClusterInfo *compute_tf.ClusterDetails `tfsdk:"cluster_info" tf:"optional,computed"` +} + +func (d *ClusterDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = "databricks_cluster_pluginframework" +} + +func (d *ClusterDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: tfschema.DataSourceStructToSchemaMap(ClusterInfo{}, nil), + } +} + +func (d *ClusterDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { + if d.Client == nil { + d.Client = pluginfwcommon.ConfigureDataSource(req, resp) + } +} + +func validateClustersList(ctx context.Context, clusters []compute_tf.ClusterDetails, clusterName string) diag.Diagnostics { + if len(clusters) == 0 { + return diag.Diagnostics{diag.NewErrorDiagnostic(fmt.Sprintf("there is no cluster with name '%s'", clusterName), "")} + } + if len(clusters) > 1 { + clusterIDs := []string{} + for _, cluster := range clusters { + clusterIDs = append(clusterIDs, cluster.ClusterId.ValueString()) + } + return diag.Diagnostics{diag.NewErrorDiagnostic(fmt.Sprintf("there is more than one cluster with name '%s'", clusterName), fmt.Sprintf("The IDs of those clusters are: %s. When specifying a cluster name, the name must be unique. Alternatively, specify the cluster by ID using the cluster_id attribute.", strings.Join(clusterIDs, ", ")))} + } + return nil +} + +func (d *ClusterDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + w, diags := d.Client.GetWorkspaceClient() + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + var clusterInfo ClusterInfo + resp.Diagnostics.Append(req.Config.Get(ctx, &clusterInfo)...) + if resp.Diagnostics.HasError() { + return + } + clusterName := clusterInfo.Name.ValueString() + clusterId := clusterInfo.ClusterId.ValueString() + if clusterName != "" { + clustersGoSDk, err := w.Clusters.ListAll(ctx, compute.ListClustersRequest{}) + if err != nil { + resp.Diagnostics.AddError("failed to list clusters", err.Error()) + return + } + var clustersTfSDK []compute_tf.ClusterDetails + for _, cluster := range clustersGoSDk { + var clusterDetails compute_tf.ClusterDetails + resp.Diagnostics.Append(converters.GoSdkToTfSdkStruct(ctx, cluster, &clusterDetails)...) + if resp.Diagnostics.HasError() { + return + } + clustersTfSDK = append(clustersTfSDK, clusterDetails) + } + namedClusters := []compute_tf.ClusterDetails{} + for _, cluster := range clustersTfSDK { + if cluster.ClusterName == clusterInfo.Name { + namedClusters = append(namedClusters, cluster) + } + } + resp.Diagnostics.Append(validateClustersList(ctx, namedClusters, clusterName)...) + if resp.Diagnostics.HasError() { + return + } + clusterInfo.ClusterInfo = &namedClusters[0] + } else if clusterId != "" { + cluster, err := w.Clusters.GetByClusterId(ctx, clusterId) + if err != nil { + if apierr.IsMissing(err) { + resp.State.RemoveResource(ctx) + } + resp.Diagnostics.AddError(fmt.Sprintf("failed to get cluster with cluster id: %s", clusterId), err.Error()) + return + } + var clusterDetails compute_tf.ClusterDetails + resp.Diagnostics.Append(converters.GoSdkToTfSdkStruct(ctx, cluster, &clusterDetails)...) + if resp.Diagnostics.HasError() { + return + } + clusterInfo.ClusterInfo = &clusterDetails + } else { + resp.Diagnostics.AddError("you need to specify either `cluster_name` or `cluster_id`", "") + return + } + clusterInfo.ClusterId = clusterInfo.ClusterInfo.ClusterId + clusterInfo.Name = clusterInfo.ClusterInfo.ClusterName + resp.Diagnostics.Append(resp.State.Set(ctx, clusterInfo)...) +} diff --git a/internal/providers/pluginfw/resources/cluster/data_cluster_acc_test.go b/internal/providers/pluginfw/resources/cluster/data_cluster_acc_test.go new file mode 100644 index 0000000000..cbac44de04 --- /dev/null +++ b/internal/providers/pluginfw/resources/cluster/data_cluster_acc_test.go @@ -0,0 +1,28 @@ +package cluster_test + +import ( + "testing" + + "github.com/databricks/terraform-provider-databricks/internal/acceptance" +) + +const dataClusterTemplateById = ` + data "databricks_cluster_pluginframework" "by_id" { + cluster_id = "{env.TEST_DEFAULT_CLUSTER_ID}" + } +` + +func TestAccDataSourceClusterByID(t *testing.T) { + acceptance.WorkspaceLevel(t, acceptance.Step{ + Template: dataClusterTemplateById, + }) +} + +func TestAccDataSourceClusterByName(t *testing.T) { + acceptance.WorkspaceLevel(t, acceptance.Step{ + Template: dataClusterTemplateById + ` + data "databricks_cluster_pluginframework" "by_name" { + cluster_name = data.databricks_cluster_pluginframework.by_id.cluster_name + }`, + }) +} diff --git a/internal/providers/pluginfw/resources/cluster/data_cluster_test.go b/internal/providers/pluginfw/resources/cluster/data_cluster_test.go new file mode 100644 index 0000000000..83ee608a98 --- /dev/null +++ b/internal/providers/pluginfw/resources/cluster/data_cluster_test.go @@ -0,0 +1,39 @@ +package cluster + +import ( + "context" + "fmt" + "testing" + + "github.com/databricks/terraform-provider-databricks/internal/service/compute_tf" + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/stretchr/testify/assert" +) + +func TestNoClusterError(t *testing.T) { + clusterName := "test-cluster-name" + clusters := []compute_tf.ClusterDetails{} + actualDiagnostics := validateClustersList(context.Background(), clusters, clusterName) + expectedDiagnostics := diag.Diagnostics{diag.NewErrorDiagnostic(fmt.Sprintf("there is no cluster with name '%s'", clusterName), "")} + assert.True(t, actualDiagnostics.HasError()) + assert.Equal(t, expectedDiagnostics, actualDiagnostics) +} + +func TestMultipleClustersError(t *testing.T) { + clusterName := "test-cluster-name" + clusters := []compute_tf.ClusterDetails{ + { + ClusterName: types.StringValue("test-cluster-name"), + ClusterId: types.StringValue("123"), + }, + { + ClusterName: types.StringValue("test-cluster-name"), + ClusterId: types.StringValue("456"), + }, + } + actualDiagnostics := validateClustersList(context.Background(), clusters, clusterName) + expectedDiagnostics := diag.Diagnostics{diag.NewErrorDiagnostic(fmt.Sprintf("there is more than one cluster with name '%s'", clusterName), "The IDs of those clusters are: 123, 456. When specifying a cluster name, the name must be unique. Alternatively, specify the cluster by ID using the cluster_id attribute.")} + assert.True(t, actualDiagnostics.HasError()) + assert.Equal(t, expectedDiagnostics, actualDiagnostics) +} diff --git a/internal/providers/pluginfw/resources/library/resource_library_test.go b/internal/providers/pluginfw/resources/library/resource_library_acc_test.go similarity index 100% rename from internal/providers/pluginfw/resources/library/resource_library_test.go rename to internal/providers/pluginfw/resources/library/resource_library_acc_test.go diff --git a/internal/providers/pluginfw/resources/qualitymonitor/resource_quality_monitor_test.go b/internal/providers/pluginfw/resources/qualitymonitor/resource_quality_monitor_acc_test.go similarity index 97% rename from internal/providers/pluginfw/resources/qualitymonitor/resource_quality_monitor_test.go rename to internal/providers/pluginfw/resources/qualitymonitor/resource_quality_monitor_acc_test.go index a2e391bda3..f9934c9cd9 100644 --- a/internal/providers/pluginfw/resources/qualitymonitor/resource_quality_monitor_test.go +++ b/internal/providers/pluginfw/resources/qualitymonitor/resource_quality_monitor_acc_test.go @@ -48,7 +48,7 @@ resource "databricks_sql_table" "myInferenceTable" { ` -func TestUcAccQualityMonitorPluginFramework(t *testing.T) { +func TestUcAccQualityMonitor(t *testing.T) { if os.Getenv("GOOGLE_CREDENTIALS") != "" { t.Skipf("databricks_quality_monitor resource is not available on GCP") } @@ -115,7 +115,7 @@ func TestUcAccQualityMonitorPluginFramework(t *testing.T) { }) } -func TestUcAccUpdateQualityMonitorPluginFramework(t *testing.T) { +func TestUcAccUpdateQualityMonitor(t *testing.T) { if os.Getenv("GOOGLE_CREDENTIALS") != "" { t.Skipf("databricks_quality_monitor resource is not available on GCP") } diff --git a/internal/providers/pluginfw/resources/volume/data_volumes.go b/internal/providers/pluginfw/resources/volume/data_volumes.go index cf9101b52e..590a85f95b 100644 --- a/internal/providers/pluginfw/resources/volume/data_volumes.go +++ b/internal/providers/pluginfw/resources/volume/data_volumes.go @@ -28,7 +28,7 @@ type VolumesDataSource struct { type VolumesList struct { CatalogName types.String `tfsdk:"catalog_name"` SchemaName types.String `tfsdk:"schema_name"` - Ids []types.String `tfsdk:"ids" tf:"optional"` + Ids []types.String `tfsdk:"ids" tf:"optional,computed"` } func (d *VolumesDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { @@ -37,10 +37,7 @@ func (d *VolumesDataSource) Metadata(ctx context.Context, req datasource.Metadat func (d *VolumesDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { resp.Schema = schema.Schema{ - Attributes: tfschema.DataSourceStructToSchemaMap(VolumesList{}, func(c tfschema.CustomizableSchema) tfschema.CustomizableSchema { - c.SetComputed("ids") - return c - }), + Attributes: tfschema.DataSourceStructToSchemaMap(VolumesList{}, nil), } } @@ -69,13 +66,12 @@ func (d *VolumesDataSource) Read(ctx context.Context, req datasource.ReadRequest if err != nil { if apierr.IsMissing(err) { resp.State.RemoveResource(ctx) - return } - resp.Diagnostics.AddError(fmt.Sprintf("Failed to get volumes for the catalog:%s and schema%s", listVolumesRequest.CatalogName, listVolumesRequest.SchemaName), err.Error()) + resp.Diagnostics.AddError(fmt.Sprintf("failed to get volumes for the catalog:%s and schema%s", listVolumesRequest.CatalogName, listVolumesRequest.SchemaName), err.Error()) return } for _, v := range volumes { volumesList.Ids = append(volumesList.Ids, types.StringValue(v.FullName)) } - resp.State.Set(ctx, volumesList) + resp.Diagnostics.Append(resp.State.Set(ctx, volumesList)...) } diff --git a/internal/providers/pluginfw/resources/volume/data_volumes_test.go b/internal/providers/pluginfw/resources/volume/data_volumes_acc_test.go similarity index 88% rename from internal/providers/pluginfw/resources/volume/data_volumes_test.go rename to internal/providers/pluginfw/resources/volume/data_volumes_acc_test.go index 89177583fb..0fdfc8aa50 100644 --- a/internal/providers/pluginfw/resources/volume/data_volumes_test.go +++ b/internal/providers/pluginfw/resources/volume/data_volumes_acc_test.go @@ -10,7 +10,7 @@ import ( "github.com/stretchr/testify/require" ) -func checkDataSourceVolumesPluginFrameworkPopulated(t *testing.T) func(s *terraform.State) error { +func checkDataSourceVolumesPopulated(t *testing.T) func(s *terraform.State) error { return func(s *terraform.State) error { _, ok := s.Modules[0].Resources["data.databricks_volumes_pluginframework.this"] require.True(t, ok, "data.databricks_volumes_pluginframework.this has to be there") @@ -20,7 +20,7 @@ func checkDataSourceVolumesPluginFrameworkPopulated(t *testing.T) func(s *terraf } } -func TestUcAccDataSourceVolumesPluginFramework(t *testing.T) { +func TestUcAccDataSourceVolumes(t *testing.T) { acceptance.UnityWorkspaceLevel(t, acceptance.Step{ Template: ` resource "databricks_catalog" "sandbox" { @@ -54,6 +54,6 @@ func TestUcAccDataSourceVolumesPluginFramework(t *testing.T) { value = length(data.databricks_volumes_pluginframework.this.ids) } `, - Check: checkDataSourceVolumesPluginFrameworkPopulated(t), + Check: checkDataSourceVolumesPopulated(t), }) } From 1153bba6de9148ba60796d85f065b47462fc681b Mon Sep 17 00:00:00 2001 From: Miles Yucht Date: Mon, 16 Sep 2024 09:01:15 -0400 Subject: [PATCH 31/54] [Feature] Add support for filters in `databricks_clusters` data source (#4014) ## Changes Version 1.50 of the Terraform Provider featured an upgrade to the Go SDK affecting cluster listing. The new List Clusters API returns all terminated clusters in the last 30 days without a limit. This results in the list operation taking considerably longer for some workspaces, especially workspaces with many jobs where clusters are frequently created. This impacts the `databricks_clusters` data source, which can be slow. This PR partially addresses this by adding support for `filter_by` to the `databricks_clusters` API. Filters expressed here are pushed to the server and result in fewer clusters being returned by the API. Users of this data source can specify a particular cluster state, cluster source, pinned status, or cluster policy ID to limit the number of clusters returned by the API, drastically speeding up performance. ## Tests Integration tests for `databricks_cluster` data source test setting the `filter_by` parameter's attributes. - [ ] `make test` run locally - [ ] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [ ] using Go SDK --- clusters/data_clusters.go | 11 ++-- docs/data-sources/clusters.md | 10 ++++ internal/acceptance/data_clusters_test.go | 70 +++++++++++++++++++++++ 3 files changed, 87 insertions(+), 4 deletions(-) diff --git a/clusters/data_clusters.go b/clusters/data_clusters.go index 45e41a432c..3fbf55c5b4 100644 --- a/clusters/data_clusters.go +++ b/clusters/data_clusters.go @@ -11,11 +11,14 @@ import ( func DataSourceClusters() common.Resource { return common.WorkspaceData(func(ctx context.Context, data *struct { - Id string `json:"id,omitempty" tf:"computed"` - Ids []string `json:"ids,omitempty" tf:"computed,slice_set"` - ClusterNameContains string `json:"cluster_name_contains,omitempty"` + Id string `json:"id,omitempty" tf:"computed"` + Ids []string `json:"ids,omitempty" tf:"computed,slice_set"` + ClusterNameContains string `json:"cluster_name_contains,omitempty"` + FilterBy *compute.ListClustersFilterBy `json:"filter_by,omitempty"` }, w *databricks.WorkspaceClient) error { - clusters, err := w.Clusters.ListAll(ctx, compute.ListClustersRequest{}) + clusters, err := w.Clusters.ListAll(ctx, compute.ListClustersRequest{ + FilterBy: data.FilterBy, + }) if err != nil { return err } diff --git a/docs/data-sources/clusters.md b/docs/data-sources/clusters.md index bfe875b73a..ee976406c5 100644 --- a/docs/data-sources/clusters.md +++ b/docs/data-sources/clusters.md @@ -27,6 +27,16 @@ data "databricks_clusters" "all_shared" { ## Argument Reference * `cluster_name_contains` - (Optional) Only return [databricks_cluster](../resources/cluster.md#cluster_id) ids that match the given name string. +* `filter_by` - (Optional) Filters to apply to the listed clusters. See [filter_by Configuration Block](#filter_by-configuration-block) below for details. + +### filter_by Configuration Block + +The `filter_by` block controls the filtering of the listed clusters. It supports the following arguments: + +* `cluster_sources` - (Optional) List of cluster sources to filter by. Possible values are `API`, `JOB`, `MODELS`, `PIPELINE`, `PIPELINE_MAINTENANCE`, `SQL`, and `UI`. +* `cluster_states` - (Optional) List of cluster states to filter by. Possible values are `RUNNING`, `PENDING`, `RESIZING`, `RESTARTING`, `TERMINATING`, `TERMINATED`, `ERROR`, and `UNKNOWN`. +* `is_pinned` - (Optional) Whether to filter by pinned clusters. +* `policy_id` - (Optional) Filter by [databricks_cluster_policy](../resources/cluster_policy.md) id. ## Attribute Reference diff --git a/internal/acceptance/data_clusters_test.go b/internal/acceptance/data_clusters_test.go index 45d578873d..f7e79a8103 100644 --- a/internal/acceptance/data_clusters_test.go +++ b/internal/acceptance/data_clusters_test.go @@ -1,7 +1,13 @@ package acceptance import ( + "context" "testing" + + "github.com/databricks/databricks-sdk-go" + "github.com/databricks/databricks-sdk-go/service/compute" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/stretchr/testify/assert" ) func TestAccDataSourceClustersNoFilter(t *testing.T) { @@ -20,3 +26,67 @@ func TestAccDataSourceClustersWithFilter(t *testing.T) { }`, }) } + +func checkFirstCluster(t *testing.T, f func(*compute.ClusterDetails)) func(*terraform.State) error { + return func(s *terraform.State) error { + w := databricks.Must(databricks.NewWorkspaceClient()) + firstClusterId, ok := s.RootModule().Resources["data.databricks_clusters.this"].Primary.Attributes["ids.0"] + if ok { + firstCluster, err := w.Clusters.GetByClusterId(context.Background(), firstClusterId) + assert.NoError(t, err) + f(firstCluster) + } + return nil + } +} + +func TestAccDataSourceClusters_FilterBy(t *testing.T) { + WorkspaceLevel(t, Step{ + Template: ` + data "databricks_clusters" "this" { + filter_by { + cluster_sources = ["UI", "API"] + } + }`, + Check: checkFirstCluster(t, func(c *compute.ClusterDetails) { + assert.Contains(t, []compute.ClusterSource{"UI", "API"}, c.ClusterSource) + }), + }, Step{ + Template: ` + data "databricks_clusters" "this" { + filter_by { + cluster_states = ["RUNNING", "RESIZING"] + } + }`, + Check: checkFirstCluster(t, func(c *compute.ClusterDetails) { + assert.Contains(t, []compute.State{"RUNNING", "RESIZING"}, c.State) + }), + }, Step{ + Template: ` + data "databricks_clusters" "this" { + filter_by { + is_pinned = true + } + }`, + // Not possible to get whether a cluster is pinned or not + }, Step{ + Template: ` + resource "databricks_cluster_policy" "this" { + name = "test" + definition = jsonencode({ + "spark_conf.spark.hadoop.javax.jdo.option.ConnectionURL": { + "type": "fixed", + "value": "jdbc:sqlserver://" + } + }) + } + data "databricks_clusters" "this" { + filter_by { + policy_id = databricks_cluster_policy.this.id + } + }`, + Check: checkFirstCluster(t, func(c *compute.ClusterDetails) { + assert.Equal(t, "abc-123", c.PolicyId) + }), + }) +} From fb178f96aece64b0fa6aa7bbb2b780eba198eab7 Mon Sep 17 00:00:00 2001 From: Tanmay Rustagi <88379306+tanmay-db@users.noreply.github.com> Date: Mon, 16 Sep 2024 17:09:56 +0200 Subject: [PATCH 32/54] [Fix] Permanently delete `ERROR` and `TERMINATED` state clusters if their creation fails (#4021) ## Changes If we get error or terminated cluster (after getting WaitGetClusterRunning in Create) then we permanently delete them. ## Tests Unit tests - [ ] `make test` run locally - [ ] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [ ] using Go SDK --- clusters/resource_cluster.go | 5 ++ clusters/resource_cluster_test.go | 111 ++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+) diff --git a/clusters/resource_cluster.go b/clusters/resource_cluster.go index 6595b92a9f..fb77a5f76d 100644 --- a/clusters/resource_cluster.go +++ b/clusters/resource_cluster.go @@ -472,6 +472,11 @@ func resourceClusterCreate(ctx context.Context, d *schema.ResourceData, c *commo clusterInfo, err := clusterWaiter.GetWithTimeout(timeout) if err != nil { + // In case of "ERROR" or "TERMINATED" state, WaitGetClusterRunning returns an error and we should delete the cluster before returning + deleteError := resourceClusterDelete(ctx, d, c) + if deleteError != nil { + return fmt.Errorf("failed to create cluster: %v and failed to delete it during cleanup: %v", err, deleteError) + } return err } diff --git a/clusters/resource_cluster_test.go b/clusters/resource_cluster_test.go index b5af784be5..804067597b 100644 --- a/clusters/resource_cluster_test.go +++ b/clusters/resource_cluster_test.go @@ -164,6 +164,117 @@ func TestResourceClusterCreatePinned(t *testing.T) { assert.Equal(t, "abc", d.Id()) } +func TestResourceClusterCreateErrorFollowedByDeletion(t *testing.T) { + d, err := qa.ResourceFixture{ + Fixtures: []qa.HTTPFixture{ + { + Method: "POST", + Resource: "/api/2.1/clusters/create", + ExpectedRequest: compute.CreateCluster{ + NumWorkers: 100, + ClusterName: "Shared Autoscaling", + SparkVersion: "7.1-scala12", + NodeTypeId: "i3.xlarge", + AutoterminationMinutes: 15, + }, + Response: compute.ClusterDetails{ + ClusterId: "abc", + }, + }, + { + Method: "GET", + ReuseRequest: true, + Resource: "/api/2.1/clusters/get?cluster_id=abc", + Response: compute.ClusterDetails{ + ClusterId: "abc", + NumWorkers: 100, + ClusterName: "Shared Autoscaling", + SparkVersion: "7.1-scala12", + NodeTypeId: "i3.xlarge", + AutoterminationMinutes: 15, + State: compute.StateTerminated, + }, + }, + { + Method: "POST", + Resource: "/api/2.1/clusters/permanent-delete", + ExpectedRequest: compute.PermanentDeleteCluster{ + ClusterId: "abc", + }, + }, + }, + Create: true, + Resource: ResourceCluster(), + State: map[string]any{ + "autotermination_minutes": 15, + "cluster_name": "Shared Autoscaling", + "spark_version": "7.1-scala12", + "node_type_id": "i3.xlarge", + "num_workers": 100, + }, + }.Apply(t) + assert.ErrorContains(t, err, "failed to reach RUNNING, got TERMINATED") + assert.Equal(t, "abc", d.Id()) +} + +func TestResourceClusterCreateErrorFollowedByDeletionError(t *testing.T) { + d, err := qa.ResourceFixture{ + Fixtures: []qa.HTTPFixture{ + { + Method: "POST", + Resource: "/api/2.1/clusters/create", + ExpectedRequest: compute.CreateCluster{ + NumWorkers: 100, + ClusterName: "Shared Autoscaling", + SparkVersion: "7.1-scala12", + NodeTypeId: "i3.xlarge", + AutoterminationMinutes: 15, + }, + Response: compute.ClusterDetails{ + ClusterId: "abc", + }, + }, + { + Method: "GET", + ReuseRequest: true, + Resource: "/api/2.1/clusters/get?cluster_id=abc", + Response: compute.ClusterDetails{ + ClusterId: "abc", + NumWorkers: 100, + ClusterName: "Shared Autoscaling", + SparkVersion: "7.1-scala12", + NodeTypeId: "i3.xlarge", + AutoterminationMinutes: 15, + State: compute.StateTerminated, + }, + }, + { + Method: "POST", + Resource: "/api/2.1/clusters/permanent-delete", + ExpectedRequest: compute.PermanentDeleteCluster{ + ClusterId: "abc", + }, + Status: 500, + Response: common.APIErrorBody{ + ErrorCode: "INTERNAL_ERROR", + Message: "Internal error happened", + }, + }, + }, + Create: true, + Resource: ResourceCluster(), + State: map[string]any{ + "autotermination_minutes": 15, + "cluster_name": "Shared Autoscaling", + "spark_version": "7.1-scala12", + "node_type_id": "i3.xlarge", + "num_workers": 100, + }, + }.Apply(t) + assert.ErrorContains(t, err, "failed to create cluster: failed to reach RUNNING, got TERMINATED: and failed to delete it during cleanup: Internal error happened") + assert.Equal(t, "abc", d.Id()) +} + func TestResourceClusterCreate_WithLibraries(t *testing.T) { d, err := qa.ResourceFixture{ Fixtures: []qa.HTTPFixture{ From d22064ebc231ca445d16389ba605e4a9edd767bd Mon Sep 17 00:00:00 2001 From: Alex Ott Date: Tue, 17 Sep 2024 05:41:02 +0200 Subject: [PATCH 33/54] [Exporter] Expand list of non-interactive clusters (#4023) ## Changes So we can avoid generation of not related cluster resources ## Tests - [x] `make test` run locally - [ ] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [ ] using Go SDK --- exporter/importables.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exporter/importables.go b/exporter/importables.go index 88a90e3bcd..8aeeaefeef 100644 --- a/exporter/importables.go +++ b/exporter/importables.go @@ -327,7 +327,7 @@ var resourcesMap map[string]importable = map[string]importable{ return err } lastActiveMs := ic.getLastActiveMs() - nonInteractiveClusters := []string{"JOB", "PIPELINE_MAINTENANCE", "PIPELINE", "SQL"} + nonInteractiveClusters := []string{"JOB", "MODELS", "PIPELINE_MAINTENANCE", "PIPELINE", "SQL"} for offset, c := range clusters { if slices.Contains(nonInteractiveClusters, string(c.ClusterSource)) { // TODO: Should we check cluster name as well? From 1908a92a8c23e6bc062527bced2028b5601008c4 Mon Sep 17 00:00:00 2001 From: Alex Ott Date: Tue, 17 Sep 2024 11:09:03 +0200 Subject: [PATCH 34/54] [Exporter] Ignore `databricks_artifact_allowlist` with zero `artifact_matcher` blocks (#4019) ## Changes Don't generate `databricks_artifact_allowlist` when no `artifact_matcher` blocks are defined ## Tests - [x] `make test` run locally - [ ] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [ ] using Go SDK --- exporter/importables.go | 8 ++++++++ exporter/importables_test.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/exporter/importables.go b/exporter/importables.go index 8aeeaefeef..d2cb8d0f36 100644 --- a/exporter/importables.go +++ b/exporter/importables.go @@ -2518,6 +2518,14 @@ var resourcesMap map[string]importable = map[string]importable{ } return nil }, + Ignore: func(ic *importContext, r *resource) bool { + numBlocks := r.Data.Get("artifact_matcher.#").(int) + if numBlocks == 0 { + log.Printf("[WARN] Ignoring artifcat allowlist with ID %s", r.ID) + ic.addIgnoredResource(fmt.Sprintf("databricks_artifact_allowlist. id=%s", r.ID)) + } + return numBlocks == 0 + }, Depends: []reference{ {Path: "artifact_matcher.artifact", Resource: "databricks_volume", Match: "volume_path", IsValidApproximation: isMatchingAllowListArtifact}, diff --git a/exporter/importables_test.go b/exporter/importables_test.go index b503117595..544322a745 100644 --- a/exporter/importables_test.go +++ b/exporter/importables_test.go @@ -1474,6 +1474,34 @@ func TestListUcAllowListSuccess(t *testing.T) { err := resourcesMap["databricks_artifact_allowlist"].List(ic) assert.NoError(t, err) assert.Equal(t, len(ic.testEmits), 3) + // Test ignore function + d := tfcatalog.ResourceArtifactAllowlist().ToResource().TestResourceData() + d.MarkNewResource() + d.Set("id", "abc") + res := ic.Importables["databricks_artifact_allowlist"].Ignore(ic, &resource{ + ID: "abc", + Data: d, + }) + assert.True(t, res) + assert.Contains(t, ic.ignoredResources, "databricks_artifact_allowlist. id=abc") + // Test ignore function, with blocks + err = common.StructToData( + tfcatalog.ArtifactAllowlistInfo{ + ArtifactType: "INIT_SCRIPT", + ArtifactMatchers: []catalog.ArtifactMatcher{ + { + Artifact: "/Volumes/inits", + MatchType: "PREFIX_MATCH", + }, + }, + }, + tfcatalog.ResourceArtifactAllowlist().Schema, d) + assert.NoError(t, err) + res = ic.Importables["databricks_artifact_allowlist"].Ignore(ic, &resource{ + ID: "abc", + Data: d, + }) + assert.False(t, res) } func TestEmitSqlParent(t *testing.T) { From e13ce2cf33bf183c9543d3bb0df1476deaf1d765 Mon Sep 17 00:00:00 2001 From: Tanmay Rustagi <88379306+tanmay-db@users.noreply.github.com> Date: Tue, 17 Sep 2024 14:50:34 +0200 Subject: [PATCH 35/54] [Release] Release v1.52.0 (#4022) ### New Features and Improvements * Add support for filters in `databricks_clusters` data source ([#4014](https://github.com/databricks/terraform-provider-databricks/pull/4014)). * Added `no_wait` option for clusters to skip waiting to start on cluster creation ([#3953](https://github.com/databricks/terraform-provider-databricks/pull/3953)). * Introduced Plugin Framework ([#3920](https://github.com/databricks/terraform-provider-databricks/pull/3920)). ### Bug Fixes * Add suppress diff for `azure_attributes.spot_bid_max_price` in `databricks_instance_pool` ([#3970](https://github.com/databricks/terraform-provider-databricks/pull/3970)). * Correctly send workload_type fields in `databricks_cluster` to allow users to disable usage in certain contexts ([#3972](https://github.com/databricks/terraform-provider-databricks/pull/3972)). * Fix `databricks_sql_table` treatment of properties ([#3925](https://github.com/databricks/terraform-provider-databricks/pull/3925)). * Force send fields for settings resources ([#3978](https://github.com/databricks/terraform-provider-databricks/pull/3978)). * Handle cluster deletion in `databricks_library` read ([#3909](https://github.com/databricks/terraform-provider-databricks/pull/3909)). * Make subscriptions optional for SqlAlertTask ([#3983](https://github.com/databricks/terraform-provider-databricks/pull/3983)). * Permanently delete `ERROR` and `TERMINATED` state clusters if their creation fails ([#4021](https://github.com/databricks/terraform-provider-databricks/pull/4021)). ### Documentation * Add troubleshooting guide for Provider "registry.terraform.io/databricks/databricks" planned an invalid value ([#3961](https://github.com/databricks/terraform-provider-databricks/pull/3961)). * Adopt official naming of Mosaic AI Vector Search ([#3971](https://github.com/databricks/terraform-provider-databricks/pull/3971)). * Document Terraform 1.0 as minimum version ([#3952](https://github.com/databricks/terraform-provider-databricks/pull/3952)). * Mention Salesforce as supported type in `databricks_connection` ([#3949](https://github.com/databricks/terraform-provider-databricks/pull/3949)). * Reimplement Azure Databricks deployment guide to use VNet injection & NPIP ([#3986](https://github.com/databricks/terraform-provider-databricks/pull/3986)). * Resolves [#3127](https://github.com/databricks/terraform-provider-databricks/pull/3127): Remove deprecated account_id field from mws_credentials resource ([#3974](https://github.com/databricks/terraform-provider-databricks/pull/3974)). * Small Grammar Corrections in Docs ([#4006](https://github.com/databricks/terraform-provider-databricks/pull/4006)). * Update `databricks_vector_search_index` docs to match latest SDK ([#4008](https://github.com/databricks/terraform-provider-databricks/pull/4008)). * Update aws_unity_catalog_assume_role_policy.md ([#3968](https://github.com/databricks/terraform-provider-databricks/pull/3968)). * Update documentation regarding authentication with Azure-managed Service Principal using GITHUB OIDC ([#3932](https://github.com/databricks/terraform-provider-databricks/pull/3932)). * Update metastore_assignment.md to properly reflect possible usage ([#3967](https://github.com/databricks/terraform-provider-databricks/pull/3967)). * Update minimum supported terraform version to 1.1.5 ([#3965](https://github.com/databricks/terraform-provider-databricks/pull/3965)). * Update resources diagram to include newer resources ([#3962](https://github.com/databricks/terraform-provider-databricks/pull/3962)). * Update workspace_binding import command ([#3944](https://github.com/databricks/terraform-provider-databricks/pull/3944)). * fix possible values for `securable_type` in `databricks_workspace_binding` ([#3942](https://github.com/databricks/terraform-provider-databricks/pull/3942)). ### Internal Changes * Add `AddPlanModifer` method for AttributeBuilder ([#4009](https://github.com/databricks/terraform-provider-databricks/pull/4009)). * Add integration tests for volumes and quality monitor plugin framework ([#3975](https://github.com/databricks/terraform-provider-databricks/pull/3975)). * Add support for `computed` tag in TfSDK Structs ([#4005](https://github.com/databricks/terraform-provider-databricks/pull/4005)). * Added `databricks_quality_monitor` resource and `databricks_volumes` data source to plugin framework ([#3958](https://github.com/databricks/terraform-provider-databricks/pull/3958)). * Allow vector search tests to fail ([#3959](https://github.com/databricks/terraform-provider-databricks/pull/3959)). * Clean up comments in library resource ([#4015](https://github.com/databricks/terraform-provider-databricks/pull/4015)). * Fix irregularities in plugin framework converter function errors ([#4010](https://github.com/databricks/terraform-provider-databricks/pull/4010)). * Make test utils public and move integration test for quality monitor ([#3993](https://github.com/databricks/terraform-provider-databricks/pull/3993)). * Migrate Share resource to Go SDK ([#3916](https://github.com/databricks/terraform-provider-databricks/pull/3916)). * Migrate `databricks_cluster` data source to plugin framework ([#3988](https://github.com/databricks/terraform-provider-databricks/pull/3988)). * Migrate imports for terraform plugin framework + update init test provider factory ([#3943](https://github.com/databricks/terraform-provider-databricks/pull/3943)). * Move volumes test next to plugin framework data source ([#3995](https://github.com/databricks/terraform-provider-databricks/pull/3995)). * Refactor provider and related packages ([#3940](https://github.com/databricks/terraform-provider-databricks/pull/3940)). * Support import in acceptance test + adding import state for quality monitor ([#3994](https://github.com/databricks/terraform-provider-databricks/pull/3994)). * Library plugin framework migration ([#3979](https://github.com/databricks/terraform-provider-databricks/pull/3979)). * Fix `TestAccClusterResource_WorkloadType` ([#3989](https://github.com/databricks/terraform-provider-databricks/pull/3989)). ### Dependency Updates * Bump github.com/hashicorp/hcl/v2 from 2.21.0 to 2.22.0 ([#3948](https://github.com/databricks/terraform-provider-databricks/pull/3948)). * Update Go SDK to 0.46.0 ([#4007](https://github.com/databricks/terraform-provider-databricks/pull/4007)). ### Exporter * Don't generate instance pools if the pool name is empty ([#3960](https://github.com/databricks/terraform-provider-databricks/pull/3960)). * Expand list of non-interactive clusters ([#4023](https://github.com/databricks/terraform-provider-databricks/pull/4023)). * Ignore databricks_artifact_allowlist with zero artifact_matcher blocks ([#4019](https://github.com/databricks/terraform-provider-databricks/pull/4019)). ## [Release] Release v1.51.0 ### Breaking Changes With this release, only protocol version 6 will be supported which is compatible with terraform CLI version 1.1.5 and later. If you are using an older version of the terraform CLI, please upgrade it to use this and further releases of Databricks terraform provider. ### New Features and Improvements * Automatically create `parent_path` folder when creating `databricks_dashboard resource` if it doesn't exist ([#3778](https://github.com/databricks/terraform-provider-databricks/pull/3778)). ### Bug Fixes * Fixed logging for underlying Go SDK ([#3917](https://github.com/databricks/terraform-provider-databricks/pull/3917)). * Remove not necessary field in `databricks_job` schema ([#3907](https://github.com/databricks/terraform-provider-databricks/pull/3907)). ### Internal Changes * Add AttributeBuilder for Plugin Framework schema ([#3922](https://github.com/databricks/terraform-provider-databricks/pull/3922)). * Add CustomizableSchema for Plugin Framework ([#3927](https://github.com/databricks/terraform-provider-databricks/pull/3927)). * Add StructToSchema for Plugin Framework ([#3928](https://github.com/databricks/terraform-provider-databricks/pull/3928)). * Add codegen template and generated files for tfsdk structs ([#3911](https://github.com/databricks/terraform-provider-databricks/pull/3911)). * Add converter functions and tests for plugin framework ([#3914](https://github.com/databricks/terraform-provider-databricks/pull/3914)). * Added support to use protocol version 6 provider server for SDK plugin ([#3862](https://github.com/databricks/terraform-provider-databricks/pull/3862)). * Bump Go SDK to v0.45.0 ([#3933](https://github.com/databricks/terraform-provider-databricks/pull/3933)). * Change name with the aliases in codegen template ([#3936](https://github.com/databricks/terraform-provider-databricks/pull/3936)). * Update jd version from latest to 1.8.1 ([#3915](https://github.com/databricks/terraform-provider-databricks/pull/3915)). * Upgrade `staticcheck` to v0.5.1 to get Go 1.23 support ([#3931](https://github.com/databricks/terraform-provider-databricks/pull/3931)). * OPENAPI_SHA check ([#3935](https://github.com/databricks/terraform-provider-databricks/pull/3935)). * Use generic error for missing clusters ([#3938](https://github.com/databricks/terraform-provider-databricks/pull/3938)) ### Exporter * Better support for notebooks with /Workspace path ([#3901](https://github.com/databricks/terraform-provider-databricks/pull/3901)). * Improve exporting of DLT and test coverage ([#3898](https://github.com/databricks/terraform-provider-databricks/pull/3898)). --- CHANGELOG.md | 72 +++++++++++++++++++++++++++++++++++++++++++++++ common/version.go | 2 +- 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c7171ba1e..aecd839d63 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,77 @@ # Version changelog +## [Release] Release v1.52.0 + +### New Features and Improvements + + * Add support for filters in `databricks_clusters` data source ([#4014](https://github.com/databricks/terraform-provider-databricks/pull/4014)). + * Added `no_wait` option for clusters to skip waiting to start on cluster creation ([#3953](https://github.com/databricks/terraform-provider-databricks/pull/3953)). + * Introduced Plugin Framework ([#3920](https://github.com/databricks/terraform-provider-databricks/pull/3920)). + + +### Bug Fixes + + * Add suppress diff for `azure_attributes.spot_bid_max_price` in `databricks_instance_pool` ([#3970](https://github.com/databricks/terraform-provider-databricks/pull/3970)). + * Correctly send workload_type fields in `databricks_cluster` to allow users to disable usage in certain contexts ([#3972](https://github.com/databricks/terraform-provider-databricks/pull/3972)). + * Fix `databricks_sql_table` treatment of properties ([#3925](https://github.com/databricks/terraform-provider-databricks/pull/3925)). + * Force send fields for settings resources ([#3978](https://github.com/databricks/terraform-provider-databricks/pull/3978)). + * Handle cluster deletion in `databricks_library` read ([#3909](https://github.com/databricks/terraform-provider-databricks/pull/3909)). + * Make subscriptions optional for SqlAlertTask ([#3983](https://github.com/databricks/terraform-provider-databricks/pull/3983)). + * Permanently delete `ERROR` and `TERMINATED` state clusters if their creation fails ([#4021](https://github.com/databricks/terraform-provider-databricks/pull/4021)). + + +### Documentation + + * Add troubleshooting guide for Provider "registry.terraform.io/databricks/databricks" planned an invalid value ([#3961](https://github.com/databricks/terraform-provider-databricks/pull/3961)). + * Adopt official naming of Mosaic AI Vector Search ([#3971](https://github.com/databricks/terraform-provider-databricks/pull/3971)). + * Document Terraform 1.0 as minimum version ([#3952](https://github.com/databricks/terraform-provider-databricks/pull/3952)). + * Mention Salesforce as supported type in `databricks_connection` ([#3949](https://github.com/databricks/terraform-provider-databricks/pull/3949)). + * Reimplement Azure Databricks deployment guide to use VNet injection & NPIP ([#3986](https://github.com/databricks/terraform-provider-databricks/pull/3986)). + * Resolves [#3127](https://github.com/databricks/terraform-provider-databricks/pull/3127): Remove deprecated account_id field from mws_credentials resource ([#3974](https://github.com/databricks/terraform-provider-databricks/pull/3974)). + * Small Grammar Corrections in Docs ([#4006](https://github.com/databricks/terraform-provider-databricks/pull/4006)). + * Update `databricks_vector_search_index` docs to match latest SDK ([#4008](https://github.com/databricks/terraform-provider-databricks/pull/4008)). + * Update aws_unity_catalog_assume_role_policy.md ([#3968](https://github.com/databricks/terraform-provider-databricks/pull/3968)). + * Update documentation regarding authentication with Azure-managed Service Principal using GITHUB OIDC ([#3932](https://github.com/databricks/terraform-provider-databricks/pull/3932)). + * Update metastore_assignment.md to properly reflect possible usage ([#3967](https://github.com/databricks/terraform-provider-databricks/pull/3967)). + * Update minimum supported terraform version to 1.1.5 ([#3965](https://github.com/databricks/terraform-provider-databricks/pull/3965)). + * Update resources diagram to include newer resources ([#3962](https://github.com/databricks/terraform-provider-databricks/pull/3962)). + * Update workspace_binding import command ([#3944](https://github.com/databricks/terraform-provider-databricks/pull/3944)). + * fix possible values for `securable_type` in `databricks_workspace_binding` ([#3942](https://github.com/databricks/terraform-provider-databricks/pull/3942)). + + +### Internal Changes + + * Add `AddPlanModifer` method for AttributeBuilder ([#4009](https://github.com/databricks/terraform-provider-databricks/pull/4009)). + * Add integration tests for volumes and quality monitor plugin framework ([#3975](https://github.com/databricks/terraform-provider-databricks/pull/3975)). + * Add support for `computed` tag in TfSDK Structs ([#4005](https://github.com/databricks/terraform-provider-databricks/pull/4005)). + * Added `databricks_quality_monitor` resource and `databricks_volumes` data source to plugin framework ([#3958](https://github.com/databricks/terraform-provider-databricks/pull/3958)). + * Allow vector search tests to fail ([#3959](https://github.com/databricks/terraform-provider-databricks/pull/3959)). + * Clean up comments in library resource ([#4015](https://github.com/databricks/terraform-provider-databricks/pull/4015)). + * Fix irregularities in plugin framework converter function errors ([#4010](https://github.com/databricks/terraform-provider-databricks/pull/4010)). + * Make test utils public and move integration test for quality monitor ([#3993](https://github.com/databricks/terraform-provider-databricks/pull/3993)). + * Migrate Share resource to Go SDK ([#3916](https://github.com/databricks/terraform-provider-databricks/pull/3916)). + * Migrate `databricks_cluster` data source to plugin framework ([#3988](https://github.com/databricks/terraform-provider-databricks/pull/3988)). + * Migrate imports for terraform plugin framework + update init test provider factory ([#3943](https://github.com/databricks/terraform-provider-databricks/pull/3943)). + * Move volumes test next to plugin framework data source ([#3995](https://github.com/databricks/terraform-provider-databricks/pull/3995)). + * Refactor provider and related packages ([#3940](https://github.com/databricks/terraform-provider-databricks/pull/3940)). + * Support import in acceptance test + adding import state for quality monitor ([#3994](https://github.com/databricks/terraform-provider-databricks/pull/3994)). + * Library plugin framework migration ([#3979](https://github.com/databricks/terraform-provider-databricks/pull/3979)). + * Fix `TestAccClusterResource_WorkloadType` ([#3989](https://github.com/databricks/terraform-provider-databricks/pull/3989)). + + +### Dependency Updates + + * Bump github.com/hashicorp/hcl/v2 from 2.21.0 to 2.22.0 ([#3948](https://github.com/databricks/terraform-provider-databricks/pull/3948)). + * Update Go SDK to 0.46.0 ([#4007](https://github.com/databricks/terraform-provider-databricks/pull/4007)). + + +### Exporter + + * Don't generate instance pools if the pool name is empty ([#3960](https://github.com/databricks/terraform-provider-databricks/pull/3960)). + * Expand list of non-interactive clusters ([#4023](https://github.com/databricks/terraform-provider-databricks/pull/4023)). + * Ignore databricks_artifact_allowlist with zero artifact_matcher blocks ([#4019](https://github.com/databricks/terraform-provider-databricks/pull/4019)). + + ## [Release] Release v1.51.0 ### Breaking Changes diff --git a/common/version.go b/common/version.go index 5deca1da97..417761fcf5 100644 --- a/common/version.go +++ b/common/version.go @@ -3,7 +3,7 @@ package common import "context" var ( - version = "1.51.0" + version = "1.52.0" // ResourceName is resource name without databricks_ prefix ResourceName contextKey = 1 // Provider is the current instance of provider From af46555600f4895d84419675ae445bfe61c4143c Mon Sep 17 00:00:00 2001 From: Miles Yucht Date: Wed, 18 Sep 2024 07:41:00 -0400 Subject: [PATCH 36/54] [Doc] Add guide for OIDC authentication (#4016) ## Changes To encourage users to follow best security practices, we recommend authenticating to Databricks using OIDC where possible. This PR introduces a guide for setting up OIDC from GitHub Actions and Azure DevOps when authenticating to Azure and GCP Databricks. Currently, Databricks on AWS doesn't support OIDC authentication natively. ## Tests - [x] The GCP configuration is used internally already; this just documents how we've set up OIDC. Thanks @hectorcast-db! - [ ] The Azure configuration still needs to be tested. --- docs/guides/azure-authenticate-with-oidc.md | 199 ++++++++++++++++++++ docs/guides/gcp-authenticate-with-oidc.md | 144 ++++++++++++++ 2 files changed, 343 insertions(+) create mode 100644 docs/guides/azure-authenticate-with-oidc.md create mode 100644 docs/guides/gcp-authenticate-with-oidc.md diff --git a/docs/guides/azure-authenticate-with-oidc.md b/docs/guides/azure-authenticate-with-oidc.md new file mode 100644 index 0000000000..85015a77cb --- /dev/null +++ b/docs/guides/azure-authenticate-with-oidc.md @@ -0,0 +1,199 @@ +--- +page_title: "Authenticate with OpenID Connect: Azure" +--- + +# Authenticate with OpenID Connect + +OpenID Connect (OIDC) is an authentication protocol allowing users to authenticate to applications without managing long-lived credentials. The Terraform Provider for Databricks can leverage OIDC to authenticate to Databricks accounts and workspaces. This guide will walk you through the steps to authenticate to Azure Databricks using OIDC on GitHub Actions and Azure DevOps. + +This guide assumes that you have an existing Azure Databricks workspace. + +## GitHub Actions + +### Configure your service principal with federated credentials + +First, you need to create a service principal with federated credentials. This service principal will be used to authenticate to Azure Databricks. You can create a service principal using the `azuread` Terraform provider. + +```hcl +provider "azurerm" { + features {} +} + +resource "azuread_application_registration" "example" { + display_name = "example" +} + +resource "azuread_service_principal" "example" { + application_id = azuread_application_registration.example.application_id +} +``` + +Then, configure the service principal to use federated credentials issued by GitHub Actions. + +```hcl +resource "azuread_application_federated_identity_credential" "example" { + application_id = azuread_application_registration.example.id + display_name = "my-repo-deploy" + description = "Deployments for my-repo" + audiences = ["api://AzureADTokenExchange"] + issuer = "https://token.actions.githubusercontent.com" + subject = "repo:/:environment:" +} +``` + +Finally, grant the service principal access to the workspace. + +```hcl +resource "azurerm_role_assignment" "example" { + scope = "/subscriptions//resourceGroups//providers/Microsoft.Databricks/workspaces/" + role_definition_name = "Contributor" + principal_id = azuread_service_principal.example.id +} +``` + +### Configure the Databricks provider to use the service principal + +In your Terraform configuration, configure the Databricks provider to use the service principal. + +```hcl +provider "databricks" { + azure_client_id = "" + azure_tenant_id = "" + host = "https://" +} +``` + +### Create a GitHub Action that authenticates to Azure Databricks + +To create a GitHub Action, make a `.github/workflows/deploy.yml` file in your repository. + +To authenticate to Azure Databricks using OIDC, ensure that your action has the `id-token: write` permission. You can then authenticate to Azure using the `azure/login` action. Finally, run `terraform apply` with the `azure/cli` action. + +```yaml +name: Deploy to Azure Databricks +jobs: + deploy: + runs-on: ubuntu-latest + environments: production + permissions: + id-token: write + contents: read + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Set up Terraform + uses: hashicorp/setup-terraform@v3 + + - name: Apply Terraform + run: | + terraform init + terraform plan + terraform apply -auto-approve + working-directory: path/to/terraform/module +``` + +### (Optional) GitHub Actions Details + +The `subject` field is used to scope the federated credentials to a specific GitHub Actions environment. The `subject` field is a string in the format `repo:/:environment:`. The `organization`, `repo`, and `environment` fields should be replaced with the appropriate values. + +If the action runs without an environment context, the `subject` field should be set to `repo:/:ref:refs/heads/` if the workflow is triggered from a branch, or `repo:/:ref:refs/tags/` when triggered from a tag. + +If needed, it is also possible to configure the `subject` field for your organization or repository. See the [GitHub Actions OIDC documentation](https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/about-security-hardening-with-openid-connect) for more information about how to configure the `subject` field. + +## Azure DevOps + +In Azure DevOps, you can use Workload Identity federation to authenticate to Azure Databricks using OIDC. This allows you to authenticate to Azure Databricks using federated credentials issued by Azure DevOps. Today, the Terraform Provider for Databricks leverages the Azure CLI to use workflow identity federation in Azure DevOps. This guide will walk you through the steps to authenticate to Azure Databricks using OIDC on Azure DevOps. + +### Configure a service connection for your DevOps pipeline + +First, you need to create a service principal in Azure Entra ID with federated credentials. This principal will be used to authenticate to Azure Databricks. You can create it using the `azuread` Terraform provider with the following template: + +```hcl +provider "azurerm" { + features {} +} + +resource "azuread_application_registration" "example" { + display_name = "example" +} + +resource "azuread_service_principal" "example" { + application_id = azuread_application_registration.example.application_id +} +``` + +Then, configure the service principal to use federated credentials issued by Azure DevOps. + +```hcl +resource "azuread_application_federated_identity_credential" "example" { + application_id = azuread_application_registration.example.id + display_name = "my-repo-deploy" + description = "Deployments for my-repo" + audiences = ["api://AzureADTokenExchange"] + issuer = "https://vstoken.dev.azure.com/" + subject = "sc:////" +} +``` + +Finally, grant the service principal access to the workspace. + +```hcl +resource "azurerm_role_assignment" "example" { + scope = "/subscriptions//resourceGroups//providers/Microsoft.Databricks/workspaces/" + role_definition_name = "Contributor" + principal_id = azuread_service_principal.example.id +} +``` + +In Azure DevOps, navigate to the project settings and create a new service connection. Select `Azure Resource Manager`, then `Workload Identity federation (manual)` and enter the subscription ID, subscription name, service principal ID and tenant ID in the dialog. Note that the Issuer and Subject Identifier fields must match the `issuer` and `subject` attributes of the `azuread_application_federated_identity_credential` resource. + +### Configure the Databricks provider to use the service principal + +In your Terraform configuration, configure the Databricks provider to use the service principal. + +```hcl +provider "databricks" { + azure_client_id = "" + azure_tenant_id = "" + host = "https://" +} +``` + +### Create a DevOps Pipeline that authenticates to Azure Databricks + +To create a pipeline, make a `pipelines/deploy.yml` file in your repository. + +To authenticate to Azure Databricks using OIDC, use the `AzureCLI@2` task. This automatically authenticates the Azure CLI using the service connection you created earlier. The Terraform Provider for Databricks will detect the authenticated CLI and use it to authenticate to Azure Databricks. + +```yaml +steps: + - task: Checkout@1 + displayName: "Checkout repository" + inputs: + repository: "self" + path: "main" + + - task: TerraformInstaller@0 + inputs: + terraformVersion: "latest" + + - task: AzureCLI@2 + displayName: "TF init" + inputs: + azureSubscription: + scriptType: bash + scriptLocation: inlineScript + workingDirectory: "$(Pipeline.Workspace)/main//path/to/terraform/module" + inlineScript: | + terraform init + terraform plan + terraform apply -auto-approve +``` + +## References + +For more information about OIDC and the above OIDC providers, see the following resources: + +- [GitHub Actions OIDC documentation](https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/about-security-hardening-with-openid-connect) +- [Azure DevOps Workload federation blog post](https://devblogs.microsoft.com/devops/introduction-to-azure-devops-workload-identity-federation-oidc-with-terraform/) diff --git a/docs/guides/gcp-authenticate-with-oidc.md b/docs/guides/gcp-authenticate-with-oidc.md new file mode 100644 index 0000000000..873d3ec96b --- /dev/null +++ b/docs/guides/gcp-authenticate-with-oidc.md @@ -0,0 +1,144 @@ +--- +page_title: "Authenticate with OpenID Connect: Google Cloud" +--- + +# Authenticate with OpenID Connect + +OpenID Connect (OIDC) is an authentication protocol allowing users to authenticate to applications without managing long-lived credentials. The Terraform Provider for Databricks can leverage OIDC to authenticate to Databricks accounts and workspaces. For Databricks on Google Cloud, the provider can authenticate leveraging OIDC using workload identity pools. This guide will walk you through the steps to authenticate to Databricks using OIDC on GitHub Actions. + +This guide assumes that you have an existing GCP Databricks workspace. + +## GitHub Actions + +### Configure your service account and workload identity pool + +First, you need to create a service account and a workload identity pool. The pool is configured to allow clients using OIDC to assume the identity of the service account. The service account will be used to authenticate to Databricks on GCP. You can create a service account using the `google` Terraform provider. + +```hcl +provider "google" { + features {} +} + +resource "google_service_account" "github_actions" { + project = "" + account_id = "github-actions" + display_name = "GitHub Actions Service Account" +} +``` + +Then, create the workload identity pool, and configure it to use the service account. + +```hcl +resource "google_iam_workload_identity_pool" "github_pool" { + project = "" + workload_identity_pool_id = "github-pool" + display_name = "GitHub Actions Pool" + description = "Identity pool for GitHub Actions" +} + +resource "google_iam_workload_identity_pool_provider" "github_provider" { + project = "" + workload_identity_pool_id = google_iam_workload_identity_pool.github_pool.workload_identity_pool_id + workload_identity_pool_provider_id = "github-provider" + display_name = "GitHub Actions Provider" + attribute_mapping = { + "google.subject" = "assertion.sub" + "attribute.actor" = "assertion.actor" + "attribute.repository" = "assertion.repository" + "attribute.ref" = "assertion.ref" + "attribute.event_name" = "assertion.event_name" + } + oidc { + issuer_uri = "https://token.actions.githubusercontent.com" + } + attribute_condition = "assertion.sub == 'repo:/:environment:'" +} + +resource "google_service_account_iam_binding" "workload_identity_user" { + service_account_id = google_service_account.github_actions.name + role = "roles/iam.workloadIdentityUser" + members = [ + "principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.github_pool.name}/attribute.repository//" + ] +} + +resource "google_project_iam_member" "token_creator_binding" { + project = module.defaults.google_project_isolated + role = "roles/iam.serviceAccountTokenCreator" + member = "serviceAccount:${google_service_account.github_actions.email}" +} +``` + +Finally, grant the service principal access to the workspace by following the instructions in the [Databricks documentation](https://docs.gcp.databricks.com/en/dev-tools/google-id-auth.html#step-2-assign-your-google-cloud-service-account-to-your-databricks-account). + +### Configure the Databricks provider to use the service principal + +In your Terraform configuration, configure the Databricks provider to use the service principal. + +```hcl +# account-level provider +provider "databricks" { + host = "https://accounts.gcp.databricks.com" + account_id = "" + google_service_account = google_service_account.github_actions.email +} + +# workspace-level provider +provider "databricks" { + host = "https://" + google_service_account = google_service_account.github_actions.email +} +``` + +### Create a GitHub Action that authenticates to Databricks on Google Cloud + +To create a GitHub Action, make a `.github/workflows/deploy.yml` file in your repository. + +To authenticate to Databricks using OIDC, ensure that your action has the `id-token: write` permission. You can then authenticate to Google using the `google-github-actions/auth` action. Finally, run `terraform apply`. + +```yaml +name: Deploy to Databricks on GCP +jobs: + deploy: + runs-on: ubuntu-latest + environments: production + permissions: + id-token: write + contents: read + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: "Authenticate to Google Cloud" + uses: "google-github-actions/auth@v2" + with: + token_format: "access_token" + workload_identity_provider: "projects//locations/global/workloadIdentityPools/github-pool/providers/github-provider" + service_account: "" + + - name: Set up Terraform + uses: hashicorp/setup-terraform@v3 + + - name: Terraform Init + run: terraform init + working-directory: path/to/terraform/module +``` + +### (Optional) GitHub Actions Details + +The `subject` field is used to scope the federated credentials to a specific GitHub Actions environment. The `subject` field is a string in the format `repo:/:environment:`. The `organization`, `repo`, and `environment` fields should be replaced with the appropriate values. + +If the action runs without an environment context, the `subject` field should be set to `repo:/:ref:refs/heads/` if the workflow is triggered from a branch, or `repo:/:ref:refs/tags/` when triggered from a tag. + +If needed, it is also possible to configure the `subject` field for your organization or repository. See the [GitHub Actions OIDC documentation](https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/about-security-hardening-with-openid-connect) for more information about how to configure the `subject` field. + +### (Optional) Restrict access to the workload identity pool + +The workload identity pool provider can be configured to restrict access to specific repositories, branches, or tags. The `attribute_condition` field in the `google_iam_workload_identity_pool_provider` resource specifies the conditions under which the provider will issue tokens. See [the Google Cloud reference](https://cloud.google.com/iam/docs/workload-identity-federation#conditions) for more information. + +## References + +For more information about OIDC and the above OIDC providers, see the following resources: + +- [GitHub Actions OIDC documentation](https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/about-security-hardening-with-openid-connect) +- [Google Cloud Workload Identity documentation](https://cloud.google.com/iam/docs/workload-identity-federation) From b827aeccb86c1cd7c5803e8a755d7085ebbdb207 Mon Sep 17 00:00:00 2001 From: Alex Ott Date: Tue, 24 Sep 2024 03:34:33 +0200 Subject: [PATCH 37/54] [Doc] Fixing links to `databricks_service_principal` in TF guides (#4020) ## Changes Resolves #4017 ## Tests - [ ] `make test` run locally - [x] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [ ] using Go SDK --- docs/guides/aws-e2-firewall-hub-and-spoke.md | 2 +- docs/guides/aws-e2-firewall-workspace.md | 2 +- docs/guides/aws-workspace.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/guides/aws-e2-firewall-hub-and-spoke.md b/docs/guides/aws-e2-firewall-hub-and-spoke.md index 78c0ff0cb2..9b5f785f67 100644 --- a/docs/guides/aws-e2-firewall-hub-and-spoke.md +++ b/docs/guides/aws-e2-firewall-hub-and-spoke.md @@ -12,7 +12,7 @@ You can provision multiple Databricks workspaces with Terraform, and where many ## Provider initialization for AWS workspaces -This guide assumes you have the `client_id`, which is the `application_id` of the [Service Principal](resources/service_principal.md), `client_secret`, which is its secret, and `databricks_account_id`, which can be found in the top right corner of the [Account Console](https://accounts.cloud.databricks.com). (see [instruction](https://docs.databricks.com/dev-tools/authentication-oauth.html#step-2-create-an-oauth-secret-for-a-service-principal)). This guide is provided as is and assumes you will use it as the basis for your setup. If you use AWS Firewall to block most traffic but allow the URLs to which Databricks needs to connect, please update the configuration based on your region. You can get the configuration details for your region from [Firewall Appliance](https://docs.databricks.com/administration-guide/cloud-configurations/aws/customer-managed-vpc.html#firewall-appliance-infrastructure) document. +This guide assumes you have the `client_id`, which is the `application_id` of the [Service Principal](../resources/service_principal.md), `client_secret`, which is its secret, and `databricks_account_id`, which can be found in the top right corner of the [Account Console](https://accounts.cloud.databricks.com). (see [instruction](https://docs.databricks.com/dev-tools/authentication-oauth.html#step-2-create-an-oauth-secret-for-a-service-principal)). This guide is provided as is and assumes you will use it as the basis for your setup. If you use AWS Firewall to block most traffic but allow the URLs to which Databricks needs to connect, please update the configuration based on your region. You can get the configuration details for your region from [Firewall Appliance](https://docs.databricks.com/administration-guide/cloud-configurations/aws/customer-managed-vpc.html#firewall-appliance-infrastructure) document. ```hcl variable "client_id" {} diff --git a/docs/guides/aws-e2-firewall-workspace.md b/docs/guides/aws-e2-firewall-workspace.md index d7b00334f9..5e7af4c57c 100644 --- a/docs/guides/aws-e2-firewall-workspace.md +++ b/docs/guides/aws-e2-firewall-workspace.md @@ -14,7 +14,7 @@ For more information, please visit [Data Exfiltration Protection With Databricks ## Provider initialization for AWS workspaces -This guide assumes you have the `client_id`, which is the `application_id` of the [Service Principal](resources/service_principal.md), `client_secret`, which is its secret, and `databricks_account_id`, which can be found in the top right corner of the [Account Console](https://accounts.cloud.databricks.com). (see [instruction](https://docs.databricks.com/dev-tools/authentication-oauth.html#step-2-create-an-oauth-secret-for-a-service-principal)). This guide is provided as is and assumes you will use it as the basis for your setup. If you are using AWS Firewall to block most traffic but allow the URLs that Databricks needs to connect to, please update the configuration based on your region. You can get the configuration details for your region from [Firewall Appliance](https://docs.databricks.com/administration-guide/cloud-configurations/aws/customer-managed-vpc.html#firewall-appliance-infrastructure) document. +This guide assumes you have the `client_id`, which is the `application_id` of the [Service Principal](../resources/service_principal.md), `client_secret`, which is its secret, and `databricks_account_id`, which can be found in the top right corner of the [Account Console](https://accounts.cloud.databricks.com). (see [instruction](https://docs.databricks.com/dev-tools/authentication-oauth.html#step-2-create-an-oauth-secret-for-a-service-principal)). This guide is provided as is and assumes you will use it as the basis for your setup. If you are using AWS Firewall to block most traffic but allow the URLs that Databricks needs to connect to, please update the configuration based on your region. You can get the configuration details for your region from [Firewall Appliance](https://docs.databricks.com/administration-guide/cloud-configurations/aws/customer-managed-vpc.html#firewall-appliance-infrastructure) document. ```hcl variable "client_id" {} diff --git a/docs/guides/aws-workspace.md b/docs/guides/aws-workspace.md index 596076f66c..47b9e15e24 100644 --- a/docs/guides/aws-workspace.md +++ b/docs/guides/aws-workspace.md @@ -12,7 +12,7 @@ You can provision multiple Databricks workspaces with Terraform. ## Provider initialization for AWS workspaces -This guide assumes you have the `client_id`, which is the `application_id` of the [Service Principal](resources/service_principal.md), `client_secret`, which is its secret, and `databricks_account_id`, which can be found in the top right corner of the [Account Console](https://accounts.cloud.databricks.com). (see [instruction](https://docs.databricks.com/dev-tools/authentication-oauth.html#step-2-create-an-oauth-secret-for-a-service-principal)). This guide is provided as is and assumes you will use it as the basis for your setup. +This guide assumes you have the `client_id`, which is the `application_id` of the [Service Principal](../resources/service_principal.md), `client_secret`, which is its secret, and `databricks_account_id`, which can be found in the top right corner of the [Account Console](https://accounts.cloud.databricks.com). (see [instruction](https://docs.databricks.com/dev-tools/authentication-oauth.html#step-2-create-an-oauth-secret-for-a-service-principal)). This guide is provided as is and assumes you will use it as the basis for your setup. ```hcl variable "client_id" {} From ae06c79a8faefce0faf97a48fe89e4826bee1ff9 Mon Sep 17 00:00:00 2001 From: Alex Ott Date: Sat, 28 Sep 2024 13:16:23 +0200 Subject: [PATCH 38/54] [Feature] Add computed attribute `table_serving_url` to `databricks_online_table` (#4048) ## Changes New attribute was added, but it wasn't marked as `computed` in the TF resource definition ## Tests - [x] `make test` run locally - [x] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [x] using Go SDK --- catalog/resource_online_table.go | 1 + docs/resources/online_table.md | 1 + 2 files changed, 2 insertions(+) diff --git a/catalog/resource_online_table.go b/catalog/resource_online_table.go index 0dd75ffe90..ca46b8eed1 100644 --- a/catalog/resource_online_table.go +++ b/catalog/resource_online_table.go @@ -59,6 +59,7 @@ func ResourceOnlineTable() common.Resource { common.CustomizeSchemaPath(m, "spec", "source_table_full_name").SetCustomSuppressDiff(common.EqualFoldDiffSuppress) common.CustomizeSchemaPath(m, "name").SetRequired().SetForceNew() common.CustomizeSchemaPath(m, "status").SetReadOnly() + common.CustomizeSchemaPath(m, "table_serving_url").SetReadOnly() common.CustomizeSchemaPath(m, "spec", "pipeline_id").SetReadOnly() runTypes := []string{"spec.0.run_triggered", "spec.0.run_continuously"} diff --git a/docs/resources/online_table.md b/docs/resources/online_table.md index 66aa48025c..dbaaeafa58 100644 --- a/docs/resources/online_table.md +++ b/docs/resources/online_table.md @@ -50,6 +50,7 @@ In addition to all arguments above, the following attributes are exported: * `status` - object describing status of the online table: * `detailed_state` - The state of the online table. * `message` - A text description of the current state of the online table. +* `table_serving_url` - Data serving REST API URL for this table. ## Import From 1cfc531666d0179395a170f5ea61decfe22bf881 Mon Sep 17 00:00:00 2001 From: hectorcast-db Date: Mon, 30 Sep 2024 11:02:22 +0200 Subject: [PATCH 39/54] [Feature] Add support for Identity Column in `databricks_sql_table` (#4035) ## Changes Add support for Identity Column in `databricks_sql_table` ## Tests - [X] `make test` run locally - [X] relevant change in `docs/` folder - [X] covered with integration tests in `internal/acceptance` - [X] relevant acceptance tests are passing - [X] using Go SDK --------- Co-authored-by: Miles Yucht --- catalog/resource_sql_table.go | 70 +++++++++- catalog/resource_sql_table_test.go | 193 ++++++++++++++++++++++++++ docs/resources/sql_table.md | 41 ++++++ internal/acceptance/sql_table_test.go | 64 +++++++++ 4 files changed, 363 insertions(+), 5 deletions(-) diff --git a/catalog/resource_sql_table.go b/catalog/resource_sql_table.go index 922d2d0cd2..ce9d4dbd7a 100644 --- a/catalog/resource_sql_table.go +++ b/catalog/resource_sql_table.go @@ -2,6 +2,7 @@ package catalog import ( "context" + "encoding/json" "fmt" "log" "reflect" @@ -22,12 +23,24 @@ import ( var MaxSqlExecWaitTimeout = 50 type SqlColumnInfo struct { - Name string `json:"name"` - Type string `json:"type_text,omitempty" tf:"alias:type,computed"` - Comment string `json:"comment,omitempty"` - Nullable bool `json:"nullable,omitempty" tf:"default:true"` + Name string `json:"name"` + Type string `json:"type_text,omitempty" tf:"alias:type,computed"` + Identity IdentityColumn `json:"identity,omitempty"` + Comment string `json:"comment,omitempty"` + Nullable bool `json:"nullable,omitempty" tf:"default:true"` + TypeJson string `json:"type_json,omitempty" tf:"computed"` } +type TypeJson struct { + Metadata map[string]any `json:"metadata,omitempty"` +} + +type IdentityColumn string + +const IdentityColumnNone IdentityColumn = "" +const IdentityColumnAlways IdentityColumn = "always" +const IdentityColumnDefault IdentityColumn = "default" + type SqlTableInfo struct { Name string `json:"name"` CatalogName string `json:"catalog_name" tf:"force_new"` @@ -108,6 +121,28 @@ func parseComment(s string) string { return strings.ReplaceAll(strings.ReplaceAll(s, `\'`, `'`), `'`, `\'`) } +func reconstructIdentity(c *SqlColumnInfo) (IdentityColumn, error) { + if c.TypeJson == "" { + return IdentityColumnNone, nil + } + var typeJson TypeJson + err := json.Unmarshal([]byte(c.TypeJson), &typeJson) + if err != nil { + return IdentityColumnNone, err + } + if _, ok := typeJson.Metadata["delta.identity.start"]; !ok { + return IdentityColumnNone, nil + } + explicit, ok := typeJson.Metadata["delta.identity.allowExplicitInsert"] + if !ok { + return IdentityColumnNone, nil + } + if explicit.(bool) { + return IdentityColumnDefault, nil + } + return IdentityColumnAlways, nil +} + func (ti *SqlTableInfo) initCluster(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) (err error) { defaultClusterName := "terraform-sql-table" clustersAPI := clusters.NewClustersAPI(ctx, c) @@ -171,7 +206,22 @@ func (ti *SqlTableInfo) getOrCreateCluster(clusterName string, clustersAPI clust return aclCluster.ClusterID, nil } +func (ci *SqlColumnInfo) getColumnType() string { + var colType string + switch ci.Identity { + case IdentityColumnAlways: + colType = fmt.Sprintf("%s GENERATED ALWAYS AS IDENTITY", ci.Type) + case IdentityColumnDefault: + colType = fmt.Sprintf("%s GENERATED BY DEFAULT AS IDENTITY", ci.Type) + default: + colType = ci.Type + } + return colType +} + func (ti *SqlTableInfo) serializeColumnInfo(col SqlColumnInfo) string { + var colType = col.getColumnType() + notNull := "" if !col.Nullable { notNull = " NOT NULL" @@ -181,7 +231,7 @@ func (ti *SqlTableInfo) serializeColumnInfo(col SqlColumnInfo) string { if col.Comment != "" { comment = fmt.Sprintf(" COMMENT '%s'", parseComment(col.Comment)) } - return fmt.Sprintf("%s %s%s%s", col.getWrappedColumnName(), col.Type, notNull, comment) // id INT NOT NULL COMMENT 'something' + return fmt.Sprintf("%s %s%s%s", col.getWrappedColumnName(), colType, notNull, comment) // id INT NOT NULL COMMENT 'something' } func (ti *SqlTableInfo) serializeColumnInfos() string { @@ -502,6 +552,9 @@ func assertNoColumnTypeDiff(oldCols []interface{}, newColumnInfos []SqlColumnInf if getColumnType(oldColMap["type"].(string)) != getColumnType(newColumnInfos[i].Type) { return fmt.Errorf("changing the 'type' of an existing column is not supported") } + if oldColMap["identity"].(string) != string(newColumnInfos[i].Identity) { + return fmt.Errorf("changing the 'identity' type of an existing column is not supported") + } } return nil } @@ -602,6 +655,13 @@ func ResourceSqlTable() common.Resource { if err != nil { return err } + for i := range ti.ColumnInfos { + c := &ti.ColumnInfos[i] + c.Identity, err = reconstructIdentity(c) + if err != nil { + return err + } + } return common.StructToData(ti, tableSchema, d) }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { diff --git a/catalog/resource_sql_table_test.go b/catalog/resource_sql_table_test.go index 795a1d3f31..f2f0a6c5e2 100644 --- a/catalog/resource_sql_table_test.go +++ b/catalog/resource_sql_table_test.go @@ -35,6 +35,36 @@ func TestResourceSqlTableCreateStatement_External(t *testing.T) { assert.Contains(t, stmt, "COMMENT 'terraform managed'") } +func TestResourceSqlTableCreateStatement_IdentityColumn(t *testing.T) { + ti := &SqlTableInfo{ + Name: "bar", + CatalogName: "main", + SchemaName: "foo", + TableType: "EXTERNAL", + DataSourceFormat: "DELTA", + StorageLocation: "s3://ext-main/foo/bar1", + StorageCredentialName: "somecred", + Comment: "terraform managed", + ColumnInfos: []SqlColumnInfo{ + { + Name: "id", + Type: "bigint", + Identity: "default", + }, + { + Name: "name", + Comment: "a comment", + }, + }, + } + stmt := ti.buildTableCreateStatement() + assert.Contains(t, stmt, "CREATE EXTERNAL TABLE `main`.`foo`.`bar`") + assert.Contains(t, stmt, "USING DELTA") + assert.Contains(t, stmt, "(`id` bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, `name` NOT NULL COMMENT 'a comment')") + assert.Contains(t, stmt, "LOCATION 's3://ext-main/foo/bar1' WITH (CREDENTIAL `somecred`)") + assert.Contains(t, stmt, "COMMENT 'terraform managed'") +} + func TestResourceSqlTableCreateStatement_View(t *testing.T) { ti := &SqlTableInfo{ Name: "bar", @@ -1334,6 +1364,169 @@ func TestResourceSqlTableCreateTable_ExistingSQLWarehouse(t *testing.T) { assert.NoError(t, err) } +func TestResourceSqlTableCreateTableWithIdentityColumn_ExistingSQLWarehouse(t *testing.T) { + qa.ResourceFixture{ + CommandMock: func(commandStr string) common.CommandResults { + return common.CommandResults{ + ResultType: "", + Data: nil, + } + }, + HCL: ` + name = "bar" + catalog_name = "main" + schema_name = "foo" + table_type = "MANAGED" + data_source_format = "DELTA" + storage_location = "abfss://container@account/somepath" + warehouse_id = "existingwarehouse" + + column { + name = "id" + type = "bigint" + identity = "default" + } + column { + name = "name" + type = "string" + comment = "name of thing" + } + column { + name = "number" + type = "bigint" + identity = "always" + } + comment = "this table is managed by terraform" + `, + Fixtures: []qa.HTTPFixture{ + { + Method: "POST", + Resource: "/api/2.0/sql/statements/", + ExpectedRequest: sql.ExecuteStatementRequest{ + Statement: "CREATE TABLE `main`.`foo`.`bar` (`id` bigint GENERATED BY DEFAULT AS IDENTITY, `name` string COMMENT 'name of thing', `number` bigint GENERATED ALWAYS AS IDENTITY)\nUSING DELTA\nCOMMENT 'this table is managed by terraform'\nLOCATION 'abfss://container@account/somepath';", + WaitTimeout: "50s", + WarehouseId: "existingwarehouse", + OnWaitTimeout: sql.ExecuteStatementRequestOnWaitTimeoutCancel, + }, + Response: sql.StatementResponse{ + StatementId: "statement1", + Status: &sql.StatementStatus{ + State: "SUCCEEDED", + }, + }, + }, + { + Method: "GET", + Resource: "/api/2.1/unity-catalog/tables/main.foo.bar", + Response: SqlTableInfo{ + Name: "bar", + CatalogName: "main", + SchemaName: "foo", + TableType: "EXTERNAL", + DataSourceFormat: "DELTA", + StorageLocation: "s3://ext-main/foo/bar1", + StorageCredentialName: "somecred", + Comment: "terraform managed", + Properties: map[string]string{ + "one": "two", + "three": "four", + }, + ColumnInfos: []SqlColumnInfo{ + { + Name: "id", + Type: "bigint", + TypeJson: "{\"type\":\"bigint\",\"nullable\":true, \"metadata\":{\"delta.identity.start\":1,\"delta.identity.allowExplicitInsert\":true}}", + }, + { + Name: "name", + Type: "string", + Comment: "name of thing", + }, + { + Name: "number", + Type: "bigint", + TypeJson: "{\"type\":\"bigint\",\"nullable\":true, \"metadata\":{\"delta.identity.start\":1,\"delta.identity.allowExplicitInsert\":false}}", + }, + }, + }, + }, + }, + Create: true, + Resource: ResourceSqlTable(), + }.ApplyAndExpectData(t, map[string]any{ + "column.0.identity": "default", + "column.1.identity": "", + "column.2.identity": "always", + }) +} + +func TestResourceSqlTableReadTableWithIdentityColumn_ExistingSQLWarehouse(t *testing.T) { + qa.ResourceFixture{ + CommandMock: func(commandStr string) common.CommandResults { + return common.CommandResults{ + ResultType: "", + Data: nil, + } + }, + HCL: ` + name = "bar" + catalog_name = "main" + schema_name = "foo" + table_type = "MANAGED" + data_source_format = "DELTA" + storage_location = "abfss://container@account/somepath" + warehouse_id = "existingwarehouse" + + + comment = "this table is managed by terraform" + `, + Fixtures: []qa.HTTPFixture{ + { + Method: "GET", + Resource: "/api/2.1/unity-catalog/tables/main.foo.bar", + Response: SqlTableInfo{ + Name: "bar", + CatalogName: "main", + SchemaName: "foo", + TableType: "EXTERNAL", + DataSourceFormat: "DELTA", + StorageLocation: "s3://ext-main/foo/bar1", + StorageCredentialName: "somecred", + Comment: "terraform managed", + Properties: map[string]string{ + "one": "two", + "three": "four", + }, + ColumnInfos: []SqlColumnInfo{ + { + Name: "id", + Type: "bigint", + TypeJson: "{\"type\":\"bigint\",\"nullable\":true, \"metadata\":{\"delta.identity.start\":1,\"delta.identity.allowExplicitInsert\":false}}", + }, + { + Name: "name", + Type: "string", + Comment: "name of thing", + }, + { + Name: "number", + Type: "bigint", + TypeJson: "{\"type\":\"bigint\",\"nullable\":true, \"metadata\":{\"delta.identity.start\":1,\"delta.identity.allowExplicitInsert\":true}}", + }, + }, + }, + }, + }, + ID: "main.foo.bar", + Read: true, + Resource: ResourceSqlTable(), + }.ApplyAndExpectData(t, map[string]any{ + "column.0.identity": "always", + "column.1.identity": "", + "column.2.identity": "default", + }) +} + func TestResourceSqlTableCreateTable_OnlyManagedProperties(t *testing.T) { qa.ResourceFixture{ CommandMock: func(commandStr string) common.CommandResults { diff --git a/docs/resources/sql_table.md b/docs/resources/sql_table.md index aeec6d9ce9..67483248d6 100644 --- a/docs/resources/sql_table.md +++ b/docs/resources/sql_table.md @@ -109,6 +109,46 @@ resource "databricks_sql_table" "thing_view" { } ``` +## Use an Identity Column + +```hcl +resource "databricks_catalog" "sandbox" { + name = "sandbox" + comment = "this catalog is managed by terraform" + properties = { + purpose = "testing" + } +} +resource "databricks_schema" "things" { + catalog_name = databricks_catalog.sandbox.id + name = "things" + comment = "this database is managed by terraform" + properties = { + kind = "various" + } +} +resource "databricks_sql_table" "thing" { + provider = databricks.workspace + name = "quickstart_table" + catalog_name = databricks_catalog.sandbox.name + schema_name = databricks_schema.things.name + table_type = "MANAGED" + data_source_format = "DELTA" + storage_location = "" + column { + name = "id" + type = "bigint" + identity = "default" + } + column { + name = "name" + type = "string" + comment = "name of thing" + } + comment = "this table is managed by terraform" +} +``` + ## Argument Reference The following arguments are supported: @@ -137,6 +177,7 @@ Currently, changing the column definitions for a table will require dropping and * `name` - User-visible name of column * `type` - Column type spec (with metadata) as SQL text. Not supported for `VIEW` table_type. +* `identity` - (Optional) Whether field is an identity column. Can be `default`, `always` or unset. It is unset by default. * `comment` - (Optional) User-supplied free-form text. * `nullable` - (Optional) Whether field is nullable (Default: `true`) diff --git a/internal/acceptance/sql_table_test.go b/internal/acceptance/sql_table_test.go index 0f0a87dec9..6ba5a83714 100644 --- a/internal/acceptance/sql_table_test.go +++ b/internal/acceptance/sql_table_test.go @@ -72,6 +72,70 @@ func TestUcAccResourceSqlTable_Managed(t *testing.T) { }) } +func TestUcAccResourceSqlTableWithIdentityColumn_Managed(t *testing.T) { + if os.Getenv("GOOGLE_CREDENTIALS") != "" { + skipf(t)("databricks_sql_table resource not available on GCP") + } + UnityWorkspaceLevel(t, Step{ + Template: ` + resource "databricks_schema" "this" { + name = "{var.STICKY_RANDOM}" + catalog_name = "main" + } + + resource "databricks_sql_table" "this" { + name = "bar" + catalog_name = "main" + schema_name = databricks_schema.this.name + table_type = "MANAGED" + properties = { + this = "that" + something = "else" + } + + column { + name = "id" + type = "bigint" + identity = "default" + } + column { + name = "name" + type = "string" + } + comment = "this table is managed by terraform" + owner = "account users" + }`, + }, Step{ + Template: ` + resource "databricks_schema" "this" { + name = "{var.STICKY_RANDOM}" + catalog_name = "main" + } + + resource "databricks_sql_table" "this" { + name = "bar" + catalog_name = "main" + schema_name = databricks_schema.this.name + table_type = "MANAGED" + properties = { + that = "this" + something = "else2" + } + + column { + name = "id" + type = "bigint" + identity = "default" + } + column { + name = "name" + type = "string" + } + comment = "this table is managed by terraform..." + }`, + }) +} + func TestUcAccResourceSqlTable_External(t *testing.T) { UnityWorkspaceLevel(t, Step{ Template: ` From 9c2bf50e4fbfcc19774c38583a02745c727a8d20 Mon Sep 17 00:00:00 2001 From: Miles Yucht Date: Tue, 1 Oct 2024 07:26:13 -0400 Subject: [PATCH 40/54] [Fix] Refactor `databricks_permissions` and allow the current user to set their own permissions (#3956) ## Changes In https://github.com/databricks/terraform-provider-databricks/commit/c441517af5ed3f2c6d793d64d5cf5d4e1ca0dc68, a check was added to prevent users from assigning any permissions for themselves in `databricks_permissions`. This unfortunately makes it impossible for users to legitimately assign themselves as the owner of certain resources, such as jobs, if they are currently owned by a different principal. This PR removes this unnecessary restriction. If the user requests to set permissions for an object in a way that is incompatible with the object, such as removing themselves as owner, the failure will be propagated from the backend to the user instead. This does not make any changes to the way the ownership ACLs are set up (e.g. for resources that require an owner, like jobs, if the Terraform user did not specify an owner, the provider will still set the current user as the owner). This PR also refactors the permissions resource substantially. The logic for implementing each resource type's permissions, including the field name, object type and resource-specific modifications, are all colocated with the resource's own definition. The type encapsulating this is called`resourcePermissions`. As a result, the control flow is easier to follow: * Read reads from the API, customizes the response in a resource-specific way, maps the response to the TF state representation, and stores, or marks as deleted if there are no permissions. * Create and Update read the desired permissions from ResourceData, perform some validation, perform resource-specific, then puts the update with an owner if not specified. * Delete resets the ACLs to only admins + resource-specific customizations. Customizations are defined in the permissions/read and permissions/update packages. For update, a mini expression language is defined to support conditional application of customizations. Lastly, this PR also migrates the resource to the Databricks SDK. Fixes #2407. ## Tests This PR adds integration test coverage for the `databricks_permissions` resource for nearly all supported resource types. I wasn't able to run the integration test for `authorization = "passwords"` because password-based auth is deprecated, nor for serving endpoints because of a likely race condition. Integration tests cover all permission levels, and all principal types. Included is special edge case testing for root directory and all registered models. - [ ] `make test` run locally - [x] relevant change in `docs/` folder - [x] covered with integration tests in `internal/acceptance` - [x] relevant acceptance tests are passing - [ ] using Go SDK --- docs/resources/permissions.md | 6 +- exporter/exporter_test.go | 48 +- exporter/importables.go | 4 +- exporter/importables_test.go | 5 +- internal/acceptance/permissions_test.go | 970 ++++++++-- permissions/entity/permissions_entity.go | 18 + permissions/permission_definitions.go | 731 ++++++++ permissions/read/customizers.go | 54 + permissions/resource_permissions.go | 540 ++---- permissions/resource_permissions_test.go | 2110 ++++++++++------------ permissions/update/customizers.go | 97 + 11 files changed, 2833 insertions(+), 1750 deletions(-) create mode 100644 permissions/entity/permissions_entity.go create mode 100644 permissions/permission_definitions.go create mode 100644 permissions/read/customizers.go create mode 100644 permissions/update/customizers.go diff --git a/docs/resources/permissions.md b/docs/resources/permissions.md index ef5e1c4de8..b47a43aba3 100644 --- a/docs/resources/permissions.md +++ b/docs/resources/permissions.md @@ -4,11 +4,11 @@ subcategory: "Security" # databricks_permissions Resource -This resource allows you to generically manage [access control](https://docs.databricks.com/security/access-control/index.html) in Databricks workspace. It would guarantee that only _admins_, _authenticated principal_ and those declared within `access_control` blocks would have specified access. It is not possible to remove management rights from _admins_ group. +This resource allows you to generically manage [access control](https://docs.databricks.com/security/access-control/index.html) in Databricks workspaces. It ensures that only _admins_, _authenticated principal_ and those declared within `access_control` blocks would have specified access. It is not possible to remove management rights from _admins_ group. --> **Note** Configuring this resource for an object will **OVERWRITE** any existing permissions of the same type unless imported, and changes made outside of Terraform will be reset unless the changes are also reflected in the configuration. +-> **Note** This resource is _authoritative_ for permissions on objects. Configuring this resource for an object will **OVERWRITE** any existing permissions of the same type unless imported, and changes made outside of Terraform will be reset. --> **Note** It is not possible to lower permissions for `admins` or your own user anywhere from `CAN_MANAGE` level, so Databricks Terraform Provider [removes](https://github.com/databricks/terraform-provider-databricks/blob/main/permissions/resource_permissions.go#L324-L332) those `access_control` blocks automatically. +-> **Note** It is not possible to lower permissions for `admins`, so Databricks Terraform Provider removes those `access_control` blocks automatically. -> **Note** If multiple permission levels are specified for an identity (e.g. `CAN_RESTART` and `CAN_MANAGE` for a cluster), only the highest level permission is returned and will cause permanent drift. diff --git a/exporter/exporter_test.go b/exporter/exporter_test.go index a027005090..43c6c10916 100644 --- a/exporter/exporter_test.go +++ b/exporter/exporter_test.go @@ -862,7 +862,7 @@ func TestImportingClusters(t *testing.T) { }, { Method: "GET", - Resource: "/api/2.0/permissions/clusters/test1", + Resource: "/api/2.0/permissions/clusters/test1?", Response: getJSONObject("test-data/get-cluster-permissions-test1-response.json"), }, { @@ -913,7 +913,7 @@ func TestImportingClusters(t *testing.T) { }, { Method: "GET", - Resource: "/api/2.0/permissions/clusters/test2", + Resource: "/api/2.0/permissions/clusters/test2?", Response: getJSONObject("test-data/get-cluster-permissions-test2-response.json"), }, { @@ -923,7 +923,7 @@ func TestImportingClusters(t *testing.T) { }, { Method: "GET", - Resource: "/api/2.0/permissions/cluster-policies/123", + Resource: "/api/2.0/permissions/cluster-policies/123?", Response: getJSONObject("test-data/get-cluster-policy-permissions.json"), }, { @@ -949,7 +949,7 @@ func TestImportingClusters(t *testing.T) { }, { Method: "GET", - Resource: "/api/2.0/permissions/clusters/awscluster", + Resource: "/api/2.0/permissions/clusters/awscluster?", Response: getJSONObject("test-data/get-cluster-permissions-awscluster-response.json"), }, { @@ -971,7 +971,7 @@ func TestImportingClusters(t *testing.T) { }, { Method: "GET", - Resource: "/api/2.0/permissions/instance-pools/pool1", + Resource: "/api/2.0/permissions/instance-pools/pool1?", ReuseRequest: true, Response: getJSONObject("test-data/get-job-permissions-14.json"), }, @@ -1089,7 +1089,7 @@ func TestImportingJobs_JobList(t *testing.T) { }, { Method: "GET", - Resource: "/api/2.0/permissions/jobs/14", + Resource: "/api/2.0/permissions/jobs/14?", Response: getJSONObject("test-data/get-job-permissions-14.json"), }, { @@ -1112,7 +1112,7 @@ func TestImportingJobs_JobList(t *testing.T) { }, { Method: "GET", - Resource: "/api/2.0/permissions/instance-pools/pool1", + Resource: "/api/2.0/permissions/instance-pools/pool1?", ReuseRequest: true, Response: getJSONObject("test-data/get-job-permissions-14.json"), }, @@ -1202,7 +1202,7 @@ func TestImportingJobs_JobList(t *testing.T) { }, { Method: "GET", - Resource: "/api/2.0/permissions/cluster-policies/123", + Resource: "/api/2.0/permissions/cluster-policies/123?", Response: getJSONObject("test-data/get-cluster-policy-permissions.json"), }, { @@ -1218,7 +1218,7 @@ func TestImportingJobs_JobList(t *testing.T) { }, { Method: "GET", - Resource: "/api/2.0/permissions/instance-pools/pool1", + Resource: "/api/2.0/permissions/instance-pools/pool1?", ReuseRequest: true, Response: getJSONObject("test-data/get-job-permissions-14.json"), }, @@ -1307,7 +1307,7 @@ func TestImportingJobs_JobListMultiTask(t *testing.T) { }, { Method: "GET", - Resource: "/api/2.0/permissions/jobs/14", + Resource: "/api/2.0/permissions/jobs/14?", Response: getJSONObject("test-data/get-job-permissions-14.json"), ReuseRequest: true, }, @@ -1331,7 +1331,7 @@ func TestImportingJobs_JobListMultiTask(t *testing.T) { }, { Method: "GET", - Resource: "/api/2.0/permissions/instance-pools/pool1", + Resource: "/api/2.0/permissions/instance-pools/pool1?", ReuseRequest: true, Response: getJSONObject("test-data/get-job-permissions-14.json"), }, @@ -1470,7 +1470,7 @@ func TestImportingJobs_JobListMultiTask(t *testing.T) { }, { Method: "GET", - Resource: "/api/2.0/permissions/cluster-policies/123", + Resource: "/api/2.0/permissions/cluster-policies/123?", Response: getJSONObject("test-data/get-cluster-policy-permissions.json"), }, { @@ -1486,7 +1486,7 @@ func TestImportingJobs_JobListMultiTask(t *testing.T) { }, { Method: "GET", - Resource: "/api/2.0/permissions/instance-pools/pool1", + Resource: "/api/2.0/permissions/instance-pools/pool1?", ReuseRequest: true, Response: getJSONObject("test-data/get-job-permissions-14.json"), }, @@ -1777,7 +1777,7 @@ func TestImportingRepos(t *testing.T) { }, { Method: "GET", - Resource: "/api/2.0/permissions/repos/121232342", + Resource: "/api/2.0/permissions/repos/121232342?", Response: getJSONObject("test-data/get-repo-permissions.json"), }, }, @@ -1902,7 +1902,7 @@ func TestImportingSqlObjects(t *testing.T) { }, { Method: "GET", - Resource: "/api/2.0/permissions/directories/4451965692354143", + Resource: "/api/2.0/permissions/directories/4451965692354143?", Response: getJSONObject("test-data/get-directory-permissions.json"), }, { @@ -1933,7 +1933,7 @@ func TestImportingSqlObjects(t *testing.T) { }, { Method: "GET", - Resource: "/api/2.0/permissions/sql/warehouses/f562046bc1272886", + Resource: "/api/2.0/permissions/sql/warehouses/f562046bc1272886?", Response: getJSONObject("test-data/get-sql-endpoint-permissions.json"), }, { @@ -1962,12 +1962,12 @@ func TestImportingSqlObjects(t *testing.T) { }, { Method: "GET", - Resource: "/api/2.0/preview/sql/permissions/queries/16c4f969-eea0-4aad-8f82-03d79b078dcc", + Resource: "/api/2.0/permissions/sql/queries/16c4f969-eea0-4aad-8f82-03d79b078dcc?", Response: getJSONObject("test-data/get-sql-query-permissions.json"), }, { Method: "GET", - Resource: "/api/2.0/preview/sql/permissions/dashboards/9cb0c8f5-6262-4a1f-a741-2181de76028f", + Resource: "/api/2.0/permissions/dbsql-dashboards/9cb0c8f5-6262-4a1f-a741-2181de76028f?", Response: getJSONObject("test-data/get-sql-dashboard-permissions.json"), }, { @@ -1983,7 +1983,7 @@ func TestImportingSqlObjects(t *testing.T) { }, { Method: "GET", - Resource: "/api/2.0/preview/sql/permissions/alerts/3cf91a42-6217-4f3c-a6f0-345d489051b9", + Resource: "/api/2.0/permissions/sql/alerts/3cf91a42-6217-4f3c-a6f0-345d489051b9?", Response: getJSONObject("test-data/get-sql-alert-permissions.json"), }, }, @@ -2039,7 +2039,7 @@ func TestImportingDLTPipelines(t *testing.T) { }, { Method: "GET", - Resource: "/api/2.0/permissions/repos/123", + Resource: "/api/2.0/permissions/repos/123?", Response: getJSONObject("test-data/get-repo-permissions.json"), }, { @@ -2085,12 +2085,12 @@ func TestImportingDLTPipelines(t *testing.T) { }, { Method: "GET", - Resource: "/api/2.0/permissions/pipelines/123", + Resource: "/api/2.0/permissions/pipelines/123?", Response: getJSONObject("test-data/get-pipeline-permissions.json"), }, { Method: "GET", - Resource: "/api/2.0/permissions/notebooks/123", + Resource: "/api/2.0/permissions/notebooks/123?", Response: getJSONObject("test-data/get-notebook-permissions.json"), }, { @@ -2169,7 +2169,7 @@ func TestImportingDLTPipelines(t *testing.T) { }, { Method: "GET", - Resource: "/api/2.0/permissions/files/789", + Resource: "/api/2.0/permissions/files/789?", Response: getJSONObject("test-data/get-workspace-file-permissions.json"), }, }, @@ -2257,7 +2257,7 @@ func TestImportingDLTPipelinesMatchingOnly(t *testing.T) { }, { Method: "GET", - Resource: "/api/2.0/permissions/pipelines/123", + Resource: "/api/2.0/permissions/pipelines/123?", Response: getJSONObject("test-data/get-pipeline-permissions.json"), }, { diff --git a/exporter/importables.go b/exporter/importables.go index d2cb8d0f36..5ea235c335 100644 --- a/exporter/importables.go +++ b/exporter/importables.go @@ -32,7 +32,7 @@ import ( "github.com/databricks/terraform-provider-databricks/common" "github.com/databricks/terraform-provider-databricks/jobs" "github.com/databricks/terraform-provider-databricks/mws" - "github.com/databricks/terraform-provider-databricks/permissions" + "github.com/databricks/terraform-provider-databricks/permissions/entity" tfpipelines "github.com/databricks/terraform-provider-databricks/pipelines" "github.com/databricks/terraform-provider-databricks/repos" tfsettings "github.com/databricks/terraform-provider-databricks/settings" @@ -1184,7 +1184,7 @@ var resourcesMap map[string]importable = map[string]importable{ return (r.Data.Get("access_control.#").(int) == 0) }, Import: func(ic *importContext, r *resource) error { - var permissions permissions.PermissionsEntity + var permissions entity.PermissionsEntity s := ic.Resources["databricks_permissions"].Schema common.DataToStructPointer(r.Data, s, &permissions) for _, ac := range permissions.AccessControlList { diff --git a/exporter/importables_test.go b/exporter/importables_test.go index 544322a745..6bea1a8cf0 100644 --- a/exporter/importables_test.go +++ b/exporter/importables_test.go @@ -25,6 +25,7 @@ import ( "github.com/databricks/terraform-provider-databricks/common" "github.com/databricks/terraform-provider-databricks/jobs" "github.com/databricks/terraform-provider-databricks/permissions" + "github.com/databricks/terraform-provider-databricks/permissions/entity" "github.com/databricks/terraform-provider-databricks/internal/providers/sdkv2" dlt_pipelines "github.com/databricks/terraform-provider-databricks/pipelines" @@ -220,8 +221,8 @@ func TestPermissions(t *testing.T) { assert.Equal(t, "abc", name) d.MarkNewResource() - err := common.StructToData(permissions.PermissionsEntity{ - AccessControlList: []permissions.AccessControlChange{ + err := common.StructToData(entity.PermissionsEntity{ + AccessControlList: []iam.AccessControlRequest{ { UserName: "a", }, diff --git a/internal/acceptance/permissions_test.go b/internal/acceptance/permissions_test.go index 5d803bd451..1386ee9db4 100644 --- a/internal/acceptance/permissions_test.go +++ b/internal/acceptance/permissions_test.go @@ -3,222 +3,836 @@ package acceptance import ( "context" "fmt" + "regexp" + "strconv" "testing" - "github.com/databricks/databricks-sdk-go/client" - "github.com/databricks/databricks-sdk-go/config" + "github.com/databricks/databricks-sdk-go" + "github.com/databricks/databricks-sdk-go/service/iam" "github.com/databricks/terraform-provider-databricks/common" - "github.com/databricks/terraform-provider-databricks/permissions" - - "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) -func TestAccDatabricksPermissionsResourceFullLifecycle(t *testing.T) { - randomName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) - WorkspaceLevel(t, Step{ - Template: fmt.Sprintf(` - resource "databricks_notebook" "this" { - content_base64 = base64encode("# Databricks notebook source\nprint(1)") - path = "/Beginning/%[1]s/Init" - language = "PYTHON" +// +// databricks_permissions testing support +// + +type permissionSettings struct { + // Name of the SP or group. Must be quoted for a literal string, or can be a reference to another object. + ref string + // If true, the resource will not be created + skipCreation bool + permissionLevel string +} + +type makePermissionsConfig struct { + servicePrincipal []permissionSettings + group []permissionSettings + user []permissionSettings +} + +// Not used today, so this fails linting, but we can uncomment it if needed in the future. +// func servicePrincipalPermissions(permissionLevel ...string) func(*makePermissionsConfig) { +// return func(config *makePermissionsConfig) { +// config.servicePrincipal = simpleSettings(permissionLevel...) +// } +// } + +func groupPermissions(permissionLevel ...string) func(*makePermissionsConfig) { + return func(config *makePermissionsConfig) { + config.group = simpleSettings(permissionLevel...) + } +} + +func userPermissions(permissionLevel ...string) func(*makePermissionsConfig) { + return func(config *makePermissionsConfig) { + config.user = simpleSettings(permissionLevel...) + } +} + +func allPrincipalPermissions(permissionLevel ...string) func(*makePermissionsConfig) { + return func(config *makePermissionsConfig) { + config.servicePrincipal = append(config.servicePrincipal, simpleSettings(permissionLevel...)...) + config.group = append(config.group, simpleSettings(permissionLevel...)...) + config.user = append(config.user, simpleSettings(permissionLevel...)...) + } +} + +func currentPrincipalPermission(t *testing.T, permissionLevel string) func(*makePermissionsConfig) { + settings := permissionSettings{ + permissionLevel: permissionLevel, + ref: "data.databricks_current_user.me.user_name", + skipCreation: true, + } + return func(config *makePermissionsConfig) { + if isGcp(t) { + config.user = append(config.user, settings) + } else { + config.servicePrincipal = append(config.servicePrincipal, settings) } - resource "databricks_group" "first" { - display_name = "First %[1]s" + } +} + +func currentPrincipalType(t *testing.T) string { + if isGcp(t) { + return "user" + } + return "service_principal" +} + +func customPermission(name string, permissionSettings permissionSettings) func(*makePermissionsConfig) { + return func(config *makePermissionsConfig) { + switch name { + case "service_principal": + config.servicePrincipal = append(config.servicePrincipal, permissionSettings) + case "group": + config.group = append(config.group, permissionSettings) + case "user": + config.user = append(config.user, permissionSettings) + default: + panic(fmt.Sprintf("unknown permission type: %s", name)) } - resource "databricks_permissions" "dummy" { - notebook_path = databricks_notebook.this.id + } +} + +func simpleSettings(permissionLevel ...string) []permissionSettings { + var settings []permissionSettings + for _, level := range permissionLevel { + settings = append(settings, permissionSettings{permissionLevel: level}) + } + return settings +} + +func makePermissionsTestStage(idAttribute, idValue string, permissionOptions ...func(*makePermissionsConfig)) string { + config := makePermissionsConfig{} + for _, option := range permissionOptions { + option(&config) + } + var resources string + var accessControlBlocks string + addPermissions := func(permissionSettings []permissionSettings, resourceType, resourceNameAttribute, idAttribute, accessControlAttribute string, getName func(int) string) { + for i, permission := range permissionSettings { + if !permission.skipCreation { + resources += fmt.Sprintf(` + resource "%s" "_%d" { + %s = "permissions-%s" + }`, resourceType, i, resourceNameAttribute, getName(i)) + } + var name string + if permission.ref == "" { + name = fmt.Sprintf("%s._%d.%s", resourceType, i, idAttribute) + } else { + name = permission.ref + } + accessControlBlocks += fmt.Sprintf(` access_control { - group_name = databricks_group.first.display_name - permission_level = "CAN_MANAGE" + %s = %s + permission_level = "%s" + }`, accessControlAttribute, name, permission.permissionLevel) + } + } + addPermissions(config.servicePrincipal, "databricks_service_principal", "display_name", "application_id", "service_principal_name", func(i int) string { + return fmt.Sprintf("{var.STICKY_RANDOM}-%d", i) + }) + addPermissions(config.group, "databricks_group", "display_name", "display_name", "group_name", func(i int) string { + return fmt.Sprintf("{var.STICKY_RANDOM}-%d", i) + }) + addPermissions(config.user, "databricks_user", "user_name", "user_name", "user_name", func(i int) string { + return fmt.Sprintf("{var.STICKY_RANDOM}-%d@databricks.com", i) + }) + return fmt.Sprintf(` + data databricks_current_user me {} + %s + resource "databricks_permissions" "this" { + %s = %s + %s + } + `, resources, idAttribute, idValue, accessControlBlocks) +} + +func assertContainsPermission(t *testing.T, permissions *iam.ObjectPermissions, principalType, name string, permissionLevel iam.PermissionLevel) { + for _, acl := range permissions.AccessControlList { + switch principalType { + case "user": + if acl.UserName == name { + assert.Equal(t, permissionLevel, acl.AllPermissions[0].PermissionLevel) + return + } + case "service_principal": + if acl.ServicePrincipalName == name { + assert.Equal(t, permissionLevel, acl.AllPermissions[0].PermissionLevel) + return + } + case "group": + if acl.GroupName == name { + assert.Equal(t, permissionLevel, acl.AllPermissions[0].PermissionLevel) + return } - }`, randomName), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("databricks_permissions.dummy", - "object_type", "notebook"), - resourceCheck("databricks_permissions.dummy", - func(ctx context.Context, client *common.DatabricksClient, id string) error { - permissions, err := permissions.NewPermissionsAPI(ctx, client).Read(id) - if err != nil { - return err - } - assert.GreaterOrEqual(t, len(permissions.AccessControlList), 1) - return nil - }), - ), - }, Step{ - Template: fmt.Sprintf(` - resource "databricks_notebook" "this" { - content_base64 = base64encode("# Databricks notebook source\nprint(1)") - path = "/Beginning/%[1]s/Init" - language = "PYTHON" } - resource "databricks_group" "first" { - display_name = "First %[1]s" + } + assert.Fail(t, fmt.Sprintf("permission not found for %s %s", principalType, name)) +} + +// +// databricks_permissions acceptance tests +// + +func TestAccPermissions_ClusterPolicy(t *testing.T) { + loadDebugEnvIfRunsFromIDE(t, "workspace") + policyTemplate := ` + resource "databricks_cluster_policy" "this" { + name = "{var.STICKY_RANDOM}" + definition = jsonencode({ + "spark_conf.spark.hadoop.javax.jdo.option.ConnectionURL": { + "type": "fixed", + "value": "jdbc:sqlserver://" + } + }) + }` + + WorkspaceLevel(t, Step{ + Template: policyTemplate + makePermissionsTestStage("cluster_policy_id", "databricks_cluster_policy.this.id", groupPermissions("CAN_USE")), + }, Step{ + Template: policyTemplate + makePermissionsTestStage("cluster_policy_id", "databricks_cluster_policy.this.id", currentPrincipalPermission(t, "CAN_USE"), allPrincipalPermissions("CAN_USE")), + }) +} + +func TestAccPermissions_InstancePool(t *testing.T) { + loadDebugEnvIfRunsFromIDE(t, "workspace") + policyTemplate := ` + data "databricks_node_type" "smallest" { + local_disk = true + } + + resource "databricks_instance_pool" "this" { + instance_pool_name = "{var.STICKY_RANDOM}" + min_idle_instances = 0 + max_capacity = 1 + node_type_id = data.databricks_node_type.smallest.id + idle_instance_autotermination_minutes = 10 + }` + + WorkspaceLevel(t, Step{ + Template: policyTemplate + makePermissionsTestStage("instance_pool_id", "databricks_instance_pool.this.id", groupPermissions("CAN_ATTACH_TO")), + }, Step{ + Template: policyTemplate + makePermissionsTestStage("instance_pool_id", "databricks_instance_pool.this.id", currentPrincipalPermission(t, "CAN_MANAGE"), allPrincipalPermissions("CAN_ATTACH_TO", "CAN_MANAGE")), + }, Step{ + Template: policyTemplate + makePermissionsTestStage("instance_pool_id", "databricks_instance_pool.this.id", currentPrincipalPermission(t, "CAN_ATTACH_TO")), + ExpectError: regexp.MustCompile("cannot remove management permissions for the current user for instance-pool, allowed levels: CAN_MANAGE"), + }) +} + +func TestAccPermissions_Cluster(t *testing.T) { + loadDebugEnvIfRunsFromIDE(t, "workspace") + policyTemplate := ` + +data "databricks_spark_version" "latest" { +} + + resource "databricks_cluster" "this" { + cluster_name = "singlenode-{var.RANDOM}" + spark_version = data.databricks_spark_version.latest.id + instance_pool_id = "{env.TEST_INSTANCE_POOL_ID}" + num_workers = 0 + autotermination_minutes = 10 + spark_conf = { + "spark.databricks.cluster.profile" = "singleNode" + "spark.master" = "local[*]" } - resource "databricks_group" "second" { - display_name = "Second %[1]s" + custom_tags = { + "ResourceClass" = "SingleNode" } - resource "databricks_permissions" "dummy" { - notebook_path = databricks_notebook.this.id - access_control { - group_name = databricks_group.first.display_name - permission_level = "CAN_MANAGE" - } - access_control { - group_name = databricks_group.second.display_name - permission_level = "CAN_RUN" + }` + + WorkspaceLevel(t, Step{ + Template: policyTemplate + makePermissionsTestStage("cluster_id", "databricks_cluster.this.id", groupPermissions("CAN_ATTACH_TO")), + }, Step{ + Template: policyTemplate + makePermissionsTestStage("cluster_id", "databricks_cluster.this.id", currentPrincipalPermission(t, "CAN_MANAGE"), allPrincipalPermissions("CAN_ATTACH_TO", "CAN_RESTART", "CAN_MANAGE")), + }, Step{ + Template: policyTemplate + makePermissionsTestStage("cluster_id", "databricks_cluster.this.id", currentPrincipalPermission(t, "CAN_ATTACH_TO")), + ExpectError: regexp.MustCompile("cannot remove management permissions for the current user for cluster, allowed levels: CAN_MANAGE"), + }) +} + +func TestAccPermissions_Job(t *testing.T) { + loadDebugEnvIfRunsFromIDE(t, "workspace") + template := ` + resource "databricks_job" "this" { + name = "{var.STICKY_RANDOM}" + }` + WorkspaceLevel(t, Step{ + Template: template + makePermissionsTestStage("job_id", "databricks_job.this.id", groupPermissions("CAN_VIEW")), + }, Step{ + Template: template + makePermissionsTestStage("job_id", "databricks_job.this.id", currentPrincipalPermission(t, "IS_OWNER"), allPrincipalPermissions("CAN_VIEW", "CAN_MANAGE_RUN", "CAN_MANAGE")), + }, Step{ + Template: template + makePermissionsTestStage("job_id", "databricks_job.this.id", currentPrincipalPermission(t, "CAN_MANAGE_RUN")), + ExpectError: regexp.MustCompile("cannot remove management permissions for the current user for job, allowed levels: CAN_MANAGE, IS_OWNER"), + }, Step{ + Template: template + makePermissionsTestStage("job_id", "databricks_job.this.id", currentPrincipalPermission(t, "CAN_MANAGE"), userPermissions("IS_OWNER")), + }, Step{ + Template: template, + Check: func(s *terraform.State) error { + w := databricks.Must(databricks.NewWorkspaceClient()) + jobId := s.RootModule().Resources["databricks_job.this"].Primary.ID + permissions, err := w.Permissions.GetByRequestObjectTypeAndRequestObjectId(context.Background(), "jobs", jobId) + assert.NoError(t, err) + idInt, err := strconv.Atoi(jobId) + assert.NoError(t, err) + job, err := w.Jobs.GetByJobId(context.Background(), int64(idInt)) + assert.NoError(t, err) + assertContainsPermission(t, permissions, currentPrincipalType(t), job.CreatorUserName, iam.PermissionLevelIsOwner) + return nil + }, + }) +} + +func TestAccPermissions_Pipeline(t *testing.T) { + loadDebugEnvIfRunsFromIDE(t, "workspace") + policyTemplate := ` + + locals { + name = "{var.STICKY_RANDOM}" + } + + resource "databricks_pipeline" "this" { + name = "${local.name}" + storage = "/test/${local.name}" + + library { + notebook { + path = databricks_notebook.this.path } - }`, randomName), - Check: resourceCheck("databricks_permissions.dummy", - func(ctx context.Context, client *common.DatabricksClient, id string) error { - permissions, err := permissions.NewPermissionsAPI(ctx, client).Read(id) - if err != nil { - return err - } - assert.GreaterOrEqual(t, len(permissions.AccessControlList), 2) - return nil - }), + } + continuous = false + }` + dltNotebookResource + + WorkspaceLevel(t, Step{ + Template: policyTemplate + makePermissionsTestStage("pipeline_id", "databricks_pipeline.this.id", groupPermissions("CAN_VIEW")), + }, Step{ + Template: policyTemplate + makePermissionsTestStage("pipeline_id", "databricks_pipeline.this.id", currentPrincipalPermission(t, "IS_OWNER"), allPrincipalPermissions("CAN_VIEW", "CAN_RUN", "CAN_MANAGE")), + }, Step{ + Template: policyTemplate + makePermissionsTestStage("pipeline_id", "databricks_pipeline.this.id", currentPrincipalPermission(t, "CAN_RUN")), + ExpectError: regexp.MustCompile("cannot remove management permissions for the current user for pipelines, allowed levels: CAN_MANAGE, IS_OWNER"), + }, Step{ + Template: policyTemplate + makePermissionsTestStage("pipeline_id", "databricks_pipeline.this.id", currentPrincipalPermission(t, "CAN_MANAGE"), userPermissions("IS_OWNER"), groupPermissions("CAN_VIEW", "CAN_RUN", "CAN_MANAGE")), + }, Step{ + Template: policyTemplate, + Check: resourceCheck("databricks_pipeline.this", func(ctx context.Context, c *common.DatabricksClient, id string) error { + w, err := c.WorkspaceClient() + assert.NoError(t, err) + pipeline, err := w.Pipelines.GetByPipelineId(context.Background(), id) + assert.NoError(t, err) + permissions, err := w.Permissions.GetByRequestObjectTypeAndRequestObjectId(context.Background(), "pipelines", id) + assert.NoError(t, err) + assertContainsPermission(t, permissions, currentPrincipalType(t), pipeline.CreatorUserName, iam.PermissionLevelIsOwner) + return nil + }), + }) +} + +func TestAccPermissions_Notebook_Path(t *testing.T) { + loadDebugEnvIfRunsFromIDE(t, "workspace") + notebookTemplate := ` + resource "databricks_directory" "this" { + path = "/permissions_test/{var.STICKY_RANDOM}" + } + resource "databricks_notebook" "this" { + source = "{var.CWD}/../../storage/testdata/tf-test-python.py" + path = "${databricks_directory.this.path}/test_notebook" + }` + WorkspaceLevel(t, Step{ + Template: notebookTemplate + makePermissionsTestStage("notebook_path", "databricks_notebook.this.id", groupPermissions("CAN_RUN")), + }, Step{ + Template: notebookTemplate + makePermissionsTestStage("notebook_path", "databricks_notebook.this.id", currentPrincipalPermission(t, "CAN_MANAGE"), allPrincipalPermissions("CAN_RUN", "CAN_READ", "CAN_EDIT", "CAN_MANAGE")), + }, Step{ + // The current user can be removed from permissions since they inherit permissions from the directory they created. + Template: notebookTemplate + makePermissionsTestStage("notebook_path", "databricks_notebook.this.id", allPrincipalPermissions("CAN_RUN", "CAN_READ", "CAN_EDIT", "CAN_MANAGE")), + }, Step{ + Template: notebookTemplate + makePermissionsTestStage("notebook_path", "databricks_notebook.this.id", currentPrincipalPermission(t, "CAN_READ")), + ExpectError: regexp.MustCompile("cannot remove management permissions for the current user for notebook, allowed levels: CAN_MANAGE"), + }) +} + +func TestAccPermissions_Notebook_Id(t *testing.T) { + loadDebugEnvIfRunsFromIDE(t, "workspace") + notebookTemplate := ` + resource "databricks_directory" "this" { + path = "/permissions_test/{var.STICKY_RANDOM}" + } + resource "databricks_notebook" "this" { + source = "{var.CWD}/../../storage/testdata/tf-test-python.py" + path = "${databricks_directory.this.path}/test_notebook" + }` + WorkspaceLevel(t, Step{ + Template: notebookTemplate + makePermissionsTestStage("notebook_id", "databricks_notebook.this.object_id", groupPermissions("CAN_RUN")), + }, Step{ + Template: notebookTemplate + makePermissionsTestStage("notebook_id", "databricks_notebook.this.object_id", currentPrincipalPermission(t, "CAN_MANAGE"), allPrincipalPermissions("CAN_RUN", "CAN_READ", "CAN_EDIT", "CAN_MANAGE")), + }, Step{ + // The current user can be removed from permissions since they inherit permissions from the directory they created. + Template: notebookTemplate + makePermissionsTestStage("notebook_id", "databricks_notebook.this.object_id", allPrincipalPermissions("CAN_RUN", "CAN_READ", "CAN_EDIT", "CAN_MANAGE")), + }, Step{ + Template: notebookTemplate + makePermissionsTestStage("notebook_id", "databricks_notebook.this.object_id", currentPrincipalPermission(t, "CAN_READ")), + ExpectError: regexp.MustCompile("cannot remove management permissions for the current user for notebook, allowed levels: CAN_MANAGE"), }) } -func TestAccDatabricksReposPermissionsResourceFullLifecycle(t *testing.T) { - randomName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) +func TestAccPermissions_Directory_Path(t *testing.T) { + loadDebugEnvIfRunsFromIDE(t, "workspace") + directoryTemplate := ` + resource "databricks_directory" "this" { + path = "/permissions_test/{var.STICKY_RANDOM}" + }` WorkspaceLevel(t, Step{ - Template: fmt.Sprintf(` + Template: directoryTemplate + makePermissionsTestStage("directory_path", "databricks_directory.this.id", groupPermissions("CAN_RUN")), + }, Step{ + Template: directoryTemplate + makePermissionsTestStage("directory_path", "databricks_directory.this.id", currentPrincipalPermission(t, "CAN_MANAGE"), allPrincipalPermissions("CAN_RUN", "CAN_READ", "CAN_EDIT", "CAN_MANAGE")), + }, Step{ + // The current user can be removed from permissions since they inherit permissions from the directory they created. + Template: directoryTemplate + makePermissionsTestStage("directory_path", "databricks_directory.this.id", allPrincipalPermissions("CAN_RUN", "CAN_READ", "CAN_EDIT", "CAN_MANAGE")), + }, Step{ + Template: directoryTemplate + makePermissionsTestStage("directory_path", "databricks_directory.this.id", currentPrincipalPermission(t, "CAN_READ")), + ExpectError: regexp.MustCompile("cannot remove management permissions for the current user for directory, allowed levels: CAN_MANAGE"), + }) +} + +func TestAccPermissions_Directory_Id(t *testing.T) { + loadDebugEnvIfRunsFromIDE(t, "workspace") + directoryTemplate := ` + resource "databricks_directory" "this" { + path = "/permissions_test/{var.STICKY_RANDOM}" + }` + WorkspaceLevel(t, Step{ + Template: directoryTemplate + makePermissionsTestStage("directory_id", "databricks_directory.this.object_id", groupPermissions("CAN_RUN")), + }, Step{ + Template: directoryTemplate + makePermissionsTestStage("directory_id", "databricks_directory.this.object_id", currentPrincipalPermission(t, "CAN_MANAGE"), allPrincipalPermissions("CAN_RUN", "CAN_READ", "CAN_EDIT", "CAN_MANAGE")), + }, Step{ + // The current user can be removed from permissions since they inherit permissions from the directory they created. + Template: directoryTemplate + makePermissionsTestStage("directory_id", "databricks_directory.this.object_id", allPrincipalPermissions("CAN_RUN", "CAN_READ", "CAN_EDIT", "CAN_MANAGE")), + }, Step{ + Template: directoryTemplate + makePermissionsTestStage("directory_id", "databricks_directory.this.object_id", currentPrincipalPermission(t, "CAN_READ")), + ExpectError: regexp.MustCompile("cannot remove management permissions for the current user for directory, allowed levels: CAN_MANAGE"), + }) +} + +// This test exercises both by ID and by path permissions for the root directory. Testing them +// concurrently would result in a race condition. +func TestAccPermissions_Directory_RootDirectoryCorrectlyHandlesAdminUsers(t *testing.T) { + loadDebugEnvIfRunsFromIDE(t, "workspace") + expectedAclAfterDeletion := []iam.AccessControlResponse{ + { + GroupName: "admins", + AllPermissions: []iam.Permission{ + { + PermissionLevel: iam.PermissionLevelCanManage, + ForceSendFields: []string{"Inherited", "PermissionLevel"}, + }, + }, + ForceSendFields: []string{"GroupName"}, + }, + } + WorkspaceLevel(t, Step{ + Template: makePermissionsTestStage("directory_id", "\"0\"", groupPermissions("CAN_RUN")), + }, Step{ + Template: `data databricks_current_user me {}`, + Check: func(s *terraform.State) error { + w := databricks.Must(databricks.NewWorkspaceClient()) + permissions, err := w.Permissions.GetByRequestObjectTypeAndRequestObjectId(context.Background(), "directories", "0") + assert.NoError(t, err) + assert.Equal(t, expectedAclAfterDeletion, permissions.AccessControlList) + return nil + }, + }, Step{ + Template: makePermissionsTestStage("directory_path", "\"/\"", userPermissions("CAN_RUN")), + }, Step{ + Template: `data databricks_current_user me {}`, + Check: func(s *terraform.State) error { + w := databricks.Must(databricks.NewWorkspaceClient()) + permissions, err := w.Permissions.GetByRequestObjectTypeAndRequestObjectId(context.Background(), "directories", "0") + assert.NoError(t, err) + assert.Equal(t, expectedAclAfterDeletion, permissions.AccessControlList) + return nil + }, + }) +} + +func TestAccPermissions_WorkspaceFile_Path(t *testing.T) { + loadDebugEnvIfRunsFromIDE(t, "workspace") + workspaceFile := ` + resource "databricks_directory" "this" { + path = "/permissions_test/{var.STICKY_RANDOM}" + } + resource "databricks_workspace_file" "this" { + source = "{var.CWD}/../../storage/testdata/tf-test-python.py" + path = "${databricks_directory.this.path}/test_notebook" + }` + WorkspaceLevel(t, Step{ + Template: workspaceFile + makePermissionsTestStage("workspace_file_path", "databricks_workspace_file.this.id", groupPermissions("CAN_RUN")), + }, Step{ + Template: workspaceFile + makePermissionsTestStage("workspace_file_path", "databricks_workspace_file.this.id", currentPrincipalPermission(t, "CAN_MANAGE"), allPrincipalPermissions("CAN_RUN", "CAN_READ", "CAN_EDIT", "CAN_MANAGE")), + }, Step{ + // The current user can be removed from permissions since they inherit permissions from the directory they created. + Template: workspaceFile + makePermissionsTestStage("workspace_file_path", "databricks_workspace_file.this.id", allPrincipalPermissions("CAN_RUN", "CAN_READ", "CAN_EDIT", "CAN_MANAGE")), + }, Step{ + Template: workspaceFile + makePermissionsTestStage("workspace_file_path", "databricks_workspace_file.this.id", currentPrincipalPermission(t, "CAN_READ")), + ExpectError: regexp.MustCompile("cannot remove management permissions for the current user for file, allowed levels: CAN_MANAGE"), + }) +} + +func TestAccPermissions_WorkspaceFile_Id(t *testing.T) { + loadDebugEnvIfRunsFromIDE(t, "workspace") + workspaceFile := ` + resource "databricks_directory" "this" { + path = "/permissions_test/{var.STICKY_RANDOM}" + } + resource "databricks_workspace_file" "this" { + source = "{var.CWD}/../../storage/testdata/tf-test-python.py" + path = "${databricks_directory.this.path}/test_notebook" + }` + WorkspaceLevel(t, Step{ + Template: workspaceFile + makePermissionsTestStage("workspace_file_id", "databricks_workspace_file.this.object_id", groupPermissions("CAN_RUN")), + }, Step{ + Template: workspaceFile + makePermissionsTestStage("workspace_file_id", "databricks_workspace_file.this.object_id", currentPrincipalPermission(t, "CAN_MANAGE"), allPrincipalPermissions("CAN_RUN", "CAN_READ", "CAN_EDIT", "CAN_MANAGE")), + }, Step{ + // The current user can be removed from permissions since they inherit permissions from the directory they created. + Template: workspaceFile + makePermissionsTestStage("workspace_file_id", "databricks_workspace_file.this.object_id", allPrincipalPermissions("CAN_RUN", "CAN_READ", "CAN_EDIT", "CAN_MANAGE")), + }, Step{ + Template: workspaceFile + makePermissionsTestStage("workspace_file_id", "databricks_workspace_file.this.object_id", currentPrincipalPermission(t, "CAN_READ")), + ExpectError: regexp.MustCompile("cannot remove management permissions for the current user for file, allowed levels: CAN_MANAGE"), + }) +} + +func TestAccPermissions_Repo_Id(t *testing.T) { + loadDebugEnvIfRunsFromIDE(t, "workspace") + template := ` resource "databricks_repo" "this" { url = "https://github.com/databrickslabs/tempo.git" - path = "/Repos/terraform-tests/tempo-%[1]s" + path = "/Repos/terraform-tests/tempo-{var.STICKY_RANDOM}" } - resource "databricks_group" "first" { - display_name = "First %[1]s" - } - resource "databricks_group" "second" { - display_name = "Second %[1]s" + ` + WorkspaceLevel(t, Step{ + Template: template + makePermissionsTestStage("repo_id", "databricks_repo.this.id", groupPermissions("CAN_MANAGE", "CAN_READ")), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("databricks_permissions.this", "object_type", "repo"), + func(s *terraform.State) error { + w := databricks.Must(databricks.NewWorkspaceClient()) + repoId := s.RootModule().Resources["databricks_repo.this"].Primary.ID + permissions, err := w.Permissions.GetByRequestObjectTypeAndRequestObjectId(context.Background(), "repos", repoId) + assert.NoError(t, err) + group1Name := s.RootModule().Resources["databricks_group._0"].Primary.Attributes["display_name"] + assertContainsPermission(t, permissions, "group", group1Name, iam.PermissionLevelCanManage) + group2Name := s.RootModule().Resources["databricks_group._1"].Primary.Attributes["display_name"] + assertContainsPermission(t, permissions, "group", group2Name, iam.PermissionLevelCanRead) + return nil + }, + ), + }, Step{ + Template: template + makePermissionsTestStage("repo_id", "databricks_repo.this.id", currentPrincipalPermission(t, "CAN_MANAGE"), allPrincipalPermissions("CAN_READ", "CAN_MANAGE", "CAN_RUN", "CAN_EDIT")), + }, Step{ + Template: template + makePermissionsTestStage("repo_id", "databricks_repo.this.id", allPrincipalPermissions("CAN_READ", "CAN_MANAGE", "CAN_RUN", "CAN_EDIT")), + }, Step{ + Template: template + makePermissionsTestStage("repo_id", "databricks_repo.this.id", currentPrincipalPermission(t, "CAN_READ")), + ExpectError: regexp.MustCompile("cannot remove management permissions for the current user for repo, allowed levels: CAN_MANAGE"), + }) +} + +func TestAccPermissions_Repo_Path(t *testing.T) { + loadDebugEnvIfRunsFromIDE(t, "workspace") + template := ` + resource "databricks_repo" "this" { + url = "https://github.com/databrickslabs/tempo.git" + path = "/Repos/terraform-tests/tempo-{var.STICKY_RANDOM}" } - resource "databricks_permissions" "dummy" { - repo_path = databricks_repo.this.path - access_control { - group_name = databricks_group.first.display_name - permission_level = "CAN_MANAGE" - } - access_control { - group_name = databricks_group.second.display_name - permission_level = "CAN_RUN" - } - }`, randomName), + ` + WorkspaceLevel(t, Step{ + Template: template + makePermissionsTestStage("repo_path", "databricks_repo.this.path", groupPermissions("CAN_MANAGE", "CAN_RUN")), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("databricks_permissions.dummy", - "object_type", "repo"), - resourceCheck("databricks_permissions.dummy", - func(ctx context.Context, client *common.DatabricksClient, id string) error { - permissions, err := permissions.NewPermissionsAPI(ctx, client).Read(id) - if err != nil { - return err - } - assert.GreaterOrEqual(t, len(permissions.AccessControlList), 2) - return nil - }), + resource.TestCheckResourceAttr("databricks_permissions.this", "object_type", "repo"), + func(s *terraform.State) error { + w := databricks.Must(databricks.NewWorkspaceClient()) + repoId := s.RootModule().Resources["databricks_repo.this"].Primary.ID + permissions, err := w.Permissions.GetByRequestObjectTypeAndRequestObjectId(context.Background(), "repos", repoId) + assert.NoError(t, err) + group1Name := s.RootModule().Resources["databricks_group._0"].Primary.Attributes["display_name"] + assertContainsPermission(t, permissions, "group", group1Name, iam.PermissionLevelCanManage) + group2Name := s.RootModule().Resources["databricks_group._1"].Primary.Attributes["display_name"] + assertContainsPermission(t, permissions, "group", group2Name, iam.PermissionLevelCanRun) + return nil + }, ), + }, Step{ + Template: template + makePermissionsTestStage("repo_id", "databricks_repo.this.id", currentPrincipalPermission(t, "CAN_MANAGE"), allPrincipalPermissions("CAN_READ", "CAN_MANAGE", "CAN_RUN", "CAN_EDIT")), + }, Step{ + Template: template + makePermissionsTestStage("repo_id", "databricks_repo.this.id", allPrincipalPermissions("CAN_READ", "CAN_MANAGE", "CAN_RUN", "CAN_EDIT")), + }, Step{ + Template: template + makePermissionsTestStage("repo_id", "databricks_repo.this.id", currentPrincipalPermission(t, "CAN_READ")), + ExpectError: regexp.MustCompile("cannot remove management permissions for the current user for repo, allowed levels: CAN_MANAGE"), }) } -func TestAccDatabricksPermissionsForSqlWarehouses(t *testing.T) { - // Random string to annotate newly created groups - randomName := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) +func TestAccPermissions_Authorization_Passwords(t *testing.T) { + skipf(t)("ACLs for passwords are disabled on testing workspaces") + loadDebugEnvIfRunsFromIDE(t, "workspace") + WorkspaceLevel(t, Step{ + Template: makePermissionsTestStage("authorization", "\"passwords\"", groupPermissions("CAN_USE")), + }, Step{ + Template: makePermissionsTestStage("authorization", "\"passwords\"", customPermission("group", permissionSettings{ref: `"admins"`, skipCreation: true, permissionLevel: "CAN_USE"})), + }) +} - // Create a client to query the permissions API - c, err := client.New(&config.Config{}) - require.NoError(t, err) - permissionsClient := permissions.NewPermissionsAPI(context.Background(), &common.DatabricksClient{DatabricksClient: c}) +func TestAccPermissions_Authorization_Tokens(t *testing.T) { + loadDebugEnvIfRunsFromIDE(t, "workspace") + WorkspaceLevel(t, Step{ + Template: makePermissionsTestStage("authorization", "\"tokens\"", groupPermissions("CAN_USE")), + }, Step{ + Template: makePermissionsTestStage("authorization", "\"tokens\"", customPermission("group", permissionSettings{ref: `"users"`, skipCreation: true, permissionLevel: "CAN_USE"})), + }, Step{ + // Template needs to be non-empty + Template: "data databricks_current_user me {}", + Check: func(s *terraform.State) error { + w := databricks.Must(databricks.NewWorkspaceClient()) + permissions, err := w.Permissions.GetByRequestObjectTypeAndRequestObjectId(context.Background(), "authorization", "tokens") + assert.NoError(t, err) + assert.Len(t, permissions.AccessControlList, 1) + assert.Equal(t, iam.AccessControlResponse{ + GroupName: "admins", + AllPermissions: []iam.Permission{ + { + PermissionLevel: iam.PermissionLevelCanManage, + ForceSendFields: []string{"Inherited", "PermissionLevel"}, + }, + }, + ForceSendFields: []string{"GroupName"}, + }, permissions.AccessControlList[0]) + return nil + }, + }) +} + +func TestAccPermissions_SqlWarehouses(t *testing.T) { + loadDebugEnvIfRunsFromIDE(t, "workspace") + sqlWarehouseTemplate := ` + resource "databricks_sql_endpoint" "this" { + name = "{var.STICKY_RANDOM}" + cluster_size = "2X-Small" + }` + WorkspaceLevel(t, Step{ + Template: sqlWarehouseTemplate + makePermissionsTestStage("sql_endpoint_id", "databricks_sql_endpoint.this.id", groupPermissions("CAN_USE")), + }, Step{ + Template: sqlWarehouseTemplate + makePermissionsTestStage("sql_endpoint_id", "databricks_sql_endpoint.this.id", currentPrincipalPermission(t, "IS_OWNER"), allPrincipalPermissions("CAN_USE", "CAN_MANAGE", "CAN_MONITOR")), + // Note: ideally we could test making a new user/SP the owner of the warehouse, but the new user + // needs cluster creation permissions, and the SCIM API doesn't provide get-after-put consistency, + // so this would introduce flakiness. + // }, Step{ + // Template: sqlWarehouseTemplate + makePermissionsTestStage("sql_endpoint_id", "databricks_sql_endpoint.this.id", currentPrincipalPermission(t, "CAN_MANAGE"), servicePrincipalPermissions("IS_OWNER")) + ` + // resource databricks_entitlements "this" { + // application_id = databricks_service_principal._0.application_id + // allow_cluster_create = true + // } + // `, + }, Step{ + Template: sqlWarehouseTemplate + makePermissionsTestStage("sql_endpoint_id", "databricks_sql_endpoint.this.id", currentPrincipalPermission(t, "CAN_USE")), + ExpectError: regexp.MustCompile("cannot remove management permissions for the current user for warehouses, allowed levels: CAN_MANAGE, IS_OWNER"), + }, Step{ + Template: sqlWarehouseTemplate, + Check: func(s *terraform.State) error { + w := databricks.Must(databricks.NewWorkspaceClient()) + id := s.RootModule().Resources["databricks_sql_endpoint.this"].Primary.ID + warehouse, err := w.Warehouses.GetById(context.Background(), id) + assert.NoError(t, err) + permissions, err := w.Permissions.GetByRequestObjectTypeAndRequestObjectId(context.Background(), "warehouses", id) + assert.NoError(t, err) + assertContainsPermission(t, permissions, currentPrincipalType(t), warehouse.CreatorName, iam.PermissionLevelIsOwner) + return nil + }, + }) +} - // Validates export attribute "object_type" for the permissions resource - // is set to warehouses - checkObjectType := resource.TestCheckResourceAttr("databricks_permissions.this", - "object_type", "warehouses") +func TestAccPermissions_SqlDashboard(t *testing.T) { + loadDebugEnvIfRunsFromIDE(t, "workspace") + dashboardTemplate := ` + resource "databricks_sql_dashboard" "this" { + name = "{var.STICKY_RANDOM}" + }` + WorkspaceLevel(t, Step{ + Template: dashboardTemplate + makePermissionsTestStage("sql_dashboard_id", "databricks_sql_dashboard.this.id", groupPermissions("CAN_VIEW")), + }, Step{ + Template: dashboardTemplate + makePermissionsTestStage("sql_dashboard_id", "databricks_sql_dashboard.this.id", currentPrincipalPermission(t, "CAN_VIEW")), + ExpectError: regexp.MustCompile("cannot remove management permissions for the current user for dashboard, allowed levels: CAN_MANAGE"), + }, Step{ + Template: dashboardTemplate + makePermissionsTestStage("sql_dashboard_id", "databricks_sql_dashboard.this.id", currentPrincipalPermission(t, "CAN_MANAGE"), allPrincipalPermissions("CAN_VIEW", "CAN_READ", "CAN_EDIT", "CAN_RUN", "CAN_MANAGE")), + }) +} - // Asserts value of a permission level for a group - assertPermissionLevel := func(t *testing.T, permissionId, groupName, permissionLevel string) { - // Query permissions on warehouse - warehousePermissions, err := permissionsClient.Read(permissionId) - require.NoError(t, err) +func TestAccPermissions_SqlAlert(t *testing.T) { + loadDebugEnvIfRunsFromIDE(t, "workspace") + alertTemplate := ` + resource "databricks_sql_query" "this" { + name = "{var.STICKY_RANDOM}-query" + query = "SELECT 1 AS p1, 2 as p2" + data_source_id = "{env.TEST_DEFAULT_WAREHOUSE_DATASOURCE_ID}" + } + resource "databricks_sql_alert" "this" { + name = "{var.STICKY_RANDOM}-alert" + query_id = databricks_sql_query.this.id + options { + column = "p1" + op = ">=" + value = "3" + muted = false + } + }` + WorkspaceLevel(t, Step{ + Template: alertTemplate + makePermissionsTestStage("sql_alert_id", "databricks_sql_alert.this.id", groupPermissions("CAN_VIEW")), + }, Step{ + Template: alertTemplate + makePermissionsTestStage("sql_alert_id", "databricks_sql_alert.this.id", currentPrincipalPermission(t, "CAN_MANAGE"), groupPermissions("CAN_VIEW", "CAN_EDIT", "CAN_RUN", "CAN_MANAGE")), + }, Step{ + Template: alertTemplate + makePermissionsTestStage("sql_alert_id", "databricks_sql_alert.this.id", currentPrincipalPermission(t, "CAN_VIEW"), groupPermissions("CAN_VIEW", "CAN_EDIT", "CAN_RUN", "CAN_MANAGE")), + ExpectError: regexp.MustCompile("cannot remove management permissions for the current user for alert, allowed levels: CAN_MANAGE"), + }) +} - // Assert expected permission level is present - assert.Contains(t, warehousePermissions.AccessControlList, permissions.AccessControl{ - GroupName: groupName, - AllPermissions: []permissions.Permission{ - { - PermissionLevel: permissionLevel, - }, - }, - }) - } +func TestAccPermissions_SqlQuery(t *testing.T) { + loadDebugEnvIfRunsFromIDE(t, "workspace") + queryTemplate := ` + resource "databricks_sql_query" "this" { + name = "{var.STICKY_RANDOM}-query" + query = "SELECT 1 AS p1, 2 as p2" + data_source_id = "{env.TEST_DEFAULT_WAREHOUSE_DATASOURCE_ID}" + }` + WorkspaceLevel(t, Step{ + Template: queryTemplate + makePermissionsTestStage("sql_query_id", "databricks_sql_query.this.id", groupPermissions("CAN_VIEW")), + }, Step{ + Template: queryTemplate + makePermissionsTestStage("sql_query_id", "databricks_sql_query.this.id", currentPrincipalPermission(t, "CAN_MANAGE"), groupPermissions("CAN_VIEW", "CAN_EDIT", "CAN_RUN", "CAN_MANAGE")), + }, Step{ + Template: queryTemplate + makePermissionsTestStage("sql_query_id", "databricks_sql_query.this.id", currentPrincipalPermission(t, "CAN_VIEW"), groupPermissions("CAN_VIEW", "CAN_EDIT", "CAN_RUN", "CAN_MANAGE")), + ExpectError: regexp.MustCompile("cannot remove management permissions for the current user for query, allowed levels: CAN_MANAGE"), + }) +} - // Get permission ID from the terraform state - getPermissionId := func(s *terraform.State) string { - resourcePermission, ok := s.RootModule().Resources["databricks_permissions.this"] - require.True(t, ok, "could not find permissions resource: databricks_permissions.this") - return resourcePermission.Primary.ID - } +func TestAccPermissions_Dashboard(t *testing.T) { + loadDebugEnvIfRunsFromIDE(t, "workspace") + dashboardTemplate := ` + resource "databricks_directory" "this" { + path = "/permissions_test/{var.STICKY_RANDOM}" + } + resource "databricks_dashboard" "dashboard" { + display_name = "TF New Dashboard" + warehouse_id = "{env.TEST_DEFAULT_WAREHOUSE_ID}" + parent_path = databricks_directory.this.path + } + ` + WorkspaceLevel(t, Step{ + Template: dashboardTemplate + makePermissionsTestStage("dashboard_id", "databricks_dashboard.dashboard.id", groupPermissions("CAN_READ")), + }, Step{ + Template: dashboardTemplate + makePermissionsTestStage("dashboard_id", "databricks_dashboard.dashboard.id", currentPrincipalPermission(t, "CAN_MANAGE"), groupPermissions("CAN_READ", "CAN_EDIT", "CAN_RUN", "CAN_MANAGE")), + }, Step{ + Template: dashboardTemplate + makePermissionsTestStage("dashboard_id", "databricks_dashboard.dashboard.id", currentPrincipalPermission(t, "CAN_READ"), groupPermissions("CAN_READ", "CAN_EDIT", "CAN_RUN", "CAN_MANAGE")), + ExpectError: regexp.MustCompile("cannot remove management permissions for the current user for dashboard, allowed levels: CAN_MANAGE"), + }) +} - // Configuration for step 1 of the test. Create a databricks_permissions - // resources, assigning a group CAN_MANAGE permission to the warehouse. - config1 := fmt.Sprintf(` - resource "databricks_group" "one" { - display_name = "test-warehouse-permission-one-%s" - } - resource "databricks_permissions" "this" { - sql_endpoint_id = "{env.TEST_DEFAULT_WAREHOUSE_ID}" - access_control { - group_name = databricks_group.one.display_name - permission_level = "CAN_MANAGE" +func TestAccPermissions_Experiment(t *testing.T) { + loadDebugEnvIfRunsFromIDE(t, "workspace") + experimentTemplate := ` + resource "databricks_directory" "this" { + path = "/permissions_test/{var.STICKY_RANDOM}" } - }`, randomName) + resource "databricks_mlflow_experiment" "this" { + name = "${databricks_directory.this.path}/experiment" + }` + WorkspaceLevel(t, Step{ + Template: experimentTemplate + makePermissionsTestStage("experiment_id", "databricks_mlflow_experiment.this.id", groupPermissions("CAN_READ")), + }, Step{ + Template: experimentTemplate + makePermissionsTestStage("experiment_id", "databricks_mlflow_experiment.this.id", currentPrincipalPermission(t, "CAN_MANAGE"), groupPermissions("CAN_READ", "CAN_EDIT", "CAN_MANAGE")), + }, Step{ + Template: experimentTemplate + makePermissionsTestStage("experiment_id", "databricks_mlflow_experiment.this.id", currentPrincipalPermission(t, "CAN_READ"), groupPermissions("CAN_READ", "CAN_EDIT", "CAN_MANAGE")), + ExpectError: regexp.MustCompile("cannot remove management permissions for the current user for mlflowExperiment, allowed levels: CAN_MANAGE"), + }) +} - // Configuration for step 2 of the test. Create another group and update - // permissions to CAN_USE for the second group - config2 := fmt.Sprintf(` - resource "databricks_group" "one" { - display_name = "test-warehouse-permission-one-%[1]s" - } - resource "databricks_group" "two" { - display_name = "test-warehouse-permission-two-%[1]s" +func TestAccPermissions_RegisteredModel(t *testing.T) { + loadDebugEnvIfRunsFromIDE(t, "workspace") + modelTemplate := ` + resource "databricks_mlflow_model" "m1" { + name = "tf-{var.STICKY_RANDOM}" + description = "tf-{var.STICKY_RANDOM} description" } - resource "databricks_permissions" "this" { - sql_endpoint_id = "{env.TEST_DEFAULT_WAREHOUSE_ID}" - access_control { - group_name = databricks_group.one.display_name - permission_level = "CAN_MANAGE" - } - access_control { - group_name = databricks_group.two.display_name - permission_level = "CAN_USE" - } - }`, randomName) - - WorkspaceLevel(t, - Step{ - Template: config1, - Check: resource.ComposeTestCheckFunc( - checkObjectType, - func(s *terraform.State) error { - id := getPermissionId(s) - assertPermissionLevel(t, id, "test-warehouse-permission-one-"+randomName, "CAN_MANAGE") - return nil + ` + WorkspaceLevel(t, Step{ + Template: modelTemplate + makePermissionsTestStage("registered_model_id", "databricks_mlflow_model.m1.registered_model_id", groupPermissions("CAN_READ")), + }, Step{ + Template: modelTemplate + makePermissionsTestStage("registered_model_id", "databricks_mlflow_model.m1.registered_model_id", currentPrincipalPermission(t, "CAN_MANAGE"), groupPermissions("CAN_READ", "CAN_EDIT", "CAN_MANAGE_STAGING_VERSIONS", "CAN_MANAGE_PRODUCTION_VERSIONS", "CAN_MANAGE")), + }, Step{ + Template: modelTemplate + makePermissionsTestStage("registered_model_id", "databricks_mlflow_model.m1.registered_model_id", currentPrincipalPermission(t, "CAN_READ"), groupPermissions("CAN_READ", "CAN_EDIT", "CAN_MANAGE_STAGING_VERSIONS", "CAN_MANAGE_PRODUCTION_VERSIONS", "CAN_MANAGE")), + ExpectError: regexp.MustCompile("cannot remove management permissions for the current user for registered-model, allowed levels: CAN_MANAGE"), + }) +} + +func TestAccPermissions_RegisteredModel_Root(t *testing.T) { + loadDebugEnvIfRunsFromIDE(t, "workspace") + WorkspaceLevel(t, Step{ + Template: makePermissionsTestStage("registered_model_id", "\"root\"", groupPermissions("CAN_READ")), + }, Step{ + Template: makePermissionsTestStage("registered_model_id", "\"root\"", currentPrincipalPermission(t, "CAN_MANAGE"), groupPermissions("CAN_READ", "CAN_EDIT", "CAN_MANAGE_STAGING_VERSIONS", "CAN_MANAGE_PRODUCTION_VERSIONS", "CAN_MANAGE")), + }, Step{ + Template: makePermissionsTestStage("registered_model_id", "\"root\"", currentPrincipalPermission(t, "CAN_READ"), groupPermissions("CAN_READ", "CAN_EDIT", "CAN_MANAGE_STAGING_VERSIONS", "CAN_MANAGE_PRODUCTION_VERSIONS", "CAN_MANAGE")), + ExpectError: regexp.MustCompile("cannot remove management permissions for the current user for registered-model, allowed levels: CAN_MANAGE"), + }, Step{ + Template: "data databricks_current_user me {}", + Check: func(s *terraform.State) error { + w := databricks.Must(databricks.NewWorkspaceClient()) + permissions, err := w.Permissions.GetByRequestObjectTypeAndRequestObjectId(context.Background(), "registered-models", "root") + assert.NoError(t, err) + assert.Len(t, permissions.AccessControlList, 1) + assert.Equal(t, iam.AccessControlResponse{ + GroupName: "admins", + AllPermissions: []iam.Permission{ + { + PermissionLevel: iam.PermissionLevelCanManage, + ForceSendFields: []string{"Inherited", "PermissionLevel"}, + }, }, - ), + ForceSendFields: []string{"GroupName"}, + }, permissions.AccessControlList[0]) + return nil }, - Step{ - Template: config2, - Check: func(s *terraform.State) error { - id := getPermissionId(s) - assertPermissionLevel(t, id, "test-warehouse-permission-one-"+randomName, "CAN_MANAGE") - assertPermissionLevel(t, id, "test-warehouse-permission-two-"+randomName, "CAN_USE") - return nil - }, - }, - ) + }) +} + +func TestAccPermissions_ServingEndpoint(t *testing.T) { + loadDebugEnvIfRunsFromIDE(t, "workspace") + if isGcp(t) { + skipf(t)("Serving endpoints are not supported on GCP") + } + endpointTemplate := ` + resource "databricks_model_serving" "endpoint" { + name = "{var.STICKY_RANDOM}" + config { + served_models { + name = "prod_model" + model_name = "experiment-fixture-model" + model_version = "1" + workload_size = "Small" + scale_to_zero_enabled = true + } + traffic_config { + routes { + served_model_name = "prod_model" + traffic_percentage = 100 + } + } + } + }` + WorkspaceLevel(t, Step{ + Template: endpointTemplate + makePermissionsTestStage("serving_endpoint_id", "databricks_model_serving.endpoint.serving_endpoint_id", groupPermissions("CAN_VIEW")), + // Updating a serving endpoint seems to be flaky, so we'll only test that we can't remove management permissions for the current user. + // }, Step{ + // Template: endpointTemplate + makePermissionsTestStage("serving_endpoint_id", "databricks_model_serving.endpoint.id", currentPrincipalPermission(t, "CAN_MANAGE"), groupPermissions("CAN_VIEW", "CAN_QUERY", "CAN_MANAGE")), + }, Step{ + Template: endpointTemplate + makePermissionsTestStage("serving_endpoint_id", "databricks_model_serving.endpoint.serving_endpoint_id", currentPrincipalPermission(t, "CAN_VIEW"), groupPermissions("CAN_VIEW", "CAN_QUERY", "CAN_MANAGE")), + ExpectError: regexp.MustCompile("cannot remove management permissions for the current user for serving-endpoint, allowed levels: CAN_MANAGE"), + }) } diff --git a/permissions/entity/permissions_entity.go b/permissions/entity/permissions_entity.go new file mode 100644 index 0000000000..e8c1f4b067 --- /dev/null +++ b/permissions/entity/permissions_entity.go @@ -0,0 +1,18 @@ +package entity + +import "github.com/databricks/databricks-sdk-go/service/iam" + +// PermissionsEntity is the one used for resource metadata +type PermissionsEntity struct { + ObjectType string `json:"object_type,omitempty" tf:"computed"` + AccessControlList []iam.AccessControlRequest `json:"access_control" tf:"slice_set"` +} + +func (p PermissionsEntity) ContainsUserOrServicePrincipal(name string) bool { + for _, ac := range p.AccessControlList { + if ac.UserName == name || ac.ServicePrincipalName == name { + return true + } + } + return false +} diff --git a/permissions/permission_definitions.go b/permissions/permission_definitions.go new file mode 100644 index 0000000000..fbc9158517 --- /dev/null +++ b/permissions/permission_definitions.go @@ -0,0 +1,731 @@ +package permissions + +import ( + "context" + "fmt" + "sort" + "strconv" + "strings" + + "github.com/databricks/databricks-sdk-go" + "github.com/databricks/databricks-sdk-go/service/iam" + "github.com/databricks/terraform-provider-databricks/common" + "github.com/databricks/terraform-provider-databricks/permissions/entity" + "github.com/databricks/terraform-provider-databricks/permissions/read" + "github.com/databricks/terraform-provider-databricks/permissions/update" + "github.com/hashicorp/terraform-plugin-log/tflog" +) + +// resourcePermissions captures all the information needed to manage permissions for a given object type. +type resourcePermissions struct { + // Mandatory Fields + + // The attribute name that users configure with the ID of the object to manage + // e.g. "cluster_id" for a cluster + field string + // The object type to use in the Permissions API, e.g. "cluster" for a cluster. + objectType string + // The name of the object in the ID of the TF resource, e.g. "clusters" for a cluster, + // where the ID would be /clusters/. This should also match the prefix of the + // object ID in the API response, unless idMatcher is set. + requestObjectType string + // The allowed permission levels for this object type and its options. + allowedPermissionLevels map[string]permissionLevelOptions + + // ID Remapping Options + + // Returns the object ID for the given user-specified ID. This is necessary because permissions for + // some objects are done by path, whereas others are by ID. Those by path need to be converted to the + // internal object ID before being stored in the state. If not specified, the default ID is "//". + idRetriever func(ctx context.Context, w *databricks.WorkspaceClient, id string) (string, error) + // By default, a resourcePermissions can be retrieved based on the structure of the ID, as described above. + // If this function is set, it will be used to determine whether the ID matches this resource type. + idMatcher func(id string) bool + // A custom matcher to check whether a given ID matches this resource type. + // Most resources can be determined by looking at the attribute name used to configure the permission, but + // tokens & passwords are special cases where the resource type is determined by the value of this attribute. + stateMatcher func(id string) bool + + // Behavior Options and Customizations + + // The alternative name of the "path" attribute for this resource. E.g. "workspace_file_path" for a file. + // If not set, default is "_path". + pathVariant string + // If true, the provider will allow the user to configure the "admins" group for this resource type. Otherwise, + // validation will fail if the user tries to configure the "admins" group, and admin configurations in API + // responses will be ignored. This should only be set to true for the "authorization = passwords" resource. + allowConfiguringAdmins bool + // Customizers when handling permission resource creation and update. + // + // Most resources that have a CAN_MANAGE permission level should add update.AddCurrentUserAsManage to this list + // to ensure that the user applying the template always has management permissions on the underlying resource. + updateAclCustomizers []update.ACLCustomizer + // Customizers when handling permission resource deletion. + // + // Most resources that have a CAN_MANAGE permission level should add update.AddCurrentUserAsManage to this list + // to ensure that the user applying the template always has management permissions on the underlying resource. + deleteAclCustomizers []update.ACLCustomizer + // Customizers when handling permission resource read. + // + // Resources for which admins inherit permissions should add removeAdminPermissionsCustomizer to this list. This + // prevents the admin group from being included in the permissions when reading the state. + readAclCustomizers []read.ACLCustomizer + + // Returns the creator of the object. Used when deleting databricks_permissions resources, when the + // creator of the object is restored as the owner. + fetchObjectCreator func(ctx context.Context, w *databricks.WorkspaceClient, objectID string) (string, error) +} + +// getAllowedPermissionLevels returns the list of permission levels that are allowed for this resource type. +func (p resourcePermissions) getAllowedPermissionLevels(includeNonManagementPermissions bool) []string { + levels := make([]string, 0, len(p.allowedPermissionLevels)) + for level := range p.allowedPermissionLevels { + if includeNonManagementPermissions || p.allowedPermissionLevels[level].isManagementPermission { + levels = append(levels, level) + } + } + sort.Strings(levels) + return levels +} + +// resourceStatus captures the status of a resource with permissions. If the resource doesn't exist, +// the provider will not try to update its permissions. Otherwise, the creator will be returned if +// it can be determined for the given resource type. +type resourceStatus struct { + exists bool + creator string +} + +// getObjectStatus returns the creator of the object and whether the object exists. If the object creator cannot be determined for this +// resource type, an empty string is returned. Resources without fetchObjectCreator are assumed to exist and have an unknown creator. +func (p resourcePermissions) getObjectStatus(ctx context.Context, w *databricks.WorkspaceClient, objectID string) (resourceStatus, error) { + if p.fetchObjectCreator != nil { + creator, err := p.fetchObjectCreator(ctx, w, objectID) + if err != nil { + return resourceStatus{}, err + } + return resourceStatus{exists: creator != "", creator: creator}, nil + } + return resourceStatus{exists: true, creator: ""}, nil +} + +// getPathVariant returns the name of the path attribute for this resource type. +func (p resourcePermissions) getPathVariant() string { + if p.pathVariant != "" { + return p.pathVariant + } + return p.objectType + "_path" +} + +// validate checks that the user is not trying to set permissions for the admin group or remove their own management permissions. +func (p resourcePermissions) validate(ctx context.Context, entity entity.PermissionsEntity, currentUsername string) error { + for _, change := range entity.AccessControlList { + // Prevent users from setting permissions for admins. + if change.GroupName == "admins" && !p.allowConfiguringAdmins { + return fmt.Errorf("it is not possible to modify admin permissions for %s resources", p.objectType) + } + // Check that the user is preventing themselves from managing the object + level := p.allowedPermissionLevels[string(change.PermissionLevel)] + if (change.UserName == currentUsername || change.ServicePrincipalName == currentUsername) && !level.isManagementPermission { + allowedLevelsForCurrentUser := p.getAllowedPermissionLevels(false) + return fmt.Errorf("cannot remove management permissions for the current user for %s, allowed levels: %s", p.objectType, strings.Join(allowedLevelsForCurrentUser, ", ")) + } + + if level.deprecated != "" { + tflog.Debug(ctx, fmt.Sprintf("the permission level %s for %s is deprecated: %s", change.PermissionLevel, p.objectType, level.deprecated)) + } + } + return nil +} + +// getID returns the object ID for the given user-specified ID. +func (p resourcePermissions) getID(ctx context.Context, w *databricks.WorkspaceClient, id string) (string, error) { + var err error + if p.idRetriever != nil { + id, err = p.idRetriever(ctx, w, id) + if err != nil { + return "", err + } + } + return fmt.Sprintf("/%s/%s", p.requestObjectType, id), nil +} + +// prepareForUpdate prepares the access control list for an update request by calling all update customizers. +func (p resourcePermissions) prepareForUpdate(objectID string, e entity.PermissionsEntity, currentUser string) (entity.PermissionsEntity, error) { + cachedCurrentUser := func() (string, error) { return currentUser, nil } + ctx := update.ACLCustomizerContext{ + GetCurrentUser: cachedCurrentUser, + GetId: func() string { return objectID }, + } + var err error + for _, customizer := range p.updateAclCustomizers { + e.AccessControlList, err = customizer(ctx, e.AccessControlList) + if err != nil { + return entity.PermissionsEntity{}, err + } + } + return e, nil +} + +// prepareForDelete prepares the access control list for a delete request by calling all delete customizers. +func (p resourcePermissions) prepareForDelete(objectACL *iam.ObjectPermissions, getCurrentUser func() (string, error)) ([]iam.AccessControlRequest, error) { + accl := make([]iam.AccessControlRequest, 0, len(objectACL.AccessControlList)) + // By default, only admins have access to a resource when databricks_permissions for that resource are deleted. + for _, acl := range objectACL.AccessControlList { + if acl.GroupName != "admins" { + continue + } + for _, permission := range acl.AllPermissions { + if !permission.Inherited { + // keep everything direct for admin group + accl = append(accl, iam.AccessControlRequest{ + GroupName: acl.GroupName, + PermissionLevel: permission.PermissionLevel, + }) + break + } + } + } + ctx := update.ACLCustomizerContext{ + GetCurrentUser: getCurrentUser, + GetId: func() string { return objectACL.ObjectId }, + } + var err error + for _, customizer := range p.deleteAclCustomizers { + accl, err = customizer(ctx, accl) + if err != nil { + return nil, err + } + } + return accl, nil +} + +// prepareResponse prepares the access control list for a read response by calling all read customizers. +// +// If the user does not include an access_control block for themselves, it will not be included in the state. This +// prevents diffs when the applying user is not included in the access_control block for the resource but is +// added by update.AddCurrentUserAsManage. +// +// Read customizers are able to access the current state of the object in order to customize the response accordingly. +// For example, the SQL API previously used CAN_VIEW for read-only permission, but the GA API uses CAN_READ. Users may +// have CAN_VIEW in their resource configuration, so the read customizer will rewrite the response from CAN_READ to +// CAN_VIEW to match the user's configuration. +func (p resourcePermissions) prepareResponse(objectID string, objectACL *iam.ObjectPermissions, existing entity.PermissionsEntity, me string) (entity.PermissionsEntity, error) { + ctx := read.ACLCustomizerContext{ + GetId: func() string { return objectID }, + GetExistingPermissionsEntity: func() entity.PermissionsEntity { return existing }, + } + acl := *objectACL + for _, customizer := range p.readAclCustomizers { + acl = customizer(ctx, acl) + } + if acl.ObjectType != p.objectType { + return entity.PermissionsEntity{}, fmt.Errorf("expected object type %s, got %s", p.objectType, objectACL.ObjectType) + } + entity := entity.PermissionsEntity{} + for _, accessControl := range acl.AccessControlList { + // If the user doesn't include an access_control block for themselves, do not include it in the state. + // On create/update, the provider will automatically include the current user in the access_control block + // for appropriate resources. Otherwise, it must be included in state to prevent configuration drift. + if me == accessControl.UserName || me == accessControl.ServicePrincipalName { + if !existing.ContainsUserOrServicePrincipal(me) { + continue + } + } + // Skip admin permissions for resources where users are not allowed to explicitly configure them. + if accessControl.GroupName == "admins" && !p.allowConfiguringAdmins { + continue + } + for _, permission := range accessControl.AllPermissions { + // Inherited permissions can be ignored, as they are not set by the user. + if permission.Inherited { + continue + } + entity.AccessControlList = append(entity.AccessControlList, iam.AccessControlRequest{ + GroupName: accessControl.GroupName, + UserName: accessControl.UserName, + ServicePrincipalName: accessControl.ServicePrincipalName, + PermissionLevel: permission.PermissionLevel, + }) + } + } + return entity, nil +} + +// addOwnerPermissionIfNeeded adds the owner permission to the object ACL if the owner permission is allowed and not already set. +func (p resourcePermissions) addOwnerPermissionIfNeeded(objectACL []iam.AccessControlRequest, ownerOpt string) []iam.AccessControlRequest { + _, ok := p.allowedPermissionLevels["IS_OWNER"] + if !ok { + return objectACL + } + + for _, acl := range objectACL { + if acl.PermissionLevel == "IS_OWNER" { + return objectACL + } + } + + return append(objectACL, iam.AccessControlRequest{ + UserName: ownerOpt, + PermissionLevel: "IS_OWNER", + }) +} + +// permissionLevelOptions indicates the properties of a permissions level. Today, the only property +// is whether the current user can set the permission level for themselves. +type permissionLevelOptions struct { + // Whether users with this permission level are allowed to manage the resource. + // For some resources where ACLs don't define who can manage the resource, this might be unintuitive, + // e.g. all cluster policies permissions are considered management permissions because cluster policy + // ACLs don't define who can manage the cluster policy. + isManagementPermission bool + + // If non-empty, the permission level is deprecated. The string is a message to display to the user when + // this permission level is used. + deprecated string +} + +func getResourcePermissionsFromId(id string) (resourcePermissions, error) { + idParts := strings.Split(id, "/") + objectType := strings.Join(idParts[1:len(idParts)-1], "/") + for _, mapping := range allResourcePermissions() { + if mapping.idMatcher != nil { + if mapping.idMatcher(id) { + return mapping, nil + } + continue + } + if mapping.requestObjectType == objectType { + return mapping, nil + } + } + return resourcePermissions{}, fmt.Errorf("resource type for %s not found", id) +} + +// getResourcePermissionsFromState returns the resourcePermissions for the given state. +func getResourcePermissionsFromState(d interface{ GetOk(string) (any, bool) }) (resourcePermissions, string, error) { + allPermissions := allResourcePermissions() + for _, mapping := range allPermissions { + if v, ok := d.GetOk(mapping.field); ok { + id := v.(string) + if mapping.stateMatcher != nil && !mapping.stateMatcher(id) { + continue + } + return mapping, id, nil + } + } + allFields := make([]string, 0, len(allPermissions)) + seen := make(map[string]struct{}) + for _, mapping := range allPermissions { + if _, ok := seen[mapping.field]; ok { + continue + } + seen[mapping.field] = struct{}{} + allFields = append(allFields, mapping.field) + } + sort.Strings(allFields) + return resourcePermissions{}, "", fmt.Errorf("at least one type of resource identifier must be set; allowed fields: %s", strings.Join(allFields, ", ")) +} + +// getResourcePermissionsForObjectAcl returns the resourcePermissions for the given ObjectAclApiResponse. +// allResourcePermissions is the list of all resource types that can be managed by the databricks_permissions resource. +func allResourcePermissions() []resourcePermissions { + PATH := func(ctx context.Context, w *databricks.WorkspaceClient, path string) (string, error) { + info, err := w.Workspace.GetStatusByPath(ctx, path) + if err != nil { + return "", fmt.Errorf("cannot load path %s: %s", path, err) + } + return strconv.FormatInt(info.ObjectId, 10), nil + } + rewriteCanViewToCanRead := update.RewritePermissions(map[iam.PermissionLevel]iam.PermissionLevel{ + iam.PermissionLevelCanView: iam.PermissionLevelCanRead, + }) + rewriteCanReadToCanView := read.RewritePermissions(map[iam.PermissionLevel]iam.PermissionLevel{ + iam.PermissionLevelCanRead: iam.PermissionLevelCanView, + }) + return []resourcePermissions{ + { + field: "cluster_policy_id", + objectType: "cluster-policy", + requestObjectType: "cluster-policies", + allowedPermissionLevels: map[string]permissionLevelOptions{ + "CAN_USE": {isManagementPermission: true}, + }, + }, + { + field: "instance_pool_id", + objectType: "instance-pool", + requestObjectType: "instance-pools", + allowedPermissionLevels: map[string]permissionLevelOptions{ + "CAN_ATTACH_TO": {isManagementPermission: false}, + "CAN_MANAGE": {isManagementPermission: true}, + }, + updateAclCustomizers: []update.ACLCustomizer{update.AddCurrentUserAsManage}, + deleteAclCustomizers: []update.ACLCustomizer{update.AddCurrentUserAsManage}, + }, + { + field: "cluster_id", + objectType: "cluster", + requestObjectType: "clusters", + allowedPermissionLevels: map[string]permissionLevelOptions{ + "CAN_ATTACH_TO": {isManagementPermission: false}, + "CAN_RESTART": {isManagementPermission: false}, + "CAN_MANAGE": {isManagementPermission: true}, + }, + updateAclCustomizers: []update.ACLCustomizer{update.AddCurrentUserAsManage}, + deleteAclCustomizers: []update.ACLCustomizer{update.AddCurrentUserAsManage}, + }, + { + field: "pipeline_id", + objectType: "pipelines", + requestObjectType: "pipelines", + allowedPermissionLevels: map[string]permissionLevelOptions{ + "CAN_VIEW": {isManagementPermission: false}, + "CAN_RUN": {isManagementPermission: false}, + "CAN_MANAGE": {isManagementPermission: true}, + "IS_OWNER": {isManagementPermission: true}, + }, + fetchObjectCreator: func(ctx context.Context, w *databricks.WorkspaceClient, objectID string) (string, error) { + pipeline, err := w.Pipelines.GetByPipelineId(ctx, strings.ReplaceAll(objectID, "/pipelines/", "")) + if err != nil { + return "", common.IgnoreNotFoundError(err) + } + return pipeline.CreatorUserName, nil + }, + }, + { + field: "job_id", + objectType: "job", + requestObjectType: "jobs", + allowedPermissionLevels: map[string]permissionLevelOptions{ + "CAN_VIEW": {isManagementPermission: false}, + "CAN_MANAGE_RUN": {isManagementPermission: false}, + "IS_OWNER": {isManagementPermission: true}, + "CAN_MANAGE": {isManagementPermission: true}, + }, + fetchObjectCreator: func(ctx context.Context, w *databricks.WorkspaceClient, objectID string) (string, error) { + jobId, err := strconv.ParseInt(strings.ReplaceAll(objectID, "/jobs/", ""), 10, 64) + if err != nil { + return "", err + } + job, err := w.Jobs.GetByJobId(ctx, jobId) + if err != nil { + return "", common.IgnoreNotFoundError(err) + } + return job.CreatorUserName, nil + }, + }, + { + field: "notebook_id", + objectType: "notebook", + requestObjectType: "notebooks", + allowedPermissionLevels: map[string]permissionLevelOptions{ + "CAN_READ": {isManagementPermission: false}, + "CAN_RUN": {isManagementPermission: false}, + "CAN_EDIT": {isManagementPermission: false}, + "CAN_MANAGE": {isManagementPermission: true}, + }, + }, + { + field: "notebook_path", + objectType: "notebook", + requestObjectType: "notebooks", + allowedPermissionLevels: map[string]permissionLevelOptions{ + "CAN_READ": {isManagementPermission: false}, + "CAN_RUN": {isManagementPermission: false}, + "CAN_EDIT": {isManagementPermission: false}, + "CAN_MANAGE": {isManagementPermission: true}, + }, + idRetriever: PATH, + }, + { + field: "directory_id", + objectType: "directory", + requestObjectType: "directories", + allowedPermissionLevels: map[string]permissionLevelOptions{ + "CAN_READ": {isManagementPermission: false}, + "CAN_RUN": {isManagementPermission: false}, + "CAN_EDIT": {isManagementPermission: false}, + "CAN_MANAGE": {isManagementPermission: true}, + }, + updateAclCustomizers: []update.ACLCustomizer{ + update.If(update.ObjectIdMatches("/directories/0"), update.AddAdmin), + }, + deleteAclCustomizers: []update.ACLCustomizer{ + update.If(update.ObjectIdMatches("/directories/0"), update.AddAdmin), + }, + }, + { + field: "directory_path", + objectType: "directory", + requestObjectType: "directories", + allowedPermissionLevels: map[string]permissionLevelOptions{ + "CAN_READ": {isManagementPermission: false}, + "CAN_RUN": {isManagementPermission: false}, + "CAN_EDIT": {isManagementPermission: false}, + "CAN_MANAGE": {isManagementPermission: true}, + }, + idRetriever: PATH, + updateAclCustomizers: []update.ACLCustomizer{ + update.If(update.ObjectIdMatches("/directories/0"), update.AddAdmin), + }, + deleteAclCustomizers: []update.ACLCustomizer{ + update.If(update.ObjectIdMatches("/directories/0"), update.AddAdmin), + }, + }, + { + field: "workspace_file_id", + objectType: "file", + requestObjectType: "files", + allowedPermissionLevels: map[string]permissionLevelOptions{ + "CAN_READ": {isManagementPermission: false}, + "CAN_RUN": {isManagementPermission: false}, + "CAN_EDIT": {isManagementPermission: false}, + "CAN_MANAGE": {isManagementPermission: true}, + }, + pathVariant: "workspace_file_path", + }, + { + field: "workspace_file_path", + objectType: "file", + requestObjectType: "files", + allowedPermissionLevels: map[string]permissionLevelOptions{ + "CAN_READ": {isManagementPermission: false}, + "CAN_RUN": {isManagementPermission: false}, + "CAN_EDIT": {isManagementPermission: false}, + "CAN_MANAGE": {isManagementPermission: true}, + }, + idRetriever: PATH, + pathVariant: "workspace_file_path", + }, + { + field: "repo_id", + objectType: "repo", + requestObjectType: "repos", + allowedPermissionLevels: map[string]permissionLevelOptions{ + "CAN_READ": {isManagementPermission: false}, + "CAN_RUN": {isManagementPermission: false}, + "CAN_EDIT": {isManagementPermission: false}, + "CAN_MANAGE": {isManagementPermission: true}, + }, + }, + { + field: "repo_path", + objectType: "repo", + requestObjectType: "repos", + allowedPermissionLevels: map[string]permissionLevelOptions{ + "CAN_READ": {isManagementPermission: false}, + "CAN_RUN": {isManagementPermission: false}, + "CAN_EDIT": {isManagementPermission: false}, + "CAN_MANAGE": {isManagementPermission: true}, + }, + idRetriever: PATH, + }, + { + field: "authorization", + objectType: "tokens", + requestObjectType: "authorization", + stateMatcher: func(id string) bool { + return id == "tokens" + }, + idMatcher: func(id string) bool { + return id == "/authorization/tokens" + }, + allowedPermissionLevels: map[string]permissionLevelOptions{ + "CAN_USE": {isManagementPermission: true}, + "CAN_MANAGE": {isManagementPermission: true}, + }, + updateAclCustomizers: []update.ACLCustomizer{ + update.If(update.ObjectIdMatches("/authorization/tokens"), update.AddAdmin), + }, + }, + { + field: "authorization", + objectType: "passwords", + requestObjectType: "authorization", + stateMatcher: func(id string) bool { + return id == "passwords" + }, + idMatcher: func(id string) bool { + return id == "/authorization/passwords" + }, + allowedPermissionLevels: map[string]permissionLevelOptions{ + "CAN_USE": {isManagementPermission: true}, + }, + allowConfiguringAdmins: true, + }, + { + field: "sql_endpoint_id", + objectType: "warehouses", + requestObjectType: "sql/warehouses", + allowedPermissionLevels: map[string]permissionLevelOptions{ + "CAN_USE": {isManagementPermission: false}, + "CAN_MANAGE": {isManagementPermission: true}, + "CAN_MONITOR": {isManagementPermission: false}, + "IS_OWNER": {isManagementPermission: true}, + }, + updateAclCustomizers: []update.ACLCustomizer{update.AddCurrentUserAsManage}, + deleteAclCustomizers: []update.ACLCustomizer{update.AddCurrentUserAsManage}, + fetchObjectCreator: func(ctx context.Context, w *databricks.WorkspaceClient, objectID string) (string, error) { + warehouse, err := w.Warehouses.GetById(ctx, strings.ReplaceAll(objectID, "/sql/warehouses/", "")) + if err != nil { + return "", common.IgnoreNotFoundError(err) + } + return warehouse.CreatorName, nil + }, + }, + { + field: "sql_dashboard_id", + objectType: "dashboard", + requestObjectType: "dbsql-dashboards", + allowedPermissionLevels: map[string]permissionLevelOptions{ + "CAN_EDIT": {isManagementPermission: false}, + "CAN_RUN": {isManagementPermission: false}, + "CAN_MANAGE": {isManagementPermission: true}, + "CAN_READ": {isManagementPermission: false}, + // This was part of the original SQL permissions API but was replaced by CAN_READ in the GA API. + "CAN_VIEW": { + isManagementPermission: false, + deprecated: "use CAN_READ instead", + }, + }, + idMatcher: func(id string) bool { + return strings.HasPrefix(id, "/dbsql-dashboards/") || strings.HasPrefix(id, "/sql/dashboards/") + }, + updateAclCustomizers: []update.ACLCustomizer{ + update.AddCurrentUserAsManage, + rewriteCanViewToCanRead, + }, + deleteAclCustomizers: []update.ACLCustomizer{ + update.AddCurrentUserAsManage, + rewriteCanViewToCanRead, + }, + readAclCustomizers: []read.ACLCustomizer{ + rewriteCanReadToCanView, + func(ctx read.ACLCustomizerContext, objectAcls iam.ObjectPermissions) iam.ObjectPermissions { + // The object type in the new API is "dbsql-dashboard", but for compatibility this should + // be "dashboard" in the state. + objectAcls.ObjectType = "dashboard" + return objectAcls + }, + }, + }, + { + field: "sql_alert_id", + objectType: "alert", + requestObjectType: "sql/alerts", + allowedPermissionLevels: map[string]permissionLevelOptions{ + "CAN_EDIT": {isManagementPermission: false}, + "CAN_RUN": {isManagementPermission: false}, + "CAN_MANAGE": {isManagementPermission: true}, + "CAN_READ": {isManagementPermission: false}, + // This was part of the original SQL permissions API but was replaced by CAN_READ in the GA API. + // It should eventually be deprecated. + "CAN_VIEW": { + isManagementPermission: false, + deprecated: "use CAN_READ instead", + }, + }, + updateAclCustomizers: []update.ACLCustomizer{ + update.AddCurrentUserAsManage, + rewriteCanViewToCanRead, + }, + deleteAclCustomizers: []update.ACLCustomizer{ + update.AddCurrentUserAsManage, + rewriteCanViewToCanRead, + }, + readAclCustomizers: []read.ACLCustomizer{ + rewriteCanReadToCanView, + }, + }, + { + field: "sql_query_id", + objectType: "query", + requestObjectType: "sql/queries", + allowedPermissionLevels: map[string]permissionLevelOptions{ + "CAN_EDIT": {isManagementPermission: false}, + "CAN_RUN": {isManagementPermission: false}, + "CAN_MANAGE": {isManagementPermission: true}, + "CAN_READ": {isManagementPermission: false}, + // This was part of the original SQL permissions API but was replaced by CAN_READ in the GA API. + // It should eventually be deprecated. + "CAN_VIEW": { + isManagementPermission: false, + deprecated: "use CAN_READ instead", + }, + }, + updateAclCustomizers: []update.ACLCustomizer{ + update.AddCurrentUserAsManage, + rewriteCanViewToCanRead, + }, + deleteAclCustomizers: []update.ACLCustomizer{ + update.AddCurrentUserAsManage, + rewriteCanViewToCanRead, + }, + readAclCustomizers: []read.ACLCustomizer{ + rewriteCanReadToCanView, + }, + }, + { + field: "dashboard_id", + objectType: "dashboard", + requestObjectType: "dashboards", + allowedPermissionLevels: map[string]permissionLevelOptions{ + "CAN_EDIT": {isManagementPermission: false}, + "CAN_RUN": {isManagementPermission: false}, + "CAN_MANAGE": {isManagementPermission: true}, + "CAN_READ": {isManagementPermission: false}, + }, + readAclCustomizers: []read.ACLCustomizer{ + func(ctx read.ACLCustomizerContext, objectAcls iam.ObjectPermissions) iam.ObjectPermissions { + if strings.HasPrefix(objectAcls.ObjectId, "/dashboards/") { + // workaround for inconsistent API response returning object ID of file in the workspace + objectAcls.ObjectId = ctx.GetId() + } + return objectAcls + }, + }, + }, + { + field: "experiment_id", + objectType: "mlflowExperiment", + requestObjectType: "experiments", + allowedPermissionLevels: map[string]permissionLevelOptions{ + "CAN_READ": {isManagementPermission: false}, + "CAN_EDIT": {isManagementPermission: false}, + "CAN_MANAGE": {isManagementPermission: true}, + }, + }, + { + field: "registered_model_id", + objectType: "registered-model", + requestObjectType: "registered-models", + allowedPermissionLevels: map[string]permissionLevelOptions{ + "CAN_READ": {isManagementPermission: false}, + "CAN_EDIT": {isManagementPermission: false}, + "CAN_MANAGE_STAGING_VERSIONS": {isManagementPermission: false}, + "CAN_MANAGE_PRODUCTION_VERSIONS": {isManagementPermission: false}, + "CAN_MANAGE": {isManagementPermission: true}, + }, + updateAclCustomizers: []update.ACLCustomizer{ + update.AddCurrentUserAsManage, + update.If(update.ObjectIdMatches("/registered-models/root"), update.AddAdmin), + }, + deleteAclCustomizers: []update.ACLCustomizer{ + update.If(update.Not(update.ObjectIdMatches("/registered-models/root")), update.AddCurrentUserAsManage), + }, + }, + { + field: "serving_endpoint_id", + objectType: "serving-endpoint", + requestObjectType: "serving-endpoints", + allowedPermissionLevels: map[string]permissionLevelOptions{ + "CAN_VIEW": {isManagementPermission: false}, + "CAN_QUERY": {isManagementPermission: false}, + "CAN_MANAGE": {isManagementPermission: true}, + }, + updateAclCustomizers: []update.ACLCustomizer{update.AddCurrentUserAsManage}, + deleteAclCustomizers: []update.ACLCustomizer{update.AddCurrentUserAsManage}, + }, + } +} diff --git a/permissions/read/customizers.go b/permissions/read/customizers.go new file mode 100644 index 0000000000..3cee278fbb --- /dev/null +++ b/permissions/read/customizers.go @@ -0,0 +1,54 @@ +package read + +import ( + "github.com/databricks/databricks-sdk-go/service/iam" + "github.com/databricks/terraform-provider-databricks/permissions/entity" +) + +// Context that is available to aclReadCustomizer implementations. +type ACLCustomizerContext struct { + GetId func() string + GetExistingPermissionsEntity func() entity.PermissionsEntity +} + +// ACLCustomizer is a function that modifies the access control list of an object after it is read. +type ACLCustomizer func(ctx ACLCustomizerContext, objectAcls iam.ObjectPermissions) iam.ObjectPermissions + +// Rewrites the permission level of the access control list of an object after it is read. +// This is done only for resources in state where the permission level is equal to the replacement value +// in the mapping. For example, the permissons endpoint used to use the "CAN_VIEW" permission level for +// read-only access, but this was changed to "CAN_READ". Users who previously used "CAN_VIEW" should not +// be forced to change to "CAN_READ". This customizer will rewrite "CAN_READ" to "CAN_VIEW" when the +// user-specified value is CAN_VIEW and the API response is CAN_READ. +func RewritePermissions(mapping map[iam.PermissionLevel]iam.PermissionLevel) ACLCustomizer { + findOriginalAcl := func(new iam.AccessControlResponse, original entity.PermissionsEntity) (iam.AccessControlRequest, bool) { + for _, old := range original.AccessControlList { + if new.GroupName != "" && old.GroupName == new.GroupName { + return old, true + } + if new.UserName != "" && old.UserName == new.UserName { + return old, true + } + if new.ServicePrincipalName != "" && old.ServicePrincipalName == new.ServicePrincipalName { + return old, true + } + } + return iam.AccessControlRequest{}, false + } + return func(ctx ACLCustomizerContext, acl iam.ObjectPermissions) iam.ObjectPermissions { + original := ctx.GetExistingPermissionsEntity() + for i := range acl.AccessControlList { + inState, found := findOriginalAcl(acl.AccessControlList[i], original) + for j := range acl.AccessControlList[i].AllPermissions { + // If the original permission level is remapped to a replacement level, and the permission level + // in state is equal to the replacement level, we rewrite it to the replacement level. + original := acl.AccessControlList[i].AllPermissions[j].PermissionLevel + replacement, ok := mapping[original] + if ok && found && inState.PermissionLevel == replacement { + acl.AccessControlList[i].AllPermissions[j].PermissionLevel = replacement + } + } + } + return acl + } +} diff --git a/permissions/resource_permissions.go b/permissions/resource_permissions.go index fb0b24eebf..6eb138fb80 100644 --- a/permissions/resource_permissions.go +++ b/permissions/resource_permissions.go @@ -4,96 +4,17 @@ import ( "context" "errors" "fmt" - "log" "path" - "strconv" "strings" - "github.com/databricks/databricks-sdk-go" "github.com/databricks/databricks-sdk-go/apierr" + "github.com/databricks/databricks-sdk-go/service/iam" "github.com/databricks/terraform-provider-databricks/common" + "github.com/databricks/terraform-provider-databricks/permissions/entity" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -// ObjectACL is a structure to generically describe access control -type ObjectACL struct { - ObjectID string `json:"object_id,omitempty"` - ObjectType string `json:"object_type,omitempty"` - AccessControlList []AccessControl `json:"access_control_list"` -} - -// AccessControl is a structure to describe user/group permissions -type AccessControl struct { - UserName string `json:"user_name,omitempty"` - GroupName string `json:"group_name,omitempty"` - ServicePrincipalName string `json:"service_principal_name,omitempty"` - AllPermissions []Permission `json:"all_permissions,omitempty"` - - // SQLA entities don't use the `all_permissions` nesting, but rather a simple - // top level string with the permission level when retrieving permissions. - PermissionLevel string `json:"permission_level,omitempty"` -} - -func (ac AccessControl) toAccessControlChange() (AccessControlChange, bool) { - for _, permission := range ac.AllPermissions { - if permission.Inherited { - continue - } - return AccessControlChange{ - PermissionLevel: permission.PermissionLevel, - UserName: ac.UserName, - GroupName: ac.GroupName, - ServicePrincipalName: ac.ServicePrincipalName, - }, true - } - if ac.PermissionLevel != "" { - return AccessControlChange{ - PermissionLevel: ac.PermissionLevel, - UserName: ac.UserName, - GroupName: ac.GroupName, - ServicePrincipalName: ac.ServicePrincipalName, - }, true - } - return AccessControlChange{}, false -} - -func (ac AccessControl) String() string { - return fmt.Sprintf("%s%s%s%v", ac.GroupName, ac.UserName, ac.ServicePrincipalName, ac.AllPermissions) -} - -// Permission is a structure to describe permission level -type Permission struct { - PermissionLevel string `json:"permission_level"` - Inherited bool `json:"inherited,omitempty"` - InheritedFromObject []string `json:"inherited_from_object,omitempty"` -} - -func (p Permission) String() string { - if len(p.InheritedFromObject) > 0 { - return fmt.Sprintf("%s (from %s)", p.PermissionLevel, p.InheritedFromObject) - } - return p.PermissionLevel -} - -// AccessControlChangeList is wrapper around ACL changes for REST API -type AccessControlChangeList struct { - AccessControlList []AccessControlChange `json:"access_control_list"` -} - -// AccessControlChange is API wrapper for changing permissions -type AccessControlChange struct { - UserName string `json:"user_name,omitempty"` - GroupName string `json:"group_name,omitempty"` - ServicePrincipalName string `json:"service_principal_name,omitempty"` - PermissionLevel string `json:"permission_level"` -} - -func (acc AccessControlChange) String() string { - return fmt.Sprintf("%v%v%v %s", acc.UserName, acc.GroupName, acc.ServicePrincipalName, - acc.PermissionLevel) -} - // NewPermissionsAPI creates PermissionsAPI instance from provider meta func NewPermissionsAPI(ctx context.Context, m any) PermissionsAPI { return PermissionsAPI{ @@ -108,187 +29,103 @@ type PermissionsAPI struct { context context.Context } -func isDbsqlPermissionsWorkaroundNecessary(objectID string) bool { - return strings.HasPrefix(objectID, "/sql/") && !strings.HasPrefix(objectID, "/sql/warehouses") -} - -func urlPathForObjectID(objectID string) string { - if isDbsqlPermissionsWorkaroundNecessary(objectID) { - // Permissions for SQLA entities are routed differently from the others. - return "/preview/sql/permissions" + objectID[4:] - } - return "/permissions" + objectID -} - -// As described in https://github.com/databricks/terraform-provider-databricks/issues/1504, -// certain object types require that we explicitly grant the calling user CAN_MANAGE -// permissions when POSTing permissions changes through the REST API, to avoid accidentally -// revoking the calling user's ability to manage the current object. -func (a PermissionsAPI) shouldExplicitlyGrantCallingUserManagePermissions(objectID string) bool { - for _, prefix := range [...]string{"/registered-models/", "/clusters/", "/instance-pools/", "/serving-endpoints/", "/queries/", "/sql/warehouses"} { - if strings.HasPrefix(objectID, prefix) { - return true - } - } - return isDbsqlPermissionsWorkaroundNecessary(objectID) -} - -func isOwnershipWorkaroundNecessary(objectID string) bool { - return strings.HasPrefix(objectID, "/jobs") || strings.HasPrefix(objectID, "/pipelines") || strings.HasPrefix(objectID, "/sql/warehouses") -} - -func (a PermissionsAPI) getObjectCreator(objectID string) (string, error) { +// safePutWithOwner is a workaround for the limitation where warehouse without owners cannot have IS_OWNER set +func (a PermissionsAPI) safePutWithOwner(objectID string, objectACL []iam.AccessControlRequest, mapping resourcePermissions, ownerOpt string) error { w, err := a.client.WorkspaceClient() if err != nil { - return "", err + return err } - if strings.HasPrefix(objectID, "/jobs") { - jobId, err := strconv.ParseInt(strings.ReplaceAll(objectID, "/jobs/", ""), 10, 64) - if err != nil { - return "", err - } - job, err := w.Jobs.GetByJobId(a.context, jobId) - if err != nil { - return "", common.IgnoreNotFoundError(err) - } - return job.CreatorUserName, nil - } else if strings.HasPrefix(objectID, "/pipelines") { - pipeline, err := w.Pipelines.GetByPipelineId(a.context, strings.ReplaceAll(objectID, "/pipelines/", "")) - if err != nil { - return "", common.IgnoreNotFoundError(err) - } - return pipeline.CreatorUserName, nil - } else if strings.HasPrefix(objectID, "/sql/warehouses") { - warehouse, err := w.Warehouses.GetById(a.context, strings.ReplaceAll(objectID, "/sql/warehouses/", "")) - if err != nil { - return "", common.IgnoreNotFoundError(err) + idParts := strings.Split(objectID, "/") + id := idParts[len(idParts)-1] + withOwner := mapping.addOwnerPermissionIfNeeded(objectACL, ownerOpt) + _, err = w.Permissions.Set(a.context, iam.PermissionsRequest{ + RequestObjectId: id, + RequestObjectType: mapping.requestObjectType, + AccessControlList: withOwner, + }) + if err != nil { + if strings.Contains(err.Error(), "with no existing owner must provide a new owner") { + _, err = w.Permissions.Set(a.context, iam.PermissionsRequest{ + RequestObjectId: id, + RequestObjectType: mapping.requestObjectType, + AccessControlList: objectACL, + }) } - return warehouse.CreatorName, nil + return err } - return "", nil + return nil } -func (a PermissionsAPI) ensureCurrentUserCanManageObject(objectID string, objectACL AccessControlChangeList) (AccessControlChangeList, error) { - if !a.shouldExplicitlyGrantCallingUserManagePermissions(objectID) { - return objectACL, nil - } +func (a PermissionsAPI) getCurrentUser() (string, error) { w, err := a.client.WorkspaceClient() if err != nil { - return objectACL, err + return "", err } me, err := w.CurrentUser.Me(a.context) if err != nil { - return objectACL, err + return "", err } - objectACL.AccessControlList = append(objectACL.AccessControlList, AccessControlChange{ - UserName: me.UserName, - PermissionLevel: "CAN_MANAGE", - }) - return objectACL, nil + return me.UserName, nil } -// Helper function for applying permissions changes. Ensures that -// we select the correct HTTP method based on the object type and preserve the calling -// user's ability to manage the specified object when applying permissions changes. -func (a PermissionsAPI) put(objectID string, objectACL AccessControlChangeList) error { - objectACL, err := a.ensureCurrentUserCanManageObject(objectID, objectACL) +// Update updates object permissions. Technically, it's using method named SetOrDelete, but here we do more +func (a PermissionsAPI) Update(objectID string, entity entity.PermissionsEntity, mapping resourcePermissions) error { + currentUser, err := a.getCurrentUser() if err != nil { return err } - if isDbsqlPermissionsWorkaroundNecessary(objectID) { - // SQLA entities use POST for permission updates. - return a.client.Post(a.context, urlPathForObjectID(objectID), objectACL, nil) + // this logic was moved from CustomizeDiff because of undeterministic auth behavior + // in the corner-case scenarios. + // see https://github.com/databricks/terraform-provider-databricks/issues/2052 + err = mapping.validate(a.context, entity, currentUser) + if err != nil { + return err } - log.Printf("[DEBUG] PUT %s %v", objectID, objectACL) - return a.client.Put(a.context, urlPathForObjectID(objectID), objectACL) -} - -// safePutWithOwner is a workaround for the limitation where warehouse without owners cannot have IS_OWNER set -func (a PermissionsAPI) safePutWithOwner(objectID string, objectACL AccessControlChangeList, originalAcl []AccessControlChange) error { - err := a.put(objectID, objectACL) + prepared, err := mapping.prepareForUpdate(objectID, entity, currentUser) if err != nil { - if strings.Contains(err.Error(), "with no existing owner must provide a new owner") { - objectACL.AccessControlList = originalAcl - return a.put(objectID, objectACL) - } return err } - return nil + return a.safePutWithOwner(objectID, prepared.AccessControlList, mapping, currentUser) } -// Update updates object permissions. Technically, it's using method named SetOrDelete, but here we do more -func (a PermissionsAPI) Update(objectID string, objectACL AccessControlChangeList) error { - if objectID == "/authorization/tokens" || objectID == "/registered-models/root" || objectID == "/directories/0" { - // Prevent "Cannot change permissions for group 'admins' to None." - objectACL.AccessControlList = append(objectACL.AccessControlList, AccessControlChange{ - GroupName: "admins", - PermissionLevel: "CAN_MANAGE", - }) +// Delete gracefully removes permissions of non-admin users. After this operation, the object is managed +// by the current user and admin group. If the resource has IS_OWNER permissions, they are reset to the +// object creator, if it can be determined. +func (a PermissionsAPI) Delete(objectID string, mapping resourcePermissions) error { + objectACL, err := a.readRaw(objectID, mapping) + if err != nil { + return err } - originalAcl := make([]AccessControlChange, len(objectACL.AccessControlList)) - _ = copy(originalAcl, objectACL.AccessControlList) - if isOwnershipWorkaroundNecessary(objectID) { - owners := 0 - for _, acl := range objectACL.AccessControlList { - if acl.PermissionLevel == "IS_OWNER" { - owners++ - } - } - if owners == 0 { - w, err := a.client.WorkspaceClient() - if err != nil { - return err - } - me, err := w.CurrentUser.Me(a.context) - if err != nil { - return err - } - // add owner if it's missing, otherwise automated planning might be difficult - objectACL.AccessControlList = append(objectACL.AccessControlList, AccessControlChange{ - UserName: me.UserName, - PermissionLevel: "IS_OWNER", - }) - } + accl, err := mapping.prepareForDelete(objectACL, a.getCurrentUser) + if err != nil { + return err } - return a.safePutWithOwner(objectID, objectACL, originalAcl) -} - -// Delete gracefully removes permissions. Technically, it's using method named SetOrDelete, but here we do more -func (a PermissionsAPI) Delete(objectID string) error { - objectACL, err := a.Read(objectID) + w, err := a.client.WorkspaceClient() if err != nil { return err } - accl := AccessControlChangeList{} - for _, acl := range objectACL.AccessControlList { - if acl.GroupName == "admins" && objectID != "/authorization/passwords" { - if change, direct := acl.toAccessControlChange(); direct { - // keep everything direct for admin group - accl.AccessControlList = append(accl.AccessControlList, change) - } - } + resourceStatus, err := mapping.getObjectStatus(a.context, w, objectID) + if err != nil { + return err } - originalAcl := make([]AccessControlChange, len(accl.AccessControlList)) - _ = copy(originalAcl, accl.AccessControlList) - if isOwnershipWorkaroundNecessary(objectID) { - creator, err := a.getObjectCreator(objectID) - if err != nil { - return err - } - if creator == "" { - return nil - } - accl.AccessControlList = append(accl.AccessControlList, AccessControlChange{ - UserName: creator, - PermissionLevel: "IS_OWNER", - }) + // Do not bother resetting permissions for deleted resources + if !resourceStatus.exists { + return nil } - return a.safePutWithOwner(objectID, accl, originalAcl) + return a.safePutWithOwner(objectID, accl, mapping, resourceStatus.creator) } -// Read gets all relevant permissions for the object, including inherited ones -func (a PermissionsAPI) Read(objectID string) (objectACL ObjectACL, err error) { - err = a.client.Get(a.context, urlPathForObjectID(objectID), nil, &objectACL) +func (a PermissionsAPI) readRaw(objectID string, mapping resourcePermissions) (*iam.ObjectPermissions, error) { + w, err := a.client.WorkspaceClient() + if err != nil { + return nil, err + } + idParts := strings.Split(objectID, "/") + id := idParts[len(idParts)-1] + permissions, err := w.Permissions.Get(a.context, iam.GetPermissionRequest{ + RequestObjectId: id, + RequestObjectType: mapping.requestObjectType, + }) var apiErr *apierr.APIError // https://github.com/databricks/terraform-provider-databricks/issues/1227 // platform propagates INVALID_STATE error for auto-purged clusters in @@ -296,143 +133,34 @@ func (a PermissionsAPI) Read(objectID string) (objectACL ObjectACL, err error) { // cross-package dependency on "clusters". if errors.As(err, &apiErr) && strings.Contains(apiErr.Message, "Cannot access cluster") && apiErr.StatusCode == 400 { apiErr.StatusCode = 404 + apiErr.ErrorCode = "RESOURCE_DOES_NOT_EXIST" err = apiErr - return - } - if strings.HasPrefix(objectID, "/dashboards/") { - // workaround for inconsistent API response returning object ID of file in the workspace - objectACL.ObjectID = objectID - } - return -} - -// permissionsIDFieldMapping holds mapping -type permissionsIDFieldMapping struct { - field, objectType, resourceType string - - allowedPermissionLevels []string - - idRetriever func(ctx context.Context, w *databricks.WorkspaceClient, id string) (string, error) -} - -// PermissionsResourceIDFields shows mapping of id columns to resource types -func permissionsResourceIDFields() []permissionsIDFieldMapping { - SIMPLE := func(ctx context.Context, w *databricks.WorkspaceClient, id string) (string, error) { - return id, nil - } - PATH := func(ctx context.Context, w *databricks.WorkspaceClient, path string) (string, error) { - info, err := w.Workspace.GetStatusByPath(ctx, path) - if err != nil { - return "", fmt.Errorf("cannot load path %s: %s", path, err) - } - return strconv.FormatInt(info.ObjectId, 10), nil - } - return []permissionsIDFieldMapping{ - {"cluster_policy_id", "cluster-policy", "cluster-policies", []string{"CAN_USE"}, SIMPLE}, - {"instance_pool_id", "instance-pool", "instance-pools", []string{"CAN_ATTACH_TO", "CAN_MANAGE"}, SIMPLE}, - {"cluster_id", "cluster", "clusters", []string{"CAN_ATTACH_TO", "CAN_RESTART", "CAN_MANAGE"}, SIMPLE}, - {"pipeline_id", "pipelines", "pipelines", []string{"CAN_VIEW", "CAN_RUN", "CAN_MANAGE", "IS_OWNER"}, SIMPLE}, - {"job_id", "job", "jobs", []string{"CAN_VIEW", "CAN_MANAGE_RUN", "IS_OWNER", "CAN_MANAGE"}, SIMPLE}, - {"notebook_id", "notebook", "notebooks", []string{"CAN_READ", "CAN_RUN", "CAN_EDIT", "CAN_MANAGE"}, SIMPLE}, - {"notebook_path", "notebook", "notebooks", []string{"CAN_READ", "CAN_RUN", "CAN_EDIT", "CAN_MANAGE"}, PATH}, - {"directory_id", "directory", "directories", []string{"CAN_READ", "CAN_RUN", "CAN_EDIT", "CAN_MANAGE"}, SIMPLE}, - {"directory_path", "directory", "directories", []string{"CAN_READ", "CAN_RUN", "CAN_EDIT", "CAN_MANAGE"}, PATH}, - {"workspace_file_id", "file", "files", []string{"CAN_READ", "CAN_RUN", "CAN_EDIT", "CAN_MANAGE"}, SIMPLE}, - {"workspace_file_path", "file", "files", []string{"CAN_READ", "CAN_RUN", "CAN_EDIT", "CAN_MANAGE"}, PATH}, - {"repo_id", "repo", "repos", []string{"CAN_READ", "CAN_RUN", "CAN_EDIT", "CAN_MANAGE"}, SIMPLE}, - {"repo_path", "repo", "repos", []string{"CAN_READ", "CAN_RUN", "CAN_EDIT", "CAN_MANAGE"}, PATH}, - {"authorization", "tokens", "authorization", []string{"CAN_USE"}, SIMPLE}, - {"authorization", "passwords", "authorization", []string{"CAN_USE"}, SIMPLE}, - {"sql_endpoint_id", "warehouses", "sql/warehouses", []string{"CAN_USE", "CAN_MANAGE", "CAN_MONITOR", "IS_OWNER"}, SIMPLE}, - {"sql_dashboard_id", "dashboard", "sql/dashboards", []string{"CAN_EDIT", "CAN_RUN", "CAN_MANAGE", "CAN_VIEW"}, SIMPLE}, - {"sql_alert_id", "alert", "sql/alerts", []string{"CAN_EDIT", "CAN_RUN", "CAN_MANAGE", "CAN_VIEW"}, SIMPLE}, - {"sql_query_id", "query", "sql/queries", []string{"CAN_EDIT", "CAN_RUN", "CAN_MANAGE", "CAN_VIEW"}, SIMPLE}, - {"dashboard_id", "dashboard", "dashboards", []string{"CAN_EDIT", "CAN_RUN", "CAN_MANAGE", "CAN_READ"}, SIMPLE}, - {"experiment_id", "mlflowExperiment", "experiments", []string{"CAN_READ", "CAN_EDIT", "CAN_MANAGE"}, SIMPLE}, - {"registered_model_id", "registered-model", "registered-models", []string{ - "CAN_READ", "CAN_EDIT", "CAN_MANAGE_STAGING_VERSIONS", "CAN_MANAGE_PRODUCTION_VERSIONS", "CAN_MANAGE"}, SIMPLE}, - {"serving_endpoint_id", "serving-endpoint", "serving-endpoints", []string{"CAN_VIEW", "CAN_QUERY", "CAN_MANAGE"}, SIMPLE}, - } -} - -// PermissionsEntity is the one used for resource metadata -type PermissionsEntity struct { - ObjectType string `json:"object_type,omitempty" tf:"computed"` - AccessControlList []AccessControlChange `json:"access_control" tf:"slice_set"` -} - -func (oa *ObjectACL) isMatchingMapping(mapping permissionsIDFieldMapping) bool { - if mapping.objectType != oa.ObjectType { - return false - } - if oa.ObjectID != "" && oa.ObjectID[0] == '/' { - return strings.HasPrefix(oa.ObjectID[1:], mapping.resourceType) - } - if strings.HasPrefix(oa.ObjectID, "dashboards/") || strings.HasPrefix(oa.ObjectID, "alerts/") || strings.HasPrefix(oa.ObjectID, "queries/") { - idx := strings.Index(oa.ObjectID, "/") - if idx != -1 { - return mapping.resourceType == "sql/"+oa.ObjectID[:idx] - } - } - - return false -} - -func (oa *ObjectACL) ToPermissionsEntity(d *schema.ResourceData, me string) (PermissionsEntity, error) { - entity := PermissionsEntity{} - for _, accessControl := range oa.AccessControlList { - if accessControl.GroupName == "admins" && d.Id() != "/authorization/passwords" { - // not possible to lower admins permissions anywhere from CAN_MANAGE - continue - } - if me == accessControl.UserName || me == accessControl.ServicePrincipalName { - // not possible to lower one's permissions anywhere from CAN_MANAGE - continue - } - if change, direct := accessControl.toAccessControlChange(); direct { - entity.AccessControlList = append(entity.AccessControlList, change) - } } - for _, mapping := range permissionsResourceIDFields() { - if !oa.isMatchingMapping(mapping) { - continue - } - entity.ObjectType = mapping.objectType - var pathVariant any - if mapping.objectType == "file" { - pathVariant = d.Get("workspace_file_path") - } else { - pathVariant = d.Get(mapping.objectType + "_path") - } - if pathVariant != nil && pathVariant.(string) != "" { - // we're not importing and it's a path... it's set, so let's not re-set it - return entity, nil - } - identifier := path.Base(oa.ObjectID) - return entity, d.Set(mapping.field, identifier) + if err != nil { + return nil, err } - return entity, fmt.Errorf("unknown object type %s", oa.ObjectType) + return permissions, nil } -func stringInSlice(a string, list []string) bool { - for _, b := range list { - if b == a { - return true - } +// Read gets all relevant permissions for the object, including inherited ones +func (a PermissionsAPI) Read(objectID string, mapping resourcePermissions, existing entity.PermissionsEntity, me string) (entity.PermissionsEntity, error) { + permissions, err := a.readRaw(objectID, mapping) + if err != nil { + return entity.PermissionsEntity{}, err } - return false + return mapping.prepareResponse(objectID, permissions, existing, me) } // ResourcePermissions definition func ResourcePermissions() common.Resource { - s := common.StructToSchema(PermissionsEntity{}, func(s map[string]*schema.Schema) map[string]*schema.Schema { - for _, mapping := range permissionsResourceIDFields() { + s := common.StructToSchema(entity.PermissionsEntity{}, func(s map[string]*schema.Schema) map[string]*schema.Schema { + for _, mapping := range allResourcePermissions() { s[mapping.field] = &schema.Schema{ ForceNew: true, Type: schema.TypeString, Optional: true, } - for _, m := range permissionsResourceIDFields() { + for _, m := range allResourcePermissions() { if m.field == mapping.field { continue } @@ -445,38 +173,44 @@ func ResourcePermissions() common.Resource { return common.Resource{ Schema: s, CustomizeDiff: func(ctx context.Context, diff *schema.ResourceDiff) error { + mapping, _, err := getResourcePermissionsFromState(diff) + if err != nil { + // This preserves current behavior but is likely only exercised in tests where + // the original config is not specified. + return nil + } + planned := entity.PermissionsEntity{} + common.DiffToStructPointer(diff, s, &planned) // Plan time validation for object permission levels - for _, mapping := range permissionsResourceIDFields() { - if _, ok := diff.GetOk(mapping.field); !ok { + for _, accessControl := range planned.AccessControlList { + permissionLevel := accessControl.PermissionLevel + // No diff in permission level, so don't need to check. + if permissionLevel == "" { continue } - access_control_list := diff.Get("access_control").(*schema.Set).List() - for _, access_control := range access_control_list { - m := access_control.(map[string]any) - permission_level := m["permission_level"].(string) - if !stringInSlice(permission_level, mapping.allowedPermissionLevels) { - return fmt.Errorf(`permission_level %s is not supported with %s objects`, - permission_level, mapping.field) - } + // TODO: only warn on unknown permission levels, as new levels may be released that the TF provider + // is not aware of. + if _, ok := mapping.allowedPermissionLevels[string(permissionLevel)]; !ok { + return fmt.Errorf(`permission_level %s is not supported with %s objects; allowed levels: %s`, + permissionLevel, mapping.field, strings.Join(mapping.getAllowedPermissionLevels(true), ", ")) } } return nil }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - id := d.Id() - w, err := c.WorkspaceClient() - if err != nil { - return err - } - objectACL, err := NewPermissionsAPI(ctx, c).Read(id) + a := NewPermissionsAPI(ctx, c) + mapping, err := getResourcePermissionsFromId(d.Id()) if err != nil { return err } - me, err := w.CurrentUser.Me(ctx) + var existing entity.PermissionsEntity + common.DataToStructPointer(d, s, &existing) + me, err := a.getCurrentUser() if err != nil { return err } - entity, err := objectACL.ToPermissionsEntity(d, me.UserName) + id := d.Id() + entity, err := a.Read(id, mapping, existing, me) if err != nil { return err } @@ -485,61 +219,53 @@ func ResourcePermissions() common.Resource { d.SetId("") return nil } + entity.ObjectType = mapping.objectType + pathVariant := d.Get(mapping.getPathVariant()) + if pathVariant == nil || pathVariant.(string) == "" { + identifier := path.Base(id) + if err = d.Set(mapping.field, identifier); err != nil { + return err + } + } return common.StructToData(entity, s, d) }, Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - var entity PermissionsEntity + var entity entity.PermissionsEntity common.DataToStructPointer(d, s, &entity) w, err := c.WorkspaceClient() if err != nil { return err } - me, err := w.CurrentUser.Me(ctx) + mapping, configuredValue, err := getResourcePermissionsFromState(d) if err != nil { return err } - for _, mapping := range permissionsResourceIDFields() { - if v, ok := d.GetOk(mapping.field); ok { - id, err := mapping.idRetriever(ctx, w, v.(string)) - if err != nil { - return err - } - objectID := fmt.Sprintf("/%s/%s", mapping.resourceType, id) - // this logic was moved from CustomizeDiff because of undeterministic auth behavior - // in the corner-case scenarios. - // see https://github.com/databricks/terraform-provider-databricks/issues/2052 - for _, v := range entity.AccessControlList { - if v.UserName == me.UserName { - format := "it is not possible to decrease administrative permissions for the current user: %s" - return fmt.Errorf(format, me.UserName) - } - - if v.GroupName == "admins" && mapping.resourceType != "authorization" { - // should allow setting admins permissions for passwords and tokens usage - return fmt.Errorf("it is not possible to restrict any permissions from `admins`") - } - } - err = NewPermissionsAPI(ctx, c).Update(objectID, AccessControlChangeList{ - AccessControlList: entity.AccessControlList, - }) - if err != nil { - return err - } - d.SetId(objectID) - return nil - } + objectID, err := mapping.getID(ctx, w, configuredValue) + if err != nil { + return err + } + err = NewPermissionsAPI(ctx, c).Update(objectID, entity, mapping) + if err != nil { + return err } - return errors.New("at least one type of resource identifiers must be set") + d.SetId(objectID) + return nil }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - var entity PermissionsEntity + var entity entity.PermissionsEntity common.DataToStructPointer(d, s, &entity) - return NewPermissionsAPI(ctx, c).Update(d.Id(), AccessControlChangeList{ - AccessControlList: entity.AccessControlList, - }) + mapping, err := getResourcePermissionsFromId(d.Id()) + if err != nil { + return err + } + return NewPermissionsAPI(ctx, c).Update(d.Id(), entity, mapping) }, Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - return NewPermissionsAPI(ctx, c).Delete(d.Id()) + mapping, err := getResourcePermissionsFromId(d.Id()) + if err != nil { + return err + } + return NewPermissionsAPI(ctx, c).Delete(d.Id(), mapping) }, } } diff --git a/permissions/resource_permissions_test.go b/permissions/resource_permissions_test.go index b01fddb1ca..7019ae5c56 100644 --- a/permissions/resource_permissions_test.go +++ b/permissions/resource_permissions_test.go @@ -2,17 +2,21 @@ package permissions import ( "context" - "net/http" + "fmt" "testing" + "github.com/stretchr/testify/mock" + "github.com/databricks/databricks-sdk-go" "github.com/databricks/databricks-sdk-go/apierr" + "github.com/databricks/databricks-sdk-go/experimental/mocks" + "github.com/databricks/databricks-sdk-go/service/iam" "github.com/databricks/databricks-sdk-go/service/jobs" + "github.com/databricks/databricks-sdk-go/service/pipelines" + "github.com/databricks/databricks-sdk-go/service/workspace" "github.com/databricks/terraform-provider-databricks/common" - "github.com/databricks/terraform-provider-databricks/scim" - + "github.com/databricks/terraform-provider-databricks/permissions/entity" "github.com/databricks/terraform-provider-databricks/qa" - "github.com/databricks/terraform-provider-databricks/workspace" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -22,70 +26,39 @@ var ( TestingUser = "ben" TestingAdminUser = "admin" TestingOwner = "testOwner" - me = qa.HTTPFixture{ - ReuseRequest: true, - Method: "GET", - Resource: "/api/2.0/preview/scim/v2/Me", - Response: scim.User{ - UserName: TestingAdminUser, - }, - } ) -func TestEntityAccessControlChangeString(t *testing.T) { - assert.Equal(t, "me CAN_READ", AccessControlChange{ - UserName: "me", - PermissionLevel: "CAN_READ", - }.String()) -} - -func TestEntityAccessControlString(t *testing.T) { - assert.Equal(t, "me[CAN_READ (from [parent]) CAN_MANAGE]", AccessControl{ - UserName: "me", - AllPermissions: []Permission{ - { - InheritedFromObject: []string{"parent"}, - PermissionLevel: "CAN_READ", - }, - { - PermissionLevel: "CAN_MANAGE", - }, - }, - }.String()) -} - func TestResourcePermissionsRead(t *testing.T) { d, err := qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - me, - { - Method: http.MethodGet, - Resource: "/api/2.0/permissions/clusters/abc", - Response: ObjectACL{ - ObjectID: "/clusters/abc", - ObjectType: "cluster", - AccessControlList: []AccessControl{ - { - UserName: TestingUser, - AllPermissions: []Permission{ - { - PermissionLevel: "CAN_READ", - Inherited: false, - }, + MockWorkspaceClientFunc: func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockCurrentUserAPI().EXPECT().Me(mock.Anything).Return(&iam.User{UserName: "admin"}, nil) + mwc.GetMockPermissionsAPI().EXPECT().Get(mock.Anything, iam.GetPermissionRequest{ + RequestObjectId: "abc", + RequestObjectType: "clusters", + }).Return(&iam.ObjectPermissions{ + ObjectId: "/clusters/abc", + ObjectType: "cluster", + AccessControlList: []iam.AccessControlResponse{ + { + UserName: TestingUser, + AllPermissions: []iam.Permission{ + { + PermissionLevel: "CAN_READ", + Inherited: false, }, }, - { - UserName: TestingAdminUser, - AllPermissions: []Permission{ - { - PermissionLevel: "CAN_MANAGE", - Inherited: false, - }, + }, + { + UserName: TestingAdminUser, + AllPermissions: []iam.Permission{ + { + PermissionLevel: "CAN_MANAGE", + Inherited: false, }, }, }, }, - }, + }, nil) }, Resource: ResourcePermissions(), Read: true, @@ -104,17 +77,16 @@ func TestResourcePermissionsRead(t *testing.T) { // https://github.com/databricks/terraform-provider-databricks/issues/1227 func TestResourcePermissionsRead_RemovedCluster(t *testing.T) { qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - me, - { - Method: http.MethodGet, - Resource: "/api/2.0/permissions/clusters/abc", - Status: 400, - Response: apierr.APIError{ - ErrorCode: "INVALID_STATE", - Message: "Cannot access cluster X that was terminated or unpinned more than Y days ago.", - }, - }, + MockWorkspaceClientFunc: func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockCurrentUserAPI().EXPECT().Me(mock.Anything).Return(&iam.User{UserName: "admin"}, nil) + mwc.GetMockPermissionsAPI().EXPECT().Get(mock.Anything, iam.GetPermissionRequest{ + RequestObjectId: "abc", + RequestObjectType: "clusters", + }).Return(nil, &apierr.APIError{ + StatusCode: 400, + ErrorCode: "INVALID_STATE", + Message: "Cannot access cluster X that was terminated or unpinned more than Y days ago.", + }) }, Resource: ResourcePermissions(), Read: true, @@ -126,27 +98,25 @@ func TestResourcePermissionsRead_RemovedCluster(t *testing.T) { func TestResourcePermissionsRead_Mlflow_Model(t *testing.T) { d, err := qa.ResourceFixture{ - // Pass list of API request mocks - Fixtures: []qa.HTTPFixture{ - me, - { - Method: http.MethodGet, - Resource: "/api/2.0/permissions/registered-models/fakeuuid123", - Response: ObjectACL{ - ObjectID: "/registered-models/fakeuuid123", - ObjectType: "registered-model", - AccessControlList: []AccessControl{ - { - UserName: TestingUser, - PermissionLevel: "CAN_READ", - }, - { - UserName: TestingAdminUser, - PermissionLevel: "CAN_MANAGE", - }, + MockWorkspaceClientFunc: func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockCurrentUserAPI().EXPECT().Me(mock.Anything).Return(&iam.User{UserName: "admin"}, nil) + mwc.GetMockPermissionsAPI().EXPECT().Get(mock.Anything, iam.GetPermissionRequest{ + RequestObjectId: "fakeuuid123", + RequestObjectType: "registered-models", + }).Return(&iam.ObjectPermissions{ + ObjectId: "/registered-models/fakeuuid123", + ObjectType: "registered-model", + AccessControlList: []iam.AccessControlResponse{ + { + UserName: TestingUser, + AllPermissions: []iam.Permission{{PermissionLevel: iam.PermissionLevelCanRead}}, + }, + { + UserName: TestingAdminUser, + AllPermissions: []iam.Permission{{PermissionLevel: iam.PermissionLevelCanManage}}, }, }, - }, + }, nil) }, Resource: ResourcePermissions(), Read: true, @@ -164,42 +134,40 @@ func TestResourcePermissionsRead_Mlflow_Model(t *testing.T) { func TestResourcePermissionsCreate_Mlflow_Model(t *testing.T) { d, err := qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - me, - { - Method: http.MethodPut, - Resource: "/api/2.0/permissions/registered-models/fakeuuid123", - ExpectedRequest: AccessControlChangeList{ - AccessControlList: []AccessControlChange{ - { - UserName: TestingUser, - PermissionLevel: "CAN_READ", - }, - { - UserName: TestingAdminUser, - PermissionLevel: "CAN_MANAGE", - }, + MockWorkspaceClientFunc: func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockCurrentUserAPI().EXPECT().Me(mock.Anything).Return(&iam.User{UserName: "admin"}, nil) + e := mwc.GetMockPermissionsAPI().EXPECT() + e.Set(mock.Anything, iam.PermissionsRequest{ + RequestObjectId: "fakeuuid123", + RequestObjectType: "registered-models", + AccessControlList: []iam.AccessControlRequest{ + { + UserName: TestingUser, + PermissionLevel: "CAN_READ", + }, + { + UserName: TestingAdminUser, + PermissionLevel: "CAN_MANAGE", }, }, - }, - { - Method: http.MethodGet, - Resource: "/api/2.0/permissions/registered-models/fakeuuid123", - Response: ObjectACL{ - ObjectID: "/registered-models/fakeuuid123", - ObjectType: "registered-model", - AccessControlList: []AccessControl{ - { - UserName: TestingUser, - PermissionLevel: "CAN_READ", - }, - { - UserName: TestingAdminUser, - PermissionLevel: "CAN_MANAGE", - }, + }).Return(nil, nil) + e.Get(mock.Anything, iam.GetPermissionRequest{ + RequestObjectId: "fakeuuid123", + RequestObjectType: "registered-models", + }).Return(&iam.ObjectPermissions{ + ObjectId: "/registered-models/fakeuuid123", + ObjectType: "registered-model", + AccessControlList: []iam.AccessControlResponse{ + { + UserName: TestingUser, + AllPermissions: []iam.Permission{{PermissionLevel: iam.PermissionLevelCanRead}}, + }, + { + UserName: TestingAdminUser, + AllPermissions: []iam.Permission{{PermissionLevel: iam.PermissionLevelCanManage}}, }, }, - }, + }, nil) }, Resource: ResourcePermissions(), State: map[string]any{ @@ -223,42 +191,40 @@ func TestResourcePermissionsCreate_Mlflow_Model(t *testing.T) { func TestResourcePermissionsUpdate_Mlflow_Model(t *testing.T) { d, err := qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - me, - { - Method: http.MethodPut, - Resource: "/api/2.0/permissions/registered-models/fakeuuid123", - ExpectedRequest: AccessControlChangeList{ - AccessControlList: []AccessControlChange{ - { - UserName: TestingUser, - PermissionLevel: "CAN_READ", - }, - { - UserName: TestingAdminUser, - PermissionLevel: "CAN_MANAGE", - }, + MockWorkspaceClientFunc: func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockCurrentUserAPI().EXPECT().Me(mock.Anything).Return(&iam.User{UserName: "admin"}, nil) + e := mwc.GetMockPermissionsAPI().EXPECT() + e.Set(mock.Anything, iam.PermissionsRequest{ + RequestObjectId: "fakeuuid123", + RequestObjectType: "registered-models", + AccessControlList: []iam.AccessControlRequest{ + { + UserName: TestingUser, + PermissionLevel: "CAN_READ", + }, + { + UserName: TestingAdminUser, + PermissionLevel: "CAN_MANAGE", }, }, - }, - { - Method: http.MethodGet, - Resource: "/api/2.0/permissions/registered-models/fakeuuid123", - Response: ObjectACL{ - ObjectID: "/registered-models/fakeuuid123", - ObjectType: "registered-model", - AccessControlList: []AccessControl{ - { - UserName: TestingUser, - PermissionLevel: "CAN_READ", - }, - { - UserName: TestingAdminUser, - PermissionLevel: "CAN_MANAGE", - }, + }).Return(nil, nil) + e.Get(mock.Anything, iam.GetPermissionRequest{ + RequestObjectId: "fakeuuid123", + RequestObjectType: "registered-models", + }).Return(&iam.ObjectPermissions{ + ObjectId: "/registered-models/fakeuuid123", + ObjectType: "registered-model", + AccessControlList: []iam.AccessControlResponse{ + { + UserName: TestingUser, + AllPermissions: []iam.Permission{{PermissionLevel: iam.PermissionLevelCanRead}}, + }, + { + UserName: TestingAdminUser, + AllPermissions: []iam.Permission{{PermissionLevel: iam.PermissionLevelCanManage}}, }, }, - }, + }, nil) }, InstanceState: map[string]string{ "registered_model_id": "fakeuuid123", @@ -287,38 +253,36 @@ func TestResourcePermissionsUpdate_Mlflow_Model(t *testing.T) { func TestResourcePermissionsDelete_Mlflow_Model(t *testing.T) { d, err := qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - me, - { - Method: http.MethodGet, - Resource: "/api/2.0/permissions/registered-models/fakeuuid123", - Response: ObjectACL{ - ObjectID: "/registered-models/fakeuuid123", - ObjectType: "registered-model", - AccessControlList: []AccessControl{ - { - UserName: TestingUser, - PermissionLevel: "CAN_READ", - }, - { - UserName: TestingAdminUser, - PermissionLevel: "CAN_MANAGE", - }, + MockWorkspaceClientFunc: func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockCurrentUserAPI().EXPECT().Me(mock.Anything).Return(&iam.User{UserName: "admin"}, nil) + e := mwc.GetMockPermissionsAPI().EXPECT() + e.Get(mock.Anything, iam.GetPermissionRequest{ + RequestObjectId: "fakeuuid123", + RequestObjectType: "registered-models", + }).Return(&iam.ObjectPermissions{ + ObjectId: "/registered-models/fakeuuid123", + ObjectType: "registered-model", + AccessControlList: []iam.AccessControlResponse{ + { + UserName: TestingUser, + AllPermissions: []iam.Permission{{PermissionLevel: iam.PermissionLevelCanRead}}, + }, + { + UserName: TestingAdminUser, + AllPermissions: []iam.Permission{{PermissionLevel: iam.PermissionLevelCanManage}}, }, }, - }, - { - Method: http.MethodPut, - Resource: "/api/2.0/permissions/registered-models/fakeuuid123", - ExpectedRequest: AccessControlChangeList{ - AccessControlList: []AccessControlChange{ - { - UserName: TestingAdminUser, - PermissionLevel: "CAN_MANAGE", - }, + }, nil) + e.Set(mock.Anything, iam.PermissionsRequest{ + RequestObjectId: "fakeuuid123", + RequestObjectType: "registered-models", + AccessControlList: []iam.AccessControlRequest{ + { + UserName: TestingAdminUser, + PermissionLevel: "CAN_MANAGE", }, }, - }, + }).Return(nil, nil) }, Resource: ResourcePermissions(), Delete: true, @@ -330,31 +294,38 @@ func TestResourcePermissionsDelete_Mlflow_Model(t *testing.T) { func TestResourcePermissionsRead_SQLA_Asset(t *testing.T) { d, err := qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - me, - { - Method: http.MethodGet, - Resource: "/api/2.0/preview/sql/permissions/dashboards/abc", - Response: ObjectACL{ - ObjectID: "dashboards/abc", - ObjectType: "dashboard", - AccessControlList: []AccessControl{ - { - UserName: TestingUser, - PermissionLevel: "CAN_READ", - }, - { - UserName: TestingAdminUser, - PermissionLevel: "CAN_MANAGE", - }, + MockWorkspaceClientFunc: func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockCurrentUserAPI().EXPECT().Me(mock.Anything).Return(&iam.User{UserName: "admin"}, nil) + e := mwc.GetMockPermissionsAPI().EXPECT() + e.Get(mock.Anything, iam.GetPermissionRequest{ + RequestObjectId: "abc", + RequestObjectType: "dbsql-dashboards", + }).Return(&iam.ObjectPermissions{ + ObjectId: "dashboards/abc", + ObjectType: "dashboard", + AccessControlList: []iam.AccessControlResponse{ + { + UserName: TestingUser, + AllPermissions: []iam.Permission{{PermissionLevel: iam.PermissionLevelCanRead}}, + }, + { + UserName: TestingAdminUser, + AllPermissions: []iam.Permission{{PermissionLevel: iam.PermissionLevelCanManage}}, }, }, - }, + }, nil) }, Resource: ResourcePermissions(), Read: true, New: true, ID: "/sql/dashboards/abc", + HCL: ` + sql_dashboard_id = "abc" + access_control { + user_name = "ben" + permission_level = "CAN_VIEW" + } + `, }.Apply(t) assert.NoError(t, err) assert.Equal(t, "/sql/dashboards/abc", d.Id()) @@ -362,31 +333,31 @@ func TestResourcePermissionsRead_SQLA_Asset(t *testing.T) { require.Equal(t, 1, len(ac.List())) firstElem := ac.List()[0].(map[string]any) assert.Equal(t, TestingUser, firstElem["user_name"]) - assert.Equal(t, "CAN_READ", firstElem["permission_level"]) + assert.Equal(t, "CAN_VIEW", firstElem["permission_level"]) } func TestResourcePermissionsRead_Dashboard(t *testing.T) { d, err := qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - me, - { - Method: http.MethodGet, - Resource: "/api/2.0/permissions/dashboards/abc", - Response: ObjectACL{ - ObjectID: "dashboards/abc", - ObjectType: "dashboard", - AccessControlList: []AccessControl{ - { - UserName: TestingUser, - PermissionLevel: "CAN_READ", - }, - { - UserName: TestingAdminUser, - PermissionLevel: "CAN_MANAGE", - }, + MockWorkspaceClientFunc: func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockCurrentUserAPI().EXPECT().Me(mock.Anything).Return(&iam.User{UserName: "admin"}, nil) + e := mwc.GetMockPermissionsAPI().EXPECT() + e.Get(mock.Anything, iam.GetPermissionRequest{ + RequestObjectId: "abc", + RequestObjectType: "dashboards", + }).Return(&iam.ObjectPermissions{ + ObjectId: "dashboards/abc", + ObjectType: "dashboard", + AccessControlList: []iam.AccessControlResponse{ + { + UserName: TestingUser, + AllPermissions: []iam.Permission{{PermissionLevel: iam.PermissionLevelCanRead}}, + }, + { + UserName: TestingAdminUser, + AllPermissions: []iam.Permission{{PermissionLevel: iam.PermissionLevelCanManage}}, }, }, - }, + }, nil) }, Resource: ResourcePermissions(), Read: true, @@ -405,17 +376,16 @@ func TestResourcePermissionsRead_Dashboard(t *testing.T) { func TestResourcePermissionsRead_NotFound(t *testing.T) { qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - me, - { - Method: http.MethodGet, - Resource: "/api/2.0/permissions/clusters/abc", - Response: apierr.APIError{ - ErrorCode: "NOT_FOUND", - Message: "Cluster does not exist", - }, - Status: 404, - }, + MockWorkspaceClientFunc: func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockCurrentUserAPI().EXPECT().Me(mock.Anything).Return(&iam.User{UserName: "admin"}, nil) + mwc.GetMockPermissionsAPI().EXPECT().Get(mock.Anything, iam.GetPermissionRequest{ + RequestObjectId: "abc", + RequestObjectType: "clusters", + }).Return(nil, &apierr.APIError{ + StatusCode: 404, + ErrorCode: "NOT_FOUND", + Message: "Cluster does not exist", + }) }, Resource: ResourcePermissions(), Read: true, @@ -427,17 +397,16 @@ func TestResourcePermissionsRead_NotFound(t *testing.T) { func TestResourcePermissionsRead_some_error(t *testing.T) { _, err := qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - me, - { - Method: http.MethodGet, - Resource: "/api/2.0/permissions/clusters/abc", - Response: apierr.APIError{ - ErrorCode: "INVALID_REQUEST", - Message: "Internal error happened", - }, - Status: 400, - }, + MockWorkspaceClientFunc: func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockCurrentUserAPI().EXPECT().Me(mock.Anything).Return(&iam.User{UserName: "admin"}, nil) + mwc.GetMockPermissionsAPI().EXPECT().Get(mock.Anything, iam.GetPermissionRequest{ + RequestObjectId: "abc", + RequestObjectType: "clusters", + }).Return(nil, &apierr.APIError{ + StatusCode: 400, + ErrorCode: "INVALID_REQUEST", + Message: "Internal error happened", + }) }, Resource: ResourcePermissions(), Read: true, @@ -455,56 +424,17 @@ func TestResourcePermissionsCustomizeDiff_ErrorOnCreate(t *testing.T) { access_control { permission_level = "WHATEVER" }`, - }.ExpectError(t, "permission_level WHATEVER is not supported with cluster_id objects") -} - -func TestResourcePermissionsCustomizeDiff_ErrorOnPermissionsDecreate(t *testing.T) { - qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - me, - }, - Resource: ResourcePermissions(), - Create: true, - HCL: ` - cluster_id = "abc" - access_control { - permission_level = "CAN_ATTACH_TO" - user_name = "admin" - }`, - }.ExpectError(t, "it is not possible to decrease administrative permissions for the current user: admin") + }.ExpectError(t, "permission_level WHATEVER is not supported with cluster_id objects; allowed levels: CAN_ATTACH_TO, CAN_MANAGE, CAN_RESTART") } func TestResourcePermissionsRead_ErrorOnScimMe(t *testing.T) { - qa.HTTPFixturesApply(t, []qa.HTTPFixture{ - { - Method: http.MethodGet, - Resource: "/api/2.0/permissions/clusters/abc", - Response: ObjectACL{ - ObjectID: "/clusters/abc", - ObjectType: "clusters", - AccessControlList: []AccessControl{ - { - UserName: TestingUser, - AllPermissions: []Permission{ - { - PermissionLevel: "CAN_READ", - Inherited: false, - }, - }, - }, - }, - }, - }, - { - Method: http.MethodGet, - Resource: "/api/2.0/preview/scim/v2/Me", - Response: apierr.APIError{ - ErrorCode: "INVALID_REQUEST", - Message: "Internal error happened", - }, - Status: 400, - }, - }, func(ctx context.Context, client *common.DatabricksClient) { + mock := func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockCurrentUserAPI().EXPECT().Me(mock.Anything).Return(nil, &apierr.APIError{ + ErrorCode: "INVALID_REQUEST", + Message: "Internal error happened", + }) + } + qa.MockWorkspaceApply(t, mock, func(ctx context.Context, client *common.DatabricksClient) { r := ResourcePermissions().ToResource() d := r.TestResourceData() d.SetId("/clusters/abc") @@ -516,35 +446,33 @@ func TestResourcePermissionsRead_ErrorOnScimMe(t *testing.T) { func TestResourcePermissionsRead_ToPermissionsEntity_Error(t *testing.T) { qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - me, - { - Method: http.MethodGet, - Resource: "/api/2.0/permissions/clusters/abc", - Response: ObjectACL{ - ObjectType: "teapot", - }, - }, + MockWorkspaceClientFunc: func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockCurrentUserAPI().EXPECT().Me(mock.Anything).Return(&iam.User{UserName: "admin"}, nil) + mwc.GetMockPermissionsAPI().EXPECT().Get(mock.Anything, iam.GetPermissionRequest{ + RequestObjectId: "abc", + RequestObjectType: "clusters", + }).Return(&iam.ObjectPermissions{ + ObjectType: "teapot", + }, nil) }, Resource: ResourcePermissions(), Read: true, New: true, ID: "/clusters/abc", - }.ExpectError(t, "unknown object type teapot") + }.ExpectError(t, "expected object type cluster, got teapot") } func TestResourcePermissionsRead_EmptyListResultsInRemoval(t *testing.T) { qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - me, - { - Method: http.MethodGet, - Resource: "/api/2.0/permissions/clusters/abc", - Response: ObjectACL{ - ObjectID: "/clusters/abc", - ObjectType: "cluster", - }, - }, + MockWorkspaceClientFunc: func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockCurrentUserAPI().EXPECT().Me(mock.Anything).Return(&iam.User{UserName: "admin"}, nil) + mwc.GetMockPermissionsAPI().EXPECT().Get(mock.Anything, iam.GetPermissionRequest{ + RequestObjectId: "abc", + RequestObjectType: "clusters", + }).Return(&iam.ObjectPermissions{ + ObjectId: "/clusters/abc", + ObjectType: "cluster", + }, nil) }, Resource: ResourcePermissions(), Read: true, @@ -558,48 +486,46 @@ func TestResourcePermissionsRead_EmptyListResultsInRemoval(t *testing.T) { func TestResourcePermissionsDelete(t *testing.T) { d, err := qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - me, - { - Method: http.MethodGet, - Resource: "/api/2.0/permissions/clusters/abc", - Response: ObjectACL{ - ObjectID: "/clusters/abc", - ObjectType: "clusters", - AccessControlList: []AccessControl{ - { - UserName: TestingUser, - AllPermissions: []Permission{ - { - PermissionLevel: "CAN_READ", - Inherited: false, - }, + MockWorkspaceClientFunc: func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockCurrentUserAPI().EXPECT().Me(mock.Anything).Return(&iam.User{UserName: "admin"}, nil) + e := mwc.GetMockPermissionsAPI().EXPECT() + e.Get(mock.Anything, iam.GetPermissionRequest{ + RequestObjectId: "abc", + RequestObjectType: "clusters", + }).Return(&iam.ObjectPermissions{ + ObjectId: "/clusters/abc", + ObjectType: "cluster", + AccessControlList: []iam.AccessControlResponse{ + { + UserName: TestingUser, + AllPermissions: []iam.Permission{ + { + PermissionLevel: "CAN_READ", + Inherited: false, }, }, - { - UserName: TestingAdminUser, - AllPermissions: []Permission{ - { - PermissionLevel: "CAN_MANAGE", - Inherited: false, - }, + }, + { + UserName: TestingAdminUser, + AllPermissions: []iam.Permission{ + { + PermissionLevel: "CAN_MANAGE", + Inherited: false, }, }, }, }, - }, - { - Method: http.MethodPut, - Resource: "/api/2.0/permissions/clusters/abc", - ExpectedRequest: AccessControlChangeList{ - AccessControlList: []AccessControlChange{ - { - UserName: TestingAdminUser, - PermissionLevel: "CAN_MANAGE", - }, + }, nil) + e.Set(mock.Anything, iam.PermissionsRequest{ + RequestObjectId: "abc", + RequestObjectType: "clusters", + AccessControlList: []iam.AccessControlRequest{ + { + UserName: TestingAdminUser, + PermissionLevel: "CAN_MANAGE", }, }, - }, + }).Return(nil, nil) }, Resource: ResourcePermissions(), Delete: true, @@ -611,53 +537,50 @@ func TestResourcePermissionsDelete(t *testing.T) { func TestResourcePermissionsDelete_error(t *testing.T) { _, err := qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - me, - { - Method: http.MethodGet, - Resource: "/api/2.0/permissions/clusters/abc", - Response: ObjectACL{ - ObjectID: "/clusters/abc", - ObjectType: "clusters", - AccessControlList: []AccessControl{ - { - UserName: TestingUser, - AllPermissions: []Permission{ - { - PermissionLevel: "CAN_READ", - Inherited: false, - }, + MockWorkspaceClientFunc: func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockCurrentUserAPI().EXPECT().Me(mock.Anything).Return(&iam.User{UserName: "admin"}, nil) + e := mwc.GetMockPermissionsAPI().EXPECT() + e.Get(mock.Anything, iam.GetPermissionRequest{ + RequestObjectId: "abc", + RequestObjectType: "clusters", + }).Return(&iam.ObjectPermissions{ + ObjectId: "/clusters/abc", + ObjectType: "cluster", + AccessControlList: []iam.AccessControlResponse{ + { + UserName: TestingUser, + AllPermissions: []iam.Permission{ + { + PermissionLevel: "CAN_READ", + Inherited: false, }, }, - { - UserName: TestingAdminUser, - AllPermissions: []Permission{ - { - PermissionLevel: "CAN_MANAGE", - Inherited: false, - }, + }, + { + UserName: TestingAdminUser, + AllPermissions: []iam.Permission{ + { + PermissionLevel: "CAN_MANAGE", + Inherited: false, }, }, }, }, - }, - { - Method: http.MethodPut, - Resource: "/api/2.0/permissions/clusters/abc", - ExpectedRequest: AccessControlChangeList{ - AccessControlList: []AccessControlChange{ - { - UserName: TestingAdminUser, - PermissionLevel: "CAN_MANAGE", - }, + }, nil) + e.Set(mock.Anything, iam.PermissionsRequest{ + RequestObjectId: "abc", + RequestObjectType: "clusters", + AccessControlList: []iam.AccessControlRequest{ + { + UserName: TestingAdminUser, + PermissionLevel: "CAN_MANAGE", }, }, - Response: apierr.APIError{ - ErrorCode: "INVALID_REQUEST", - Message: "Internal error happened", - }, - Status: 400, - }, + }).Return(nil, &apierr.APIError{ + ErrorCode: "INVALID_REQUEST", + Message: "Internal error happened", + StatusCode: 400, + }) }, Resource: ResourcePermissions(), Delete: true, @@ -668,15 +591,13 @@ func TestResourcePermissionsDelete_error(t *testing.T) { func TestResourcePermissionsCreate_invalid(t *testing.T) { qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{me}, Resource: ResourcePermissions(), Create: true, - }.ExpectError(t, "at least one type of resource identifiers must be set") + }.ExpectError(t, "at least one type of resource identifier must be set; allowed fields: authorization, cluster_id, cluster_policy_id, dashboard_id, directory_id, directory_path, experiment_id, instance_pool_id, job_id, notebook_id, notebook_path, pipeline_id, registered_model_id, repo_id, repo_path, serving_endpoint_id, sql_alert_id, sql_dashboard_id, sql_endpoint_id, sql_query_id, workspace_file_id, workspace_file_path") } func TestResourcePermissionsCreate_no_access_control(t *testing.T) { qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{}, Resource: ResourcePermissions(), Create: true, State: map[string]any{ @@ -687,7 +608,6 @@ func TestResourcePermissionsCreate_no_access_control(t *testing.T) { func TestResourcePermissionsCreate_conflicting_fields(t *testing.T) { qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{}, Resource: ResourcePermissions(), Create: true, State: map[string]any{ @@ -705,7 +625,9 @@ func TestResourcePermissionsCreate_conflicting_fields(t *testing.T) { func TestResourcePermissionsCreate_AdminsThrowError(t *testing.T) { _, err := qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{me}, + MockWorkspaceClientFunc: func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockCurrentUserAPI().EXPECT().Me(mock.Anything).Return(&iam.User{UserName: "admin"}, nil) + }, Resource: ResourcePermissions(), Create: true, HCL: ` @@ -716,57 +638,55 @@ func TestResourcePermissionsCreate_AdminsThrowError(t *testing.T) { } `, }.Apply(t) - assert.EqualError(t, err, "it is not possible to restrict any permissions from `admins`") + assert.EqualError(t, err, "it is not possible to modify admin permissions for cluster resources") } func TestResourcePermissionsCreate(t *testing.T) { d, err := qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - me, - { - Method: http.MethodPut, - Resource: "/api/2.0/permissions/clusters/abc", - ExpectedRequest: AccessControlChangeList{ - AccessControlList: []AccessControlChange{ - { - UserName: TestingUser, - PermissionLevel: "CAN_ATTACH_TO", - }, - { - UserName: TestingAdminUser, - PermissionLevel: "CAN_MANAGE", - }, - }, - }, - }, - { - Method: http.MethodGet, - Resource: "/api/2.0/permissions/clusters/abc", - Response: ObjectACL{ - ObjectID: "/clusters/abc", - ObjectType: "cluster", - AccessControlList: []AccessControl{ - { - UserName: TestingUser, - AllPermissions: []Permission{ - { - PermissionLevel: "CAN_ATTACH_TO", - Inherited: false, - }, + MockWorkspaceClientFunc: func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockCurrentUserAPI().EXPECT().Me(mock.Anything).Return(&iam.User{UserName: "admin"}, nil) + e := mwc.GetMockPermissionsAPI().EXPECT() + e.Get(mock.Anything, iam.GetPermissionRequest{ + RequestObjectId: "abc", + RequestObjectType: "clusters", + }).Return(&iam.ObjectPermissions{ + ObjectId: "/clusters/abc", + ObjectType: "cluster", + AccessControlList: []iam.AccessControlResponse{ + { + UserName: TestingUser, + AllPermissions: []iam.Permission{ + { + PermissionLevel: "CAN_ATTACH_TO", + Inherited: false, }, }, - { - UserName: TestingAdminUser, - AllPermissions: []Permission{ - { - PermissionLevel: "CAN_MANAGE", - Inherited: false, - }, + }, + { + UserName: TestingAdminUser, + AllPermissions: []iam.Permission{ + { + PermissionLevel: "CAN_MANAGE", + Inherited: false, }, }, }, }, - }, + }, nil) + e.Set(mock.Anything, iam.PermissionsRequest{ + RequestObjectId: "abc", + RequestObjectType: "clusters", + AccessControlList: []iam.AccessControlRequest{ + { + UserName: TestingUser, + PermissionLevel: "CAN_ATTACH_TO", + }, + { + UserName: TestingAdminUser, + PermissionLevel: "CAN_MANAGE", + }, + }, + }).Return(nil, nil) }, Resource: ResourcePermissions(), State: map[string]any{ @@ -790,42 +710,50 @@ func TestResourcePermissionsCreate(t *testing.T) { func TestResourcePermissionsCreate_SQLA_Asset(t *testing.T) { d, err := qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - me, - { - Method: http.MethodPost, - Resource: "/api/2.0/preview/sql/permissions/dashboards/abc", - ExpectedRequest: AccessControlChangeList{ - AccessControlList: []AccessControlChange{ - { - UserName: TestingUser, - PermissionLevel: "CAN_RUN", + MockWorkspaceClientFunc: func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockCurrentUserAPI().EXPECT().Me(mock.Anything).Return(&iam.User{UserName: "admin"}, nil) + e := mwc.GetMockPermissionsAPI().EXPECT() + e.Get(mock.Anything, iam.GetPermissionRequest{ + RequestObjectId: "abc", + RequestObjectType: "dbsql-dashboards", + }).Return(&iam.ObjectPermissions{ + ObjectId: "/dashboards/abc", + ObjectType: "dashboard", + AccessControlList: []iam.AccessControlResponse{ + { + UserName: TestingUser, + AllPermissions: []iam.Permission{ + { + PermissionLevel: "CAN_RUN", + Inherited: false, + }, }, - { - UserName: TestingAdminUser, - PermissionLevel: "CAN_MANAGE", + }, + { + UserName: TestingAdminUser, + AllPermissions: []iam.Permission{ + { + PermissionLevel: "CAN_MANAGE", + Inherited: false, + }, }, }, }, - }, - { - Method: http.MethodGet, - Resource: "/api/2.0/preview/sql/permissions/dashboards/abc", - Response: ObjectACL{ - ObjectID: "dashboards/abc", - ObjectType: "dashboard", - AccessControlList: []AccessControl{ - { - UserName: TestingUser, - PermissionLevel: "CAN_RUN", - }, - { - UserName: TestingAdminUser, - PermissionLevel: "CAN_MANAGE", - }, + }, nil) + e.Set(mock.Anything, iam.PermissionsRequest{ + RequestObjectId: "abc", + RequestObjectType: "dbsql-dashboards", + AccessControlList: []iam.AccessControlRequest{ + { + UserName: TestingUser, + PermissionLevel: "CAN_RUN", + }, + { + UserName: TestingAdminUser, + PermissionLevel: "CAN_MANAGE", }, }, - }, + }).Return(nil, nil) }, Resource: ResourcePermissions(), State: map[string]any{ @@ -849,50 +777,48 @@ func TestResourcePermissionsCreate_SQLA_Asset(t *testing.T) { func TestResourcePermissionsCreate_SQLA_Endpoint(t *testing.T) { d, err := qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - me, - { - Method: "PUT", - Resource: "/api/2.0/permissions/sql/warehouses/abc", - ExpectedRequest: AccessControlChangeList{ - AccessControlList: []AccessControlChange{ - { - UserName: TestingUser, - PermissionLevel: "CAN_USE", - }, - { - UserName: TestingAdminUser, - PermissionLevel: "IS_OWNER", - }, - { - UserName: TestingAdminUser, - PermissionLevel: "CAN_MANAGE", - }, + MockWorkspaceClientFunc: func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockCurrentUserAPI().EXPECT().Me(mock.Anything).Return(&iam.User{UserName: "admin"}, nil) + e := mwc.GetMockPermissionsAPI().EXPECT() + e.Set(mock.Anything, iam.PermissionsRequest{ + RequestObjectId: "abc", + RequestObjectType: "sql/warehouses", + AccessControlList: []iam.AccessControlRequest{ + { + UserName: TestingUser, + PermissionLevel: "CAN_USE", + }, + { + UserName: TestingAdminUser, + PermissionLevel: "CAN_MANAGE", + }, + { + UserName: TestingAdminUser, + PermissionLevel: "IS_OWNER", }, }, - }, - { - Method: http.MethodGet, - Resource: "/api/2.0/permissions/sql/warehouses/abc", - Response: ObjectACL{ - ObjectID: "dashboards/abc", - ObjectType: "dashboard", - AccessControlList: []AccessControl{ - { - UserName: TestingUser, - PermissionLevel: "CAN_USE", - }, - { - UserName: TestingAdminUser, - PermissionLevel: "IS_OWNER", - }, - { - UserName: TestingAdminUser, - PermissionLevel: "CAN_MANAGE", - }, + }).Return(nil, nil) + e.Get(mock.Anything, iam.GetPermissionRequest{ + RequestObjectId: "abc", + RequestObjectType: "sql/warehouses", + }).Return(&iam.ObjectPermissions{ + ObjectId: "warehouses/abc", + ObjectType: "warehouses", + AccessControlList: []iam.AccessControlResponse{ + { + UserName: TestingUser, + AllPermissions: []iam.Permission{{PermissionLevel: iam.PermissionLevelCanUse}}, + }, + { + UserName: TestingAdminUser, + AllPermissions: []iam.Permission{{PermissionLevel: iam.PermissionLevelCanManage}}, + }, + { + UserName: TestingAdminUser, + AllPermissions: []iam.Permission{{PermissionLevel: iam.PermissionLevelIsOwner}}, }, }, - }, + }, nil) }, Resource: ResourcePermissions(), State: map[string]any{ @@ -916,71 +842,66 @@ func TestResourcePermissionsCreate_SQLA_Endpoint(t *testing.T) { func TestResourcePermissionsCreate_SQLA_Endpoint_WithOwnerError(t *testing.T) { d, err := qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - me, - { - Method: "PUT", - Resource: "/api/2.0/permissions/sql/warehouses/abc", - ExpectedRequest: AccessControlChangeList{ - AccessControlList: []AccessControlChange{ - { - UserName: TestingUser, - PermissionLevel: "CAN_USE", - }, - { - UserName: TestingAdminUser, - PermissionLevel: "IS_OWNER", - }, - { - UserName: TestingAdminUser, - PermissionLevel: "CAN_MANAGE", - }, + MockWorkspaceClientFunc: func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockCurrentUserAPI().EXPECT().Me(mock.Anything).Return(&iam.User{UserName: "admin"}, nil) + e := mwc.GetMockPermissionsAPI().EXPECT() + e.Set(mock.Anything, iam.PermissionsRequest{ + RequestObjectId: "abc", + RequestObjectType: "sql/warehouses", + AccessControlList: []iam.AccessControlRequest{ + { + UserName: TestingUser, + PermissionLevel: "CAN_USE", + }, + { + UserName: TestingAdminUser, + PermissionLevel: "CAN_MANAGE", + }, + { + UserName: TestingAdminUser, + PermissionLevel: "IS_OWNER", }, }, - Response: apierr.APIError{ - ErrorCode: "INVALID_PARAMETER_VALUE", - Message: "PUT requests for warehouse *** with no existing owner must provide a new owner.", - }, - Status: 400, - }, - { - Method: "PUT", - Resource: "/api/2.0/permissions/sql/warehouses/abc", - ExpectedRequest: AccessControlChangeList{ - AccessControlList: []AccessControlChange{ - { - UserName: TestingUser, - PermissionLevel: "CAN_USE", - }, - { - UserName: TestingAdminUser, - PermissionLevel: "CAN_MANAGE", - }, + }).Return(nil, &apierr.APIError{ + ErrorCode: "INVALID_PARAMETER_VALUE", + Message: "PUT requests for warehouse *** with no existing owner must provide a new owner.", + StatusCode: 400, + }) + e.Set(mock.Anything, iam.PermissionsRequest{ + RequestObjectId: "abc", + RequestObjectType: "sql/warehouses", + AccessControlList: []iam.AccessControlRequest{ + { + UserName: TestingUser, + PermissionLevel: "CAN_USE", + }, + { + UserName: TestingAdminUser, + PermissionLevel: "CAN_MANAGE", }, }, - }, - { - Method: http.MethodGet, - Resource: "/api/2.0/permissions/sql/warehouses/abc", - Response: ObjectACL{ - ObjectID: "dashboards/abc", - ObjectType: "dashboard", - AccessControlList: []AccessControl{ - { - UserName: TestingUser, - PermissionLevel: "CAN_USE", - }, - { - UserName: TestingAdminUser, - PermissionLevel: "IS_OWNER", - }, - { - UserName: TestingAdminUser, - PermissionLevel: "CAN_MANAGE", - }, + }).Return(nil, nil) + e.Get(mock.Anything, iam.GetPermissionRequest{ + RequestObjectId: "abc", + RequestObjectType: "sql/warehouses", + }).Return(&iam.ObjectPermissions{ + ObjectId: "warehouses/abc", + ObjectType: "warehouses", + AccessControlList: []iam.AccessControlResponse{ + { + UserName: TestingUser, + AllPermissions: []iam.Permission{{PermissionLevel: iam.PermissionLevelCanUse}}, + }, + { + UserName: TestingAdminUser, + AllPermissions: []iam.Permission{{PermissionLevel: iam.PermissionLevelCanManage}}, + }, + { + UserName: TestingAdminUser, + AllPermissions: []iam.Permission{{PermissionLevel: iam.PermissionLevelIsOwner}}, }, }, - }, + }, nil) }, Resource: ResourcePermissions(), State: map[string]any{ @@ -1004,50 +925,48 @@ func TestResourcePermissionsCreate_SQLA_Endpoint_WithOwnerError(t *testing.T) { func TestResourcePermissionsCreate_SQLA_Endpoint_WithOwner(t *testing.T) { d, err := qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - me, - { - Method: "PUT", - Resource: "/api/2.0/permissions/sql/warehouses/abc", - ExpectedRequest: AccessControlChangeList{ - AccessControlList: []AccessControlChange{ - { - UserName: TestingOwner, - PermissionLevel: "IS_OWNER", - }, - { - UserName: TestingUser, - PermissionLevel: "CAN_USE", - }, - { - UserName: TestingAdminUser, - PermissionLevel: "CAN_MANAGE", - }, + MockWorkspaceClientFunc: func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockCurrentUserAPI().EXPECT().Me(mock.Anything).Return(&iam.User{UserName: "admin"}, nil) + e := mwc.GetMockPermissionsAPI().EXPECT() + e.Set(mock.Anything, iam.PermissionsRequest{ + RequestObjectId: "abc", + RequestObjectType: "sql/warehouses", + AccessControlList: []iam.AccessControlRequest{ + { + UserName: TestingOwner, + PermissionLevel: "IS_OWNER", + }, + { + UserName: TestingUser, + PermissionLevel: "CAN_USE", + }, + { + UserName: TestingAdminUser, + PermissionLevel: "CAN_MANAGE", }, }, - }, - { - Method: http.MethodGet, - Resource: "/api/2.0/permissions/sql/warehouses/abc", - Response: ObjectACL{ - ObjectID: "dashboards/abc", - ObjectType: "dashboard", - AccessControlList: []AccessControl{ - { - UserName: TestingUser, - PermissionLevel: "CAN_USE", - }, - { - UserName: TestingAdminUser, - PermissionLevel: "CAN_MANAGE", - }, - { - UserName: TestingOwner, - PermissionLevel: "IS_OWNER", - }, + }).Return(nil, nil) + e.Get(mock.Anything, iam.GetPermissionRequest{ + RequestObjectId: "abc", + RequestObjectType: "sql/warehouses", + }).Return(&iam.ObjectPermissions{ + ObjectId: "warehouses/abc", + ObjectType: "warehouses", + AccessControlList: []iam.AccessControlResponse{ + { + UserName: TestingUser, + AllPermissions: []iam.Permission{{PermissionLevel: iam.PermissionLevelCanUse}}, + }, + { + UserName: TestingAdminUser, + AllPermissions: []iam.Permission{{PermissionLevel: iam.PermissionLevelCanManage}}, + }, + { + UserName: TestingOwner, + AllPermissions: []iam.Permission{{PermissionLevel: iam.PermissionLevelIsOwner}}, }, }, - }, + }, nil) }, Resource: ResourcePermissions(), State: map[string]any{ @@ -1094,17 +1013,12 @@ func TestResourcePermissionsCreate_SQLA_Endpoint_WithOwner(t *testing.T) { func TestResourcePermissionsCreate_NotebookPath_NotExists(t *testing.T) { _, err := qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - me, - { - Method: http.MethodGet, - Resource: "/api/2.0/workspace/get-status?path=%2FDevelopment%2FInit", - Response: apierr.APIError{ - ErrorCode: "INVALID_REQUEST", - Message: "Internal error happened", - }, - Status: 400, - }, + MockWorkspaceClientFunc: func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockWorkspaceAPI().EXPECT().GetStatusByPath(mock.Anything, "/Development/Init").Return(nil, &apierr.APIError{ + ErrorCode: "INVALID_REQUEST", + Message: "Internal error happened", + StatusCode: 400, + }) }, Resource: ResourcePermissions(), State: map[string]any{ @@ -1112,7 +1026,7 @@ func TestResourcePermissionsCreate_NotebookPath_NotExists(t *testing.T) { "access_control": []any{ map[string]any{ "user_name": TestingUser, - "permission_level": "CAN_USE", + "permission_level": "CAN_READ", }, }, }, @@ -1124,56 +1038,50 @@ func TestResourcePermissionsCreate_NotebookPath_NotExists(t *testing.T) { func TestResourcePermissionsCreate_NotebookPath(t *testing.T) { d, err := qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - me, - { - Method: http.MethodGet, - Resource: "/api/2.0/workspace/get-status?path=%2FDevelopment%2FInit", - Response: workspace.ObjectStatus{ - ObjectID: 988765, - ObjectType: "NOTEBOOK", - }, - }, - { - Method: http.MethodPut, - Resource: "/api/2.0/permissions/notebooks/988765", - ExpectedRequest: AccessControlChangeList{ - AccessControlList: []AccessControlChange{ - { - UserName: TestingUser, - PermissionLevel: "CAN_READ", - }, + MockWorkspaceClientFunc: func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockCurrentUserAPI().EXPECT().Me(mock.Anything).Return(&iam.User{UserName: "admin"}, nil) + mwc.GetMockWorkspaceAPI().EXPECT().GetStatusByPath(mock.Anything, "/Development/Init").Return(&workspace.ObjectInfo{ + ObjectId: 988765, + ObjectType: workspace.ObjectTypeNotebook, + }, nil) + e := mwc.GetMockPermissionsAPI().EXPECT() + e.Set(mock.Anything, iam.PermissionsRequest{ + RequestObjectId: "988765", + RequestObjectType: "notebooks", + AccessControlList: []iam.AccessControlRequest{ + { + UserName: TestingUser, + PermissionLevel: "CAN_READ", }, }, - }, - { - Method: http.MethodGet, - Resource: "/api/2.0/permissions/notebooks/988765", - Response: ObjectACL{ - ObjectID: "/notebooks/988765", - ObjectType: "notebook", - AccessControlList: []AccessControl{ - { - UserName: TestingUser, - AllPermissions: []Permission{ - { - PermissionLevel: "CAN_READ", - Inherited: false, - }, + }).Return(nil, nil) + e.Get(mock.Anything, iam.GetPermissionRequest{ + RequestObjectId: "988765", + RequestObjectType: "notebooks", + }).Return(&iam.ObjectPermissions{ + ObjectId: "/notebooks/988765", + ObjectType: "notebook", + AccessControlList: []iam.AccessControlResponse{ + { + UserName: TestingUser, + AllPermissions: []iam.Permission{ + { + PermissionLevel: "CAN_READ", + Inherited: false, }, }, - { - UserName: TestingAdminUser, - AllPermissions: []Permission{ - { - PermissionLevel: "CAN_MANAGE", - Inherited: false, - }, + }, + { + UserName: TestingAdminUser, + AllPermissions: []iam.Permission{ + { + PermissionLevel: "CAN_MANAGE", + Inherited: false, }, }, }, }, - }, + }, nil) }, Resource: ResourcePermissions(), State: map[string]any{ @@ -1198,56 +1106,50 @@ func TestResourcePermissionsCreate_NotebookPath(t *testing.T) { func TestResourcePermissionsCreate_WorkspaceFilePath(t *testing.T) { d, err := qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - me, - { - Method: http.MethodGet, - Resource: "/api/2.0/workspace/get-status?path=%2FDevelopment%2FInit", - Response: workspace.ObjectStatus{ - ObjectID: 988765, - ObjectType: workspace.File, - }, - }, - { - Method: http.MethodPut, - Resource: "/api/2.0/permissions/files/988765", - ExpectedRequest: AccessControlChangeList{ - AccessControlList: []AccessControlChange{ - { - UserName: TestingUser, - PermissionLevel: "CAN_READ", - }, + MockWorkspaceClientFunc: func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockCurrentUserAPI().EXPECT().Me(mock.Anything).Return(&iam.User{UserName: "admin"}, nil) + mwc.GetMockWorkspaceAPI().EXPECT().GetStatusByPath(mock.Anything, "/Development/Init").Return(&workspace.ObjectInfo{ + ObjectId: 988765, + ObjectType: workspace.ObjectTypeFile, + }, nil) + e := mwc.GetMockPermissionsAPI().EXPECT() + e.Set(mock.Anything, iam.PermissionsRequest{ + RequestObjectId: "988765", + RequestObjectType: "files", + AccessControlList: []iam.AccessControlRequest{ + { + UserName: TestingUser, + PermissionLevel: "CAN_READ", }, }, - }, - { - Method: http.MethodGet, - Resource: "/api/2.0/permissions/files/988765", - Response: ObjectACL{ - ObjectID: "/files/988765", - ObjectType: "file", - AccessControlList: []AccessControl{ - { - UserName: TestingUser, - AllPermissions: []Permission{ - { - PermissionLevel: "CAN_READ", - Inherited: false, - }, + }).Return(nil, nil) + e.Get(mock.Anything, iam.GetPermissionRequest{ + RequestObjectId: "988765", + RequestObjectType: "files", + }).Return(&iam.ObjectPermissions{ + ObjectId: "/files/988765", + ObjectType: "file", + AccessControlList: []iam.AccessControlResponse{ + { + UserName: TestingUser, + AllPermissions: []iam.Permission{ + { + PermissionLevel: "CAN_READ", + Inherited: false, }, }, - { - UserName: TestingAdminUser, - AllPermissions: []Permission{ - { - PermissionLevel: "CAN_MANAGE", - Inherited: false, - }, + }, + { + UserName: TestingAdminUser, + AllPermissions: []iam.Permission{ + { + PermissionLevel: "CAN_MANAGE", + Inherited: false, }, }, }, }, - }, + }, nil) }, Resource: ResourcePermissions(), State: map[string]any{ @@ -1272,18 +1174,6 @@ func TestResourcePermissionsCreate_WorkspaceFilePath(t *testing.T) { func TestResourcePermissionsCreate_error(t *testing.T) { qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - me, - { - Method: http.MethodPut, - Resource: "/api/2.0/permissions/clusters/abc", - Response: apierr.APIError{ - ErrorCode: "INVALID_REQUEST", - Message: "Internal error happened", - }, - Status: 400, - }, - }, Resource: ResourcePermissions(), State: map[string]any{ "cluster_id": "abc", @@ -1295,14 +1185,17 @@ func TestResourcePermissionsCreate_error(t *testing.T) { }, }, Create: true, - }.ExpectError(t, "permission_level CAN_USE is not supported with cluster_id objects") + }.ExpectError(t, "permission_level CAN_USE is not supported with cluster_id objects; allowed levels: CAN_ATTACH_TO, CAN_MANAGE, CAN_RESTART") } func TestResourcePermissionsCreate_PathIdRetriever_Error(t *testing.T) { qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - me, - qa.HTTPFailures[0], + MockWorkspaceClientFunc: func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockWorkspaceAPI().EXPECT().GetStatusByPath(mock.Anything, "/foo/bar").Return(nil, &apierr.APIError{ + ErrorCode: "INVALID_REQUEST", + Message: "i'm a teapot", + StatusCode: 418, + }) }, Resource: ResourcePermissions(), Create: true, @@ -1317,9 +1210,13 @@ func TestResourcePermissionsCreate_PathIdRetriever_Error(t *testing.T) { func TestResourcePermissionsCreate_ActualUpdate_Error(t *testing.T) { qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - me, - qa.HTTPFailures[0], + MockWorkspaceClientFunc: func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockCurrentUserAPI().EXPECT().Me(mock.Anything).Return(&iam.User{UserName: "admin"}, nil) + mwc.GetMockPermissionsAPI().EXPECT().Set(mock.Anything, mock.Anything).Return(nil, &apierr.APIError{ + ErrorCode: "INVALID_REQUEST", + Message: "i'm a teapot", + StatusCode: 418, + }) }, Resource: ResourcePermissions(), Create: true, @@ -1334,52 +1231,50 @@ func TestResourcePermissionsCreate_ActualUpdate_Error(t *testing.T) { func TestResourcePermissionsUpdate(t *testing.T) { d, err := qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - me, - { - Method: http.MethodGet, - Resource: "/api/2.0/permissions/jobs/9", - Response: ObjectACL{ - ObjectID: "/jobs/9", - ObjectType: "job", - AccessControlList: []AccessControl{ - { - UserName: TestingUser, - AllPermissions: []Permission{ - { - PermissionLevel: "CAN_VIEW", - Inherited: false, - }, + MockWorkspaceClientFunc: func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockCurrentUserAPI().EXPECT().Me(mock.Anything).Return(&iam.User{UserName: "admin"}, nil) + e := mwc.GetMockPermissionsAPI().EXPECT() + e.Get(mock.Anything, iam.GetPermissionRequest{ + RequestObjectId: "9", + RequestObjectType: "jobs", + }).Return(&iam.ObjectPermissions{ + ObjectId: "/jobs/9", + ObjectType: "job", + AccessControlList: []iam.AccessControlResponse{ + { + UserName: TestingUser, + AllPermissions: []iam.Permission{ + { + PermissionLevel: "CAN_VIEW", + Inherited: false, }, }, - { - UserName: TestingAdminUser, - AllPermissions: []Permission{ - { - PermissionLevel: "CAN_MANAGE", - Inherited: false, - }, + }, + { + UserName: TestingAdminUser, + AllPermissions: []iam.Permission{ + { + PermissionLevel: "CAN_MANAGE", + Inherited: false, }, }, }, }, - }, - { - Method: http.MethodPut, - Resource: "/api/2.0/permissions/jobs/9", - ExpectedRequest: AccessControlChangeList{ - AccessControlList: []AccessControlChange{ - { - UserName: TestingUser, - PermissionLevel: "CAN_VIEW", - }, - { - UserName: TestingAdminUser, - PermissionLevel: "IS_OWNER", - }, + }, nil) + e.Set(mock.Anything, iam.PermissionsRequest{ + RequestObjectId: "9", + RequestObjectType: "jobs", + AccessControlList: []iam.AccessControlRequest{ + { + UserName: TestingUser, + PermissionLevel: "CAN_VIEW", + }, + { + UserName: TestingAdminUser, + PermissionLevel: "IS_OWNER", }, }, - }, + }).Return(nil, nil) }, InstanceState: map[string]string{ "job_id": "9", @@ -1405,235 +1300,202 @@ func TestResourcePermissionsUpdate(t *testing.T) { assert.Equal(t, "CAN_VIEW", firstElem["permission_level"]) } +func getResourcePermissions(field, objectType string) resourcePermissions { + for _, mapping := range allResourcePermissions() { + if mapping.field == field && mapping.objectType == objectType { + return mapping + } + } + panic(fmt.Sprintf("could not find resource permissions for field %s and object type %s", field, objectType)) +} + func TestResourcePermissionsUpdateTokensAlwaysThereForAdmins(t *testing.T) { - qa.HTTPFixturesApply(t, []qa.HTTPFixture{ - { - Method: "PUT", - Resource: "/api/2.0/permissions/authorization/tokens", - ExpectedRequest: AccessControlChangeList{ - AccessControlList: []AccessControlChange{ - { - UserName: "me", - PermissionLevel: "CAN_MANAGE", - }, - { - GroupName: "admins", - PermissionLevel: "CAN_MANAGE", - }, + qa.MockWorkspaceApply(t, func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockCurrentUserAPI().EXPECT().Me(mock.Anything).Return(&iam.User{UserName: "me"}, nil) + mwc.GetMockPermissionsAPI().EXPECT().Set(mock.Anything, iam.PermissionsRequest{ + RequestObjectId: "tokens", + RequestObjectType: "authorization", + AccessControlList: []iam.AccessControlRequest{ + { + UserName: "me", + PermissionLevel: "CAN_MANAGE", + }, + { + GroupName: "admins", + PermissionLevel: "CAN_MANAGE", }, }, - }, + }).Return(nil, nil) }, func(ctx context.Context, client *common.DatabricksClient) { p := NewPermissionsAPI(ctx, client) - err := p.Update("/authorization/tokens", AccessControlChangeList{ - AccessControlList: []AccessControlChange{ + mapping := getResourcePermissions("authorization", "tokens") + err := p.Update("/authorization/tokens", entity.PermissionsEntity{ + AccessControlList: []iam.AccessControlRequest{ { UserName: "me", PermissionLevel: "CAN_MANAGE", }, }, - }) + }, mapping) assert.NoError(t, err) }) } func TestShouldKeepAdminsOnAnythingExceptPasswordsAndAssignsOwnerForJob(t *testing.T) { - qa.HTTPFixturesApply(t, []qa.HTTPFixture{ - { - Method: "GET", - Resource: "/api/2.0/permissions/jobs/123", - Response: ObjectACL{ - ObjectID: "/jobs/123", - ObjectType: "job", - AccessControlList: []AccessControl{ - { - GroupName: "admins", - AllPermissions: []Permission{ - { - PermissionLevel: "CAN_DO_EVERYTHING", - Inherited: true, - }, - { - PermissionLevel: "CAN_MANAGE", - Inherited: false, - }, + qa.MockWorkspaceApply(t, func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockJobsAPI().EXPECT().GetByJobId(mock.Anything, int64(123)).Return(&jobs.Job{ + CreatorUserName: "creator@example.com", + }, nil) + e := mwc.GetMockPermissionsAPI().EXPECT() + e.Get(mock.Anything, iam.GetPermissionRequest{ + RequestObjectId: "123", + RequestObjectType: "jobs", + }).Return(&iam.ObjectPermissions{ + ObjectId: "/jobs/123", + ObjectType: "job", + AccessControlList: []iam.AccessControlResponse{ + { + GroupName: "admins", + AllPermissions: []iam.Permission{ + { + PermissionLevel: "CAN_DO_EVERYTHING", + Inherited: true, + }, + { + PermissionLevel: "CAN_MANAGE", + Inherited: false, }, }, }, }, - }, - { - Method: "GET", - Resource: "/api/2.1/jobs/get?job_id=123", - Response: jobs.Job{ - CreatorUserName: "creator@example.com", - }, - }, - { - Method: "PUT", - Resource: "/api/2.0/permissions/jobs/123", - ExpectedRequest: ObjectACL{ - AccessControlList: []AccessControl{ - { - GroupName: "admins", - PermissionLevel: "CAN_MANAGE", - }, - { - UserName: "creator@example.com", - PermissionLevel: "IS_OWNER", - }, + }, nil) + e.Set(mock.Anything, iam.PermissionsRequest{ + RequestObjectId: "123", + RequestObjectType: "jobs", + AccessControlList: []iam.AccessControlRequest{ + { + GroupName: "admins", + PermissionLevel: "CAN_MANAGE", + }, + { + UserName: "creator@example.com", + PermissionLevel: "IS_OWNER", }, }, - }, + }).Return(nil, nil) }, func(ctx context.Context, client *common.DatabricksClient) { p := NewPermissionsAPI(ctx, client) - err := p.Delete("/jobs/123") + mapping := getResourcePermissions("job_id", "job") + err := p.Delete("/jobs/123", mapping) assert.NoError(t, err) }) } func TestShouldDeleteNonExistentJob(t *testing.T) { - qa.HTTPFixturesApply(t, []qa.HTTPFixture{ - { - Method: "GET", - Resource: "/api/2.0/permissions/jobs/123", - Response: ObjectACL{ - ObjectID: "/jobs/123", - ObjectType: "job", - AccessControlList: []AccessControl{ - { - GroupName: "admins", - AllPermissions: []Permission{ - { - PermissionLevel: "CAN_DO_EVERYTHING", - Inherited: true, - }, - { - PermissionLevel: "CAN_MANAGE", - Inherited: false, - }, + qa.MockWorkspaceApply(t, func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockPermissionsAPI().EXPECT().Get(mock.Anything, iam.GetPermissionRequest{ + RequestObjectId: "123", + RequestObjectType: "jobs", + }).Return(&iam.ObjectPermissions{ + ObjectId: "/jobs/123", + ObjectType: "job", + AccessControlList: []iam.AccessControlResponse{ + { + GroupName: "admins", + AllPermissions: []iam.Permission{ + { + PermissionLevel: "CAN_DO_EVERYTHING", + Inherited: true, + }, + { + PermissionLevel: "CAN_MANAGE", + Inherited: false, }, }, }, }, - }, - { - Method: "GET", - Resource: "/api/2.1/jobs/get?job_id=123", - Status: 400, - Response: apierr.APIError{ - StatusCode: 400, - Message: "Job 123 does not exist.", - ErrorCode: "INVALID_PARAMETER_VALUE", - }, - }, + }, nil) + mwc.GetMockJobsAPI().EXPECT().GetByJobId(mock.Anything, int64(123)).Return(nil, &apierr.APIError{ + StatusCode: 400, + Message: "Job 123 does not exist.", + ErrorCode: "INVALID_PARAMETER_VALUE", + }) }, func(ctx context.Context, client *common.DatabricksClient) { p := NewPermissionsAPI(ctx, client) - err := p.Delete("/jobs/123") + mapping := getResourcePermissions("job_id", "job") + err := p.Delete("/jobs/123", mapping) assert.NoError(t, err) }) } func TestShouldKeepAdminsOnAnythingExceptPasswordsAndAssignsOwnerForPipeline(t *testing.T) { - qa.HTTPFixturesApply(t, []qa.HTTPFixture{ - { - Method: "GET", - Resource: "/api/2.0/permissions/pipelines/123", - Response: ObjectACL{ - ObjectID: "/pipelines/123", - ObjectType: "pipeline", - AccessControlList: []AccessControl{ - { - GroupName: "admins", - AllPermissions: []Permission{ - { - PermissionLevel: "CAN_DO_EVERYTHING", - Inherited: true, - }, - { - PermissionLevel: "CAN_MANAGE", - Inherited: false, - }, + qa.MockWorkspaceApply(t, func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockPipelinesAPI().EXPECT().GetByPipelineId(mock.Anything, "123").Return(&pipelines.GetPipelineResponse{ + CreatorUserName: "creator@example.com", + }, nil) + e := mwc.GetMockPermissionsAPI().EXPECT() + e.Get(mock.Anything, iam.GetPermissionRequest{ + RequestObjectId: "123", + RequestObjectType: "pipelines", + }).Return(&iam.ObjectPermissions{ + ObjectId: "/pipelines/123", + ObjectType: "pipeline", + AccessControlList: []iam.AccessControlResponse{ + { + GroupName: "admins", + AllPermissions: []iam.Permission{ + { + PermissionLevel: "CAN_DO_EVERYTHING", + Inherited: true, + }, + { + PermissionLevel: "CAN_MANAGE", + Inherited: false, }, }, }, }, - }, - { - Method: "GET", - Resource: "/api/2.0/pipelines/123?", - Response: jobs.Job{ - CreatorUserName: "creator@example.com", - }, - }, - { - Method: "PUT", - Resource: "/api/2.0/permissions/pipelines/123", - ExpectedRequest: ObjectACL{ - AccessControlList: []AccessControl{ - { - GroupName: "admins", - PermissionLevel: "CAN_MANAGE", - }, - { - UserName: "creator@example.com", - PermissionLevel: "IS_OWNER", - }, + }, nil) + e.Set(mock.Anything, iam.PermissionsRequest{ + RequestObjectId: "123", + RequestObjectType: "pipelines", + AccessControlList: []iam.AccessControlRequest{ + { + GroupName: "admins", + PermissionLevel: "CAN_MANAGE", + }, + { + UserName: "creator@example.com", + PermissionLevel: "IS_OWNER", }, }, - }, + }).Return(nil, nil) }, func(ctx context.Context, client *common.DatabricksClient) { p := NewPermissionsAPI(ctx, client) - err := p.Delete("/pipelines/123") + mapping := getResourcePermissions("pipeline_id", "pipelines") + err := p.Delete("/pipelines/123", mapping) assert.NoError(t, err) }) } func TestPathPermissionsResourceIDFields(t *testing.T) { - var m permissionsIDFieldMapping - for _, x := range permissionsResourceIDFields() { - if x.field == "notebook_path" { - m = x - } - } + m := getResourcePermissions("notebook_path", "notebook") w, err := databricks.NewWorkspaceClient(&databricks.Config{}) require.NoError(t, err) _, err = m.idRetriever(context.Background(), w, "x") assert.ErrorContains(t, err, "cannot load path x") } -func TestObjectACLToPermissionsEntityCornerCases(t *testing.T) { - _, err := (&ObjectACL{ - ObjectType: "bananas", - AccessControlList: []AccessControl{ - { - GroupName: "admins", - }, - }, - }).ToPermissionsEntity(ResourcePermissions().ToResource().TestResourceData(), "me") - assert.EqualError(t, err, "unknown object type bananas") -} - -func TestEntityAccessControlToAccessControlChange(t *testing.T) { - _, res := AccessControl{}.toAccessControlChange() - assert.False(t, res) -} - -func TestCornerCases(t *testing.T) { - qa.ResourceCornerCases(t, ResourcePermissions(), qa.CornerCaseSkipCRUD("create")) -} - func TestDeleteMissing(t *testing.T) { - qa.HTTPFixturesApply(t, []qa.HTTPFixture{ - { - MatchAny: true, - Status: 404, - Response: apierr.NotFound("missing"), - }, + qa.MockWorkspaceApply(t, func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockPermissionsAPI().EXPECT().Get(mock.Anything, iam.GetPermissionRequest{ + RequestObjectId: "x", + RequestObjectType: "clusters", + }).Return(nil, apierr.ErrNotFound) }, func(ctx context.Context, client *common.DatabricksClient) { p := ResourcePermissions().ToResource() d := p.TestResourceData() - d.SetId("x") + d.SetId("/clusters/x") diags := p.DeleteContext(ctx, d, client) assert.Nil(t, diags) }) @@ -1641,65 +1503,59 @@ func TestDeleteMissing(t *testing.T) { func TestResourcePermissionsCreate_RepoPath(t *testing.T) { d, err := qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - me, - { - Method: http.MethodGet, - Resource: "/api/2.0/workspace/get-status?path=%2FRepos%2FDevelopment%2FInit", - Response: workspace.ObjectStatus{ - ObjectID: 988765, - ObjectType: "repo", - }, - }, - { - Method: http.MethodPut, - Resource: "/api/2.0/permissions/repos/988765", - ExpectedRequest: AccessControlChangeList{ - AccessControlList: []AccessControlChange{ - { - UserName: TestingUser, - PermissionLevel: "CAN_READ", - }, - }, - }, - }, - { - Method: http.MethodGet, - Resource: "/api/2.0/permissions/repos/988765", - Response: ObjectACL{ - ObjectID: "/repos/988765", - ObjectType: "repo", - AccessControlList: []AccessControl{ - { - UserName: TestingUser, - AllPermissions: []Permission{ - { - PermissionLevel: "CAN_READ", - Inherited: false, - }, + MockWorkspaceClientFunc: func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockCurrentUserAPI().EXPECT().Me(mock.Anything).Return(&iam.User{UserName: TestingAdminUser}, nil) + mwc.GetMockWorkspaceAPI().EXPECT().GetStatusByPath(mock.Anything, "/Repos/Development/Init").Return(&workspace.ObjectInfo{ + ObjectId: 988765, + ObjectType: workspace.ObjectTypeRepo, + }, nil) + e := mwc.GetMockPermissionsAPI().EXPECT() + e.Get(mock.Anything, iam.GetPermissionRequest{ + RequestObjectId: "988765", + RequestObjectType: "repos", + }).Return(&iam.ObjectPermissions{ + ObjectId: "/repos/988765", + ObjectType: "repo", + AccessControlList: []iam.AccessControlResponse{ + { + UserName: TestingUser, + AllPermissions: []iam.Permission{ + { + PermissionLevel: "CAN_READ", + Inherited: false, }, }, - { - UserName: TestingAdminUser, - AllPermissions: []Permission{ - { - PermissionLevel: "CAN_RUN", - Inherited: false, - }, + }, + { + UserName: TestingAdminUser, + AllPermissions: []iam.Permission{ + { + PermissionLevel: "CAN_RUN", + Inherited: false, }, }, - { - UserName: TestingAdminUser, - AllPermissions: []Permission{ - { - PermissionLevel: "CAN_MANAGE", - Inherited: false, - }, + }, + { + UserName: TestingAdminUser, + AllPermissions: []iam.Permission{ + { + PermissionLevel: "CAN_MANAGE", + Inherited: false, }, }, }, }, - }, + }, nil) + e.Set(mock.Anything, iam.PermissionsRequest{ + RequestObjectId: "988765", + RequestObjectType: "repos", + AccessControlList: []iam.AccessControlRequest{ + { + UserName: TestingUser, + PermissionLevel: "CAN_READ", + }, + }, + }).Return(nil, nil) }, Resource: ResourcePermissions(), State: map[string]any{ @@ -1725,42 +1581,40 @@ func TestResourcePermissionsCreate_RepoPath(t *testing.T) { // when caller does not specify CAN_MANAGE permission during create, it should be explictly added func TestResourcePermissionsCreate_Sql_Queries(t *testing.T) { d, err := qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - me, - { - Method: http.MethodPost, - Resource: "/api/2.0/preview/sql/permissions/queries/id111", - ExpectedRequest: AccessControlChangeList{ - AccessControlList: []AccessControlChange{ - { - UserName: TestingUser, - PermissionLevel: "CAN_RUN", - }, - { - UserName: TestingAdminUser, - PermissionLevel: "CAN_MANAGE", - }, + MockWorkspaceClientFunc: func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockCurrentUserAPI().EXPECT().Me(mock.Anything).Return(&iam.User{UserName: TestingAdminUser}, nil) + e := mwc.GetMockPermissionsAPI().EXPECT() + e.Set(mock.Anything, iam.PermissionsRequest{ + RequestObjectId: "id111", + RequestObjectType: "sql/queries", + AccessControlList: []iam.AccessControlRequest{ + { + UserName: TestingUser, + PermissionLevel: "CAN_RUN", + }, + { + UserName: TestingAdminUser, + PermissionLevel: "CAN_MANAGE", }, }, - }, - { - Method: http.MethodGet, - Resource: "/api/2.0/preview/sql/permissions/queries/id111", - Response: ObjectACL{ - ObjectID: "queries/id111", - ObjectType: "query", - AccessControlList: []AccessControl{ - { - UserName: TestingUser, - PermissionLevel: "CAN_RUN", - }, - { - UserName: TestingAdminUser, - PermissionLevel: "CAN_MANAGE", - }, + }).Return(nil, nil) + e.Get(mock.Anything, iam.GetPermissionRequest{ + RequestObjectId: "id111", + RequestObjectType: "sql/queries", + }).Return(&iam.ObjectPermissions{ + ObjectId: "queries/id111", + ObjectType: "query", + AccessControlList: []iam.AccessControlResponse{ + { + UserName: TestingUser, + AllPermissions: []iam.Permission{{PermissionLevel: iam.PermissionLevelCanRun}}, + }, + { + UserName: TestingAdminUser, + AllPermissions: []iam.Permission{{PermissionLevel: iam.PermissionLevelCanManage}}, }, }, - }, + }, nil) }, Resource: ResourcePermissions(), State: map[string]any{ @@ -1785,42 +1639,40 @@ func TestResourcePermissionsCreate_Sql_Queries(t *testing.T) { // when caller does not specify CAN_MANAGE permission during update, it should be explictly added func TestResourcePermissionsUpdate_Sql_Queries(t *testing.T) { d, err := qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - me, - { - Method: http.MethodPost, - Resource: "/api/2.0/preview/sql/permissions/queries/id111", - ExpectedRequest: AccessControlChangeList{ - AccessControlList: []AccessControlChange{ - { - UserName: TestingUser, - PermissionLevel: "CAN_RUN", - }, - { - UserName: TestingAdminUser, - PermissionLevel: "CAN_MANAGE", - }, + MockWorkspaceClientFunc: func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockCurrentUserAPI().EXPECT().Me(mock.Anything).Return(&iam.User{UserName: TestingAdminUser}, nil) + e := mwc.GetMockPermissionsAPI().EXPECT() + e.Set(mock.Anything, iam.PermissionsRequest{ + RequestObjectId: "id111", + RequestObjectType: "sql/queries", + AccessControlList: []iam.AccessControlRequest{ + { + UserName: TestingUser, + PermissionLevel: "CAN_RUN", + }, + { + UserName: TestingAdminUser, + PermissionLevel: "CAN_MANAGE", }, }, - }, - { - Method: http.MethodGet, - Resource: "/api/2.0/preview/sql/permissions/queries/id111", - Response: ObjectACL{ - ObjectID: "queries/id111", - ObjectType: "query", - AccessControlList: []AccessControl{ - { - UserName: TestingUser, - PermissionLevel: "CAN_RUN", - }, - { - UserName: TestingAdminUser, - PermissionLevel: "CAN_MANAGE", - }, + }).Return(nil, nil) + e.Get(mock.Anything, iam.GetPermissionRequest{ + RequestObjectId: "id111", + RequestObjectType: "sql/queries", + }).Return(&iam.ObjectPermissions{ + ObjectId: "queries/id111", + ObjectType: "query", + AccessControlList: []iam.AccessControlResponse{ + { + UserName: TestingUser, + AllPermissions: []iam.Permission{{PermissionLevel: iam.PermissionLevelCanRun}}, + }, + { + UserName: TestingAdminUser, + AllPermissions: []iam.Permission{{PermissionLevel: iam.PermissionLevelCanManage}}, }, }, - }, + }, nil) }, InstanceState: map[string]string{ "sql_query_id": "id111", @@ -1847,65 +1699,59 @@ func TestResourcePermissionsUpdate_Sql_Queries(t *testing.T) { func TestResourcePermissionsCreate_DirectoryPath(t *testing.T) { d, err := qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - me, - { - Method: http.MethodGet, - Resource: "/api/2.0/workspace/get-status?path=%2FFirst", - Response: workspace.ObjectStatus{ - ObjectID: 123456, - ObjectType: "directory", - }, - }, - { - Method: http.MethodPut, - Resource: "/api/2.0/permissions/directories/123456", - ExpectedRequest: AccessControlChangeList{ - AccessControlList: []AccessControlChange{ - { - UserName: TestingUser, - PermissionLevel: "CAN_READ", - }, + MockWorkspaceClientFunc: func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockCurrentUserAPI().EXPECT().Me(mock.Anything).Return(&iam.User{UserName: TestingAdminUser}, nil) + mwc.GetMockWorkspaceAPI().EXPECT().GetStatusByPath(mock.Anything, "/First").Return(&workspace.ObjectInfo{ + ObjectId: 123456, + ObjectType: workspace.ObjectTypeDirectory, + }, nil) + e := mwc.GetMockPermissionsAPI().EXPECT() + e.Set(mock.Anything, iam.PermissionsRequest{ + RequestObjectId: "123456", + RequestObjectType: "directories", + AccessControlList: []iam.AccessControlRequest{ + { + UserName: TestingUser, + PermissionLevel: "CAN_READ", }, }, - }, - { - Method: http.MethodGet, - Resource: "/api/2.0/permissions/directories/123456", - Response: ObjectACL{ - ObjectID: "/directories/123456", - ObjectType: "directory", - AccessControlList: []AccessControl{ - { - UserName: TestingUser, - AllPermissions: []Permission{ - { - PermissionLevel: "CAN_READ", - Inherited: false, - }, + }).Return(nil, nil) + e.Get(mock.Anything, iam.GetPermissionRequest{ + RequestObjectId: "123456", + RequestObjectType: "directories", + }).Return(&iam.ObjectPermissions{ + ObjectId: "/directories/123456", + ObjectType: "directory", + AccessControlList: []iam.AccessControlResponse{ + { + UserName: TestingUser, + AllPermissions: []iam.Permission{ + { + PermissionLevel: "CAN_READ", + Inherited: false, }, }, - { - UserName: TestingAdminUser, - AllPermissions: []Permission{ - { - PermissionLevel: "CAN_RUN", - Inherited: false, - }, + }, + { + UserName: TestingAdminUser, + AllPermissions: []iam.Permission{ + { + PermissionLevel: "CAN_RUN", + Inherited: false, }, }, - { - UserName: TestingAdminUser, - AllPermissions: []Permission{ - { - PermissionLevel: "CAN_MANAGE", - Inherited: false, - }, + }, + { + UserName: TestingAdminUser, + AllPermissions: []iam.Permission{ + { + PermissionLevel: "CAN_MANAGE", + Inherited: false, }, }, }, }, - }, + }, nil) }, Resource: ResourcePermissions(), State: map[string]any{ @@ -1930,34 +1776,32 @@ func TestResourcePermissionsCreate_DirectoryPath(t *testing.T) { func TestResourcePermissionsPasswordUsage(t *testing.T) { d, err := qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - me, - { - Method: http.MethodPut, - Resource: "/api/2.0/permissions/authorization/passwords", - ExpectedRequest: AccessControlChangeList{ - AccessControlList: []AccessControlChange{ - { - GroupName: "admins", - PermissionLevel: "CAN_USE", - }, + MockWorkspaceClientFunc: func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockCurrentUserAPI().EXPECT().Me(mock.Anything).Return(&iam.User{UserName: TestingAdminUser}, nil) + e := mwc.GetMockPermissionsAPI().EXPECT() + e.Get(mock.Anything, iam.GetPermissionRequest{ + RequestObjectId: "passwords", + RequestObjectType: "authorization", + }).Return(&iam.ObjectPermissions{ + ObjectId: "/authorization/passwords", + ObjectType: "passwords", + AccessControlList: []iam.AccessControlResponse{ + { + GroupName: "admins", + AllPermissions: []iam.Permission{{PermissionLevel: iam.PermissionLevelCanUse}}, }, }, - }, - { - Method: http.MethodGet, - Resource: "/api/2.0/permissions/authorization/passwords", - Response: ObjectACL{ - ObjectID: "/authorization/passwords", - ObjectType: "passwords", - AccessControlList: []AccessControl{ - { - GroupName: "admins", - PermissionLevel: "CAN_USE", - }, + }, nil) + e.Set(mock.Anything, iam.PermissionsRequest{ + RequestObjectId: "passwords", + RequestObjectType: "authorization", + AccessControlList: []iam.AccessControlRequest{ + { + GroupName: "admins", + PermissionLevel: "CAN_USE", }, }, - }, + }).Return(nil, nil) }, Resource: ResourcePermissions(), HCL: ` @@ -1979,42 +1823,40 @@ func TestResourcePermissionsPasswordUsage(t *testing.T) { func TestResourcePermissionsRootDirectory(t *testing.T) { d, err := qa.ResourceFixture{ - Fixtures: []qa.HTTPFixture{ - me, - { - Method: http.MethodPut, - Resource: "/api/2.0/permissions/directories/0", - ExpectedRequest: AccessControlChangeList{ - AccessControlList: []AccessControlChange{ - { - UserName: TestingUser, - PermissionLevel: "CAN_READ", - }, - { - GroupName: "admins", - PermissionLevel: "CAN_MANAGE", - }, + MockWorkspaceClientFunc: func(mwc *mocks.MockWorkspaceClient) { + mwc.GetMockCurrentUserAPI().EXPECT().Me(mock.Anything).Return(&iam.User{UserName: TestingAdminUser}, nil) + e := mwc.GetMockPermissionsAPI().EXPECT() + e.Get(mock.Anything, iam.GetPermissionRequest{ + RequestObjectId: "0", + RequestObjectType: "directories", + }).Return(&iam.ObjectPermissions{ + ObjectId: "/directories/0", + ObjectType: "directory", + AccessControlList: []iam.AccessControlResponse{ + { + UserName: TestingUser, + AllPermissions: []iam.Permission{{PermissionLevel: iam.PermissionLevelCanRead}}, + }, + { + GroupName: "admins", + AllPermissions: []iam.Permission{{PermissionLevel: iam.PermissionLevelCanManage}}, }, }, - }, - { - Method: http.MethodGet, - Resource: "/api/2.0/permissions/directories/0", - Response: ObjectACL{ - ObjectID: "/directories/0", - ObjectType: "directory", - AccessControlList: []AccessControl{ - { - UserName: TestingUser, - PermissionLevel: "CAN_READ", - }, - { - GroupName: "admins", - PermissionLevel: "CAN_MANAGE", - }, + }, nil) + e.Set(mock.Anything, iam.PermissionsRequest{ + RequestObjectId: "0", + RequestObjectType: "directories", + AccessControlList: []iam.AccessControlRequest{ + { + UserName: TestingUser, + PermissionLevel: "CAN_READ", + }, + { + GroupName: "admins", + PermissionLevel: "CAN_MANAGE", }, }, - }, + }).Return(nil, nil) }, Resource: ResourcePermissions(), HCL: ` diff --git a/permissions/update/customizers.go b/permissions/update/customizers.go new file mode 100644 index 0000000000..ea2c5dd5db --- /dev/null +++ b/permissions/update/customizers.go @@ -0,0 +1,97 @@ +package update + +import ( + "github.com/databricks/databricks-sdk-go/service/iam" +) + +// Context that is available to aclUpdateCustomizer implementations. +type ACLCustomizerContext struct { + GetCurrentUser func() (string, error) + GetId func() string +} + +// ACLCustomizer is a function that modifies the access control list of an object before it is updated. +type ACLCustomizer func(ctx ACLCustomizerContext, objectAcls []iam.AccessControlRequest) ([]iam.AccessControlRequest, error) + +// If applies ths customizer if the condition is true. +func If(condition func(ACLCustomizerContext, []iam.AccessControlRequest) bool, customizer ACLCustomizer) ACLCustomizer { + return func(ctx ACLCustomizerContext, acl []iam.AccessControlRequest) ([]iam.AccessControlRequest, error) { + if condition(ctx, acl) { + return customizer(ctx, acl) + } + return acl, nil + } +} + +func Not(condition func(ACLCustomizerContext, []iam.AccessControlRequest) bool) func(ACLCustomizerContext, []iam.AccessControlRequest) bool { + return func(ctx ACLCustomizerContext, acl []iam.AccessControlRequest) bool { + return !condition(ctx, acl) + } +} + +// ObjectIdMatches returns a condition that checks if the object ID matches the expected value. +func ObjectIdMatches(expected string) func(ACLCustomizerContext, []iam.AccessControlRequest) bool { + return func(ctx ACLCustomizerContext, acl []iam.AccessControlRequest) bool { + return ctx.GetId() == expected + } +} + +// AddAdmin adds an explicit CAN_MANAGE permission for the 'admins' group if explicitAdminPermissionCheck returns true +// for the provided object ID. +func AddAdmin(ctx ACLCustomizerContext, acl []iam.AccessControlRequest) ([]iam.AccessControlRequest, error) { + found := false + for _, acl := range acl { + if acl.GroupName == "admins" { + found = true + break + } + } + if !found { + // Prevent "Cannot change permissions for group 'admins' to None." + acl = append(acl, iam.AccessControlRequest{ + GroupName: "admins", + PermissionLevel: "CAN_MANAGE", + }) + } + return acl, nil +} + +// Whether the object requires explicit manage permissions for the calling user if not set. +// As described in https://github.com/databricks/terraform-provider-databricks/issues/1504, +// certain object types require that we explicitly grant the calling user CAN_MANAGE +// permissions when POSTing permissions changes through the REST API, to avoid accidentally +// revoking the calling user's ability to manage the current object. +func AddCurrentUserAsManage(ctx ACLCustomizerContext, acl []iam.AccessControlRequest) ([]iam.AccessControlRequest, error) { + currentUser, err := ctx.GetCurrentUser() + if err != nil { + return nil, err + } + // The validate() method called in Update() ensures that the current user's permissions are either CAN_MANAGE + // or IS_OWNER if they are specified. If the current user is not specified in the access control list, we add + // them with CAN_MANAGE permissions. + found := false + for _, acl := range acl { + if acl.UserName == currentUser || acl.ServicePrincipalName == currentUser { + found = true + break + } + } + if !found { + acl = append(acl, iam.AccessControlRequest{ + UserName: currentUser, + PermissionLevel: "CAN_MANAGE", + }) + } + return acl, nil +} + +func RewritePermissions(mapping map[iam.PermissionLevel]iam.PermissionLevel) ACLCustomizer { + return func(ctx ACLCustomizerContext, acl []iam.AccessControlRequest) ([]iam.AccessControlRequest, error) { + for i := range acl { + if new, ok := mapping[acl[i].PermissionLevel]; ok { + acl[i].PermissionLevel = new + } + } + return acl, nil + } +} From afdbafcb4d1530f021a8af94b94262ade87df239 Mon Sep 17 00:00:00 2001 From: Tanmay Rustagi <88379306+tanmay-db@users.noreply.github.com> Date: Tue, 1 Oct 2024 14:56:54 +0200 Subject: [PATCH 41/54] [Internal] Bump Go SDK to latest and generate TF structs (#4062) ## Changes Bump Go SDK to latest release and generate tf structs for same openapi sha as in Go SDK ## Tests Unit tests, nightly tests will run on release PR - [ ] `make test` run locally - [ ] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [ ] using Go SDK --- .codegen/_openapi_sha | 2 +- go.mod | 2 +- go.sum | 4 +- internal/service/apps_tf/model.go | 31 +++--- internal/service/catalog_tf/model.go | 85 ++++++++++++++- internal/service/compute_tf/model.go | 60 ++++++++--- internal/service/jobs_tf/model.go | 42 +++++--- internal/service/pipelines_tf/model.go | 8 ++ internal/service/serving_tf/model.go | 128 +++++++++++++++++++++- internal/service/settings_tf/model.go | 142 +++++++++++++++++++++++++ internal/service/sql_tf/model.go | 79 -------------- 11 files changed, 454 insertions(+), 129 deletions(-) diff --git a/.codegen/_openapi_sha b/.codegen/_openapi_sha index 4ceeab3d38..ffd6f58dd9 100644 --- a/.codegen/_openapi_sha +++ b/.codegen/_openapi_sha @@ -1 +1 @@ -d05898328669a3f8ab0c2ecee37db2673d3ea3f7 \ No newline at end of file +6f6b1371e640f2dfeba72d365ac566368656f6b6 \ No newline at end of file diff --git a/go.mod b/go.mod index 8f5de34e8d..cb0d35a5ba 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/databricks/terraform-provider-databricks go 1.22 require ( - github.com/databricks/databricks-sdk-go v0.46.0 + github.com/databricks/databricks-sdk-go v0.47.0 github.com/golang-jwt/jwt/v4 v4.5.0 github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 github.com/hashicorp/hcl v1.0.0 diff --git a/go.sum b/go.sum index 9cace277b5..8ff73d7ad5 100644 --- a/go.sum +++ b/go.sum @@ -26,8 +26,8 @@ github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBS github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= -github.com/databricks/databricks-sdk-go v0.46.0 h1:D0TxmtSVAOsdnfzH4OGtAmcq+8TyA7Z6fA6JEYhupeY= -github.com/databricks/databricks-sdk-go v0.46.0/go.mod h1:ds+zbv5mlQG7nFEU5ojLtgN/u0/9YzZmKQES/CfedzU= +github.com/databricks/databricks-sdk-go v0.47.0 h1:eE7dN9axviL8+s10jnQAayOYDaR+Mfu7E9COGjO4lrQ= +github.com/databricks/databricks-sdk-go v0.47.0/go.mod h1:ds+zbv5mlQG7nFEU5ojLtgN/u0/9YzZmKQES/CfedzU= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/internal/service/apps_tf/model.go b/internal/service/apps_tf/model.go index 2ae21cc7d9..74406307a5 100755 --- a/internal/service/apps_tf/model.go +++ b/internal/service/apps_tf/model.go @@ -17,6 +17,10 @@ import ( type App struct { // The active deployment of the app. ActiveDeployment *AppDeployment `tfsdk:"active_deployment" tf:"optional"` + + AppStatus *ApplicationStatus `tfsdk:"app_status" tf:"optional"` + + ComputeStatus *ComputeStatus `tfsdk:"compute_status" tf:"optional"` // The creation time of the app. Formatted timestamp in ISO 6801. CreateTime types.String `tfsdk:"create_time" tf:"optional"` // The email of the user that created the app. @@ -32,8 +36,6 @@ type App struct { ServicePrincipalId types.Int64 `tfsdk:"service_principal_id" tf:"optional"` ServicePrincipalName types.String `tfsdk:"service_principal_name" tf:"optional"` - - Status *AppStatus `tfsdk:"status" tf:"optional"` // The update time of the app. Formatted timestamp in ISO 6801. UpdateTime types.String `tfsdk:"update_time" tf:"optional"` // The email of the user that last updated the app. @@ -84,7 +86,7 @@ type AppDeployment struct { // the app in the workspace during deployment creation, whereas the latter // provides a system generated stable snapshotted source code path used by // the deployment. - SourceCodePath types.String `tfsdk:"source_code_path" tf:""` + SourceCodePath types.String `tfsdk:"source_code_path" tf:"optional"` // Status and status message of the deployment Status *AppDeploymentStatus `tfsdk:"status" tf:"optional"` // The update time of the deployment. Formatted timestamp in ISO 6801. @@ -132,16 +134,25 @@ type AppPermissionsRequest struct { AppName types.String `tfsdk:"-"` } -type AppStatus struct { - // Message corresponding with the app state. +type ApplicationStatus struct { + // Application status message + Message types.String `tfsdk:"message" tf:"optional"` + // State of the application. + State types.String `tfsdk:"state" tf:"optional"` +} + +type ComputeStatus struct { + // Compute status message Message types.String `tfsdk:"message" tf:"optional"` - // State of the app. + // State of the app compute. State types.String `tfsdk:"state" tf:"optional"` } type CreateAppDeploymentRequest struct { // The name of the app. AppName types.String `tfsdk:"-"` + // The unique id of the deployment. + DeploymentId types.String `tfsdk:"deployment_id" tf:"optional"` // The mode of which the deployment will manage the source code. Mode types.String `tfsdk:"mode" tf:"optional"` // The workspace file system path of the source code used to create the app @@ -151,7 +162,7 @@ type CreateAppDeploymentRequest struct { // the app in the workspace during deployment creation, whereas the latter // provides a system generated stable snapshotted source code path used by // the deployment. - SourceCodePath types.String `tfsdk:"source_code_path" tf:""` + SourceCodePath types.String `tfsdk:"source_code_path" tf:"optional"` } type CreateAppRequest struct { @@ -168,9 +179,6 @@ type DeleteAppRequest struct { Name types.String `tfsdk:"-"` } -type DeleteResponse struct { -} - // Get an app deployment type GetAppDeploymentRequest struct { // The name of the app. @@ -245,9 +253,6 @@ type StopAppRequest struct { Name types.String `tfsdk:"-"` } -type StopAppResponse struct { -} - type UpdateAppRequest struct { // The description of the app. Description types.String `tfsdk:"description" tf:"optional"` diff --git a/internal/service/catalog_tf/model.go b/internal/service/catalog_tf/model.go index e84b479703..78848824f1 100755 --- a/internal/service/catalog_tf/model.go +++ b/internal/service/catalog_tf/model.go @@ -88,6 +88,21 @@ type ArtifactMatcher struct { type AssignResponse struct { } +// AWS temporary credentials for API authentication. Read more at +// https://docs.aws.amazon.com/STS/latest/APIReference/API_Credentials.html. +type AwsCredentials struct { + // The access key ID that identifies the temporary credentials. + AccessKeyId types.String `tfsdk:"access_key_id" tf:"optional"` + // The Amazon Resource Name (ARN) of the S3 access point for temporary + // credentials related the external location. + AccessPoint types.String `tfsdk:"access_point" tf:"optional"` + // The secret access key that can be used to sign AWS API requests. + SecretAccessKey types.String `tfsdk:"secret_access_key" tf:"optional"` + // The token that users must pass to AWS API to use the temporary + // credentials. + SessionToken types.String `tfsdk:"session_token" tf:"optional"` +} + type AwsIamRoleRequest struct { // The Amazon Resource Name (ARN) of the AWS IAM role for S3 data access. RoleArn types.String `tfsdk:"role_arn" tf:""` @@ -145,6 +160,13 @@ type AzureServicePrincipal struct { DirectoryId types.String `tfsdk:"directory_id" tf:""` } +// Azure temporary credentials for API authentication. Read more at +// https://docs.microsoft.com/en-us/rest/api/storageservices/create-user-delegation-sas +type AzureUserDelegationSas struct { + // The signed URI (SAS Token) used to access blob services for a given path + SasToken types.String `tfsdk:"sas_token" tf:"optional"` +} + // Cancel refresh type CancelRefreshRequest struct { // ID of the refresh. @@ -404,7 +426,7 @@ type CreateFunction struct { // JSON-serialized key-value pair map, encoded (escaped) as a string. Properties types.String `tfsdk:"properties" tf:"optional"` // Table function return parameters. - ReturnParams FunctionParameterInfos `tfsdk:"return_params" tf:""` + ReturnParams *FunctionParameterInfos `tfsdk:"return_params" tf:"optional"` // Function language. When **EXTERNAL** is used, the language of the routine // function should be specified in the __external_language__ field, and the // __return_params__ of the function cannot be used (as **TABLE** return @@ -414,7 +436,7 @@ type CreateFunction struct { // Function body. RoutineDefinition types.String `tfsdk:"routine_definition" tf:""` // Function dependencies. - RoutineDependencies DependencyList `tfsdk:"routine_dependencies" tf:""` + RoutineDependencies *DependencyList `tfsdk:"routine_dependencies" tf:"optional"` // Name of parent schema relative to its parent catalog. SchemaName types.String `tfsdk:"schema_name" tf:""` // Function security type. @@ -1018,6 +1040,42 @@ type FunctionParameterInfos struct { Parameters []FunctionParameterInfo `tfsdk:"parameters" tf:"optional"` } +// GCP temporary credentials for API authentication. Read more at +// https://developers.google.com/identity/protocols/oauth2/service-account +type GcpOauthToken struct { + OauthToken types.String `tfsdk:"oauth_token" tf:"optional"` +} + +type GenerateTemporaryTableCredentialRequest struct { + // The operation performed against the table data, either READ or + // READ_WRITE. If READ_WRITE is specified, the credentials returned will + // have write permissions, otherwise, it will be read only. + Operation types.String `tfsdk:"operation" tf:"optional"` + // UUID of the table to read or write. + TableId types.String `tfsdk:"table_id" tf:"optional"` +} + +type GenerateTemporaryTableCredentialResponse struct { + // AWS temporary credentials for API authentication. Read more at + // https://docs.aws.amazon.com/STS/latest/APIReference/API_Credentials.html. + AwsTempCredentials *AwsCredentials `tfsdk:"aws_temp_credentials" tf:"optional"` + // Azure temporary credentials for API authentication. Read more at + // https://docs.microsoft.com/en-us/rest/api/storageservices/create-user-delegation-sas + AzureUserDelegationSas *AzureUserDelegationSas `tfsdk:"azure_user_delegation_sas" tf:"optional"` + // Server time when the credential will expire, in unix epoch milliseconds + // since January 1, 1970 at 00:00:00 UTC. The API client is advised to cache + // the credential given this expiration time. + ExpirationTime types.Int64 `tfsdk:"expiration_time" tf:"optional"` + // GCP temporary credentials for API authentication. Read more at + // https://developers.google.com/identity/protocols/oauth2/service-account + GcpOauthToken *GcpOauthToken `tfsdk:"gcp_oauth_token" tf:"optional"` + // R2 temporary credentials for API authentication. Read more at + // https://developers.cloudflare.com/r2/api/s3/tokens/. + R2TempCredentials *R2Credentials `tfsdk:"r2_temp_credentials" tf:"optional"` + // The URL of the storage path accessible by the temporary credential. + Url types.String `tfsdk:"url" tf:"optional"` +} + // Gets the metastore assignment for a workspace type GetAccountMetastoreAssignmentRequest struct { // Workspace ID. @@ -1150,6 +1208,9 @@ type GetMetastoreSummaryResponse struct { DeltaSharingRecipientTokenLifetimeInSeconds types.Int64 `tfsdk:"delta_sharing_recipient_token_lifetime_in_seconds" tf:"optional"` // The scope of Delta Sharing enabled for the metastore. DeltaSharingScope types.String `tfsdk:"delta_sharing_scope" tf:"optional"` + // Whether to allow non-DBR clients to directly access entities under the + // metastore. + ExternalAccessEnabled types.Bool `tfsdk:"external_access_enabled" tf:"optional"` // Globally unique metastore ID across clouds and regions, of the form // `cloud:region:metastore_id`. GlobalMetastoreId types.String `tfsdk:"global_metastore_id" tf:"optional"` @@ -1262,6 +1323,8 @@ type GetTableRequest struct { IncludeBrowse types.Bool `tfsdk:"-"` // Whether delta metadata should be included in the response. IncludeDeltaMetadata types.Bool `tfsdk:"-"` + // Whether to include a manifest containing capabilities the table has. + IncludeManifestCapabilities types.Bool `tfsdk:"-"` } // Get catalog workspace bindings @@ -1546,6 +1609,8 @@ type ListStorageCredentialsResponse struct { type ListSummariesRequest struct { // Name of parent catalog for tables of interest. CatalogName types.String `tfsdk:"-"` + // Whether to include a manifest containing capabilities the table has. + IncludeManifestCapabilities types.Bool `tfsdk:"-"` // Maximum number of summaries for tables to return. If not set, the page // length is set to a server configured value (10000, as of 1/5/2024). - // when set to a value greater than 0, the page length is the minimum of @@ -1606,6 +1671,8 @@ type ListTablesRequest struct { IncludeBrowse types.Bool `tfsdk:"-"` // Whether delta metadata should be included in the response. IncludeDeltaMetadata types.Bool `tfsdk:"-"` + // Whether to include a manifest containing capabilities the table has. + IncludeManifestCapabilities types.Bool `tfsdk:"-"` // Maximum number of tables to return. If not set, all the tables are // returned (not recommended). - when set to a value greater than 0, the // page length is the minimum of this value and a server configured value; - @@ -1693,6 +1760,9 @@ type MetastoreInfo struct { DeltaSharingRecipientTokenLifetimeInSeconds types.Int64 `tfsdk:"delta_sharing_recipient_token_lifetime_in_seconds" tf:"optional"` // The scope of Delta Sharing enabled for the metastore. DeltaSharingScope types.String `tfsdk:"delta_sharing_scope" tf:"optional"` + // Whether to allow non-DBR clients to directly access entities under the + // metastore. + ExternalAccessEnabled types.Bool `tfsdk:"external_access_enabled" tf:"optional"` // Globally unique metastore ID across clouds and regions, of the form // `cloud:region:metastore_id`. GlobalMetastoreId types.String `tfsdk:"global_metastore_id" tf:"optional"` @@ -2098,6 +2168,17 @@ type QuotaInfo struct { QuotaName types.String `tfsdk:"quota_name" tf:"optional"` } +// R2 temporary credentials for API authentication. Read more at +// https://developers.cloudflare.com/r2/api/s3/tokens/. +type R2Credentials struct { + // The access key ID that identifies the temporary credentials. + AccessKeyId types.String `tfsdk:"access_key_id" tf:"optional"` + // The secret access key associated with the access key. + SecretAccessKey types.String `tfsdk:"secret_access_key" tf:"optional"` + // The generated JWT that users must pass to use the temporary credentials. + SessionToken types.String `tfsdk:"session_token" tf:"optional"` +} + // Get a Volume type ReadVolumeRequest struct { // Whether to include volumes in the response for which the principal can diff --git a/internal/service/compute_tf/model.go b/internal/service/compute_tf/model.go index e983a492c4..223ba1cb66 100755 --- a/internal/service/compute_tf/model.go +++ b/internal/service/compute_tf/model.go @@ -326,8 +326,14 @@ type ClusterAttributes struct { NodeTypeId types.String `tfsdk:"node_type_id" tf:"optional"` // The ID of the cluster policy used to create the cluster if applicable. PolicyId types.String `tfsdk:"policy_id" tf:"optional"` - // Decides which runtime engine to be use, e.g. Standard vs. Photon. If - // unspecified, the runtime engine is inferred from spark_version. + // Determines the cluster's runtime engine, either standard or Photon. + // + // This field is not compatible with legacy `spark_version` values that + // contain `-photon-`. Remove `-photon-` from the `spark_version` and set + // `runtime_engine` to `PHOTON`. + // + // If left unspecified, the runtime engine defaults to standard unless the + // spark_version contains -photon-, in which case Photon will be used. RuntimeEngine types.String `tfsdk:"runtime_engine" tf:"optional"` // Single user name if data_security_mode is `SINGLE_USER` SingleUserName types.String `tfsdk:"single_user_name" tf:"optional"` @@ -526,8 +532,14 @@ type ClusterDetails struct { NumWorkers types.Int64 `tfsdk:"num_workers" tf:"optional"` // The ID of the cluster policy used to create the cluster if applicable. PolicyId types.String `tfsdk:"policy_id" tf:"optional"` - // Decides which runtime engine to be use, e.g. Standard vs. Photon. If - // unspecified, the runtime engine is inferred from spark_version. + // Determines the cluster's runtime engine, either standard or Photon. + // + // This field is not compatible with legacy `spark_version` values that + // contain `-photon-`. Remove `-photon-` from the `spark_version` and set + // `runtime_engine` to `PHOTON`. + // + // If left unspecified, the runtime engine defaults to standard unless the + // spark_version contains -photon-, in which case Photon will be used. RuntimeEngine types.String `tfsdk:"runtime_engine" tf:"optional"` // Single user name if data_security_mode is `SINGLE_USER` SingleUserName types.String `tfsdk:"single_user_name" tf:"optional"` @@ -844,8 +856,14 @@ type ClusterSpec struct { NumWorkers types.Int64 `tfsdk:"num_workers" tf:"optional"` // The ID of the cluster policy used to create the cluster if applicable. PolicyId types.String `tfsdk:"policy_id" tf:"optional"` - // Decides which runtime engine to be use, e.g. Standard vs. Photon. If - // unspecified, the runtime engine is inferred from spark_version. + // Determines the cluster's runtime engine, either standard or Photon. + // + // This field is not compatible with legacy `spark_version` values that + // contain `-photon-`. Remove `-photon-` from the `spark_version` and set + // `runtime_engine` to `PHOTON`. + // + // If left unspecified, the runtime engine defaults to standard unless the + // spark_version contains -photon-, in which case Photon will be used. RuntimeEngine types.String `tfsdk:"runtime_engine" tf:"optional"` // Single user name if data_security_mode is `SINGLE_USER` SingleUserName types.String `tfsdk:"single_user_name" tf:"optional"` @@ -1040,8 +1058,14 @@ type CreateCluster struct { NumWorkers types.Int64 `tfsdk:"num_workers" tf:"optional"` // The ID of the cluster policy used to create the cluster if applicable. PolicyId types.String `tfsdk:"policy_id" tf:"optional"` - // Decides which runtime engine to be use, e.g. Standard vs. Photon. If - // unspecified, the runtime engine is inferred from spark_version. + // Determines the cluster's runtime engine, either standard or Photon. + // + // This field is not compatible with legacy `spark_version` values that + // contain `-photon-`. Remove `-photon-` from the `spark_version` and set + // `runtime_engine` to `PHOTON`. + // + // If left unspecified, the runtime engine defaults to standard unless the + // spark_version contains -photon-, in which case Photon will be used. RuntimeEngine types.String `tfsdk:"runtime_engine" tf:"optional"` // Single user name if data_security_mode is `SINGLE_USER` SingleUserName types.String `tfsdk:"single_user_name" tf:"optional"` @@ -1423,8 +1447,14 @@ type EditCluster struct { NumWorkers types.Int64 `tfsdk:"num_workers" tf:"optional"` // The ID of the cluster policy used to create the cluster if applicable. PolicyId types.String `tfsdk:"policy_id" tf:"optional"` - // Decides which runtime engine to be use, e.g. Standard vs. Photon. If - // unspecified, the runtime engine is inferred from spark_version. + // Determines the cluster's runtime engine, either standard or Photon. + // + // This field is not compatible with legacy `spark_version` values that + // contain `-photon-`. Remove `-photon-` from the `spark_version` and set + // `runtime_engine` to `PHOTON`. + // + // If left unspecified, the runtime engine defaults to standard unless the + // spark_version contains -photon-, in which case Photon will be used. RuntimeEngine types.String `tfsdk:"runtime_engine" tf:"optional"` // Single user name if data_security_mode is `SINGLE_USER` SingleUserName types.String `tfsdk:"single_user_name" tf:"optional"` @@ -2963,8 +2993,14 @@ type UpdateClusterResource struct { NumWorkers types.Int64 `tfsdk:"num_workers" tf:"optional"` // The ID of the cluster policy used to create the cluster if applicable. PolicyId types.String `tfsdk:"policy_id" tf:"optional"` - // Decides which runtime engine to be use, e.g. Standard vs. Photon. If - // unspecified, the runtime engine is inferred from spark_version. + // Determines the cluster's runtime engine, either standard or Photon. + // + // This field is not compatible with legacy `spark_version` values that + // contain `-photon-`. Remove `-photon-` from the `spark_version` and set + // `runtime_engine` to `PHOTON`. + // + // If left unspecified, the runtime engine defaults to standard unless the + // spark_version contains -photon-, in which case Photon will be used. RuntimeEngine types.String `tfsdk:"runtime_engine" tf:"optional"` // Single user name if data_security_mode is `SINGLE_USER` SingleUserName types.String `tfsdk:"single_user_name" tf:"optional"` diff --git a/internal/service/jobs_tf/model.go b/internal/service/jobs_tf/model.go index d5a1b57f58..457ea2bb4a 100755 --- a/internal/service/jobs_tf/model.go +++ b/internal/service/jobs_tf/model.go @@ -263,7 +263,11 @@ type CreateJob struct { // begin or complete as well as when this job is deleted. EmailNotifications *JobEmailNotifications `tfsdk:"email_notifications" tf:"optional"` // A list of task execution environment specifications that can be - // referenced by tasks of this job. + // referenced by serverless tasks of this job. An environment is required to + // be present for serverless tasks. For serverless notebook tasks, the + // environment is accessible in the notebook environment panel. For other + // serverless tasks, the task environment is required to be specified using + // environment_key in the task settings. Environments []JobEnvironment `tfsdk:"environment" tf:"optional"` // Used to tell what is the format of the job. This field is ignored in // Create/Update/Reset calls. When using the Jobs API 2.1 this value is @@ -309,12 +313,12 @@ type CreateJob struct { Parameters []JobParameterDefinition `tfsdk:"parameter" tf:"optional"` // The queue settings of the job. Queue *QueueSettings `tfsdk:"queue" tf:"optional"` - // Write-only setting, available only in Create/Update/Reset and Submit - // calls. Specifies the user or service principal that the job runs as. If - // not specified, the job runs as the user who created the job. + // Write-only setting. Specifies the user, service principal or group that + // the job/pipeline runs as. If not specified, the job/pipeline runs as the + // user who created the job/pipeline. // - // Only `user_name` or `service_principal_name` can be specified. If both - // are specified, an error is thrown. + // Exactly one of `user_name`, `service_principal_name`, `group_name` should + // be specified. If not, an error is thrown. RunAs *JobRunAs `tfsdk:"run_as" tf:"optional"` // An optional periodic schedule for this job. The default behavior is that // the job only runs when triggered by clicking “Run Now” in the Jobs UI @@ -827,12 +831,12 @@ type JobPermissionsRequest struct { JobId types.String `tfsdk:"-"` } -// Write-only setting, available only in Create/Update/Reset and Submit calls. -// Specifies the user or service principal that the job runs as. If not -// specified, the job runs as the user who created the job. +// Write-only setting. Specifies the user, service principal or group that the +// job/pipeline runs as. If not specified, the job/pipeline runs as the user who +// created the job/pipeline. // -// Only `user_name` or `service_principal_name` can be specified. If both are -// specified, an error is thrown. +// Exactly one of `user_name`, `service_principal_name`, `group_name` should be +// specified. If not, an error is thrown. type JobRunAs struct { // Application ID of an active service principal. Setting this field // requires the `servicePrincipal/user` role. @@ -861,7 +865,11 @@ type JobSettings struct { // begin or complete as well as when this job is deleted. EmailNotifications *JobEmailNotifications `tfsdk:"email_notifications" tf:"optional"` // A list of task execution environment specifications that can be - // referenced by tasks of this job. + // referenced by serverless tasks of this job. An environment is required to + // be present for serverless tasks. For serverless notebook tasks, the + // environment is accessible in the notebook environment panel. For other + // serverless tasks, the task environment is required to be specified using + // environment_key in the task settings. Environments []JobEnvironment `tfsdk:"environment" tf:"optional"` // Used to tell what is the format of the job. This field is ignored in // Create/Update/Reset calls. When using the Jobs API 2.1 this value is @@ -907,12 +915,12 @@ type JobSettings struct { Parameters []JobParameterDefinition `tfsdk:"parameter" tf:"optional"` // The queue settings of the job. Queue *QueueSettings `tfsdk:"queue" tf:"optional"` - // Write-only setting, available only in Create/Update/Reset and Submit - // calls. Specifies the user or service principal that the job runs as. If - // not specified, the job runs as the user who created the job. + // Write-only setting. Specifies the user, service principal or group that + // the job/pipeline runs as. If not specified, the job/pipeline runs as the + // user who created the job/pipeline. // - // Only `user_name` or `service_principal_name` can be specified. If both - // are specified, an error is thrown. + // Exactly one of `user_name`, `service_principal_name`, `group_name` should + // be specified. If not, an error is thrown. RunAs *JobRunAs `tfsdk:"run_as" tf:"optional"` // An optional periodic schedule for this job. The default behavior is that // the job only runs when triggered by clicking “Run Now” in the Jobs UI diff --git a/internal/service/pipelines_tf/model.go b/internal/service/pipelines_tf/model.go index 1caafa7419..b6abbbb71c 100755 --- a/internal/service/pipelines_tf/model.go +++ b/internal/service/pipelines_tf/model.go @@ -19,6 +19,8 @@ type CreatePipeline struct { // If false, deployment will fail if name conflicts with that of another // pipeline. AllowDuplicateNames types.Bool `tfsdk:"allow_duplicate_names" tf:"optional"` + // Budget policy of this pipeline. + BudgetPolicyId types.String `tfsdk:"budget_policy_id" tf:"optional"` // A catalog in Unity Catalog to publish data from this pipeline to. If // `target` is specified, tables in this pipeline are published to a // `target` schema inside `catalog` (for example, @@ -103,6 +105,8 @@ type EditPipeline struct { // If false, deployment will fail if name has changed and conflicts the name // of another pipeline. AllowDuplicateNames types.Bool `tfsdk:"allow_duplicate_names" tf:"optional"` + // Budget policy of this pipeline. + BudgetPolicyId types.String `tfsdk:"budget_policy_id" tf:"optional"` // A catalog in Unity Catalog to publish data from this pipeline to. If // `target` is specified, tables in this pipeline are published to a // `target` schema inside `catalog` (for example, @@ -209,6 +213,8 @@ type GetPipelineResponse struct { ClusterId types.String `tfsdk:"cluster_id" tf:"optional"` // The username of the pipeline creator. CreatorUserName types.String `tfsdk:"creator_user_name" tf:"optional"` + // Serverless budget policy ID of this pipeline. + EffectiveBudgetPolicyId types.String `tfsdk:"effective_budget_policy_id" tf:"optional"` // The health of a pipeline. Health types.String `tfsdk:"health" tf:"optional"` // The last time the pipeline settings were modified or created. @@ -642,6 +648,8 @@ type PipelinePermissionsRequest struct { } type PipelineSpec struct { + // Budget policy of this pipeline. + BudgetPolicyId types.String `tfsdk:"budget_policy_id" tf:"optional"` // A catalog in Unity Catalog to publish data from this pipeline to. If // `target` is specified, tables in this pipeline are published to a // `target` schema inside `catalog` (for example, diff --git a/internal/service/serving_tf/model.go b/internal/service/serving_tf/model.go index c40d18ee63..b22dc911a7 100755 --- a/internal/service/serving_tf/model.go +++ b/internal/service/serving_tf/model.go @@ -30,6 +30,85 @@ type Ai21LabsConfig struct { Ai21labsApiKeyPlaintext types.String `tfsdk:"ai21labs_api_key_plaintext" tf:"optional"` } +type AiGatewayConfig struct { + // Configuration for AI Guardrails to prevent unwanted data and unsafe data + // in requests and responses. + Guardrails *AiGatewayGuardrails `tfsdk:"guardrails" tf:"optional"` + // Configuration for payload logging using inference tables. Use these + // tables to monitor and audit data being sent to and received from model + // APIs and to improve model quality. + InferenceTableConfig *AiGatewayInferenceTableConfig `tfsdk:"inference_table_config" tf:"optional"` + // Configuration for rate limits which can be set to limit endpoint traffic. + RateLimits []AiGatewayRateLimit `tfsdk:"rate_limits" tf:"optional"` + // Configuration to enable usage tracking using system tables. These tables + // allow you to monitor operational usage on endpoints and their associated + // costs. + UsageTrackingConfig *AiGatewayUsageTrackingConfig `tfsdk:"usage_tracking_config" tf:"optional"` +} + +type AiGatewayGuardrailParameters struct { + // List of invalid keywords. AI guardrail uses keyword or string matching to + // decide if the keyword exists in the request or response content. + InvalidKeywords []types.String `tfsdk:"invalid_keywords" tf:"optional"` + // Configuration for guardrail PII filter. + Pii *AiGatewayGuardrailPiiBehavior `tfsdk:"pii" tf:"optional"` + // Indicates whether the safety filter is enabled. + Safety types.Bool `tfsdk:"safety" tf:"optional"` + // The list of allowed topics. Given a chat request, this guardrail flags + // the request if its topic is not in the allowed topics. + ValidTopics []types.String `tfsdk:"valid_topics" tf:"optional"` +} + +type AiGatewayGuardrailPiiBehavior struct { + // Behavior for PII filter. Currently only 'BLOCK' is supported. If 'BLOCK' + // is set for the input guardrail and the request contains PII, the request + // is not sent to the model server and 400 status code is returned; if + // 'BLOCK' is set for the output guardrail and the model response contains + // PII, the PII info in the response is redacted and 400 status code is + // returned. + Behavior types.String `tfsdk:"behavior" tf:""` +} + +type AiGatewayGuardrails struct { + // Configuration for input guardrail filters. + Input *AiGatewayGuardrailParameters `tfsdk:"input" tf:"optional"` + // Configuration for output guardrail filters. + Output *AiGatewayGuardrailParameters `tfsdk:"output" tf:"optional"` +} + +type AiGatewayInferenceTableConfig struct { + // The name of the catalog in Unity Catalog. Required when enabling + // inference tables. NOTE: On update, you have to disable inference table + // first in order to change the catalog name. + CatalogName types.String `tfsdk:"catalog_name" tf:"optional"` + // Indicates whether the inference table is enabled. + Enabled types.Bool `tfsdk:"enabled" tf:"optional"` + // The name of the schema in Unity Catalog. Required when enabling inference + // tables. NOTE: On update, you have to disable inference table first in + // order to change the schema name. + SchemaName types.String `tfsdk:"schema_name" tf:"optional"` + // The prefix of the table in Unity Catalog. NOTE: On update, you have to + // disable inference table first in order to change the prefix name. + TableNamePrefix types.String `tfsdk:"table_name_prefix" tf:"optional"` +} + +type AiGatewayRateLimit struct { + // Used to specify how many calls are allowed for a key within the + // renewal_period. + Calls types.Int64 `tfsdk:"calls" tf:""` + // Key field for a rate limit. Currently, only 'user' and 'endpoint' are + // supported, with 'endpoint' being the default if not specified. + Key types.String `tfsdk:"key" tf:"optional"` + // Renewal period field for a rate limit. Currently, only 'minute' is + // supported. + RenewalPeriod types.String `tfsdk:"renewal_period" tf:""` +} + +type AiGatewayUsageTrackingConfig struct { + // Whether to enable usage tracking. + Enabled types.Bool `tfsdk:"enabled" tf:"optional"` +} + type AmazonBedrockConfig struct { // The Databricks secret key reference for an AWS access key ID with // permissions to interact with Bedrock services. If you prefer to paste @@ -147,14 +226,17 @@ type CohereConfig struct { } type CreateServingEndpoint struct { + // The AI Gateway configuration for the serving endpoint. NOTE: only + // external model endpoints are supported as of now. + AiGateway *AiGatewayConfig `tfsdk:"ai_gateway" tf:"optional"` // The core config of the serving endpoint. Config EndpointCoreConfigInput `tfsdk:"config" tf:""` // The name of the serving endpoint. This field is required and must be // unique across a Databricks workspace. An endpoint name can consist of // alphanumeric characters, dashes, and underscores. Name types.String `tfsdk:"name" tf:""` - // Rate limits to be applied to the serving endpoint. NOTE: only external - // and foundation model endpoints are supported as of now. + // Rate limits to be applied to the serving endpoint. NOTE: this field is + // deprecated, please use AI Gateway to manage rate limits. RateLimits []RateLimit `tfsdk:"rate_limits" tf:"optional"` // Enable route optimization for the serving endpoint. RouteOptimized types.Bool `tfsdk:"route_optimized" tf:"optional"` @@ -520,6 +602,42 @@ type PayloadTable struct { StatusMessage types.String `tfsdk:"status_message" tf:"optional"` } +// Update AI Gateway of a serving endpoint +type PutAiGatewayRequest struct { + // Configuration for AI Guardrails to prevent unwanted data and unsafe data + // in requests and responses. + Guardrails *AiGatewayGuardrails `tfsdk:"guardrails" tf:"optional"` + // Configuration for payload logging using inference tables. Use these + // tables to monitor and audit data being sent to and received from model + // APIs and to improve model quality. + InferenceTableConfig *AiGatewayInferenceTableConfig `tfsdk:"inference_table_config" tf:"optional"` + // The name of the serving endpoint whose AI Gateway is being updated. This + // field is required. + Name types.String `tfsdk:"-"` + // Configuration for rate limits which can be set to limit endpoint traffic. + RateLimits []AiGatewayRateLimit `tfsdk:"rate_limits" tf:"optional"` + // Configuration to enable usage tracking using system tables. These tables + // allow you to monitor operational usage on endpoints and their associated + // costs. + UsageTrackingConfig *AiGatewayUsageTrackingConfig `tfsdk:"usage_tracking_config" tf:"optional"` +} + +type PutAiGatewayResponse struct { + // Configuration for AI Guardrails to prevent unwanted data and unsafe data + // in requests and responses. + Guardrails *AiGatewayGuardrails `tfsdk:"guardrails" tf:"optional"` + // Configuration for payload logging using inference tables. Use these + // tables to monitor and audit data being sent to and received from model + // APIs and to improve model quality . + InferenceTableConfig *AiGatewayInferenceTableConfig `tfsdk:"inference_table_config" tf:"optional"` + // Configuration for rate limits which can be set to limit endpoint traffic. + RateLimits []AiGatewayRateLimit `tfsdk:"rate_limits" tf:"optional"` + // Configuration to enable usage tracking using system tables. These tables + // allow you to monitor operational usage on endpoints and their associated + // costs. + UsageTrackingConfig *AiGatewayUsageTrackingConfig `tfsdk:"usage_tracking_config" tf:"optional"` +} + // Update rate limits of a serving endpoint type PutRequest struct { // The name of the serving endpoint whose rate limits are being updated. @@ -914,6 +1032,9 @@ type ServerLogsResponse struct { } type ServingEndpoint struct { + // The AI Gateway configuration for the serving endpoint. NOTE: Only + // external model endpoints are currently supported. + AiGateway *AiGatewayConfig `tfsdk:"ai_gateway" tf:"optional"` // The config that is currently being served by the endpoint. Config *EndpointCoreConfigSummary `tfsdk:"config" tf:"optional"` // The timestamp when the endpoint was created in Unix time. @@ -960,6 +1081,9 @@ type ServingEndpointAccessControlResponse struct { } type ServingEndpointDetailed struct { + // The AI Gateway configuration for the serving endpoint. NOTE: Only + // external model endpoints are currently supported. + AiGateway *AiGatewayConfig `tfsdk:"ai_gateway" tf:"optional"` // The config that is currently being served by the endpoint. Config *EndpointCoreConfigOutput `tfsdk:"config" tf:"optional"` // The timestamp when the endpoint was created in Unix time. diff --git a/internal/service/settings_tf/model.go b/internal/service/settings_tf/model.go index 55059248b5..117cf8d113 100755 --- a/internal/service/settings_tf/model.go +++ b/internal/service/settings_tf/model.go @@ -32,6 +32,10 @@ type AutomaticClusterUpdateSetting struct { SettingName types.String `tfsdk:"setting_name" tf:"optional"` } +type BooleanMessage struct { + Value types.Bool `tfsdk:"value" tf:"optional"` +} + type ClusterAutoRestartMessage struct { CanToggle types.Bool `tfsdk:"can_toggle" tf:"optional"` @@ -292,6 +296,54 @@ type DeleteDefaultNamespaceSettingResponse struct { Etag types.String `tfsdk:"etag" tf:""` } +// Delete Legacy Access Disablement Status +type DeleteDisableLegacyAccessRequest struct { + // etag used for versioning. The response is at least as fresh as the eTag + // provided. This is used for optimistic concurrency control as a way to + // help prevent simultaneous writes of a setting overwriting each other. It + // is strongly suggested that systems make use of the etag in the read -> + // delete pattern to perform setting deletions in order to avoid race + // conditions. That is, get an etag from a GET request, and pass it with the + // DELETE request to identify the rule set version you are deleting. + Etag types.String `tfsdk:"-"` +} + +// The etag is returned. +type DeleteDisableLegacyAccessResponse struct { + // etag used for versioning. The response is at least as fresh as the eTag + // provided. This is used for optimistic concurrency control as a way to + // help prevent simultaneous writes of a setting overwriting each other. It + // is strongly suggested that systems make use of the etag in the read -> + // delete pattern to perform setting deletions in order to avoid race + // conditions. That is, get an etag from a GET request, and pass it with the + // DELETE request to identify the rule set version you are deleting. + Etag types.String `tfsdk:"etag" tf:""` +} + +// Delete the disable legacy features setting +type DeleteDisableLegacyFeaturesRequest struct { + // etag used for versioning. The response is at least as fresh as the eTag + // provided. This is used for optimistic concurrency control as a way to + // help prevent simultaneous writes of a setting overwriting each other. It + // is strongly suggested that systems make use of the etag in the read -> + // delete pattern to perform setting deletions in order to avoid race + // conditions. That is, get an etag from a GET request, and pass it with the + // DELETE request to identify the rule set version you are deleting. + Etag types.String `tfsdk:"-"` +} + +// The etag is returned. +type DeleteDisableLegacyFeaturesResponse struct { + // etag used for versioning. The response is at least as fresh as the eTag + // provided. This is used for optimistic concurrency control as a way to + // help prevent simultaneous writes of a setting overwriting each other. It + // is strongly suggested that systems make use of the etag in the read -> + // delete pattern to perform setting deletions in order to avoid race + // conditions. That is, get an etag from a GET request, and pass it with the + // DELETE request to identify the rule set version you are deleting. + Etag types.String `tfsdk:"etag" tf:""` +} + // Delete access list type DeleteIpAccessListRequest struct { // The ID for the corresponding IP access list @@ -377,6 +429,42 @@ type DeleteTokenManagementRequest struct { TokenId types.String `tfsdk:"-"` } +type DisableLegacyAccess struct { + DisableLegacyAccess BooleanMessage `tfsdk:"disable_legacy_access" tf:""` + // etag used for versioning. The response is at least as fresh as the eTag + // provided. This is used for optimistic concurrency control as a way to + // help prevent simultaneous writes of a setting overwriting each other. It + // is strongly suggested that systems make use of the etag in the read -> + // update pattern to perform setting updates in order to avoid race + // conditions. That is, get an etag from a GET request, and pass it with the + // PATCH request to identify the setting version you are updating. + Etag types.String `tfsdk:"etag" tf:"optional"` + // Name of the corresponding setting. This field is populated in the + // response, but it will not be respected even if it's set in the request + // body. The setting name in the path parameter will be respected instead. + // Setting name is required to be 'default' if the setting only has one + // instance per workspace. + SettingName types.String `tfsdk:"setting_name" tf:"optional"` +} + +type DisableLegacyFeatures struct { + DisableLegacyFeatures BooleanMessage `tfsdk:"disable_legacy_features" tf:""` + // etag used for versioning. The response is at least as fresh as the eTag + // provided. This is used for optimistic concurrency control as a way to + // help prevent simultaneous writes of a setting overwriting each other. It + // is strongly suggested that systems make use of the etag in the read -> + // update pattern to perform setting updates in order to avoid race + // conditions. That is, get an etag from a GET request, and pass it with the + // PATCH request to identify the setting version you are updating. + Etag types.String `tfsdk:"etag" tf:"optional"` + // Name of the corresponding setting. This field is populated in the + // response, but it will not be respected even if it's set in the request + // body. The setting name in the path parameter will be respected instead. + // Setting name is required to be 'default' if the setting only has one + // instance per workspace. + SettingName types.String `tfsdk:"setting_name" tf:"optional"` +} + type EmailConfig struct { // Email addresses to notify. Addresses []types.String `tfsdk:"addresses" tf:"optional"` @@ -538,6 +626,30 @@ type GetDefaultNamespaceSettingRequest struct { Etag types.String `tfsdk:"-"` } +// Retrieve Legacy Access Disablement Status +type GetDisableLegacyAccessRequest struct { + // etag used for versioning. The response is at least as fresh as the eTag + // provided. This is used for optimistic concurrency control as a way to + // help prevent simultaneous writes of a setting overwriting each other. It + // is strongly suggested that systems make use of the etag in the read -> + // delete pattern to perform setting deletions in order to avoid race + // conditions. That is, get an etag from a GET request, and pass it with the + // DELETE request to identify the rule set version you are deleting. + Etag types.String `tfsdk:"-"` +} + +// Get the disable legacy features setting +type GetDisableLegacyFeaturesRequest struct { + // etag used for versioning. The response is at least as fresh as the eTag + // provided. This is used for optimistic concurrency control as a way to + // help prevent simultaneous writes of a setting overwriting each other. It + // is strongly suggested that systems make use of the etag in the read -> + // delete pattern to perform setting deletions in order to avoid race + // conditions. That is, get an etag from a GET request, and pass it with the + // DELETE request to identify the rule set version you are deleting. + Etag types.String `tfsdk:"-"` +} + // Get the enhanced security monitoring setting type GetEnhancedSecurityMonitoringSettingRequest struct { // etag used for versioning. The response is at least as fresh as the eTag @@ -1045,6 +1157,8 @@ type TokenInfo struct { OwnerId types.Int64 `tfsdk:"owner_id" tf:"optional"` // ID of the token. TokenId types.String `tfsdk:"token_id" tf:"optional"` + // If applicable, the ID of the workspace that the token was created in. + WorkspaceId types.Int64 `tfsdk:"workspace_id" tf:"optional"` } type TokenPermission struct { @@ -1137,6 +1251,34 @@ type UpdateDefaultNamespaceSettingRequest struct { Setting DefaultNamespaceSetting `tfsdk:"setting" tf:""` } +// Details required to update a setting. +type UpdateDisableLegacyAccessRequest struct { + // This should always be set to true for Settings API. Added for AIP + // compliance. + AllowMissing types.Bool `tfsdk:"allow_missing" tf:""` + // Field mask is required to be passed into the PATCH request. Field mask + // specifies which fields of the setting payload will be updated. The field + // mask needs to be supplied as single string. To specify multiple fields in + // the field mask, use comma as the separator (no space). + FieldMask types.String `tfsdk:"field_mask" tf:""` + + Setting DisableLegacyAccess `tfsdk:"setting" tf:""` +} + +// Details required to update a setting. +type UpdateDisableLegacyFeaturesRequest struct { + // This should always be set to true for Settings API. Added for AIP + // compliance. + AllowMissing types.Bool `tfsdk:"allow_missing" tf:""` + // Field mask is required to be passed into the PATCH request. Field mask + // specifies which fields of the setting payload will be updated. The field + // mask needs to be supplied as single string. To specify multiple fields in + // the field mask, use comma as the separator (no space). + FieldMask types.String `tfsdk:"field_mask" tf:""` + + Setting DisableLegacyFeatures `tfsdk:"setting" tf:""` +} + // Details required to update a setting. type UpdateEnhancedSecurityMonitoringSettingRequest struct { // This should always be set to true for Settings API. Added for AIP diff --git a/internal/service/sql_tf/model.go b/internal/service/sql_tf/model.go index 8bbdb536f4..cbee45561b 100755 --- a/internal/service/sql_tf/model.go +++ b/internal/service/sql_tf/model.go @@ -208,15 +208,6 @@ type ChannelInfo struct { Name types.String `tfsdk:"name" tf:"optional"` } -// Client code that triggered the request -type ClientCallContext struct { - // File name that contains the last line that triggered the request. - FileName *EncodedText `tfsdk:"file_name" tf:"optional"` - // Last line number within a file or notebook cell that triggered the - // request. - LineNumber types.Int64 `tfsdk:"line_number" tf:"optional"` -} - type ColumnInfo struct { // The name of the column. Name types.String `tfsdk:"name" tf:"optional"` @@ -710,13 +701,6 @@ type EditWarehouseResponse struct { type Empty struct { } -type EncodedText struct { - // Carry text data in different form. - Encoding types.String `tfsdk:"encoding" tf:"optional"` - // text data - Text types.String `tfsdk:"text" tf:"optional"` -} - type EndpointConfPair struct { Key types.String `tfsdk:"key" tf:"optional"` @@ -1673,8 +1657,6 @@ type QueryInfo struct { QueryEndTimeMs types.Int64 `tfsdk:"query_end_time_ms" tf:"optional"` // The query ID. QueryId types.String `tfsdk:"query_id" tf:"optional"` - - QuerySource *QuerySource `tfsdk:"query_source" tf:"optional"` // The time the query started. QueryStartTimeMs types.Int64 `tfsdk:"query_start_time_ms" tf:"optional"` // The text of the query. @@ -1834,62 +1816,6 @@ type QueryPostContent struct { Tags []types.String `tfsdk:"tags" tf:"optional"` } -type QuerySource struct { - // UUID - AlertId types.String `tfsdk:"alert_id" tf:"optional"` - // Client code that triggered the request - ClientCallContext *ClientCallContext `tfsdk:"client_call_context" tf:"optional"` - // Id associated with a notebook cell - CommandId types.String `tfsdk:"command_id" tf:"optional"` - // Id associated with a notebook run or execution - CommandRunId types.String `tfsdk:"command_run_id" tf:"optional"` - // UUID - DashboardId types.String `tfsdk:"dashboard_id" tf:"optional"` - // UUID for Lakeview Dashboards, separate from DBSQL Dashboards - // (dashboard_id) - DashboardV3Id types.String `tfsdk:"dashboard_v3_id" tf:"optional"` - - DriverInfo *QuerySourceDriverInfo `tfsdk:"driver_info" tf:"optional"` - // Spark service that received and processed the query - EntryPoint types.String `tfsdk:"entry_point" tf:"optional"` - // UUID for Genie space - GenieSpaceId types.String `tfsdk:"genie_space_id" tf:"optional"` - - IsCloudFetch types.Bool `tfsdk:"is_cloud_fetch" tf:"optional"` - - IsDatabricksSqlExecApi types.Bool `tfsdk:"is_databricks_sql_exec_api" tf:"optional"` - - JobId types.String `tfsdk:"job_id" tf:"optional"` - // With background compute, jobs can be managed by different internal teams. - // When not specified, not a background compute job When specified and the - // value is not JOBS, it is a background compute job - JobManagedBy types.String `tfsdk:"job_managed_by" tf:"optional"` - - NotebookId types.String `tfsdk:"notebook_id" tf:"optional"` - // String provided by a customer that'll help them identify the query - QueryTags types.String `tfsdk:"query_tags" tf:"optional"` - // Id associated with a job run or execution - RunId types.String `tfsdk:"run_id" tf:"optional"` - // Id associated with a notebook cell run or execution - RunnableCommandId types.String `tfsdk:"runnable_command_id" tf:"optional"` - - ScheduledBy types.String `tfsdk:"scheduled_by" tf:"optional"` - - ServerlessChannelInfo *ServerlessChannelInfo `tfsdk:"serverless_channel_info" tf:"optional"` - // UUID - SourceQueryId types.String `tfsdk:"source_query_id" tf:"optional"` -} - -type QuerySourceDriverInfo struct { - BiToolEntry types.String `tfsdk:"bi_tool_entry" tf:"optional"` - - DriverName types.String `tfsdk:"driver_name" tf:"optional"` - - SimbaBrandingVendor types.String `tfsdk:"simba_branding_vendor" tf:"optional"` - - VersionNumber types.String `tfsdk:"version_number" tf:"optional"` -} - type RepeatedEndpointConfPairs struct { // Deprecated: Use configuration_pairs ConfigPair []EndpointConfPair `tfsdk:"config_pair" tf:"optional"` @@ -1964,11 +1890,6 @@ type ResultSchema struct { Columns []ColumnInfo `tfsdk:"columns" tf:"optional"` } -type ServerlessChannelInfo struct { - // Name of the Channel - Name types.String `tfsdk:"name" tf:"optional"` -} - type ServiceError struct { ErrorCode types.String `tfsdk:"error_code" tf:"optional"` // A brief summary of the error condition. From 1e89ad4d0a71d2867d6fdddab1a5726b5287ee1d Mon Sep 17 00:00:00 2001 From: Pieter Noordhuis Date: Tue, 1 Oct 2024 15:19:16 +0200 Subject: [PATCH 42/54] [Fix] Ignore presence or absence of `/Workspace` prefix for dashboard resource (#4061) ## Changes Users may choose to include the `/Workspace` prefix in the `parent_path` attribute of a dashboard to unambiguously refer to the workspace file system. This prefix is not included in reads, triggering a recreate. This change ignores this type of diff. ## Tests - [x] `make test` run locally - [ ] relevant change in `docs/` folder - [x] covered with integration tests in `internal/acceptance` - [x] relevant acceptance tests are passing - [ ] using Go SDK --- common/resource.go | 10 ++++++++++ common/resource_test.go | 8 ++++++++ dashboards/resource_dashboard.go | 2 +- internal/acceptance/dashboard_test.go | 18 +++++++++++++++++- 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/common/resource.go b/common/resource.go index 77ba894853..9e639eb962 100644 --- a/common/resource.go +++ b/common/resource.go @@ -440,6 +440,16 @@ func genericDatabricksData[T, P, C any]( } } +// WorkspacePathPrefixDiffSuppress suppresses diffs for workspace paths where both sides +// may or may not include the `/Workspace` prefix. +// +// This is the case for dashboards where at create time, the user may include the `/Workspace` +// prefix for the `parent_path` field, but the read response will not include the prefix. +func WorkspacePathPrefixDiffSuppress(k, old, new string, d *schema.ResourceData) bool { + const prefix = "/Workspace" + return strings.TrimPrefix(old, prefix) == strings.TrimPrefix(new, prefix) +} + func EqualFoldDiffSuppress(k, old, new string, d *schema.ResourceData) bool { if strings.EqualFold(old, new) { log.Printf("[INFO] Suppressing diff on %s", k) diff --git a/common/resource_test.go b/common/resource_test.go index 360c10b476..e93885a02c 100644 --- a/common/resource_test.go +++ b/common/resource_test.go @@ -179,6 +179,14 @@ func TestCustomizeDiffRobustness(t *testing.T) { assert.EqualError(t, err, "cannot customize diff for sample: panic: oops") } +func TestWorkspacePathPrefixDiffSuppress(t *testing.T) { + assert.True(t, WorkspacePathPrefixDiffSuppress("k", "/Workspace/foo/bar", "/Workspace/foo/bar", nil)) + assert.True(t, WorkspacePathPrefixDiffSuppress("k", "/Workspace/foo/bar", "/foo/bar", nil)) + assert.True(t, WorkspacePathPrefixDiffSuppress("k", "/foo/bar", "/Workspace/foo/bar", nil)) + assert.True(t, WorkspacePathPrefixDiffSuppress("k", "/foo/bar", "/foo/bar", nil)) + assert.False(t, WorkspacePathPrefixDiffSuppress("k", "/Workspace/1", "/Workspace/2", nil)) +} + func TestEqualFoldDiffSuppress(t *testing.T) { assert.True(t, EqualFoldDiffSuppress("k", "A", "a", nil)) assert.False(t, EqualFoldDiffSuppress("k", "A", "A2", nil)) diff --git a/dashboards/resource_dashboard.go b/dashboards/resource_dashboard.go index 531a6e5de4..d872b33f49 100644 --- a/dashboards/resource_dashboard.go +++ b/dashboards/resource_dashboard.go @@ -42,7 +42,7 @@ func (Dashboard) CustomizeSchema(s *common.CustomizableSchema) *common.Customiza s.SchemaPath("md5").SetComputed() // ForceNew fields - s.SchemaPath("parent_path").SetForceNew() + s.SchemaPath("parent_path").SetCustomSuppressDiff(common.WorkspacePathPrefixDiffSuppress).SetForceNew() // ConflictsWith fields s.SchemaPath("serialized_dashboard").SetConflictsWith([]string{"file_path"}) diff --git a/internal/acceptance/dashboard_test.go b/internal/acceptance/dashboard_test.go index 5fbf28b03a..49118c9455 100644 --- a/internal/acceptance/dashboard_test.go +++ b/internal/acceptance/dashboard_test.go @@ -58,7 +58,7 @@ resource "databricks_permissions" "dashboard_usage" { return templateString } -// Altough EmbedCredentials is an optional field, please specify its value if you want to modify it. +// Although EmbedCredentials is an optional field, please specify its value if you want to modify it. func (t *templateStruct) SetAttributes(mapper map[string]string) templateStruct { // Switch case for each attribute. If it is set in the mapper, set it in the struct if val, ok := mapper["display_name"]; ok { @@ -491,3 +491,19 @@ func TestAccDashboardTestAll(t *testing.T) { }), }) } + +func TestAccDashboardWithWorkspacePrefix(t *testing.T) { + var template templateStruct + + // Test that the dashboard can use a /Workspace prefix on the parent path and not trigger recreation. + // If this does NOT work, the test fails with an error that the non-refresh plan is non-empty. + + WorkspaceLevel(t, Step{ + Template: makeTemplate(template.SetAttributes(map[string]string{ + "display_name": fmt.Sprintf("Test Dashboard - %s", qa.RandomName()), + "warehouse_id": "{env.TEST_DEFAULT_WAREHOUSE_ID}", + "parent_path": "/Workspace/Shared/provider-test", + "serialized_dashboard": `{\"pages\":[{\"name\":\"new_name\",\"displayName\":\"New Page\"}]}`, + })), + }) +} From f757db0bf02fd32549e57fec49fc0e40125167f8 Mon Sep 17 00:00:00 2001 From: Cedric <23346008+840@users.noreply.github.com> Date: Wed, 2 Oct 2024 04:37:22 +0200 Subject: [PATCH 43/54] [Feature] Add `databricks_budget` resource (#3955) ## Changes Add support for account-level [Budget](https://docs.databricks.com/api/account/budgets) resource Example structure ``` resource "databricks_budget" "this" { display_name = "data-science-budget" alert_configurations { time_period = "MONTH" trigger_type = "CUMULATIVE_SPENDING_EXCEEDED" quantity_type = "LIST_PRICE_DOLLARS_USD" quantity_threshold = "840" action_configurations { action_type = "EMAIL_NOTIFICATION" target = "me@databricks.com" } } filter { workspace_id { operator = "IN" values = [ 1234567890098765 ] } tags { key = "Databricks" value { operator = "IN" values = ["Data Science"] } } } } ``` Resolves #3887 ## Tests - [x] `make test` run locally - [x] relevant change in `docs/` folder - [x] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [x] using Go SDK --------- Co-authored-by: Alex Ott --- docs/resources/budget.md | 103 ++++++++++++ finops/resource_budget.go | 102 ++++++++++++ finops/resource_budget_test.go | 243 +++++++++++++++++++++++++++++ internal/acceptance/budget_test.go | 57 +++++++ internal/providers/sdkv2/sdkv2.go | 2 + 5 files changed, 507 insertions(+) create mode 100644 docs/resources/budget.md create mode 100644 finops/resource_budget.go create mode 100644 finops/resource_budget_test.go create mode 100644 internal/acceptance/budget_test.go diff --git a/docs/resources/budget.md b/docs/resources/budget.md new file mode 100644 index 0000000000..3b99fa7c8a --- /dev/null +++ b/docs/resources/budget.md @@ -0,0 +1,103 @@ +--- +subcategory: "FinOps" +--- +# databricks_budget Resource + +-> **Note** Initialize provider with `alias = "account"`, and `host` pointing to the account URL, like, `host = "https://accounts.cloud.databricks.com"`. Use `provider = databricks.account` for all account-level resources. + +-> **Public Preview** This feature is in [Public Preview](https://docs.databricks.com/release-notes/release-types.html). + +This resource allows you to manage [Databricks Budgets](https://docs.databricks.com/en/admin/account-settings/budgets.html). + +## Example Usage + +```hcl +resource "databricks_budget" "this" { + display_name = "databricks-workspace-budget" + + alert_configurations { + time_period = "MONTH" + trigger_type = "CUMULATIVE_SPENDING_EXCEEDED" + quantity_type = "LIST_PRICE_DOLLARS_USD" + quantity_threshold = "840" + + action_configurations { + action_type = "EMAIL_NOTIFICATION" + target = "abc@gmail.com" + } + } + + filter { + workspace_id { + operator = "IN" + values = [ + 1234567890098765 + ] + } + + tags { + key = "Team" + value { + operator = "IN" + values = ["Data Science"] + } + } + + tags { + key = "Environment" + value { + operator = "IN" + values = ["Development"] + } + } + } +} +``` + +## Argument Reference + +The following arguments are available: + +* `display_name` - (Required) Name of the budget in Databricks Account. + +### alert_configurations Configuration Block (Required) + +* `time_period` - (Required, String Enum) The time window of usage data for the budget. (Enum: `MONTH`) +* `trigger_type` - (Required, String Enum) The evaluation method to determine when this budget alert is in a triggered state. (Enum: `CUMULATIVE_SPENDING_EXCEEDED`) +* `quantity_type` - (Required, String Enum) The way to calculate cost for this budget alert. This is what quantity_threshold is measured in. (Enum: `LIST_PRICE_DOLLARS_USD`) +* `quantity_threshold` - (Required, String) The threshold for the budget alert to determine if it is in a triggered state. The number is evaluated based on `quantity_type`. +* `action_configurations` - (Required) List of action configurations to take when the budget alert is triggered. Consists of the following fields: + * `action_type` - (Required, String Enum) The type of action to take when the budget alert is triggered. (Enum: `EMAIL_NOTIFICATION`) + * `target` - (Required, String) The target of the action. For `EMAIL_NOTIFICATION`, this is the email address to send the notification to. + +### filter Configuration Block (Optional) + +* `workspace_id` - (Optional) Filter by workspace ID (if empty, include usage all usage for this account). Consists of the following fields: + * `operator` - (Required, String Enum) The operator to use for the filter. (Enum: `IN`) + * `values` - (Required, List of numbers) The values to filter by. +* `tags` - (Optional) List of tags to filter by. Consists of the following fields: + * `key` - (Required, String) The key of the tag. + * `value` - (Required) Consists of the following fields: + * `operator` - (Required, String Enum) The operator to use for the filter. (Enum: `IN`) + * `values` - (Required, List of strings) The values to filter by. + +## Attribute Reference + +In addition to all arguments above, the following attributes are exported: + +* `budget_configuration_id` - The ID of the budget configuration. +* `account_id` - The ID of the Databricks Account. + +## Import + +This resource can be imported by Databricks account ID and Budget. + +```sh +terraform import databricks_budget.this '|' +``` + +## Related Resources + +The following resources are used in the context: + +* [databricks_mws_workspaces](mws_workspaces.md) to set up Databricks workspaces. diff --git a/finops/resource_budget.go b/finops/resource_budget.go new file mode 100644 index 0000000000..3213907929 --- /dev/null +++ b/finops/resource_budget.go @@ -0,0 +1,102 @@ +package finops + +import ( + "context" + "strings" + + "github.com/databricks/databricks-sdk-go/service/billing" + "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" +) + +func ResourceBudget() common.Resource { + s := common.StructToSchema(billing.BudgetConfiguration{}, func(m map[string]*schema.Schema) map[string]*schema.Schema { + common.CustomizeSchemaPath(m, "display_name").SetValidateFunc(validation.StringLenBetween(1, 128)) + for _, p := range []string{"account_id", "budget_configuration_id", "create_time", "update_time"} { + common.CustomizeSchemaPath(m, p).SetComputed() + } + common.CustomizeSchemaPath(m, "alert_configurations", "alert_configuration_id").SetComputed() + common.CustomizeSchemaPath(m, "alert_configurations", "action_configurations", "action_configuration_id").SetComputed() + // We need SuppressDiff because API returns a string representation of BigDecimal with a lot + // of trailing 0s, etc. + common.CustomizeSchemaPath(m, "alert_configurations", "quantity_threshold").SetCustomSuppressDiff(func(k, old, new string, d *schema.ResourceData) bool { + normalize := func(v string) string { + if strings.Contains(v, ".") { + v = strings.TrimRight(v, "0") + v = strings.TrimSuffix(v, ".") + } + return v + } + return normalize(old) == normalize(new) + }) + return m + }) + p := common.NewPairID("account_id", "budget_configuration_id") + return common.Resource{ + Create: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { + var create billing.CreateBudgetConfigurationBudget + common.DataToStructPointer(d, s, &create) + acc, err := c.AccountClient() + if err != nil { + return err + } + budget, err := acc.Budgets.Create(ctx, billing.CreateBudgetConfigurationRequest{Budget: create}) + if err != nil { + return err + } + d.Set("budget_configuration_id", budget.Budget.BudgetConfigurationId) + d.Set("account_id", c.Config.AccountID) + common.StructToData(budget.Budget, s, d) + p.Pack(d) + return nil + }, + Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { + _, id, err := p.Unpack(d) + if err != nil { + return err + } + acc, err := c.AccountClient() + if err != nil { + return err + } + budget, err := acc.Budgets.GetByBudgetId(ctx, id) + if err != nil { + return err + } + return common.StructToData(budget.Budget, s, d) + }, + Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { + var update billing.UpdateBudgetConfigurationBudget + _, id, err := p.Unpack(d) + if err != nil { + return err + } + common.DataToStructPointer(d, s, &update) + acc, err := c.AccountClient() + if err != nil { + return err + } + budget, err := acc.Budgets.Update(ctx, billing.UpdateBudgetConfigurationRequest{ + Budget: update, + BudgetId: id, + }) + if err != nil { + return err + } + return common.StructToData(budget.Budget, s, d) + }, + Delete: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { + _, id, err := p.Unpack(d) + if err != nil { + return err + } + acc, err := c.AccountClient() + if err != nil { + return err + } + return acc.Budgets.DeleteByBudgetId(ctx, id) + }, + Schema: s, + } +} diff --git a/finops/resource_budget_test.go b/finops/resource_budget_test.go new file mode 100644 index 0000000000..311397155c --- /dev/null +++ b/finops/resource_budget_test.go @@ -0,0 +1,243 @@ +package finops + +import ( + "fmt" + "testing" + + "github.com/databricks/databricks-sdk-go/experimental/mocks" + "github.com/databricks/databricks-sdk-go/service/billing" + "github.com/stretchr/testify/mock" + + "github.com/databricks/terraform-provider-databricks/qa" +) + +func getTestBudget() *billing.BudgetConfiguration { + return &billing.BudgetConfiguration{ + AccountId: "account_id", + AlertConfigurations: []billing.AlertConfiguration{ + { + ActionConfigurations: []billing.ActionConfiguration{ + { + ActionType: billing.ActionConfigurationTypeEmailNotification, + Target: "me@databricks.com", + }, + }, + QuantityThreshold: "840.840000000000000000", + QuantityType: billing.AlertConfigurationQuantityTypeListPriceDollarsUsd, + TimePeriod: billing.AlertConfigurationTimePeriodMonth, + TriggerType: billing.AlertConfigurationTriggerTypeCumulativeSpendingExceeded, + }, + }, + Filter: &billing.BudgetConfigurationFilter{ + Tags: []billing.BudgetConfigurationFilterTagClause{ + { + Key: "Environment", + Value: &billing.BudgetConfigurationFilterClause{ + Operator: billing.BudgetConfigurationFilterOperatorIn, + Values: []string{"Testing"}, + }, + }, + }, + WorkspaceId: &billing.BudgetConfigurationFilterWorkspaceIdClause{ + Operator: billing.BudgetConfigurationFilterOperatorIn, + Values: []int64{ + 1234567890098765, + }, + }, + }, + BudgetConfigurationId: "budget_configuration_id", + DisplayName: "budget_name", + } +} + +func TestResourceBudgetCreate(t *testing.T) { + qa.ResourceFixture{ + MockAccountClientFunc: func(a *mocks.MockAccountClient) { + api := a.GetMockbudgetsAPI().EXPECT() + api.Create(mock.Anything, billing.CreateBudgetConfigurationRequest{ + Budget: billing.CreateBudgetConfigurationBudget{ + AlertConfigurations: []billing.CreateBudgetConfigurationBudgetAlertConfigurations{ + { + ActionConfigurations: []billing.CreateBudgetConfigurationBudgetActionConfigurations{ + { + ActionType: getTestBudget().AlertConfigurations[0].ActionConfigurations[0].ActionType, + Target: getTestBudget().AlertConfigurations[0].ActionConfigurations[0].Target, + }, + }, + QuantityThreshold: "840.84", + QuantityType: getTestBudget().AlertConfigurations[0].QuantityType, + TimePeriod: getTestBudget().AlertConfigurations[0].TimePeriod, + TriggerType: getTestBudget().AlertConfigurations[0].TriggerType, + }, + }, + DisplayName: getTestBudget().DisplayName, + Filter: getTestBudget().Filter, + }, + }).Return(&billing.CreateBudgetConfigurationResponse{Budget: getTestBudget()}, nil) + api.GetByBudgetId(mock.Anything, "budget_configuration_id").Return( + &billing.GetBudgetConfigurationResponse{Budget: getTestBudget()}, nil, + ) + }, + Create: true, + AccountID: "account_id", + HCL: ` + display_name = "budget_name" + + alert_configurations { + time_period = "MONTH" + trigger_type = "CUMULATIVE_SPENDING_EXCEEDED" + quantity_type = "LIST_PRICE_DOLLARS_USD" + quantity_threshold = "840.84" + + action_configurations { + action_type = "EMAIL_NOTIFICATION" + target = "me@databricks.com" + } + } + + filter { + tags { + key = "Environment" + value { + operator = "IN" + values = ["Testing"] + } + } + + workspace_id { + operator = "IN" + values = [ + 1234567890098765 + ] + } + } + `, + Resource: ResourceBudget(), + }.ApplyAndExpectData(t, map[string]any{ + "display_name": "budget_name", + "id": "account_id|budget_configuration_id", + "alert_configurations.#": 1, + "filter.#": 1, + }) +} + +func TestResourceBudgetRead(t *testing.T) { + qa.ResourceFixture{ + MockAccountClientFunc: func(a *mocks.MockAccountClient) { + a.GetMockbudgetsAPI().EXPECT(). + GetByBudgetId(mock.Anything, "budget_configuration_id"). + Return(&billing.GetBudgetConfigurationResponse{Budget: getTestBudget()}, nil) + }, + Resource: ResourceBudget(), + Read: true, + New: true, + AccountID: "account_id", + ID: "account_id|budget_configuration_id", + }.ApplyAndExpectData(t, map[string]any{ + "display_name": "budget_name", + "id": "account_id|budget_configuration_id", + "alert_configurations.#": 1, + "filter.#": 1, + }) +} + +func TestResourceBudgetRead_UnpackError(t *testing.T) { + qa.ResourceFixture{ + Resource: ResourceBudget(), + Read: true, + New: true, + AccountID: "account_id", + ID: "budget_configuration_id", + }.ExpectError(t, "invalid ID: budget_configuration_id") +} + +func TestResourceBudgetUpdate(t *testing.T) { + qa.ResourceFixture{ + MockAccountClientFunc: func(a *mocks.MockAccountClient) { + api := a.GetMockbudgetsAPI().EXPECT() + api.Update(mock.Anything, billing.UpdateBudgetConfigurationRequest{ + Budget: billing.UpdateBudgetConfigurationBudget{ + AccountId: getTestBudget().AccountId, + AlertConfigurations: []billing.AlertConfiguration{ + { + ActionConfigurations: []billing.ActionConfiguration{ + { + ActionType: getTestBudget().AlertConfigurations[0].ActionConfigurations[0].ActionType, + Target: getTestBudget().AlertConfigurations[0].ActionConfigurations[0].Target, + }, + }, + QuantityThreshold: "840.84", + QuantityType: getTestBudget().AlertConfigurations[0].QuantityType, + TimePeriod: getTestBudget().AlertConfigurations[0].TimePeriod, + TriggerType: getTestBudget().AlertConfigurations[0].TriggerType, + }, + }, + BudgetConfigurationId: getTestBudget().BudgetConfigurationId, + DisplayName: fmt.Sprintf("%s_update", getTestBudget().DisplayName), + Filter: getTestBudget().Filter, + }, + BudgetId: "budget_configuration_id", + }).Return(&billing.UpdateBudgetConfigurationResponse{Budget: getTestBudget()}, nil) + api.GetByBudgetId(mock.Anything, "budget_configuration_id").Return( + &billing.GetBudgetConfigurationResponse{Budget: &billing.BudgetConfiguration{ + AccountId: getTestBudget().AccountId, + AlertConfigurations: getTestBudget().AlertConfigurations, + BudgetConfigurationId: getTestBudget().BudgetConfigurationId, + DisplayName: fmt.Sprintf("%s_update", getTestBudget().DisplayName), + Filter: getTestBudget().Filter, + }}, nil, + ) + }, + Resource: ResourceBudget(), + Update: true, + HCL: ` + display_name = "budget_name_update" + + alert_configurations { + time_period = "MONTH" + trigger_type = "CUMULATIVE_SPENDING_EXCEEDED" + quantity_type = "LIST_PRICE_DOLLARS_USD" + quantity_threshold = "840.84" + + action_configurations { + action_type = "EMAIL_NOTIFICATION" + target = "me@databricks.com" + } + } + + filter { + tags { + key = "Environment" + value { + operator = "IN" + values = ["Testing"] + } + } + + workspace_id { + operator = "IN" + values = [ + 1234567890098765 + ] + } + } + `, + AccountID: "account_id", + ID: "account_id|budget_configuration_id", + }.ApplyAndExpectData(t, map[string]any{ + "display_name": "budget_name_update", + "id": "account_id|budget_configuration_id", + }) +} + +func TestResourceBudgetDelete(t *testing.T) { + qa.ResourceFixture{ + MockAccountClientFunc: func(a *mocks.MockAccountClient) { + a.GetMockbudgetsAPI().EXPECT().DeleteByBudgetId(mock.Anything, "budget_configuration_id").Return(nil) + }, + Resource: ResourceBudget(), + AccountID: "account_id", + Delete: true, + ID: "account_id|budget_configuration_id", + }.ApplyAndExpectData(t, nil) +} diff --git a/internal/acceptance/budget_test.go b/internal/acceptance/budget_test.go new file mode 100644 index 0000000000..379ad84dc4 --- /dev/null +++ b/internal/acceptance/budget_test.go @@ -0,0 +1,57 @@ +package acceptance + +import ( + "fmt" + "testing" +) + +var ( + budgetTemplate = `resource "databricks_budget" "this" { + display_name = "tf-{var.RANDOM}" + + alert_configurations { + time_period = "MONTH" + trigger_type = "CUMULATIVE_SPENDING_EXCEEDED" + quantity_type = "LIST_PRICE_DOLLARS_USD" + quantity_threshold = "%s" + + action_configurations { + action_type = "EMAIL_NOTIFICATION" + target = "me@databricks.com" + } + } + + filter { + tags { + key = "Environment" + value { + operator = "IN" + values = ["Testing"] + } + } + + workspace_id { + operator = "IN" + values = [ + 1234567890098765 + ] + } + } + }` +) + +func TestMwsAccBudgetCreate(t *testing.T) { + loadAccountEnv(t) + AccountLevel(t, Step{ + Template: fmt.Sprintf(budgetTemplate, "840"), + }) +} + +func TestMwsAccBudgetUpdate(t *testing.T) { + loadAccountEnv(t) + AccountLevel(t, Step{ + Template: fmt.Sprintf(budgetTemplate, "840"), + }, Step{ + Template: fmt.Sprintf(budgetTemplate, "940"), + }) +} diff --git a/internal/providers/sdkv2/sdkv2.go b/internal/providers/sdkv2/sdkv2.go index b9ee686121..6d1b712cb0 100644 --- a/internal/providers/sdkv2/sdkv2.go +++ b/internal/providers/sdkv2/sdkv2.go @@ -29,6 +29,7 @@ import ( "github.com/databricks/terraform-provider-databricks/commands" "github.com/databricks/terraform-provider-databricks/common" "github.com/databricks/terraform-provider-databricks/dashboards" + "github.com/databricks/terraform-provider-databricks/finops" providercommon "github.com/databricks/terraform-provider-databricks/internal/providers/common" "github.com/databricks/terraform-provider-databricks/jobs" "github.com/databricks/terraform-provider-databricks/logger" @@ -131,6 +132,7 @@ func DatabricksProvider() *schema.Provider { "databricks_azure_adls_gen1_mount": storage.ResourceAzureAdlsGen1Mount().ToResource(), "databricks_azure_adls_gen2_mount": storage.ResourceAzureAdlsGen2Mount().ToResource(), "databricks_azure_blob_mount": storage.ResourceAzureBlobMount().ToResource(), + "databricks_budget": finops.ResourceBudget().ToResource(), "databricks_catalog": catalog.ResourceCatalog().ToResource(), "databricks_catalog_workspace_binding": catalog.ResourceCatalogWorkspaceBinding().ToResource(), "databricks_connection": catalog.ResourceConnection().ToResource(), From 1da7d9342ba758c865f6506b48ff9713ee0a2f78 Mon Sep 17 00:00:00 2001 From: Cedric <23346008+840@users.noreply.github.com> Date: Wed, 2 Oct 2024 15:29:53 +0200 Subject: [PATCH 44/54] [Feature] Add `databricks_mlflow_models` data source (#3874) ## Changes Add `databricks_mlflow_models` data source ## Tests Add integration and acceptance test - [x] `make test` run locally - [x] relevant change in `docs/` folder - [x] covered with integration tests in `internal/acceptance` - [x] relevant acceptance tests are passing - [x] using Go SDK Resolves #3791 --------- Co-authored-by: Alex Ott --- docs/data-sources/mlflow_models.md | 42 ++++++++++++++++++ .../acceptance/data_mlflow_models_test.go | 44 +++++++++++++++++++ internal/providers/sdkv2/sdkv2.go | 1 + mlflow/data_mlflow_models.go | 26 +++++++++++ mlflow/data_mlflow_models_test.go | 32 ++++++++++++++ 5 files changed, 145 insertions(+) create mode 100644 docs/data-sources/mlflow_models.md create mode 100644 internal/acceptance/data_mlflow_models_test.go create mode 100644 mlflow/data_mlflow_models.go create mode 100644 mlflow/data_mlflow_models_test.go diff --git a/docs/data-sources/mlflow_models.md b/docs/data-sources/mlflow_models.md new file mode 100644 index 0000000000..b8b67c9096 --- /dev/null +++ b/docs/data-sources/mlflow_models.md @@ -0,0 +1,42 @@ +--- +subcategory: "MLflow" +--- +# databricks_mlflow_models Data Source + +-> **Note** This data source could be only used with workspace-level provider! + +Retrieves a list of [databricks_mlflow_model](../resources/mlflow_model.md) objects, that were created by Terraform or manually, so that special handling could be applied. + +## Example Usage + +```hcl +data "databricks_mlflow_models" "this" {} + +output "model" { + value = data.databricks_mlflow_models.this +} +``` + +```hcl +data "databricks_mlflow_models" "this" {} + +check "model_list_not_empty" { + assert { + condition = length(data.databricks_mlflow_models.this.names) != 0 + error_message = "Model list is empty." + } +} + +check "model_list_contains_model" { + assert { + condition = contains(data.databricks_mlflow_models.this.names, "model_1") + error_message = "model_1 is missing in model list." + } +} +``` + +## Attribute Reference + +This data source exports the following attributes: + +* `names` - List of names of [databricks_mlflow_model](./mlflow_model.md) \ No newline at end of file diff --git a/internal/acceptance/data_mlflow_models_test.go b/internal/acceptance/data_mlflow_models_test.go new file mode 100644 index 0000000000..7cd13a2a02 --- /dev/null +++ b/internal/acceptance/data_mlflow_models_test.go @@ -0,0 +1,44 @@ +package acceptance + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/terraform" +) + +func TestAccDataMlflowModels(t *testing.T) { + WorkspaceLevel(t, + Step{ + Template: ` + resource "databricks_mlflow_model" "this" { + name = "model-{var.RANDOM}" + + description = "My MLflow model description" + + tags { + key = "key1" + value = "value1" + } + tags { + key = "key2" + value = "value2" + } + } + + data "databricks_mlflow_models" "this" { + depends_on = [databricks_mlflow_model.this] + }`, + Check: func(s *terraform.State) error { + r, ok := s.RootModule().Resources["data.databricks_mlflow_models.this"] + if !ok { + return fmt.Errorf("data not found in state") + } + names := r.Primary.Attributes["names.#"] + if names == "" { + return fmt.Errorf("names are empty: %v", r.Primary.Attributes) + } + return nil + }, + }) +} diff --git a/internal/providers/sdkv2/sdkv2.go b/internal/providers/sdkv2/sdkv2.go index 6d1b712cb0..65ab1f4973 100644 --- a/internal/providers/sdkv2/sdkv2.go +++ b/internal/providers/sdkv2/sdkv2.go @@ -100,6 +100,7 @@ func DatabricksProvider() *schema.Provider { "databricks_metastores": catalog.DataSourceMetastores().ToResource(), "databricks_mlflow_experiment": mlflow.DataSourceExperiment().ToResource(), "databricks_mlflow_model": mlflow.DataSourceModel().ToResource(), + "databricks_mlflow_models": mlflow.DataSourceModels().ToResource(), "databricks_mws_credentials": mws.DataSourceMwsCredentials().ToResource(), "databricks_mws_workspaces": mws.DataSourceMwsWorkspaces().ToResource(), "databricks_node_type": clusters.DataSourceNodeType().ToResource(), diff --git a/mlflow/data_mlflow_models.go b/mlflow/data_mlflow_models.go new file mode 100644 index 0000000000..96ce6bed05 --- /dev/null +++ b/mlflow/data_mlflow_models.go @@ -0,0 +1,26 @@ +package mlflow + +import ( + "context" + "github.com/databricks/databricks-sdk-go/service/ml" + + "github.com/databricks/databricks-sdk-go" + "github.com/databricks/terraform-provider-databricks/common" +) + +type modelsData struct { + Names []string `json:"names,omitempty" tf:"computed"` +} + +func DataSourceModels() common.Resource { + return common.WorkspaceData(func(ctx context.Context, data *modelsData, w *databricks.WorkspaceClient) error { + list, err := w.ModelRegistry.ListModelsAll(ctx, ml.ListModelsRequest{}) + if err != nil { + return err + } + for _, m := range list { + data.Names = append(data.Names, m.Name) + } + return nil + }) +} diff --git a/mlflow/data_mlflow_models_test.go b/mlflow/data_mlflow_models_test.go new file mode 100644 index 0000000000..b115ce9e23 --- /dev/null +++ b/mlflow/data_mlflow_models_test.go @@ -0,0 +1,32 @@ +package mlflow + +import ( + "github.com/databricks/databricks-sdk-go/experimental/mocks" + "github.com/stretchr/testify/mock" + "testing" + + "github.com/databricks/databricks-sdk-go/service/ml" + "github.com/databricks/terraform-provider-databricks/qa" +) + +func TestDataSourceModels(t *testing.T) { + qa.ResourceFixture{ + MockWorkspaceClientFunc: func(w *mocks.MockWorkspaceClient) { + api := w.GetMockModelRegistryAPI() + api.EXPECT().ListModelsAll(mock.Anything, ml.ListModelsRequest{}).Return([]ml.Model{ + { + Name: "model-01", + }, + { + Name: "model-02", + }, + }, nil) + }, + Read: true, + NonWritable: true, + Resource: DataSourceModels(), + ID: ".", + }.ApplyAndExpectData(t, map[string]interface{}{ + "names": []interface{}{"model-01", "model-02"}, + }) +} From ea7070f503d70ffe9f058965daa32f3e45106a9c Mon Sep 17 00:00:00 2001 From: Alex Ott Date: Thu, 3 Oct 2024 16:48:14 +0200 Subject: [PATCH 45/54] [Internal] Skip Budget tests on GCP (#4070) It looks like we have environment problem on CGP (manual tests are working), so let skip tests until we fix internal environments. ## Changes ## Tests - [ ] `make test` run locally - [ ] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [ ] using Go SDK --- internal/acceptance/budget_test.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/internal/acceptance/budget_test.go b/internal/acceptance/budget_test.go index 379ad84dc4..44b8262de9 100644 --- a/internal/acceptance/budget_test.go +++ b/internal/acceptance/budget_test.go @@ -42,6 +42,9 @@ var ( func TestMwsAccBudgetCreate(t *testing.T) { loadAccountEnv(t) + if isGcp(t) { + skipf(t)("not available on GCP") + } AccountLevel(t, Step{ Template: fmt.Sprintf(budgetTemplate, "840"), }) @@ -49,6 +52,9 @@ func TestMwsAccBudgetCreate(t *testing.T) { func TestMwsAccBudgetUpdate(t *testing.T) { loadAccountEnv(t) + if isGcp(t) { + skipf(t)("not available on GCP") + } AccountLevel(t, Step{ Template: fmt.Sprintf(budgetTemplate, "840"), }, Step{ From 481d460d635ee170a9284f20e611bd9604a8c90b Mon Sep 17 00:00:00 2001 From: Parth Bansal Date: Thu, 3 Oct 2024 18:10:24 +0200 Subject: [PATCH 46/54] [Internal] Update to latest OpenAPI spec and bump Go SDK (#4069) ## Changes Update to latest OpenAPI spec and Bump go sdk ## Tests - [ ] `make test` run locally - [ ] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [ ] using Go SDK --- .codegen/_openapi_sha | 2 +- go.mod | 2 +- go.sum | 4 +- internal/service/apps_tf/model.go | 59 ++++++++ internal/service/catalog_tf/model.go | 5 +- internal/service/dashboards_tf/model.go | 31 +++- internal/service/jobs_tf/model.go | 19 ++- internal/service/pipelines_tf/model.go | 12 ++ internal/service/sql_tf/model.go | 6 +- internal/service/workspace_tf/model.go | 186 +++++++++++++++--------- mlflow/data_mlflow_models.go | 1 + mlflow/data_mlflow_models_test.go | 3 +- repos/resource_git_credential.go | 10 +- repos/resource_git_credential_test.go | 22 +-- 14 files changed, 250 insertions(+), 112 deletions(-) diff --git a/.codegen/_openapi_sha b/.codegen/_openapi_sha index ffd6f58dd9..303c785539 100644 --- a/.codegen/_openapi_sha +++ b/.codegen/_openapi_sha @@ -1 +1 @@ -6f6b1371e640f2dfeba72d365ac566368656f6b6 \ No newline at end of file +0c86ea6dbd9a730c24ff0d4e509603e476955ac5 \ No newline at end of file diff --git a/go.mod b/go.mod index cb0d35a5ba..e01145f07e 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/databricks/terraform-provider-databricks go 1.22 require ( - github.com/databricks/databricks-sdk-go v0.47.0 + github.com/databricks/databricks-sdk-go v0.48.0 github.com/golang-jwt/jwt/v4 v4.5.0 github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 github.com/hashicorp/hcl v1.0.0 diff --git a/go.sum b/go.sum index 8ff73d7ad5..dfd13d335a 100644 --- a/go.sum +++ b/go.sum @@ -26,8 +26,8 @@ github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBS github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= -github.com/databricks/databricks-sdk-go v0.47.0 h1:eE7dN9axviL8+s10jnQAayOYDaR+Mfu7E9COGjO4lrQ= -github.com/databricks/databricks-sdk-go v0.47.0/go.mod h1:ds+zbv5mlQG7nFEU5ojLtgN/u0/9YzZmKQES/CfedzU= +github.com/databricks/databricks-sdk-go v0.48.0 h1:46KtsnRo+FGhC3izUXbpL0PXBNomvsdignYDhJZlm9s= +github.com/databricks/databricks-sdk-go v0.48.0/go.mod h1:ds+zbv5mlQG7nFEU5ojLtgN/u0/9YzZmKQES/CfedzU= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/internal/service/apps_tf/model.go b/internal/service/apps_tf/model.go index 74406307a5..41a6990157 100755 --- a/internal/service/apps_tf/model.go +++ b/internal/service/apps_tf/model.go @@ -25,6 +25,10 @@ type App struct { CreateTime types.String `tfsdk:"create_time" tf:"optional"` // The email of the user that created the app. Creator types.String `tfsdk:"creator" tf:"optional"` + // The default workspace file system path of the source code from which app + // deployment are created. This field tracks the workspace source code path + // of the last active deployment. + DefaultSourceCodePath types.String `tfsdk:"default_source_code_path" tf:"optional"` // The description of the app. Description types.String `tfsdk:"description" tf:"optional"` // The name of the app. The name must contain only lowercase alphanumeric @@ -32,6 +36,8 @@ type App struct { Name types.String `tfsdk:"name" tf:""` // The pending deployment of the app. PendingDeployment *AppDeployment `tfsdk:"pending_deployment" tf:"optional"` + // Resources for the app. + Resources []AppResource `tfsdk:"resources" tf:"optional"` ServicePrincipalId types.Int64 `tfsdk:"service_principal_id" tf:"optional"` @@ -134,6 +140,55 @@ type AppPermissionsRequest struct { AppName types.String `tfsdk:"-"` } +type AppResource struct { + // Description of the App Resource. + Description types.String `tfsdk:"description" tf:"optional"` + + Job *AppResourceJob `tfsdk:"job" tf:"optional"` + // Name of the App Resource. + Name types.String `tfsdk:"name" tf:""` + + Secret *AppResourceSecret `tfsdk:"secret" tf:"optional"` + + ServingEndpoint *AppResourceServingEndpoint `tfsdk:"serving_endpoint" tf:"optional"` + + SqlWarehouse *AppResourceSqlWarehouse `tfsdk:"sql_warehouse" tf:"optional"` +} + +type AppResourceJob struct { + // Id of the job to grant permission on. + Id types.String `tfsdk:"id" tf:""` + // Permissions to grant on the Job. Supported permissions are: "CAN_MANAGE", + // "IS_OWNER", "CAN_MANAGE_RUN", "CAN_VIEW". + Permission types.String `tfsdk:"permission" tf:""` +} + +type AppResourceSecret struct { + // Key of the secret to grant permission on. + Key types.String `tfsdk:"key" tf:""` + // Permission to grant on the secret scope. For secrets, only one permission + // is allowed. Permission must be one of: "READ", "WRITE", "MANAGE". + Permission types.String `tfsdk:"permission" tf:""` + // Scope of the secret to grant permission on. + Scope types.String `tfsdk:"scope" tf:""` +} + +type AppResourceServingEndpoint struct { + // Name of the serving endpoint to grant permission on. + Name types.String `tfsdk:"name" tf:""` + // Permission to grant on the serving endpoint. Supported permissions are: + // "CAN_MANAGE", "CAN_QUERY", "CAN_VIEW". + Permission types.String `tfsdk:"permission" tf:""` +} + +type AppResourceSqlWarehouse struct { + // Id of the SQL warehouse to grant permission on. + Id types.String `tfsdk:"id" tf:""` + // Permission to grant on the SQL warehouse. Supported permissions are: + // "CAN_MANAGE", "CAN_USE", "IS_OWNER". + Permission types.String `tfsdk:"permission" tf:""` +} + type ApplicationStatus struct { // Application status message Message types.String `tfsdk:"message" tf:"optional"` @@ -171,6 +226,8 @@ type CreateAppRequest struct { // The name of the app. The name must contain only lowercase alphanumeric // characters and hyphens. It must be unique within the workspace. Name types.String `tfsdk:"name" tf:""` + // Resources for the app. + Resources []AppResource `tfsdk:"resources" tf:"optional"` } // Delete an app @@ -259,4 +316,6 @@ type UpdateAppRequest struct { // The name of the app. The name must contain only lowercase alphanumeric // characters and hyphens. It must be unique within the workspace. Name types.String `tfsdk:"name" tf:""` + // Resources for the app. + Resources []AppResource `tfsdk:"resources" tf:"optional"` } diff --git a/internal/service/catalog_tf/model.go b/internal/service/catalog_tf/model.go index 78848824f1..358885d57d 100755 --- a/internal/service/catalog_tf/model.go +++ b/internal/service/catalog_tf/model.go @@ -1062,9 +1062,8 @@ type GenerateTemporaryTableCredentialResponse struct { // Azure temporary credentials for API authentication. Read more at // https://docs.microsoft.com/en-us/rest/api/storageservices/create-user-delegation-sas AzureUserDelegationSas *AzureUserDelegationSas `tfsdk:"azure_user_delegation_sas" tf:"optional"` - // Server time when the credential will expire, in unix epoch milliseconds - // since January 1, 1970 at 00:00:00 UTC. The API client is advised to cache - // the credential given this expiration time. + // Server time when the credential will expire, in epoch milliseconds. The + // API client is advised to cache the credential given this expiration time. ExpirationTime types.Int64 `tfsdk:"expiration_time" tf:"optional"` // GCP temporary credentials for API authentication. Read more at // https://developers.google.com/identity/protocols/oauth2/service-account diff --git a/internal/service/dashboards_tf/model.go b/internal/service/dashboards_tf/model.go index fcc9f0adf6..2fcdbdc14c 100755 --- a/internal/service/dashboards_tf/model.go +++ b/internal/service/dashboards_tf/model.go @@ -23,7 +23,12 @@ type CreateDashboardRequest struct { // Dashboards responses. ParentPath types.String `tfsdk:"parent_path" tf:"optional"` // The contents of the dashboard in serialized string form. This field is - // excluded in List Dashboards responses. + // excluded in List Dashboards responses. Use the [get dashboard API] to + // retrieve an example response, which includes the `serialized_dashboard` + // field. This field provides the structure of the JSON string that + // represents the dashboard's layout and components. + // + // [get dashboard API]: https://docs.databricks.com/api/workspace/lakeview/get SerializedDashboard types.String `tfsdk:"serialized_dashboard" tf:"optional"` // The warehouse ID used to run the dashboard. WarehouseId types.String `tfsdk:"warehouse_id" tf:"optional"` @@ -81,11 +86,17 @@ type Dashboard struct { // leading slash and no trailing slash. This field is excluded in List // Dashboards responses. ParentPath types.String `tfsdk:"parent_path" tf:"optional"` - // The workspace path of the dashboard asset, including the file name. This + // The workspace path of the dashboard asset, including the file name. + // Exported dashboards always have the file extension `.lvdash.json`. This // field is excluded in List Dashboards responses. Path types.String `tfsdk:"path" tf:"optional"` // The contents of the dashboard in serialized string form. This field is - // excluded in List Dashboards responses. + // excluded in List Dashboards responses. Use the [get dashboard API] to + // retrieve an example response, which includes the `serialized_dashboard` + // field. This field provides the structure of the JSON string that + // represents the dashboard's layout and components. + // + // [get dashboard API]: https://docs.databricks.com/api/workspace/lakeview/get SerializedDashboard types.String `tfsdk:"serialized_dashboard" tf:"optional"` // The timestamp of when the dashboard was last updated by the user. This // field is excluded in List Dashboards responses. @@ -213,9 +224,10 @@ type GenieMessage struct { // Genie space ID SpaceId types.String `tfsdk:"space_id" tf:""` // MesssageStatus. The possible values are: * `FETCHING_METADATA`: Fetching - // metadata from the data sources. * `ASKING_AI`: Waiting for the LLM to - // respond to the users question. * `EXECUTING_QUERY`: Executing AI provided - // SQL query. Get the SQL query result by calling + // metadata from the data sources. * `FILTERING_CONTEXT`: Running smart + // context step to determine relevant context. * `ASKING_AI`: Waiting for + // the LLM to respond to the users question. * `EXECUTING_QUERY`: Executing + // AI provided SQL query. Get the SQL query result by calling // [getMessageQueryResult](:method:genie/getMessageQueryResult) API. // **Important: The message status will stay in the `EXECUTING_QUERY` until // a client calls @@ -510,7 +522,12 @@ type UpdateDashboardRequest struct { // field is excluded in List Dashboards responses. Etag types.String `tfsdk:"etag" tf:"optional"` // The contents of the dashboard in serialized string form. This field is - // excluded in List Dashboards responses. + // excluded in List Dashboards responses. Use the [get dashboard API] to + // retrieve an example response, which includes the `serialized_dashboard` + // field. This field provides the structure of the JSON string that + // represents the dashboard's layout and components. + // + // [get dashboard API]: https://docs.databricks.com/api/workspace/lakeview/get SerializedDashboard types.String `tfsdk:"serialized_dashboard" tf:"optional"` // The warehouse ID used to run the dashboard. WarehouseId types.String `tfsdk:"warehouse_id" tf:"optional"` diff --git a/internal/service/jobs_tf/model.go b/internal/service/jobs_tf/model.go index 457ea2bb4a..2699dc2286 100755 --- a/internal/service/jobs_tf/model.go +++ b/internal/service/jobs_tf/model.go @@ -735,7 +735,8 @@ type JobDeployment struct { type JobEmailNotifications struct { // If true, do not send email to recipients specified in `on_failure` if the - // run is skipped. + // run is skipped. This field is `deprecated`. Please use the + // `notification_settings.no_alert_for_skipped_runs` field. NoAlertForSkippedRuns types.Bool `tfsdk:"no_alert_for_skipped_runs" tf:"optional"` // A list of email addresses to be notified when the duration of a run // exceeds the threshold specified for the `RUN_DURATION_SECONDS` metric in @@ -1274,7 +1275,7 @@ type RepairRun struct { // [Task parameter variables]: https://docs.databricks.com/jobs.html#parameter-variables // [dbutils.widgets.get]: https://docs.databricks.com/dev-tools/databricks-utils.html NotebookParams map[string]types.String `tfsdk:"notebook_params" tf:"optional"` - + // Controls whether the pipeline should perform a full refresh PipelineParams *PipelineParams `tfsdk:"pipeline_params" tf:"optional"` PythonNamedParams map[string]types.String `tfsdk:"python_named_params" tf:"optional"` @@ -1630,7 +1631,7 @@ type RunJobTask struct { // [Task parameter variables]: https://docs.databricks.com/jobs.html#parameter-variables // [dbutils.widgets.get]: https://docs.databricks.com/dev-tools/databricks-utils.html NotebookParams map[string]types.String `tfsdk:"notebook_params" tf:"optional"` - + // Controls whether the pipeline should perform a full refresh PipelineParams *PipelineParams `tfsdk:"pipeline_params" tf:"optional"` PythonNamedParams map[string]types.String `tfsdk:"python_named_params" tf:"optional"` @@ -1733,7 +1734,7 @@ type RunNow struct { // [Task parameter variables]: https://docs.databricks.com/jobs.html#parameter-variables // [dbutils.widgets.get]: https://docs.databricks.com/dev-tools/databricks-utils.html NotebookParams map[string]types.String `tfsdk:"notebook_params" tf:"optional"` - + // Controls whether the pipeline should perform a full refresh PipelineParams *PipelineParams `tfsdk:"pipeline_params" tf:"optional"` PythonNamedParams map[string]types.String `tfsdk:"python_named_params" tf:"optional"` @@ -1867,7 +1868,7 @@ type RunParameters struct { // [Task parameter variables]: https://docs.databricks.com/jobs.html#parameter-variables // [dbutils.widgets.get]: https://docs.databricks.com/dev-tools/databricks-utils.html NotebookParams map[string]types.String `tfsdk:"notebook_params" tf:"optional"` - + // Controls whether the pipeline should perform a full refresh PipelineParams *PipelineParams `tfsdk:"pipeline_params" tf:"optional"` PythonNamedParams map[string]types.String `tfsdk:"python_named_params" tf:"optional"` @@ -2613,7 +2614,8 @@ type TaskDependency struct { type TaskEmailNotifications struct { // If true, do not send email to recipients specified in `on_failure` if the - // run is skipped. + // run is skipped. This field is `deprecated`. Please use the + // `notification_settings.no_alert_for_skipped_runs` field. NoAlertForSkippedRuns types.Bool `tfsdk:"no_alert_for_skipped_runs" tf:"optional"` // A list of email addresses to be notified when the duration of a run // exceeds the threshold specified for the `RUN_DURATION_SECONDS` metric in @@ -2662,8 +2664,9 @@ type TaskNotificationSettings struct { type TerminationDetails struct { // The code indicates why the run was terminated. Additional codes might be // introduced in future releases. * `SUCCESS`: The run was completed - // successfully. * `CANCELED`: The run was canceled during execution by the - // Databricks platform; for example, if the maximum run duration was + // successfully. * `USER_CANCELED`: The run was successfully canceled during + // execution by a user. * `CANCELED`: The run was canceled during execution + // by the Databricks platform; for example, if the maximum run duration was // exceeded. * `SKIPPED`: Run was never executed, for example, if the // upstream task run failed, the dependency type condition was not met, or // there were no material tasks to execute. * `INTERNAL_ERROR`: The run diff --git a/internal/service/pipelines_tf/model.go b/internal/service/pipelines_tf/model.go index b6abbbb71c..1740d0ee0b 100755 --- a/internal/service/pipelines_tf/model.go +++ b/internal/service/pipelines_tf/model.go @@ -60,6 +60,10 @@ type CreatePipeline struct { Notifications []Notifications `tfsdk:"notifications" tf:"optional"` // Whether Photon is enabled for this pipeline. Photon types.Bool `tfsdk:"photon" tf:"optional"` + // The default schema (database) where tables are read from or published to. + // The presence of this field implies that the pipeline is in direct + // publishing mode. + Schema types.String `tfsdk:"schema" tf:"optional"` // Whether serverless compute is enabled for this pipeline. Serverless types.Bool `tfsdk:"serverless" tf:"optional"` // DBFS root directory for storing checkpoints and tables. @@ -150,6 +154,10 @@ type EditPipeline struct { Photon types.Bool `tfsdk:"photon" tf:"optional"` // Unique identifier for this pipeline. PipelineId types.String `tfsdk:"pipeline_id" tf:"optional"` + // The default schema (database) where tables are read from or published to. + // The presence of this field implies that the pipeline is in direct + // publishing mode. + Schema types.String `tfsdk:"schema" tf:"optional"` // Whether serverless compute is enabled for this pipeline. Serverless types.Bool `tfsdk:"serverless" tf:"optional"` // DBFS root directory for storing checkpoints and tables. @@ -687,6 +695,10 @@ type PipelineSpec struct { Notifications []Notifications `tfsdk:"notifications" tf:"optional"` // Whether Photon is enabled for this pipeline. Photon types.Bool `tfsdk:"photon" tf:"optional"` + // The default schema (database) where tables are read from or published to. + // The presence of this field implies that the pipeline is in direct + // publishing mode. + Schema types.String `tfsdk:"schema" tf:"optional"` // Whether serverless compute is enabled for this pipeline. Serverless types.Bool `tfsdk:"serverless" tf:"optional"` // DBFS root directory for storing checkpoints and tables. diff --git a/internal/service/sql_tf/model.go b/internal/service/sql_tf/model.go index cbee45561b..e912363c30 100755 --- a/internal/service/sql_tf/model.go +++ b/internal/service/sql_tf/model.go @@ -194,6 +194,8 @@ type CancelExecutionRequest struct { type CancelExecutionResponse struct { } +// Configures the channel name and DBSQL version of the warehouse. +// CHANNEL_NAME_CUSTOM should be chosen only when `dbsql_version` is specified. type Channel struct { DbsqlVersion types.String `tfsdk:"dbsql_version" tf:"optional"` @@ -347,7 +349,9 @@ type CreateWarehouseRequest struct { // The amount of time in minutes that a SQL warehouse must be idle (i.e., no // RUNNING queries) before it is automatically stopped. // - // Supported values: - Must be == 0 or >= 10 mins - 0 indicates no autostop. + // Supported values: - Must be >= 0 mins for serverless warehouses - Must be + // == 0 or >= 10 mins for non-serverless warehouses - 0 indicates no + // autostop. // // Defaults to 120 mins AutoStopMins types.Int64 `tfsdk:"auto_stop_mins" tf:"optional"` diff --git a/internal/service/workspace_tf/model.go b/internal/service/workspace_tf/model.go index d11553b3a0..fe451acf89 100755 --- a/internal/service/workspace_tf/model.go +++ b/internal/service/workspace_tf/model.go @@ -29,11 +29,11 @@ type AzureKeyVaultSecretScopeMetadata struct { ResourceId types.String `tfsdk:"resource_id" tf:""` } -type CreateCredentials struct { +type CreateCredentialsRequest struct { // Git provider. This field is case-insensitive. The available Git providers - // are gitHub, bitbucketCloud, gitLab, azureDevOpsServices, - // gitHubEnterprise, bitbucketServer, gitLabEnterpriseEdition and - // awsCodeCommit. + // are `gitHub`, `bitbucketCloud`, `gitLab`, `azureDevOpsServices`, + // `gitHubEnterprise`, `bitbucketServer`, `gitLabEnterpriseEdition` and + // `awsCodeCommit`. GitProvider types.String `tfsdk:"git_provider" tf:""` // The username or email provided with your Git provider account, depending // on which provider you are using. For GitHub, GitHub Enterprise Server, or @@ -45,8 +45,7 @@ type CreateCredentials struct { GitUsername types.String `tfsdk:"git_username" tf:"optional"` // The personal access token used to authenticate to the corresponding Git // provider. For certain providers, support may exist for other types of - // scoped access tokens. [Learn more]. The personal access token used to - // authenticate to the corresponding Git + // scoped access tokens. [Learn more]. // // [Learn more]: https://docs.databricks.com/repos/get-access-tokens-from-git-provider.html PersonalAccessToken types.String `tfsdk:"personal_access_token" tf:"optional"` @@ -54,31 +53,23 @@ type CreateCredentials struct { type CreateCredentialsResponse struct { // ID of the credential object in the workspace. - CredentialId types.Int64 `tfsdk:"credential_id" tf:"optional"` - // Git provider. This field is case-insensitive. The available Git providers - // are gitHub, bitbucketCloud, gitLab, azureDevOpsServices, - // gitHubEnterprise, bitbucketServer, gitLabEnterpriseEdition and - // awsCodeCommit. - GitProvider types.String `tfsdk:"git_provider" tf:"optional"` - // The username or email provided with your Git provider account, depending - // on which provider you are using. For GitHub, GitHub Enterprise Server, or - // Azure DevOps Services, either email or username may be used. For GitLab, - // GitLab Enterprise Edition, email must be used. For AWS CodeCommit, - // BitBucket or BitBucket Server, username must be used. For all other - // providers please see your provider's Personal Access Token authentication - // documentation to see what is supported. + CredentialId types.Int64 `tfsdk:"credential_id" tf:""` + // The Git provider associated with the credential. + GitProvider types.String `tfsdk:"git_provider" tf:""` + // The username or email provided with your Git provider account and + // associated with the credential. GitUsername types.String `tfsdk:"git_username" tf:"optional"` } -type CreateRepo struct { +type CreateRepoRequest struct { // Desired path for the repo in the workspace. Almost any path in the - // workspace can be chosen. If repo is created in /Repos, path must be in - // the format /Repos/{folder}/{repo-name}. + // workspace can be chosen. If repo is created in `/Repos`, path must be in + // the format `/Repos/{folder}/{repo-name}`. Path types.String `tfsdk:"path" tf:"optional"` // Git provider. This field is case-insensitive. The available Git providers - // are gitHub, bitbucketCloud, gitLab, azureDevOpsServices, - // gitHubEnterprise, bitbucketServer, gitLabEnterpriseEdition and - // awsCodeCommit. + // are `gitHub`, `bitbucketCloud`, `gitLab`, `azureDevOpsServices`, + // `gitHubEnterprise`, `bitbucketServer`, `gitLabEnterpriseEdition` and + // `awsCodeCommit`. Provider types.String `tfsdk:"provider" tf:""` // If specified, the repo will be created with sparse checkout enabled. You // cannot enable/disable sparse checkout after the repo is created. @@ -87,6 +78,24 @@ type CreateRepo struct { Url types.String `tfsdk:"url" tf:""` } +type CreateRepoResponse struct { + // Branch that the Git folder (repo) is checked out to. + Branch types.String `tfsdk:"branch" tf:"optional"` + // SHA-1 hash representing the commit ID of the current HEAD of the Git + // folder (repo). + HeadCommitId types.String `tfsdk:"head_commit_id" tf:"optional"` + // ID of the Git folder (repo) object in the workspace. + Id types.Int64 `tfsdk:"id" tf:"optional"` + // Path of the Git folder (repo) in the workspace. + Path types.String `tfsdk:"path" tf:"optional"` + // Git provider of the linked Git repository. + Provider types.String `tfsdk:"provider" tf:"optional"` + // Sparse checkout settings for the Git folder (repo). + SparseCheckout *SparseCheckout `tfsdk:"sparse_checkout" tf:"optional"` + // URL of the linked Git repository. + Url types.String `tfsdk:"url" tf:"optional"` +} + type CreateScope struct { // The metadata for the secret scope if the type is `AZURE_KEYVAULT` BackendAzureKeyvault *AzureKeyVaultSecretScopeMetadata `tfsdk:"backend_azure_keyvault" tf:"optional"` @@ -105,19 +114,11 @@ type CreateScopeResponse struct { type CredentialInfo struct { // ID of the credential object in the workspace. - CredentialId types.Int64 `tfsdk:"credential_id" tf:"optional"` - // Git provider. This field is case-insensitive. The available Git providers - // are gitHub, gitHubOAuth, bitbucketCloud, gitLab, azureDevOpsServices, - // gitHubEnterprise, bitbucketServer, gitLabEnterpriseEdition and - // awsCodeCommit. + CredentialId types.Int64 `tfsdk:"credential_id" tf:""` + // The Git provider associated with the credential. GitProvider types.String `tfsdk:"git_provider" tf:"optional"` - // The username or email provided with your Git provider account, depending - // on which provider you are using. For GitHub, GitHub Enterprise Server, or - // Azure DevOps Services, either email or username may be used. For GitLab, - // GitLab Enterprise Edition, email must be used. For AWS CodeCommit, - // BitBucket or BitBucket Server, username must be used. For all other - // providers please see your provider's Personal Access Token authentication - // documentation to see what is supported. + // The username or email provided with your Git provider account and + // associated with the credential. GitUsername types.String `tfsdk:"git_username" tf:"optional"` } @@ -142,17 +143,23 @@ type DeleteAclResponse struct { } // Delete a credential -type DeleteGitCredentialRequest struct { +type DeleteCredentialsRequest struct { // The ID for the corresponding credential to access. CredentialId types.Int64 `tfsdk:"-"` } +type DeleteCredentialsResponse struct { +} + // Delete a repo type DeleteRepoRequest struct { - // The ID for the corresponding repo to access. + // ID of the Git folder (repo) object in the workspace. RepoId types.Int64 `tfsdk:"-"` } +type DeleteRepoResponse struct { +} + type DeleteResponse struct { } @@ -212,16 +219,22 @@ type GetAclRequest struct { Scope types.String `tfsdk:"-"` } -type GetCredentialsResponse struct { - Credentials []CredentialInfo `tfsdk:"credentials" tf:"optional"` -} - // Get a credential entry -type GetGitCredentialRequest struct { +type GetCredentialsRequest struct { // The ID for the corresponding credential to access. CredentialId types.Int64 `tfsdk:"-"` } +type GetCredentialsResponse struct { + // ID of the credential object in the workspace. + CredentialId types.Int64 `tfsdk:"credential_id" tf:""` + // The Git provider associated with the credential. + GitProvider types.String `tfsdk:"git_provider" tf:"optional"` + // The username or email provided with your Git provider account and + // associated with the credential. + GitUsername types.String `tfsdk:"git_username" tf:"optional"` +} + // Get repo permission levels type GetRepoPermissionLevelsRequest struct { // The repo for which to get or manage permissions. @@ -241,10 +254,27 @@ type GetRepoPermissionsRequest struct { // Get a repo type GetRepoRequest struct { - // The ID for the corresponding repo to access. + // ID of the Git folder (repo) object in the workspace. RepoId types.Int64 `tfsdk:"-"` } +type GetRepoResponse struct { + // Branch that the local version of the repo is checked out to. + Branch types.String `tfsdk:"branch" tf:"optional"` + // SHA-1 hash representing the commit ID of the current HEAD of the repo. + HeadCommitId types.String `tfsdk:"head_commit_id" tf:"optional"` + // ID of the Git folder (repo) object in the workspace. + Id types.Int64 `tfsdk:"id" tf:"optional"` + // Path of the Git folder (repo) in the workspace. + Path types.String `tfsdk:"path" tf:"optional"` + // Git provider of the linked Git repository. + Provider types.String `tfsdk:"provider" tf:"optional"` + // Sparse checkout settings for the Git folder (repo). + SparseCheckout *SparseCheckout `tfsdk:"sparse_checkout" tf:"optional"` + // URL of the linked Git repository. + Url types.String `tfsdk:"url" tf:"optional"` +} + // Get a secret type GetSecretRequest struct { // The key to fetch secret for. @@ -334,6 +364,11 @@ type ListAclsResponse struct { Items []AclItem `tfsdk:"items" tf:"optional"` } +type ListCredentialsResponse struct { + // List of credentials. + Credentials []CredentialInfo `tfsdk:"credentials" tf:"optional"` +} + // Get repos type ListReposRequest struct { // Token used to get the next page of results. If not specified, returns the @@ -341,15 +376,16 @@ type ListReposRequest struct { // results. NextPageToken types.String `tfsdk:"-"` // Filters repos that have paths starting with the given path prefix. If not - // provided repos from /Repos will be served. + // provided or when provided an effectively empty prefix (`/` or + // `/Workspace`) Git folders (repos) from `/Workspace/Repos` will be served. PathPrefix types.String `tfsdk:"-"` } type ListReposResponse struct { - // Token that can be specified as a query parameter to the GET /repos + // Token that can be specified as a query parameter to the `GET /repos` // endpoint to retrieve the next page of results. NextPageToken types.String `tfsdk:"next_page_token" tf:"optional"` - + // List of Git folders (repos). Repos []RepoInfo `tfsdk:"repos" tf:"optional"` } @@ -467,25 +503,21 @@ type RepoAccessControlResponse struct { UserName types.String `tfsdk:"user_name" tf:"optional"` } +// Git folder (repo) information. type RepoInfo struct { - // Branch that the local version of the repo is checked out to. + // Name of the current git branch of the git folder (repo). Branch types.String `tfsdk:"branch" tf:"optional"` - // SHA-1 hash representing the commit ID of the current HEAD of the repo. + // Current git commit id of the git folder (repo). HeadCommitId types.String `tfsdk:"head_commit_id" tf:"optional"` - // ID of the repo object in the workspace. + // Id of the git folder (repo) in the Workspace. Id types.Int64 `tfsdk:"id" tf:"optional"` - // Desired path for the repo in the workspace. Almost any path in the - // workspace can be chosen. If repo is created in /Repos, path must be in - // the format /Repos/{folder}/{repo-name}. + // Root path of the git folder (repo) in the Workspace. Path types.String `tfsdk:"path" tf:"optional"` - // Git provider. This field is case-insensitive. The available Git providers - // are gitHub, bitbucketCloud, gitLab, azureDevOpsServices, - // gitHubEnterprise, bitbucketServer, gitLabEnterpriseEdition and - // awsCodeCommit. + // Git provider of the remote git repository, e.g. `gitHub`. Provider types.String `tfsdk:"provider" tf:"optional"` - + // Sparse checkout config for the git folder (repo). SparseCheckout *SparseCheckout `tfsdk:"sparse_checkout" tf:"optional"` - // URL of the Git repository to be linked. + // URL of the remote git repository. Url types.String `tfsdk:"url" tf:"optional"` } @@ -533,24 +565,32 @@ type SecretScope struct { Name types.String `tfsdk:"name" tf:"optional"` } +// Sparse checkout configuration, it contains options like cone patterns. type SparseCheckout struct { - // List of patterns to include for sparse checkout. + // List of sparse checkout cone patterns, see [cone mode handling] for + // details. + // + // [cone mode handling]: https://git-scm.com/docs/git-sparse-checkout#_internalscone_mode_handling Patterns []types.String `tfsdk:"patterns" tf:"optional"` } +// Sparse checkout configuration, it contains options like cone patterns. type SparseCheckoutUpdate struct { - // List of patterns to include for sparse checkout. + // List of sparse checkout cone patterns, see [cone mode handling] for + // details. + // + // [cone mode handling]: https://git-scm.com/docs/git-sparse-checkout#_internalscone_mode_handling Patterns []types.String `tfsdk:"patterns" tf:"optional"` } -type UpdateCredentials struct { +type UpdateCredentialsRequest struct { // The ID for the corresponding credential to access. CredentialId types.Int64 `tfsdk:"-"` // Git provider. This field is case-insensitive. The available Git providers - // are gitHub, bitbucketCloud, gitLab, azureDevOpsServices, - // gitHubEnterprise, bitbucketServer, gitLabEnterpriseEdition and - // awsCodeCommit. - GitProvider types.String `tfsdk:"git_provider" tf:"optional"` + // are `gitHub`, `bitbucketCloud`, `gitLab`, `azureDevOpsServices`, + // `gitHubEnterprise`, `bitbucketServer`, `gitLabEnterpriseEdition` and + // `awsCodeCommit`. + GitProvider types.String `tfsdk:"git_provider" tf:""` // The username or email provided with your Git provider account, depending // on which provider you are using. For GitHub, GitHub Enterprise Server, or // Azure DevOps Services, either email or username may be used. For GitLab, @@ -561,17 +601,19 @@ type UpdateCredentials struct { GitUsername types.String `tfsdk:"git_username" tf:"optional"` // The personal access token used to authenticate to the corresponding Git // provider. For certain providers, support may exist for other types of - // scoped access tokens. [Learn more]. The personal access token used to - // authenticate to the corresponding Git + // scoped access tokens. [Learn more]. // // [Learn more]: https://docs.databricks.com/repos/get-access-tokens-from-git-provider.html PersonalAccessToken types.String `tfsdk:"personal_access_token" tf:"optional"` } -type UpdateRepo struct { +type UpdateCredentialsResponse struct { +} + +type UpdateRepoRequest struct { // Branch that the local version of the repo is checked out to. Branch types.String `tfsdk:"branch" tf:"optional"` - // The ID for the corresponding repo to access. + // ID of the Git folder (repo) object in the workspace. RepoId types.Int64 `tfsdk:"-"` // If specified, update the sparse checkout settings. The update will fail // if sparse checkout is not enabled for the repo. @@ -583,7 +625,7 @@ type UpdateRepo struct { Tag types.String `tfsdk:"tag" tf:"optional"` } -type UpdateResponse struct { +type UpdateRepoResponse struct { } type WorkspaceObjectAccessControlRequest struct { diff --git a/mlflow/data_mlflow_models.go b/mlflow/data_mlflow_models.go index 96ce6bed05..127b4f465f 100644 --- a/mlflow/data_mlflow_models.go +++ b/mlflow/data_mlflow_models.go @@ -2,6 +2,7 @@ package mlflow import ( "context" + "github.com/databricks/databricks-sdk-go/service/ml" "github.com/databricks/databricks-sdk-go" diff --git a/mlflow/data_mlflow_models_test.go b/mlflow/data_mlflow_models_test.go index b115ce9e23..04ff88be8d 100644 --- a/mlflow/data_mlflow_models_test.go +++ b/mlflow/data_mlflow_models_test.go @@ -1,9 +1,10 @@ package mlflow import ( + "testing" + "github.com/databricks/databricks-sdk-go/experimental/mocks" "github.com/stretchr/testify/mock" - "testing" "github.com/databricks/databricks-sdk-go/service/ml" "github.com/databricks/terraform-provider-databricks/qa" diff --git a/repos/resource_git_credential.go b/repos/resource_git_credential.go index 38f7b94044..9858ff9683 100644 --- a/repos/resource_git_credential.go +++ b/repos/resource_git_credential.go @@ -12,7 +12,7 @@ import ( ) func ResourceGitCredential() common.Resource { - s := common.StructToSchema(workspace.CreateCredentials{}, func(s map[string]*schema.Schema) map[string]*schema.Schema { + s := common.StructToSchema(workspace.CreateCredentialsRequest{}, func(s map[string]*schema.Schema) map[string]*schema.Schema { s["force"] = &schema.Schema{ Type: schema.TypeBool, Optional: true, @@ -34,7 +34,7 @@ func ResourceGitCredential() common.Resource { return err } - var req workspace.CreateCredentials + var req workspace.CreateCredentialsRequest common.DataToStructPointer(d, s, &req) resp, err := w.GitCredentials.Create(ctx, req) @@ -49,7 +49,7 @@ func ResourceGitCredential() common.Resource { if len(creds) != 1 { return fmt.Errorf("list of credentials is either empty or have more than one entry (%d)", len(creds)) } - var req workspace.UpdateCredentials + var req workspace.UpdateCredentialsRequest common.DataToStructPointer(d, s, &req) req.CredentialId = creds[0].CredentialId @@ -71,7 +71,7 @@ func ResourceGitCredential() common.Resource { if err != nil { return err } - resp, err := w.GitCredentials.Get(ctx, workspace.GetGitCredentialRequest{CredentialId: cred_id}) + resp, err := w.GitCredentials.Get(ctx, workspace.GetCredentialsRequest{CredentialId: cred_id}) if err != nil { return err } @@ -80,7 +80,7 @@ func ResourceGitCredential() common.Resource { return nil }, Update: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { - var req workspace.UpdateCredentials + var req workspace.UpdateCredentialsRequest common.DataToStructPointer(d, s, &req) cred_id, err := strconv.ParseInt(d.Id(), 10, 64) diff --git a/repos/resource_git_credential_test.go b/repos/resource_git_credential_test.go index 911a48eeb0..1a64cf273c 100644 --- a/repos/resource_git_credential_test.go +++ b/repos/resource_git_credential_test.go @@ -85,7 +85,7 @@ func TestResourceGitCredentialUpdate(t *testing.T) { { Method: "PATCH", Resource: fmt.Sprintf("/api/2.0/git-credentials/%d", credID), - ExpectedRequest: workspace.UpdateCredentials{ + ExpectedRequest: workspace.UpdateCredentialsRequest{ CredentialId: int64(credID), GitProvider: provider, GitUsername: user, @@ -125,7 +125,7 @@ func TestResourceGitCredentialUpdate_Error(t *testing.T) { { Method: "PATCH", Resource: fmt.Sprintf("/api/2.0/git-credentials/%d", credID), - ExpectedRequest: workspace.UpdateCredentials{ + ExpectedRequest: workspace.UpdateCredentialsRequest{ CredentialId: int64(credID), GitProvider: provider, GitUsername: user, @@ -168,7 +168,7 @@ func TestResourceGitCredentialCreate(t *testing.T) { { Method: "POST", Resource: "/api/2.0/git-credentials", - ExpectedRequest: workspace.CreateCredentials{ + ExpectedRequest: workspace.CreateCredentialsRequest{ GitProvider: provider, GitUsername: user, PersonalAccessToken: token, @@ -200,7 +200,7 @@ func TestResourceGitCredentialCreate_Error(t *testing.T) { { Method: "POST", Resource: "/api/2.0/git-credentials", - ExpectedRequest: workspace.CreateCredentials{ + ExpectedRequest: workspace.CreateCredentialsRequest{ GitProvider: provider, GitUsername: user, PersonalAccessToken: token, @@ -236,7 +236,7 @@ func TestResourceGitCredentialCreateWithForce(t *testing.T) { { Method: "POST", Resource: "/api/2.0/git-credentials", - ExpectedRequest: workspace.CreateCredentials{ + ExpectedRequest: workspace.CreateCredentialsRequest{ GitProvider: provider, GitUsername: user, PersonalAccessToken: token, @@ -250,14 +250,14 @@ func TestResourceGitCredentialCreateWithForce(t *testing.T) { { Method: http.MethodGet, Resource: "/api/2.0/git-credentials", - Response: workspace.GetCredentialsResponse{ + Response: workspace.ListCredentialsResponse{ Credentials: []workspace.CredentialInfo{resp}, }, }, { Method: http.MethodPatch, Resource: fmt.Sprintf("/api/2.0/git-credentials/%d", resp.CredentialId), - ExpectedRequest: workspace.UpdateCredentials{ + ExpectedRequest: workspace.UpdateCredentialsRequest{ CredentialId: resp.CredentialId, GitProvider: provider, GitUsername: user, @@ -291,7 +291,7 @@ func TestResourceGitCredentialCreateWithForce_Error_List(t *testing.T) { { Method: "POST", Resource: "/api/2.0/git-credentials", - ExpectedRequest: workspace.CreateCredentials{ + ExpectedRequest: workspace.CreateCredentialsRequest{ GitProvider: provider, GitUsername: user, PersonalAccessToken: token, @@ -332,7 +332,7 @@ func TestResourceGitCredentialCreateWithForce_ErrorEmptyList(t *testing.T) { { Method: "POST", Resource: "/api/2.0/git-credentials", - ExpectedRequest: workspace.CreateCredentials{ + ExpectedRequest: workspace.CreateCredentialsRequest{ GitProvider: provider, GitUsername: user, PersonalAccessToken: token, @@ -374,7 +374,7 @@ func TestResourceGitCredentialCreateWithForce_ErrorUpdate(t *testing.T) { { Method: "POST", Resource: "/api/2.0/git-credentials", - ExpectedRequest: workspace.CreateCredentials{ + ExpectedRequest: workspace.CreateCredentialsRequest{ GitProvider: provider, GitUsername: user, PersonalAccessToken: token, @@ -388,7 +388,7 @@ func TestResourceGitCredentialCreateWithForce_ErrorUpdate(t *testing.T) { { Method: http.MethodGet, Resource: "/api/2.0/git-credentials", - Response: workspace.GetCredentialsResponse{ + Response: workspace.ListCredentialsResponse{ Credentials: []workspace.CredentialInfo{resp}, }, }, From 7d0491f6e9fa30295bb88771d22af096354bde52 Mon Sep 17 00:00:00 2001 From: Parth Bansal Date: Fri, 4 Oct 2024 11:51:42 +0200 Subject: [PATCH 47/54] [Fix] Fix Permissions Dashboard Test (#4071) ## Changes It seems like we need to specify the `serialized_dashboard` field to be able to create the dashboard. I have raised this concern with the responsible team. But for unblocking our integration tests we can specify this for now. ## Tests Integration Tests Passing - [x] `make test` run locally - [x] covered with integration tests in `internal/acceptance` - [x] relevant acceptance tests are passing --- internal/acceptance/permissions_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/acceptance/permissions_test.go b/internal/acceptance/permissions_test.go index 1386ee9db4..bcd67fa8c9 100644 --- a/internal/acceptance/permissions_test.go +++ b/internal/acceptance/permissions_test.go @@ -722,6 +722,7 @@ func TestAccPermissions_Dashboard(t *testing.T) { display_name = "TF New Dashboard" warehouse_id = "{env.TEST_DEFAULT_WAREHOUSE_ID}" parent_path = databricks_directory.this.path + serialized_dashboard = "{\"pages\":[{\"name\":\"b532570b\",\"displayName\":\"New Page\"}]}" } ` WorkspaceLevel(t, Step{ From 60b8a6ffca1fdd540424acba3e26464a8168ca41 Mon Sep 17 00:00:00 2001 From: Tanmay Rustagi <88379306+tanmay-db@users.noreply.github.com> Date: Fri, 4 Oct 2024 14:36:52 +0200 Subject: [PATCH 48/54] [Fix] Set ID for online table resource if creation succeeds but it isn't available yet (#4072) ## Changes We should set the id right after creation and before waiting for online table to be available. This is because in case when online table isn't available, we still should have that resource in the state. Also the timeout has been increased to 2x (I am going to following up with online tables team for suitable timeout but since we have to do a release, going ahead with small time increase should be good) Note: We should add setting id right after creation for similar resources to CONTRIBUTING guide (which I will do in a separate PR) ## Tests Added unit test to check that pathway, id is set (which wasn't the case before) - [ ] `make test` run locally - [ ] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [ ] using Go SDK --------- Co-authored-by: Miles Yucht --- catalog/resource_online_table.go | 7 ++++--- catalog/resource_online_table_test.go | 7 +++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/catalog/resource_online_table.go b/catalog/resource_online_table.go index ca46b8eed1..7c317a9742 100644 --- a/catalog/resource_online_table.go +++ b/catalog/resource_online_table.go @@ -14,7 +14,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -const onlineTableDefaultProvisionTimeout = 45 * time.Minute +const onlineTableDefaultProvisionTimeout = 90 * time.Minute func waitForOnlineTableCreation(w *databricks.WorkspaceClient, ctx context.Context, onlineTableName string) error { return retry.RetryContext(ctx, onlineTableDefaultProvisionTimeout, func() *retry.RetryError { @@ -80,13 +80,14 @@ func ResourceOnlineTable() common.Resource { if err != nil { return err } + // Note: We should set the id right after creation and before waiting for online table to be available. + // If the resource creation timeout is exceeded while waiting for the online table to be ready, this ensures the online table is persisted in the state. + d.SetId(res.Name) // this should be specified in the API Spec - filed a ticket to add it err = waitForOnlineTableCreation(w, ctx, res.Name) if err != nil { - return err } - d.SetId(res.Name) return nil }, Read: func(ctx context.Context, d *schema.ResourceData, c *common.DatabricksClient) error { diff --git a/catalog/resource_online_table_test.go b/catalog/resource_online_table_test.go index 104d6a21c6..1deddd02a3 100644 --- a/catalog/resource_online_table_test.go +++ b/catalog/resource_online_table_test.go @@ -9,6 +9,7 @@ import ( "github.com/databricks/databricks-sdk-go/service/catalog" "github.com/databricks/terraform-provider-databricks/qa" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" ) @@ -108,7 +109,7 @@ func TestOnlineTableCreate_ErrorInWait(t *testing.T) { }, Status: &catalog.OnlineTableStatus{DetailedState: catalog.OnlineTableStateOfflineFailed}, } - qa.ResourceFixture{ + d, err := qa.ResourceFixture{ MockWorkspaceClientFunc: func(w *mocks.MockWorkspaceClient) { e := w.GetMockOnlineTablesAPI().EXPECT() e.Create(mock.Anything, catalog.CreateOnlineTableRequest{ @@ -124,7 +125,9 @@ func TestOnlineTableCreate_ErrorInWait(t *testing.T) { Resource: ResourceOnlineTable(), HCL: onlineTableHcl, Create: true, - }.ExpectError(t, "online table status returned OFFLINE_FAILED for online table: main.default.online_table") + }.Apply(t) + qa.AssertErrorStartsWith(t, err, "online table status returned OFFLINE_FAILED for online table: main.default.online_table") + assert.Equal(t, "main.default.online_table", d.Id()) } func TestOnlineTableRead(t *testing.T) { From 704db81699e8b28607be930afb49a3e4b646538b Mon Sep 17 00:00:00 2001 From: Alex Ott Date: Sat, 5 Oct 2024 02:01:26 -0400 Subject: [PATCH 49/54] [Doc] Correctly use native markdown callouts supported by TF Registry (#4073) ## Changes TF registry supports a [number of special callouts](https://developer.hashicorp.com/terraform/registry/providers/docs#callouts) to highlight paragraphs. These callouts automatically add text like `**Note**` or `**Warning**` so we don't need to add them ourselves. Also, make consistent usage of informational callouts (`->`), important callouts (`~>`, that uses yellow background for paragraph), and warnings (`!>`). ## Tests - [ ] `make test` run locally - [x] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [ ] using Go SDK --- docs/resources/access_control_rule_set.md | 6 +++--- docs/resources/artifact_allowlist.md | 5 ++--- .../automatic_cluster_update_setting.md | 2 +- docs/resources/budget.md | 4 ++-- docs/resources/catalog.md | 2 +- docs/resources/catalog_workspace_binding.md | 8 +++----- docs/resources/cluster.md | 8 ++++---- .../compliance_security_profile_setting.md | 4 ++-- docs/resources/connection.md | 2 +- docs/resources/dbfs_file.md | 2 +- docs/resources/default_namespace_setting.md | 2 +- .../enhanced_security_monitoring_setting.md | 2 +- docs/resources/entitlements.md | 2 +- docs/resources/external_location.md | 2 +- docs/resources/global_init_script.md | 2 +- docs/resources/grant.md | 6 ++---- docs/resources/grants.md | 6 ++---- docs/resources/group.md | 4 ++-- docs/resources/group_instance_profile.md | 2 +- docs/resources/group_role.md | 2 +- docs/resources/instance_pool.md | 2 +- docs/resources/instance_profile.md | 2 +- docs/resources/ip_access_list.md | 2 +- docs/resources/job.md | 10 +++++----- docs/resources/library.md | 6 +++--- docs/resources/metastore.md | 2 +- docs/resources/metastore_assignment.md | 2 +- docs/resources/metastore_data_access.md | 2 +- docs/resources/mlflow_model.md | 2 +- docs/resources/mlflow_webhook.md | 2 +- docs/resources/model_serving.md | 2 +- docs/resources/mount.md | 10 +++++----- docs/resources/mws_credentials.md | 2 +- docs/resources/mws_customer_managed_keys.md | 6 +++--- docs/resources/mws_log_delivery.md | 4 ++-- docs/resources/mws_ncc_binding.md | 4 ++-- .../resources/mws_ncc_private_endpoint_rule.md | 4 ++-- .../mws_network_connectivity_config.md | 2 +- docs/resources/mws_networks.md | 8 ++++---- docs/resources/mws_private_access_settings.md | 6 +++--- docs/resources/mws_storage_configurations.md | 4 ++-- docs/resources/mws_vpc_endpoint.md | 4 ++-- docs/resources/mws_workspaces.md | 10 +++++----- docs/resources/notebook.md | 2 +- docs/resources/obo_token.md | 4 ++-- docs/resources/online_table.md | 6 ++---- docs/resources/permissions.md | 18 +++++++++--------- docs/resources/provider.md | 4 ++-- docs/resources/recipient.md | 2 +- docs/resources/registered_model.md | 2 +- docs/resources/repo.md | 4 ++-- .../restrict_workspace_admins_setting.md | 4 ++-- docs/resources/schema.md | 2 +- docs/resources/service_principal.md | 4 ++-- docs/resources/service_principal_role.md | 2 +- docs/resources/service_principal_secret.md | 2 +- docs/resources/share.md | 4 ++-- docs/resources/sql_alert.md | 2 +- docs/resources/sql_dashboard.md | 4 ++-- docs/resources/sql_permissions.md | 2 +- docs/resources/sql_query.md | 2 +- docs/resources/sql_visualization.md | 2 +- docs/resources/sql_widget.md | 4 ++-- docs/resources/storage_credential.md | 2 +- docs/resources/system_schema.md | 4 ++-- docs/resources/token.md | 2 +- docs/resources/user.md | 4 ++-- docs/resources/user_instance_profile.md | 2 +- docs/resources/user_role.md | 2 +- docs/resources/vector_search_endpoint.md | 2 +- docs/resources/vector_search_index.md | 2 +- docs/resources/volume.md | 4 ++-- docs/resources/workspace_binding.md | 8 +++----- docs/resources/workspace_conf.md | 6 +++--- docs/resources/workspace_file.md | 2 +- 75 files changed, 138 insertions(+), 149 deletions(-) diff --git a/docs/resources/access_control_rule_set.md b/docs/resources/access_control_rule_set.md index 3a7767c570..1bd2ee1e50 100644 --- a/docs/resources/access_control_rule_set.md +++ b/docs/resources/access_control_rule_set.md @@ -4,13 +4,13 @@ subcategory: "Security" # databricks_access_control_rule_set Resource --> **Note** This resource can be used with an account or workspace-level provider. +-> This resource can be used with an account or workspace-level provider. This resource allows you to manage access rules on Databricks account level resources. For convenience we allow accessing this resource through the Databricks account and workspace. --> **Note** Currently, we only support managing access rules on service principal, group and account resources through `databricks_access_control_rule_set`. +-> Currently, we only support managing access rules on service principal, group and account resources through `databricks_access_control_rule_set`. --> **Warning** `databricks_access_control_rule_set` cannot be used to manage access rules for resources supported by [databricks_permissions](permissions.md). Refer to its documentation for more information. +!> `databricks_access_control_rule_set` cannot be used to manage access rules for resources supported by [databricks_permissions](permissions.md). Refer to its documentation for more information. ## Service principal rule set usage diff --git a/docs/resources/artifact_allowlist.md b/docs/resources/artifact_allowlist.md index a65fe6dd57..d6272b9322 100644 --- a/docs/resources/artifact_allowlist.md +++ b/docs/resources/artifact_allowlist.md @@ -3,10 +3,9 @@ subcategory: "Unity Catalog" --- # databricks_artifact_allowlist Resource --> **Note** - It is required to define all allowlist for an artifact type in a single resource, otherwise Terraform cannot guarantee config drift prevention. +~> It is required to define all allowlist for an artifact type in a single resource, otherwise Terraform cannot guarantee config drift prevention. --> **Note** This resource can only be used with a workspace-level provider! +-> This resource can only be used with a workspace-level provider! In Databricks Runtime 13.3 and above, you can add libraries and init scripts to the allowlist in UC so that users can leverage these artifacts on compute configured with shared access mode. diff --git a/docs/resources/automatic_cluster_update_setting.md b/docs/resources/automatic_cluster_update_setting.md index 152a95b9ea..b8f4e719aa 100644 --- a/docs/resources/automatic_cluster_update_setting.md +++ b/docs/resources/automatic_cluster_update_setting.md @@ -4,7 +4,7 @@ subcategory: "Settings" # databricks_automatic_cluster_update_workspace_setting Resource --> **Note** This resource can only be used with a workspace-level provider! +-> This resource can only be used with a workspace-level provider! The `databricks_automatic_cluster_update_workspace_setting` resource allows you to control whether automatic cluster update is enabled for the current workspace. By default, it is turned off. Enabling this feature on a workspace requires that you add the Enhanced Security and Compliance add-on. diff --git a/docs/resources/budget.md b/docs/resources/budget.md index 3b99fa7c8a..31378d4254 100644 --- a/docs/resources/budget.md +++ b/docs/resources/budget.md @@ -3,9 +3,9 @@ subcategory: "FinOps" --- # databricks_budget Resource --> **Note** Initialize provider with `alias = "account"`, and `host` pointing to the account URL, like, `host = "https://accounts.cloud.databricks.com"`. Use `provider = databricks.account` for all account-level resources. +-> Initialize provider with `alias = "account"`, and `host` pointing to the account URL, like, `host = "https://accounts.cloud.databricks.com"`. Use `provider = databricks.account` for all account-level resources. --> **Public Preview** This feature is in [Public Preview](https://docs.databricks.com/release-notes/release-types.html). +-> This feature is in [Public Preview](https://docs.databricks.com/release-notes/release-types.html). This resource allows you to manage [Databricks Budgets](https://docs.databricks.com/en/admin/account-settings/budgets.html). diff --git a/docs/resources/catalog.md b/docs/resources/catalog.md index 980c6c837d..fb854f4786 100644 --- a/docs/resources/catalog.md +++ b/docs/resources/catalog.md @@ -3,7 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_catalog Resource --> **Note** This resource can only be used with a workspace-level provider! +-> This resource can only be used with a workspace-level provider! Within a metastore, Unity Catalog provides a 3-level namespace for organizing data: Catalogs, Databases (also called Schemas), and Tables / Views. diff --git a/docs/resources/catalog_workspace_binding.md b/docs/resources/catalog_workspace_binding.md index 5520192fb5..0eafd00a2c 100644 --- a/docs/resources/catalog_workspace_binding.md +++ b/docs/resources/catalog_workspace_binding.md @@ -3,17 +3,15 @@ subcategory: "Unity Catalog" --- # databricks_catalog_workspace_binding Resource --> **NOTE**This resource has been deprecated and will be removed soon. Please use the [databricks_workspace_binding resource](./workspace_binding.md) instead. +~> This resource has been deprecated and will be removed soon. Please use the [databricks_workspace_binding resource](./workspace_binding.md) instead. If you use workspaces to isolate user data access, you may want to limit catalog access to specific workspaces in your account, also known as workspace-catalog binding By default, Databricks assigns the catalog to all workspaces attached to the current metastore. By using `databricks_catalog_workspace_binding`, the catalog will be unassigned from all workspaces and only assigned explicitly using this resource. --> **Note** - To use this resource the catalog must have its isolation mode set to `ISOLATED` in the [`databricks_catalog`](https://registry.terraform.io/providers/databricks/databricks/latest/docs/resources/catalog#isolation_mode) resource. Alternatively, the isolation mode can be set using the UI or API by following [this guide](https://docs.databricks.com/data-governance/unity-catalog/create-catalogs.html#configuration). +-> To use this resource the catalog must have its isolation mode set to `ISOLATED` in the [`databricks_catalog`](https://registry.terraform.io/providers/databricks/databricks/latest/docs/resources/catalog#isolation_mode) resource. Alternatively, the isolation mode can be set using the UI or API by following [this guide](https://docs.databricks.com/data-governance/unity-catalog/create-catalogs.html#configuration). --> **Note** - If the catalog's isolation mode was set to `ISOLATED` using Terraform then the catalog will have been automatically bound to the workspace it was created from. +-> If the catalog's isolation mode was set to `ISOLATED` using Terraform then the catalog will have been automatically bound to the workspace it was created from. ## Example Usage diff --git a/docs/resources/cluster.md b/docs/resources/cluster.md index c68cc8aa81..a856812192 100644 --- a/docs/resources/cluster.md +++ b/docs/resources/cluster.md @@ -5,7 +5,7 @@ subcategory: "Compute" This resource allows you to manage [Databricks Clusters](https://docs.databricks.com/clusters/index.html). --> **Note** In case of [`Cannot access cluster ####-######-####### that was terminated or unpinned more than 30 days ago`](https://github.com/databricks/terraform-provider-databricks/issues/1197#issuecomment-1069386670) errors, please upgrade to v0.5.5 or later. If for some reason you cannot upgrade the version of provider, then the other viable option to unblock the apply pipeline is [`terraform state rm path.to.databricks_cluster.resource`](https://www.terraform.io/cli/commands/state/rm) command. +-> In case of [`Cannot access cluster ####-######-####### that was terminated or unpinned more than 30 days ago`](https://github.com/databricks/terraform-provider-databricks/issues/1197#issuecomment-1069386670) errors, please upgrade to v0.5.5 or later. If for some reason you cannot upgrade the version of provider, then the other viable option to unblock the apply pipeline is [`terraform state rm path.to.databricks_cluster.resource`](https://www.terraform.io/cli/commands/state/rm) command. ```hcl data "databricks_node_type" "smallest" { @@ -130,7 +130,7 @@ resource "databricks_cluster" "single_node" { ### (Legacy) High-Concurrency clusters --> **Note** This is a legacy cluster type, not related to the real serverless compute. See [Clusters UI changes and cluster access modes](https://docs.databricks.com/archive/compute/cluster-ui-preview.html#legacy) for information on what access mode to use when creating new clusters. +~> This is a legacy cluster type, not related to the real serverless compute. See [Clusters UI changes and cluster access modes](https://docs.databricks.com/archive/compute/cluster-ui-preview.html#legacy) for information on what access mode to use when creating new clusters. To create High-Concurrency cluster, following settings should be provided: @@ -163,7 +163,7 @@ resource "databricks_cluster" "cluster_with_table_access_control" { To install libraries, one must specify each library in a separate configuration block. Each different type of library has a slightly different syntax. It's possible to set only one type of library within one config block. Otherwise, the plan will fail with an error. --> **Note** Please consider using [databricks_library](library.md) resource for a more flexible setup. +-> Please consider using [databricks_library](library.md) resource for a more flexible setup. Installing JAR artifacts on a cluster. Location can be anything, that is DBFS or mounted object store (s3, adls, ...) @@ -484,7 +484,7 @@ resource "databricks_cluster" "this" { ### cluster_mount_info blocks (experimental) --> **Note** The underlying API is experimental and may change in the future. +~> The underlying API is experimental and may change in the future. It's possible to mount NFS (Network File System) resources into the Spark containers inside the cluster. You can specify one or more `cluster_mount_info` blocks describing the mount. This block has following attributes: diff --git a/docs/resources/compliance_security_profile_setting.md b/docs/resources/compliance_security_profile_setting.md index 6bb5afc090..acf7f6ef7e 100644 --- a/docs/resources/compliance_security_profile_setting.md +++ b/docs/resources/compliance_security_profile_setting.md @@ -4,9 +4,9 @@ subcategory: "Settings" # databricks_compliance_security_profile_workspace_setting Resource --> **Note** This resource can only be used with a workspace-level provider! +-> This resource can only be used with a workspace-level provider! --> **Note** This setting can NOT be disabled once it is enabled. +~> This setting can NOT be disabled once it is enabled. The `databricks_compliance_security_profile_workspace_setting` resource allows you to control whether to enable the compliance security profile for the current workspace. Enabling it on a workspace is permanent. By default, it is diff --git a/docs/resources/connection.md b/docs/resources/connection.md index f7421bd5da..c568c72847 100644 --- a/docs/resources/connection.md +++ b/docs/resources/connection.md @@ -3,7 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_connection (Resource) --> **Note** This resource can only be used with a workspace-level provider! +-> This resource can only be used with a workspace-level provider! Lakehouse Federation is the query federation platform for Databricks. Databricks uses Unity Catalog to manage query federation. To make a dataset available for read-only querying using Lakehouse Federation, you create the following: diff --git a/docs/resources/dbfs_file.md b/docs/resources/dbfs_file.md index e3b9c73eea..78607c733f 100644 --- a/docs/resources/dbfs_file.md +++ b/docs/resources/dbfs_file.md @@ -49,7 +49,7 @@ resource "databricks_library" "app" { ## Argument Reference --> **Note** DBFS files would only be changed, if Terraform stage did change. This means that any manual changes to managed file won't be overwritten by Terraform, if there's no local change. +-> DBFS files would only be changed, if Terraform stage did change. This means that any manual changes to managed file won't be overwritten by Terraform, if there's no local change. The following arguments are supported: diff --git a/docs/resources/default_namespace_setting.md b/docs/resources/default_namespace_setting.md index cf3c5ee36a..f21698fcb6 100644 --- a/docs/resources/default_namespace_setting.md +++ b/docs/resources/default_namespace_setting.md @@ -4,7 +4,7 @@ subcategory: "Settings" # databricks_default_namespace_setting Resource --> **Note** This resource can only be used with a workspace-level provider! +-> This resource can only be used with a workspace-level provider! The `databricks_default_namespace_setting` resource allows you to operate the setting configuration for the default namespace in the Databricks workspace. Setting the default catalog for the workspace determines the catalog that is used when queries do not reference diff --git a/docs/resources/enhanced_security_monitoring_setting.md b/docs/resources/enhanced_security_monitoring_setting.md index 64a18c9fcb..18e0de3e1a 100644 --- a/docs/resources/enhanced_security_monitoring_setting.md +++ b/docs/resources/enhanced_security_monitoring_setting.md @@ -4,7 +4,7 @@ subcategory: "Settings" # databricks_enhanced_security_monitoring_workspace_setting Resource --> **Note** This resource can only be used with a workspace-level provider! +-> This resource can only be used with a workspace-level provider! The `databricks_enhanced_security_monitoring_workspace_setting` resource allows you to control whether enhanced security monitoring is enabled for the current workspace. If the compliance security profile is enabled, this is automatically enabled. By default, diff --git a/docs/resources/entitlements.md b/docs/resources/entitlements.md index 15d7f42f6f..10852c4bb9 100644 --- a/docs/resources/entitlements.md +++ b/docs/resources/entitlements.md @@ -5,7 +5,7 @@ subcategory: "Security" This resource allows you to set entitlements to existing [databricks_users](user.md), [databricks_group](group.md) or [databricks_service_principal](service_principal.md). --> **Note** You must define entitlements of a principal using either `databricks_entitlements` or directly within one of [databricks_users](user.md), [databricks_group](group.md) or [databricks_service_principal](service_principal.md). Having entitlements defined in both resources will result in non-deterministic behaviour. +-> You must define entitlements of a principal using either `databricks_entitlements` or directly within one of [databricks_users](user.md), [databricks_group](group.md) or [databricks_service_principal](service_principal.md). Having entitlements defined in both resources will result in non-deterministic behaviour. ## Example Usage diff --git a/docs/resources/external_location.md b/docs/resources/external_location.md index 59cc555685..2495510bb0 100644 --- a/docs/resources/external_location.md +++ b/docs/resources/external_location.md @@ -3,7 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_external_location Resource --> **Note** This resource can only be used with a workspace-level provider! +-> This resource can only be used with a workspace-level provider! To work with external tables, Unity Catalog introduces two new objects to access and work with external cloud storage: diff --git a/docs/resources/global_init_script.md b/docs/resources/global_init_script.md index bb8e50d98b..90d5d42b36 100644 --- a/docs/resources/global_init_script.md +++ b/docs/resources/global_init_script.md @@ -31,7 +31,7 @@ resource "databricks_global_init_script" "init2" { ## Argument Reference --> **Note** Global init script in the Databricks workspace would only be changed, if Terraform stage did change. This means that any manual changes to managed global init script won't be overwritten by Terraform, if there's no local change to source. +-> Global init script in the Databricks workspace would only be changed, if Terraform stage did change. This means that any manual changes to managed global init script won't be overwritten by Terraform, if there's no local change to source. The size of a global init script source code must not exceed 64Kb. The following arguments are supported: diff --git a/docs/resources/grant.md b/docs/resources/grant.md index 2adfdb7d67..5f2f8b4326 100644 --- a/docs/resources/grant.md +++ b/docs/resources/grant.md @@ -3,11 +3,9 @@ subcategory: "Unity Catalog" --- # databricks_grant Resource --> **Note** - This article refers to the privileges and inheritance model in Privilege Model version 1.0. If you created your metastore during the public preview (before August 25, 2022), you can upgrade to Privilege Model version 1.0 following [Upgrade to privilege inheritance](https://docs.databricks.com/data-governance/unity-catalog/hive-metastore.html) +-> This article refers to the privileges and inheritance model in Privilege Model version 1.0. If you created your metastore during the public preview (before August 25, 2022), you can upgrade to Privilege Model version 1.0 following [Upgrade to privilege inheritance](https://docs.databricks.com/data-governance/unity-catalog/hive-metastore.html) --> **Note** - Unity Catalog APIs are accessible via **workspace-level APIs**. This design may change in the future. Account-level principal grants can be assigned with any valid workspace as the Unity Catalog is decoupled from specific workspaces. More information in [the official documentation](https://docs.databricks.com/data-governance/unity-catalog/index.html). +-> Most of Unity Catalog APIs are only accessible via **workspace-level APIs**. This design may change in the future. Account-level principal grants can be assigned with any valid workspace as the Unity Catalog is decoupled from specific workspaces. More information in [the official documentation](https://docs.databricks.com/data-governance/unity-catalog/index.html). In Unity Catalog all users initially have no access to data. Only Metastore Admins can create objects and can grant/revoke access on individual objects to users and groups. Every securable object in Unity Catalog has an owner. The owner can be any account-level user or group, called principals in general. The principal that creates an object becomes its owner. Owners receive `ALL_PRIVILEGES` on the securable object (e.g., `SELECT` and `MODIFY` on a table), as well as the permission to grant privileges to other principals. diff --git a/docs/resources/grants.md b/docs/resources/grants.md index 25f22c91af..64a52d83df 100644 --- a/docs/resources/grants.md +++ b/docs/resources/grants.md @@ -3,11 +3,9 @@ subcategory: "Unity Catalog" --- # databricks_grants Resource --> **Note** - This article refers to the privileges and inheritance model in Privilege Model version 1.0. If you created your metastore during the public preview (before August 25, 2022), you can upgrade to Privilege Model version 1.0 following [Upgrade to privilege inheritance](https://docs.databricks.com/data-governance/unity-catalog/hive-metastore.html) +-> This article refers to the privileges and inheritance model in Privilege Model version 1.0. If you created your metastore during the public preview (before August 25, 2022), you can upgrade to Privilege Model version 1.0 following [Upgrade to privilege inheritance](https://docs.databricks.com/data-governance/unity-catalog/hive-metastore.html) --> **Note** - Unity Catalog APIs are accessible via **workspace-level APIs**. This design may change in the future. Account-level principal grants can be assigned with any valid workspace as the Unity Catalog is decoupled from specific workspaces. More information in [the official documentation](https://docs.databricks.com/data-governance/unity-catalog/index.html). +-> Most of Unity Catalog APIs are only accessible via **workspace-level APIs**. This design may change in the future. Account-level principal grants can be assigned with any valid workspace as the Unity Catalog is decoupled from specific workspaces. More information in [the official documentation](https://docs.databricks.com/data-governance/unity-catalog/index.html). Two different resources help you manage your Unity Catalog grants for a securable. Each of these resources serves a different use case: diff --git a/docs/resources/group.md b/docs/resources/group.md index 5b23e83c66..aa6321e50f 100644 --- a/docs/resources/group.md +++ b/docs/resources/group.md @@ -5,9 +5,9 @@ subcategory: "Security" This resource allows you to manage both [account groups and workspace-local groups](https://docs.databricks.com/administration-guide/users-groups/groups.html). You can use the [databricks_group_member resource](group_member.md) to assign Databricks users, [service principals](service_principal.md) as well as other groups as members of the group. This is useful if you are using an application to sync users & groups with SCIM API. --> **Note** To assign an account level group to a workspace use [databricks_mws_permission_assignment](mws_permission_assignment.md). +-> To assign an account level group to a workspace use [databricks_mws_permission_assignment](mws_permission_assignment.md). --> **Note** Entitlements, like, `allow_cluster_create`, `allow_instance_pool_create`, `databricks_sql_access`, `workspace_access` applicable only for workspace-level groups. Use [databricks_entitlements](entitlements.md) resource to assign entitlements inside a workspace to account-level groups. +-> Entitlements, like, `allow_cluster_create`, `allow_instance_pool_create`, `databricks_sql_access`, `workspace_access` applicable only for workspace-level groups. Use [databricks_entitlements](entitlements.md) resource to assign entitlements inside a workspace to account-level groups. To create account groups in the Databricks account, the provider must be configured accordingly. On AWS deployment with `host = "https://accounts.cloud.databricks.com"` and `account_id = "00000000-0000-0000-0000-000000000000"`. On Azure deployments `host = "https://accounts.azuredatabricks.net"`, `account_id = "00000000-0000-0000-0000-000000000000"` and using [AAD tokens](https://registry.terraform.io/providers/databricks/databricks/latest/docs#special-configurations-for-azure) as authentication. diff --git a/docs/resources/group_instance_profile.md b/docs/resources/group_instance_profile.md index 9da28aeda1..01f9bfae97 100644 --- a/docs/resources/group_instance_profile.md +++ b/docs/resources/group_instance_profile.md @@ -39,7 +39,7 @@ In addition to all arguments above, the following attributes are exported: ## Import --> **Note** Importing this resource is not currently supported. +!> Importing this resource is not currently supported. ## Related Resources diff --git a/docs/resources/group_role.md b/docs/resources/group_role.md index 395df9f264..147d214ffa 100644 --- a/docs/resources/group_role.md +++ b/docs/resources/group_role.md @@ -59,7 +59,7 @@ In addition to all arguments above, the following attributes are exported: ## Import --> **Note** Importing this resource is not currently supported. +!> Importing this resource is not currently supported. ## Related Resources diff --git a/docs/resources/instance_pool.md b/docs/resources/instance_pool.md index 9663576c63..2c7e052cf5 100644 --- a/docs/resources/instance_pool.md +++ b/docs/resources/instance_pool.md @@ -5,7 +5,7 @@ subcategory: "Compute" This resource allows you to manage [instance pools](https://docs.databricks.com/clusters/instance-pools/index.html) to reduce [cluster](cluster.md) start and auto-scaling times by maintaining a set of idle, ready-to-use instances. An instance pool reduces [cluster](cluster.md) start and auto-scaling times by maintaining a set of idle, ready-to-use cloud instances. When a [cluster](cluster.md) attached to a pool needs an instance, it first attempts to allocate one of the pool’s idle instances. If the pool has no idle instances, it expands by allocating a new instance from the instance provider in order to accommodate the cluster’s request. When a [cluster](cluster.md) releases an instance, it returns to the pool and is free for another [cluster](cluster.md) to use. Only clusters attached to a pool can use that pool’s idle instances. --> **Note** It is important to know that different cloud service providers have different `node_type_id`, `disk_specs` and potentially other configurations. +-> It is important to know that different cloud service providers have different `node_type_id`, `disk_specs` and potentially other configurations. ## Example Usage diff --git a/docs/resources/instance_profile.md b/docs/resources/instance_profile.md index 23ef84f205..b8461dd941 100644 --- a/docs/resources/instance_profile.md +++ b/docs/resources/instance_profile.md @@ -5,7 +5,7 @@ subcategory: "Deployment" This resource allows you to manage AWS EC2 instance profiles that users can launch [databricks_cluster](cluster.md) and access data, like [databricks_mount](mount.md). The following example demonstrates how to create an instance profile and create a cluster with it. When creating a new `databricks_instance_profile`, Databricks validates that it has sufficient permissions to launch instances with the instance profile. This validation uses AWS dry-run mode for the [AWS EC2 RunInstances API](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RunInstances.html). --> **Note** Please switch to [databricks_storage_credential](storage_credential.md) with Unity Catalog to manage storage credentials, which provides a better and faster way for managing credential security. +-> Please switch to [databricks_storage_credential](storage_credential.md) with Unity Catalog to manage storage credentials, which provides a better and faster way for managing credential security. ```hcl variable "crossaccount_role_name" { diff --git a/docs/resources/ip_access_list.md b/docs/resources/ip_access_list.md index 44b8c20f46..107ea35144 100644 --- a/docs/resources/ip_access_list.md +++ b/docs/resources/ip_access_list.md @@ -5,7 +5,7 @@ subcategory: "Security" Security-conscious enterprises that use cloud SaaS applications need to restrict access to their own employees. Authentication helps to prove user identity, but that does not enforce network location of the users. Accessing a cloud service from an unsecured network can pose security risks to an enterprise, especially when the user may have authorized access to sensitive or personal data. Enterprise network perimeters apply security policies and limit access to external services (for example, firewalls, proxies, DLP, and logging), so access beyond these controls are assumed to be untrusted. Please see [IP Access List](https://docs.databricks.com/security/network/ip-access-list.html) for full feature documentation. --> **Note** The total number of IP addresses and CIDR scopes provided across all ACL Lists in a workspace can not exceed 1000. Refer to the docs above for specifics. +-> The total number of IP addresses and CIDR scopes provided across all ACL Lists in a workspace can not exceed 1000. Refer to the docs above for specifics. ## Example Usage diff --git a/docs/resources/job.md b/docs/resources/job.md index e8e3c9cdc2..dc8eebc587 100644 --- a/docs/resources/job.md +++ b/docs/resources/job.md @@ -8,7 +8,7 @@ The `databricks_job` resource allows you to manage [Databricks Jobs](https://doc ## Example Usage --> **Note** In Terraform configuration, it is recommended to define tasks in alphabetical order of their `task_key` arguments, so that you get consistent and readable diff. Whenever tasks are added or removed, or `task_key` is renamed, you'll observe a change in the majority of tasks. It's related to the fact that the current version of the provider treats `task` blocks as an ordered list. Alternatively, `task` block could have been an unordered set, though end-users would see the entire block replaced upon a change in single property of the task. +-> In Terraform configuration, it is recommended to define tasks in alphabetical order of their `task_key` arguments, so that you get consistent and readable diff. Whenever tasks are added or removed, or `task_key` is renamed, you'll observe a change in the majority of tasks. It's related to the fact that the current version of the provider treats `task` blocks as an ordered list. Alternatively, `task` block could have been an unordered set, though end-users would see the entire block replaced upon a change in single property of the task. It is possible to create [a Databricks job](https://docs.databricks.com/data-engineering/jobs/jobs-user-guide.html) using `task` blocks. A single task is defined with the `task` block containing one of the `*_task` blocks, `task_key`, and additional arguments described below. @@ -142,7 +142,7 @@ This block describes individual tasks: * `timeout_seconds` - (Optional) (Integer) An optional timeout applied to each run of this job. The default behavior is to have no timeout. * `webhook_notifications` - (Optional) (List) An optional set of system destinations (for example, webhook destinations or Slack) to be notified when runs of this task begins, completes or fails. The default behavior is to not send any notifications. This field is a block and is documented below. --> **Note** If no `job_cluster_key`, `existing_cluster_id`, or `new_cluster` were specified in task definition, then task will executed using serverless compute. +-> If no `job_cluster_key`, `existing_cluster_id`, or `new_cluster` were specified in task definition, then task will executed using serverless compute. #### condition_task Configuration Block @@ -186,7 +186,7 @@ You also need to include a `git_source` block to configure the repository that c * `pipeline_id` - (Required) The pipeline's unique ID. * `full_refresh` - (Optional) (Bool) Specifies if there should be full refresh of the pipeline. --> **Note** The following configuration blocks are only supported inside a `task` block +-> The following configuration blocks are only supported inside a `task` block #### python_wheel_task Configuration Block @@ -318,7 +318,7 @@ This block describes upstream dependencies of a given task. For multiple upstrea * `task_key` - (Required) The name of the task this task depends on. * `outcome` - (Optional, string) Can only be specified on condition task dependencies. The outcome of the dependent task that must be met for this task to run. Possible values are `"true"` or `"false"`. --> **Note** Similar to the tasks themselves, each dependency inside the task need to be declared in alphabetical order with respect to task_key in order to get consistent Terraform diffs. +-> Similar to the tasks themselves, each dependency inside the task need to be declared in alphabetical order with respect to task_key in order to get consistent Terraform diffs. ### run_as Configuration Block @@ -434,7 +434,7 @@ webhook_notifications { * `id` - ID of the system notification that is notified when an event defined in `webhook_notifications` is triggered. --> **Note** The following configuration blocks can be standalone or nested inside a `task` block +-> The following configuration blocks can be standalone or nested inside a `task` block ### notification_settings Configuration Block diff --git a/docs/resources/library.md b/docs/resources/library.md index 5eab7306fb..c693bfed8d 100644 --- a/docs/resources/library.md +++ b/docs/resources/library.md @@ -5,7 +5,7 @@ subcategory: "Compute" Installs a [library](https://docs.databricks.com/libraries/index.html) on [databricks_cluster](cluster.md). Each different type of library has a slightly different syntax. It's possible to set only one type of library within one resource. Otherwise, the plan will fail with an error. --> **Note** `databricks_library` resource would always start the associated cluster if it's not running, so make sure to have auto-termination configured. It's not possible to atomically change the version of the same library without cluster restart. Libraries are fully removed from the cluster only after restart. +-> `databricks_library` resource would always start the associated cluster if it's not running, so make sure to have auto-termination configured. It's not possible to atomically change the version of the same library without cluster restart. Libraries are fully removed from the cluster only after restart. ## Installing library on all clusters @@ -71,7 +71,7 @@ resource "databricks_library" "app" { Installing Python PyPI artifacts. You can optionally also specify the `repo` parameter for a custom PyPI mirror, which should be accessible without any authentication for the network that cluster runs in. --> **Note** `repo` host should be accessible from the Internet by Databricks control plane. If connectivity to custom PyPI repositories is required, please modify cluster-node `/etc/pip.conf` through [databricks_global_init_script](global_init_script.md). +-> `repo` host should be accessible from the Internet by Databricks control plane. If connectivity to custom PyPI repositories is required, please modify cluster-node `/etc/pip.conf` through [databricks_global_init_script](global_init_script.md). ```hcl resource "databricks_library" "fbprophet" { @@ -126,7 +126,7 @@ resource "databricks_library" "rkeops" { ## Import --> **Note** Importing this resource is not currently supported. +!> Importing this resource is not currently supported. ## Related Resources diff --git a/docs/resources/metastore.md b/docs/resources/metastore.md index 6cd5a8417e..8193f68600 100644 --- a/docs/resources/metastore.md +++ b/docs/resources/metastore.md @@ -3,7 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_metastore Resource --> **Note** This resource can be used with an account or workspace-level provider. +-> This resource can be used with an account or workspace-level provider. A metastore is the top-level container of objects in Unity Catalog. It stores data assets (tables and views) and the permissions that govern access to them. Databricks account admins can create metastores and assign them to Databricks workspaces in order to control which workloads use each metastore. diff --git a/docs/resources/metastore_assignment.md b/docs/resources/metastore_assignment.md index 6a336a312b..11a94307cd 100644 --- a/docs/resources/metastore_assignment.md +++ b/docs/resources/metastore_assignment.md @@ -3,7 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_metastore_assignment (Resource) --> **Note** This resource can be used with an account or workspace-level provider. +-> This resource can be used with an account or workspace-level provider. A single [databricks_metastore](metastore.md) can be shared across Databricks workspaces, and each linked workspace has a consistent view of the data and a single set of access policies. You can only create a single metastore for each region in which your organization operates. diff --git a/docs/resources/metastore_data_access.md b/docs/resources/metastore_data_access.md index 290eb061cb..04823fe417 100644 --- a/docs/resources/metastore_data_access.md +++ b/docs/resources/metastore_data_access.md @@ -3,7 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_metastore_data_access (Resource) --> **Note** This resource can be used with an account or workspace-level provider. +-> This resource can be used with an account or workspace-level provider. Optionally, each [databricks_metastore](metastore.md) can have a default [databricks_storage_credential](storage_credential.md) defined as `databricks_metastore_data_access`. This will be used by Unity Catalog to access data in the root storage location if defined. diff --git a/docs/resources/mlflow_model.md b/docs/resources/mlflow_model.md index 60c310d295..208866d8d7 100644 --- a/docs/resources/mlflow_model.md +++ b/docs/resources/mlflow_model.md @@ -5,7 +5,7 @@ subcategory: "MLflow" This resource allows you to create [MLflow models](https://docs.databricks.com/applications/mlflow/models.html) in Databricks. -**Note** This documentation covers the Workspace Model Registry. Databricks recommends using [Models in Unity Catalog](registered_model.md). Models in Unity Catalog provides centralized model governance, cross-workspace access, lineage, and deployment. +-> This documentation covers the Workspace Model Registry. Databricks recommends using [Models in Unity Catalog](registered_model.md). Models in Unity Catalog provides centralized model governance, cross-workspace access, lineage, and deployment. ## Example Usage diff --git a/docs/resources/mlflow_webhook.md b/docs/resources/mlflow_webhook.md index 96f62e20ff..fd280cf9b4 100644 --- a/docs/resources/mlflow_webhook.md +++ b/docs/resources/mlflow_webhook.md @@ -112,7 +112,7 @@ In addition to all arguments above, the following attributes are exported: ## Import --> **Note** Importing this resource is not currently supported. +!> Importing this resource is not currently supported. ## Related Resources diff --git a/docs/resources/model_serving.md b/docs/resources/model_serving.md index 0cac9cb8f5..0bb116bfa9 100644 --- a/docs/resources/model_serving.md +++ b/docs/resources/model_serving.md @@ -5,7 +5,7 @@ subcategory: "Serving" This resource allows you to manage [Model Serving](https://docs.databricks.com/machine-learning/model-serving/index.html) endpoints in Databricks. -**Note** If you replace `served_models` with `served_entities` in an existing serving endpoint, the serving endpoint will briefly go into an update state (~30 seconds) and increment the config version. +-> If you replace `served_models` with `served_entities` in an existing serving endpoint, the serving endpoint will briefly go into an update state (~30 seconds) and increment the config version. ## Example Usage diff --git a/docs/resources/mount.md b/docs/resources/mount.md index a0446b03ac..ff187b2daa 100644 --- a/docs/resources/mount.md +++ b/docs/resources/mount.md @@ -5,9 +5,9 @@ subcategory: "Storage" This resource will [mount your cloud storage](https://docs.databricks.com/data/databricks-file-system.html#mount-object-storage-to-dbfs) on `dbfs:/mnt/name`. Right now it supports mounting AWS S3, Azure (Blob Storage, ADLS Gen1 & Gen2), Google Cloud Storage. It is important to understand that this will start up the [cluster](cluster.md) if the cluster is terminated. The read and refresh terraform command will require a cluster and may take some time to validate the mount. -**Note** When `cluster_id` is not specified, it will create the smallest possible cluster in the default availability zone with name equal to or starting with `terraform-mount` for the shortest possible amount of time. To avoid mount failure due to potentially quota or capacity issues with the default cluster, we recommend specifying a cluster to use for mounting. +-> When `cluster_id` is not specified, it will create the smallest possible cluster in the default availability zone with name equal to or starting with `terraform-mount` for the shortest possible amount of time. To avoid mount failure due to potentially quota or capacity issues with the default cluster, we recommend specifying a cluster to use for mounting. -**Note** CRUD operations on a databricks mount require a running cluster. Due to limitations of terraform and the databricks mounts APIs, if the cluster the mount was most recently created / updated using no longer exists AND the mount is destroyed as a part of a terraform apply, we mark it as deleted without cleaning it up from the workspace. +-> CRUD operations on a databricks mount require a running cluster. Due to limitations of terraform and the databricks mounts APIs, if the cluster the mount was most recently created / updated using no longer exists AND the mount is destroyed as a part of a terraform apply, we mark it as deleted without cleaning it up from the workspace. This resource provides two ways of mounting a storage account: @@ -62,9 +62,9 @@ resource "databricks_mount" "this" { ### Example mounting ADLS Gen2 with AAD passthrough --> **Note** AAD passthrough is considered a legacy data access pattern. Use Unity Catalog for fine-grained data access control. +-> AAD passthrough is considered a legacy data access pattern. Use Unity Catalog for fine-grained data access control. --> **Note** Mounts using AAD passthrough cannot be created using a service principal. +-> Mounts using AAD passthrough cannot be created using a service principal. To mount ALDS Gen2 with Azure Active Directory Credentials passthrough we need to execute the mount commands using the cluster configured with AAD Credentials passthrough & provide necessary configuration parameters (see [documentation](https://docs.microsoft.com/en-us/azure/databricks/security/credential-passthrough/adls-passthrough#--mount-azure-data-lake-storage-to-dbfs-using-credential-passthrough) for more details). @@ -341,7 +341,7 @@ In addition to all arguments above, the following attributes are exported: ## Import --> **Note** Importing this resource is not currently supported. +!> Importing this resource is not currently supported. ## Related Resources diff --git a/docs/resources/mws_credentials.md b/docs/resources/mws_credentials.md index 7271ee6a68..0a5c69daae 100644 --- a/docs/resources/mws_credentials.md +++ b/docs/resources/mws_credentials.md @@ -3,7 +3,7 @@ subcategory: "Deployment" --- # databricks_mws_credentials Resource --> **Note** Initialize provider with `alias = "mws"`, `host = "https://accounts.cloud.databricks.com"` and use `provider = databricks.mws` +-> Initialize provider with `alias = "mws"`, `host = "https://accounts.cloud.databricks.com"` and use `provider = databricks.mws` This resource to configure the cross-account role for creation of new workspaces within AWS. diff --git a/docs/resources/mws_customer_managed_keys.md b/docs/resources/mws_customer_managed_keys.md index 3d46c6707c..206158766d 100644 --- a/docs/resources/mws_customer_managed_keys.md +++ b/docs/resources/mws_customer_managed_keys.md @@ -3,7 +3,7 @@ subcategory: "Deployment" --- # databricks_mws_customer_managed_keys Resource --> **Note** Initialize provider with `alias = "mws"`, `host = "https://accounts.cloud.databricks.com"` and use `provider = databricks.mws` +-> Initialize provider with `alias = "mws"`, `host = "https://accounts.cloud.databricks.com"` and use `provider = databricks.mws` This resource to configure KMS keys for new workspaces within AWS or GCP. This is to support the following features: @@ -14,7 +14,7 @@ Please follow this [complete runnable example](../guides/aws-workspace.md) with ## Example Usage --> **Note** If you've used the resource before, please add `use_cases = ["MANAGED_SERVICES"]` to keep the previous behaviour. +-> If you've used the resource before, please add `use_cases = ["MANAGED_SERVICES"]` to keep the previous behaviour. ### Customer-managed key for managed services @@ -251,7 +251,7 @@ In addition to all arguments above, the following attributes are exported: ## Import --> **Note** Importing this resource is not currently supported. +!> Importing this resource is not currently supported. ## Related Resources diff --git a/docs/resources/mws_log_delivery.md b/docs/resources/mws_log_delivery.md index f22b1abbf6..98e25273ff 100644 --- a/docs/resources/mws_log_delivery.md +++ b/docs/resources/mws_log_delivery.md @@ -3,7 +3,7 @@ subcategory: "Log Delivery" --- # databricks_mws_log_delivery Resource --> **Note** Initialize provider with `alias = "mws"`, `host = "https://accounts.cloud.databricks.com"` and use `provider = databricks.mws` +-> Initialize provider with `alias = "mws"`, `host = "https://accounts.cloud.databricks.com"` and use `provider = databricks.mws` This resource configures the delivery of the two supported log types from Databricks workspaces: [billable usage logs](https://docs.databricks.com/administration-guide/account-settings/billable-usage-delivery.html) and [audit logs](https://docs.databricks.com/administration-guide/account-settings/audit-logs.html). @@ -150,7 +150,7 @@ Resource exports the following attributes: ## Import --> **Note** Importing this resource is not currently supported. +!> Importing this resource is not currently supported. ## Related Resources diff --git a/docs/resources/mws_ncc_binding.md b/docs/resources/mws_ncc_binding.md index af64e6a94f..6615294941 100644 --- a/docs/resources/mws_ncc_binding.md +++ b/docs/resources/mws_ncc_binding.md @@ -3,9 +3,9 @@ subcategory: "Deployment" --- # databricks_mws_ncc_binding Resource --> **Note** Initialize provider with `alias = "account"`, `host = "https://accounts.azuredatabricks.net"` and use `provider = databricks.account` for all `databricks_mws_*` resources. +-> Initialize provider with `alias = "account"`, `host = "https://accounts.azuredatabricks.net"` and use `provider = databricks.account` for all `databricks_mws_*` resources. --> **Public Preview** This feature is available for AWS & Azure only, and is in [Public Preview](https://docs.databricks.com/release-notes/release-types.html) in AWS. +-> This feature is available for AWS & Azure only, and is in [Public Preview](https://docs.databricks.com/release-notes/release-types.html) in AWS. Allows you to attach a [Network Connectivity Config](mws_network_connectivity_config) object to a [databricks_mws_workspaces](mws_workspaces.md) resource to create a [Databricks Workspace that leverages serverless network connectivity configs](https://learn.microsoft.com/en-us/azure/databricks/sql/admin/serverless-firewall). diff --git a/docs/resources/mws_ncc_private_endpoint_rule.md b/docs/resources/mws_ncc_private_endpoint_rule.md index 0180f1e587..50fba93908 100644 --- a/docs/resources/mws_ncc_private_endpoint_rule.md +++ b/docs/resources/mws_ncc_private_endpoint_rule.md @@ -3,9 +3,9 @@ subcategory: "Deployment" --- # databricks_mws_ncc_private_endpoint_rule Resource --> **Note** Initialize provider with `alias = "account"`, `host = "https://accounts.azuredatabricks.net"` and use `provider = databricks.account` for all `databricks_mws_*` resources. +-> Initialize provider with `alias = "account"`, `host = "https://accounts.azuredatabricks.net"` and use `provider = databricks.account` for all `databricks_mws_*` resources. --> **Note** This feature is only available in Azure. +-> This feature is only available in Azure. Allows you to create a private endpoint in a [Network Connectivity Config](mws_network_connectivity_config.md) that can be used to [configure private connectivity from serverless compute](https://learn.microsoft.com/en-us/azure/databricks/security/network/serverless-network-security/serverless-private-link). diff --git a/docs/resources/mws_network_connectivity_config.md b/docs/resources/mws_network_connectivity_config.md index 401d8a98db..bf16a35caf 100644 --- a/docs/resources/mws_network_connectivity_config.md +++ b/docs/resources/mws_network_connectivity_config.md @@ -3,7 +3,7 @@ subcategory: "Deployment" --- # databricks_mws_network_connectivity_config Resource --> **Note** Initialize provider with `alias = "account"`, `host = "https://accounts.azuredatabricks.net"` and use `provider = databricks.account` for all `databricks_mws_*` resources. +-> Initialize provider with `alias = "account"`, `host = "https://accounts.azuredatabricks.net"` and use `provider = databricks.account` for all `databricks_mws_*` resources. -> **Public Preview** This feature is available for AWS & Azure only, and is in [Public Preview](https://docs.databricks.com/release-notes/release-types.html) in AWS. diff --git a/docs/resources/mws_networks.md b/docs/resources/mws_networks.md index cc26d438c9..1c7f41ee01 100644 --- a/docs/resources/mws_networks.md +++ b/docs/resources/mws_networks.md @@ -5,7 +5,7 @@ subcategory: "Deployment" ## Databricks on AWS usage --> **Note** Initialize provider with `alias = "mws"`, `host = "https://accounts.cloud.databricks.com"` and use `provider = databricks.mws` +-> Initialize provider with `alias = "mws"`, `host = "https://accounts.cloud.databricks.com"` and use `provider = databricks.mws` Use this resource to [configure VPC](https://docs.databricks.com/administration-guide/cloud-configurations/aws/customer-managed-vpc.html) & subnets for new workspaces within AWS. It is essential to understand that this will require you to configure your provider separately for the multiple workspaces resources. @@ -16,13 +16,13 @@ Use this resource to [configure VPC](https://docs.databricks.com/administration- * Subnets must have outbound access to the public network using a [aws_nat_gateway](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/nat_gateway) and [aws_internet_gateway](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/internet_gateway), or other similar customer-managed appliance infrastructure. * The NAT gateway must be set up in its subnet (public_subnets in the example below) that routes quad-zero (0.0.0.0/0) traffic to an internet gateway or other customer-managed appliance infrastructure. --> **Note** The NAT gateway needs only one IP address per AZ. Hence, the public subnet only needs two IP addresses. In order to limit the number of IP addresses in the public subnet, you can specify a secondary CIDR block (cidr_block_public) using the argument secondary_cidr_blocks then pass it to the public_subnets argument. Please review the [IPv4 CIDR block association restrictions](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Subnets.html) when choosing the secondary cidr block. +-> The NAT gateway needs only one IP address per AZ. Hence, the public subnet only needs two IP addresses. In order to limit the number of IP addresses in the public subnet, you can specify a secondary CIDR block (cidr_block_public) using the argument secondary_cidr_blocks then pass it to the public_subnets argument. Please review the [IPv4 CIDR block association restrictions](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Subnets.html) when choosing the secondary cidr block. Please follow this [complete runnable example](../guides/aws-workspace.md) with new VPC and new workspace setup. Please pay special attention to the fact that there you have two different instances of a databricks provider - one for deploying workspaces (with `host="https://accounts.cloud.databricks.com/"`) and another for the workspace you've created with `databricks_mws_workspaces` resource. If you want both creations of workspaces & clusters within the same Terraform module (essentially the same directory), you should use the provider aliasing feature of Terraform. We strongly recommend having one terraform module to create workspace + PAT token and the rest in different modules. ## Databricks on GCP usage --> **Note** Initialize provider with `alias = "mws"`, `host = "https://accounts.gcp.databricks.com"` and use `provider = databricks.mws` +-> Initialize provider with `alias = "mws"`, `host = "https://accounts.gcp.databricks.com"` and use `provider = databricks.mws` Use this resource to [configure VPC](https://docs.gcp.databricks.com/administration-guide/cloud-configurations/gcp/customer-managed-vpc.html) & subnet for new workspaces within GCP. It is essential to understand that this will require you to configure your provider separately for the multiple workspaces resources. @@ -215,7 +215,7 @@ In addition to all arguments above, the following attributes are exported: ## Import --> **Note** Importing this resource is not currently supported. +!> Importing this resource is not currently supported. ## Related Resources diff --git a/docs/resources/mws_private_access_settings.md b/docs/resources/mws_private_access_settings.md index 3fbc4577b2..24de15f5e7 100644 --- a/docs/resources/mws_private_access_settings.md +++ b/docs/resources/mws_private_access_settings.md @@ -11,7 +11,7 @@ It is strongly recommended that customers read the [Enable AWS Private Link](htt ## Databricks on AWS usage --> **Note** Initialize provider with `alias = "mws"`, `host = "https://accounts.cloud.databricks.com"` and use `provider = databricks.mws` +-> Initialize provider with `alias = "mws"`, `host = "https://accounts.cloud.databricks.com"` and use `provider = databricks.mws` ```hcl resource "databricks_mws_private_access_settings" "pas" { @@ -42,7 +42,7 @@ resource "databricks_mws_workspaces" "this" { ## Databricks on GCP usage --> **Note** Initialize provider with `alias = "mws"`, `host = "https://accounts.gcp.databricks.com"` and use `provider = databricks.mws` +-> Initialize provider with `alias = "mws"`, `host = "https://accounts.gcp.databricks.com"` and use `provider = databricks.mws` ```hcl resource "databricks_mws_workspaces" "this" { @@ -85,7 +85,7 @@ In addition to all arguments above, the following attributes are exported: ## Import --> **Note** Importing this resource is not currently supported. +!> Importing this resource is not currently supported. ## Related Resources diff --git a/docs/resources/mws_storage_configurations.md b/docs/resources/mws_storage_configurations.md index c7018a4205..779c5f3d67 100644 --- a/docs/resources/mws_storage_configurations.md +++ b/docs/resources/mws_storage_configurations.md @@ -3,7 +3,7 @@ subcategory: "Deployment" --- # databricks_mws_storage_configurations Resource --> **Note** Initialize provider with `alias = "mws"`, `host = "https://accounts.cloud.databricks.com"` and use `provider = databricks.mws` +-> Initialize provider with `alias = "mws"`, `host = "https://accounts.cloud.databricks.com"` and use `provider = databricks.mws` This resource to configure root bucket new workspaces within AWS. @@ -55,7 +55,7 @@ In addition to all arguments above, the following attributes are exported: ## Import --> **Note** Importing this resource is not currently supported. +!> Importing this resource is not currently supported. ## Related Resources diff --git a/docs/resources/mws_vpc_endpoint.md b/docs/resources/mws_vpc_endpoint.md index 1600df1e40..97ed95330d 100644 --- a/docs/resources/mws_vpc_endpoint.md +++ b/docs/resources/mws_vpc_endpoint.md @@ -3,7 +3,7 @@ subcategory: "Deployment" --- # databricks_mws_vpc_endpoint Resource --> **Note** Initialize provider with `alias = "mws"`, `host = "https://accounts.cloud.databricks.com"` and use `provider = databricks.mws` +-> Initialize provider with `alias = "mws"`, `host = "https://accounts.cloud.databricks.com"` and use `provider = databricks.mws` Enables you to register [aws_vpc_endpoint](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_endpoint) resources or gcp vpc_endpoint resources with Databricks such that they can be used as part of a [databricks_mws_networks](mws_networks.md) configuration. @@ -200,7 +200,7 @@ In addition to all arguments above, the following attributes are exported: ## Import --> **Note** Importing this resource is not currently supported. +-> Importing this resource is not currently supported. ## Related Resources diff --git a/docs/resources/mws_workspaces.md b/docs/resources/mws_workspaces.md index c56f1c51c6..4f48777274 100644 --- a/docs/resources/mws_workspaces.md +++ b/docs/resources/mws_workspaces.md @@ -3,7 +3,7 @@ subcategory: "Deployment" --- # databricks_mws_workspaces resource --> **Note** Initialize provider with `alias = "mws"`, `host = "https://accounts.cloud.databricks.com"` and use `provider = databricks.mws`. We require all `databricks_mws_*` resources to be created within its own dedicated terraform module of your environment. Usually this module creates VPC and IAM roles as well. Code that creates workspaces and code that [manages workspaces](../guides/workspace-management.md) must be in separate terraform modules to avoid common confusion between `provider = databricks.mws` and `provider = databricks.created_workspace`. This is why we specify `databricks_host` and `databricks_token` outputs, that have to be used in the latter modules: +-> Initialize provider with `alias = "mws"`, `host = "https://accounts.cloud.databricks.com"` and use `provider = databricks.mws`. We require all `databricks_mws_*` resources to be created within its own dedicated terraform module of your environment. Usually this module creates VPC and IAM roles as well. Code that creates workspaces and code that [manages workspaces](../guides/workspace-management.md) must be in separate terraform modules to avoid common confusion between `provider = databricks.mws` and `provider = databricks.created_workspace`. This is why we specify `databricks_host` and `databricks_token` outputs, that have to be used in the latter modules: ```hcl provider "databricks" { @@ -14,7 +14,7 @@ provider "databricks" { This resource allows you to set up [workspaces on AWS](https://docs.databricks.com/getting-started/overview.html#e2-architecture-1) or [workspaces on GCP](https://docs.gcp.databricks.com/administration-guide/account-settings-gcp/workspaces.html). Please follow this complete runnable example on [AWS](../guides/aws-workspace.md) or [GCP](../guides/gcp-workspace.md) with new VPC and new workspace setup. --> **Note** On Azure you need to use [azurerm_databricks_workspace](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/databricks_workspace) resource to create Azure Databricks workspaces. +-> On Azure you need to use [azurerm_databricks_workspace](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/databricks_workspace) resource to create Azure Databricks workspaces. ## Example Usage @@ -315,7 +315,7 @@ output "databricks_token" { ## Argument Reference --> **Note** All workspaces would be verified to get into runnable state or deleted upon failure. You can only update `credentials_id`, `network_id`, and `storage_customer_managed_key_id`, `private_access_settings_id` on a running workspace. +-> All workspaces would be verified to get into runnable state or deleted upon failure. You can only update `credentials_id`, `network_id`, and `storage_customer_managed_key_id`, `private_access_settings_id` on a running workspace. The following arguments are available: @@ -342,7 +342,7 @@ The following arguments are available: You can specify a `token` block in the body of the workspace resource, so that Terraform manages the refresh of the PAT token for the deployment user. The other option is to create [databricks_obo_token](obo_token.md), though it requires Premium or Enterprise plan enabled as well as more complex setup. Token block exposes `token_value`, that holds sensitive PAT token and optionally it can accept two arguments: --> **Note** Tokens managed by `token {}` block are recreated when expired. +-> Tokens managed by `token {}` block are recreated when expired. * `comment` - (Optional) Comment, that will appear in "User Settings / Access Tokens" page on Workspace UI. By default it's "Terraform PAT". * `lifetime_seconds` - (Optional) Token expiry lifetime. By default its 2592000 (30 days). @@ -392,7 +392,7 @@ You can reset local DNS caches before provisioning new workspaces with one of th ## Import --> **Note** Importing this resource is not currently supported. +!> Importing this resource is not currently supported. ## Related Resources diff --git a/docs/resources/notebook.md b/docs/resources/notebook.md index 1c00e64d4d..2f2bc46e79 100644 --- a/docs/resources/notebook.md +++ b/docs/resources/notebook.md @@ -44,7 +44,7 @@ resource "databricks_notebook" "lesson" { ## Argument Reference --> **Note** Notebook on Databricks workspace would only be changed, if Terraform stage did change. This means that any manual changes to managed notebook won't be overwritten by Terraform, if there's no local change to notebook sources. Notebooks are identified by their path, so changing notebook's name manually on the workspace and then applying Terraform state would result in creation of notebook from Terraform state. +-> Notebook on Databricks workspace would only be changed, if Terraform stage did change. This means that any manual changes to managed notebook won't be overwritten by Terraform, if there's no local change to notebook sources. Notebooks are identified by their path, so changing notebook's name manually on the workspace and then applying Terraform state would result in creation of notebook from Terraform state. The size of a notebook source code must not exceed a few megabytes. The following arguments are supported: diff --git a/docs/resources/obo_token.md b/docs/resources/obo_token.md index d43c6b6975..bd5a00c6ca 100644 --- a/docs/resources/obo_token.md +++ b/docs/resources/obo_token.md @@ -9,7 +9,7 @@ This resource creates [On-Behalf-Of tokens](https://docs.databricks.com/administ Creating a token for a narrowly-scoped service principal, that would be the only one (besides admins) allowed to use PAT token in this given workspace, keeping your automated deployment highly secure. --> **Note** A given declaration of `databricks_permissions.token_usage` would OVERWRITE permissions to use PAT tokens from any existing groups with token usage permissions such as the `users` group. To avoid this, be sure to include any desired groups in additional `access_control` blocks in the Terraform configuration file. +-> A given declaration of `databricks_permissions.token_usage` would OVERWRITE permissions to use PAT tokens from any existing groups with token usage permissions such as the `users` group. To avoid this, be sure to include any desired groups in additional `access_control` blocks in the Terraform configuration file. ```hcl resource "databricks_service_principal" "this" { @@ -78,7 +78,7 @@ In addition to all arguments above, the following attributes are exported: ## Import --> **Note** Importing this resource is not currently supported. +!> Importing this resource is not currently supported. ## Related Resources diff --git a/docs/resources/online_table.md b/docs/resources/online_table.md index dbaaeafa58..df026991aa 100644 --- a/docs/resources/online_table.md +++ b/docs/resources/online_table.md @@ -3,8 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_online_table (Resource) - --> **Note** This resource can only be used on a Unity Catalog-enabled workspace! +-> This resource can only be used on a Unity Catalog-enabled workspace! This resource allows you to create [Online Table](https://docs.databricks.com/en/machine-learning/feature-store/online-tables.html) in Databricks. An online table is a read-only copy of a Delta Table that is stored in row-oriented format optimized for online access. Online tables are fully serverless tables that auto-scale throughput capacity with the request load and provide low latency and high throughput access to data of any scale. Online tables are designed to work with Databricks Model Serving, Feature Serving, and retrieval-augmented generation (RAG) applications where they are used for fast data lookups. @@ -26,8 +25,7 @@ resource "databricks_online_table" "this" { ## Argument Reference --> **Note** If any parameter changes, online table is recreated. - +~> If any parameter changes, online table is recreated. The following arguments are supported - check [API docs](https://docs.databricks.com/api/workspace/onlinetables/create) for all supported parameters: diff --git a/docs/resources/permissions.md b/docs/resources/permissions.md index b47a43aba3..8e2e236dfe 100644 --- a/docs/resources/permissions.md +++ b/docs/resources/permissions.md @@ -6,13 +6,13 @@ subcategory: "Security" This resource allows you to generically manage [access control](https://docs.databricks.com/security/access-control/index.html) in Databricks workspaces. It ensures that only _admins_, _authenticated principal_ and those declared within `access_control` blocks would have specified access. It is not possible to remove management rights from _admins_ group. --> **Note** This resource is _authoritative_ for permissions on objects. Configuring this resource for an object will **OVERWRITE** any existing permissions of the same type unless imported, and changes made outside of Terraform will be reset. +~> This resource is _authoritative_ for permissions on objects. Configuring this resource for an object will **OVERWRITE** any existing permissions of the same type unless imported, and changes made outside of Terraform will be reset. --> **Note** It is not possible to lower permissions for `admins`, so Databricks Terraform Provider removes those `access_control` blocks automatically. +-> It is not possible to lower permissions for `admins`, so Databricks Terraform Provider removes those `access_control` blocks automatically. --> **Note** If multiple permission levels are specified for an identity (e.g. `CAN_RESTART` and `CAN_MANAGE` for a cluster), only the highest level permission is returned and will cause permanent drift. +-> If multiple permission levels are specified for an identity (e.g. `CAN_RESTART` and `CAN_MANAGE` for a cluster), only the highest level permission is returned and will cause permanent drift. --> **Warning** To manage access control on service principals, use [databricks_access_control_rule_set](access_control_rule_set.md). +~> To manage access control on service principals, use [databricks_access_control_rule_set](access_control_rule_set.md). ## Cluster usage @@ -347,7 +347,7 @@ resource "databricks_permissions" "notebook_usage_by_id" { } ``` --> **Note**: when importing a permissions resource, only the `notebook_id` is filled! +-> when importing a permissions resource, only the `notebook_id` is filled! ## Workspace file usage @@ -408,7 +408,7 @@ resource "databricks_permissions" "workspace_file_usage_by_id" { } ``` --> **Note**: when importing a permissions resource, only the `workspace_file_id` is filled! +-> when importing a permissions resource, only the `workspace_file_id` is filled! ## Folder usage @@ -474,7 +474,7 @@ resource "databricks_permissions" "folder_usage_by_id" { } ``` --> **Note**: when importing a permissions resource, only the `directory_id` is filled! +-> when importing a permissions resource, only the `directory_id` is filled! ## Repos usage @@ -801,7 +801,7 @@ resource "databricks_permissions" "sql_dashboard_usage" { [SQL queries](https://docs.databricks.com/sql/user/security/access-control/query-acl.html) have three possible permissions: `CAN_VIEW`, `CAN_RUN` and `CAN_MANAGE`: --> **Note** If you do not define an `access_control` block granting `CAN_MANAGE` explictly for the user calling this provider, Databricks Terraform Provider will add `CAN_MANAGE` permission for the caller. This is a failsafe to prevent situations where the caller is locked out from making changes to the targeted `databricks_sql_query` resource when backend API do not apply permission inheritance correctly. +-> If you do not define an `access_control` block granting `CAN_MANAGE` explictly for the user calling this provider, Databricks Terraform Provider will add `CAN_MANAGE` permission for the caller. This is a failsafe to prevent situations where the caller is locked out from making changes to the targeted `databricks_sql_query` resource when backend API do not apply permission inheritance correctly. ```hcl resource "databricks_group" "auto" { @@ -912,7 +912,7 @@ access_control { Arguments for the `access_control` block are: --> **Note** It is not possible to lower permissions for `admins` or your own user anywhere from `CAN_MANAGE` level, so Databricks Terraform Provider [removes](https://github.com/databricks/terraform-provider-databricks/blob/main/permissions/resource_permissions.go#L324-L332) those `access_control` blocks automatically. +-> It is not possible to lower permissions for `admins` or your own user anywhere from `CAN_MANAGE` level, so Databricks Terraform Provider [removes](https://github.com/databricks/terraform-provider-databricks/blob/main/permissions/resource_permissions.go#L324-L332) those `access_control` blocks automatically. - `permission_level` - (Required) permission level according to specific resource. See examples above for the reference. diff --git a/docs/resources/provider.md b/docs/resources/provider.md index 25ebe76601..6366a1f69b 100644 --- a/docs/resources/provider.md +++ b/docs/resources/provider.md @@ -3,13 +3,13 @@ subcategory: "Delta Sharing" --- # databricks_provider Resource --> **Note** This resource can only be used with a workspace-level provider! +-> This resource can only be used with a workspace-level provider! In Delta Sharing, a provider is an entity that shares data with a recipient. Within a metastore, Unity Catalog provides the ability to create a provider which contains a list of shares that have been shared with you. A `databricks_provider` is contained within [databricks_metastore](metastore.md) and can contain a list of shares that have been shared with you. -Note that Databricks to Databricks sharing automatically creates the provider. +-> Databricks to Databricks sharing automatically creates the provider. ## Example Usage diff --git a/docs/resources/recipient.md b/docs/resources/recipient.md index 6df597ea92..0f88cd05ea 100644 --- a/docs/resources/recipient.md +++ b/docs/resources/recipient.md @@ -3,7 +3,7 @@ subcategory: "Delta Sharing" --- # databricks_recipient Resource --> **Note** This resource can only be used with a workspace-level provider! +-> This resource can only be used with a workspace-level provider! In Delta Sharing, a recipient is an entity that receives shares from a provider. In Unity Catalog, a share is a securable object that represents an organization and associates it with a credential or secure sharing identifier that allows that organization to access one or more shares. diff --git a/docs/resources/registered_model.md b/docs/resources/registered_model.md index 44c583102b..4de27e474d 100644 --- a/docs/resources/registered_model.md +++ b/docs/resources/registered_model.md @@ -3,7 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_registered_model Resource --> **Note** This resource can only be used with a workspace-level provider! +-> This resource can only be used with a workspace-level provider! This resource allows you to create [Models in Unity Catalog](https://docs.databricks.com/en/mlflow/models-in-uc.html) in Databricks. diff --git a/docs/resources/repo.md b/docs/resources/repo.md index b7d40b93ab..c03805ee4f 100644 --- a/docs/resources/repo.md +++ b/docs/resources/repo.md @@ -5,7 +5,7 @@ subcategory: "Workspace" This resource allows you to manage [Databricks Git folders](https://docs.databricks.com/en/repos/index.html) (formerly known as Databricks Repos). --> **Note** To create a Git folder from a private repository you need to configure Git token as described in the [documentation](https://docs.databricks.com/en/repos/index.html#configure-your-git-integration-with-databricks). To set this token you can use [databricks_git_credential](git_credential.md) resource. +-> To create a Git folder from a private repository you need to configure Git token as described in the [documentation](https://docs.databricks.com/en/repos/index.html#configure-your-git-integration-with-databricks). To set this token you can use [databricks_git_credential](git_credential.md) resource. ## Example Usage @@ -20,7 +20,7 @@ resource "databricks_repo" "nutter_in_home" { ## Argument Reference --> **Note** Git folder in Databricks workspace would only be changed, if Terraform stage did change. This means that any manual changes to managed repository won't be overwritten by Terraform, if there's no local changes to configuration. If Git folder in Databricks workspace is modified, application of configuration changes will fail. +-> Git folder in Databricks workspace would only be changed, if Terraform stage did change. This means that any manual changes to managed repository won't be overwritten by Terraform, if there's no local changes to configuration. If Git folder in Databricks workspace is modified, application of configuration changes will fail. The following arguments are supported: diff --git a/docs/resources/restrict_workspace_admins_setting.md b/docs/resources/restrict_workspace_admins_setting.md index 765825f866..988fed0052 100644 --- a/docs/resources/restrict_workspace_admins_setting.md +++ b/docs/resources/restrict_workspace_admins_setting.md @@ -4,7 +4,7 @@ subcategory: "Settings" # databricks_restrict_workspace_admins_setting Resource --> **Note** This resource can only be used with a workspace-level provider! +-> This resource can only be used with a workspace-level provider! The `databricks_restrict_workspace_admins_setting` resource lets you control the capabilities of workspace admins. @@ -20,7 +20,7 @@ With the status set to `RESTRICT_TOKENS_AND_JOB_RUN_AS`, workspace admins can: 2. Only change a job owner to themselves. 3. Only change the job run_as setting to themselves a service principal on which they have the Service Principal User role. --> **Note** Only account admins can update the setting. And the account admin must be part of the workspace to change the setting status. +~> Only account admins can update the setting. And the account admin must be part of the workspace to change the setting status. ## Example Usage diff --git a/docs/resources/schema.md b/docs/resources/schema.md index 65a144c4e9..1f1442ee7d 100644 --- a/docs/resources/schema.md +++ b/docs/resources/schema.md @@ -3,7 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_schema Resource --> **Note** This resource can only be used with a workspace-level provider! +-> This resource can only be used with a workspace-level provider! Within a metastore, Unity Catalog provides a 3-level namespace for organizing data: Catalogs, Databases (also called Schemas), and Tables / Views. diff --git a/docs/resources/service_principal.md b/docs/resources/service_principal.md index 717b76acc7..cac064512a 100644 --- a/docs/resources/service_principal.md +++ b/docs/resources/service_principal.md @@ -11,9 +11,9 @@ There are different types of service principals: * Databricks-managed - exists only inside the Databricks platform (all clouds) and couldn't be used for accessing non-Databricks services. * Azure-managed - existing Azure service principal (enterprise application) is registered inside Databricks. It could be used to work with other Azure services. --> **Note** To assign account level service principals to workspace use [databricks_mws_permission_assignment](mws_permission_assignment.md). +-> To assign account level service principals to workspace use [databricks_mws_permission_assignment](mws_permission_assignment.md). --> **Note** Entitlements, like, `allow_cluster_create`, `allow_instance_pool_create`, `databricks_sql_access`, `workspace_access` applicable only for workspace-level service principals. Use [databricks_entitlements](entitlements.md) resource to assign entitlements inside a workspace to account-level service principals. +-> Entitlements, like, `allow_cluster_create`, `allow_instance_pool_create`, `databricks_sql_access`, `workspace_access` applicable only for workspace-level service principals. Use [databricks_entitlements](entitlements.md) resource to assign entitlements inside a workspace to account-level service principals. To create service principals in the Databricks account, the provider must be configured with `host = "https://accounts.cloud.databricks.com"` on AWS deployments or `host = "https://accounts.azuredatabricks.net"` and authenticate using the supported authentication method for account operations. diff --git a/docs/resources/service_principal_role.md b/docs/resources/service_principal_role.md index 511089d7b0..f7ef4371d0 100644 --- a/docs/resources/service_principal_role.md +++ b/docs/resources/service_principal_role.md @@ -39,7 +39,7 @@ In addition to all arguments above, the following attributes are exported: ## Import --> **Note** Importing this resource is not currently supported. +!> Importing this resource is not currently supported. ## Related Resources diff --git a/docs/resources/service_principal_secret.md b/docs/resources/service_principal_secret.md index f98abd9b3e..05f740d864 100644 --- a/docs/resources/service_principal_secret.md +++ b/docs/resources/service_principal_secret.md @@ -3,7 +3,7 @@ subcategory: "Security" --- # databricks_service_principal_secret Resource --> **Note** This resource can only be used with an account-level provider. +-> This resource can only be used with an account-level provider. With this resource you can create a secret for a given [Service Principals](https://docs.databricks.com/administration-guide/users-groups/service-principals.html). diff --git a/docs/resources/share.md b/docs/resources/share.md index 38252a8818..5dfb7128c0 100644 --- a/docs/resources/share.md +++ b/docs/resources/share.md @@ -3,7 +3,7 @@ subcategory: "Delta Sharing" --- # databricks_share Resource --> **Note** This resource can only be used with a workspace-level provider! +-> This resource can only be used with a workspace-level provider! In Delta Sharing, a share is a read-only collection of tables and table partitions that a provider wants to share with one or more recipients. If your recipient uses a Unity Catalog-enabled Databricks workspace, you can also include notebook files, views (including dynamic views that restrict access at the row and column level), Unity Catalog volumes, and Unity Catalog models in a share. @@ -11,7 +11,7 @@ In a Unity Catalog-enabled Databricks workspace, a share is a securable object r ## Example Usage --> **Note** In Terraform configuration, it is recommended to define objects in alphabetical order of their `name` arguments, so that you get consistent and readable diff. Whenever objects are added or removed, or `name` is renamed, you'll observe a change in the majority of tasks. It's related to the fact that the current version of the provider treats `object` blocks as an ordered list. Alternatively, `object` block could have been an unordered set, though end-users would see the entire block replaced upon a change in single property of the task. +-> In Terraform configuration, it is recommended to define objects in alphabetical order of their `name` arguments, so that you get consistent and readable diff. Whenever objects are added or removed, or `name` is renamed, you'll observe a change in the majority of tasks. It's related to the fact that the current version of the provider treats `object` blocks as an ordered list. Alternatively, `object` block could have been an unordered set, though end-users would see the entire block replaced upon a change in single property of the task. Creating a Delta Sharing share and add some existing tables to it diff --git a/docs/resources/sql_alert.md b/docs/resources/sql_alert.md index f523c2acc7..689a52a5d5 100644 --- a/docs/resources/sql_alert.md +++ b/docs/resources/sql_alert.md @@ -5,7 +5,7 @@ subcategory: "Databricks SQL" This resource allows you to manage [Databricks SQL Alerts](https://docs.databricks.com/sql/user/queries/index.html). -**Note:** To manage [SQLA resources](https://docs.databricks.com/sql/get-started/concepts.html) you must have `databricks_sql_access` on your [databricks_group](group.md#databricks_sql_access) or [databricks_user](user.md#databricks_sql_access). +-> To manage [SQLA resources](https://docs.databricks.com/sql/get-started/concepts.html) you must have `databricks_sql_access` on your [databricks_group](group.md#databricks_sql_access) or [databricks_user](user.md#databricks_sql_access). ## Example Usage diff --git a/docs/resources/sql_dashboard.md b/docs/resources/sql_dashboard.md index 42551121a2..5c153f96c1 100644 --- a/docs/resources/sql_dashboard.md +++ b/docs/resources/sql_dashboard.md @@ -3,12 +3,12 @@ subcategory: "Databricks SQL" --- # databricks_sql_dashboard Resource --> **Note:** Please switch to [databricks_dashboard](dashboard.md) to author new AI/BI dashboards using the latest tooling +-> Please switch to [databricks_dashboard](dashboard.md) to author new AI/BI dashboards using the latest tooling. This resource is used to manage [Legacy dashboards](https://docs.databricks.com/sql/user/dashboards/index.html). To manage [SQL resources](https://docs.databricks.com/sql/get-started/concepts.html) you must have `databricks_sql_access` on your [databricks_group](group.md#databricks_sql_access) or [databricks_user](user.md#databricks_sql_access). --> **Note:** documentation for this resource is a work in progress. +-> documentation for this resource is a work in progress. A dashboard may have one or more [widgets](sql_widget.md). diff --git a/docs/resources/sql_permissions.md b/docs/resources/sql_permissions.md index 663cd92dbe..43f754391e 100644 --- a/docs/resources/sql_permissions.md +++ b/docs/resources/sql_permissions.md @@ -3,7 +3,7 @@ subcategory: "Security" --- # databricks_sql_permissions Resource --> **Note** Please switch to [databricks_grants](grants.md) with Unity Catalog to manage data access, which provides a better and faster way for managing data security. `databricks_grants` resource *doesn't require a technical cluster to perform operations*. On workspaces with Unity Catalog enabled, you may run into errors such as `Error: cannot create sql permissions: cannot read current grants: For unity catalog, please specify the catalog name explicitly. E.g. SHOW GRANT ``your.address@email.com`` ON CATALOG main`. This happens if your `default_catalog_name` was set to a UC catalog instead of `hive_metastore`. The workaround is to re-assign the metastore again with the default catalog set to be `hive_metastore`. See [databricks_metastore_assignment](metastore_assignment.md). +-> Please switch to [databricks_grants](grants.md) with Unity Catalog to manage data access, which provides a better and faster way for managing data security. `databricks_grants` resource *doesn't require a technical cluster to perform operations*. On workspaces with Unity Catalog enabled, you may run into errors such as `Error: cannot create sql permissions: cannot read current grants: For unity catalog, please specify the catalog name explicitly. E.g. SHOW GRANT ``your.address@email.com`` ON CATALOG main`. This happens if your `default_catalog_name` was set to a UC catalog instead of `hive_metastore`. The workaround is to re-assign the metastore again with the default catalog set to be `hive_metastore`. See [databricks_metastore_assignment](metastore_assignment.md). This resource manages data object access control lists in Databricks workspaces for things like tables, views, databases, and [more](https://docs.databricks.com/security/access-control/table-acls/object-privileges.html). In order to enable Table Access control, you have to login to the workspace as administrator, go to `Admin Console`, pick `Access Control` tab, click on `Enable` button in `Table Access Control` section, and click `Confirm`. The security guarantees of table access control **will only be effective if cluster access control is also turned on**. Please make sure that no users can create clusters in your workspace and all [databricks_cluster](cluster.md) have approximately the following configuration: diff --git a/docs/resources/sql_query.md b/docs/resources/sql_query.md index 27e12e03ea..90120a28a2 100644 --- a/docs/resources/sql_query.md +++ b/docs/resources/sql_query.md @@ -5,7 +5,7 @@ subcategory: "Databricks SQL" To manage [SQLA resources](https://docs.databricks.com/sql/get-started/concepts.html) you must have `databricks_sql_access` on your [databricks_group](group.md#databricks_sql_access) or [databricks_user](user.md#databricks_sql_access). -**Note:** documentation for this resource is a work in progress. +-> documentation for this resource is a work in progress. A query may have one or more [visualizations](sql_visualization.md). diff --git a/docs/resources/sql_visualization.md b/docs/resources/sql_visualization.md index b9ea7d6c99..b9dcf3b3a6 100644 --- a/docs/resources/sql_visualization.md +++ b/docs/resources/sql_visualization.md @@ -5,7 +5,7 @@ subcategory: "Databricks SQL" To manage [SQLA resources](https://docs.databricks.com/sql/get-started/concepts.html) you must have `databricks_sql_access` on your [databricks_group](group.md#databricks_sql_access) or [databricks_user](user.md#databricks_sql_access). -**Note:** documentation for this resource is a work in progress. +-> documentation for this resource is a work in progress. A visualization is always tied to a [query](sql_query.md). Every query may have one or more visualizations. diff --git a/docs/resources/sql_widget.md b/docs/resources/sql_widget.md index e890142dd8..05fed72737 100644 --- a/docs/resources/sql_widget.md +++ b/docs/resources/sql_widget.md @@ -3,11 +3,11 @@ subcategory: "Databricks SQL" --- # databricks_sql_widget Resource --> **Note:** Please switch to [databricks_dashboard](dashboard.md) to author new AI/BI dashboards using the latest tooling +-> Please switch to [databricks_dashboard](dashboard.md) to author new AI/BI dashboards using the latest tooling To manage [SQL resources](https://docs.databricks.com/sql/get-started/concepts.html) you must have `databricks_sql_access` on your [databricks_group](group.md#databricks_sql_access) or [databricks_user](user.md#databricks_sql_access). --> **Note:** documentation for this resource is a work in progress. +-> documentation for this resource is a work in progress. A widget is always tied to a [Legacy dashboard](sql_dashboard.md). Every dashboard may have one or more widgets. diff --git a/docs/resources/storage_credential.md b/docs/resources/storage_credential.md index b57120e8dd..87d90b853b 100644 --- a/docs/resources/storage_credential.md +++ b/docs/resources/storage_credential.md @@ -3,7 +3,7 @@ subcategory: "Unity Catalog" --- # databricks_storage_credential Resource --> **Note** This resource can be used with an account or workspace-level provider. +-> This resource can be used with an account or workspace-level provider. To work with external tables, Unity Catalog introduces two new objects to access and work with external cloud storage: diff --git a/docs/resources/system_schema.md b/docs/resources/system_schema.md index 80634f0859..02945703f9 100644 --- a/docs/resources/system_schema.md +++ b/docs/resources/system_schema.md @@ -3,9 +3,9 @@ subcategory: "Unity Catalog" --- # databricks_system_schema Resource --> **Public Preview** This feature is in [Public Preview](https://docs.databricks.com/release-notes/release-types.html). +-> This feature is in [Public Preview](https://docs.databricks.com/release-notes/release-types.html). --> **Note** This resource can only be used with a workspace-level provider! +-> This resource can only be used with a workspace-level provider! Manages system tables enablement. System tables are a Databricks-hosted analytical store of your account’s operational data. System tables can be used for historical observability across your account. System tables must be enabled by an account admin. diff --git a/docs/resources/token.md b/docs/resources/token.md index 307a604c11..281399cffc 100644 --- a/docs/resources/token.md +++ b/docs/resources/token.md @@ -62,4 +62,4 @@ In addition to all arguments above, the following attributes are exported: ## Import --> **Note** Importing this resource is not currently supported. +!> Importing this resource is not currently supported. diff --git a/docs/resources/user.md b/docs/resources/user.md index 03e16365c3..1e5633e541 100644 --- a/docs/resources/user.md +++ b/docs/resources/user.md @@ -5,9 +5,9 @@ subcategory: "Security" This resource allows you to manage [users in Databricks Workspace](https://docs.databricks.com/administration-guide/users-groups/users.html), [Databricks Account Console](https://accounts.cloud.databricks.com/) or [Azure Databricks Account Console](https://accounts.azuredatabricks.net). You can also [associate](group_member.md) Databricks users to [databricks_group](group.md). Upon user creation the user will receive a welcome email. You can also get information about caller identity using [databricks_current_user](../data-sources/current_user.md) data source. --> **Note** To assign account level users to workspace use [databricks_mws_permission_assignment](mws_permission_assignment.md). +-> To assign account level users to workspace use [databricks_mws_permission_assignment](mws_permission_assignment.md). --> **Note** Entitlements, like, `allow_cluster_create`, `allow_instance_pool_create`, `databricks_sql_access`, `workspace_access` applicable only for workspace-level users. Use [databricks_entitlements](entitlements.md) resource to assign entitlements inside a workspace to account-level users. +-> Entitlements, like, `allow_cluster_create`, `allow_instance_pool_create`, `databricks_sql_access`, `workspace_access` applicable only for workspace-level users. Use [databricks_entitlements](entitlements.md) resource to assign entitlements inside a workspace to account-level users. To create users in the Databricks account, the provider must be configured with `host = "https://accounts.cloud.databricks.com"` on AWS deployments or `host = "https://accounts.azuredatabricks.net"` and authenticate using [AAD tokens](https://registry.terraform.io/providers/databricks/databricks/latest/docs#special-configurations-for-azure) on Azure deployments. diff --git a/docs/resources/user_instance_profile.md b/docs/resources/user_instance_profile.md index 88e6016c8e..1b050b386f 100644 --- a/docs/resources/user_instance_profile.md +++ b/docs/resources/user_instance_profile.md @@ -39,7 +39,7 @@ In addition to all arguments above, the following attributes are exported: ## Import --> **Note** Importing this resource is not currently supported. +!> Importing this resource is not currently supported. ## Related Resources diff --git a/docs/resources/user_role.md b/docs/resources/user_role.md index 5921b2c886..8ece375046 100644 --- a/docs/resources/user_role.md +++ b/docs/resources/user_role.md @@ -59,7 +59,7 @@ In addition to all arguments above, the following attributes are exported: ## Import --> **Note** Importing this resource is not currently supported. +!> Importing this resource is not currently supported. ## Related Resources diff --git a/docs/resources/vector_search_endpoint.md b/docs/resources/vector_search_endpoint.md index c90de0c25a..4f167bc9f6 100644 --- a/docs/resources/vector_search_endpoint.md +++ b/docs/resources/vector_search_endpoint.md @@ -3,7 +3,7 @@ subcategory: "Mosaic AI Vector Search" --- # databricks_vector_search_endpoint Resource --> **Note** This resource can only be used on a Unity Catalog-enabled workspace! +-> This resource can only be used on a Unity Catalog-enabled workspace! This resource allows you to create [Mosaic AI Vector Search Endpoint](https://docs.databricks.com/en/generative-ai/vector-search.html) in Databricks. Mosaic AI Vector Search is a serverless similarity search engine that allows you to store a vector representation of your data, including metadata, in a vector database. The Mosaic AI Vector Search Endpoint is used to create and access vector search indexes. diff --git a/docs/resources/vector_search_index.md b/docs/resources/vector_search_index.md index 0de0ac2c1f..d06db90637 100644 --- a/docs/resources/vector_search_index.md +++ b/docs/resources/vector_search_index.md @@ -3,7 +3,7 @@ subcategory: "Mosaic AI Vector Search" --- # databricks_vector_search_index Resource --> **Note** This resource can only be used on a Unity Catalog-enabled workspace! +-> This resource can only be used on a Unity Catalog-enabled workspace! This resource allows you to create [Mosaic AI Vector Search Index](https://docs.databricks.com/en/generative-ai/create-query-vector-search.html) in Databricks. Mosaic AI Vector Search is a serverless similarity search engine that allows you to store a vector representation of your data, including metadata, in a vector database. The Mosaic AI Vector Search Index provides the ability to search data in the linked Delta Table. diff --git a/docs/resources/volume.md b/docs/resources/volume.md index b116e42129..e95f54d8f3 100644 --- a/docs/resources/volume.md +++ b/docs/resources/volume.md @@ -3,9 +3,9 @@ subcategory: "Unity Catalog" --- # databricks_volume (Resource) --> **Public Preview** This feature is in [Public Preview](https://docs.databricks.com/release-notes/release-types.html). +-> This feature is in [Public Preview](https://docs.databricks.com/release-notes/release-types.html). --> **Note** This resource can only be used with a workspace-level provider! +-> This resource can only be used with a workspace-level provider! Volumes are Unity Catalog objects representing a logical volume of storage in a cloud object storage location. Volumes provide capabilities for accessing, storing, governing, and organizing files. While tables provide governance over tabular datasets, volumes add governance over non-tabular datasets. You can use volumes to store and access files in any format, including structured, semi-structured, and unstructured data. diff --git a/docs/resources/workspace_binding.md b/docs/resources/workspace_binding.md index 5a649bd9e4..e7dd0105af 100644 --- a/docs/resources/workspace_binding.md +++ b/docs/resources/workspace_binding.md @@ -3,17 +3,15 @@ subcategory: "Unity Catalog" --- # databricks_workspace_binding Resource --> **Note** This resource can only be used with a workspace-level provider! +-> This resource can only be used with a workspace-level provider! If you use workspaces to isolate user data access, you may want to limit access to catalog, external locations or storage credentials from specific workspaces in your account, also known as workspace binding By default, Databricks assigns the securable to all workspaces attached to the current metastore. By using `databricks_workspace_binding`, the securable will be unassigned from all workspaces and only assigned explicitly using this resource. --> **Note** - To use this resource the securable must have its isolation mode set to `ISOLATED` (for [databricks_catalog](catalog.md)) or `ISOLATION_MODE_ISOLATED` (for (for [databricks_external_location](external_location.md) or [databricks_storage_credential](storage_credential.md)) for the `isolation_mode` attribute. Alternatively, the isolation mode can be set using the UI or API by following [this guide](https://docs.databricks.com/data-governance/unity-catalog/create-catalogs.html#configuration), [this guide](https://docs.databricks.com/en/connect/unity-catalog/external-locations.html#workspace-binding) or [this guide](https://docs.databricks.com/en/connect/unity-catalog/storage-credentials.html#optional-assign-a-storage-credential-to-specific-workspaces). +-> To use this resource the securable must have its isolation mode set to `ISOLATED` (for [databricks_catalog](catalog.md)) or `ISOLATION_MODE_ISOLATED` (for (for [databricks_external_location](external_location.md) or [databricks_storage_credential](storage_credential.md)) for the `isolation_mode` attribute. Alternatively, the isolation mode can be set using the UI or API by following [this guide](https://docs.databricks.com/data-governance/unity-catalog/create-catalogs.html#configuration), [this guide](https://docs.databricks.com/en/connect/unity-catalog/external-locations.html#workspace-binding) or [this guide](https://docs.databricks.com/en/connect/unity-catalog/storage-credentials.html#optional-assign-a-storage-credential-to-specific-workspaces). --> **Note** - If the securable's isolation mode was set to `ISOLATED` using Terraform then the securable will have been automatically bound to the workspace it was created from. +-> If the securable's isolation mode was set to `ISOLATED` using Terraform then the securable will have been automatically bound to the workspace it was created from. ## Example Usage diff --git a/docs/resources/workspace_conf.md b/docs/resources/workspace_conf.md index 0986f8a133..6e02461381 100644 --- a/docs/resources/workspace_conf.md +++ b/docs/resources/workspace_conf.md @@ -4,11 +4,11 @@ subcategory: "Workspace" # databricks_workspace_conf Resource --> **Note** This resource has an evolving API, which may change in future versions of the provider. +~> This resource has an evolving API, which may change in future versions of the provider. Manages workspace configuration for expert usage. Currently, more than one instance of resource can exist in Terraform state, though there's no deterministic behavior, when they manage the same property. We strongly recommend to use a single `databricks_workspace_conf` per workspace. --> **Note** Deleting `databricks_workspace_conf` resources may fail depending on the configuration properties set, including but not limited to `enableIpAccessLists`, `enableGp3`, and `maxTokenLifetimeDays`. The provider will print a warning if this occurs. You can verify the workspace configuration by reviewing [the workspace settings in the UI](https://docs.databricks.com/en/admin/workspace-settings/index.html). +-> Deleting `databricks_workspace_conf` resources may fail depending on the configuration properties set, including but not limited to `enableIpAccessLists`, `enableGp3`, and `maxTokenLifetimeDays`. The provider will print a warning if this occurs. You can verify the workspace configuration by reviewing [the workspace settings in the UI](https://docs.databricks.com/en/admin/workspace-settings/index.html). ## Example Usage @@ -36,4 +36,4 @@ The following arguments are available: ## Import --> **Note** Importing this resource is not currently supported. +!> Importing this resource is not currently supported. diff --git a/docs/resources/workspace_file.md b/docs/resources/workspace_file.md index f7cbc8e1de..997e7eac24 100644 --- a/docs/resources/workspace_file.md +++ b/docs/resources/workspace_file.md @@ -34,7 +34,7 @@ resource "databricks_workspace_file" "init_script" { ## Argument Reference --> **Note** Files in Databricks workspace would only be changed, if Terraform stage did change. This means that any manual changes to managed workspace files won't be overwritten by Terraform, if there's no local change to file sources. Workspace files are identified by their path, so changing file's name manually on the workspace and then applying Terraform state would result in creation of workspace file from Terraform state. +-> Files in Databricks workspace would only be changed, if Terraform stage did change. This means that any manual changes to managed workspace files won't be overwritten by Terraform, if there's no local change to file sources. Workspace files are identified by their path, so changing file's name manually on the workspace and then applying Terraform state would result in creation of workspace file from Terraform state. The size of a workspace file source code must not exceed a few megabytes. The following arguments are supported: From c56bc9028885e588204aec574a2e55c5ff38cb3f Mon Sep 17 00:00:00 2001 From: Callum Dempsey Leach Date: Mon, 7 Oct 2024 12:25:40 +0100 Subject: [PATCH 50/54] [Fix] Add Sufficient Network Privileges to the Databricks Default Cross Account Policy (#4027) ## Changes Currently, the Databricks-provided Cross Account Policy IAM Role does not include all the necessary permissions to set up a workspace. Attempting to set up a workspace using this policy results in the following error (see [Issue #4026](https://github.com/databricks/terraform-provider-databricks/issues/4026)): ``` MALFORMED_REQUEST: Failed credentials validation checks: Allocate Address ``` This makes it difficult for new engineers to onboard to Databricks without troubleshooting unexpected errors. This PR adds the missing network permissions to the Databricks Managed VPC policy types ("managed" and "customer"), ensuring that all required permissions are included for successful workspace deployment. These changes are not applied to the "restricted" policy type to avoid allowing Elastic IP allocations, which may not be desirable for some Databricks customers. See the bottom of the description for the full list. ## Tests This change has been tested locally and is running in our staging workspace using the same configuration. As this is a fix for 'managed' type Databricks deployment configurations, I have matched this with positive and negative unit tests to guard precise and expected roles. I have then added extra tests to confirm the expected policies across each branch, 'managed', 'customer', and 'restricted'. Feel free to remove these if overboard, as I recognise you _could_ make a similar weaker assertion using 'len'. - [x] `make test` run locally - [x] Relevant acceptance tests are passing - [ ] Relevant change in `docs/` folder (if necessary) - [x] Covered with integration tests in `internal/acceptance` - [ ] Using Go SDK (N/A) The full list of permissions which align with the Databricks documentation, now included in the "managed" policy type, are: ```json [ "ec2:AllocateAddress", "ec2:AssignPrivateIpAddresses", "ec2:AssociateDhcpOptions", "ec2:AssociateIamInstanceProfile", "ec2:AssociateRouteTable", "ec2:AttachInternetGateway", "ec2:AttachVolume", "ec2:AuthorizeSecurityGroupEgress", "ec2:AuthorizeSecurityGroupIngress", "ec2:CancelSpotInstanceRequests", "ec2:CreateDhcpOptions", "ec2:CreateFleet", "ec2:CreateInternetGateway", "ec2:CreateLaunchTemplate", "ec2:CreateLaunchTemplateVersion", "ec2:CreateNatGateway", "ec2:CreateRoute", "ec2:CreateRouteTable", "ec2:CreateSecurityGroup", "ec2:CreateSubnet", "ec2:CreateTags", "ec2:CreateVolume", "ec2:CreateVpc", "ec2:CreateVpcEndpoint", "ec2:DeleteDhcpOptions", "ec2:DeleteFleets", "ec2:DeleteInternetGateway", "ec2:DeleteLaunchTemplate", "ec2:DeleteLaunchTemplateVersions", "ec2:DeleteNatGateway", "ec2:DeleteRoute", "ec2:DeleteRouteTable", "ec2:DeleteSecurityGroup", "ec2:DeleteSubnet", "ec2:DeleteTags", "ec2:DeleteVolume", "ec2:DeleteVpc", "ec2:DeleteVpcEndpoints", "ec2:DescribeAvailabilityZones", "ec2:DescribeFleetHistory", "ec2:DescribeFleetInstances", "ec2:DescribeFleets", "ec2:DescribeIamInstanceProfileAssociations", "ec2:DescribeInstanceStatus", "ec2:DescribeInstances", "ec2:DescribeInternetGateways", "ec2:DescribeLaunchTemplates", "ec2:DescribeLaunchTemplateVersions", "ec2:DescribeNatGateways", "ec2:DescribeNetworkAcls", "ec2:DescribePrefixLists", "ec2:DescribeReservedInstancesOfferings", "ec2:DescribeRouteTables", "ec2:DescribeSecurityGroups", "ec2:DescribeSpotInstanceRequests", "ec2:DescribeSpotPriceHistory", "ec2:DescribeSubnets", "ec2:DescribeVolumes", "ec2:DescribeVpcAttribute", "ec2:DescribeVpcs", "ec2:DetachInternetGateway", "ec2:DisassociateIamInstanceProfile", "ec2:DisassociateRouteTable", "ec2:GetLaunchTemplateData", "ec2:GetSpotPlacementScores", "ec2:ModifyFleet", "ec2:ModifyLaunchTemplate", "ec2:ModifyVpcAttribute", "ec2:ReleaseAddress", "ec2:ReplaceIamInstanceProfileAssociation", "ec2:RequestSpotInstances", "ec2:RevokeSecurityGroupEgress", "ec2:RevokeSecurityGroupIngress", "ec2:RunInstances", "ec2:TerminateInstances" ] ``` Resolves #4026 --- aws/data_aws_crossaccount_policy.go | 4 + aws/data_aws_crossaccount_policy_test.go | 471 ++++++++++++++++++++++- 2 files changed, 473 insertions(+), 2 deletions(-) diff --git a/aws/data_aws_crossaccount_policy.go b/aws/data_aws_crossaccount_policy.go index 6737e9376a..a5da5d9365 100644 --- a/aws/data_aws_crossaccount_policy.go +++ b/aws/data_aws_crossaccount_policy.go @@ -103,6 +103,10 @@ func DataAwsCrossaccountPolicy() common.Resource { // additional permissions for Databricks-managed VPC policy if data.PolicyType == "managed" { actions = append(actions, []string{ + "ec2:AttachInternetGateway", + "ec2:AllocateAddress", + "ec2:AssociateDhcpOptions", + "ec2:AssociateRouteTable", "ec2:CreateDhcpOptions", "ec2:CreateInternetGateway", "ec2:CreateNatGateway", diff --git a/aws/data_aws_crossaccount_policy_test.go b/aws/data_aws_crossaccount_policy_test.go index 2bdf183993..177cb166e9 100644 --- a/aws/data_aws_crossaccount_policy_test.go +++ b/aws/data_aws_crossaccount_policy_test.go @@ -16,7 +16,7 @@ func TestDataAwsCrossAccountDatabricksManagedPolicy(t *testing.T) { }.Apply(t) assert.NoError(t, err) j := d.Get("json") - assert.Lenf(t, j, 3032, "Strange length for policy: %s", j) + assert.Lenf(t, j, 3171, "Strange length for policy: %s", j) } func TestDataAwsCrossAccountCustomerManagedPolicy(t *testing.T) { @@ -42,7 +42,474 @@ func TestDataAwsCrossAccountPolicy_WithPassRoles(t *testing.T) { }.Apply(t) assert.NoError(t, err) j := d.Get("json") - assert.Lenf(t, j, 3168, "Strange length for policy: %s", j) + assert.Lenf(t, j, 3307, "Strange length for policy: %s", j) +} + +func TestDataAwsCrossAccountManagedPolicyRoles(t *testing.T) { + expectedJSON := `{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "ec2:AssignPrivateIpAddresses", + "ec2:CancelSpotInstanceRequests", + "ec2:DescribeAvailabilityZones", + "ec2:DescribeIamInstanceProfileAssociations", + "ec2:DescribeInstanceStatus", + "ec2:DescribeInstances", + "ec2:DescribeInternetGateways", + "ec2:DescribeNatGateways", + "ec2:DescribeNetworkAcls", + "ec2:DescribePrefixLists", + "ec2:DescribeReservedInstancesOfferings", + "ec2:DescribeRouteTables", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSpotInstanceRequests", + "ec2:DescribeSpotPriceHistory", + "ec2:DescribeSubnets", + "ec2:DescribeVolumes", + "ec2:DescribeVpcAttribute", + "ec2:DescribeVpcs", + "ec2:CreateTags", + "ec2:DeleteTags", + "ec2:GetSpotPlacementScores", + "ec2:RequestSpotInstances", + "ec2:DescribeFleetHistory", + "ec2:ModifyFleet", + "ec2:DeleteFleets", + "ec2:DescribeFleetInstances", + "ec2:DescribeFleets", + "ec2:CreateFleet", + "ec2:DeleteLaunchTemplate", + "ec2:GetLaunchTemplateData", + "ec2:CreateLaunchTemplate", + "ec2:DescribeLaunchTemplates", + "ec2:DescribeLaunchTemplateVersions", + "ec2:ModifyLaunchTemplate", + "ec2:DeleteLaunchTemplateVersions", + "ec2:CreateLaunchTemplateVersion", + "ec2:AssociateIamInstanceProfile", + "ec2:AttachVolume", + "ec2:AuthorizeSecurityGroupEgress", + "ec2:AuthorizeSecurityGroupIngress", + "ec2:CreateVolume", + "ec2:DeleteVolume", + "ec2:DetachVolume", + "ec2:DisassociateIamInstanceProfile", + "ec2:ReplaceIamInstanceProfileAssociation", + "ec2:RevokeSecurityGroupEgress", + "ec2:RevokeSecurityGroupIngress", + "ec2:RunInstances", + "ec2:TerminateInstances", + "ec2:AttachInternetGateway", + "ec2:AllocateAddress", + "ec2:AssociateDhcpOptions", + "ec2:AssociateRouteTable", + "ec2:CreateDhcpOptions", + "ec2:CreateInternetGateway", + "ec2:CreateNatGateway", + "ec2:CreateRoute", + "ec2:CreateRouteTable", + "ec2:CreateSecurityGroup", + "ec2:CreateSubnet", + "ec2:CreateVpc", + "ec2:CreateVpcEndpoint", + "ec2:DeleteDhcpOptions", + "ec2:DeleteInternetGateway", + "ec2:DeleteNatGateway", + "ec2:DeleteRoute", + "ec2:DeleteRouteTable", + "ec2:DeleteSecurityGroup", + "ec2:DeleteSubnet", + "ec2:DeleteVpc", + "ec2:DeleteVpcEndpoints", + "ec2:DetachInternetGateway", + "ec2:DisassociateRouteTable", + "ec2:ModifyVpcAttribute", + "ec2:ReleaseAddress" + ], + "Resource": "*" + }, + { + "Effect": "Allow", + "Action": [ + "iam:CreateServiceLinkedRole", + "iam:PutRolePolicy" + ], + "Resource": "arn:aws:iam::*:role/aws-service-role/spot.amazonaws.com/AWSServiceRoleForEC2Spot", + "Condition": { + "StringLike": { + "iam:AWSServiceName": "spot.amazonaws.com" + } + } + } + ] +}` + + d, err := qa.ResourceFixture{ + Read: true, + Resource: DataAwsCrossaccountPolicy(), + NonWritable: true, + HCL: `policy_type = "managed"`, + ID: ".", + }.Apply(t) + assert.NoError(t, err) + actualJSON := d.Get("json").(string) + assert.Equal(t, expectedJSON, actualJSON) + + // Negative test: ensure that customer policy is not equal to customer policy + managedD, err := qa.ResourceFixture{ + Read: true, + Resource: DataAwsCrossaccountPolicy(), + NonWritable: true, + HCL: `policy_type = "customer"`, + ID: ".", + }.Apply(t) + assert.NoError(t, err) + managedJSON := managedD.Get("json").(string) + assert.NotEqual(t, actualJSON, managedJSON) +} + +func TestDataAwsCrossAccountCustomerManagedPolicyRoles(t *testing.T) { + expectedJSON := `{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "ec2:AssignPrivateIpAddresses", + "ec2:CancelSpotInstanceRequests", + "ec2:DescribeAvailabilityZones", + "ec2:DescribeIamInstanceProfileAssociations", + "ec2:DescribeInstanceStatus", + "ec2:DescribeInstances", + "ec2:DescribeInternetGateways", + "ec2:DescribeNatGateways", + "ec2:DescribeNetworkAcls", + "ec2:DescribePrefixLists", + "ec2:DescribeReservedInstancesOfferings", + "ec2:DescribeRouteTables", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSpotInstanceRequests", + "ec2:DescribeSpotPriceHistory", + "ec2:DescribeSubnets", + "ec2:DescribeVolumes", + "ec2:DescribeVpcAttribute", + "ec2:DescribeVpcs", + "ec2:CreateTags", + "ec2:DeleteTags", + "ec2:GetSpotPlacementScores", + "ec2:RequestSpotInstances", + "ec2:DescribeFleetHistory", + "ec2:ModifyFleet", + "ec2:DeleteFleets", + "ec2:DescribeFleetInstances", + "ec2:DescribeFleets", + "ec2:CreateFleet", + "ec2:DeleteLaunchTemplate", + "ec2:GetLaunchTemplateData", + "ec2:CreateLaunchTemplate", + "ec2:DescribeLaunchTemplates", + "ec2:DescribeLaunchTemplateVersions", + "ec2:ModifyLaunchTemplate", + "ec2:DeleteLaunchTemplateVersions", + "ec2:CreateLaunchTemplateVersion", + "ec2:AssociateIamInstanceProfile", + "ec2:AttachVolume", + "ec2:AuthorizeSecurityGroupEgress", + "ec2:AuthorizeSecurityGroupIngress", + "ec2:CreateVolume", + "ec2:DeleteVolume", + "ec2:DetachVolume", + "ec2:DisassociateIamInstanceProfile", + "ec2:ReplaceIamInstanceProfileAssociation", + "ec2:RevokeSecurityGroupEgress", + "ec2:RevokeSecurityGroupIngress", + "ec2:RunInstances", + "ec2:TerminateInstances" + ], + "Resource": "*" + }, + { + "Effect": "Allow", + "Action": [ + "iam:CreateServiceLinkedRole", + "iam:PutRolePolicy" + ], + "Resource": "arn:aws:iam::*:role/aws-service-role/spot.amazonaws.com/AWSServiceRoleForEC2Spot", + "Condition": { + "StringLike": { + "iam:AWSServiceName": "spot.amazonaws.com" + } + } + } + ] +}` + + d, err := qa.ResourceFixture{ + Read: true, + Resource: DataAwsCrossaccountPolicy(), + NonWritable: true, + HCL: `policy_type = "customer"`, + ID: ".", + }.Apply(t) + assert.NoError(t, err) + actualJSON := d.Get("json").(string) + assert.Equal(t, expectedJSON, actualJSON) + + // Negative test: ensure that customer policy is not equal to managed policy + managedD, err := qa.ResourceFixture{ + Read: true, + Resource: DataAwsCrossaccountPolicy(), + NonWritable: true, + HCL: `policy_type = "managed"`, + ID: ".", + }.Apply(t) + assert.NoError(t, err) + managedJSON := managedD.Get("json").(string) + assert.NotEqual(t, actualJSON, managedJSON) +} + +func TestDataAwsCrossAccountRestrictedPolicyRoles(t *testing.T) { + expectedJSON := `{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "ec2:AssignPrivateIpAddresses", + "ec2:CancelSpotInstanceRequests", + "ec2:DescribeAvailabilityZones", + "ec2:DescribeIamInstanceProfileAssociations", + "ec2:DescribeInstanceStatus", + "ec2:DescribeInstances", + "ec2:DescribeInternetGateways", + "ec2:DescribeNatGateways", + "ec2:DescribeNetworkAcls", + "ec2:DescribePrefixLists", + "ec2:DescribeReservedInstancesOfferings", + "ec2:DescribeRouteTables", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSpotInstanceRequests", + "ec2:DescribeSpotPriceHistory", + "ec2:DescribeSubnets", + "ec2:DescribeVolumes", + "ec2:DescribeVpcAttribute", + "ec2:DescribeVpcs", + "ec2:CreateTags", + "ec2:DeleteTags", + "ec2:GetSpotPlacementScores", + "ec2:RequestSpotInstances", + "ec2:DescribeFleetHistory", + "ec2:ModifyFleet", + "ec2:DeleteFleets", + "ec2:DescribeFleetInstances", + "ec2:DescribeFleets", + "ec2:CreateFleet", + "ec2:DeleteLaunchTemplate", + "ec2:GetLaunchTemplateData", + "ec2:CreateLaunchTemplate", + "ec2:DescribeLaunchTemplates", + "ec2:DescribeLaunchTemplateVersions", + "ec2:ModifyLaunchTemplate", + "ec2:DeleteLaunchTemplateVersions", + "ec2:CreateLaunchTemplateVersion" + ], + "Resource": "*" + }, + { + "Effect": "Allow", + "Action": [ + "iam:CreateServiceLinkedRole", + "iam:PutRolePolicy" + ], + "Resource": "arn:aws:iam::*:role/aws-service-role/spot.amazonaws.com/AWSServiceRoleForEC2Spot", + "Condition": { + "StringLike": { + "iam:AWSServiceName": "spot.amazonaws.com" + } + } + }, + { + "Sid": "InstancePoolsSupport", + "Effect": "Allow", + "Action": [ + "ec2:AssociateIamInstanceProfile", + "ec2:DisassociateIamInstanceProfile", + "ec2:ReplaceIamInstanceProfileAssociation" + ], + "Resource": "arn:aws:ec2:us-west-2:123456789012:instance/*", + "Condition": { + "StringEquals": { + "ec2:ResourceTag/Vendor": "Databricks" + } + } + }, + { + "Sid": "AllowEc2RunInstancePerTag", + "Effect": "Allow", + "Action": "ec2:RunInstances", + "Resource": [ + "arn:aws:ec2:us-west-2:123456789012:volume/*", + "arn:aws:ec2:us-west-2:123456789012:instance/*" + ], + "Condition": { + "StringEquals": { + "aws:RequestTag/Vendor": "Databricks" + } + } + }, + { + "Sid": "AllowEc2RunInstanceImagePerTag", + "Effect": "Allow", + "Action": "ec2:RunInstances", + "Resource": "arn:aws:ec2:us-west-2:123456789012:image/*", + "Condition": { + "StringEquals": { + "aws:ResourceTag/Vendor": "Databricks" + } + } + }, + { + "Sid": "AllowEc2RunInstancePerVPCid", + "Effect": "Allow", + "Action": "ec2:RunInstances", + "Resource": [ + "arn:aws:ec2:us-west-2:123456789012:network-interface/*", + "arn:aws:ec2:us-west-2:123456789012:subnet/*", + "arn:aws:ec2:us-west-2:123456789012:security-group/*" + ], + "Condition": { + "StringEquals": { + "ec2:vpc": "arn:aws:ec2:us-west-2:123456789012:vpc/vpc-abcdefg12345" + } + } + }, + { + "Sid": "AllowEc2RunInstanceOtherResources", + "Effect": "Allow", + "Action": "ec2:RunInstances", + "NotResource": [ + "arn:aws:ec2:us-west-2:123456789012:image/*", + "arn:aws:ec2:us-west-2:123456789012:network-interface/*", + "arn:aws:ec2:us-west-2:123456789012:subnet/*", + "arn:aws:ec2:us-west-2:123456789012:security-group/*", + "arn:aws:ec2:us-west-2:123456789012:volume/*", + "arn:aws:ec2:us-west-2:123456789012:instance/*" + ] + }, + { + "Sid": "EC2TerminateInstancesTag", + "Effect": "Allow", + "Action": "ec2:TerminateInstances", + "Resource": "arn:aws:ec2:us-west-2:123456789012:instance/*", + "Condition": { + "StringEquals": { + "ec2:ResourceTag/Vendor": "Databricks" + } + } + }, + { + "Sid": "EC2AttachDetachVolumeTag", + "Effect": "Allow", + "Action": [ + "ec2:AttachVolume", + "ec2:DetachVolume" + ], + "Resource": [ + "arn:aws:ec2:us-west-2:123456789012:instance/*", + "arn:aws:ec2:us-west-2:123456789012:volume/*" + ], + "Condition": { + "StringEquals": { + "ec2:ResourceTag/Vendor": "Databricks" + } + } + }, + { + "Sid": "EC2CreateVolumeByTag", + "Effect": "Allow", + "Action": "ec2:CreateVolume", + "Resource": "arn:aws:ec2:us-west-2:123456789012:volume/*", + "Condition": { + "StringEquals": { + "aws:RequestTag/Vendor": "Databricks" + } + } + }, + { + "Sid": "EC2DeleteVolumeByTag", + "Effect": "Allow", + "Action": "ec2:DeleteVolume", + "Resource": [ + "arn:aws:ec2:us-west-2:123456789012:volume/*" + ], + "Condition": { + "StringEquals": { + "ec2:ResourceTag/Vendor": "Databricks" + } + } + }, + { + "Sid": "VpcNonresourceSpecificActions", + "Effect": "Allow", + "Action": [ + "ec2:AuthorizeSecurityGroupEgress", + "ec2:AuthorizeSecurityGroupIngress", + "ec2:RevokeSecurityGroupEgress", + "ec2:RevokeSecurityGroupIngress" + ], + "Resource": "arn:aws:ec2:us-west-2:123456789012:security-group/sg-12345678", + "Condition": { + "StringEquals": { + "ec2:vpc": "arn:aws:ec2:us-west-2:123456789012:vpc/vpc-abcdefg12345" + } + } + } + ] +}` + + d, err := qa.ResourceFixture{ + Read: true, + Resource: DataAwsCrossaccountPolicy(), + NonWritable: true, + HCL: ` +policy_type = "restricted" +aws_account_id = "123456789012" +vpc_id = "vpc-abcdefg12345" +region = "us-west-2" +security_group_id = "sg-12345678" +`, + ID: ".", + }.Apply(t) + assert.NoError(t, err) + actualJSON := d.Get("json").(string) + assert.Equal(t, expectedJSON, actualJSON) + + // Negative test: ensure that restricted policy is not equal to managed policy + managedD, err := qa.ResourceFixture{ + Read: true, + Resource: DataAwsCrossaccountPolicy(), + NonWritable: true, + HCL: `policy_type = "managed"`, + ID: ".", + }.Apply(t) + assert.NoError(t, err) + managedJSON := managedD.Get("json").(string) + assert.NotEqual(t, actualJSON, managedJSON) + + // Negative test: ensure that restricted policy is not equal to customer policy + customerD, err := qa.ResourceFixture{ + Read: true, + Resource: DataAwsCrossaccountPolicy(), + NonWritable: true, + HCL: `policy_type = "customer"`, + ID: ".", + }.Apply(t) + assert.NoError(t, err) + customerJSON := customerD.Get("json").(string) + assert.NotEqual(t, actualJSON, customerJSON) } func TestDataAwsCrossAccountRestrictedPolicy(t *testing.T) { From 54d9b1762974050c2be68298ad4871720109b601 Mon Sep 17 00:00:00 2001 From: Tanmay Rustagi <88379306+tanmay-db@users.noreply.github.com> Date: Mon, 7 Oct 2024 16:49:59 +0200 Subject: [PATCH 51/54] [Doc] Update CONTRIBUTING guide for plugin framework resources (#4078) ## Changes Update the guide to give detailed information on how to navigate and get started with adding / migrating resources to plugin framework. ## Tests NA - [ ] `make test` run locally - [ ] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [ ] using Go SDK --- CONTRIBUTING.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4062159c53..ab38782660 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -118,6 +118,22 @@ We are migrating the resource from SDKv2 to Plugin Framework provider and hence - `pluginfw`: Contains the changes specific to Plugin Framework. This package shouldn't depend on sdkv2 or common. - `sdkv2`: Contains the changes specific to SDKv2. This package shouldn't depend on pluginfw or common. +### Adding a new resource +1. Check if the directory for this particular resource exists under `internal/providers/pluginfw/resources`, if not create the directory eg: `cluster`, `volume` etc... Please note: Resources and Data sources are organized under the same package for that service. +2. Create a file with resource_resource-name.go and write the CRUD methods, schema for that resource. For reference, please take a look at existing resources eg: `resource_quality_monitor.go` +3. Create a file with `resource_resource-name_acc_test.go` and add integration tests here. +4. Create a file with `resource_resource-name_test.go` and add unit tests here. Note: Please make sure to abstract specific method of the resource so they are unit test friendly and not testing internal part of terraform plugin framework library. You can compare the diagnostics, for example: please take a look at: `data_cluster_test.go` +5. Add the resource under `internal/providers/pluginfw/pluginfw.go` in `Resources()` method. Please update the list so that it stays in alphabetically sorted order. +6. Create a PR and send it for review. + +### Adding a new data source +1. Check if the directory for this particular datasource exists under `internal/providers/pluginfw/resources`, if not create the directory eg: `cluster`, `volume` etc... Please note: Resources and Data sources are organized under the same package for that service. +2. Create a file with `data_resource-name.go` and write the CRUD methods, schema for that data source. For reference, please take a look at existing data sources eg: `data_cluster.go` +3. Create a file with `data_resource-name_acc_test.go` and add integration tests here. +4. Create a file with `data_resource-name_test.go` and add unit tests here. Note: Please make sure to abstract specific method of the resource so they are unit test friendly and not testing internal part of terraform plugin framework library. You can compare the diagnostics, for example: please take a look at: `data_cluster_test.go` +5. Add the resource under `internal/providers/pluginfw/pluginfw.go` in `DataSources()` method. Please update the list so that it stays in alphabetically sorted order. +6. Create a PR and send it for review. + ### Migrating resource to plugin framework Ideally there shouldn't be any behaviour change when migrating a resource or data source to either Go SDk or Plugin Framework. - Please make sure there are no breaking differences due to changes in schema by running: `make diff-schema`. From 2557380827bf1c643a5c1525a3ff7362eb565c3d Mon Sep 17 00:00:00 2001 From: Parth Bansal Date: Mon, 7 Oct 2024 18:38:29 +0200 Subject: [PATCH 52/54] [Release] Release v1.53.0 (#4076) ### New Features and Improvements * Add `databricks_budget` resource ([#3955](https://github.com/databricks/terraform-provider-databricks/pull/3955)). * Add `databricks_mlflow_models` data source ([#3874](https://github.com/databricks/terraform-provider-databricks/pull/3874)). * Add computed attribute `table_serving_url` to `databricks_online_table` ([#4048](https://github.com/databricks/terraform-provider-databricks/pull/4048)). * Add support for Identity Column in `databricks_sql_table` ([#4035](https://github.com/databricks/terraform-provider-databricks/pull/4035)). ### Bug Fixes * Add Sufficient Network Privileges to the Databricks Default Cross Account Policy ([#4027](https://github.com/databricks/terraform-provider-databricks/pull/4027)) * Ignore presence or absence of `/Workspace` prefix for dashboard resource ([#4061](https://github.com/databricks/terraform-provider-databricks/pull/4061)). * Refactor `databricks_permissions` and allow the current user to set their own permissions ([#3956](https://github.com/databricks/terraform-provider-databricks/pull/3956)). * Set ID for online table resource if creation succeeds but it isn't available yet ([#4072](https://github.com/databricks/terraform-provider-databricks/pull/4072)). ### Documentation * Update CONTRIBUTING guide for plugin framework resources ([#4078](https://github.com/databricks/terraform-provider-databricks/pull/4078)) * Add guide for OIDC authentication ([#4016](https://github.com/databricks/terraform-provider-databricks/pull/4016)). * Correctly use native markdown callouts supported by TF Registry ([#4073](https://github.com/databricks/terraform-provider-databricks/pull/4073)). * Fixing links to `databricks_service_principal` in TF guides ([#4020](https://github.com/databricks/terraform-provider-databricks/pull/4020)). ### Internal Changes * Fix Permissions Dashboard Test ([#4071](https://github.com/databricks/terraform-provider-databricks/pull/4071)). * Bump Go SDK to latest and generate TF structs ([#4062](https://github.com/databricks/terraform-provider-databricks/pull/4062)). * Skip Budget tests on GCP ([#4070](https://github.com/databricks/terraform-provider-databricks/pull/4070)). * Update to latest OpenAPI spec and bump Go SDK ([#4069](https://github.com/databricks/terraform-provider-databricks/pull/4069)). --- CHANGELOG.md | 34 ++++++++++++++++++++++++++++++++++ common/version.go | 2 +- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aecd839d63..769b48fa35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,39 @@ # Version changelog +## [Release] Release v1.53.0 + +### New Features and Improvements + + * Add `databricks_budget` resource ([#3955](https://github.com/databricks/terraform-provider-databricks/pull/3955)). + * Add `databricks_mlflow_models` data source ([#3874](https://github.com/databricks/terraform-provider-databricks/pull/3874)). + * Add computed attribute `table_serving_url` to `databricks_online_table` ([#4048](https://github.com/databricks/terraform-provider-databricks/pull/4048)). + * Add support for Identity Column in `databricks_sql_table` ([#4035](https://github.com/databricks/terraform-provider-databricks/pull/4035)). + + +### Bug Fixes + + * Add Sufficient Network Privileges to the Databricks Default Cross Account Policy ([#4027](https://github.com/databricks/terraform-provider-databricks/pull/4027)) + * Ignore presence or absence of `/Workspace` prefix for dashboard resource ([#4061](https://github.com/databricks/terraform-provider-databricks/pull/4061)). + * Refactor `databricks_permissions` and allow the current user to set their own permissions ([#3956](https://github.com/databricks/terraform-provider-databricks/pull/3956)). + * Set ID for online table resource if creation succeeds but it isn't available yet ([#4072](https://github.com/databricks/terraform-provider-databricks/pull/4072)). + + +### Documentation + + * Update CONTRIBUTING guide for plugin framework resources ([#4078](https://github.com/databricks/terraform-provider-databricks/pull/4078)) + * Add guide for OIDC authentication ([#4016](https://github.com/databricks/terraform-provider-databricks/pull/4016)). + * Correctly use native markdown callouts supported by TF Registry ([#4073](https://github.com/databricks/terraform-provider-databricks/pull/4073)). + * Fixing links to `databricks_service_principal` in TF guides ([#4020](https://github.com/databricks/terraform-provider-databricks/pull/4020)). + + +### Internal Changes + + * Fix Permissions Dashboard Test ([#4071](https://github.com/databricks/terraform-provider-databricks/pull/4071)). + * Bump Go SDK to latest and generate TF structs ([#4062](https://github.com/databricks/terraform-provider-databricks/pull/4062)). + * Skip Budget tests on GCP ([#4070](https://github.com/databricks/terraform-provider-databricks/pull/4070)). + * Update to latest OpenAPI spec and bump Go SDK ([#4069](https://github.com/databricks/terraform-provider-databricks/pull/4069)). + + ## [Release] Release v1.52.0 ### New Features and Improvements diff --git a/common/version.go b/common/version.go index 417761fcf5..86d57fba64 100644 --- a/common/version.go +++ b/common/version.go @@ -3,7 +3,7 @@ package common import "context" var ( - version = "1.52.0" + version = "1.53.0" // ResourceName is resource name without databricks_ prefix ResourceName contextKey = 1 // Provider is the current instance of provider From b937e0bc8d0a55a735e437366bb701e89a332cb6 Mon Sep 17 00:00:00 2001 From: Alex Ott Date: Wed, 9 Oct 2024 06:04:19 -0400 Subject: [PATCH 53/54] [Fix] force send `read_only` in `databricks_external_location` when it's changed (#4067) ## Changes See linked issue for details Resolves #4037, Resolves #4004 ## Tests - [x] `make test` run locally - [ ] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [ ] using Go SDK --- catalog/resource_external_location.go | 3 ++ catalog/resource_external_location_test.go | 47 ++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/catalog/resource_external_location.go b/catalog/resource_external_location.go index f21549cb98..04985370ee 100644 --- a/catalog/resource_external_location.go +++ b/catalog/resource_external_location.go @@ -116,6 +116,9 @@ func ResourceExternalLocation() common.Resource { if !d.HasChangeExcept("owner") { return nil } + if d.HasChange("read_only") { + updateExternalLocationRequest.ForceSendFields = append(updateExternalLocationRequest.ForceSendFields, "ReadOnly") + } updateExternalLocationRequest.Owner = "" _, err = w.ExternalLocations.Update(ctx, updateExternalLocationRequest) diff --git a/catalog/resource_external_location_test.go b/catalog/resource_external_location_test.go index 26493c1005..c424bbc2fc 100644 --- a/catalog/resource_external_location_test.go +++ b/catalog/resource_external_location_test.go @@ -293,6 +293,7 @@ func TestUpdateExternalLocation(t *testing.T) { Url: "s3://foo/bar", CredentialName: "bcd", Comment: "def", + ReadOnly: false, }, }, { @@ -324,6 +325,52 @@ func TestUpdateExternalLocation(t *testing.T) { }.ApplyNoError(t) } +func TestUpdateExternalLocation_FromReadOnly(t *testing.T) { + qa.ResourceFixture{ + Fixtures: []qa.HTTPFixture{ + { + Method: "PATCH", + Resource: "/api/2.1/unity-catalog/external-locations/abc", + ExpectedRequest: catalog.UpdateExternalLocation{ + Url: "s3://foo/bar", + CredentialName: "bcd", + Comment: "def", + ReadOnly: false, + ForceSendFields: []string{"ReadOnly"}, + }, + }, + { + Method: "GET", + Resource: "/api/2.1/unity-catalog/external-locations/abc?", + Response: catalog.ExternalLocationInfo{ + Name: "abc", + Url: "s3://foo/bar", + CredentialName: "bcd", + Comment: "def", + ReadOnly: false, + }, + }, + }, + Resource: ResourceExternalLocation(), + Update: true, + ID: "abc", + InstanceState: map[string]string{ + "name": "abc", + "url": "s3://foo/bar", + "credential_name": "abc", + "comment": "def", + "read_only": "true", + }, + HCL: ` + name = "abc" + url = "s3://foo/bar" + credential_name = "bcd" + comment = "def" + read_only = false + `, + }.ApplyNoError(t) +} + func TestUpdateExternalLocationOnlyOwner(t *testing.T) { qa.ResourceFixture{ Fixtures: []qa.HTTPFixture{ From 4e5951e3141019caffaf2a2450da45e70c3c59e7 Mon Sep 17 00:00:00 2001 From: Alex Ott Date: Wed, 9 Oct 2024 07:05:04 -0400 Subject: [PATCH 54/54] [Fix] force send `read_only` in `databricks_storage_credential` when it's changed (#4083) ## Changes It's similar to #4067 - the `read_only = false` wasn't sent for storage credentials as well ## Tests - [x] `make test` run locally - [ ] relevant change in `docs/` folder - [ ] covered with integration tests in `internal/acceptance` - [ ] relevant acceptance tests are passing - [ ] using Go SDK --- catalog/resource_storage_credential.go | 6 +++ catalog/resource_storage_credential_test.go | 48 +++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/catalog/resource_storage_credential.go b/catalog/resource_storage_credential.go index 38c6a92109..17e7896ae3 100644 --- a/catalog/resource_storage_credential.go +++ b/catalog/resource_storage_credential.go @@ -196,6 +196,9 @@ func ResourceStorageCredential() common.Resource { return nil } + if d.HasChange("read_only") { + update.ForceSendFields = append(update.ForceSendFields, "ReadOnly") + } update.Owner = "" _, err := acc.StorageCredentials.Update(ctx, catalog.AccountsUpdateStorageCredential{ CredentialInfo: &update, @@ -240,6 +243,9 @@ func ResourceStorageCredential() common.Resource { return nil } + if d.HasChange("read_only") { + update.ForceSendFields = append(update.ForceSendFields, "ReadOnly") + } update.Owner = "" _, err = w.StorageCredentials.Update(ctx, update) if err != nil { diff --git a/catalog/resource_storage_credential_test.go b/catalog/resource_storage_credential_test.go index e09f8af8e8..7e3c31b35a 100644 --- a/catalog/resource_storage_credential_test.go +++ b/catalog/resource_storage_credential_test.go @@ -432,6 +432,54 @@ func TestUpdateStorageCredentials(t *testing.T) { }.ApplyNoError(t) } +func TestUpdateStorageCredentialsFromReadOnly(t *testing.T) { + qa.ResourceFixture{ + Fixtures: []qa.HTTPFixture{ + { + Method: "PATCH", + Resource: "/api/2.1/unity-catalog/storage-credentials/a", + ExpectedRequest: catalog.UpdateStorageCredential{ + AwsIamRole: &catalog.AwsIamRoleRequest{ + RoleArn: "CHANGED", + }, + Comment: "c", + ReadOnly: false, + ForceSendFields: []string{"ReadOnly"}, + }, + }, + { + Method: "GET", + Resource: "/api/2.1/unity-catalog/storage-credentials/a?", + Response: catalog.StorageCredentialInfo{ + Name: "a", + AwsIamRole: &catalog.AwsIamRoleResponse{ + RoleArn: "CHANGED", + }, + MetastoreId: "d", + Comment: "c", + ReadOnly: false, + }, + }, + }, + Resource: ResourceStorageCredential(), + Update: true, + ID: "a", + InstanceState: map[string]string{ + "name": "a", + "comment": "c", + "read_only": "true", + }, + HCL: ` + name = "a" + aws_iam_role { + role_arn = "CHANGED" + } + comment = "c" + read_only = false + `, + }.ApplyNoError(t) +} + func TestUpdateStorageCredentialsWithOwnerOnly(t *testing.T) { qa.ResourceFixture{ Fixtures: []qa.HTTPFixture{

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