From 61b5a2ef196020c63905e8cb223fc282a98ba95b Mon Sep 17 00:00:00 2001 From: Andrew Nester Date: Mon, 2 Mar 2026 17:16:14 +0100 Subject: [PATCH 1/3] Added permissions support for Lakebase Database projects --- .../current_can_manage/databricks.yml | 17 ++++++ .../current_can_manage/out.plan.direct.json | 47 ++++++++++++++++ .../out.plan.terraform.json | 11 ++++ .../out.requests.deploy.direct.json | 24 +++++++++ .../out.requests.deploy.terraform.json | 24 +++++++++ .../out.requests.destroy.direct.json | 0 .../out.requests.destroy.terraform.json | 12 +++++ .../current_can_manage/out.test.toml | 5 ++ .../current_can_manage/output.txt | 35 ++++++++++++ .../current_can_manage/script | 1 + .../permissions/postgres_projects/test.toml | 1 + .../apply_bundle_permissions.go | 4 ++ .../apply_bundle_permissions_test.go | 1 - bundle/config/resources/permission.go | 15 ++++++ bundle/config/resources/postgres_project.go | 2 + bundle/deploy/terraform/showplanfile.go | 1 + .../tfdyn/convert_postgres_project.go | 7 +++ .../tfdyn/convert_postgres_project_test.go | 53 +++++++++++++++++++ bundle/direct/dresources/all.go | 1 + bundle/direct/dresources/all_test.go | 22 ++++++++ bundle/direct/dresources/permissions.go | 6 +++ libs/testserver/permissions.go | 1 + 22 files changed, 289 insertions(+), 1 deletion(-) create mode 100644 acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/databricks.yml create mode 100644 acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/out.plan.direct.json create mode 100644 acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/out.plan.terraform.json create mode 100644 acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/out.requests.deploy.direct.json create mode 100644 acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/out.requests.deploy.terraform.json create mode 100644 acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/out.requests.destroy.direct.json create mode 100644 acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/out.requests.destroy.terraform.json create mode 100644 acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/out.test.toml create mode 100644 acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/output.txt create mode 100644 acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/script create mode 100644 acceptance/bundle/resources/permissions/postgres_projects/test.toml diff --git a/acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/databricks.yml b/acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/databricks.yml new file mode 100644 index 0000000000..fdce7d9c53 --- /dev/null +++ b/acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/databricks.yml @@ -0,0 +1,17 @@ +bundle: + name: test-bundle + +resources: + postgres_projects: + foo: + project_id: test-project + display_name: Test Postgres Project + permissions: + - level: CAN_USE + user_name: viewer@example.com + - level: CAN_MANAGE + group_name: data-team + - level: CAN_MANAGE + service_principal_name: f37d18cd-98a8-4db5-8112-12dd0a6bfe38 + - level: CAN_MANAGE + user_name: tester@databricks.com diff --git a/acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/out.plan.direct.json b/acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/out.plan.direct.json new file mode 100644 index 0000000000..5dc10317fe --- /dev/null +++ b/acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/out.plan.direct.json @@ -0,0 +1,47 @@ +{ + "plan_version": 2, + "cli_version": "[DEV_VERSION]", + "plan": { + "resources.postgres_projects.foo": { + "action": "create", + "new_state": { + "value": { + "display_name": "Test Postgres Project", + "project_id": "test-project" + } + } + }, + "resources.postgres_projects.foo.permissions": { + "depends_on": [ + { + "node": "resources.postgres_projects.foo", + "label": "${resources.postgres_projects.foo.project_id}" + } + ], + "action": "create", + "new_state": { + "value": { + "object_id": "/database-projects/test-project", + "permissions": [ + { + "permission_level": "CAN_USE", + "user_name": "viewer@example.com" + }, + { + "group_name": "data-team", + "permission_level": "CAN_MANAGE" + }, + { + "permission_level": "CAN_MANAGE", + "service_principal_name": "[UUID]" + }, + { + "permission_level": "CAN_MANAGE", + "user_name": "[USERNAME]" + } + ] + } + } + } + } +} diff --git a/acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/out.plan.terraform.json b/acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/out.plan.terraform.json new file mode 100644 index 0000000000..c6e5e5c644 --- /dev/null +++ b/acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/out.plan.terraform.json @@ -0,0 +1,11 @@ +{ + "cli_version": "[DEV_VERSION]", + "plan": { + "resources.postgres_projects.foo": { + "action": "create" + }, + "resources.postgres_projects.foo.permissions": { + "action": "create" + } + } +} diff --git a/acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/out.requests.deploy.direct.json b/acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/out.requests.deploy.direct.json new file mode 100644 index 0000000000..673b537f7f --- /dev/null +++ b/acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/out.requests.deploy.direct.json @@ -0,0 +1,24 @@ +{ + "method": "PUT", + "path": "/api/2.0/permissions/database-projects/test-project", + "body": { + "access_control_list": [ + { + "permission_level": "CAN_USE", + "user_name": "viewer@example.com" + }, + { + "group_name": "data-team", + "permission_level": "CAN_MANAGE" + }, + { + "permission_level": "CAN_MANAGE", + "service_principal_name": "[UUID]" + }, + { + "permission_level": "CAN_MANAGE", + "user_name": "[USERNAME]" + } + ] + } +} diff --git a/acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/out.requests.deploy.terraform.json b/acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/out.requests.deploy.terraform.json new file mode 100644 index 0000000000..f554e966cc --- /dev/null +++ b/acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/out.requests.deploy.terraform.json @@ -0,0 +1,24 @@ +{ + "method": "PUT", + "path": "/api/2.0/permissions/database-projects/test-project", + "body": { + "access_control_list": [ + { + "permission_level": "CAN_USE", + "user_name": "viewer@example.com" + }, + { + "permission_level": "CAN_MANAGE", + "service_principal_name": "[UUID]" + }, + { + "group_name": "data-team", + "permission_level": "CAN_MANAGE" + }, + { + "permission_level": "CAN_MANAGE", + "user_name": "[USERNAME]" + } + ] + } +} diff --git a/acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/out.requests.destroy.direct.json b/acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/out.requests.destroy.direct.json new file mode 100644 index 0000000000..e69de29bb2 diff --git a/acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/out.requests.destroy.terraform.json b/acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/out.requests.destroy.terraform.json new file mode 100644 index 0000000000..1df0a7fbeb --- /dev/null +++ b/acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/out.requests.destroy.terraform.json @@ -0,0 +1,12 @@ +{ + "method": "PUT", + "path": "/api/2.0/permissions/database-projects/test-project", + "body": { + "access_control_list": [ + { + "permission_level": "CAN_MANAGE", + "user_name": "[USERNAME]" + } + ] + } +} diff --git a/acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/out.test.toml b/acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/out.test.toml new file mode 100644 index 0000000000..d560f1de04 --- /dev/null +++ b/acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/out.test.toml @@ -0,0 +1,5 @@ +Local = true +Cloud = false + +[EnvMatrix] + DATABRICKS_BUNDLE_ENGINE = ["terraform", "direct"] diff --git a/acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/output.txt b/acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/output.txt new file mode 100644 index 0000000000..10e8ce61d5 --- /dev/null +++ b/acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/output.txt @@ -0,0 +1,35 @@ + +>>> [CLI] bundle validate -o json +[ + { + "level": "CAN_USE", + "user_name": "viewer@example.com" + }, + { + "group_name": "data-team", + "level": "CAN_MANAGE" + }, + { + "level": "CAN_MANAGE", + "service_principal_name": "[UUID]" + }, + { + "level": "CAN_MANAGE", + "user_name": "[USERNAME]" + } +] + +>>> [CLI] bundle deploy +Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files... +Deploying resources... +Updating deployment state... +Deployment complete! + +>>> [CLI] bundle destroy --auto-approve +The following resources will be deleted: + delete resources.postgres_projects.foo + +All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/test-bundle/default + +Deleting files... +Destroy complete! diff --git a/acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/script b/acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/script new file mode 100644 index 0000000000..7d1e9fc8e2 --- /dev/null +++ b/acceptance/bundle/resources/permissions/postgres_projects/current_can_manage/script @@ -0,0 +1 @@ +source $TESTDIR/../../_script diff --git a/acceptance/bundle/resources/permissions/postgres_projects/test.toml b/acceptance/bundle/resources/permissions/postgres_projects/test.toml new file mode 100644 index 0000000000..1d603576d1 --- /dev/null +++ b/acceptance/bundle/resources/permissions/postgres_projects/test.toml @@ -0,0 +1 @@ +Env.RESOURCE = "postgres_projects" # for ../_script diff --git a/bundle/config/mutator/resourcemutator/apply_bundle_permissions.go b/bundle/config/mutator/resourcemutator/apply_bundle_permissions.go index dfb36fbca1..e99281b27a 100644 --- a/bundle/config/mutator/resourcemutator/apply_bundle_permissions.go +++ b/bundle/config/mutator/resourcemutator/apply_bundle_permissions.go @@ -67,6 +67,10 @@ var ( permissions.CAN_MANAGE: "CAN_MANAGE", permissions.CAN_VIEW: "CAN_USE", }, + "postgres_projects": { + permissions.CAN_MANAGE: "CAN_MANAGE", + permissions.CAN_VIEW: "CAN_USE", + }, "clusters": { // https://docs.databricks.com/aws/en/security/auth/access-control/#compute-acls permissions.CAN_MANAGE: "CAN_MANAGE", diff --git a/bundle/config/mutator/resourcemutator/apply_bundle_permissions_test.go b/bundle/config/mutator/resourcemutator/apply_bundle_permissions_test.go index 609215b053..9afe53fe1d 100644 --- a/bundle/config/mutator/resourcemutator/apply_bundle_permissions_test.go +++ b/bundle/config/mutator/resourcemutator/apply_bundle_permissions_test.go @@ -27,7 +27,6 @@ var unsupportedResources = []string{ "registered_models", "database_catalogs", "synced_database_tables", - "postgres_projects", "postgres_branches", "postgres_endpoints", } diff --git a/bundle/config/resources/permission.go b/bundle/config/resources/permission.go index b13c81e5e9..8964af5f0c 100644 --- a/bundle/config/resources/permission.go +++ b/bundle/config/resources/permission.go @@ -45,6 +45,7 @@ type ( ClusterPermissionLevel string DashboardPermissionLevel string DatabaseInstancePermissionLevel string + DatabaseProjectPermissionLevel string JobPermissionLevel string MlflowExperimentPermissionLevel string MlflowModelPermissionLevel string @@ -102,6 +103,14 @@ type DatabaseInstancePermission struct { GroupName string `json:"group_name,omitempty"` } +type DatabaseProjectPermission struct { + Level DatabaseProjectPermissionLevel `json:"level"` + + UserName string `json:"user_name,omitempty"` + ServicePrincipalName string `json:"service_principal_name,omitempty"` + GroupName string `json:"group_name,omitempty"` +} + type JobPermission struct { Level JobPermissionLevel `json:"level"` @@ -157,6 +166,7 @@ func (p AppPermission) GetAPIRequestObjectType() string { return "/ func (p ClusterPermission) GetAPIRequestObjectType() string { return "/clusters/" } func (p DashboardPermission) GetAPIRequestObjectType() string { return "/dashboards/" } func (p DatabaseInstancePermission) GetAPIRequestObjectType() string { return "/database-instances/" } +func (p DatabaseProjectPermission) GetAPIRequestObjectType() string { return "/database-projects/" } func (p JobPermission) GetAPIRequestObjectType() string { return "/jobs/" } func (p MlflowExperimentPermission) GetAPIRequestObjectType() string { return "/experiments/" } func (p MlflowModelPermission) GetAPIRequestObjectType() string { return "/registered-models/" } @@ -193,6 +203,11 @@ func (p DatabaseInstancePermission) GetUserName() string { return p. func (p DatabaseInstancePermission) GetServicePrincipalName() string { return p.ServicePrincipalName } func (p DatabaseInstancePermission) GetGroupName() string { return p.GroupName } +func (p DatabaseProjectPermission) GetLevel() string { return string(p.Level) } +func (p DatabaseProjectPermission) GetUserName() string { return p.UserName } +func (p DatabaseProjectPermission) GetServicePrincipalName() string { return p.ServicePrincipalName } +func (p DatabaseProjectPermission) GetGroupName() string { return p.GroupName } + func (p JobPermission) GetLevel() string { return string(p.Level) } func (p JobPermission) GetUserName() string { return p.UserName } func (p JobPermission) GetServicePrincipalName() string { return p.ServicePrincipalName } diff --git a/bundle/config/resources/postgres_project.go b/bundle/config/resources/postgres_project.go index 90fbac75f7..a1c26d00ed 100644 --- a/bundle/config/resources/postgres_project.go +++ b/bundle/config/resources/postgres_project.go @@ -29,6 +29,8 @@ func (c *PostgresProjectConfig) MarshalJSON() ([]byte, error) { type PostgresProject struct { BaseResource PostgresProjectConfig + + Permissions []DatabaseProjectPermission `json:"permissions,omitempty"` } func (p *PostgresProject) Exists(ctx context.Context, w *databricks.WorkspaceClient, name string) (bool, error) { diff --git a/bundle/deploy/terraform/showplanfile.go b/bundle/deploy/terraform/showplanfile.go index bbddc599b0..23e9436b34 100644 --- a/bundle/deploy/terraform/showplanfile.go +++ b/bundle/deploy/terraform/showplanfile.go @@ -28,6 +28,7 @@ var prefixToGroup = []struct{ prefix, group string }{ {"model_serving_", "model_serving_endpoints"}, {"sql_endpoint_", "sql_warehouses"}, {"database_instance_", "database_instances"}, + {"postgres_project_", "postgres_projects"}, } var grantsPrefix = []struct{ prefix, group string }{ diff --git a/bundle/deploy/terraform/tfdyn/convert_postgres_project.go b/bundle/deploy/terraform/tfdyn/convert_postgres_project.go index 69bc081544..b6b1294caf 100644 --- a/bundle/deploy/terraform/tfdyn/convert_postgres_project.go +++ b/bundle/deploy/terraform/tfdyn/convert_postgres_project.go @@ -2,6 +2,7 @@ package tfdyn import ( "context" + "fmt" "github.com/databricks/cli/bundle/internal/tf/schema" "github.com/databricks/cli/libs/dyn" @@ -52,6 +53,12 @@ func (c postgresProjectConverter) Convert(ctx context.Context, key string, vin d out.PostgresProject[key] = vout.AsAny() + // Configure permissions for this resource. + if permissions := convertPermissionsResource(ctx, vin); permissions != nil { + permissions.DatabaseProjectName = fmt.Sprintf("${databricks_postgres_project.%s.project_id}", key) + out.Permissions["postgres_project_"+key] = permissions + } + return nil } diff --git a/bundle/deploy/terraform/tfdyn/convert_postgres_project_test.go b/bundle/deploy/terraform/tfdyn/convert_postgres_project_test.go index c8fb955468..d403569b2d 100644 --- a/bundle/deploy/terraform/tfdyn/convert_postgres_project_test.go +++ b/bundle/deploy/terraform/tfdyn/convert_postgres_project_test.go @@ -56,6 +56,59 @@ func TestConvertPostgresProject(t *testing.T) { }, postgresProject) } +func TestConvertPostgresProjectWithPermissions(t *testing.T) { + src := resources.PostgresProject{ + PostgresProjectConfig: resources.PostgresProjectConfig{ + ProjectId: "my-project", + ProjectSpec: postgres.ProjectSpec{ + DisplayName: "My Postgres Project", + PgVersion: 17, + }, + }, + Permissions: []resources.DatabaseProjectPermission{ + { + Level: "CAN_USE", + UserName: "user@example.com", + }, + { + Level: "CAN_MANAGE", + ServicePrincipalName: "sp-name", + }, + }, + } + + vin, err := convert.FromTyped(src, dyn.NilValue) + require.NoError(t, err) + + ctx := context.Background() + out := schema.NewResources() + err = postgresProjectConverter{}.Convert(ctx, "my_postgres_project", vin, out) + require.NoError(t, err) + + postgresProject := out.PostgresProject["my_postgres_project"] + assert.Equal(t, map[string]any{ + "project_id": "my-project", + "spec": map[string]any{ + "display_name": "My Postgres Project", + "pg_version": int64(17), + }, + }, postgresProject) + + assert.Equal(t, &schema.ResourcePermissions{ + DatabaseProjectName: "${databricks_postgres_project.my_postgres_project.project_id}", + AccessControl: []schema.ResourcePermissionsAccessControl{ + { + PermissionLevel: "CAN_USE", + UserName: "user@example.com", + }, + { + PermissionLevel: "CAN_MANAGE", + ServicePrincipalName: "sp-name", + }, + }, + }, out.Permissions["postgres_project_my_postgres_project"]) +} + func TestConvertPostgresProjectMinimal(t *testing.T) { src := resources.PostgresProject{ PostgresProjectConfig: resources.PostgresProjectConfig{ diff --git a/bundle/direct/dresources/all.go b/bundle/direct/dresources/all.go index 56da049ab2..6a7381a3fc 100644 --- a/bundle/direct/dresources/all.go +++ b/bundle/direct/dresources/all.go @@ -38,6 +38,7 @@ var SupportedResources = map[string]any{ "alerts.permissions": (*ResourcePermissions)(nil), "clusters.permissions": (*ResourcePermissions)(nil), "database_instances.permissions": (*ResourcePermissions)(nil), + "postgres_projects.permissions": (*ResourcePermissions)(nil), "experiments.permissions": (*ResourcePermissions)(nil), "models.permissions": (*ResourcePermissions)(nil), "sql_warehouses.permissions": (*ResourcePermissions)(nil), diff --git a/bundle/direct/dresources/all_test.go b/bundle/direct/dresources/all_test.go index 559685b891..664f01b7f7 100644 --- a/bundle/direct/dresources/all_test.go +++ b/bundle/direct/dresources/all_test.go @@ -396,6 +396,28 @@ var testDeps = map[string]prepareWorkspace{ }, nil }, + "postgres_projects.permissions": func(client *databricks.WorkspaceClient) (any, error) { + waiter, err := client.Postgres.CreateProject(context.Background(), postgres.CreateProjectRequest{ + ProjectId: "permissions-project", + }) + if err != nil { + return nil, err + } + result, err := waiter.Wait(context.Background()) + if err != nil { + return nil, err + } + + components, _ := ParsePostgresName(result.Name) + return &PermissionsState{ + ObjectID: "/database-projects/" + components.ProjectID, + Permissions: []iam.AccessControlRequest{{ + PermissionLevel: "CAN_MANAGE", + UserName: "user@example.com", + }}, + }, nil + }, + "dashboards.permissions": func(client *databricks.WorkspaceClient) (any, error) { ctx := context.Background() parentPath := "/Workspace/Users/user@example.com" diff --git a/bundle/direct/dresources/permissions.go b/bundle/direct/dresources/permissions.go index 553f6b4e0b..7c47e11c73 100644 --- a/bundle/direct/dresources/permissions.go +++ b/bundle/direct/dresources/permissions.go @@ -66,6 +66,12 @@ func PreparePermissionsInputConfig(inputConfig any, node string) (*structvar.Str objectIdRef = prefix + "${" + baseNode + ".endpoint_id}" } + // Postgres projects store their hierarchical name ("projects/{project_id}") as the state ID, + // but the permissions API expects just the project_id. + if strings.HasPrefix(baseNode, "resources.postgres_projects.") { + objectIdRef = prefix + "${" + baseNode + ".project_id}" + } + return &structvar.StructVar{ Value: &PermissionsState{ ObjectID: "", // Always a reference, defined in Refs below diff --git a/libs/testserver/permissions.go b/libs/testserver/permissions.go index 12483429af..5049f948ab 100644 --- a/libs/testserver/permissions.go +++ b/libs/testserver/permissions.go @@ -31,6 +31,7 @@ var requestObjectTypeToObjectType = map[string]string{ "vector-search-endpoints": "vector-search-endpoints", "apps": "apps", "database-instances": "database-instances", + "database-projects": "database-projects", "alertsv2": "alertv2", } From 6bd21670207809b3b4c4d516170b6481c4672780 Mon Sep 17 00:00:00 2001 From: Andrew Nester Date: Tue, 3 Mar 2026 10:42:16 +0100 Subject: [PATCH 2/3] fixed schema --- bundle/internal/schema/annotations.yml | 16 ++++++ .../validation/generated/required_fields.go | 3 +- bundle/schema/jsonschema.json | 49 +++++++++++++++++++ 3 files changed, 67 insertions(+), 1 deletion(-) diff --git a/bundle/internal/schema/annotations.yml b/bundle/internal/schema/annotations.yml index 137bb9bc57..8b4817bd4f 100644 --- a/bundle/internal/schema/annotations.yml +++ b/bundle/internal/schema/annotations.yml @@ -693,6 +693,19 @@ github.com/databricks/cli/bundle/config/resources.DatabaseInstancePermission: "user_name": "description": |- PLACEHOLDER +github.com/databricks/cli/bundle/config/resources.DatabaseProjectPermission: + "group_name": + "description": |- + PLACEHOLDER + "level": + "description": |- + PLACEHOLDER + "service_principal_name": + "description": |- + PLACEHOLDER + "user_name": + "description": |- + PLACEHOLDER github.com/databricks/cli/bundle/config/resources.ExternalLocation: "comment": "description": |- @@ -957,6 +970,9 @@ github.com/databricks/cli/bundle/config/resources.PostgresProject: "name": "description": |- PLACEHOLDER + "permissions": + "description": |- + PLACEHOLDER "pg_version": "description": |- PLACEHOLDER diff --git a/bundle/internal/validation/generated/required_fields.go b/bundle/internal/validation/generated/required_fields.go index ae59c9f046..99b6dc2890 100644 --- a/bundle/internal/validation/generated/required_fields.go +++ b/bundle/internal/validation/generated/required_fields.go @@ -219,7 +219,8 @@ var RequiredFields = map[string][]string{ "resources.postgres_endpoints.*": {"endpoint_type", "endpoint_id", "parent"}, "resources.postgres_endpoints.*.group": {"max", "min"}, - "resources.postgres_projects.*": {"project_id"}, + "resources.postgres_projects.*": {"project_id"}, + "resources.postgres_projects.*.permissions[*]": {"level"}, "resources.quality_monitors.*": {"assets_dir", "output_schema_name", "table_name"}, "resources.quality_monitors.*.custom_metrics[*]": {"definition", "input_columns", "name", "output_data_type", "type"}, diff --git a/bundle/schema/jsonschema.json b/bundle/schema/jsonschema.json index 6cff9a7f60..5d4c7b9b3a 100644 --- a/bundle/schema/jsonschema.json +++ b/bundle/schema/jsonschema.json @@ -906,6 +906,38 @@ } ] }, + "resources.DatabaseProjectPermission": { + "oneOf": [ + { + "type": "object", + "properties": { + "group_name": { + "$ref": "#/$defs/string" + }, + "level": { + "$ref": "#/$defs/github.com/databricks/cli/bundle/config/resources.DatabaseProjectPermissionLevel" + }, + "service_principal_name": { + "$ref": "#/$defs/string" + }, + "user_name": { + "$ref": "#/$defs/string" + } + }, + "additionalProperties": false, + "required": [ + "level" + ] + }, + { + "type": "string", + "pattern": "\\$\\{(var(\\.[a-zA-Z]+([-_]?[a-zA-Z0-9]+)*(\\[[0-9]+\\])*)+)\\}" + } + ] + }, + "resources.DatabaseProjectPermissionLevel": { + "type": "string" + }, "resources.ExternalLocation": { "oneOf": [ { @@ -1830,6 +1862,9 @@ "lifecycle": { "$ref": "#/$defs/github.com/databricks/cli/bundle/config/resources.Lifecycle" }, + "permissions": { + "$ref": "#/$defs/slice/github.com/databricks/cli/bundle/config/resources.DatabaseProjectPermission" + }, "pg_version": { "$ref": "#/$defs/int" }, @@ -11189,6 +11224,20 @@ } ] }, + "resources.DatabaseProjectPermission": { + "oneOf": [ + { + "type": "array", + "items": { + "$ref": "#/$defs/github.com/databricks/cli/bundle/config/resources.DatabaseProjectPermission" + } + }, + { + "type": "string", + "pattern": "\\$\\{(var(\\.[a-zA-Z]+([-_]?[a-zA-Z0-9]+)*(\\[[0-9]+\\])*)+)\\}" + } + ] + }, "resources.ExternalLocationGrant": { "oneOf": [ { From 61ee600691841f452be9850fc3689a13c9970b38 Mon Sep 17 00:00:00 2001 From: Andrew Nester Date: Tue, 3 Mar 2026 10:55:33 +0100 Subject: [PATCH 3/3] fixes --- acceptance/bundle/refschema/out.fields.txt | 13 +++++++++++++ .../bundle/resources/permissions/output.txt | 19 +++++++++++++++++++ .../schema/annotations_openapi_overrides.yml | 7 +++++++ bundle/schema/jsonschema.json | 14 +++++++++++++- 4 files changed, 52 insertions(+), 1 deletion(-) diff --git a/acceptance/bundle/refschema/out.fields.txt b/acceptance/bundle/refschema/out.fields.txt index 3ebaeaa628..f401945572 100644 --- a/acceptance/bundle/refschema/out.fields.txt +++ b/acceptance/bundle/refschema/out.fields.txt @@ -2627,6 +2627,12 @@ resources.postgres_projects.*.lifecycle resources.Lifecycle INPUT resources.postgres_projects.*.lifecycle.prevent_destroy bool INPUT resources.postgres_projects.*.modified_status string INPUT resources.postgres_projects.*.name string REMOTE +resources.postgres_projects.*.permissions []resources.DatabaseProjectPermission INPUT +resources.postgres_projects.*.permissions[*] resources.DatabaseProjectPermission INPUT +resources.postgres_projects.*.permissions[*].group_name string INPUT +resources.postgres_projects.*.permissions[*].level resources.DatabaseProjectPermissionLevel INPUT +resources.postgres_projects.*.permissions[*].service_principal_name string INPUT +resources.postgres_projects.*.permissions[*].user_name string INPUT resources.postgres_projects.*.pg_version int INPUT STATE resources.postgres_projects.*.project_id string INPUT STATE resources.postgres_projects.*.spec *postgres.ProjectSpec REMOTE @@ -2667,6 +2673,13 @@ resources.postgres_projects.*.status.synthetic_storage_size_bytes int64 REMOTE resources.postgres_projects.*.uid string REMOTE resources.postgres_projects.*.update_time *time.Time REMOTE resources.postgres_projects.*.url string INPUT +resources.postgres_projects.*.permissions.object_id string ALL +resources.postgres_projects.*.permissions.permissions []iam.AccessControlRequest ALL +resources.postgres_projects.*.permissions.permissions[*] iam.AccessControlRequest ALL +resources.postgres_projects.*.permissions.permissions[*].group_name string ALL +resources.postgres_projects.*.permissions.permissions[*].permission_level iam.PermissionLevel ALL +resources.postgres_projects.*.permissions.permissions[*].service_principal_name string ALL +resources.postgres_projects.*.permissions.permissions[*].user_name string ALL resources.quality_monitors.*.assets_dir string ALL resources.quality_monitors.*.baseline_table_name string ALL resources.quality_monitors.*.custom_metrics []catalog.MonitorMetric ALL diff --git a/acceptance/bundle/resources/permissions/output.txt b/acceptance/bundle/resources/permissions/output.txt index 7e3d1bdf4a..ab4953f6b5 100644 --- a/acceptance/bundle/resources/permissions/output.txt +++ b/acceptance/bundle/resources/permissions/output.txt @@ -331,6 +331,25 @@ MATCH pipelines/other_can_manage/out.requests.deploy.direct.json EXACT pipelines/other_can_manage/out.requests.destroy.direct.json EXACT pipelines/other_is_owner/out.requests.deploy.direct.json EXACT pipelines/other_is_owner/out.requests.destroy.direct.json +MATCH postgres_projects/current_can_manage/out.requests.deploy.direct.json +DIFF postgres_projects/current_can_manage/out.requests.destroy.direct.json +--- postgres_projects/current_can_manage/out.requests.destroy.direct.json ++++ postgres_projects/current_can_manage/out.requests.destroy.terraform.json +@@ -1 +1,14 @@ +-[]+[ ++ { ++ "body": { ++ "access_control_list": [ ++ { ++ "permission_level": "CAN_MANAGE", ++ "user_name": "[USERNAME]" ++ } ++ ] ++ }, ++ "method": "PUT", ++ "path": "/api/2.0/permissions/database-projects/test-project" ++ } ++] MATCH sql_warehouses/current_can_manage/out.requests.deploy.direct.json DIFF sql_warehouses/current_can_manage/out.requests.destroy.direct.json --- sql_warehouses/current_can_manage/out.requests.destroy.direct.json diff --git a/bundle/internal/schema/annotations_openapi_overrides.yml b/bundle/internal/schema/annotations_openapi_overrides.yml index 170519b6ca..c9eeaa13e1 100644 --- a/bundle/internal/schema/annotations_openapi_overrides.yml +++ b/bundle/internal/schema/annotations_openapi_overrides.yml @@ -260,6 +260,13 @@ github.com/databricks/cli/bundle/config/resources.DatabaseInstancePermissionLeve CAN_USE - |- CAN_MANAGE +github.com/databricks/cli/bundle/config/resources.DatabaseProjectPermissionLevel: + "_": + "enum": + - |- + CAN_USE + - |- + CAN_MANAGE github.com/databricks/cli/bundle/config/resources.ExternalLocationGrantPrivilege: "_": "description": |- diff --git a/bundle/schema/jsonschema.json b/bundle/schema/jsonschema.json index 5d4c7b9b3a..07df75a018 100644 --- a/bundle/schema/jsonschema.json +++ b/bundle/schema/jsonschema.json @@ -936,7 +936,19 @@ ] }, "resources.DatabaseProjectPermissionLevel": { - "type": "string" + "oneOf": [ + { + "type": "string", + "enum": [ + "CAN_USE", + "CAN_MANAGE" + ] + }, + { + "type": "string", + "pattern": "\\$\\{(var(\\.[a-zA-Z]+([-_]?[a-zA-Z0-9]+)*(\\[[0-9]+\\])*)+)\\}" + } + ] }, "resources.ExternalLocation": { "oneOf": [