Skip to content

Refactor validate_direct_only_resources and approval log loops#5215

Merged
janniklasrose merged 4 commits intomainfrom
janniklasrose/phases-and-validate-cleanup
May 8, 2026
Merged

Refactor validate_direct_only_resources and approval log loops#5215
janniklasrose merged 4 commits intomainfrom
janniklasrose/phases-and-validate-cleanup

Conversation

@janniklasrose
Copy link
Copy Markdown
Contributor

Changes

Two independent refactors in bundle/:

  1. bundle/config/mutator/validate_direct_only_resources.go — drop the local directOnlyResource struct (whose pluralName/singularName fields actually held SingularTitle/SingularName values) and the per-type getResources closures. Iterate b.Config.Resources.AllResources() and key off PluralName via a small map[string]bool instead, reading SingularTitle/SingularName from the canonical ResourceDescription. Adds a unit test covering direct/terraform engines × the three direct-only resource types.

  2. bundle/phases/{deploy,destroy}.go — collapse the eight (deploy) and seven (destroy) near-identical if len(xActions) != 0 { LogString(message); for _ { Log(action) } } blocks into a table-driven helper logApprovalGroups in a new bundle/phases/approval.go. The deploy version also replaces the eight-clause len(...) == 0 && early-return with a single total == 0 check returned from the helper. The schema child-resource skip (deploy only) and trailing blank lines (destroy only) are preserved via per-group skipChildren/trailingGap flags. The outer "all deletes" preamble in destroy stays as-is — it's structurally different.

Net diff: −215 source LOC, +110 test LOC.

Why

Both files had grown into mechanical repetition. validate_direct_only_resources.go re-declared resource metadata that already lives on each resource's ResourceDescription() and named the fields incorrectly. The approval functions repeated the same eight-/seven-times pattern inline, with an opaque eight-clause boolean expression for the early-return.

There is one minor user-visible wording change: for external_locations and vector_search_endpoints, the Detail message now reads ... use external_location resources. / ... use vector_search_endpoint resources. (snake_case, from SingularName) instead of ... use external location resources. / ... use vector search endpoint resources. (the old struct's hand-written field with spaces). The catalog message is byte-identical. There are no acceptance tests covering the other two messages.

Tests

  • New unit test validate_direct_only_resources_test.go (table-driven over the three direct-only types).
  • Existing acceptance test bundle/validate/catalog_requires_direct_mode passes byte-identically.
  • bundle/destroy/..., bundle/deploy/... (excluding the pre-existing spark-jar-task Java env failure that also fails on main), bundle/resources/grants/schemas/..., bundle/config-remote-sync/..., and bundle/user_agent/simple all pass byte-identically.
  • ./task fmt, ./task checks, ./task lint clean.

This PR was written by Claude Code.

Drop the local directOnlyResource struct (whose field names misnamed
SingularTitle/SingularName as pluralName/singularName) and the per-type
getResources closures. Iterate AllResources() and key off PluralName
instead, reading SingularTitle/SingularName from the canonical
ResourceDescription. Add a unit test covering direct/terraform engines
and each direct-only resource type.

Co-authored-by: Isaac
Replace the eight (deploy) and seven (destroy) near-identical
'if len(...) != 0 { LogString(message); for _ { Log(action) } }'
blocks with a table-driven helper, logApprovalGroups, that takes a
slice of {group, message, skipChildren, trailingGap} entries.

deploy collapses the eight-clause len()==0 early-return to total==0
returned from the helper. The schema child-resource skip and the
destroy trailing blank lines are preserved via the per-group flags.
The outer "all deletes" preamble in destroy stays as-is because it
is structurally different (it skips children and has no trailing
banner per group).

Co-authored-by: Isaac
@janniklasrose janniklasrose requested a review from denik May 8, 2026 11:16
},
// directOnlyResourceTypes lists resources only supported in direct deployment mode.
// Keys are PluralName values from resources.ResourceDescription.
var directOnlyResourceTypes = map[string]bool{
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.

Could we make use of these two maps to automatically figure this out?

bundle/deploy/terraform/pkg.go:var GroupToTerraformName = map[string]string{
bundle/deploy/terraform/pkg.go- // 2 level groups: resources.GROUP
bundle/deploy/terraform/pkg.go- "jobs":                    "databricks_job",
bundle/deploy/terraform/pkg.go- "pipelines":               "databricks_pipeline",
bundle/deploy/terraform/pkg.go- "models":                  "databricks_mlflow_model",
bundle/deploy/terraform/pkg.go- "experiments":             "databricks_mlflow_experiment",

bundle/deploy/terraform/pkg.go:var GroupToTerraformName = map[string]string{

bundle/direct/dresources/all.go:var SupportedResources = map[string]any{
bundle/direct/dresources/all.go-        "jobs":                    (*ResourceJob)(nil),
bundle/direct/dresources/all.go-        "pipelines":               (*ResourcePipeline)(nil),
bundle/direct/dresources/all.go-        "experiments":             (*ResourceExperiment)(nil),
bundle/direct/dresources/all.go-        "catalogs":                (*ResourceCatalog)(nil),
bundle/direct/dresources/all.go-        "schemas":                 (*ResourceSchema)(nil),

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.

perfect!

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.

Done in 6e6940disDirectOnly(name) now checks dresources.SupportedResources minus terraform.GroupToTerraformName.

Comment thread bundle/phases/destroy.go Outdated
{group: "database_instances", message: deleteDatabaseInstanceMessage, trailingGap: true},
{group: "synced_database_tables", message: deleteSyncedDatabaseTableMessage, trailingGap: true},
{group: "postgres_projects", message: deletePostgresProjectMessage, trailingGap: true},
{group: "postgres_branches", message: deletePostgresBranchMessage, trailingGap: true},
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.

trailingGap is always true, is that intentional?

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.

kinda, because approvalGroup is shared between deploy and destroy. But on second thought it's probably better to omit per-resource boolean and pass it as a single parameter to logApprovalGroups

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.

Done in c3bef30trailingNewline is now a parameter to logApprovalGroups (also renamed from trailingGap since "newline" describes what cmdio.LogString(ctx, "") actually emits).

Replace the hardcoded directOnlyResourceTypes set with a check against
dresources.SupportedResources and terraform.GroupToTerraformName: a
resource type is direct-only if it appears in the former but not the
latter. Removes the third source of truth for which resource types
exist where.

Co-authored-by: Isaac
Drop the per-group trailingGap field on approvalGroup (it was always
true for destroy and never set for deploy) and pass a single bool
parameter to logApprovalGroups instead. Also rename the concept from
"gap" to "newline" since that's what cmdio.LogString(ctx, "") prints.

Co-authored-by: Isaac
@janniklasrose janniklasrose merged commit 1d3083f into main May 8, 2026
23 of 25 checks passed
@janniklasrose janniklasrose deleted the janniklasrose/phases-and-validate-cleanup branch May 8, 2026 17:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants