Skip to content

kyaml merge2: $patch directives on list elements ignored with ListPrepend #6146

Description

@rm3l

/kind bug

Bug

When using merge2.MergeStrings with MergeOptions{ListIncreaseDirection: MergeOptionsListPrepend}, strategic merge patch directives ($patch: replace, $patch: delete) on individual associative list elements are silently ignored.

With default MergeOptions{} (Append), $patch: replace correctly replaces the matched list element. With ListPrepend, the original element remains unchanged and the replacement is dropped.

Root cause

In kyaml/yaml/walk/associative_sequence.go, setAssociativeSequenceElements() assembles the final list differently depending on the merge direction:

  • Append (correct): appendListNode(dest, itemsToBeAdded, ...); merged results from itemsToBeAdded overwrite originals in dest.
  • ListPrepend (buggy): appendListNode(itemsToBeAdded, dest, ...); the arguments are swapped for ordering, but this causes ElementSetter to overwrite already-merged items in itemsToBeAdded with the unmerged originals from dest, undoing $patch directive effects.

Reproduction

Minimal reproduction project: https://github.com/rm3l/kyaml-listprepend-bug

git clone https://github.com/rm3l/kyaml-listprepend-bug
cd kyaml-listprepend-bug
go test -v ./...
  • TestPatchReplaceWithDefaultMerge: PASS
  • TestPatchReplaceWithListPrepend: FAIL (the $patch: replace is ignored)

Versions affected

Tested and confirmed on:

  • sigs.k8s.io/kustomize/kyaml v0.18.1
  • sigs.k8s.io/kustomize/kyaml v0.19.0
  • sigs.k8s.io/kustomize/kyaml v0.21.0
  • sigs.k8s.io/kustomize/kyaml v0.21.1
  • Latest master commit (313aace, 2025-05-02)

Impact

This bug prevents combining ListPrepend (for controlling list item ordering) with $patch: replace or $patch: delete (for replacing/removing individual items by merge key). The two features are independent and should compose correctly IMHO.

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind/bugCategorizes issue or PR as related to a bug.needs-triageIndicates an issue or PR lacks a `triage/foo` label and requires one.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions