diff --git a/acceptance/bundle/invariant/configs/empty.yml.tmpl b/acceptance/bundle/invariant/configs/empty.yml.tmpl new file mode 100644 index 0000000000..244a11badf --- /dev/null +++ b/acceptance/bundle/invariant/configs/empty.yml.tmpl @@ -0,0 +1,2 @@ +bundle: + name: test-bundle-$UNIQUE_NAME diff --git a/acceptance/bundle/invariant/continue_293/out.test.toml b/acceptance/bundle/invariant/continue_293/out.test.toml index 6e9c780939..3d8ba42f1c 100644 --- a/acceptance/bundle/invariant/continue_293/out.test.toml +++ b/acceptance/bundle/invariant/continue_293/out.test.toml @@ -15,6 +15,7 @@ EnvMatrix.INPUT_CONFIG = [ "database_catalog.yml.tmpl", "database_instance.yml.tmpl", "database_instance_with_permissions.yml.tmpl", + "empty.yml.tmpl", "experiment.yml.tmpl", "external_location.yml.tmpl", "job.yml.tmpl", diff --git a/acceptance/bundle/invariant/delete/out.test.toml b/acceptance/bundle/invariant/delete/out.test.toml new file mode 100644 index 0000000000..33c84b67de --- /dev/null +++ b/acceptance/bundle/invariant/delete/out.test.toml @@ -0,0 +1,61 @@ +Local = true +Cloud = true +RequiresUnityCatalog = true +EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"] +EnvMatrix.INPUT_CONFIG = [ + "alert.yml.tmpl", + "app.yml.tmpl", + "catalog.yml.tmpl", + "cluster.yml.tmpl", + "cluster_apply_policy_default_values.yml.tmpl", + "dashboard.yml.tmpl", + "job_apply_policy_default_values_job_cluster.yml.tmpl", + "job_apply_policy_default_values_task_cluster.yml.tmpl", + "job_apply_policy_default_values_for_each_task.yml.tmpl", + "database_catalog.yml.tmpl", + "database_instance.yml.tmpl", + "database_instance_with_permissions.yml.tmpl", + "empty.yml.tmpl", + "experiment.yml.tmpl", + "external_location.yml.tmpl", + "genie_space.yml.tmpl", + "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_run_job_ref.yml.tmpl", + "job_with_depends_on.yml.tmpl", + "job_with_permissions.yml.tmpl", + "job_with_task.yml.tmpl", + "model.yml.tmpl", + "model_with_permissions.yml.tmpl", + "model_serving_endpoint.yml.tmpl", + "model_serving_endpoint_with_permissions.yml.tmpl", + "pipeline.yml.tmpl", + "pipeline_apply_policy_default_values.yml.tmpl", + "pipeline_config_dots.yml.tmpl", + "postgres_branch.yml.tmpl", + "postgres_catalog.yml.tmpl", + "postgres_database.yml.tmpl", + "postgres_endpoint.yml.tmpl", + "postgres_project.yml.tmpl", + "postgres_role.yml.tmpl", + "postgres_synced_table.yml.tmpl", + "registered_model.yml.tmpl", + "schema.yml.tmpl", + "schema_grant_ref.yml.tmpl", + "schema_uppercase_name.yml.tmpl", + "schema_with_grants.yml.tmpl", + "secret_scope.yml.tmpl", + "secret_scope_default_backend_type.yml.tmpl", + "secret_scope_with_permissions.yml.tmpl", + "sql_warehouse.yml.tmpl", + "synced_database_table.yml.tmpl", + "vector_search_endpoint.yml.tmpl", + "vector_search_index.yml.tmpl", + "volume.yml.tmpl", + "volume_external.yml.tmpl", + "volume_uppercase_name.yml.tmpl" +] +EnvMatrix.READPLAN = ["", "1"] diff --git a/acceptance/bundle/invariant/delete/output.txt b/acceptance/bundle/invariant/delete/output.txt new file mode 100644 index 0000000000..7a28cb73a5 --- /dev/null +++ b/acceptance/bundle/invariant/delete/output.txt @@ -0,0 +1 @@ +INPUT_CONFIG_OK diff --git a/acceptance/bundle/invariant/delete/script b/acceptance/bundle/invariant/delete/script new file mode 100644 index 0000000000..60c465ec3b --- /dev/null +++ b/acceptance/bundle/invariant/delete/script @@ -0,0 +1,66 @@ +# Invariant to test: deleting all resources from a deployed bundle leaves an empty plan and summary +# Additional checks: no internal errors / panics in validate/plan/deploy/destroy + +# Copy data files to test directory +cp -r "$TESTDIR/../data/." . &> LOG.cp + +# Run init script if present +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 + +cp databricks.yml LOG.config + +# We redirect output rather than record it because some configs that are being tested may produce warnings +trace $CLI bundle validate &> LOG.validate +cat LOG.validate | contains.py '!panic' '!internal error' > /dev/null + +cleanup() { + trace $CLI bundle destroy --auto-approve &> LOG.destroy + cat LOG.destroy | contains.py '!panic' '!internal error' > /dev/null + + # Run cleanup script if present + CLEANUP_SCRIPT="$TESTDIR/../configs/$INPUT_CONFIG-cleanup.sh" + if [ -f "$CLEANUP_SCRIPT" ]; then + source "$CLEANUP_SCRIPT" &> LOG.cleanup + fi +} + +trap cleanup EXIT + +# Deploy the config with all its resources +trace $CLI bundle deploy &> LOG.deploy +cat LOG.deploy | contains.py '!panic' '!internal error' > /dev/null + +# Special message to fuzzer that generated config was fine. +# Any failures after this point will be considered as "bug detected" by fuzzer. +echo INPUT_CONFIG_OK + +# Replace the config with an empty bundle, keeping only the bundle name so the +# deployment continues to target the same state root. +envsubst < $TESTDIR/../configs/empty.yml.tmpl > databricks.yml +cp databricks.yml LOG.config.empty + +# Save a plan for the emptied config; the second variant deploys with it via --plan +$CLI bundle plan -o json > plan.json 2>LOG.plan_delete.err +cat LOG.plan_delete.err | contains.py '!panic' '!internal error' > /dev/null + +# Deploy the emptied config, deleting all resources +trace $CLI bundle deploy --auto-approve $(readplanarg plan.json) &> LOG.deploy_delete +cat LOG.deploy_delete | contains.py '!panic' '!internal error' > /dev/null + +# After deleting all resources, the plan must be empty (no drift, no resources) +$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, 0 unchanged' > LOG.plan +cat LOG.plan.err | contains.py '!panic' '!internal error' > /dev/null + +# The summary must also report no resources +$CLI bundle summary -o json > LOG.summary 2>LOG.summary.err +cat LOG.summary.err | contains.py '!panic' '!internal error' > /dev/null +cat LOG.summary | jq -e '(.resources // {}) == {}' > /dev/null diff --git a/acceptance/bundle/invariant/delete/test.toml b/acceptance/bundle/invariant/delete/test.toml new file mode 100644 index 0000000000..ff8a66c196 --- /dev/null +++ b/acceptance/bundle/invariant/delete/test.toml @@ -0,0 +1 @@ +EnvMatrix.READPLAN = ["", "1"] diff --git a/acceptance/bundle/invariant/migrate/test.toml b/acceptance/bundle/invariant/migrate/test.toml index a121cbf647..6553736cb9 100644 --- a/acceptance/bundle/invariant/migrate/test.toml +++ b/acceptance/bundle/invariant/migrate/test.toml @@ -23,6 +23,10 @@ EnvMatrixExclude.no_grant_ref = ["INPUT_CONFIG=schema_grant_ref.yml.tmpl"] # SQL warehouses currently failing with migration with permanent drift. TODO: fix this. EnvMatrixExclude.no_sql_warehouse = ["INPUT_CONFIG=sql_warehouse.yml.tmpl"] +# The empty bundle has no resources, so the terraform deploy writes no state and +# there is nothing for "bundle deployment migrate" to migrate. +EnvMatrixExclude.no_empty = ["INPUT_CONFIG=empty.yml.tmpl"] + # The 1000-task scale case is covered by no_drift. Running it here adds ~1.5 min # per variant (deploy + migrate + plan at 1000 tasks) without incremental coverage. EnvMatrixExclude.no_pydabs_1000_tasks = ["INPUT_CONFIG=job_pydabs_1000_tasks.yml.tmpl"] diff --git a/acceptance/bundle/invariant/no_drift/out.test.toml b/acceptance/bundle/invariant/no_drift/out.test.toml index a77c832256..33c84b67de 100644 --- a/acceptance/bundle/invariant/no_drift/out.test.toml +++ b/acceptance/bundle/invariant/no_drift/out.test.toml @@ -15,6 +15,7 @@ EnvMatrix.INPUT_CONFIG = [ "database_catalog.yml.tmpl", "database_instance.yml.tmpl", "database_instance_with_permissions.yml.tmpl", + "empty.yml.tmpl", "experiment.yml.tmpl", "external_location.yml.tmpl", "genie_space.yml.tmpl", diff --git a/acceptance/bundle/invariant/test.toml b/acceptance/bundle/invariant/test.toml index 4d296cb83d..9e0eedd99c 100644 --- a/acceptance/bundle/invariant/test.toml +++ b/acceptance/bundle/invariant/test.toml @@ -33,6 +33,7 @@ EnvMatrix.INPUT_CONFIG = [ "database_catalog.yml.tmpl", "database_instance.yml.tmpl", "database_instance_with_permissions.yml.tmpl", + "empty.yml.tmpl", "experiment.yml.tmpl", "external_location.yml.tmpl", "genie_space.yml.tmpl",