Skip to content

Match keyed slices by value in structdiff, ignoring the key field - #6732

Draft
denik wants to merge 3 commits into
mainfrom
denik/structdiff-key-field-swap
Draft

denik wants to merge 3 commits into
mainfrom
denik/structdiff-key-field-swap

Conversation

@denik

@denik denik commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Problem

When a service principal is declared in bundle permissions under user_name (its application-ID UUID), the Permissions API stores and returns it as service_principal_name. The direct engine's plan compared desired (user_name) against remote (service_principal_name) and reported a no-op update of the ACL on every run — a false positive that never converged. Reported by a customer after migrating to the direct engine.

Fix

Keyed slices are already matched by key value (the key field is only used to render the path). So within a matched pair, a diff on the element's own key field means the two sides carry the same identity under a different field — not a real change. structdiff.diffSliceByKey now drops those key-field diffs; non-key fields (e.g. permission level) still diff normally.

This fixes the drift generically for any keyed slice with interchangeable identity fields, with no per-resource logic — the permissions resource stays as just KeyedSlices. It's value-based, so GCP name-based service principals are handled too.

The testserver models the backend's user_name(UUID) → service_principal_name readback, and a new acceptance test asserts the plan converges after deploy and that a genuine level change is still reported.

Alternative to #6710

This is the generic-diff alternative to the resource-level OverrideChangeDesc fix in #6710. Verified no golden moves across the keyed-slice surface (jobs, grants, secret scopes, permissions, run_as, dms) and the full bundle/invariant no_drift sweep — the change is a no-op for slices whose key field is constant, and the intended fix for permissions.

This pull request and its description were written by Isaac.

denik and others added 2 commits September 17, 2026 15:02
Keyed slices are matched by key value alone (the key field is only used to
render the path). A diff on a matched element's own key field therefore means
the two sides carry the same identity under a different field — e.g. a
permission declared under user_name that the Permissions API stores and returns
as service_principal_name — which is not a real change. Drop those field diffs;
non-key fields still diff normally.

This fixes a perpetual no-op "update" of dashboard/job/etc permissions when a
service principal is declared under user_name, generically for any keyed slice,
without per-resource logic. Alternative to the resource-level fix in #6710.

The testserver models the backend's user_name(UUID) -> service_principal_name
readback so the case reproduces locally.

Co-authored-by: Isaac <no-reply@databricks.com>
Co-authored-by: Isaac <no-reply@databricks.com>
@eng-dev-ecosystem-bot

eng-dev-ecosystem-bot commented Sep 17, 2026

Copy link
Copy Markdown
Collaborator

Integration test report

Commit: fcb6e08

Run: 35227338016

Env 🔄​flaky ✅​pass 🙈​skip Time
🔄​ aws linux 1 275 16 6:05
✅​ aws windows 278 14 4:04
✅​ azure linux 275 16 4:04
✅​ azure windows 277 14 3:43
✅​ gcp linux 276 16 4:35
✅​ gcp windows 278 14 3:44
Test Name aws linux
🔄​ TestSyncEnsureRemotePathIsUsableIfRepoExists 🔄​f
Top 3 slowest tests (at least 2 minutes):
duration env testname
4:02 aws windows TestAccept
3:42 gcp windows TestAccept
3:41 azure windows TestAccept

prepareChanges indexed changes by the full path string, so a keyed element
whose key field differs between the saved state and the backend (e.g. a
principal saved under user_name but read back as service_principal_name)
produced two half-populated change entries for one field. Index by the
key-field-agnostic path (structpath.KeyValueAgnosticString) so the local and
remote views merge into one entry; the displayed path stays the local one.

Also document the value-match / key-field-drop semantics on structdiff.KeyFunc
and cross-reference it from IResource.KeyedSlices.

Co-authored-by: Isaac <no-reply@databricks.com>

This branch has not been deployed

No deployments
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