From 302cc866adcc6f4db00180fda9c3689b22893b97 Mon Sep 17 00:00:00 2001 From: Sam Dowell Date: Mon, 24 Jan 2022 22:37:31 +0000 Subject: [PATCH] implement TrackableFilter interface with imagetag This change updates the imagetag filter to implement the TrackableFilter interface. This provides the functionality for the user to track which fields were updated by the imagetag filter. --- api/filters/imagetag/imagetag.go | 14 ++- api/filters/imagetag/imagetag_test.go | 120 +++++++++++++++++++++++++- api/filters/imagetag/updater.go | 7 +- 3 files changed, 132 insertions(+), 9 deletions(-) diff --git a/api/filters/imagetag/imagetag.go b/api/filters/imagetag/imagetag.go index 699fdc18d..24ab99f74 100644 --- a/api/filters/imagetag/imagetag.go +++ b/api/filters/imagetag/imagetag.go @@ -4,6 +4,7 @@ package imagetag import ( + "sigs.k8s.io/kustomize/api/filters/filtersutil" "sigs.k8s.io/kustomize/api/filters/fsslice" "sigs.k8s.io/kustomize/api/types" "sigs.k8s.io/kustomize/kyaml/kio" @@ -22,9 +23,17 @@ type Filter struct { // FsSlice contains the FieldSpecs to locate an image field, // e.g. Path: "spec/myContainers[]/image" FsSlice types.FsSlice `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"` + + trackableSetter filtersutil.TrackableSetter } var _ kio.Filter = Filter{} +var _ kio.TrackableFilter = &Filter{} + +// WithMutationTracker registers a callback which will be invoked each time a field is mutated +func (f *Filter) WithMutationTracker(callback func(key, value, tag string, node *yaml.RNode)) { + f.trackableSetter.WithMutationTracker(callback) +} func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) { _, err := kio.FilterAll(yaml.FilterFunc(f.filter)).Filter(nodes) @@ -39,9 +48,10 @@ func (f Filter) filter(node *yaml.RNode) (*yaml.RNode, error) { return node, nil } if err := node.PipeE(fsslice.Filter{ - FsSlice: f.FsSlice, + FsSlice: f.FsSlice, SetValue: imageTagUpdater{ - ImageTag: f.ImageTag, + ImageTag: f.ImageTag, + trackableSetter: f.trackableSetter, }.SetImageValue, }); err != nil { return nil, err diff --git a/api/filters/imagetag/imagetag_test.go b/api/filters/imagetag/imagetag_test.go index 96d68366a..a62f95a9f 100644 --- a/api/filters/imagetag/imagetag_test.go +++ b/api/filters/imagetag/imagetag_test.go @@ -10,14 +10,35 @@ import ( "github.com/stretchr/testify/assert" filtertest "sigs.k8s.io/kustomize/api/testutils/filtertest" "sigs.k8s.io/kustomize/api/types" + "sigs.k8s.io/kustomize/kyaml/yaml" ) +type setValueArg struct { + Key string + Value string + Tag string + PrevValue string +} + +var setValueArgs []setValueArg + +func setValueCallbackStub(key, value, tag string, node *yaml.RNode) { + setValueArgs = append(setValueArgs, setValueArg{ + Key: key, + Value: value, + Tag: tag, + PrevValue: node.YNode().Value, + }) +} + func TestImageTagUpdater_Filter(t *testing.T) { testCases := map[string]struct { - input string - expectedOutput string - filter Filter - fsSlice types.FsSlice + input string + expectedOutput string + filter Filter + fsSlice types.FsSlice + setValueCallback func(key, value, tag string, node *yaml.RNode) + expectedSetValueArgs []setValueArg }{ "ignore CustomResourceDefinition": { input: ` @@ -658,17 +679,108 @@ spec: }, }, }, + "mutation tracker": { + input: ` +group: apps +apiVersion: v1 +kind: Deployment +metadata: + name: deploy1 +spec: + template: + spec: + containers: + - image: nginx:1.7.9 + name: nginx-tagged + - image: nginx:latest + name: nginx-latest + - image: foobar:1 + name: replaced-with-digest + - image: postgres:1.8.0 + name: postgresdb + initContainers: + - image: nginx + name: nginx-notag + - image: nginx@sha256:111111111111111111 + name: nginx-sha256 + - image: alpine:1.8.0 + name: init-alpine +`, + expectedOutput: ` +group: apps +apiVersion: v1 +kind: Deployment +metadata: + name: deploy1 +spec: + template: + spec: + containers: + - image: busybox:v3 + name: nginx-tagged + - image: busybox:v3 + name: nginx-latest + - image: foobar:1 + name: replaced-with-digest + - image: postgres:1.8.0 + name: postgresdb + initContainers: + - image: busybox:v3 + name: nginx-notag + - image: busybox:v3 + name: nginx-sha256 + - image: alpine:1.8.0 + name: init-alpine +`, + filter: Filter{ + ImageTag: types.Image{ + Name: "nginx", + NewName: "busybox", + NewTag: "v3", + }, + }, + fsSlice: []types.FieldSpec{ + { + Path: "spec/template/spec/containers[]/image", + }, + { + Path: "spec/template/spec/initContainers[]/image", + }, + }, + setValueCallback: setValueCallbackStub, + expectedSetValueArgs: []setValueArg{ + { + Value: "busybox:v3", + PrevValue: "nginx:1.7.9", + }, + { + Value: "busybox:v3", + PrevValue: "nginx:latest", + }, + { + Value: "busybox:v3", + PrevValue: "nginx", + }, + { + Value: "busybox:v3", + PrevValue: "nginx@sha256:111111111111111111", + }, + }, + }, } for tn, tc := range testCases { + setValueArgs = nil t.Run(tn, func(t *testing.T) { filter := tc.filter + filter.WithMutationTracker(tc.setValueCallback) filter.FsSlice = tc.fsSlice if !assert.Equal(t, strings.TrimSpace(tc.expectedOutput), strings.TrimSpace(filtertest.RunFilter(t, tc.input, filter))) { t.FailNow() } + assert.Equal(t, tc.expectedSetValueArgs, setValueArgs) }) } } diff --git a/api/filters/imagetag/updater.go b/api/filters/imagetag/updater.go index af8de4393..50c0dcdc8 100644 --- a/api/filters/imagetag/updater.go +++ b/api/filters/imagetag/updater.go @@ -14,8 +14,9 @@ import ( // that will update the value of the yaml node based on the provided // ImageTag if the current value matches the format of an image reference. type imageTagUpdater struct { - Kind string `yaml:"kind,omitempty"` - ImageTag types.Image `yaml:"imageTag,omitempty"` + Kind string `yaml:"kind,omitempty"` + ImageTag types.Image `yaml:"imageTag,omitempty"` + trackableSetter filtersutil.TrackableSetter } func (u imageTagUpdater) SetImageValue(rn *yaml.RNode) error { @@ -40,7 +41,7 @@ func (u imageTagUpdater) SetImageValue(rn *yaml.RNode) error { tag = "@" + u.ImageTag.Digest } - return filtersutil.SetScalar(name + tag)(rn) + return u.trackableSetter.SetScalar(name + tag)(rn) } func (u imageTagUpdater) Filter(rn *yaml.RNode) (*yaml.RNode, error) {