Skip to content

Commit 07c879f

Browse files
authored
Merge branch 'main' into deprecate-sql-dashboards
2 parents 0021afa + 2709ff1 commit 07c879f

14 files changed

+1737
-1920
lines changed

NEXT_CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,5 @@
2222

2323
### Internal Changes
2424

25+
* Refactor `databricks_mws_workspaces` resource and datasource, as well as `databricks_mws_ncc_binding`, to use the Go SDK ([#4633](https://github.com/databricks/terraform-provider-databricks/pull/4633)).
2526
* Add `TestMwsAccGcpWorkspaces` and `TestMwsAccGcpByovpcWorkspaces` to flaky test ([#4624](https://github.com/databricks/terraform-provider-databricks/pull/4624)).

common/client.go

+56-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

common/client_test.go

+98
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,21 @@ package common
22

33
import (
44
"context"
5+
"fmt"
56
"log"
67
"net/http"
78
"path/filepath"
89
"strings"
910
"testing"
1011

12+
"github.com/databricks/databricks-sdk-go"
1113
"github.com/databricks/databricks-sdk-go/client"
1214
"github.com/databricks/databricks-sdk-go/config"
15+
"github.com/databricks/databricks-sdk-go/experimental/mocks"
1316
"github.com/databricks/databricks-sdk-go/service/iam"
17+
"github.com/databricks/databricks-sdk-go/service/provisioning"
1418
"github.com/stretchr/testify/assert"
19+
"github.com/stretchr/testify/mock"
1520
"github.com/stretchr/testify/require"
1621
)
1722

@@ -335,3 +340,96 @@ func TestCachedMe_Me_MakesSingleRequest(t *testing.T) {
335340
cm.Me(context.Background())
336341
assert.Equal(t, 1, mock.count)
337342
}
343+
344+
func TestWorkspaceClientForWorkspace_WorkspaceDoesNotExist(t *testing.T) {
345+
mockAcc := mocks.NewMockAccountClient(t)
346+
mockWorkspacesAPI := mockAcc.GetMockWorkspacesAPI()
347+
348+
// Setup the mock to return an error for non-existent workspace
349+
mockWorkspacesAPI.EXPECT().Get(mock.Anything, provisioning.GetWorkspaceRequest{
350+
WorkspaceId: 12345,
351+
}).Return(nil, fmt.Errorf("workspace not found"))
352+
353+
// Create a DatabricksClient with the mock account client
354+
dc := &DatabricksClient{
355+
DatabricksClient: &client.DatabricksClient{
356+
Config: &config.Config{},
357+
},
358+
}
359+
dc.SetAccountClient(mockAcc.AccountClient)
360+
361+
// Call the method with a non-existent workspace ID
362+
_, err := dc.WorkspaceClientForWorkspace(context.Background(), 12345)
363+
364+
// Verify the error
365+
assert.Error(t, err)
366+
assert.Contains(t, err.Error(), "workspace not found")
367+
}
368+
369+
func TestWorkspaceClientForWorkspace_WorkspaceExistsNotInCache(t *testing.T) {
370+
mockAcc := mocks.NewMockAccountClient(t)
371+
mockAcc.AccountClient.Config = &config.Config{
372+
Token: "dapi123", // Instantiating WorkspaceClient attempts authentication, this allows Configure() to complete quickly.
373+
}
374+
mockWorkspacesAPI := mockAcc.GetMockWorkspacesAPI()
375+
376+
// Create a mock workspace
377+
mockWorkspace := &provisioning.Workspace{
378+
WorkspaceId: 12345,
379+
WorkspaceName: "test-workspace",
380+
DeploymentName: "test-deployment",
381+
}
382+
383+
// Setup the mock to return the workspace
384+
mockWorkspacesAPI.EXPECT().Get(mock.Anything, provisioning.GetWorkspaceRequest{
385+
WorkspaceId: 12345,
386+
}).Return(mockWorkspace, nil)
387+
388+
// Create a DatabricksClient with the mock account client
389+
dc := &DatabricksClient{
390+
DatabricksClient: &client.DatabricksClient{
391+
Config: &config.Config{},
392+
},
393+
}
394+
dc.SetAccountClient(mockAcc.AccountClient)
395+
396+
// Call the method with the workspace ID
397+
workspaceClient, err := dc.WorkspaceClientForWorkspace(context.Background(), 12345)
398+
399+
// Verify no error and client is returned
400+
assert.NoError(t, err)
401+
assert.NotNil(t, workspaceClient)
402+
403+
// Verify the workspace client is configured correctly
404+
assert.Equal(t, fmt.Sprintf("https://%s.cloud.databricks.com", mockWorkspace.DeploymentName), workspaceClient.Config.Host)
405+
406+
// Verify the client is cached
407+
dc.mu.Lock()
408+
cachedClient, exists := dc.cachedWorkspaceClients[12345]
409+
dc.mu.Unlock()
410+
411+
assert.True(t, exists)
412+
assert.Equal(t, workspaceClient, cachedClient)
413+
}
414+
415+
func TestWorkspaceClientForWorkspace_WorkspaceExistsInCache(t *testing.T) {
416+
// Create a mock workspace client
417+
mockWorkspaceClient := &databricks.WorkspaceClient{}
418+
419+
// Create a DatabricksClient with the mock workspace client in cache
420+
dc := &DatabricksClient{
421+
DatabricksClient: &client.DatabricksClient{
422+
Config: &config.Config{},
423+
},
424+
}
425+
426+
// Set the workspace client in cache
427+
dc.SetWorkspaceClientForWorkspace(12345, mockWorkspaceClient)
428+
429+
// Call the method with the workspace ID
430+
workspaceClient, err := dc.WorkspaceClientForWorkspace(context.Background(), 12345)
431+
432+
// Verify no error and the cached client is returned
433+
assert.NoError(t, err)
434+
assert.Equal(t, mockWorkspaceClient, workspaceClient)
435+
}

common/constants.go

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package common
2+
3+
import "context"
4+
5+
var (
6+
// ResourceName is resource name without databricks_ prefix
7+
ResourceName contextKey = 1
8+
// Provider is the current instance of provider
9+
Provider contextKey = 2
10+
// Current is the current name of integration test
11+
Current contextKey = 3
12+
// If current resource is data
13+
IsData contextKey = 4
14+
// apiVersion
15+
Api contextKey = 5
16+
// SDK used
17+
Sdk contextKey = 6
18+
)
19+
20+
type contextKey int
21+
22+
func (k contextKey) GetOrUnknown(ctx context.Context) string {
23+
rn, ok := ctx.Value(k).(string)
24+
if !ok {
25+
return "unknown"
26+
}
27+
return rn
28+
}

common/version.go

+1-27
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,6 @@
11
package common
22

3-
import "context"
4-
5-
var (
6-
version = "1.72.0"
7-
// ResourceName is resource name without databricks_ prefix
8-
ResourceName contextKey = 1
9-
// Provider is the current instance of provider
10-
Provider contextKey = 2
11-
// Current is the current name of integration test
12-
Current contextKey = 3
13-
// If current resource is data
14-
IsData contextKey = 4
15-
// apiVersion
16-
Api contextKey = 5
17-
// SDK used
18-
Sdk contextKey = 6
19-
)
20-
21-
type contextKey int
22-
23-
func (k contextKey) GetOrUnknown(ctx context.Context) string {
24-
rn, ok := ctx.Value(k).(string)
25-
if !ok {
26-
return "unknown"
27-
}
28-
return rn
29-
}
3+
var version = "1.72.0"
304

315
// Version returns version of provider
326
func Version() string {

docs/resources/mws_workspaces.md

+11-7
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ The following arguments are available:
323323
* `deployment_name` - (Optional) part of URL as in `https://<prefix>-<deployment-name>.cloud.databricks.com`. Deployment name cannot be used until a deployment name prefix is defined. Please contact your Databricks representative. Once a new deployment prefix is added/updated, it only will affect the new workspaces created.
324324
* `workspace_name` - name of the workspace, will appear on UI.
325325
* `network_id` - (Optional) `network_id` from [networks](mws_networks.md).
326+
* `credentials_id` - (AWS only) ID of the workspace's credential configuration object.
326327
* `aws_region` - (AWS only) region of VPC.
327328
* `storage_configuration_id` - (AWS only)`storage_configuration_id` from [storage configuration](mws_storage_configurations.md).
328329
* `managed_services_customer_managed_key_id` - (Optional) `customer_managed_key_id` from [customer managed keys](mws_customer_managed_keys.md) with `use_cases` set to `MANAGED_SERVICES`. This is used to encrypt the workspace's notebook and secret data in the control plane.
@@ -331,7 +332,9 @@ The following arguments are available:
331332
* `cloud_resource_container` - (GCP only) A block that specifies GCP workspace configurations, consisting of following blocks:
332333
* `gcp` - A block that consists of the following field:
333334
* `project_id` - The Google Cloud project ID, which the workspace uses to instantiate cloud resources for your workspace.
334-
* `gke_config` - (GCP only) A block that specifies GKE configuration for the Databricks workspace:
335+
* `gcp_managed_network_config` - (GCP only) A block that describes the network configuration for workspaces with Databricks-managed networks.
336+
* `subnet_cidr` - The IP range from which to allocate GKE cluster nodes. No bigger than `/9` and no smaller than `/29`.
337+
* `gke_config` - (GCP only, deprecated) A block that specifies GKE configuration for the Databricks workspace:
335338
* `connectivity_type`: Specifies the network connectivity types for the GKE nodes and the GKE master network. Possible values are: `PRIVATE_NODE_PUBLIC_MASTER`, `PUBLIC_NODE_PUBLIC_MASTER`.
336339
* `master_ip_range`: The IP range from which to allocate GKE cluster master resources. This field will be ignored if GKE private cluster is not enabled. It must be exactly as big as `/28`.
337340
* `private_access_settings_id` - (Optional) Canonical unique identifier of [databricks_mws_private_access_settings](mws_private_access_settings.md) in Databricks Account.
@@ -351,24 +354,25 @@ You can specify a `token` block in the body of the workspace resource, so that T
351354

352355
On AWS, the following arguments could be modified after the workspace is running:
353356

354-
* `network_id` - Modifying [networks on running workspaces](mws_networks.md#modifying-networks-on-running-workspaces-aws-only) would require three separate `terraform apply` steps.
355357
* `credentials_id`
356-
* `storage_customer_managed_key_id`
357-
* `private_access_settings_id`
358358
* `custom_tags`
359+
* `managed_services_customer_managed_key_id`
360+
* `network_id` - Modifying [networks on running workspaces](mws_networks.md#modifying-networks-on-running-workspaces-aws-only) would require three separate `terraform apply` steps.
361+
* `private_access_settings_id`
362+
* `storage_customer_managed_key_id`
359363

360364
## Attribute Reference
361365

362366
In addition to all arguments above, the following attributes are exported:
363367

364368
* `id` - (String) Canonical unique identifier for the workspace, of the format `<account-id>/<workspace-id>`
369+
* `creation_time` - (Integer) time when workspace was created
370+
* `custom_tags` - (Map) Custom Tags (if present) added to workspace
371+
* `gcp_workspace_sa` - (String, GCP only) identifier of a service account created for the workspace in form of `db-<workspace-id>@prod-gcp-<region>.iam.gserviceaccount.com`
365372
* `workspace_id` - (String) workspace id
366373
* `workspace_status_message` - (String) updates on workspace status
367374
* `workspace_status` - (String) workspace status
368-
* `creation_time` - (Integer) time when workspace was created
369375
* `workspace_url` - (String) URL of the workspace
370-
* `custom_tags` - (Map) Custom Tags (if present) added to workspace
371-
* `gcp_workspace_sa` - (String, GCP only) identifier of a service account created for the workspace in form of `db-<workspace-id>@prod-gcp-<region>.iam.gserviceaccount.com`
372376

373377
## Timeouts
374378

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package acceptance
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/hashicorp/terraform-plugin-testing/plancheck"
8+
)
9+
10+
type expectNotDestroyed struct {
11+
addr string
12+
}
13+
14+
func ExpectNotDestroyed(addr string) expectNotDestroyed {
15+
return expectNotDestroyed{addr: addr}
16+
}
17+
18+
func (e expectNotDestroyed) CheckPlan(ctx context.Context, req plancheck.CheckPlanRequest, resp *plancheck.CheckPlanResponse) {
19+
for _, resource := range req.Plan.ResourceChanges {
20+
if resource.Address != e.addr {
21+
continue
22+
}
23+
actions := resource.Change.Actions
24+
if actions.DestroyBeforeCreate() || actions.CreateBeforeDestroy() || actions.Delete() {
25+
resp.Error = fmt.Errorf("resource %s is marked for destruction", e.addr)
26+
return
27+
}
28+
}
29+
}

mws/data_mws_workspaces.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,17 @@ func DataSourceMwsWorkspaces() common.Resource {
1616
if c.Config.AccountID == "" {
1717
return fmt.Errorf("provider block is missing `account_id` property")
1818
}
19-
workspaces, err := NewWorkspacesAPI(ctx, c).List(c.Config.AccountID)
19+
a, err := c.AccountClient()
20+
if err != nil {
21+
return err
22+
}
23+
workspaces, err := a.Workspaces.List(ctx)
2024
if err != nil {
2125
return err
2226
}
2327
data.Ids = map[string]int64{}
2428
for _, v := range workspaces {
25-
data.Ids[v.WorkspaceName] = v.WorkspaceID
29+
data.Ids[v.WorkspaceName] = v.WorkspaceId
2630
}
2731
return nil
2832
})

0 commit comments

Comments
 (0)