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"
|
"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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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{
|
||||||
|
|||||||
@@ -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{
|
||||||
|
|||||||
@@ -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
|
||||||
|
`
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user