mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-12 01:14:22 +00:00
Convert image transformer to kyaml.
This commit is contained in:
@@ -8,10 +8,10 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"sigs.k8s.io/kustomize/api/transform"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
|
||||
"sigs.k8s.io/kustomize/api/filters/imagetag"
|
||||
"sigs.k8s.io/kustomize/api/resmap"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
"sigs.k8s.io/kustomize/kyaml/filtersutil"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
@@ -31,18 +31,18 @@ func (p *ImageTagTransformerPlugin) Config(
|
||||
|
||||
func (p *ImageTagTransformerPlugin) Transform(m resmap.ResMap) error {
|
||||
for _, r := range m.Resources() {
|
||||
for _, path := range p.FieldSpecs {
|
||||
if !r.OrgId().IsSelected(&path.Gvk) {
|
||||
continue
|
||||
}
|
||||
err := transform.MutateField(
|
||||
r.Map(), path.PathSlice(), false, p.mutateImage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// Kept for backward compatibility
|
||||
if err := p.findAndReplaceImage(r.Map()); err != nil && r.OrgId().Kind != `CustomResourceDefinition` {
|
||||
// If you're here because someone expected any field containing
|
||||
// the string "containers" or "initContainers" to get an image
|
||||
// update (not just spec/template/spec/containers[], etc.) then
|
||||
// a code change is needed. See api/filters/imagetag/legacy
|
||||
// for the start of an implementation that won't use an
|
||||
// allowlist like FsSlice, and instead walks the object looking
|
||||
// for fields named containers or initContainers.
|
||||
err := filtersutil.ApplyToJSON(imagetag.Filter{
|
||||
ImageTag: p.ImageTag,
|
||||
FsSlice: p.FieldSpecs,
|
||||
}, r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,11 +11,17 @@ import (
|
||||
"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 {
|
||||
// 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"`
|
||||
|
||||
// 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"`
|
||||
}
|
||||
|
||||
@@ -27,6 +33,12 @@ func (f Filter) Filter(nodes []*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{
|
||||
FsSlice: f.FsSlice,
|
||||
SetValue: updateImageTagFn(f.ImageTag),
|
||||
@@ -36,6 +48,18 @@ func (f Filter) filter(node *yaml.RNode) (*yaml.RNode, error) {
|
||||
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 {
|
||||
return func(node *yaml.RNode) error {
|
||||
return node.PipeE(imageTagUpdater{
|
||||
|
||||
@@ -36,7 +36,7 @@ metadata:
|
||||
name: whatever
|
||||
spec:
|
||||
containers:
|
||||
- image: theImageShouldNotChangeInACrd
|
||||
- image: whatever
|
||||
`,
|
||||
filter: Filter{
|
||||
ImageTag: types.Image{
|
||||
|
||||
@@ -4,7 +4,15 @@
|
||||
package builtinpluginconsts
|
||||
|
||||
const (
|
||||
// imageFieldSpecs is left empty since `containers` and `initContainers`
|
||||
// of *ANY* kind in *ANY* path are builtin supported in code
|
||||
imagesFieldSpecs = ``
|
||||
imagesFieldSpecs = `
|
||||
images:
|
||||
- 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
|
||||
`
|
||||
)
|
||||
|
||||
@@ -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) {
|
||||
th := kusttest_test.MakeHarness(t)
|
||||
makeTransfomersImageBase(th)
|
||||
@@ -212,25 +215,25 @@ spec2:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- image: nginx:v2
|
||||
- image: nginx:v1
|
||||
name: nginx3
|
||||
- image: my-nginx:previous
|
||||
- image: my-nginx:latest
|
||||
name: nginx4
|
||||
spec3:
|
||||
template:
|
||||
spec:
|
||||
initContainers:
|
||||
- image: my-postgres:v3
|
||||
- image: postgres:alpine-9
|
||||
name: postgresdb
|
||||
- image: my-docker@sha256:25a0d4b4
|
||||
- image: docker:17-git
|
||||
name: init-docker
|
||||
- image: myprivaterepohostname:1234/my/image:v1.0.1
|
||||
- image: myprivaterepohostname:1234/my/image:latest
|
||||
name: myImage
|
||||
- image: myprivaterepohostname:1234/my/image:v1.0.1
|
||||
- image: myprivaterepohostname:1234/my/image
|
||||
name: myImage2
|
||||
- image: my-app-image:v1
|
||||
name: my-app
|
||||
- image: my-cool-app:latest
|
||||
- image: gcr.io:8080/my-project/my-cool-app:latest
|
||||
name: my-cool-app
|
||||
`)
|
||||
}
|
||||
@@ -299,11 +302,11 @@ spec3:
|
||||
th.WriteF("/app/base/config/custom.yaml", `
|
||||
images:
|
||||
- kind: Custom
|
||||
path: spec/template/spec/myContainers/image
|
||||
path: spec/template/spec/myContainers[]/image
|
||||
- kind: Custom
|
||||
path: spec2/template/spec/myContainers/image
|
||||
path: spec2/template/spec/myContainers[]/image
|
||||
- kind: Custom
|
||||
path: spec3/template/spec/myInitContainers/image
|
||||
path: spec3/template/spec/myInitContainers[]/image
|
||||
`)
|
||||
}
|
||||
|
||||
|
||||
@@ -9,10 +9,10 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"sigs.k8s.io/kustomize/api/transform"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
|
||||
"sigs.k8s.io/kustomize/api/filters/imagetag"
|
||||
"sigs.k8s.io/kustomize/api/resmap"
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
"sigs.k8s.io/kustomize/kyaml/filtersutil"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
@@ -35,18 +35,18 @@ func (p *plugin) Config(
|
||||
|
||||
func (p *plugin) Transform(m resmap.ResMap) error {
|
||||
for _, r := range m.Resources() {
|
||||
for _, path := range p.FieldSpecs {
|
||||
if !r.OrgId().IsSelected(&path.Gvk) {
|
||||
continue
|
||||
}
|
||||
err := transform.MutateField(
|
||||
r.Map(), path.PathSlice(), false, p.mutateImage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// Kept for backward compatibility
|
||||
if err := p.findAndReplaceImage(r.Map()); err != nil && r.OrgId().Kind != `CustomResourceDefinition` {
|
||||
// If you're here because someone expected any field containing
|
||||
// the string "containers" or "initContainers" to get an image
|
||||
// update (not just spec/template/spec/containers[], etc.) then
|
||||
// a code change is needed. See api/filters/imagetag/legacy
|
||||
// for the start of an implementation that won't use an
|
||||
// allowlist like FsSlice, and instead walks the object looking
|
||||
// for fields named containers or initContainers.
|
||||
err := filtersutil.ApplyToJSON(imagetag.Filter{
|
||||
ImageTag: p.ImageTag,
|
||||
FsSlice: p.FieldSpecs,
|
||||
}, r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,9 @@ metadata:
|
||||
imageTag:
|
||||
name: nginx
|
||||
newTag: v2
|
||||
fieldSpecs:
|
||||
- path: spec/template/spec/containers[]/image
|
||||
- path: spec/template/spec/initContainers[]/image
|
||||
`, `
|
||||
group: apps
|
||||
apiVersion: v1
|
||||
@@ -89,6 +92,9 @@ metadata:
|
||||
imageTag:
|
||||
name: nginx
|
||||
newName: busybox
|
||||
fieldSpecs:
|
||||
- path: spec/template/spec/containers[]/image
|
||||
- path: spec/template/spec/initContainers[]/image
|
||||
`, `
|
||||
group: apps
|
||||
apiVersion: v1
|
||||
@@ -158,6 +164,9 @@ imageTag:
|
||||
name: nginx
|
||||
newName: busybox
|
||||
newTag: v2
|
||||
fieldSpecs:
|
||||
- path: spec/template/spec/containers[]/image
|
||||
- path: spec/template/spec/initContainers[]/image
|
||||
`, `
|
||||
group: apps
|
||||
apiVersion: v1
|
||||
@@ -226,6 +235,9 @@ metadata:
|
||||
imageTag:
|
||||
name: nginx
|
||||
Digest: sha256:222222222222222222
|
||||
fieldSpecs:
|
||||
- path: spec/template/spec/containers[]/image
|
||||
- path: spec/template/spec/initContainers[]/image
|
||||
`, `
|
||||
group: apps
|
||||
apiVersion: v1
|
||||
@@ -295,6 +307,9 @@ imageTag:
|
||||
name: nginx
|
||||
newName: busybox
|
||||
Digest: sha256:222222222222222222
|
||||
fieldSpecs:
|
||||
- path: spec/template/spec/containers[]/image
|
||||
- path: spec/template/spec/initContainers[]/image
|
||||
`, `
|
||||
group: apps
|
||||
apiVersion: v1
|
||||
@@ -363,6 +378,11 @@ metadata:
|
||||
imageTag:
|
||||
name: nginx
|
||||
newTag: v2
|
||||
fieldSpecs:
|
||||
- path: spec/template/spec/containers[]/image
|
||||
create: true
|
||||
- path: spec/template/spec/initContainers[]/image
|
||||
create: true
|
||||
`, `
|
||||
group: apps
|
||||
apiVersion: v1
|
||||
@@ -384,8 +404,8 @@ metadata:
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers: null
|
||||
initContainers: null
|
||||
containers: []
|
||||
initContainers: []
|
||||
`)
|
||||
}
|
||||
|
||||
@@ -402,6 +422,8 @@ metadata:
|
||||
imageTag:
|
||||
name: some.registry.io/my-image
|
||||
newTag: "my-fixed-tag"
|
||||
fieldSpecs:
|
||||
- path: spec/template/spec/containers[]/image
|
||||
`, `
|
||||
group: apps
|
||||
apiVersion: v1
|
||||
|
||||
@@ -4,6 +4,7 @@ go 1.14
|
||||
|
||||
require (
|
||||
sigs.k8s.io/kustomize/api v0.5.1
|
||||
sigs.k8s.io/kustomize/kyaml v0.4.1
|
||||
sigs.k8s.io/yaml v1.2.0
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user