Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
4b5881a
Add implementation plan for __EMBED__ convention in struct walkers
denik Mar 10, 2026
d93cbee
Add EmbedTagName constant and IsEmbed() method to structtag
denik Mar 10, 2026
7397d52
Support __EMBED__ tag in structwalk.Walk
denik Mar 10, 2026
e370a67
Support __EMBED__ tag in structwalk.WalkType
denik Mar 10, 2026
5c6d07e
Support __EMBED__ tag in structaccess.Get
denik Mar 10, 2026
245e651
Support __EMBED__ tag in structaccess.Set
denik Mar 10, 2026
a72a346
Support __EMBED__ tag in structaccess.ValidatePath
denik Mar 10, 2026
5af8aad
Support __EMBED__ tag in structdiff.GetStructDiff
denik Mar 10, 2026
4bbfa0b
Use __EMBED__ tag on PermissionsState.Permissions
denik Mar 10, 2026
b548dad
Enable direct engine for job_permissions acceptance test
denik Mar 10, 2026
fa2c246
Regenerate out.test.toml for job_permissions test
denik Mar 10, 2026
f9a9504
Add custom JSON marshaling for PermissionsState and regenerate outputs
denik Mar 10, 2026
958958b
add REQUEST / RESPOSNE
denik Mar 10, 2026
7e13ad8
move into TASKS
denik Mar 10, 2026
2342268
Add task 002 and claude log
denik Mar 10, 2026
793ea25
Add plan for task 002: refine __EMBED__ convention
denik Mar 10, 2026
b3053a9
Switch embed detection from json tag to field name
denik Mar 10, 2026
336982f
Rename Permissions to EmbeddedSlice, remove custom JSON marshaling
denik Mar 10, 2026
217ba29
Fix formatting after pre-commit hook
denik Mar 10, 2026
9f3b7f3
Fix trailing whitespace in TASKS/001.md
denik Mar 10, 2026
f306233
Add status for task 002
denik Mar 10, 2026
89e3948
Add PR title and description
denik Mar 10, 2026
da5b32a
Update PR title and description
denik Mar 11, 2026
a7d9751
Add changelog entry for permissions state path fix
denik Mar 11, 2026
00901f4
Add PR link to changelog entry
denik Mar 11, 2026
5553a81
clean up TASKS
denik Mar 11, 2026
7ddad7d
rename field to _
denik Mar 11, 2026
650dad6
update after rebase
denik Mar 11, 2026
d1e2cfd
Remove duplicate changelog entry
denik Mar 11, 2026
1a58675
Move EmbeddedSliceFieldName from structtag to structaccess
denik Mar 11, 2026
d8c7a0b
Revert "clean up TASKS"
denik Mar 11, 2026
8c270a4
Add task 004: acceptance tests for permission references
denik Mar 11, 2026
d5e814d
Add plan for task 004: acceptance tests for permission references
denik Mar 11, 2026
379786c
Fix reference resolution for permission sub-resources
denik Mar 11, 2026
f297b44
Add acceptance test for permission reference resolution
denik Mar 11, 2026
3a43022
Fix trailing whitespace in TASKS/004.md
denik Mar 11, 2026
9259dbc
Simplify permission_ref test: plan + deploy without request recording
denik Mar 11, 2026
a1d1e8d
Update status and PR description for task 004
denik Mar 11, 2026
16fd0e0
Add task 005: use bundle config Permission type in PermissionsState
denik Mar 11, 2026
53709e9
Add plan for task 005: use Permission type in PermissionsState
denik Mar 11, 2026
3df15e7
Use resources.Permission in PermissionsState instead of iam.AccessCon…
denik Mar 11, 2026
7a0b5a0
Update refschema and fix exhaustruct lint for Permission type change
denik Mar 11, 2026
cf8b5ee
Update acceptance test outputs: permission_level -> level in direct e…
denik Mar 11, 2026
4835485
Add task 005 status and task 006
denik Mar 11, 2026
5ebd2da
Add plan for task 006: permission_level → level state migration
denik Mar 11, 2026
5386764
Add permission_level → level migration for backward-compatible state …
denik Mar 11, 2026
efa6314
Update refschema output for StatePermission type
denik Mar 11, 2026
8878b99
Add acceptance test for permission_level → level state migration
denik Mar 11, 2026
b7995f6
Fix exhaustruct lint for StatePermission
denik Mar 11, 2026
57ec969
Update task 006 status and PR description
denik Mar 11, 2026
50abdfc
Add task 007: state migration for permissions
denik Mar 12, 2026
0626cf8
Add plan for task 007: state migration system
denik Mar 12, 2026
7c2152a
Add state migration system and move permissions migration to dstate/m…
denik Mar 12, 2026
2deedd5
Update migration test to use old v1 state format with permissions key
denik Mar 12, 2026
930d650
Update acceptance test output for state version 2 migration
denik Mar 12, 2026
c02c2c0
Update generated output: remove permission_level from StatePermission
denik Mar 12, 2026
5d14003
Handle state_version 0 (absent field) as version 1 in migration
denik Mar 12, 2026
3da53d9
Update acceptance test outputs for state_version 2
denik Mar 12, 2026
c7d2f09
Update task 007 status and PR description
denik Mar 12, 2026
b92b8b2
clean up
denik Mar 12, 2026
d0a4d17
Move embedded state fixture to separate file in permission_level_migr…
denik Mar 13, 2026
6fa5209
update cloud tests
denik Mar 13, 2026
a2ce9ce
clean up TASKS
denik Mar 13, 2026
d6f48db
Reuse dresources.PermissionsState in dstate migration instead of loca…
denik Mar 13, 2026
e96c01a
Add job_permission_ref invariant test; separate stderr in plan commands
denik Mar 13, 2026
47ce393
fix out
denik Mar 13, 2026
5d9a72a
Exclude job_permission_ref from migrate invariant test
denik Mar 13, 2026
3807946
Add job_cross_resource_ref invariant test; improve migrate exclusion …
denik Mar 13, 2026
7a1771a
update out.test.toml
denik Mar 13, 2026
c3f0b11
Add continuity invariant test for state migration from v0.293.0
denik Mar 13, 2026
557c9be
Replace continuity test with continue_293 that deploys with v0.293.0 …
denik Mar 13, 2026
38f0b94
Exclude permission ref configs from cloud runs in no_drift test
denik Mar 13, 2026
67b41b9
Use built-in groups (users, admins) in permission ref invariant configs
denik Mar 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NEXT_CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
### CLI

