From ba78878aa0c54994dca51642779df660c33e4fbf Mon Sep 17 00:00:00 2001 From: Andrew Nester Date: Mon, 22 Sep 2025 16:21:24 +0200 Subject: [PATCH 1/9] Fixed bundle deploy to not update permissions for unbound jobs --- .../deploy/experimental-python/output.txt | 1 + .../bundle/deploy/python-notebook/output.txt | 1 + .../deployment/bind/alert/out.test.toml | 2 +- .../bundle/deployment/unbind/job/output.txt | 1 + .../unbind/permissions/databricks.yml | 12 +++ .../unbind/permissions/out.test.toml | 5 ++ .../deployment/unbind/permissions/output.txt | 81 +++++++++++++++++++ .../deployment/unbind/permissions/script | 7 ++ .../deployment/unbind/permissions/test.toml | 4 + .../deployment/unbind/python-job/output.txt | 1 + .../resource_deps/jobs_update/output.txt | 1 + bundle/deploy/terraform/unbind.go | 31 +++++-- bundle/phases/bind.go | 4 +- cmd/bundle/deployment/unbind.go | 5 +- libs/testserver/fake_workspace.go | 10 ++- libs/testserver/handlers.go | 8 ++ libs/testserver/jobs.go | 58 ++++++++++++- 17 files changed, 217 insertions(+), 15 deletions(-) create mode 100644 acceptance/bundle/deployment/unbind/permissions/databricks.yml create mode 100644 acceptance/bundle/deployment/unbind/permissions/out.test.toml create mode 100644 acceptance/bundle/deployment/unbind/permissions/output.txt create mode 100644 acceptance/bundle/deployment/unbind/permissions/script create mode 100644 acceptance/bundle/deployment/unbind/permissions/test.toml diff --git a/acceptance/bundle/deploy/experimental-python/output.txt b/acceptance/bundle/deploy/experimental-python/output.txt index 590d7cd350..9dad22cf1d 100644 --- a/acceptance/bundle/deploy/experimental-python/output.txt +++ b/acceptance/bundle/deploy/experimental-python/output.txt @@ -8,6 +8,7 @@ Deployment complete! >>> [CLI] jobs list --output json [ { + "creator_user_name": "[USERNAME]", "job_id": [NUMID], "settings": { "deployment": { diff --git a/acceptance/bundle/deploy/python-notebook/output.txt b/acceptance/bundle/deploy/python-notebook/output.txt index 6e2f2f8de7..704430ada4 100644 --- a/acceptance/bundle/deploy/python-notebook/output.txt +++ b/acceptance/bundle/deploy/python-notebook/output.txt @@ -8,6 +8,7 @@ Deployment complete! >>> [CLI] jobs list --output json [ { + "creator_user_name": "[USERNAME]", "job_id": [NUMID], "settings": { "deployment": { diff --git a/acceptance/bundle/deployment/bind/alert/out.test.toml b/acceptance/bundle/deployment/bind/alert/out.test.toml index 90061dedb1..f9eb74f070 100644 --- a/acceptance/bundle/deployment/bind/alert/out.test.toml +++ b/acceptance/bundle/deployment/bind/alert/out.test.toml @@ -1,4 +1,4 @@ -Local = true +Local = false Cloud = false [EnvMatrix] diff --git a/acceptance/bundle/deployment/unbind/job/output.txt b/acceptance/bundle/deployment/unbind/job/output.txt index f3b5963b53..482431cae7 100644 --- a/acceptance/bundle/deployment/unbind/job/output.txt +++ b/acceptance/bundle/deployment/unbind/job/output.txt @@ -18,6 +18,7 @@ Deployment complete! >>> [CLI] jobs get [NUMID] --output json { + "creator_user_name":"[USERNAME]", "job_id":[NUMID], "settings": { "deployment": { diff --git a/acceptance/bundle/deployment/unbind/permissions/databricks.yml b/acceptance/bundle/deployment/unbind/permissions/databricks.yml new file mode 100644 index 0000000000..0840735b4e --- /dev/null +++ b/acceptance/bundle/deployment/unbind/permissions/databricks.yml @@ -0,0 +1,12 @@ +bundle: + name: unbind_permissions + +resources: + jobs: + job_1: + name: "Job name" + permissions: + - level: CAN_MANAGE + user_name: tester@user.com + - group_name: jiro-group + level: CAN_MANAGE diff --git a/acceptance/bundle/deployment/unbind/permissions/out.test.toml b/acceptance/bundle/deployment/unbind/permissions/out.test.toml new file mode 100644 index 0000000000..90061dedb1 --- /dev/null +++ b/acceptance/bundle/deployment/unbind/permissions/out.test.toml @@ -0,0 +1,5 @@ +Local = true +Cloud = false + +[EnvMatrix] + DATABRICKS_BUNDLE_ENGINE = ["terraform"] diff --git a/acceptance/bundle/deployment/unbind/permissions/output.txt b/acceptance/bundle/deployment/unbind/permissions/output.txt new file mode 100644 index 0000000000..6369491b2e --- /dev/null +++ b/acceptance/bundle/deployment/unbind/permissions/output.txt @@ -0,0 +1,81 @@ + +>>> [CLI] bundle deploy +Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/unbind_permissions/default/files... +Deploying resources... +Updating deployment state... +Deployment complete! + +>>> [CLI] bundle summary --output json + +>>> [CLI] jobs get-permissions [NUMID] --output json +{ + "access_control_list": [ + { + "all_permissions": [ + { + "permission_level":"CAN_MANAGE" + } + ], + "group_name":"jiro-group" + }, + { + "all_permissions": [ + { + "permission_level":"CAN_MANAGE" + } + ], + "user_name":"[USERNAME]@user.com" + }, + { + "all_permissions": [ + { + "permission_level":"IS_OWNER" + } + ], + "user_name":"[USERNAME]" + } + ], + "object_id":"jobs/[NUMID]", + "object_type":"job" +} + +>>> [CLI] bundle deployment unbind job_1 +Updating deployment state... + +>>> [CLI] bundle deploy +Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/unbind_permissions/default/files... +Deploying resources... +Updating deployment state... +Deployment complete! + +>>> [CLI] jobs get-permissions [NUMID] --output json +{ + "access_control_list": [ + { + "all_permissions": [ + { + "permission_level":"CAN_MANAGE" + } + ], + "group_name":"jiro-group" + }, + { + "all_permissions": [ + { + "permission_level":"CAN_MANAGE" + } + ], + "user_name":"[USERNAME]@user.com" + }, + { + "all_permissions": [ + { + "permission_level":"IS_OWNER" + } + ], + "user_name":"[USERNAME]" + } + ], + "object_id":"jobs/[NUMID]", + "object_type":"job" +} diff --git a/acceptance/bundle/deployment/unbind/permissions/script b/acceptance/bundle/deployment/unbind/permissions/script new file mode 100644 index 0000000000..9ed1cc7b4a --- /dev/null +++ b/acceptance/bundle/deployment/unbind/permissions/script @@ -0,0 +1,7 @@ +trace $CLI bundle deploy +job_id=$(trace $CLI bundle summary --output json | jq -r '.resources.jobs.job_1.id') +trace $CLI jobs get-permissions $job_id --output json + +trace $CLI bundle deployment unbind job_1 +trace $CLI bundle deploy +trace $CLI jobs get-permissions $job_id --output json diff --git a/acceptance/bundle/deployment/unbind/permissions/test.toml b/acceptance/bundle/deployment/unbind/permissions/test.toml new file mode 100644 index 0000000000..e4fc888c4d --- /dev/null +++ b/acceptance/bundle/deployment/unbind/permissions/test.toml @@ -0,0 +1,4 @@ +Cloud = false # test leaves deployed job + +[EnvMatrix] + DATABRICKS_BUNDLE_ENGINE = ["terraform"] diff --git a/acceptance/bundle/deployment/unbind/python-job/output.txt b/acceptance/bundle/deployment/unbind/python-job/output.txt index 95ef280a81..acfdafa930 100644 --- a/acceptance/bundle/deployment/unbind/python-job/output.txt +++ b/acceptance/bundle/deployment/unbind/python-job/output.txt @@ -18,6 +18,7 @@ Deployment complete! >>> [CLI] jobs get [NUMID] --output json { + "creator_user_name":"[USERNAME]", "job_id":[NUMID], "settings": { "deployment": { diff --git a/acceptance/bundle/resource_deps/jobs_update/output.txt b/acceptance/bundle/resource_deps/jobs_update/output.txt index 26ab67029b..10cffda960 100644 --- a/acceptance/bundle/resource_deps/jobs_update/output.txt +++ b/acceptance/bundle/resource_deps/jobs_update/output.txt @@ -153,6 +153,7 @@ Deployment complete! >>> [CLI] jobs get [BAR_ID] { + "creator_user_name":"[USERNAME]", "job_id":[BAR_ID], "settings": { "deployment": { diff --git a/bundle/deploy/terraform/unbind.go b/bundle/deploy/terraform/unbind.go index 494cb7ef1f..85a2743468 100644 --- a/bundle/deploy/terraform/unbind.go +++ b/bundle/deploy/terraform/unbind.go @@ -10,8 +10,9 @@ import ( ) type unbind struct { - resourceType string - resourceKey string + bundleType string + tfResourceType string + resourceKey string } func (m *unbind) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { @@ -25,11 +26,31 @@ func (m *unbind) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { return diag.Errorf("terraform init: %v", err) } - err = tf.StateRm(ctx, fmt.Sprintf("%s.%s", m.resourceType, m.resourceKey)) + err = tf.StateRm(ctx, fmt.Sprintf("%s.%s", m.tfResourceType, m.resourceKey)) if err != nil { return diag.Errorf("terraform state rm: %v", err) } + // Also remove the permission if it exists + // First check terraform state list to see if the permission exists + state, err := tf.Show(ctx) + if err != nil { + return diag.Errorf("terraform show: %v", err) + } + + if state.Values == nil || state.Values.RootModule == nil || state.Values.RootModule.Resources == nil { + return nil + } + + for _, resource := range state.Values.RootModule.Resources { + if resource.Address == fmt.Sprintf("databricks_permissions.%s_%s", m.bundleType, m.resourceKey) { + err = tf.StateRm(ctx, resource.Address) + if err != nil { + return diag.Errorf("terraform state rm: %v", err) + } + } + } + return nil } @@ -37,6 +58,6 @@ func (*unbind) Name() string { return "terraform.Unbind" } -func Unbind(resourceType, resourceKey string) bundle.Mutator { - return &unbind{resourceType: resourceType, resourceKey: resourceKey} +func Unbind(bundleType, tfResourceType, resourceKey string) bundle.Mutator { + return &unbind{bundleType: bundleType, tfResourceType: tfResourceType, resourceKey: resourceKey} } diff --git a/bundle/phases/bind.go b/bundle/phases/bind.go index afc42a639c..8d8f5ff7a1 100644 --- a/bundle/phases/bind.go +++ b/bundle/phases/bind.go @@ -32,7 +32,7 @@ func Bind(ctx context.Context, b *bundle.Bundle, opts *terraform.BindOptions) { ) } -func Unbind(ctx context.Context, b *bundle.Bundle, resourceType, resourceKey string) { +func Unbind(ctx context.Context, b *bundle.Bundle, bundleType, tfResourceType, resourceKey string) { log.Info(ctx, "Phase: unbind") bundle.ApplyContext(ctx, b, lock.Acquire()) @@ -48,7 +48,7 @@ func Unbind(ctx context.Context, b *bundle.Bundle, resourceType, resourceKey str statemgmt.StatePull(), terraform.Interpolate(), terraform.Write(), - terraform.Unbind(resourceType, resourceKey), + terraform.Unbind(bundleType, tfResourceType, resourceKey), statemgmt.StatePush(), ) } diff --git a/cmd/bundle/deployment/unbind.go b/cmd/bundle/deployment/unbind.go index c0ebe52661..0c9d399c9d 100644 --- a/cmd/bundle/deployment/unbind.go +++ b/cmd/bundle/deployment/unbind.go @@ -76,8 +76,9 @@ To re-bind the resource later, use: b.Config.Bundle.Deployment.Lock.Force = forceLock }) - tfName := terraform.GroupToTerraformName[resource.ResourceDescription().PluralName] - phases.Unbind(ctx, b, tfName, args[0]) + rd := resource.ResourceDescription() + tfName := terraform.GroupToTerraformName[rd.PluralName] + phases.Unbind(ctx, b, rd.SingularName, tfName, args[0]) if logdiag.HasError(ctx) { return root.ErrAlreadyPrinted } diff --git a/libs/testserver/fake_workspace.go b/libs/testserver/fake_workspace.go index 00e85d3453..55ad6cbf6a 100644 --- a/libs/testserver/fake_workspace.go +++ b/libs/testserver/fake_workspace.go @@ -60,10 +60,11 @@ type FakeWorkspace struct { repoIdByPath map[string]int64 // normally, ids are not sequential, but we make them sequential for deterministic diff - nextJobId int64 - nextJobRunId int64 - Jobs map[int64]jobs.Job - JobRuns map[int64]jobs.Run + nextJobId int64 + nextJobRunId int64 + Jobs map[int64]jobs.Job + JobRuns map[int64]jobs.Run + JobsPermissions map[string][]jobs.JobAccessControlRequest Pipelines map[string]pipelines.GetPipelineResponse PipelineUpdates map[string]bool @@ -153,6 +154,7 @@ func NewFakeWorkspace(url, token string) *FakeWorkspace { Jobs: map[int64]jobs.Job{}, JobRuns: map[int64]jobs.Run{}, + JobsPermissions: map[string][]jobs.JobAccessControlRequest{}, nextJobId: TestJobID, nextJobRunId: TestRunID, Pipelines: map[string]pipelines.GetPipelineResponse{}, diff --git a/libs/testserver/handlers.go b/libs/testserver/handlers.go index 256e3766e9..f8f2c7fc83 100644 --- a/libs/testserver/handlers.go +++ b/libs/testserver/handlers.go @@ -505,4 +505,12 @@ func AddDefaultHandlers(server *Server) { server.Handle("DELETE", "/api/2.0/database/synced_tables/{name}", func(req Request) any { return MapDelete(req.Workspace, req.Workspace.SyncedDatabaseTables, req.Vars["name"]) }) + + server.Handle("PUT", "/api/2.0/permissions/jobs/{job_id}", func(req Request) any { + return req.Workspace.JobsUpdatePermissions(req, req.Vars["job_id"]) + }) + + server.Handle("GET", "/api/2.0/permissions/jobs/{job_id}", func(req Request) any { + return req.Workspace.JobsGetPermissions(req, req.Vars["job_id"]) + }) } diff --git a/libs/testserver/jobs.go b/libs/testserver/jobs.go index 334898a306..ea8cebff9f 100644 --- a/libs/testserver/jobs.go +++ b/libs/testserver/jobs.go @@ -31,7 +31,7 @@ func (s *FakeWorkspace) JobsCreate(req Request) Response { } } - s.Jobs[jobId] = jobs.Job{JobId: jobId, Settings: &jobSettings} + s.Jobs[jobId] = jobs.Job{JobId: jobId, Settings: &jobSettings, CreatorUserName: TestUser.UserName} return Response{Body: jobs.CreateResponse{JobId: jobId}} } @@ -145,6 +145,62 @@ func (s *FakeWorkspace) JobsGetRun(req Request) Response { return Response{Body: run} } +func (s *FakeWorkspace) JobsUpdatePermissions(req Request, jobId string) Response { + var request jobs.JobPermissionsRequest + if err := json.Unmarshal(req.Body, &request); err != nil { + return Response{ + StatusCode: 400, + Body: fmt.Sprintf("request parsing error: %s", err), + } + } + + defer s.LockUnlock()() + + s.JobsPermissions[jobId] = request.AccessControlList + acl := []jobs.JobAccessControlResponse{} + for _, accessControlList := range request.AccessControlList { + acl = append(acl, jobs.JobAccessControlResponse{ + UserName: accessControlList.UserName, + ServicePrincipalName: accessControlList.ServicePrincipalName, + GroupName: accessControlList.GroupName, + AllPermissions: []jobs.JobPermission{ + { + PermissionLevel: accessControlList.PermissionLevel, + }, + }, + }) + } + + return Response{Body: jobs.JobPermissions{ + AccessControlList: acl, + ObjectType: "job", + ObjectId: jobId, + }} +} + +func (s *FakeWorkspace) JobsGetPermissions(req Request, jobId string) Response { + jobPermissions := s.JobsPermissions[jobId] + acl := []jobs.JobAccessControlResponse{} + for _, accessControlList := range jobPermissions { + acl = append(acl, jobs.JobAccessControlResponse{ + UserName: accessControlList.UserName, + ServicePrincipalName: accessControlList.ServicePrincipalName, + GroupName: accessControlList.GroupName, + AllPermissions: []jobs.JobPermission{ + { + PermissionLevel: accessControlList.PermissionLevel, + }, + }, + }) + } + + return Response{Body: jobs.JobPermissions{ + AccessControlList: acl, + ObjectType: "job", + ObjectId: fmt.Sprintf("jobs/%s", jobId), + }} +} + func setSourceIfNotSet(job jobs.Job) jobs.Job { if job.Settings != nil { source := "WORKSPACE" From a52e1225858ccc01ccc3ed5936994067e8cac34a Mon Sep 17 00:00:00 2001 From: Andrew Nester Date: Mon, 22 Sep 2025 16:33:59 +0200 Subject: [PATCH 2/9] fix lint --- libs/testserver/jobs.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/testserver/jobs.go b/libs/testserver/jobs.go index ea8cebff9f..29e95ee336 100644 --- a/libs/testserver/jobs.go +++ b/libs/testserver/jobs.go @@ -157,7 +157,7 @@ func (s *FakeWorkspace) JobsUpdatePermissions(req Request, jobId string) Respons defer s.LockUnlock()() s.JobsPermissions[jobId] = request.AccessControlList - acl := []jobs.JobAccessControlResponse{} + var acl []jobs.JobAccessControlResponse for _, accessControlList := range request.AccessControlList { acl = append(acl, jobs.JobAccessControlResponse{ UserName: accessControlList.UserName, @@ -180,7 +180,7 @@ func (s *FakeWorkspace) JobsUpdatePermissions(req Request, jobId string) Respons func (s *FakeWorkspace) JobsGetPermissions(req Request, jobId string) Response { jobPermissions := s.JobsPermissions[jobId] - acl := []jobs.JobAccessControlResponse{} + var acl []jobs.JobAccessControlResponse for _, accessControlList := range jobPermissions { acl = append(acl, jobs.JobAccessControlResponse{ UserName: accessControlList.UserName, @@ -197,7 +197,7 @@ func (s *FakeWorkspace) JobsGetPermissions(req Request, jobId string) Response { return Response{Body: jobs.JobPermissions{ AccessControlList: acl, ObjectType: "job", - ObjectId: fmt.Sprintf("jobs/%s", jobId), + ObjectId: "jobs/" + jobId, }} } From a2f9235907456a9d53ff9f867b6856dc9bc185cc Mon Sep 17 00:00:00 2001 From: Andrew Nester Date: Tue, 23 Sep 2025 14:10:38 +0200 Subject: [PATCH 3/9] run on cloud --- .../unbind/permissions/databricks.yml | 4 +- .../unbind/permissions/out.test.toml | 2 +- .../deployment/unbind/permissions/output.txt | 70 ++++++------------- .../deployment/unbind/permissions/script | 11 ++- .../deployment/unbind/permissions/test.toml | 2 +- libs/testserver/jobs.go | 4 +- 6 files changed, 35 insertions(+), 58 deletions(-) diff --git a/acceptance/bundle/deployment/unbind/permissions/databricks.yml b/acceptance/bundle/deployment/unbind/permissions/databricks.yml index 0840735b4e..7343099126 100644 --- a/acceptance/bundle/deployment/unbind/permissions/databricks.yml +++ b/acceptance/bundle/deployment/unbind/permissions/databricks.yml @@ -6,7 +6,5 @@ resources: job_1: name: "Job name" permissions: - - level: CAN_MANAGE - user_name: tester@user.com - - group_name: jiro-group + - group_name: users level: CAN_MANAGE diff --git a/acceptance/bundle/deployment/unbind/permissions/out.test.toml b/acceptance/bundle/deployment/unbind/permissions/out.test.toml index 90061dedb1..a9f28de48a 100644 --- a/acceptance/bundle/deployment/unbind/permissions/out.test.toml +++ b/acceptance/bundle/deployment/unbind/permissions/out.test.toml @@ -1,5 +1,5 @@ Local = true -Cloud = false +Cloud = true [EnvMatrix] DATABRICKS_BUNDLE_ENGINE = ["terraform"] diff --git a/acceptance/bundle/deployment/unbind/permissions/output.txt b/acceptance/bundle/deployment/unbind/permissions/output.txt index 6369491b2e..1fd072c891 100644 --- a/acceptance/bundle/deployment/unbind/permissions/output.txt +++ b/acceptance/bundle/deployment/unbind/permissions/output.txt @@ -9,34 +9,13 @@ Deployment complete! >>> [CLI] jobs get-permissions [NUMID] --output json { - "access_control_list": [ + "all_permissions": [ { - "all_permissions": [ - { - "permission_level":"CAN_MANAGE" - } - ], - "group_name":"jiro-group" - }, - { - "all_permissions": [ - { - "permission_level":"CAN_MANAGE" - } - ], - "user_name":"[USERNAME]@user.com" - }, - { - "all_permissions": [ - { - "permission_level":"IS_OWNER" - } - ], - "user_name":"[USERNAME]" + "inherited": false, + "permission_level": "CAN_MANAGE" } ], - "object_id":"jobs/[NUMID]", - "object_type":"job" + "group_name": "users" } >>> [CLI] bundle deployment unbind job_1 @@ -50,32 +29,23 @@ Deployment complete! >>> [CLI] jobs get-permissions [NUMID] --output json { - "access_control_list": [ - { - "all_permissions": [ - { - "permission_level":"CAN_MANAGE" - } - ], - "group_name":"jiro-group" - }, - { - "all_permissions": [ - { - "permission_level":"CAN_MANAGE" - } - ], - "user_name":"[USERNAME]@user.com" - }, + "all_permissions": [ { - "all_permissions": [ - { - "permission_level":"IS_OWNER" - } - ], - "user_name":"[USERNAME]" + "inherited": false, + "permission_level": "CAN_MANAGE" } ], - "object_id":"jobs/[NUMID]", - "object_type":"job" + "group_name": "users" } + +>>> [CLI] bundle destroy --auto-approve +The following resources will be deleted: + delete job job_1 + +All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/unbind_permissions/default + +Deleting files... +Destroy complete! + +>>> [CLI] jobs delete [NUMID] +0 diff --git a/acceptance/bundle/deployment/unbind/permissions/script b/acceptance/bundle/deployment/unbind/permissions/script index 9ed1cc7b4a..b742d72e32 100644 --- a/acceptance/bundle/deployment/unbind/permissions/script +++ b/acceptance/bundle/deployment/unbind/permissions/script @@ -1,7 +1,14 @@ +cleanup() { + trace $CLI bundle destroy --auto-approve + trace $CLI jobs delete $job_id + echo $? +} +trap cleanup EXIT + trace $CLI bundle deploy job_id=$(trace $CLI bundle summary --output json | jq -r '.resources.jobs.job_1.id') -trace $CLI jobs get-permissions $job_id --output json +trace $CLI jobs get-permissions $job_id --output json | jq '.access_control_list[] | select(.group_name == "users")' trace $CLI bundle deployment unbind job_1 trace $CLI bundle deploy -trace $CLI jobs get-permissions $job_id --output json +trace $CLI jobs get-permissions $job_id --output json | jq '.access_control_list[] | select(.group_name == "users")' diff --git a/acceptance/bundle/deployment/unbind/permissions/test.toml b/acceptance/bundle/deployment/unbind/permissions/test.toml index e4fc888c4d..22ffcf9cf6 100644 --- a/acceptance/bundle/deployment/unbind/permissions/test.toml +++ b/acceptance/bundle/deployment/unbind/permissions/test.toml @@ -1,4 +1,4 @@ -Cloud = false # test leaves deployed job +IsServicePrincipal = true [EnvMatrix] DATABRICKS_BUNDLE_ENGINE = ["terraform"] diff --git a/libs/testserver/jobs.go b/libs/testserver/jobs.go index 29e95ee336..ea2cfc2632 100644 --- a/libs/testserver/jobs.go +++ b/libs/testserver/jobs.go @@ -184,11 +184,13 @@ func (s *FakeWorkspace) JobsGetPermissions(req Request, jobId string) Response { for _, accessControlList := range jobPermissions { acl = append(acl, jobs.JobAccessControlResponse{ UserName: accessControlList.UserName, + DisplayName: accessControlList.UserName, ServicePrincipalName: accessControlList.ServicePrincipalName, GroupName: accessControlList.GroupName, AllPermissions: []jobs.JobPermission{ { PermissionLevel: accessControlList.PermissionLevel, + ForceSendFields: []string{"Inherited"}, }, }, }) @@ -197,7 +199,7 @@ func (s *FakeWorkspace) JobsGetPermissions(req Request, jobId string) Response { return Response{Body: jobs.JobPermissions{ AccessControlList: acl, ObjectType: "job", - ObjectId: "jobs/" + jobId, + ObjectId: "/jobs/" + jobId, }} } From b8d4fcfd583d4e82779c1df969133a066bdadb4a Mon Sep 17 00:00:00 2001 From: Andrew Nester Date: Tue, 23 Sep 2025 15:24:15 +0200 Subject: [PATCH 4/9] do not change grants as well --- .../unbind/grants/databricks.yml.tmpl | 19 ++++++++ .../deployment/unbind/grants/out.test.toml | 7 +++ .../deployment/unbind/grants/output.txt | 48 +++++++++++++++++++ .../bundle/deployment/unbind/grants/script | 18 +++++++ .../bundle/deployment/unbind/grants/test.toml | 9 ++++ .../deployment/unbind/permissions/test.toml | 4 ++ bundle/deploy/terraform/unbind.go | 6 +++ libs/testserver/fake_workspace.go | 2 + libs/testserver/handlers.go | 8 ++++ libs/testserver/schemas.go | 40 ++++++++++++++++ 10 files changed, 161 insertions(+) create mode 100644 acceptance/bundle/deployment/unbind/grants/databricks.yml.tmpl create mode 100644 acceptance/bundle/deployment/unbind/grants/out.test.toml create mode 100644 acceptance/bundle/deployment/unbind/grants/output.txt create mode 100644 acceptance/bundle/deployment/unbind/grants/script create mode 100644 acceptance/bundle/deployment/unbind/grants/test.toml diff --git a/acceptance/bundle/deployment/unbind/grants/databricks.yml.tmpl b/acceptance/bundle/deployment/unbind/grants/databricks.yml.tmpl new file mode 100644 index 0000000000..ca0346b412 --- /dev/null +++ b/acceptance/bundle/deployment/unbind/grants/databricks.yml.tmpl @@ -0,0 +1,19 @@ +bundle: + name: unbind_grants-$UNIQUE_NAME + +workspace: + root_path: ~/.bundle/$UNIQUE_NAME + +variables: + suffix: + default: "" + description: "Suffix for the schema name" + +resources: + schemas: + schema_1: + name: "test-schema-$UNIQUE_NAME${var.suffix}" + catalog_name: "main" + grants: + - principal: "account users" + privileges: ["CREATE_VOLUME", "SELECT"] diff --git a/acceptance/bundle/deployment/unbind/grants/out.test.toml b/acceptance/bundle/deployment/unbind/grants/out.test.toml new file mode 100644 index 0000000000..8409922737 --- /dev/null +++ b/acceptance/bundle/deployment/unbind/grants/out.test.toml @@ -0,0 +1,7 @@ +Local = true +Cloud = true +RequiresUnityCatalog = true + +[EnvMatrix] + DATABRICKS_BUNDLE_ENGINE = ["terraform"] + Ignore = [".databricks"] diff --git a/acceptance/bundle/deployment/unbind/grants/output.txt b/acceptance/bundle/deployment/unbind/grants/output.txt new file mode 100644 index 0000000000..c0fd96a70c --- /dev/null +++ b/acceptance/bundle/deployment/unbind/grants/output.txt @@ -0,0 +1,48 @@ + +>>> [CLI] bundle deploy +Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/[UNIQUE_NAME]/files... +Deploying resources... +Updating deployment state... +Deployment complete! + +>>> [CLI] grants get schema main.test-schema-[UNIQUE_NAME] --output json +{ + "principal": "account users", + "privileges": [ + "CREATE_VOLUME", + "SELECT" + ] +} + +>>> [CLI] bundle deployment unbind schema_1 +Updating deployment state... + +>>> [CLI] bundle deploy --var suffix=another +Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/[UNIQUE_NAME]/files... +Deploying resources... +Updating deployment state... +Deployment complete! + +>>> [CLI] grants get schema main.test-schema-[UNIQUE_NAME] --output json +{ + "principal": "account users", + "privileges": [ + "CREATE_VOLUME", + "SELECT" + ] +} + +>>> [CLI] bundle destroy --auto-approve +The following resources will be deleted: + delete schema schema_1 + +This action will result in the deletion of the following UC schemas. Any underlying data may be lost: + delete schema schema_1 + +All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/[UNIQUE_NAME] + +Deleting files... +Destroy complete! + +>>> [CLI] schemas delete main.test-schema-[UNIQUE_NAME] +0 diff --git a/acceptance/bundle/deployment/unbind/grants/script b/acceptance/bundle/deployment/unbind/grants/script new file mode 100644 index 0000000000..af1b4685e0 --- /dev/null +++ b/acceptance/bundle/deployment/unbind/grants/script @@ -0,0 +1,18 @@ +envsubst < databricks.yml.tmpl > databricks.yml + +cleanup() { + trace $CLI bundle destroy --auto-approve + if [[ -n "$schema_id" ]]; then + trace $CLI schemas delete $schema_id + fi + echo $? +} +trap cleanup EXIT + +trace $CLI bundle deploy +schema_id=$($CLI bundle summary --output json | jq -r '.resources.schemas.schema_1.id') +trace $CLI grants get schema $schema_id --output json | jq '.privilege_assignments[] | select(.principal == "account users")' + +trace $CLI bundle deployment unbind schema_1 +trace $CLI bundle deploy --var "suffix=another" +trace $CLI grants get schema $schema_id --output json | jq '.privilege_assignments[] | select(.principal == "account users")' diff --git a/acceptance/bundle/deployment/unbind/grants/test.toml b/acceptance/bundle/deployment/unbind/grants/test.toml new file mode 100644 index 0000000000..6acaacbd44 --- /dev/null +++ b/acceptance/bundle/deployment/unbind/grants/test.toml @@ -0,0 +1,9 @@ +IsServicePrincipal = true +RequiresUnityCatalog = true + +[EnvMatrix] + DATABRICKS_BUNDLE_ENGINE = ["terraform"] + +Ignore = [ + ".databricks", +] diff --git a/acceptance/bundle/deployment/unbind/permissions/test.toml b/acceptance/bundle/deployment/unbind/permissions/test.toml index 22ffcf9cf6..aac25997c4 100644 --- a/acceptance/bundle/deployment/unbind/permissions/test.toml +++ b/acceptance/bundle/deployment/unbind/permissions/test.toml @@ -2,3 +2,7 @@ IsServicePrincipal = true [EnvMatrix] DATABRICKS_BUNDLE_ENGINE = ["terraform"] + +Ignore = [ + ".databricks", +] diff --git a/bundle/deploy/terraform/unbind.go b/bundle/deploy/terraform/unbind.go index 85a2743468..04a63258e1 100644 --- a/bundle/deploy/terraform/unbind.go +++ b/bundle/deploy/terraform/unbind.go @@ -49,6 +49,12 @@ func (m *unbind) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { return diag.Errorf("terraform state rm: %v", err) } } + if resource.Address == fmt.Sprintf("databricks_grants.%s_%s", m.bundleType, m.resourceKey) { + err = tf.StateRm(ctx, resource.Address) + if err != nil { + return diag.Errorf("terraform state rm: %v", err) + } + } } return nil diff --git a/libs/testserver/fake_workspace.go b/libs/testserver/fake_workspace.go index 55ad6cbf6a..f97b0255e8 100644 --- a/libs/testserver/fake_workspace.go +++ b/libs/testserver/fake_workspace.go @@ -65,6 +65,7 @@ type FakeWorkspace struct { Jobs map[int64]jobs.Job JobRuns map[int64]jobs.Run JobsPermissions map[string][]jobs.JobAccessControlRequest + SchemasGrants map[string][]catalog.PrivilegeAssignment Pipelines map[string]pipelines.GetPipelineResponse PipelineUpdates map[string]bool @@ -155,6 +156,7 @@ func NewFakeWorkspace(url, token string) *FakeWorkspace { Jobs: map[int64]jobs.Job{}, JobRuns: map[int64]jobs.Run{}, JobsPermissions: map[string][]jobs.JobAccessControlRequest{}, + SchemasGrants: map[string][]catalog.PrivilegeAssignment{}, nextJobId: TestJobID, nextJobRunId: TestRunID, Pipelines: map[string]pipelines.GetPipelineResponse{}, diff --git a/libs/testserver/handlers.go b/libs/testserver/handlers.go index f8f2c7fc83..a0ab2070eb 100644 --- a/libs/testserver/handlers.go +++ b/libs/testserver/handlers.go @@ -349,6 +349,14 @@ func AddDefaultHandlers(server *Server) { return MapDelete(req.Workspace, req.Workspace.Schemas, req.Vars["full_name"]) }) + server.Handle("PATCH", "/api/2.1/unity-catalog/permissions/schema/{full_name}", func(req Request) any { + return req.Workspace.SchemasUpdateGrants(req, req.Vars["full_name"]) + }) + + server.Handle("GET", "/api/2.1/unity-catalog/permissions/schema/{full_name}", func(req Request) any { + return req.Workspace.SchemasGetGrants(req, req.Vars["full_name"]) + }) + // Volumes: server.Handle("GET", "/api/2.1/unity-catalog/volumes/{full_name}", func(req Request) any { diff --git a/libs/testserver/schemas.go b/libs/testserver/schemas.go index 94c63b0627..b3dbacf9a7 100644 --- a/libs/testserver/schemas.go +++ b/libs/testserver/schemas.go @@ -60,3 +60,43 @@ func (s *FakeWorkspace) SchemasUpdate(req Request, name string) Response { Body: existing, } } + +func (s *FakeWorkspace) SchemasUpdateGrants(req Request, fullName string) Response { + var request catalog.UpdatePermissions + if err := json.Unmarshal(req.Body, &request); err != nil { + return Response{ + StatusCode: http.StatusBadRequest, + Body: fmt.Sprintf("request parsing error: %s", err), + } + } + defer s.LockUnlock()() + + // For simplicity, we'll just replace all grants (similar to how job permissions work) + var grants []catalog.PrivilegeAssignment + for _, change := range request.Changes { + if len(change.Add) > 0 { + grants = append(grants, catalog.PrivilegeAssignment{ + Principal: change.Principal, + Privileges: change.Add, + }) + } + } + s.SchemasGrants[fullName] = grants + + return Response{ + Body: catalog.GetPermissionsResponse{ + PrivilegeAssignments: grants, + }, + } +} + +func (s *FakeWorkspace) SchemasGetGrants(req Request, fullName string) Response { + defer s.LockUnlock()() + + grants := s.SchemasGrants[fullName] + return Response{ + Body: catalog.GetPermissionsResponse{ + PrivilegeAssignments: grants, + }, + } +} From 08bf1208857d7e9f95702a98c7de6e7ff2f42560 Mon Sep 17 00:00:00 2001 From: Andrew Nester Date: Tue, 23 Sep 2025 15:54:04 +0200 Subject: [PATCH 5/9] fix lint and test --- acceptance/bundle/deployment/unbind/grants/out.test.toml | 1 - libs/testserver/schemas.go | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/acceptance/bundle/deployment/unbind/grants/out.test.toml b/acceptance/bundle/deployment/unbind/grants/out.test.toml index 8409922737..9016731b25 100644 --- a/acceptance/bundle/deployment/unbind/grants/out.test.toml +++ b/acceptance/bundle/deployment/unbind/grants/out.test.toml @@ -4,4 +4,3 @@ RequiresUnityCatalog = true [EnvMatrix] DATABRICKS_BUNDLE_ENGINE = ["terraform"] - Ignore = [".databricks"] diff --git a/libs/testserver/schemas.go b/libs/testserver/schemas.go index b3dbacf9a7..4dace522be 100644 --- a/libs/testserver/schemas.go +++ b/libs/testserver/schemas.go @@ -70,7 +70,7 @@ func (s *FakeWorkspace) SchemasUpdateGrants(req Request, fullName string) Respon } } defer s.LockUnlock()() - + // For simplicity, we'll just replace all grants (similar to how job permissions work) var grants []catalog.PrivilegeAssignment for _, change := range request.Changes { @@ -82,7 +82,7 @@ func (s *FakeWorkspace) SchemasUpdateGrants(req Request, fullName string) Respon } } s.SchemasGrants[fullName] = grants - + return Response{ Body: catalog.GetPermissionsResponse{ PrivilegeAssignments: grants, @@ -92,7 +92,7 @@ func (s *FakeWorkspace) SchemasUpdateGrants(req Request, fullName string) Respon func (s *FakeWorkspace) SchemasGetGrants(req Request, fullName string) Response { defer s.LockUnlock()() - + grants := s.SchemasGrants[fullName] return Response{ Body: catalog.GetPermissionsResponse{ From 11acdcc021655fc042ab80fa47c35c6b1884942f Mon Sep 17 00:00:00 2001 From: Andrew Nester Date: Tue, 23 Sep 2025 16:21:58 +0200 Subject: [PATCH 6/9] fixed out.test.toml --- acceptance/bundle/deployment/unbind/grants/out.test.toml | 1 + acceptance/bundle/deployment/unbind/permissions/out.test.toml | 1 + 2 files changed, 2 insertions(+) diff --git a/acceptance/bundle/deployment/unbind/grants/out.test.toml b/acceptance/bundle/deployment/unbind/grants/out.test.toml index 9016731b25..8409922737 100644 --- a/acceptance/bundle/deployment/unbind/grants/out.test.toml +++ b/acceptance/bundle/deployment/unbind/grants/out.test.toml @@ -4,3 +4,4 @@ RequiresUnityCatalog = true [EnvMatrix] DATABRICKS_BUNDLE_ENGINE = ["terraform"] + Ignore = [".databricks"] diff --git a/acceptance/bundle/deployment/unbind/permissions/out.test.toml b/acceptance/bundle/deployment/unbind/permissions/out.test.toml index a9f28de48a..4dccab7df1 100644 --- a/acceptance/bundle/deployment/unbind/permissions/out.test.toml +++ b/acceptance/bundle/deployment/unbind/permissions/out.test.toml @@ -3,3 +3,4 @@ Cloud = true [EnvMatrix] DATABRICKS_BUNDLE_ENGINE = ["terraform"] + Ignore = [".databricks"] From c04d29bcca21407af81454a82a225c4083c32ecb Mon Sep 17 00:00:00 2001 From: Andrew Nester Date: Tue, 23 Sep 2025 17:10:53 +0200 Subject: [PATCH 7/9] use unique path --- .../permissions/{databricks.yml => databricks.yml.tmpl} | 3 +++ acceptance/bundle/deployment/unbind/permissions/output.txt | 6 +++--- acceptance/bundle/deployment/unbind/permissions/script | 2 ++ 3 files changed, 8 insertions(+), 3 deletions(-) rename acceptance/bundle/deployment/unbind/permissions/{databricks.yml => databricks.yml.tmpl} (76%) diff --git a/acceptance/bundle/deployment/unbind/permissions/databricks.yml b/acceptance/bundle/deployment/unbind/permissions/databricks.yml.tmpl similarity index 76% rename from acceptance/bundle/deployment/unbind/permissions/databricks.yml rename to acceptance/bundle/deployment/unbind/permissions/databricks.yml.tmpl index 7343099126..206eee9d19 100644 --- a/acceptance/bundle/deployment/unbind/permissions/databricks.yml +++ b/acceptance/bundle/deployment/unbind/permissions/databricks.yml.tmpl @@ -1,6 +1,9 @@ bundle: name: unbind_permissions +workspace: + root_path: "~/.bundle/$UNIQUE_NAME" + resources: jobs: job_1: diff --git a/acceptance/bundle/deployment/unbind/permissions/output.txt b/acceptance/bundle/deployment/unbind/permissions/output.txt index 1fd072c891..7dcf2f2f51 100644 --- a/acceptance/bundle/deployment/unbind/permissions/output.txt +++ b/acceptance/bundle/deployment/unbind/permissions/output.txt @@ -1,6 +1,6 @@ >>> [CLI] bundle deploy -Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/unbind_permissions/default/files... +Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/[UNIQUE_NAME]/files... Deploying resources... Updating deployment state... Deployment complete! @@ -22,7 +22,7 @@ Deployment complete! Updating deployment state... >>> [CLI] bundle deploy -Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/unbind_permissions/default/files... +Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/[UNIQUE_NAME]/files... Deploying resources... Updating deployment state... Deployment complete! @@ -42,7 +42,7 @@ Deployment complete! The following resources will be deleted: delete job job_1 -All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/unbind_permissions/default +All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/[UNIQUE_NAME] Deleting files... Destroy complete! diff --git a/acceptance/bundle/deployment/unbind/permissions/script b/acceptance/bundle/deployment/unbind/permissions/script index b742d72e32..187c05f22f 100644 --- a/acceptance/bundle/deployment/unbind/permissions/script +++ b/acceptance/bundle/deployment/unbind/permissions/script @@ -1,3 +1,5 @@ +envsubst < databricks.yml.tmpl > databricks.yml + cleanup() { trace $CLI bundle destroy --auto-approve trace $CLI jobs delete $job_id From 1851e47b2a78fffc5f93867cf78dd8fe8f1bb9ac Mon Sep 17 00:00:00 2001 From: Andrew Nester Date: Wed, 24 Sep 2025 11:06:56 +0200 Subject: [PATCH 8/9] changelog --- NEXT_CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/NEXT_CHANGELOG.md b/NEXT_CHANGELOG.md index c1f7fd6bc9..e33100ece0 100644 --- a/NEXT_CHANGELOG.md +++ b/NEXT_CHANGELOG.md @@ -10,5 +10,6 @@ ### Bundles * Add new Lakeflow Pipelines support for bundle generate ([#3568](https://github.com/databricks/cli/pull/3568)) +* Fix bundle deploy to not update permissions for unbound resources ([#3642](https://github.com/databricks/cli/pull/3642)) ### API Changes From cde762da5a7a316f1af7a7ce31e6e9ed6b17e25f Mon Sep 17 00:00:00 2001 From: Andrew Nester Date: Wed, 24 Sep 2025 11:41:24 +0200 Subject: [PATCH 9/9] fixes --- NEXT_CHANGELOG.md | 2 +- acceptance/bundle/deployment/unbind/grants/output.txt | 1 + acceptance/bundle/deployment/unbind/grants/script | 2 ++ acceptance/bundle/deployment/unbind/grants/test.toml | 1 - .../bundle/deployment/unbind/permissions/output.txt | 1 + acceptance/bundle/deployment/unbind/permissions/script | 2 ++ .../bundle/deployment/unbind/permissions/test.toml | 2 -- bundle/deploy/terraform/unbind.go | 9 ++------- libs/testserver/fake_workspace.go | 7 +++---- libs/testserver/jobs.go | 6 ++++-- 10 files changed, 16 insertions(+), 17 deletions(-) diff --git a/NEXT_CHANGELOG.md b/NEXT_CHANGELOG.md index de24d165b2..4b8ed3d9c6 100644 --- a/NEXT_CHANGELOG.md +++ b/NEXT_CHANGELOG.md @@ -10,7 +10,7 @@ ### Bundles * Add new Lakeflow Pipelines support for bundle generate ([#3568](https://github.com/databricks/cli/pull/3568)) -* Fix bundle deploy to not update permissions for unbound resources ([#3642](https://github.com/databricks/cli/pull/3642)) +* Fix bundle deploy to not update permissions or grants for unbound resources ([#3642](https://github.com/databricks/cli/pull/3642)) * Introduce new bundle variable: `${workspace.current_user.domain_friendly_name}` ([#3623](https://github.com/databricks/cli/pull/3623)) ### API Changes diff --git a/acceptance/bundle/deployment/unbind/grants/output.txt b/acceptance/bundle/deployment/unbind/grants/output.txt index c0fd96a70c..df6ed2d492 100644 --- a/acceptance/bundle/deployment/unbind/grants/output.txt +++ b/acceptance/bundle/deployment/unbind/grants/output.txt @@ -23,6 +23,7 @@ Deploying resources... Updating deployment state... Deployment complete! +=== Grants should be the same as before unbind >>> [CLI] grants get schema main.test-schema-[UNIQUE_NAME] --output json { "principal": "account users", diff --git a/acceptance/bundle/deployment/unbind/grants/script b/acceptance/bundle/deployment/unbind/grants/script index af1b4685e0..f6da92a7e6 100644 --- a/acceptance/bundle/deployment/unbind/grants/script +++ b/acceptance/bundle/deployment/unbind/grants/script @@ -15,4 +15,6 @@ trace $CLI grants get schema $schema_id --output json | jq '.privilege_assignmen trace $CLI bundle deployment unbind schema_1 trace $CLI bundle deploy --var "suffix=another" + +title "Grants should be the same as before unbind" trace $CLI grants get schema $schema_id --output json | jq '.privilege_assignments[] | select(.principal == "account users")' diff --git a/acceptance/bundle/deployment/unbind/grants/test.toml b/acceptance/bundle/deployment/unbind/grants/test.toml index 6acaacbd44..ca6de773cd 100644 --- a/acceptance/bundle/deployment/unbind/grants/test.toml +++ b/acceptance/bundle/deployment/unbind/grants/test.toml @@ -1,4 +1,3 @@ -IsServicePrincipal = true RequiresUnityCatalog = true [EnvMatrix] diff --git a/acceptance/bundle/deployment/unbind/permissions/output.txt b/acceptance/bundle/deployment/unbind/permissions/output.txt index 7dcf2f2f51..d43b51fdd5 100644 --- a/acceptance/bundle/deployment/unbind/permissions/output.txt +++ b/acceptance/bundle/deployment/unbind/permissions/output.txt @@ -27,6 +27,7 @@ Deploying resources... Updating deployment state... Deployment complete! +=== Permissions should be the same as before unbind >>> [CLI] jobs get-permissions [NUMID] --output json { "all_permissions": [ diff --git a/acceptance/bundle/deployment/unbind/permissions/script b/acceptance/bundle/deployment/unbind/permissions/script index 187c05f22f..078e3c3af6 100644 --- a/acceptance/bundle/deployment/unbind/permissions/script +++ b/acceptance/bundle/deployment/unbind/permissions/script @@ -13,4 +13,6 @@ trace $CLI jobs get-permissions $job_id --output json | jq '.access_control_list trace $CLI bundle deployment unbind job_1 trace $CLI bundle deploy + +title "Permissions should be the same as before unbind" trace $CLI jobs get-permissions $job_id --output json | jq '.access_control_list[] | select(.group_name == "users")' diff --git a/acceptance/bundle/deployment/unbind/permissions/test.toml b/acceptance/bundle/deployment/unbind/permissions/test.toml index aac25997c4..0708e106d0 100644 --- a/acceptance/bundle/deployment/unbind/permissions/test.toml +++ b/acceptance/bundle/deployment/unbind/permissions/test.toml @@ -1,5 +1,3 @@ -IsServicePrincipal = true - [EnvMatrix] DATABRICKS_BUNDLE_ENGINE = ["terraform"] diff --git a/bundle/deploy/terraform/unbind.go b/bundle/deploy/terraform/unbind.go index 04a63258e1..6eeb323f16 100644 --- a/bundle/deploy/terraform/unbind.go +++ b/bundle/deploy/terraform/unbind.go @@ -43,13 +43,8 @@ func (m *unbind) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { } for _, resource := range state.Values.RootModule.Resources { - if resource.Address == fmt.Sprintf("databricks_permissions.%s_%s", m.bundleType, m.resourceKey) { - err = tf.StateRm(ctx, resource.Address) - if err != nil { - return diag.Errorf("terraform state rm: %v", err) - } - } - if resource.Address == fmt.Sprintf("databricks_grants.%s_%s", m.bundleType, m.resourceKey) { + if resource.Address == fmt.Sprintf("databricks_permissions.%s_%s", m.bundleType, m.resourceKey) || + resource.Address == fmt.Sprintf("databricks_grants.%s_%s", m.bundleType, m.resourceKey) { err = tf.StateRm(ctx, resource.Address) if err != nil { return diag.Errorf("terraform state rm: %v", err) diff --git a/libs/testserver/fake_workspace.go b/libs/testserver/fake_workspace.go index f97b0255e8..9918cc1888 100644 --- a/libs/testserver/fake_workspace.go +++ b/libs/testserver/fake_workspace.go @@ -64,14 +64,13 @@ type FakeWorkspace struct { nextJobRunId int64 Jobs map[int64]jobs.Job JobRuns map[int64]jobs.Run - JobsPermissions map[string][]jobs.JobAccessControlRequest - SchemasGrants map[string][]catalog.PrivilegeAssignment - + JobPermissions map[string][]jobs.JobAccessControlRequest Pipelines map[string]pipelines.GetPipelineResponse PipelineUpdates map[string]bool Monitors map[string]catalog.MonitorInfo Apps map[string]apps.App Schemas map[string]catalog.SchemaInfo + SchemasGrants map[string][]catalog.PrivilegeAssignment Volumes map[string]catalog.VolumeInfo Dashboards map[string]dashboards.Dashboard SqlWarehouses map[string]sql.GetWarehouseResponse @@ -155,7 +154,7 @@ func NewFakeWorkspace(url, token string) *FakeWorkspace { Jobs: map[int64]jobs.Job{}, JobRuns: map[int64]jobs.Run{}, - JobsPermissions: map[string][]jobs.JobAccessControlRequest{}, + JobPermissions: map[string][]jobs.JobAccessControlRequest{}, SchemasGrants: map[string][]catalog.PrivilegeAssignment{}, nextJobId: TestJobID, nextJobRunId: TestRunID, diff --git a/libs/testserver/jobs.go b/libs/testserver/jobs.go index ea2cfc2632..45c368b9e2 100644 --- a/libs/testserver/jobs.go +++ b/libs/testserver/jobs.go @@ -31,6 +31,8 @@ func (s *FakeWorkspace) JobsCreate(req Request) Response { } } + // CreatorUserName field is used by TF to check if the resource exists or not. CreatorUserName should be non-empty for the resource to be considered as "exists" + // https://github.com/databricks/terraform-provider-databricks/blob/main/permissions/permission_definitions.go#L108 s.Jobs[jobId] = jobs.Job{JobId: jobId, Settings: &jobSettings, CreatorUserName: TestUser.UserName} return Response{Body: jobs.CreateResponse{JobId: jobId}} } @@ -156,7 +158,7 @@ func (s *FakeWorkspace) JobsUpdatePermissions(req Request, jobId string) Respons defer s.LockUnlock()() - s.JobsPermissions[jobId] = request.AccessControlList + s.JobPermissions[jobId] = request.AccessControlList var acl []jobs.JobAccessControlResponse for _, accessControlList := range request.AccessControlList { acl = append(acl, jobs.JobAccessControlResponse{ @@ -179,7 +181,7 @@ func (s *FakeWorkspace) JobsUpdatePermissions(req Request, jobId string) Respons } func (s *FakeWorkspace) JobsGetPermissions(req Request, jobId string) Response { - jobPermissions := s.JobsPermissions[jobId] + jobPermissions := s.JobPermissions[jobId] var acl []jobs.JobAccessControlResponse for _, accessControlList := range jobPermissions { acl = append(acl, jobs.JobAccessControlResponse{