Wildcard support for creation in ReplacementTransformer (#4886)

* Ahead-of-time wildcard path expansion solution

* Wrapped PathGetter solution

This approach doesn't work when multiple existing sequence elements
should match, i.e. because the sequence contains maps and we're
searching on a key they all contain (target all containers with a certain
image would be one use case for this). PathGetter just takes the first
match in that case, which is not what we want.

* Add creation support to PathMatcher

* Regression test for existing bug when creation is enabled and sequence query should match multiple elements

* PathMatcher Create tests and support for sequence appending

* revert hyphen append support

PathGetter treats it as meaning 'last' not 'append' and does not have test coverage for its handling of this when create is set. Semantics are dubious given that multiple Replacement fieldPaths may be specified, which would cause successive appends.

* This also provides a solution to issue 1493

* Review feedback
This commit is contained in:
Katrina Verey
2022-12-06 15:40:37 -05:00
committed by GitHub
parent 2ed910abb0
commit 903fbb6ed2
5 changed files with 661 additions and 73 deletions

View File

@@ -550,7 +550,7 @@ func (l PathGetter) getFilter(part, nextPart string, fieldPath *[]string) (Filte
default:
// mapping node
*fieldPath = append(*fieldPath, part)
return l.fieldFilter(part, l.getKind(nextPart))
return l.fieldFilter(part, getPathPartKind(nextPart, l.Create))
}
}
@@ -590,15 +590,18 @@ func (l PathGetter) fieldFilter(
return FieldMatcher{Name: name, Create: &RNode{value: &yaml.Node{Kind: kind, Style: l.Style}}}, nil
}
func (l PathGetter) getKind(nextPart string) yaml.Kind {
func getPathPartKind(nextPart string, defaultKind yaml.Kind) yaml.Kind {
if IsListIndex(nextPart) {
// if nextPart is of the form [a=b], then it is an index into a Sequence
// so the current part must be a SequenceNode
return yaml.SequenceNode
}
if IsIdxNumber(nextPart) {
return yaml.SequenceNode
}
if nextPart == "" {
// final name in the path, use the l.Create defined Kind
return l.Create
// final name in the path, use the default kind provided
return defaultKind
}
// non-sequence intermediate Node