### Bundles
* direct: Fix permissions state path to match input config schema ([#4703](https://github.com/databricks/cli/pull/4703))

### Dependency updates

Expand Down
6 changes: 6 additions & 0 deletions acceptance/acceptance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,12 @@ func testAccept(t *testing.T, inprocessMode bool, singleTest string) int {
t.Setenv("CLI", execPath)
repls.SetPath(execPath, "[CLI]")

if !inprocessMode {
cli293Path := DownloadCLI(t, buildDir, "0.293.0")
t.Setenv("CLI_293", cli293Path)
repls.SetPath(cli293Path, "[CLI_293]")
}

paths := []string{
// Make helper scripts available
filepath.Join(cwd, "bin"),
Expand Down
2 changes: 1 addition & 1 deletion acceptance/bundle/apps/job_permissions/out.test.toml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 1 addition & 7 deletions acceptance/bundle/apps/job_permissions/test.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
# Direct engine error: cannot plan resources.jobs.my_job.permissions: cannot update
# [0].service_principal_name: failed to navigate to parent [0]: [0]: cannot index struct.
# This is a bug in structaccess.Set() where it fails to index into a struct when
# setting permissions with service_principal_name.
# See https://github.com/databricks/cli/pull/4644
Badness = "Direct engine fails to plan permissions with service_principal_name on jobs"
Cloud = true
RecordRequests = false

[EnvMatrix]
DATABRICKS_BUNDLE_ENGINE = ["terraform"]
DATABRICKS_BUNDLE_ENGINE = ["terraform", "direct"]
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"state_version": 1,
"state_version": 2,
"cli_version": "[DEV_VERSION]",
"lineage": "[UUID]",
"serial": 2,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
bundle:
name: test-bundle-$UNIQUE_NAME

resources:
jobs:
# job_src defines permissions and a tag value used as references by other resources
job_src:
name: test-job-src-$UNIQUE_NAME
tags:
perm_group: users
permissions:
- level: CAN_VIEW
group_name: users

# job_perm_ref uses permission fields from job_src as its permission values
job_perm_ref:
name: test-job-perm-ref-$UNIQUE_NAME
permissions:
- level: ${resources.jobs.job_src.permissions[0].level}
group_name: ${resources.jobs.job_src.permissions[0].group_name}

# job_tag_ref uses a job tag from job_src as a permission group_name
job_tag_ref:
name: test-job-tag-ref-$UNIQUE_NAME
permissions:
- level: CAN_VIEW
group_name: ${resources.jobs.job_src.tags.perm_group}
21 changes: 21 additions & 0 deletions acceptance/bundle/invariant/configs/job_permission_ref.yml.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
bundle:
name: test-bundle-$UNIQUE_NAME

resources:
jobs:
job_b:
name: test-job-b-$UNIQUE_NAME
permissions:
- level: CAN_VIEW
group_name: users
- level: CAN_MANAGE
group_name: admins

job_a:
name: test-job-a-$UNIQUE_NAME
permissions:
# Reference level and group_name from job_b by index
- level: ${resources.jobs.job_b.permissions[0].level}
group_name: ${resources.jobs.job_b.permissions[0].group_name}
- level: ${resources.jobs.job_b.permissions[1].level}
group_name: ${resources.jobs.job_b.permissions[1].group_name}
7 changes: 7 additions & 0 deletions acceptance/bundle/invariant/continue_293/out.test.toml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions acceptance/bundle/invariant/continue_293/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
INPUT_CONFIG_OK
40 changes: 40 additions & 0 deletions acceptance/bundle/invariant/continue_293/script
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Invariant to test: current CLI can deploy on top of state produced by v0.293.0

cp -r "$TESTDIR/../data/." . &> LOG.cp

INIT_SCRIPT="$TESTDIR/../configs/$INPUT_CONFIG-init.sh"
if [ -f "$INIT_SCRIPT" ]; then
source "$INIT_SCRIPT" &> LOG.init
fi

envsubst < "$TESTDIR/../configs/$INPUT_CONFIG" > databricks.yml

cleanup() {
trace $CLI bundle destroy --auto-approve &> LOG.destroy
cat LOG.destroy | contains.py '!panic' '!internal error' > /dev/null

CLEANUP_SCRIPT="$TESTDIR/../configs/$INPUT_CONFIG-cleanup.sh"
if [ -f "$CLEANUP_SCRIPT" ]; then
source "$CLEANUP_SCRIPT" &> LOG.cleanup
fi
}

trap cleanup EXIT

# Deploy with old CLI to produce v0.293.0 state
trace $CLI_293 bundle deploy &> LOG.deploy.293
cat LOG.deploy.293 | contains.py '!panic' '!internal error' > /dev/null

echo INPUT_CONFIG_OK

# Deploy with current CLI on top of old state
trace $CLI bundle deploy &> LOG.deploy
cat LOG.deploy | contains.py '!panic' '!internal error' > /dev/null

# Verify no drift after current CLI deploy
$CLI bundle plan -o json > LOG.planjson 2>LOG.planjson.err
cat LOG.planjson.err | contains.py '!panic' '!internal error' > /dev/null
verify_no_drift.py LOG.planjson

$CLI bundle plan 2>LOG.plan.err | contains.py '!panic' '!internal error' 'Plan: 0 to add, 0 to change, 0 to delete' > LOG.plan
cat LOG.plan.err | contains.py '!panic' '!internal error' > /dev/null
5 changes: 5 additions & 0 deletions acceptance/bundle/invariant/continue_293/test.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Cloud = false

# Cross-resource permission references don't work in terraform mode.
EnvMatrixExclude.no_permission_ref = ["INPUT_CONFIG=job_permission_ref.yml.tmpl"]
EnvMatrixExclude.no_cross_resource_ref = ["INPUT_CONFIG=job_cross_resource_ref.yml.tmpl"]
2 changes: 1 addition & 1 deletion acceptance/bundle/invariant/migrate/out.test.toml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions acceptance/bundle/invariant/migrate/script
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@ trace $CLI bundle deployment migrate &> LOG.migrate

cat LOG.migrate | contains.py '!panic:' '!internal error' > /dev/null

$CLI bundle plan -o json &> plan.json
cat plan.json | contains.py '!panic:' '!internal error' > /dev/null
$CLI bundle plan -o json > plan.json 2>plan.json.err
cat plan.json.err | contains.py '!panic:' '!internal error' > /dev/null
verify_no_drift.py plan.json
9 changes: 9 additions & 0 deletions acceptance/bundle/invariant/migrate/test.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,12 @@ EnvMatrixExclude.no_external_location = ["INPUT_CONFIG=external_location.yml.tmp

# Unexpected action='create' for resources.secret_scopes.foo.permissions
EnvMatrixExclude.no_secret_scope = ["INPUT_CONFIG=secret_scope.yml.tmpl"]

# Cross-resource permission references (e.g. ${resources.jobs.job_b.permissions[0].level})
# don't work in terraform mode: the terraform interpolator converts the path to
# ${databricks_job.job_b.permissions[0].level}, but Terraform's databricks_job resource
# does not expose permissions as output attributes (permissions are a separate
# databricks_permissions resource in terraform), so the literal unresolved string
# ends up as the permission level value.
EnvMatrixExclude.no_permission_ref = ["INPUT_CONFIG=job_permission_ref.yml.tmpl"]
EnvMatrixExclude.no_cross_resource_ref = ["INPUT_CONFIG=job_cross_resource_ref.yml.tmpl"]
2 changes: 1 addition & 1 deletion acceptance/bundle/invariant/no_drift/out.test.toml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions acceptance/bundle/invariant/no_drift/script
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ echo INPUT_CONFIG_OK

# Check both text and JSON plan for no changes
# Note, expect that there maybe more than one resource unchanged
$CLI bundle plan -o json &> LOG.planjson
cat LOG.planjson | contains.py '!panic' '!internal error' > /dev/null
$CLI bundle plan -o json > LOG.planjson 2>LOG.planjson.err
cat LOG.planjson.err | contains.py '!panic' '!internal error' > /dev/null
verify_no_drift.py LOG.planjson

$CLI bundle plan | contains.py '!panic' '!internal error' 'Plan: 0 to add, 0 to change, 0 to delete' > LOG.plan
$CLI bundle plan 2>LOG.plan.err | contains.py '!panic' '!internal error' 'Plan: 0 to add, 0 to change, 0 to delete' > LOG.plan
cat LOG.plan.err | contains.py '!panic' '!internal error' > /dev/null
3 changes: 3 additions & 0 deletions acceptance/bundle/invariant/test.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Ignore = [
"plan.json",
"*.py",
"*.json",
"*.err",
"app",
]

Expand All @@ -32,6 +33,8 @@ EnvMatrix.INPUT_CONFIG = [
"job.yml.tmpl",
"job_pydabs_10_tasks.yml.tmpl",
"job_pydabs_1000_tasks.yml.tmpl",
"job_cross_resource_ref.yml.tmpl",
"job_permission_ref.yml.tmpl",
"job_with_task.yml.tmpl",
"model.yml.tmpl",
"model_serving_endpoint.yml.tmpl",
Expand Down
2 changes: 1 addition & 1 deletion acceptance/bundle/migrate/basic/out.new_state.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"state_version": 1,
"state_version": 2,
"cli_version": "[DEV_VERSION]",
"lineage": "[UUID]",
"serial": 6,
Expand Down
2 changes: 1 addition & 1 deletion acceptance/bundle/migrate/dashboards/out.new_state.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"state_version": 1,
"state_version": 2,
"cli_version": "[DEV_VERSION]",
"lineage": "[UUID]",
"serial": 3,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"state_version": 1,
"state_version": 2,
"cli_version": "[DEV_VERSION]",
"lineage": "[UUID]",
"serial": 5,
Expand Down
2 changes: 1 addition & 1 deletion acceptance/bundle/migrate/grants/out.new_state.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"state_version": 1,
"state_version": 2,
"cli_version": "[DEV_VERSION]",
"lineage": "[UUID]",
"serial": 9,
Expand Down
14 changes: 7 additions & 7 deletions acceptance/bundle/migrate/permissions/out.new_state.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"state_version": 1,
"state_version": 2,
"cli_version": "[DEV_VERSION]",
"lineage": "[UUID]",
"serial": 7,
Expand Down Expand Up @@ -32,13 +32,13 @@
"__id__": "/jobs/[NUMID]",
"state": {
"object_id": "/jobs/[NUMID]",
"permissions": [
"_": [
{
"permission_level": "CAN_VIEW",
"level": "CAN_VIEW",
"user_name": "viewer@databricks.com"
},
{
"permission_level": "IS_OWNER",
"level": "IS_OWNER",
"user_name": "[USERNAME]"
}
]
Expand Down Expand Up @@ -73,13 +73,13 @@
"__id__": "/pipelines/[UUID]",
"state": {
"object_id": "/pipelines/[UUID]",
"permissions": [
"_": [
{
"permission_level": "CAN_MANAGE",
"level": "CAN_MANAGE",
"user_name": "manager@databricks.com"
},
{
"permission_level": "IS_OWNER",
"level": "IS_OWNER",
"user_name": "[USERNAME]"
}
]
Expand Down
10 changes: 5 additions & 5 deletions acceptance/bundle/migrate/runas/out.new_state.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"state_version": 1,
"state_version": 2,
"cli_version": "[DEV_VERSION]",
"lineage": "[UUID]",
"serial": 5,
Expand Down Expand Up @@ -33,13 +33,13 @@
"__id__": "/pipelines/[UUID]",
"state": {
"object_id": "/pipelines/[UUID]",
"permissions": [
"_": [
{
"group_name": "users",
"permission_level": "CAN_VIEW"
"level": "CAN_VIEW",
"group_name": "users"
},
{
"permission_level": "IS_OWNER",
"level": "IS_OWNER",
"user_name": "[USERNAME]"
}
]
Expand Down
8 changes: 4 additions & 4 deletions acceptance/bundle/migrate/runas/out.plan.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@
"action": "skip",
"remote_state": {
"object_id": "/pipelines/[UUID]",
"permissions": [
"_": [
{
"group_name": "users",
"permission_level": "CAN_VIEW"
"level": "CAN_VIEW",
"group_name": "users"
},
{
"permission_level": "IS_OWNER",
"level": "IS_OWNER",
"user_name": "[USERNAME]"
}
]
Expand Down
Loading
Loading