Skip to content

fix(kyaml): correctly handle patches with a partial compound merge key#6192

Open
SetagGnaw wants to merge 2 commits into
kubernetes-sigs:masterfrom
SetagGnaw:test-partial-compound-merge-key-drop
Open

fix(kyaml): correctly handle patches with a partial compound merge key#6192
SetagGnaw wants to merge 2 commits into
kubernetes-sigs:masterfrom
SetagGnaw:test-partial-compound-merge-key-drop

Conversation

@SetagGnaw

Copy link
Copy Markdown

What this fixes

When a strategic merge patch targets an element of an associative list by only
part of a compound merge key, kustomize loses or corrupts data. With the
[port, protocol] merge key for Service ports ([containerPort, protocol] for
container ports), a patch that omits protocol:

  • loses an added field when it matches an existing port and adds a field;
  • drops the partial entries entirely when the patch lists several ports and
    some omit protocol while sharing a port number with a sibling that supplies
    it (patchesStrategicMerge is not working for service of single port but multiple protocols. #4752); and
  • fails to update the matching element and leave its sibling intact when the
    base holds two elements sharing the port (e.g. 8080/TCP and 8080/UDP).

Root cause

kustomize resolves an associative list's merge key to the compound
x-kubernetes-list-map-keys (e.g. [port, protocol]). A patch that specifies
only part of that key was mishandled in setAssociativeSequenceElements
(kyaml/yaml/walk/associative_sequence.go): the partial key either could not be
re-matched, so the element's data was dropped, or it matched every element
sharing the specified component, clobbering a sibling that differs only by
another component.

The fix

Match each element on the key it actually specifies:

  • when the element populates the full compound key, use it;
  • otherwise fall back to the single strategic-merge-patch merge key the schema
    declares for the list (x-kubernetes-patch-merge-key, e.g. port), which is
    the key the SMP path is meant to use.

A merged element is then re-keyed on the full key it now populates
(elementKeyValues) so it replaces its exact counterpart instead of every
element sharing the partial key, and the full compound key is passed to
appendListNode.

Net behavior: a partial-key patch merges into a single matching element (or
appends as a distinct element when none match), and same-port siblings are
preserved rather than clobbered or duplicated.

Testing

Three cases added to TestMerge in kyaml/yaml/merge2/map_test.go, all failing
before the fix and passing after:

  • port patch adds a field but omits protocol (partial compound key)
  • patch with multiple ports, some omitting protocol (#4752)
  • partial-key patch when base has two elements sharing the port (ambiguous)

go test ./yaml/merge2/... and the full kyaml suite pass. Two-commit
bug-fix convention: the first commit adds the failing tests, the second applies
the fix.

Related issues

Fixes #4752

@kubernetes-prow

Copy link
Copy Markdown
Contributor

This PR has multiple commits, and the default merge method is: merge.
You can request commits to be squashed using the label: tide/merge-method-squash

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@kubernetes-prow kubernetes-prow Bot added the do-not-merge/invalid-commit-message Indicates that a PR should not merge because it has an invalid commit message. label Jul 19, 2026
@kubernetes-prow

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: SetagGnaw
Once this PR has been reviewed and has the lgtm label, please assign varshaprasad96 for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@kubernetes-prow kubernetes-prow Bot added cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Jul 19, 2026
@kubernetes-prow

Copy link
Copy Markdown
Contributor

Hi @SetagGnaw. Thanks for your PR.

I'm waiting for a kubernetes-sigs member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work.

Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@kubernetes-prow kubernetes-prow Bot added the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label Jul 19, 2026
@SetagGnaw
SetagGnaw force-pushed the test-partial-compound-merge-key-drop branch from 1ccac38 to 36c1998 Compare July 19, 2026 20:58
A strategic merge patch that specifies only part of a compound merge
key loses data. With the [port, protocol] merge key for Service ports,
a patch that omits protocol:

- loses an added field when it matches an existing port and adds a
  field;
- drops the partial entries entirely when several ports are patched and
  some omit protocol while sharing a port number with a sibling that
  supplies it (issue 4752); and
- fails to update the matching element while leaving the sibling intact
  when the base holds two elements sharing the port (TCP and UDP).

Added to mapTestCases in kyaml/yaml/merge2/map_test.go; all fail
against the current merge logic.
kustomize resolves an associative list's merge key to the compound
x-kubernetes-list-map-keys (e.g. [port, protocol] for Service ports).
A strategic merge patch that specifies only part of that key was
mishandled: the partial key could not be re-matched and its data was
dropped, or it matched every element sharing the specified component
and clobbered a sibling that differs only by another component.

Match each element on the key it actually specifies. When it populates
the full compound key, use it; otherwise fall back to the single
strategic-merge-patch merge key the schema declares
(x-kubernetes-patch-merge-key, e.g. port), which is the key the SMP
path is meant to use. A merged element is re-keyed on the full key it
now populates (elementKeyValues) so it replaces its exact counterpart,
and the full compound key is passed to appendListNode. A partial-key
patch now merges into a single matching element or appends as distinct;
an element that specifies neither the full key nor the SMP key is left
alone rather than clobbering an unrelated element.
@SetagGnaw
SetagGnaw force-pushed the test-partial-compound-merge-key-drop branch from 36c1998 to 85c4e2e Compare July 19, 2026 21:01
@kubernetes-prow kubernetes-prow Bot removed the do-not-merge/invalid-commit-message Indicates that a PR should not merge because it has an invalid commit message. label Jul 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

patchesStrategicMerge is not working for service of single port but multiple protocols.

1 participant