Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
7589ebf
Report PII-free error templates in deploy telemetry
denik Aug 24, 2026
41edf7a
Drop redundant telemetry payload goldens from the two error-template …
denik Aug 24, 2026
32ccd26
Report error templates as dedicated fields instead of a generic strin…
denik Aug 24, 2026
6efae3b
Drop the "resources." prefix from a safe resource key
denik Aug 24, 2026
c95d7f7
Order the safe API descriptor status-first, like FormatAPIErrorSummary
denik Aug 24, 2026
2f0dca8
Let the CLI's own typed errors report their classification
denik Aug 24, 2026
6f5619c
Log migration telemetry from every migration acceptance test
denik Aug 24, 2026
747356a
Print migration telemetry from every migration test, one block per de…
denik Aug 24, 2026
a3d24ab
Narrow telemetry to migration errors, and cover the conversion failure
denik Aug 24, 2026
e36fec2
Keep the real error when the secret scope fixups fail during migration
denik Aug 24, 2026
5555ae5
Restore migration templates in two goldens after the rebase
denik Aug 25, 2026
08474a7
Drop a redundant test.toml from the conversion-failure test
denik Aug 25, 2026
270c9fb
Convert the resource key once per iteration, not at every error site
denik Aug 25, 2026
150026b
Cover four more migration paths, failing and not
denik Aug 25, 2026
7b7ec87
Report the first conversion warning in telemetry
denik Aug 25, 2026
71caf79
Rename the migration error metrics off "Template", and fix two broken…
denik Aug 25, 2026
c34b3b6
Mark the migrated-state defect with the Badness convention
denik Aug 25, 2026
c885b5c
Make the DABs-only field test reach the conversion, and drop the sent…
denik Aug 25, 2026
62d369a
Drive the DABs-only field test through bundle.engine, gaining telemetry
denik Aug 25, 2026
7220373
Expand table test cases to one field per line, and cover a %w with no…
denik Aug 25, 2026
3fded0c
Close five gaps found by an adversarial review
denik Aug 25, 2026
73c464d
Pin the wire names of the three saferr fields
denik Aug 25, 2026
79aba45
Cover the warning path end to end with a crafted terraform state
denik Aug 25, 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
bundle:
name: test-bundle

resources:
secret_scopes:
my_scope:
name: my-scope
permissions:
# An unknown level: SecretScopeFixups rejects it when it prepares the
# config for the direct engine, so the state conversion fails while the
# terraform deploy itself succeeds.
- level: BOGUS
user_name: someone@example.com

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@

