Updates in image transformer (#911)

- Decouple `mutateImage` from `updateContainers` to be reused as `mutateFunc`
- Ignore default image transform error for CRD which may contain non-array type `containers` field

Related to #890, #904, fixes #890
This commit is contained in:
Yujun Zhang
2019-03-30 04:11:07 +08:00
committed by Jingfang Liu
parent 21a0cba43e
commit 2490e605c3
3 changed files with 150 additions and 19 deletions

View File

@@ -320,3 +320,64 @@ spec:
action: makehoney action: makehoney
`) `)
} }
func TestCrdWithContainers(t *testing.T) {
th := NewKustTestHarness(t, "/app/crd/containers")
th.writeK("/app/crd/containers", `
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- crd.yaml
images:
- name: test/test
newName: registry.gitlab.com/test
newTag: latest
`)
th.writeF("/app/crd/containers/crd.yaml", `
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: crontabs.stable.example.com
spec:
group: stable.example.com
scope: Namespaced
names:
plural: crontabs
singular: crontab
kind: CronTab
shortNames:
- ct
validation:
openAPIV3Schema:
properties:
spec:
containers:
description: Containers allows injecting additional containers
`)
m, err := th.makeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
th.assertActualEqualsExpected(m, `
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: crontabs.stable.example.com
spec:
group: stable.example.com
names:
kind: CronTab
plural: crontabs
shortNames:
- ct
singular: crontab
scope: Namespaced
validation:
openAPIV3Schema:
properties:
spec:
containers:
description: Containers allows injecting additional containers
`)
}

View File

@@ -233,11 +233,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 path: spec/template/spec/myContainers/image
- kind: Custom - kind: Custom
path: spec2/template/spec/myContainers path: spec2/template/spec/myContainers/image
- kind: Custom - kind: Custom
path: spec3/template/spec/myInitContainers path: spec3/template/spec/myInitContainers/image
`) `)
} }
func TestTransfomersImageCustomConfig(t *testing.T) { func TestTransfomersImageCustomConfig(t *testing.T) {
@@ -283,3 +283,56 @@ spec3:
name: my-cool-app name: my-cool-app
`) `)
} }
func makeTransfomersImageKnativeBase(th *KustTestHarness) {
th.writeK("/app/base", `
resources:
- knative.yaml
configurations:
- config/knative.yaml
images:
- name: solsa-echo
newTag: foo
`)
th.writeF("/app/base/knative.yaml", `
apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
name: echo
spec:
runLatest:
configuration:
revisionTemplate:
spec:
container:
image: solsa-echo
`)
th.writeF("/app/base/config/knative.yaml", `
images:
- path: spec/runLatest/configuration/revisionTemplate/spec/container/image
apiVersion: serving.knative.dev/v1alpha1
kind: Service
`)
}
func TestTransfomersImageKnativeConfig(t *testing.T) {
th := NewKustTestHarness(t, "/app/base")
makeTransfomersImageKnativeBase(th)
m, err := th.makeKustTarget().MakeCustomizedResMap()
if err != nil {
t.Fatalf("Err: %v", err)
}
th.assertActualEqualsExpected(m, `
apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
name: echo
spec:
runLatest:
configuration:
revisionTemplate:
spec:
container:
image: solsa-echo:foo
`)
}

View File

@@ -50,20 +50,44 @@ func (pt *imageTransformer) Transform(m resmap.ResMap) error {
if !id.Gvk().IsSelected(&path.Gvk) { if !id.Gvk().IsSelected(&path.Gvk) {
continue continue
} }
err := mutateField(objMap, path.PathSlice(), false, pt.updateContainers) err := mutateField(objMap, path.PathSlice(), false, pt.mutateImage)
if err != nil { if err != nil {
return err return err
} }
} }
// Keep for backward compatibility // Kept for backward compatibility
err := pt.findAndReplaceImage(objMap) if err := pt.findAndReplaceImage(objMap); err != nil && id.Gvk().Kind != `CustomResourceDefinition` {
if err != nil {
return err return err
} }
} }
return nil return nil
} }
func (pt *imageTransformer) mutateImage(in interface{}) (interface{}, error) {
image, ok := in.(string)
if !ok {
return nil, fmt.Errorf("image path is not of type string but %T", in)
}
for _, img := range pt.images {
if !isImageMatched(image, img.Name) {
continue
}
name, tag := split(image)
if img.NewName != "" {
name = img.NewName
}
if img.NewTag != "" {
tag = ":" + img.NewTag
}
if img.Digest != "" {
tag = "@" + img.Digest
}
return name + tag, nil
}
return image, nil
}
/* /*
findAndReplaceImage replaces the image name and tags inside one object findAndReplaceImage replaces the image name and tags inside one object
It searches the object for container session It searches the object for container session
@@ -76,8 +100,7 @@ func (pt *imageTransformer) findAndReplaceImage(obj map[string]interface{}) erro
for _, path := range paths { for _, path := range paths {
containers, found := obj[path] containers, found := obj[path]
if found { if found {
_, err := pt.updateContainers(containers) if _, err := pt.updateContainers(containers); err != nil {
if err != nil {
return err return err
} }
updated = true updated = true
@@ -106,17 +129,11 @@ func (pt *imageTransformer) updateContainers(in interface{}) (interface{}, error
if !isImageMatched(imageName, img.Name) { if !isImageMatched(imageName, img.Name) {
continue continue
} }
name, tag := split(imageName) newImage, err := pt.mutateImage(imageName)
if img.NewName != "" { if err != nil {
name = img.NewName return nil, err
} }
if img.NewTag != "" { container["image"] = newImage
tag = ":" + img.NewTag
}
if img.Digest != "" {
tag = "@" + img.Digest
}
container["image"] = name + tag
break break
} }
} }