Skip to content

fix: don't clobber non-ignored fields on "replace"#27136

Open
blakepettersson wants to merge 4 commits into
argoproj:masterfrom
blakepettersson:fix/pdb-ignoredifferences
Open

fix: don't clobber non-ignored fields on "replace"#27136
blakepettersson wants to merge 4 commits into
argoproj:masterfrom
blakepettersson:fix/pdb-ignoredifferences

Conversation

@blakepettersson
Copy link
Copy Markdown
Member

@blakepettersson blakepettersson commented Apr 2, 2026

When normalizeTargetResources computes the live-to-target patch for RespectIgnoreDifferences, it uses strategic merge patch. For resources whose fields carry patchStrategy:"replace" (e.g. policy/v1 PDB spec.selector), strategic merge treats the entire field as atomic — so patching in one ignored sub-field (say, a single matchLabels key) pulls the entire parent from the live object, overwriting non-ignored sibling fields that the user intentionally changed.

Add a post-correction step that walks the patched target against the original target and normalized target. If a field was not touched by the normalizer (normalized == original) but was overwritten by the patch (patched != original), restore the original target value. This surgically undoes collateral damage from replace semantics without affecting array merge behavior.

Currently only policy/v1 PDB spec.selector uses patchStrategy:"replace" among built-in types, but the fix is generic and will also cover CRDs with x-kubernetes-patch-strategy: replace when OpenAPI-based patching is re-introduced. Fixes #18232.

Checklist:

  • Either (a) I've created an enhancement proposal and discussed it with the community, (b) this is a bug fix, or (c) this does not need to be in the release notes.
  • The title of the PR states what changed and the related issues number (used for the release note).
  • The title of the PR conforms to the Title of the PR
  • I've included "Closes [ISSUE #]" or "Fixes [ISSUE #]" in the description to automatically close the associated issue.
  • I've updated both the CLI and UI to expose my feature, or I plan to submit a second PR with them.
  • Does this PR require documentation updates?
  • I've updated documentation as required by this PR.
  • I have signed off all my commits as required by DCO
  • I have written unit and/or e2e tests for my change. PRs without these are unlikely to be merged.
  • My build is green (troubleshooting builds).
  • My new feature complies with the feature status guidelines.
  • I have added a brief description of why this PR is necessary and/or what this PR solves.
  • Optional. My organization is added to USERS.md.
  • Optional. For bug fixes, I've indicated what older releases this fix should be cherry-picked into (this may or may not happen depending on risk/complexity).

When normalizeTargetResources computes the live-to-target patch for
RespectIgnoreDifferences, it uses strategic merge patch. For resources
whose fields carry `patchStrategy:"replace"` (e.g. `policy/v1` PDB
`spec.selector`), strategic merge treats the entire field as atomic — so
patching in one ignored sub-field (say, a single `matchLabels` key) pulls
the entire parent from the live object, overwriting non-ignored sibling
fields that the user intentionally changed.

Add a post-correction step that walks the patched target against the
original target and normalized target. If a field was not touched by the
normalizer (`normalized == original`) but was overwritten by the patch
(`patched != original`), restore the original target value. This surgically
undoes collateral damage from replace semantics without affecting array
merge behavior.

Currently only `policy/v1` PDB `spec.selector` uses `patchStrategy:"replace"`
among built-in types, but the fix is generic and will also cover CRDs
with `x-kubernetes-patch-strategy: replace` when OpenAPI-based patching is
re-introduced. Fixes argoproj#18232.

Signed-off-by: Blake Pettersson <blake.pettersson@gmail.com>
Copilot AI review requested due to automatic review settings April 2, 2026 23:42
@blakepettersson blakepettersson requested a review from a team as a code owner April 2, 2026 23:42
@bunnyshell
Copy link
Copy Markdown

bunnyshell Bot commented Apr 2, 2026

❌ Preview Environment undeployed from Bunnyshell

Available commands (reply to this comment):

  • 🚀 /bns:deploy to deploy the environment

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes a normalization/patching edge case where strategic merge patch patchStrategy:"replace" fields (notably policy/v1 PodDisruptionBudget spec.selector) cause RespectIgnoreDifferences patching to overwrite non-ignored sibling fields in the target.

Changes:

  • Adds a post-patch correction step in normalizeTargetResources to restore non-ignored fields that were unintentionally overwritten due to patchStrategy:"replace".
  • Introduces a regression test reproducing #18232 using new live/target PDB fixtures.
  • Embeds new PDB YAML testdata into the controller testdata package.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
controller/sync.go Adds restoreNonIgnoredFields and applies it after merge-patching to prevent clobbering non-ignored fields under replace semantics.
controller/sync_test.go Adds a regression test for PDB selector behavior with RespectIgnoreDifferences=true.
controller/testdata/data.go Embeds the new PDB YAML fixtures for tests.
controller/testdata/live-pdb.yaml Live PDB fixture representing the cluster state used in the regression test.
controller/testdata/target-pdb.yaml Target PDB fixture representing the desired state used in the regression test.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread controller/sync.go Outdated
Comment thread controller/sync_test.go
Signed-off-by: Blake Pettersson <blake.pettersson@gmail.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread controller/sync.go Outdated
Comment thread controller/sync_test.go
Signed-off-by: Blake Pettersson <blake.pettersson@gmail.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread controller/sync.go Outdated
Signed-off-by: Blake Pettersson <blake.pettersson@gmail.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 3, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 63.36%. Comparing base (3eebbcb) to head (038ba21).
⚠️ Report is 185 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #27136      +/-   ##
==========================================
+ Coverage   63.23%   63.36%   +0.12%     
==========================================
  Files         415      415              
  Lines       56545    56569      +24     
==========================================
+ Hits        35759    35845      +86     
+ Misses      17408    17345      -63     
- Partials     3378     3379       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Comment thread controller/sync_test.go
// When a PDB (policy/v1) has an ignoreDifferences rule for a matchLabels sub-field and
// RespectIgnoreDifferences=true is set, normalizeTargetResources should only patch the
// ignored field — not clobber the entire selector due to patchStrategy:"replace".
func TestNormalizeTargetResourcesPDBSelector(t *testing.T) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should we add a test case when server side apply is enabled + respect ignore diff? I would assume the server handles all the diffing/merging and we wouldn't need to handle any of the replace logic?

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.

PodDisruptionBudget not syncing with RespectIgnoreDifferences flag

3 participants