Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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 .nextchanges/bundles/select-deletions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* Support selecting resources for deletion with `bundle deploy --select`. ([#7023](https://github.com/databricks/cli/pull/7023))
7 changes: 7 additions & 0 deletions acceptance/bundle/select/deletion/databricks.yml.after.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
bundle:
name: select-del-$UNIQUE_NAME

resources:
jobs:
keep:
name: keep-$UNIQUE_NAME
10 changes: 10 additions & 0 deletions acceptance/bundle/select/deletion/databricks.yml.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
bundle:
name: select-del-$UNIQUE_NAME

resources:
jobs:
keep:
name: keep-$UNIQUE_NAME

gone:
name: gone-$UNIQUE_NAME
2 changes: 2 additions & 0 deletions acceptance/bundle/select/deletion/out.test.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Cloud = true
EnvMatrix.DMS = ["", "true"]
76 changes: 76 additions & 0 deletions acceptance/bundle/select/deletion/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@

=== Initial deploy

>>> [CLI] bundle deploy
Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/select-del-[UNIQUE_NAME]/default/files...
Created jobs.gone
Created jobs.keep
Files: 3 uploaded, 0 deleted
Resources: 2 created, 0 changed, 0 deleted, 0 unchanged

>>> [CLI] bundle plan --select jobs.gone
delete jobs.gone

Plan: 0 to add, 0 to change, 1 to delete, 0 unchanged, 1 not selected

=== bundle deploy --select jobs.gone

>>> [CLI] bundle deploy --select jobs.gone
Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/select-del-[UNIQUE_NAME]/default/files...
Deleted jobs.gone
Files: 1 uploaded, 0 deleted
Resources: 0 created, 0 changed, 1 deleted, 0 unchanged, 1 not selected

>>> print_requests.py --sort //jobs/delete
{
"method": "POST",
"path": "/api/2.2/jobs/delete",
"body": {
"job_id": [GONE_ID]
}
}

>>> [CLI] bundle plan
Plan: 0 to add, 0 to change, 0 to delete, 1 unchanged

=== Redeploy gone, then select it by unqualified name

>>> [CLI] bundle deploy
Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/select-del-[UNIQUE_NAME]/default/files...
Created jobs.gone
Files: 1 uploaded, 0 deleted
Resources: 1 created, 0 changed, 0 deleted, 1 unchanged

>>> [CLI] bundle plan --select gone
delete jobs.gone

Plan: 0 to add, 0 to change, 1 to delete, 0 unchanged, 1 not selected

=== bundle deploy --select gone

>>> [CLI] bundle deploy --select gone
Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/select-del-[UNIQUE_NAME]/default/files...
Deleted jobs.gone
Files: 1 uploaded, 0 deleted
Resources: 0 created, 0 changed, 1 deleted, 0 unchanged, 1 not selected

>>> print_requests.py --sort //jobs/delete
{
"method": "POST",
"path": "/api/2.2/jobs/delete",
"body": {
"job_id": [GONE_ID_2]
}
}

>>> [CLI] bundle plan
Plan: 0 to add, 0 to change, 0 to delete, 1 unchanged

=== Destroy
>>> [CLI] bundle destroy --auto-approve
The following resources will be deleted:
delete resources.jobs.keep

All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/select-del-[UNIQUE_NAME]/default

Destroy: 1 deleted
48 changes: 48 additions & 0 deletions acceptance/bundle/select/deletion/script
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
envsubst '$UNIQUE_NAME' < databricks.yml.tmpl > databricks.yml

cleanup() {
title "Destroy"
trace $CLI bundle destroy --auto-approve
rm -f "$OUT_REQUESTS"
}
trap cleanup EXIT

# Deploy both jobs.
title "Initial deploy\n"
trace $CLI bundle deploy
# Register [KEEP_ID]/[GONE_ID] from state while both still exist, so the delete
# request body below is masked deterministically.
replace_ids.py

# Remove 'gone' from config. It is now orphaned in state and planned for deletion.
envsubst '$UNIQUE_NAME' < databricks.yml.after.tmpl > databricks.yml

# A resource removed from config is selectable by name, like any created or updated
# one. The plan is filtered to just its deletion.
trace $CLI bundle plan --select jobs.gone

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we parametrize selector? $SELECTOR

in test.toml: EnvMatrix.SELECTOR = ["jobs.gone", "gone"]

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trace outputs the command so the output would differ.

I added a second plan & deploy for "gone" below.


title "bundle deploy --select jobs.gone\n"
trace $CLI bundle deploy --select jobs.gone

# The delete call targeted 'gone' only.
trace print_requests.py --sort //jobs/delete

# A full plan now has nothing to delete and 'keep' is unchanged.
trace $CLI bundle plan

# The same works with an unqualified name. Deploy 'gone' again, then remove it from
# config so it is once more orphaned in state.
title "Redeploy gone, then select it by unqualified name\n"
envsubst '$UNIQUE_NAME' < databricks.yml.tmpl > databricks.yml
trace $CLI bundle deploy
replace_ids.py
envsubst '$UNIQUE_NAME' < databricks.yml.after.tmpl > databricks.yml

trace $CLI bundle plan --select gone

title "bundle deploy --select gone\n"
trace $CLI bundle deploy --select gone

trace print_requests.py --sort //jobs/delete

trace $CLI bundle plan
4 changes: 4 additions & 0 deletions acceptance/bundle/select/deletion/test.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Cloud = true
RecordRequests = true
# databricks.yml is generated at runtime from the committed templates.
Ignore = [".databricks", ".gitignore", "databricks.yml"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
bundle:
name: select-deldep-$UNIQUE_NAME

resources:
jobs:
keep:
name: keep-$UNIQUE_NAME
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
bundle:
name: select-deldep-$UNIQUE_NAME

resources:
jobs:
keep:
name: keep-$UNIQUE_NAME

consumer:
name: consumer-$UNIQUE_NAME
tasks:
- task_key: run_producer
run_job_task:
job_id: ${resources.jobs.producer.id}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
bundle:
name: select-deldep-$UNIQUE_NAME

resources:
jobs:
keep:
name: keep-$UNIQUE_NAME

producer:
name: producer-$UNIQUE_NAME

consumer:
name: consumer-$UNIQUE_NAME
tasks:
- task_key: run_producer
run_job_task:
job_id: ${resources.jobs.producer.id}
2 changes: 2 additions & 0 deletions acceptance/bundle/select/deletion_dependents/out.test.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Cloud = true
EnvMatrix.DMS = ["", "true"]
71 changes: 71 additions & 0 deletions acceptance/bundle/select/deletion_dependents/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@

=== Initial deploy

>>> [CLI] bundle deploy
Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/select-deldep-[UNIQUE_NAME]/default/files...
Created jobs.consumer
Created jobs.keep
Created jobs.producer
Files: 4 uploaded, 0 deleted
Resources: 3 created, 0 changed, 0 deleted, 0 unchanged

>>> [CLI] bundle plan --select jobs.producer
Error: cannot delete jobs.producer: jobs.consumer still references it; remove the reference or also remove jobs.consumer from the config

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should not this configuration fail even without --select? There is a reference to a missing resource, the whole config is not valid.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's invalid, but validate passes and a plain deploy deletes producer and then fails midway without --select.

This PR makes --select fail cleanly before deleting anything, should we do the same without --select as separate PR?



>>> [CLI] bundle deploy --select jobs.producer
Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/select-deldep-[UNIQUE_NAME]/default/files...
Error: cannot delete jobs.producer: jobs.consumer still references it; remove the reference or also remove jobs.consumer from the config

Files: 1 uploaded, 0 deleted

>>> print_requests.py --sort //jobs/delete --keep

>>> [CLI] bundle plan
update jobs.consumer
delete jobs.producer

Plan: 0 to add, 1 to change, 1 to delete, 1 unchanged

>>> [CLI] bundle plan --select jobs.producer
delete jobs.consumer
delete jobs.producer

Plan: 0 to add, 0 to change, 2 to delete, 0 unchanged, 1 not selected

=== bundle deploy --select jobs.producer

>>> [CLI] bundle deploy --select jobs.producer
Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/select-deldep-[UNIQUE_NAME]/default/files...
Deleted jobs.consumer
Deleted jobs.producer
Files: 1 uploaded, 0 deleted
Resources: 0 created, 0 changed, 2 deleted, 0 unchanged, 1 not selected

>>> print_requests.py //jobs/delete
{
"method": "POST",
"path": "/api/2.2/jobs/delete",
"body": {
"job_id": [CONSUMER_ID]
}
}
{
"method": "POST",
"path": "/api/2.2/jobs/delete",
"body": {
"job_id": [PRODUCER_ID]
}
}

>>> [CLI] bundle plan
Plan: 0 to add, 0 to change, 0 to delete, 1 unchanged

=== Destroy
>>> [CLI] bundle destroy --auto-approve
The following resources will be deleted:
delete resources.jobs.keep

All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/select-deldep-[UNIQUE_NAME]/default

Destroy: 1 deleted
49 changes: 49 additions & 0 deletions acceptance/bundle/select/deletion_dependents/script
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
envsubst '$UNIQUE_NAME' < databricks.yml.tmpl > databricks.yml

cleanup() {
title "Destroy"
trace $CLI bundle destroy --auto-approve
rm -f "$OUT_REQUESTS"
}
trap cleanup EXIT

# Deploy three jobs; consumer references producer, so state records consumer's
# dependency on producer.
title "Initial deploy\n"
trace $CLI bundle deploy
replace_ids.py

# --- error case: consumer is still live and references producer ---
# Remove only producer from config; consumer stays with its reference intact.
# Selecting producer for deletion must error: it would leave consumer broken.
envsubst '$UNIQUE_NAME' < databricks.yml.live_consumer.tmpl > databricks.yml

musterr trace $CLI bundle plan --select jobs.producer

# bundle deploy --select also errors before sending any delete request.
musterr trace $CLI bundle deploy --select jobs.producer

# No delete request was sent by either command.
trace print_requests.py --sort //jobs/delete --keep

# A full plan still works and shows producer as a pending delete.
trace $CLI bundle plan

# --- success case: both producer and consumer are removed from config ---
# Remove producer and consumer from config; both are now planned for deletion.
envsubst '$UNIQUE_NAME' < databricks.yml.after.tmpl > databricks.yml

# Selecting the depended-upon producer for deletion also deletes its dependent
# consumer (which would otherwise be left referencing a deleted job). 'keep' is
# untouched. The dependency direction is reversed for deletes.
trace $CLI bundle plan --select jobs.producer

title "bundle deploy --select jobs.producer\n"
trace $CLI bundle deploy --select jobs.producer

# Both producer and consumer were deleted, dependent first; keep was not. Not sorted:
# --sort orders by the raw job ID, which is random on a real workspace.
trace print_requests.py //jobs/delete

# A full plan now has nothing to delete and 'keep' is unchanged.
trace $CLI bundle plan
4 changes: 4 additions & 0 deletions acceptance/bundle/select/deletion_dependents/test.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Cloud = true
RecordRequests = true
# databricks.yml is generated at runtime from the committed templates.
Ignore = [".databricks", ".gitignore", "databricks.yml"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
bundle:
name: select-del-plan-$UNIQUE_NAME

resources:
jobs:
keep:
name: keep-$UNIQUE_NAME
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
bundle:
name: select-del-plan-$UNIQUE_NAME

resources:
jobs:
keep:
name: keep-$UNIQUE_NAME

gone:
name: gone-$UNIQUE_NAME
2 changes: 2 additions & 0 deletions acceptance/bundle/select/deletion_saved_plan/out.test.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Cloud = true
EnvMatrix.DMS = ["", "true"]
38 changes: 38 additions & 0 deletions acceptance/bundle/select/deletion_saved_plan/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@

=== Initial deploy

>>> [CLI] bundle deploy
Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/select-del-plan-[UNIQUE_NAME]/default/files...
Created jobs.gone
Created jobs.keep
Files: 3 uploaded, 0 deleted
Resources: 2 created, 0 changed, 0 deleted, 0 unchanged

=== bundle deploy --plan (no --select)

>>> [CLI] bundle deploy --plan plan.json
Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/select-del-plan-[UNIQUE_NAME]/default/files...
Deleted jobs.gone
Files: 2 uploaded, 0 deleted
Resources: 0 created, 0 changed, 1 deleted, 0 unchanged, 1 not selected

>>> print_requests.py --sort //jobs/delete
{
"method": "POST",
"path": "/api/2.2/jobs/delete",
"body": {
"job_id": [GONE_ID]
}
}

>>> [CLI] bundle plan
Plan: 0 to add, 0 to change, 0 to delete, 1 unchanged

=== Destroy
>>> [CLI] bundle destroy --auto-approve
The following resources will be deleted:
delete resources.jobs.keep

All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/select-del-plan-[UNIQUE_NAME]/default

Destroy: 1 deleted
Loading