Convert image transformer to kyaml.

This commit is contained in:
jregan
2020-07-18 06:53:12 -07:00
parent 46a6bf0bb4
commit ef924a5c9c
8 changed files with 107 additions and 49 deletions

View File

@@ -8,10 +8,10 @@ import (
"regexp" "regexp"
"strings" "strings"
"sigs.k8s.io/kustomize/api/transform" "sigs.k8s.io/kustomize/api/filters/imagetag"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/api/resmap" "sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/filtersutil"
"sigs.k8s.io/yaml" "sigs.k8s.io/yaml"
) )
@@ -31,18 +31,18 @@ func (p *ImageTagTransformerPlugin) Config(
func (p *ImageTagTransformerPlugin) Transform(m resmap.ResMap) error { func (p *ImageTagTransformerPlugin) Transform(m resmap.ResMap) error {
for _, r := range m.Resources() { for _, r := range m.Resources() {
for _, path := range p.FieldSpecs { // If you're here because someone expected any field containing
if !r.OrgId().IsSelected(&path.Gvk) { // the string "containers" or "initContainers" to get an image
continue // update (not just spec/template/spec/containers[], etc.) then
} // a code change is needed. See api/filters/imagetag/legacy
err := transform.MutateField( // for the start of an implementation that won't use an
r.Map(), path.PathSlice(), false, p.mutateImage) // allowlist like FsSlice, and instead walks the object looking
if err != nil { // for fields named containers or initContainers.
return err err := filtersutil.ApplyToJSON(imagetag.Filter{
} ImageTag: p.ImageTag,
} FsSlice: p.FieldSpecs,
// Kept for backward compatibility }, r)
if err := p.findAndReplaceImage(r.Map()); err != nil && r.OrgId().Kind != `CustomResourceDefinition` { if err != nil {
return err return err
} }
} }

View File

@@ -11,11 +11,17 @@ import (
"sigs.k8s.io/kustomize/kyaml/yaml" "sigs.k8s.io/kustomize/kyaml/yaml"
) )
// Filter modifies an "image tag", the value used to specify the
// name, tag, version digest etc. of (docker) container images
// used by a pod template.
type Filter struct { type Filter struct {
// imageTag is the tag we want to apply to the inputs // imageTag is the tag we want to apply to the inputs
// The name of the image is used as a key, and other fields
// can specify a new name, tag, etc.
ImageTag types.Image `json:"imageTag,omitempty" yaml:"imageTag,omitempty"` ImageTag types.Image `json:"imageTag,omitempty" yaml:"imageTag,omitempty"`
// FsSlice contains the FieldSpecs to locate the namespace field // FsSlice contains the FieldSpecs to locate an image field,
// e.g. Path: "spec/myContainers[]/image"
FsSlice types.FsSlice `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"` FsSlice types.FsSlice `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
} }
@@ -27,6 +33,12 @@ func (f Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
} }
func (f Filter) filter(node *yaml.RNode) (*yaml.RNode, error) { func (f Filter) filter(node *yaml.RNode) (*yaml.RNode, error) {
// FsSlice is an allowlist, not a denyList, so to deny
// something via configuration a new config mechanism is
// needed. Until then, hardcode it.
if f.isOnDenyList(node) {
return node, nil
}
if err := node.PipeE(fsslice.Filter{ if err := node.PipeE(fsslice.Filter{
FsSlice: f.FsSlice, FsSlice: f.FsSlice,
SetValue: updateImageTagFn(f.ImageTag), SetValue: updateImageTagFn(f.ImageTag),
@@ -36,6 +48,18 @@ func (f Filter) filter(node *yaml.RNode) (*yaml.RNode, error) {
return node, nil return node, nil
} }
func (f Filter) isOnDenyList(node *yaml.RNode) bool {
meta, err := node.GetMeta()
if err != nil {
// A missing 'meta' field will cause problems elsewhere;
// ignore it here to keep the signature simple.
return false
}
// Ignore CRDs
// https://github.com/kubernetes-sigs/kustomize/issues/890
return meta.Kind == `CustomResourceDefinition`
}
func updateImageTagFn(imageTag types.Image) filtersutil.SetFn { func updateImageTagFn(imageTag types.Image) filtersutil.SetFn {
return func(node *yaml.RNode) error { return func(node *yaml.RNode) error {
return node.PipeE(imageTagUpdater{ return node.PipeE(imageTagUpdater{

View File

@@ -36,7 +36,7 @@ metadata:
name: whatever name: whatever
spec: spec:
containers: containers:
- image: theImageShouldNotChangeInACrd - image: whatever
`, `,
filter: Filter{ filter: Filter{
ImageTag: types.Image{ ImageTag: types.Image{
@@ -139,7 +139,7 @@ spec:
- image: nginx:1.2.1 - image: nginx:1.2.1
- image: tomcat:1.2.3 - image: tomcat:1.2.3
template: template:
spec: spec:
initContainers: initContainers:
- image: nginx:1.2.1 - image: nginx:1.2.1
- image: apache:1.2.3 - image: apache:1.2.3

View File

@@ -4,7 +4,15 @@
package builtinpluginconsts package builtinpluginconsts
const ( const (
// imageFieldSpecs is left empty since `containers` and `initContainers` imagesFieldSpecs = `
// of *ANY* kind in *ANY* path are builtin supported in code images:
imagesFieldSpecs = `` - path: spec/containers[]/image
create: true
- path: spec/initContainers[]/image
create: true
- path: spec/template/spec/containers[]/image
create: true
- path: spec/template/spec/initContainers[]/image
create: true
`
) )

View File

@@ -173,6 +173,9 @@ spec:
`) `)
} }
// The default configuration recognizes image paths starting
// with "spec", not spec2 or spec3, so the latter two specs won't
// have their image entries changed.
func TestTransfomersImageDefaultConfig(t *testing.T) { func TestTransfomersImageDefaultConfig(t *testing.T) {
th := kusttest_test.MakeHarness(t) th := kusttest_test.MakeHarness(t)
makeTransfomersImageBase(th) makeTransfomersImageBase(th)
@@ -212,25 +215,25 @@ spec2:
template: template:
spec: spec:
containers: containers:
- image: nginx:v2 - image: nginx:v1
name: nginx3 name: nginx3
- image: my-nginx:previous - image: my-nginx:latest
name: nginx4 name: nginx4
spec3: spec3:
template: template:
spec: spec:
initContainers: initContainers:
- image: my-postgres:v3 - image: postgres:alpine-9
name: postgresdb name: postgresdb
- image: my-docker@sha256:25a0d4b4 - image: docker:17-git
name: init-docker name: init-docker
- image: myprivaterepohostname:1234/my/image:v1.0.1 - image: myprivaterepohostname:1234/my/image:latest
name: myImage name: myImage
- image: myprivaterepohostname:1234/my/image:v1.0.1 - image: myprivaterepohostname:1234/my/image
name: myImage2 name: myImage2
- image: my-app-image:v1 - image: my-app-image:v1
name: my-app name: my-app
- image: my-cool-app:latest - image: gcr.io:8080/my-project/my-cool-app:latest
name: my-cool-app name: my-cool-app
`) `)
} }
@@ -299,11 +302,11 @@ spec3:
th.WriteF("/app/base/config/custom.yaml", ` th.WriteF("/app/base/config/custom.yaml", `
images: images:
- kind: Custom - kind: Custom
path: spec/template/spec/myContainers/image path: spec/template/spec/myContainers[]/image
- kind: Custom - kind: Custom
path: spec2/template/spec/myContainers/image path: spec2/template/spec/myContainers[]/image
- kind: Custom - kind: Custom
path: spec3/template/spec/myInitContainers/image path: spec3/template/spec/myInitContainers[]/image
`) `)
} }

View File

@@ -9,10 +9,10 @@ import (
"regexp" "regexp"
"strings" "strings"
"sigs.k8s.io/kustomize/api/transform" "sigs.k8s.io/kustomize/api/filters/imagetag"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/api/resmap" "sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/filtersutil"
"sigs.k8s.io/yaml" "sigs.k8s.io/yaml"
) )
@@ -35,18 +35,18 @@ func (p *plugin) Config(
func (p *plugin) Transform(m resmap.ResMap) error { func (p *plugin) Transform(m resmap.ResMap) error {
for _, r := range m.Resources() { for _, r := range m.Resources() {
for _, path := range p.FieldSpecs { // If you're here because someone expected any field containing
if !r.OrgId().IsSelected(&path.Gvk) { // the string "containers" or "initContainers" to get an image
continue // update (not just spec/template/spec/containers[], etc.) then
} // a code change is needed. See api/filters/imagetag/legacy
err := transform.MutateField( // for the start of an implementation that won't use an
r.Map(), path.PathSlice(), false, p.mutateImage) // allowlist like FsSlice, and instead walks the object looking
if err != nil { // for fields named containers or initContainers.
return err err := filtersutil.ApplyToJSON(imagetag.Filter{
} ImageTag: p.ImageTag,
} FsSlice: p.FieldSpecs,
// Kept for backward compatibility }, r)
if err := p.findAndReplaceImage(r.Map()); err != nil && r.OrgId().Kind != `CustomResourceDefinition` { if err != nil {
return err return err
} }
} }

View File

@@ -22,6 +22,9 @@ metadata:
imageTag: imageTag:
name: nginx name: nginx
newTag: v2 newTag: v2
fieldSpecs:
- path: spec/template/spec/containers[]/image
- path: spec/template/spec/initContainers[]/image
`, ` `, `
group: apps group: apps
apiVersion: v1 apiVersion: v1
@@ -89,6 +92,9 @@ metadata:
imageTag: imageTag:
name: nginx name: nginx
newName: busybox newName: busybox
fieldSpecs:
- path: spec/template/spec/containers[]/image
- path: spec/template/spec/initContainers[]/image
`, ` `, `
group: apps group: apps
apiVersion: v1 apiVersion: v1
@@ -158,6 +164,9 @@ imageTag:
name: nginx name: nginx
newName: busybox newName: busybox
newTag: v2 newTag: v2
fieldSpecs:
- path: spec/template/spec/containers[]/image
- path: spec/template/spec/initContainers[]/image
`, ` `, `
group: apps group: apps
apiVersion: v1 apiVersion: v1
@@ -226,6 +235,9 @@ metadata:
imageTag: imageTag:
name: nginx name: nginx
Digest: sha256:222222222222222222 Digest: sha256:222222222222222222
fieldSpecs:
- path: spec/template/spec/containers[]/image
- path: spec/template/spec/initContainers[]/image
`, ` `, `
group: apps group: apps
apiVersion: v1 apiVersion: v1
@@ -295,6 +307,9 @@ imageTag:
name: nginx name: nginx
newName: busybox newName: busybox
Digest: sha256:222222222222222222 Digest: sha256:222222222222222222
fieldSpecs:
- path: spec/template/spec/containers[]/image
- path: spec/template/spec/initContainers[]/image
`, ` `, `
group: apps group: apps
apiVersion: v1 apiVersion: v1
@@ -363,6 +378,11 @@ metadata:
imageTag: imageTag:
name: nginx name: nginx
newTag: v2 newTag: v2
fieldSpecs:
- path: spec/template/spec/containers[]/image
create: true
- path: spec/template/spec/initContainers[]/image
create: true
`, ` `, `
group: apps group: apps
apiVersion: v1 apiVersion: v1
@@ -384,8 +404,8 @@ metadata:
spec: spec:
template: template:
spec: spec:
containers: null containers: []
initContainers: null initContainers: []
`) `)
} }
@@ -402,6 +422,8 @@ metadata:
imageTag: imageTag:
name: some.registry.io/my-image name: some.registry.io/my-image
newTag: "my-fixed-tag" newTag: "my-fixed-tag"
fieldSpecs:
- path: spec/template/spec/containers[]/image
`, ` `, `
group: apps group: apps
apiVersion: v1 apiVersion: v1
@@ -429,4 +451,4 @@ spec:
- image: some.registry.io/my-image:my-fixed-tag - image: some.registry.io/my-image:my-fixed-tag
name: my-image name: my-image
`) `)
} }

View File

@@ -4,6 +4,7 @@ go 1.14
require ( require (
sigs.k8s.io/kustomize/api v0.5.1 sigs.k8s.io/kustomize/api v0.5.1
sigs.k8s.io/kustomize/kyaml v0.4.1
sigs.k8s.io/yaml v1.2.0 sigs.k8s.io/yaml v1.2.0
) )