From 0c6de5cdf1cadccb6d1616babc35722ae80fd3e5 Mon Sep 17 00:00:00 2001 From: yuri-rod Date: Tue, 13 Oct 2026 09:54:25 -0300 Subject: [PATCH 1/4] Skip undeclared schema and catalog properties on plan --- bundle/direct/bundle_plan_test.go | 16 ++++++++++++++++ bundle/direct/dresources/configs/catalogs.yml | 4 ++++ bundle/direct/dresources/configs/schemas.yml | 4 ++++ 3 files changed, 24 insertions(+) diff --git a/bundle/direct/bundle_plan_test.go b/bundle/direct/bundle_plan_test.go index 025ef91df6e..f9253aff260 100644 --- a/bundle/direct/bundle_plan_test.go +++ b/bundle/direct/bundle_plan_test.go @@ -175,6 +175,22 @@ func TestShouldSkipBackendDefault_ManagedPropertiesOnly(t *testing.T) { } } +func TestSchemaCatalogRemoteOnlyPropertiesSkipped(t *testing.T) { + for _, resource := range []string{"schemas", "catalogs"} { + t.Run(resource, func(t *testing.T) { + cfg := dresources.GetResourceConfig(resource) + path, err := structpath.ParsePath("properties") + require.NoError(t, err) + _, ok := shouldSkipBackendDefault(cfg, path, &deployplan.ChangeDesc{ + Old: nil, + New: nil, + Remote: map[string]string{"owner": "root"}, + }) + assert.True(t, ok) + }) + } +} + // A field present in StateType but absent from RemoteType (input-only, e.g. external // locations' skip_validation) reads back nil, so a coincidental new == remote must NOT // trip RemoteAlreadySet — that would skip a real local change. A field present in RemoteType diff --git a/bundle/direct/dresources/configs/catalogs.yml b/bundle/direct/dresources/configs/catalogs.yml index 143a74c447d..636d21d1fb6 100644 --- a/bundle/direct/dresources/configs/catalogs.yml +++ b/bundle/direct/dresources/configs/catalogs.yml @@ -19,3 +19,7 @@ updatable_id_fields: backend_defaults: # UC auto-populates unity.catalog.managed..defaults.* keys after create. - field: properties['unity.catalog.managed.*.defaults.*'] + # The SDK cannot send an empty map to clear properties the config never + # declared, so a bound catalog with out-of-band properties would otherwise + # plan an Update on every deploy (#6986). + - field: properties diff --git a/bundle/direct/dresources/configs/schemas.yml b/bundle/direct/dresources/configs/schemas.yml index 8ef27e71d15..31c1311a361 100644 --- a/bundle/direct/dresources/configs/schemas.yml +++ b/bundle/direct/dresources/configs/schemas.yml @@ -15,3 +15,7 @@ backend_defaults: # Without this, every subsequent plan produces an Update whose payload is empty, # and UC rejects it with "UpdateSchema Nothing to update". - field: properties['unity.catalog.managed.*.defaults.*'] + # The SDK cannot send an empty map to clear properties the config never + # declared, so a bound schema with out-of-band properties would otherwise + # plan an Update on every deploy (#6986). + - field: properties From a6d73af422d743a66f49ac2b0eeed5cbefe9f5ec Mon Sep 17 00:00:00 2001 From: yuri-rod Date: Tue, 13 Oct 2026 09:59:57 -0300 Subject: [PATCH 2/4] Trim properties defaults to one rule --- bundle/direct/dresources/configs/catalogs.yml | 4 ---- bundle/direct/dresources/configs/schemas.yml | 4 ---- 2 files changed, 8 deletions(-) diff --git a/bundle/direct/dresources/configs/catalogs.yml b/bundle/direct/dresources/configs/catalogs.yml index 636d21d1fb6..80c439ba756 100644 --- a/bundle/direct/dresources/configs/catalogs.yml +++ b/bundle/direct/dresources/configs/catalogs.yml @@ -18,8 +18,4 @@ updatable_id_fields: reason: id_changes backend_defaults: # UC auto-populates unity.catalog.managed..defaults.* keys after create. - - field: properties['unity.catalog.managed.*.defaults.*'] - # The SDK cannot send an empty map to clear properties the config never - # declared, so a bound catalog with out-of-band properties would otherwise - # plan an Update on every deploy (#6986). - field: properties diff --git a/bundle/direct/dresources/configs/schemas.yml b/bundle/direct/dresources/configs/schemas.yml index 31c1311a361..90d59b4b08d 100644 --- a/bundle/direct/dresources/configs/schemas.yml +++ b/bundle/direct/dresources/configs/schemas.yml @@ -14,8 +14,4 @@ backend_defaults: # UC auto-populates unity.catalog.managed..defaults.* keys after create. # Without this, every subsequent plan produces an Update whose payload is empty, # and UC rejects it with "UpdateSchema Nothing to update". - - field: properties['unity.catalog.managed.*.defaults.*'] - # The SDK cannot send an empty map to clear properties the config never - # declared, so a bound schema with out-of-band properties would otherwise - # plan an Update on every deploy (#6986). - field: properties From e6c1c25bc513efa69b412983c174e61f7a7b19f8 Mon Sep 17 00:00:00 2001 From: yuri-rod Date: Tue, 13 Oct 2026 10:14:03 -0300 Subject: [PATCH 3/4] Add changelog entry for properties plan fix --- .nextchanges/bundles/7036.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 .nextchanges/bundles/7036.md diff --git a/.nextchanges/bundles/7036.md b/.nextchanges/bundles/7036.md new file mode 100644 index 00000000000..b07601212bb --- /dev/null +++ b/.nextchanges/bundles/7036.md @@ -0,0 +1 @@ +* Fix bundle plan reporting an Update on every deploy for schemas and catalogs with properties the config never declared. ([#7036](https://github.com/databricks/cli/pull/7036)) From ef42c307ec5253b290de3d06b36ba99259772336 Mon Sep 17 00:00:00 2001 From: yuri-rod Date: Tue, 13 Oct 2026 10:21:08 -0300 Subject: [PATCH 4/4] Cover declared property drift and clarify defaults --- bundle/direct/bundle_plan_test.go | 16 ++++++++++++++++ bundle/direct/dresources/configs/catalogs.yml | 5 ++++- bundle/direct/dresources/configs/schemas.yml | 7 ++++--- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/bundle/direct/bundle_plan_test.go b/bundle/direct/bundle_plan_test.go index f9253aff260..a23a8cbab49 100644 --- a/bundle/direct/bundle_plan_test.go +++ b/bundle/direct/bundle_plan_test.go @@ -187,6 +187,22 @@ func TestSchemaCatalogRemoteOnlyPropertiesSkipped(t *testing.T) { Remote: map[string]string{"owner": "root"}, }) assert.True(t, ok) + + _, ok = shouldSkipBackendDefault(cfg, path, &deployplan.ChangeDesc{ + Old: map[string]string{"owner": "root"}, + New: map[string]string{"owner": "root"}, + Remote: map[string]string{"owner": "other"}, + }) + assert.False(t, ok) + + child, err := structpath.ParsePath("properties['owner']") + require.NoError(t, err) + _, ok = shouldSkipBackendDefault(cfg, child, &deployplan.ChangeDesc{ + Old: "root", + New: "root", + Remote: "other", + }) + assert.False(t, ok) }) } } diff --git a/bundle/direct/dresources/configs/catalogs.yml b/bundle/direct/dresources/configs/catalogs.yml index 80c439ba756..538304a8a66 100644 --- a/bundle/direct/dresources/configs/catalogs.yml +++ b/bundle/direct/dresources/configs/catalogs.yml @@ -17,5 +17,8 @@ updatable_id_fields: - field: name reason: id_changes backend_defaults: - # UC auto-populates unity.catalog.managed..defaults.* keys after create. + # Skip properties present only on the remote when the config declares none, + # including unity.catalog.managed.*.defaults.* keys UC sets after create. + # The SDK cannot send an empty map to clear them. Declared properties + # still take part in drift detection. - field: properties diff --git a/bundle/direct/dresources/configs/schemas.yml b/bundle/direct/dresources/configs/schemas.yml index 90d59b4b08d..80d2c1e6e87 100644 --- a/bundle/direct/dresources/configs/schemas.yml +++ b/bundle/direct/dresources/configs/schemas.yml @@ -11,7 +11,8 @@ normalize_slash: - field: storage_root reason: uc_strips_trailing_slash backend_defaults: - # UC auto-populates unity.catalog.managed..defaults.* keys after create. - # Without this, every subsequent plan produces an Update whose payload is empty, - # and UC rejects it with "UpdateSchema Nothing to update". + # Skip properties present only on the remote when the config declares none, + # including unity.catalog.managed.*.defaults.* keys UC sets after create. + # The SDK cannot send an empty map to clear them. Declared properties + # still take part in drift detection. - field: properties