Merge pull request #841 from yujunz/transformers/image

Support custom configuration for image transformer
This commit is contained in:
Kubernetes Prow Robot
2019-03-19 14:08:22 -07:00
committed by GitHub
6 changed files with 172 additions and 13 deletions

View File

@@ -312,7 +312,7 @@ func (kt *KustTarget) newTransformer(
return nil, err
}
r = append(r, t)
t, err = transformers.NewImageTransformer(kt.kustomization.Images)
t, err = transformers.NewImageTransformer(kt.kustomization.Images, tConfig.Images)
if err != nil {
return nil, err
}

View File

@@ -168,3 +168,118 @@ spec3:
name: my-cool-app
`)
}
func makeTransfomersImageCustomBase(th *KustTestHarness) {
th.writeK("/app/base", `
resources:
- custom.yaml
configurations:
- config/custom.yaml
images:
- name: nginx
newTag: v2
- name: my-nginx
newTag: previous
- name: myprivaterepohostname:1234/my/image
newTag: v1.0.1
- name: foobar
digest: sha256:24a0c4b4
- name: alpine
newName: myprivaterepohostname:1234/my/cool-alpine
- name: gcr.io:8080/my-project/my-cool-app
newName: my-cool-app
- name: postgres
newName: my-postgres
newTag: v3
- name: docker
newName: my-docker
digest: sha256:25a0d4b4
`)
th.writeF("/app/base/custom.yaml", `
kind: customKind
metadata:
name: custom
spec:
template:
spec:
myContainers:
- name: ngnix1
image: nginx
spec2:
template:
spec:
myContainers:
- name: nginx3
image: nginx:v1
- name: nginx4
image: my-nginx:latest
spec3:
template:
spec:
myInitContainers:
- name: postgresdb
image: postgres:alpine-9
- name: init-docker
image: docker:17-git
- name: myImage
image: myprivaterepohostname:1234/my/image:latest
- name: myImage2
image: myprivaterepohostname:1234/my/image
- name: my-app
image: my-app-image:v1
- name: my-cool-app
image: gcr.io:8080/my-project/my-cool-app:latest
`)
th.writeF("/app/base/config/custom.yaml", `
images:
- kind: Custom
path: spec/template/spec/myContainers
- kind: Custom
path: spec2/template/spec/myContainers
- kind: Custom
path: spec3/template/spec/myInitContainers
`)
}
func TestTransfomersImageCustomConfig(t *testing.T) {
th := NewKustTestHarness(t, "/app/base")
makeTransfomersImageCustomBase(th)
m, err := th.makeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
th.assertActualEqualsExpected(m, `
kind: customKind
metadata:
name: custom
spec:
template:
spec:
myContainers:
- image: nginx
name: ngnix1
spec2:
template:
spec:
myContainers:
- image: nginx:v1
name: nginx3
- image: my-nginx:latest
name: nginx4
spec3:
template:
spec:
myInitContainers:
- image: postgres:alpine-9
name: postgresdb
- image: docker:17-git
name: init-docker
- image: myprivaterepohostname:1234/my/image:latest
name: myImage
- image: myprivaterepohostname:1234/my/image
name: myImage2
- image: my-app-image:v1
name: my-app
- image: gcr.io:8080/my-project/my-cool-app:latest
name: my-cool-app
`)
}

View File

@@ -31,6 +31,7 @@ func GetDefaultFieldSpecs() []byte {
[]byte(namespaceFieldSpecs),
[]byte(varReferenceFieldSpecs),
[]byte(nameReferenceFieldSpecs),
[]byte(imagesFieldSpecs),
}
return bytes.Join(configData, []byte("\n"))
}
@@ -45,5 +46,6 @@ func GetDefaultFieldSpecsAsMap() map[string]string {
result["namespace"] = namespaceFieldSpecs
result["varreference"] = varReferenceFieldSpecs
result["namereference"] = nameReferenceFieldSpecs
result["images"] = imagesFieldSpecs
return result
}

View File

@@ -0,0 +1,23 @@
/*
Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package defaultconfig
const (
// imageFieldSpecs is left empty since `containers` and `initContainers`
// of *ANY* kind in *ANY* path are builtin supported in code
imagesFieldSpecs = ``
)

View File

@@ -34,6 +34,7 @@ type TransformerConfig struct {
CommonAnnotations fsSlice `json:"commonAnnotations,omitempty" yaml:"commonAnnotations,omitempty"`
NameReference nbrSlice `json:"nameReference,omitempty" yaml:"nameReference,omitempty"`
VarReference fsSlice `json:"varReference,omitempty" yaml:"varReference,omitempty"`
Images fsSlice `json:"images,omitempty" yaml:"images,omitempty"`
}
// MakeEmptyConfig returns an empty TransformerConfig object
@@ -59,6 +60,7 @@ func (t *TransformerConfig) sortFields() {
sort.Sort(t.CommonAnnotations)
sort.Sort(t.NameReference)
sort.Sort(t.VarReference)
sort.Sort(t.Images)
}
// AddPrefixFieldSpec adds a FieldSpec to NamePrefix
@@ -129,6 +131,10 @@ func (t *TransformerConfig) Merge(input *TransformerConfig) (
if err != nil {
return nil, err
}
merged.Images, err = t.Images.mergeAll(input.Images)
if err != nil {
return nil, err
}
merged.sortFields()
return merged, nil
}

View File

@@ -23,27 +23,40 @@ import (
"sigs.k8s.io/kustomize/pkg/image"
"sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/transformers/config"
)
// imageTransformer replace image names and tags
type imageTransformer struct {
images []image.Image
images []image.Image
fieldSpecs []config.FieldSpec
}
var _ Transformer = &imageTransformer{}
// NewImageTransformer constructs an imageTransformer.
func NewImageTransformer(slice []image.Image) (Transformer, error) {
return &imageTransformer{slice}, nil
func NewImageTransformer(slice []image.Image, fs []config.FieldSpec) (Transformer, error) {
return &imageTransformer{slice, fs}, nil
}
// Transform finds the matching images and replaces name, tag and/or digest
func (pt *imageTransformer) Transform(resources resmap.ResMap) error {
func (pt *imageTransformer) Transform(m resmap.ResMap) error {
if len(pt.images) == 0 {
return nil
}
for _, res := range resources {
err := pt.findAndReplaceImage(res.Map())
for id := range m {
objMap := m[id].Map()
for _, path := range pt.fieldSpecs {
if !id.Gvk().IsSelected(&path.Gvk) {
continue
}
err := mutateField(objMap, path.PathSlice(), false, pt.updateContainers)
if err != nil {
return err
}
}
// Keep for backward compatibility
err := pt.findAndReplaceImage(objMap)
if err != nil {
return err
}
@@ -61,9 +74,9 @@ func (pt *imageTransformer) findAndReplaceImage(obj map[string]interface{}) erro
paths := []string{"containers", "initContainers"}
found := false
for _, path := range paths {
_, found = obj[path]
containers, found := obj[path]
if found {
err := pt.updateContainers(obj, path)
_, err := pt.updateContainers(containers)
if err != nil {
return err
}
@@ -75,10 +88,10 @@ func (pt *imageTransformer) findAndReplaceImage(obj map[string]interface{}) erro
return nil
}
func (pt *imageTransformer) updateContainers(obj map[string]interface{}, path string) error {
containers, ok := obj[path].([]interface{})
func (pt *imageTransformer) updateContainers(in interface{}) (interface{}, error) {
containers, ok := in.([]interface{})
if !ok {
return fmt.Errorf("containers path is not of type []interface{} but %T", obj[path])
return nil, fmt.Errorf("containers path is not of type []interface{} but %T", in)
}
for i := range containers {
container := containers[i].(map[string]interface{})
@@ -106,7 +119,7 @@ func (pt *imageTransformer) updateContainers(obj map[string]interface{}, path st
break
}
}
return nil
return containers, nil
}
func (pt *imageTransformer) findContainers(obj map[string]interface{}) error {