Skip to content

Commit

Permalink
Merge pull request #4418 from sdowell/imagetag-trackable-filter
Browse files Browse the repository at this point in the history
Imagetag trackable filter
  • Loading branch information
k8s-ci-robot committed Jan 25, 2022
2 parents c754ead + 302cc86 commit c65ef48
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 20 deletions.
23 changes: 13 additions & 10 deletions api/filters/imagetag/imagetag.go
Expand Up @@ -23,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)
Expand All @@ -40,8 +48,11 @@ func (f Filter) filter(node *yaml.RNode) (*yaml.RNode, error) {
return node, nil
}
if err := node.PipeE(fsslice.Filter{
FsSlice: f.FsSlice,
SetValue: updateImageTagFn(f.ImageTag),
FsSlice: f.FsSlice,
SetValue: imageTagUpdater{
ImageTag: f.ImageTag,
trackableSetter: f.trackableSetter,
}.SetImageValue,
}); err != nil {
return nil, err
}
Expand All @@ -59,11 +70,3 @@ func (f Filter) isOnDenyList(node *yaml.RNode) bool {
// https://github.com/kubernetes-sigs/kustomize/issues/890
return meta.Kind == `CustomResourceDefinition`
}

func updateImageTagFn(imageTag types.Image) filtersutil.SetFn {
return func(node *yaml.RNode) error {
return node.PipeE(imageTagUpdater{
ImageTag: imageTag,
})
}
}
120 changes: 116 additions & 4 deletions api/filters/imagetag/imagetag_test.go
Expand Up @@ -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: `
Expand Down Expand Up @@ -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)
})
}
}
21 changes: 15 additions & 6 deletions api/filters/imagetag/updater.go
Expand Up @@ -4,6 +4,7 @@
package imagetag

import (
"sigs.k8s.io/kustomize/api/filters/filtersutil"
"sigs.k8s.io/kustomize/api/image"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/yaml"
Expand All @@ -13,19 +14,20 @@ 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) Filter(rn *yaml.RNode) (*yaml.RNode, error) {
func (u imageTagUpdater) SetImageValue(rn *yaml.RNode) error {
if err := yaml.ErrorIfInvalid(rn, yaml.ScalarNode); err != nil {
return nil, err
return err
}

value := rn.YNode().Value

if !image.IsImageMatched(value, u.ImageTag.Name) {
return rn, nil
return nil
}

name, tag := image.Split(value)
Expand All @@ -39,5 +41,12 @@ func (u imageTagUpdater) Filter(rn *yaml.RNode) (*yaml.RNode, error) {
tag = "@" + u.ImageTag.Digest
}

return rn.Pipe(yaml.FieldSetter{StringValue: name + tag})
return u.trackableSetter.SetScalar(name + tag)(rn)
}

func (u imageTagUpdater) Filter(rn *yaml.RNode) (*yaml.RNode, error) {
if err := u.SetImageValue(rn); err != nil {
return nil, err
}
return rn, nil
}

0 comments on commit c65ef48

Please sign in to comment.