From 4bee5d345a607be3910e6d1f261119c70684ea6e Mon Sep 17 00:00:00 2001 From: Rada Kamysheva Date: Thu, 23 Jul 2026 13:57:34 +0000 Subject: [PATCH] acceptance/invariant: match Go panics precisely with '!panic:' The invariant scripts guard against panics with contains.py '!panic', which forbids the substring 'panic' anywhere in the output. That false-positives on legitimate content that merely contains the word (e.g. a resource name or a message like 'no panic'). Go's runtime prints panics as 'panic:' with a trailing colon, so match that instead. This only relaxes the guard (any output that passed still passes), while removing the substring-collision risk. Applied to all curated invariant scripts (continue_293, delete_idempotent, destroy_idempotent, no_drift) for consistency. --- acceptance/bundle/invariant/continue_293/script | 12 ++++++------ .../bundle/invariant/delete_idempotent/script | 16 ++++++++-------- .../bundle/invariant/destroy_idempotent/script | 12 ++++++------ acceptance/bundle/invariant/no_drift/script | 8 ++++---- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/acceptance/bundle/invariant/continue_293/script b/acceptance/bundle/invariant/continue_293/script index c1c8d758eeb..cd0e57ba9b8 100644 --- a/acceptance/bundle/invariant/continue_293/script +++ b/acceptance/bundle/invariant/continue_293/script @@ -11,7 +11,7 @@ envsubst < "$TESTDIR/../configs/$INPUT_CONFIG" > databricks.yml cleanup() { $CLI bundle destroy --auto-approve &> LOG.destroy - cat LOG.destroy | contains.py '!panic' '!internal error' > /dev/null + cat LOG.destroy | contains.py '!panic:' '!internal error' > /dev/null CLEANUP_SCRIPT="$TESTDIR/../configs/$INPUT_CONFIG-cleanup.sh" if [ -f "$CLEANUP_SCRIPT" ]; then @@ -24,18 +24,18 @@ trap cleanup EXIT # Deploy with old CLI to produce v0.293.0 state trace $CLI_293 --version $CLI_293 bundle deploy &> LOG.deploy.293 -cat LOG.deploy.293 | contains.py '!panic' '!internal error' > /dev/null +cat LOG.deploy.293 | contains.py '!panic:' '!internal error' > /dev/null echo INPUT_CONFIG_OK # Deploy with current CLI on top of old state $CLI bundle deploy &> LOG.deploy -cat LOG.deploy | contains.py '!panic' '!internal error' > /dev/null +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 +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 +$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 diff --git a/acceptance/bundle/invariant/delete_idempotent/script b/acceptance/bundle/invariant/delete_idempotent/script index 9a67ae36a67..e21c2887f07 100644 --- a/acceptance/bundle/invariant/delete_idempotent/script +++ b/acceptance/bundle/invariant/delete_idempotent/script @@ -22,7 +22,7 @@ STATE_PATH=/Workspace/Users/$CURRENT_USER_NAME/.bundle/$bundle_name/default/stat cleanup() { trace $CLI bundle destroy --auto-approve &> LOG.destroy - cat LOG.destroy | contains.py '!panic' '!internal error' > /dev/null + cat LOG.destroy | contains.py '!panic:' '!internal error' > /dev/null CLEANUP_SCRIPT="$TESTDIR/../configs/$INPUT_CONFIG-cleanup.sh" if [ -f "$CLEANUP_SCRIPT" ]; then @@ -36,11 +36,11 @@ trap cleanup EXIT # saved-plan deploy path; otherwise `bundle deploy` plans on its own. if [[ -n "$READPLAN" ]]; then $CLI bundle plan -o json > plan_initial.json 2>LOG.plan_initial.err - cat LOG.plan_initial.err | contains.py '!panic' '!internal error' > /dev/null + cat LOG.plan_initial.err | contains.py '!panic:' '!internal error' > /dev/null fi trace $CLI bundle deploy $(readplanarg plan_initial.json) &> LOG.deploy_initial -cat LOG.deploy_initial | contains.py '!panic' '!internal error' > /dev/null +cat LOG.deploy_initial | 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. @@ -59,11 +59,11 @@ EOF if [[ -n "$READPLAN" ]]; then $CLI bundle plan -o json > plan_delete.json 2>LOG.plan_delete.err - cat LOG.plan_delete.err | contains.py '!panic' '!internal error' > /dev/null + cat LOG.plan_delete.err | contains.py '!panic:' '!internal error' > /dev/null fi trace $CLI bundle deploy --auto-approve $(readplanarg plan_delete.json) &> LOG.deploy_delete -cat LOG.deploy_delete | contains.py '!panic' '!internal error' > /dev/null +cat LOG.deploy_delete | contains.py '!panic:' '!internal error' > /dev/null # Restore the pre-delete state; the resources are already gone from the server, # so the next delete-deploy must handle "resource already gone" idempotently. @@ -78,12 +78,12 @@ mv .databricks.backup .databricks # workspace path into C:/Program Files/Git/...; it is scoped to this command so # the Python helpers (which need their own paths converted) are unaffected. MSYS_NO_PATHCONV=1 $CLI workspace delete --recursive "$STATE_PATH" &> LOG.wipe_remote_state -cat LOG.wipe_remote_state | contains.py '!panic' '!internal error' > /dev/null +cat LOG.wipe_remote_state | contains.py '!panic:' '!internal error' > /dev/null if [[ -n "$READPLAN" ]]; then $CLI bundle plan -o json > plan_delete2.json 2>LOG.plan_delete2.err - cat LOG.plan_delete2.err | contains.py '!panic' '!internal error' > /dev/null + cat LOG.plan_delete2.err | contains.py '!panic:' '!internal error' > /dev/null fi trace $CLI bundle deploy --auto-approve $(readplanarg plan_delete2.json) &> LOG.deploy_delete2 -cat LOG.deploy_delete2 | contains.py '!panic' '!internal error' > /dev/null +cat LOG.deploy_delete2 | contains.py '!panic:' '!internal error' > /dev/null diff --git a/acceptance/bundle/invariant/destroy_idempotent/script b/acceptance/bundle/invariant/destroy_idempotent/script index 20fc4dcfc0d..d9e76cbaf1b 100644 --- a/acceptance/bundle/invariant/destroy_idempotent/script +++ b/acceptance/bundle/invariant/destroy_idempotent/script @@ -22,7 +22,7 @@ ROOT_PATH=/Workspace/Users/$CURRENT_USER_NAME/.bundle/$bundle_name/default final_cleanup() { trace $CLI bundle destroy --auto-approve &> LOG.destroy_final - cat LOG.destroy_final | contains.py '!panic' '!internal error' > /dev/null + cat LOG.destroy_final | contains.py '!panic:' '!internal error' > /dev/null CLEANUP_SCRIPT="$TESTDIR/../configs/$INPUT_CONFIG-cleanup.sh" if [ -f "$CLEANUP_SCRIPT" ]; then @@ -36,11 +36,11 @@ trap final_cleanup EXIT # saved-plan deploy path; otherwise `bundle deploy` plans on its own. if [[ -n "$READPLAN" ]]; then $CLI bundle plan -o json > plan_initial.json 2>LOG.plan_initial.err - cat LOG.plan_initial.err | contains.py '!panic' '!internal error' > /dev/null + cat LOG.plan_initial.err | contains.py '!panic:' '!internal error' > /dev/null fi trace $CLI bundle deploy $(readplanarg plan_initial.json) &> LOG.deploy_initial -cat LOG.deploy_initial | contains.py '!panic' '!internal error' > /dev/null +cat LOG.deploy_initial | 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. @@ -50,7 +50,7 @@ echo INPUT_CONFIG_OK cp -r .databricks .databricks.backup trace $CLI bundle destroy --auto-approve &> LOG.destroy1 -cat LOG.destroy1 | contains.py '!panic' '!internal error' > /dev/null +cat LOG.destroy1 | contains.py '!panic:' '!internal error' > /dev/null # Restore the pre-destroy state; the resources are already gone from the server, # so the next destroy must handle "resource already gone" idempotently. @@ -63,7 +63,7 @@ mv .databricks.backup .databricks # workspace path into C:/Program Files/Git/...; it is scoped to this command so # the Python helpers (which need their own paths converted) are unaffected. MSYS_NO_PATHCONV=1 $CLI workspace mkdirs "$ROOT_PATH" &> LOG.mkdirs -cat LOG.mkdirs | contains.py '!panic' '!internal error' > /dev/null +cat LOG.mkdirs | contains.py '!panic:' '!internal error' > /dev/null trace $CLI bundle destroy --auto-approve &> LOG.destroy2 -cat LOG.destroy2 | contains.py '!panic' '!internal error' > /dev/null +cat LOG.destroy2 | contains.py '!panic:' '!internal error' > /dev/null diff --git a/acceptance/bundle/invariant/no_drift/script b/acceptance/bundle/invariant/no_drift/script index 481f64d9e74..ca80ab85440 100644 --- a/acceptance/bundle/invariant/no_drift/script +++ b/acceptance/bundle/invariant/no_drift/script @@ -16,7 +16,7 @@ cp databricks.yml LOG.config cleanup() { trace $CLI bundle destroy --auto-approve &> LOG.destroy - cat LOG.destroy | contains.py '!panic' '!internal error' > /dev/null + cat LOG.destroy | contains.py '!panic:' '!internal error' > /dev/null # Run cleanup script if present CLEANUP_SCRIPT="$TESTDIR/../configs/$INPUT_CONFIG-cleanup.sh" @@ -32,11 +32,11 @@ trap cleanup EXIT # invocation is pure waste. if [[ -n "$READPLAN" ]]; then $CLI bundle plan -o json > plan.json 2>LOG.plan_initial.err - cat LOG.plan_initial.err | contains.py '!panic' '!internal error' > /dev/null + cat LOG.plan_initial.err | contains.py '!panic:' '!internal error' > /dev/null fi trace $CLI bundle deploy $(readplanarg plan.json) &> LOG.deploy -cat LOG.deploy | contains.py '!panic' '!internal error' > /dev/null +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. @@ -45,5 +45,5 @@ echo INPUT_CONFIG_OK # JSON plan asserts every action is "skip" -- a strict superset of the text # renderer's "Plan: 0 to add, 0 to change, 0 to delete" summary. $CLI bundle plan -o json > LOG.planjson 2>LOG.planjson.err -cat LOG.planjson.err | contains.py '!panic' '!internal error' > /dev/null +cat LOG.planjson.err | contains.py '!panic:' '!internal error' > /dev/null verify_no_drift.py LOG.planjson