Repository navigation
Support selecting resources for deletion with bundle deploy --select - #7023
andersrexdb wants to merge 3 commits into
Conversation
Add the trailing PR link required by the changelog validation so the Changelog Preview workflow passes. Co-authored-by: Isaac <no-reply@databricks.com>
Integration test reportCommit: 3f151b0
Top 2 slowest tests (at least 2 minutes):
|
aee21d0 to
30adca7
Compare
|
|
||
| # 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 |
There was a problem hiding this comment.
should we parametrize selector? $SELECTOR
in test.toml: EnvMatrix.SELECTOR = ["jobs.gone", "gone"]
There was a problem hiding this comment.
trace outputs the command so the output would differ.
I added a second plan & deploy for "gone" below.
| 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 |
There was a problem hiding this comment.
Should not this configuration fail even without --select? There is a reference to a missing resource, the whole config is not valid.
There was a problem hiding this comment.
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?
|
Commit: Regression test reportSelected 6 changed tests (limit=20, 0 not selected) 12 tests: regression=6 unreleased=0 coverage=6 failing=0
TestAccept/bundle/select/deletion/DMS=: branch ✅ | main (0a32c93) ❌ | latest (v1.21.0) ❌main (0a32c93): latest (v1.21.0): same output as main (0a32c93) TestAccept/bundle/select/deletion/DMS=true: branch ✅ | main (0a32c93) ❌ | latest (v1.21.0) ❌main (0a32c93): latest (v1.21.0): same output as main (0a32c93) TestAccept/bundle/select/deletion_dependents/DMS=: branch ✅ | main (0a32c93) ❌ | latest (v1.21.0) ❌main (0a32c93): latest (v1.21.0): same output as main (0a32c93) TestAccept/bundle/select/deletion_dependents/DMS=true: branch ✅ | main (0a32c93) ❌ | latest (v1.21.0) ❌main (0a32c93): latest (v1.21.0): same output as main (0a32c93) TestAccept/bundle/select/deletion_saved_plan/DMS=: branch ✅ | main (0a32c93) ❌ | latest (v1.21.0) ❌main (0a32c93): latest (v1.21.0): same output as main (0a32c93) TestAccept/bundle/select/deletion_saved_plan/DMS=true: branch ✅ | main (0a32c93) ❌ | latest (v1.21.0) ❌main (0a32c93): latest (v1.21.0): same output as main (0a32c93) |
Resolve --select selectors against the computed plan (Plan.FilterToSelected) instead of the config, so resources removed from config and planned for deletion can be selected like any other. The old ResolveSelect mutator is reduced to recording the select_used telemetry flag (renamed MarkSelectUsed). When a selected resource is being deleted, the plan's closure follows reverse dependency edges: its dependents are deleted too so none are left dangling, while its own dependencies are left untouched — mirroring bundle destroy. A deployed selection still follows forward edges to pull in its dependencies. Grants and permissions sub-nodes move with their parent in both directions. Deleting a resource whose dependent is still live (still in config, not itself being deleted) is an error before any API delete requests are sent. An invalid --select (a name in neither config nor state) is rejected before the predeploy script runs or any files are uploaded. When --plan is used alongside a --select that doesn't match the selectors the plan was built with, a warning is emitted. The plan serializes was_filtered and selectors so a pre-filtered plan file can be passed to bundle deploy --plan without re-specifying --select. Co-authored-by: Isaac <no-reply@databricks.com>
Co-authored-by: Isaac <no-reply@databricks.com>
| // Selectors holds the raw --select values used to produce this filtered plan. | ||
| // Serialized alongside WasFiltered so process.go can warn when --select at | ||
| // deploy time differs from the selectors baked into the plan file. | ||
| Selectors []string `json:"selectors,omitempty"` |
There was a problem hiding this comment.
We now have 3 select-related fields there:
// NotSelected is the number of resources removed by FilterToSelected via the
// --select flag. Serialized so the summary survives a deploy from a plan file
// (--plan); used only for summary reporting.
NotSelected int `json:"not_selected,omitempty"`
// WasFiltered is true when FilterToSelected was called on this plan, regardless
// of how many resources were excluded. Serialized so process.go can distinguish
// a plan that was pre-filtered at plan time (suppress the "--select ignored"
// warning) from one that was not (the flag has no effect and should warn).
WasFiltered bool `json:"was_filtered,omitempty"`
// Selectors holds the raw --select values used to produce this filtered plan.
// Serialized alongside WasFiltered so process.go can warn when --select at
// deploy time differs from the selectors baked into the plan file.
Selectors []string `json:"selectors,omitempty"
Do we need WasFiltered? Does not Selectors imply WasFiltered? Does not NotSelected imply WasFiltered?
(BTW if we do keep was_filtered, I'd rename it to "filtered")
when --select at deploy time differs from the selectors baked into the plan file.
// Serialized alongside WasFiltered so process.go can warn when --select at
// deploy time differs from the selectors baked into the plan file.
I'd actually prefer that we did not need to pass --select to deploy if we pass --plan. It should all be encoded in the plan.
Perhaps we can take these fields (WasFiltered, Selectors) out and do a separate follow up PR? It seems like it adds extra validation that we can do without for the main feature of this PR.
There was a problem hiding this comment.
Makes sense, removed WasFiltered/Selectors. I can look at plan-encoded selection (or an error for the combination) in a follow-up PR.
Remove the WasFiltered and Selectors plan fields and the --plan + --select warning they supported, per review: --plan keeps ignoring --select as before, and encoding the selection in the plan is left for a follow-up. Stop sorting the delete requests in the deletion_dependents acceptance test. --sort orders by raw job ID, which is random on a real workspace and made the test flaky in cloud runs; dependents are deleted first, so the order is stable. Co-authored-by: Isaac <no-reply@databricks.com>
3f151b0 to
1c8d42e
Compare
Resolve --select selectors against the computed plan (Plan.FilterToSelected) instead of the config, so resources removed from config and planned for deletion can be selected like any other. The old ResolveSelect mutator is reduced to recording the select_used telemetry flag (renamed MarkSelectUsed).
When a selected resource is being deleted, the plan's closure follows reverse dependency edges: its dependents are deleted too so none are left dangling, while its own dependencies are left untouched — mirroring bundle destroy. A deployed selection still follows forward edges to pull in its dependencies. Grants and permissions sub-nodes move with their parent in both directions.
Deleting a resource whose dependent is still live (still in config, not itself being deleted) is an error before any API delete requests are sent. An invalid --select (a name in neither config nor state) is rejected before the predeploy script runs or any files are uploaded.
Note: When --plan is used alongside a --select that doesn't match the selectors the plan was built with, a warning is emitted. The plan serializes was_filtered and selectors so a pre-filtered plan file can be passed to bundle deploy --plan without re-specifying --select.
Tests
Added unit tests (
TestFilterToSelected_*) and acceptance tests underacceptance/bundle/select.This pull request and its description were written by Isaac.