Skip to content

Commit

Permalink
fix: set FieldPath for SequenceNode elements
Browse files Browse the repository at this point in the history
The FieldPath was not being set for nodes underneath a SequenceNode
during fieldspec's traversal. This is in part because handleSequence
uses VisitElements in contrast to a PathGetter as is done by handleMap.

The accuracy of FieldPath is more relevant now with the recently added
support of mutation trackers in filtersutil. This change fixes the
case where a mutation tracker callback is called on a SequenceNode
element and the node does not have an accurate FieldPath value.
  • Loading branch information
sdowell committed Jan 26, 2022
1 parent c65ef48 commit 9abf5fc
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 0 deletions.
2 changes: 2 additions & 0 deletions api/filters/fieldspec/fieldspec.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ func (fltr Filter) handleMap(obj *yaml.RNode) error {
// seq calls filter on all sequence elements
func (fltr Filter) handleSequence(obj *yaml.RNode) error {
if err := obj.VisitElements(func(node *yaml.RNode) error {
// set an accurate FieldPath for nested elements
node.AppendToFieldPath(obj.FieldPath()...)
// recurse on each element -- re-allocating a Filter is
// not strictly required, but is more consistent with field
// and less likely to have side effects
Expand Down
82 changes: 82 additions & 0 deletions api/filters/fieldspec/fieldspec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -558,3 +558,85 @@ a:
})
}
}

func TestFilter_FieldPaths(t *testing.T) {
testCases := map[string]struct {
input string
fieldSpec string
expected []string
}{
"fieldpath containing SequenceNode": {
input: `
apiVersion: v1
kind: Pod
metadata:
name: app
spec:
containers:
- name: store
image: redis:6.2.6
- name: server
image: nginx:latest
`,
fieldSpec: `
path: spec/containers[]/image
kind: Pod
`,
expected: []string{
"spec.containers.image",
"spec.containers.image",
},
},
"fieldpath with MappingNode": {
input: `
apiVersion: v1
kind: Pod
metadata:
name: app
spec:
containers:
- name: store
image: redis:6.2.6
- name: server
image: nginx:latest
`,
fieldSpec: `
path: metadata/name
kind: Pod
`,
expected: []string{
"metadata.name",
},
},
}
for name, tc := range testCases {
var fieldPaths []string
trackableSetter := filtersutil.TrackableSetter{}
trackableSetter.WithMutationTracker(func(key, value, tag string, node *yaml.RNode) {
fieldPaths = append(fieldPaths, strings.Join(node.FieldPath(), "."))
})
filter := fieldspec.Filter{
SetValue: trackableSetter.SetScalar("foo"),
}

t.Run(name, func(t *testing.T) {
err := yaml.Unmarshal([]byte(tc.fieldSpec), &filter.FieldSpec)
assert.NoError(t, err)
rw := &kio.ByteReadWriter{
Reader: bytes.NewBufferString(tc.input),
Writer: &bytes.Buffer{},
OmitReaderAnnotations: true,
}

// run the filter
err = kio.Pipeline{
Inputs: []kio.Reader{rw},
Filters: []kio.Filter{kio.FilterAll(filter)},
Outputs: []kio.Writer{rw},
}.Execute()

assert.NoError(t, err)
assert.Equal(t, tc.expected, fieldPaths)
})
}
}

0 comments on commit 9abf5fc

Please sign in to comment.