=== Not opted in: the conversion failure is reported as a failed dry run
>>> DATABRICKS_BUNDLE_ENGINE=terraform [CLI] bundle deploy
Warning: invalid value "BOGUS" for enum field. Valid values are [READ WRITE MANAGE]
at resources.secret_scopes.my_scope.permissions[0].level

Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files...
Created secret_scopes.my_scope
Created secret_scopes.my_scope.permissions
Files: 4 uploaded, 0 deleted
Resources: 2 created, 0 changed, 0 deleted, 0 unchanged
Warn: post-deploy dry-run migration to direct: unknown permission level "BOGUS" for secret scope
Warn: The warnings above are from a dry-run migration to the direct deployment engine (https://docs.databricks.com/aws/en/dev-tools/bundles/direct).
Your deployment is not affected and works normally, but you may experience these issues when migrating to the direct deployment engine.
Please forward these warnings to dabs-feedback@databricks.com

>>> print_migration_telemetry
direct_drymigrate_success false
direct_drymigrate_warnings false
direct_migrate_saferr unknown permission level %q for secret scope

=== Opted in: the same failure stops the automatic migration
>>> DATABRICKS_BUNDLE_ENGINE=direct [CLI] bundle deploy
Warning: invalid value "BOGUS" for enum field. Valid values are [READ WRITE MANAGE]
at resources.secret_scopes.my_scope.permissions[0].level

Warn: Direct engine requested in DATABRICKS_BUNDLE_ENGINE environment variable but the existing state uses "terraform". Deploying on "terraform"; will attempt to migrate the state to the direct engine after this deploy.
Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files...
Files: 2 uploaded, 0 deleted
Resources: 0 created, 0 changed, 0 deleted, 2 unchanged
Warn: post-deploy dry-run migration to direct: unknown permission level "BOGUS" for secret scope
Warn: The warnings above are from a dry-run migration to the direct deployment engine (https://docs.databricks.com/aws/en/dev-tools/bundles/direct).
Your deployment is not affected and works normally, but you may experience these issues when migrating to the direct deployment engine.
Please forward these warnings to dabs-feedback@databricks.com
Warn: Direct engine was requested but the dry-run migration reported issues; automatic migration to the direct deployment engine is stopped. Address the issues above or run "databricks bundle deployment migrate" manually.

>>> print_migration_telemetry
direct_migrate_error true
direct_migrate_saferr unknown permission level %q for secret scope

=== State is still terraform, so nothing was migrated

>>> find .databricks/bundle -name resources.json -type f

>>> find .databricks/bundle -name terraform.tfstate* -type f
.databricks/bundle/default/terraform/terraform.tfstate
20 changes: 20 additions & 0 deletions acceptance/bundle/migrate/auto-migrate-conversion-failure/script
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export DATABRICKS_BUNDLE_ENGINE=

# An unknown permission level is only a warning for the terraform deploy, but
# SecretScopeFixups rejects it while preparing the config for the direct engine.
# That is a state conversion failure: no API call is involved, so unlike the
# commit failures it cannot be produced by injecting a fault.

title "Not opted in: the conversion failure is reported as a failed dry run"
trace DATABRICKS_BUNDLE_ENGINE=terraform $CLI bundle deploy
trace print_migration_telemetry
rm -f out.requests.txt

title "Opted in: the same failure stops the automatic migration"
trace DATABRICKS_BUNDLE_ENGINE=direct $CLI bundle deploy
trace print_migration_telemetry
rm -f out.requests.txt

title "State is still terraform, so nothing was migrated\n"
trace find .databricks/bundle -name "resources.json" -type f
trace find .databricks/bundle -name "terraform.tfstate*" -type f
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Warn: automatic migration to direct engine failed: pushing direct state to works

>>> print_migration_telemetry
direct_migrate_commit_error true
direct_migrate_commit_saferr pushing direct state to workspace: access denied [403 INJECTED]

=== Local state was NOT rewritten (still terraform)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Warn: automatic migration to direct engine failed: pushing direct state to works

>>> print_migration_telemetry
direct_migrate_commit_error true
direct_migrate_commit_saferr pushing direct state to workspace: deleting remote terraform state: %w [403 INJECTED]

=== Local state was NOT rewritten (still terraform)

Expand Down
24 changes: 24 additions & 0 deletions acceptance/bundle/migrate/reference-dabs-only-field/databricks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
bundle:
name: test-bundle

resources:
jobs:
src:
name: source
tasks:
- task_key: t
new_cluster: &cluster
spark_version: 15.4.x-scala2.12
node_type_id: Standard_DS3_v2
num_workers: 1
# autotermination_minutes has no Terraform equivalent for a job
# cluster, so it is absent from terraform.tfstate. Terraform never
# sees this reference either: the field is dropped on conversion.
autotermination_minutes: 20
dst:
name: dst
tasks:
- task_key: t
new_cluster:
<<: *cluster
autotermination_minutes: ${resources.jobs.src.tasks[0].new_cluster.autotermination_minutes}

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

59 changes: 59 additions & 0 deletions acceptance/bundle/migrate/reference-dabs-only-field/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@

=== Deploy on terraform: the dry run already reports the failure
>>> DATABRICKS_BUNDLE_ENGINE=terraform [CLI] bundle deploy
Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files...
Warning: unknown field: autotermination_minutes
at task[0].new_cluster
in databricks.yml:17:13

Warning: unknown field: autotermination_minutes
at task[0].new_cluster
in databricks.yml:17:13

Created jobs.dst
Created jobs.src
Files: 4 uploaded, 0 deleted
Resources: 2 created, 0 changed, 0 deleted, 0 unchanged
Warn: post-deploy dry-run migration to direct: resources.jobs.dst: cannot resolve field "tasks[0].new_cluster.autotermination_minutes" (template "${resources.jobs.src.tasks[0].new_cluster.autotermination_minutes}"): jobs.dst field tasks[0].new_cluster.autotermination_minutes: method A: jobs: "tasks[0].new_cluster.autotermination_minutes" is a DABs-only field with no Terraform equivalent; method B: cannot look up "resources.jobs.src.tasks[0].new_cluster.autotermination_minutes": jobs: "tasks[0].new_cluster.autotermination_minutes" is a DABs-only field with no Terraform equivalent
Warn: The warnings above are from a dry-run migration to the direct deployment engine (https://docs.databricks.com/aws/en/dev-tools/bundles/direct).
Your deployment is not affected and works normally, but you may experience these issues when migrating to the direct deployment engine.
Please forward these warnings to dabs-feedback@databricks.com

>>> print_migration_telemetry
direct_drymigrate_success false
direct_drymigrate_warnings false
direct_migrate_saferr jobs.*: cannot resolve field %q (template %q): jobs.%s field %s: method A: %w; method B: cannot look up %q: %w

>>> update_file.py databricks.yml name: test-bundle name: test-bundle
engine: direct

=== Opt in via config: the same failure stops the automatic migration
>>> [CLI] bundle deploy
Warn: Direct engine requested in bundle.engine setting at [TEST_TMP_DIR]/databricks.yml:3:11 but the existing state uses "terraform". Deploying on "terraform"; will attempt to migrate the state to the direct engine after this deploy.
Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files...
Warning: unknown field: autotermination_minutes
at task[0].new_cluster
in databricks.yml:18:13

Warning: unknown field: autotermination_minutes
at task[0].new_cluster
in databricks.yml:18:13

Files: 3 uploaded, 0 deleted
Resources: 0 created, 0 changed, 0 deleted, 2 unchanged
Warn: post-deploy dry-run migration to direct: resources.jobs.dst: cannot resolve field "tasks[0].new_cluster.autotermination_minutes" (template "${resources.jobs.src.tasks[0].new_cluster.autotermination_minutes}"): jobs.dst field tasks[0].new_cluster.autotermination_minutes: method A: jobs: "tasks[0].new_cluster.autotermination_minutes" is a DABs-only field with no Terraform equivalent; method B: cannot look up "resources.jobs.src.tasks[0].new_cluster.autotermination_minutes": jobs: "tasks[0].new_cluster.autotermination_minutes" is a DABs-only field with no Terraform equivalent
Warn: The warnings above are from a dry-run migration to the direct deployment engine (https://docs.databricks.com/aws/en/dev-tools/bundles/direct).
Your deployment is not affected and works normally, but you may experience these issues when migrating to the direct deployment engine.
Please forward these warnings to dabs-feedback@databricks.com
Warn: Direct engine was requested but the dry-run migration reported issues; automatic migration to the direct deployment engine is stopped. Address the issues above or run "databricks bundle deployment migrate" manually.

>>> print_migration_telemetry
direct_migrate_error true
direct_migrate_saferr jobs.*: cannot resolve field %q (template %q): jobs.%s field %s: method A: %w; method B: cannot look up %q: %w

=== State is still terraform, so nothing was migrated

>>> find .databricks/bundle -name resources.json -type f

>>> find .databricks/bundle -name terraform.tfstate* -type f
.databricks/bundle/default/terraform/terraform.tfstate
24 changes: 24 additions & 0 deletions acceptance/bundle/migrate/reference-dabs-only-field/script
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export DATABRICKS_BUNDLE_ENGINE=

# A DABs-only field pointing at another resource's DABs-only field. Neither is in
# terraform.tfstate, so both of the conversion's resolution methods fail.
#
# The deploy is unaffected: the field has no Terraform equivalent, so it is
# dropped on conversion and Terraform never sees the reference inside it. That is
# what lets the conversion, rather than the deploy, be the thing that fails.
title "Deploy on terraform: the dry run already reports the failure"
trace DATABRICKS_BUNDLE_ENGINE=terraform $CLI bundle deploy
trace print_migration_telemetry
rm -f out.requests.txt

trace update_file.py databricks.yml "name: test-bundle" "name: test-bundle
engine: direct"

title "Opt in via config: the same failure stops the automatic migration"
trace $CLI bundle deploy
trace print_migration_telemetry
rm -f out.requests.txt

title "State is still terraform, so nothing was migrated\n"
trace find .databricks/bundle -name "resources.json" -type f
trace find .databricks/bundle -name "terraform.tfstate*" -type f
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
placeholder
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
bundle:
name: test-bundle

resources:
#catalogs: {my_catalog: {name: my-catalog}}
apps:
my_app:
name: my-app
source_code_path: ./app
config:
env:
- name: CATALOG
value: plain

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

>>> DATABRICKS_BUNDLE_ENGINE=terraform [CLI] bundle deploy
Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files...
Created apps.my_app
Files: 5 uploaded, 0 deleted
Resources: 1 created, 0 changed, 0 deleted, 0 unchanged

>>> update_file.py databricks.yml #catalogs catalogs

>>> update_file.py databricks.yml value: plain value: ${resources.catalogs.my_catalog.name}

=== Direct requested: the catalog is skipped by terraform and the migration still succeeds
>>> DATABRICKS_BUNDLE_ENGINE=direct [CLI] bundle deploy
Warn: Direct engine requested in DATABRICKS_BUNDLE_ENGINE environment variable but the existing state uses "terraform". Deploying on "terraform"; will attempt to migrate the state to the direct engine after this deploy.
Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files...
Files: 3 uploaded, 0 deleted
Resources: 0 created, 0 changed, 0 deleted, 2 unchanged
Migrating state to direct deployment engine (opted in via DATABRICKS_BUNDLE_ENGINE environment variable)...
Migrated 1 resource to direct deployment engine.

>>> print_migration_telemetry
direct_migrated_via_env true
18 changes: 18 additions & 0 deletions acceptance/bundle/migrate/reference-direct-only-resource/script
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export DATABRICKS_BUNDLE_ENGINE=

# Recording that a reference into a direct-only resource type does not break the
# migration. Terraform cannot deploy catalogs at all, so the reference resolves
# to nothing in terraform.tfstate — but apps.config is inline app.yaml rather
# than an API field, so ExtractReferences drops the reference before it is ever
# resolved. See bundle/direct/bundle_plan.go: refs are kept only for fields that
# exist in the state type.
trace DATABRICKS_BUNDLE_ENGINE=terraform $CLI bundle deploy
rm -f out.requests.txt

trace update_file.py databricks.yml "#catalogs" "catalogs"
trace update_file.py databricks.yml "value: plain" 'value: ${resources.catalogs.my_catalog.name}'

title "Direct requested: the catalog is skipped by terraform and the migration still succeeds"
trace DATABRICKS_BUNDLE_ENGINE=direct $CLI bundle deploy
trace print_migration_telemetry
rm -f out.requests.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
bundle:
name: test-bundle

# Enabled by the script before the second deploy, so the first one leaves a state
# the two resolution methods agree on.
#experimental: {scripts: {postdeploy: "python3 drift_stored_name.py"}}

resources:
jobs:
src:
name: source
dst:
# Method A reads dst's own stored name; Method B evaluates this template
# against src's. The post-deploy script makes those two differ.
name: ${resources.jobs.src.name}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"""Make the two resolution methods disagree about dst's name.

Runs as a post-deploy script, so the deploy applies against a state it wrote and
only the migration sees the drift. Editing the stored value is the point: a real
deploy stores the same string on both sides of a name-to-name reference, so the
disagreement the conversion warns about cannot be produced by config alone.
"""

import json
import pathlib

p = pathlib.Path(".databricks/bundle/default/terraform/terraform.tfstate")
state = json.loads(p.read_text())

for resource in state["resources"]:
if resource.get("type") == "databricks_job" and resource.get("name") == "dst":
resource["instances"][0]["attributes"]["name"] = "source-drifted"

p.write_text(json.dumps(state, indent=2))

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

38 changes: 38 additions & 0 deletions acceptance/bundle/migrate/reference-methods-disagree/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@

=== Deploy on terraform: the methods agree, so the dry run is clean
>>> DATABRICKS_BUNDLE_ENGINE=terraform [CLI] bundle deploy
Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files...
Created jobs.dst
Created jobs.src
Files: 5 uploaded, 0 deleted
Resources: 2 created, 0 changed, 0 deleted, 0 unchanged

>>> print_migration_telemetry
direct_drymigrate_success true
direct_drymigrate_warnings false

>>> update_file.py databricks.yml #experimental experimental

=== Opt in: the methods disagree, which stops the migration without an error
>>> DATABRICKS_BUNDLE_ENGINE=direct [CLI] bundle deploy
Warn: Direct engine requested in DATABRICKS_BUNDLE_ENGINE environment variable but the existing state uses "terraform". Deploying on "terraform"; will attempt to migrate the state to the direct engine after this deploy.
Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files...
Files: 3 uploaded, 0 deleted
Resources: 0 created, 0 changed, 0 deleted, 2 unchanged
Executing 'postdeploy' script
Warn: post-deploy dry-run migration to direct: resource jobs.dst field name: method A value "source-drifted" and method B value "source" disagree; using longer (method A)
Warn: The warnings above are from a dry-run migration to the direct deployment engine (https://docs.databricks.com/aws/en/dev-tools/bundles/direct).
Your deployment is not affected and works normally, but you may experience these issues when migrating to the direct deployment engine.
Please forward these warnings to dabs-feedback@databricks.com
Warn: Direct engine was requested but the dry-run migration reported issues; automatic migration to the direct deployment engine is stopped. Address the issues above or run "databricks bundle deployment migrate" manually.

>>> print_migration_telemetry
direct_migrate_warnings true
direct_migrate_warning_saferr jobs.%s field %q: method A and method B disagree

=== State is still terraform, so nothing was migrated

>>> find .databricks/bundle -name resources.json -type f

>>> find .databricks/bundle -name terraform.tfstate* -type f
.databricks/bundle/default/terraform/terraform.tfstate
17 changes: 17 additions & 0 deletions acceptance/bundle/migrate/reference-methods-disagree/script
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export DATABRICKS_BUNDLE_ENGINE=

title "Deploy on terraform: the methods agree, so the dry run is clean"
trace DATABRICKS_BUNDLE_ENGINE=terraform $CLI bundle deploy
trace print_migration_telemetry
rm -f out.requests.txt

trace update_file.py databricks.yml "#experimental" "experimental"

title "Opt in: the methods disagree, which stops the migration without an error"
trace DATABRICKS_BUNDLE_ENGINE=direct $CLI bundle deploy
trace print_migration_telemetry
rm -f out.requests.txt

title "State is still terraform, so nothing was migrated\n"
trace find .databricks/bundle -name "resources.json" -type f
trace find .databricks/bundle -name "terraform.tfstate*" -type f
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
bundle:
name: test-bundle

resources:
jobs:
src:
name: source
dst:
name: dst
# Terraform's own reference syntax, which users copy from Terraform docs or
# carry over from a raw Terraform project. DABs does not resolve it, so it
# reaches Terraform verbatim and Terraform resolves it.
description: ${databricks_job.src.id}

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

Loading
Loading