From 6dd599a983e59f3bc95d9381b2d1ae090eefe8cf Mon Sep 17 00:00:00 2001 From: Nestor Date: Wed, 16 Jan 2019 15:10:45 +0100 Subject: [PATCH 1/3] Add image transformer --- pkg/commands/edit/set/setimagetag.go | 12 +- pkg/image/append.go | 33 ++++ pkg/image/image.go | 34 ++++ pkg/image/imagetag.go | 31 ++++ pkg/target/kusttarget.go | 2 +- pkg/transformers/image.go | 159 ++++++++++++++++++ .../{imagetag_test.go => image_test.go} | 59 ++++++- pkg/transformers/imagetag.go | 126 -------------- pkg/types/kustomization.go | 30 ++-- 9 files changed, 333 insertions(+), 153 deletions(-) create mode 100644 pkg/image/append.go create mode 100644 pkg/image/image.go create mode 100644 pkg/image/imagetag.go create mode 100644 pkg/transformers/image.go rename pkg/transformers/{imagetag_test.go => image_test.go} (72%) delete mode 100644 pkg/transformers/imagetag.go diff --git a/pkg/commands/edit/set/setimagetag.go b/pkg/commands/edit/set/setimagetag.go index 2b216b906..730dc558d 100644 --- a/pkg/commands/edit/set/setimagetag.go +++ b/pkg/commands/edit/set/setimagetag.go @@ -25,11 +25,11 @@ import ( "github.com/spf13/cobra" "sigs.k8s.io/kustomize/pkg/commands/kustfile" "sigs.k8s.io/kustomize/pkg/fs" - "sigs.k8s.io/kustomize/pkg/types" + "sigs.k8s.io/kustomize/pkg/image" ) type setImageTagOptions struct { - imageTagMap map[string]types.ImageTag + imageTagMap map[string]image.Tag } var pattern = regexp.MustCompile("^(.*):([a-zA-Z0-9._-]*)$") @@ -74,11 +74,11 @@ func (o *setImageTagOptions) Validate(args []string) error { return errors.New("no image specified") } - o.imageTagMap = make(map[string]types.ImageTag) + o.imageTagMap = make(map[string]image.Tag) for _, arg := range args { if s := strings.Split(arg, "@"); len(s) > 1 { - o.imageTagMap[s[0]] = types.ImageTag{ + o.imageTagMap[s[0]] = image.Tag{ Name: s[0], Digest: s[1], } @@ -89,7 +89,7 @@ func (o *setImageTagOptions) Validate(args []string) error { if len(s) != 3 { return errors.New("invalid format of imagetag, must specify it as : or @") } - o.imageTagMap[s[1]] = types.ImageTag{ + o.imageTagMap[s[1]] = image.Tag{ Name: s[1], NewTag: s[2], } @@ -116,7 +116,7 @@ func (o *setImageTagOptions) RunSetImageTags(fSys fs.FileSystem) error { o.imageTagMap[it.Name] = it } - var imageTags []types.ImageTag + var imageTags []image.Tag for _, v := range o.imageTagMap { imageTags = append(imageTags, v) } diff --git a/pkg/image/append.go b/pkg/image/append.go new file mode 100644 index 000000000..2edd03d16 --- /dev/null +++ b/pkg/image/append.go @@ -0,0 +1,33 @@ +/* +Copyright 2018 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 image + +// Append appends a slice of type Tag to slice of type Image +func Append(images []Image, tags ...Tag) []Image { + for _, tag := range tags { + images = append(images, toImage(tag)) + } + return images +} + +func toImage(tag Tag) Image { + return Image{ + Name: tag.Name, + NewTag: tag.NewTag, + Digest: tag.Digest, + } +} diff --git a/pkg/image/image.go b/pkg/image/image.go new file mode 100644 index 000000000..189319609 --- /dev/null +++ b/pkg/image/image.go @@ -0,0 +1,34 @@ +/* +Copyright 2018 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 image + +// Image contains an image name, a new name, a new tag or digest, +// which will replace the original name and tag. +type Image struct { + // Name is a tag-less image name. + Name string `json:"name,omitempty" yaml:"name,omitempty"` + + // NewName is the value used to replace the original name. + NewName string `json:"newName,omitempty" yaml:"newName,omitempty"` + + // NewTag is the value used to replace the original tag. + NewTag string `json:"newTag,omitempty" yaml:"newTag,omitempty"` + + // Digest is the value used to replace the original image tag. + // If digest is present NewTag value is ignored. + Digest string `json:"digest,omitempty" yaml:"digest,omitempty"` +} diff --git a/pkg/image/imagetag.go b/pkg/image/imagetag.go new file mode 100644 index 000000000..0a09ce19d --- /dev/null +++ b/pkg/image/imagetag.go @@ -0,0 +1,31 @@ +/* +Copyright 2018 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 image + +// Tag contains an image and a new tag, which will replace the original tag. +// Tag usage is deprecated, instead use ImageTag. +type Tag struct { + // Name is a tag-less image name. + Name string `json:"name,omitempty" yaml:"name,omitempty"` + + // NewTag is the value to use in replacing the original tag. + NewTag string `json:"newTag,omitempty" yaml:"newTag,omitempty"` + + // Digest is the value used to replace the original image tag. + // If digest is present NewTag value is ignored. + Digest string `json:"digest,omitempty" yaml:"digest,omitempty"` +} diff --git a/pkg/target/kusttarget.go b/pkg/target/kusttarget.go index b362737f2..fadfcee01 100644 --- a/pkg/target/kusttarget.go +++ b/pkg/target/kusttarget.go @@ -302,7 +302,7 @@ func (kt *KustTarget) newTransformer( return nil, err } r = append(r, t) - t, err = transformers.NewImageTagTransformer(kt.kustomization.ImageTags) + t, err = transformers.NewImageTransformer(kt.kustomization.Image) if err != nil { return nil, err } diff --git a/pkg/transformers/image.go b/pkg/transformers/image.go new file mode 100644 index 000000000..eed3f0274 --- /dev/null +++ b/pkg/transformers/image.go @@ -0,0 +1,159 @@ +/* +Copyright 2018 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 transformers + +import ( + "regexp" + "strings" + + "sigs.k8s.io/kustomize/pkg/image" + "sigs.k8s.io/kustomize/pkg/resmap" +) + +// imageTransformer replace image names and tags +type imageTransformer struct { + images []image.Image +} + +var _ Transformer = &imageTransformer{} + +// NewImageTransformer constructs an imageTransformer. +func NewImageTransformer(slice []image.Image) (Transformer, error) { + return &imageTransformer{slice}, nil +} + +// Transform finds the matching images and replaces name and/or tag +func (pt *imageTransformer) Transform(resources resmap.ResMap) error { + if len(pt.images) == 0 { + return nil + } + for _, res := range resources { + err := pt.findAndReplaceImage(res.Map()) + if err != nil { + return err + } + } + return nil +} + +/* + findAndReplaceImage replaces the image name and tags inside one object + It searches the object for container session + then loops though all images inside containers session, + finds matched ones and update the image name and tag name +*/ +func (pt *imageTransformer) findAndReplaceImage(obj map[string]interface{}) error { + paths := []string{"containers", "initContainers"} + found := false + for _, path := range paths { + _, found = obj[path] + if found { + err := pt.updateContainers(obj, path) + if err != nil { + return err + } + } + } + if !found { + return pt.findContainers(obj) + } + return nil +} + +func (pt *imageTransformer) updateContainers(obj map[string]interface{}, path string) error { + containers := obj[path].([]interface{}) + for i := range containers { + container := containers[i].(map[string]interface{}) + containerImage, found := container["image"] + if !found { + continue + } + + imageName := containerImage.(string) + for _, image := range pt.images { + if isImageMatched(imageName, image.Name) { + name, tag := split(imageName) + + if image.NewName != "" { + name = image.NewName + } + + if image.NewTag != "" { + tag = ":" + image.NewTag + } + + if image.Digest != "" { + tag = "@" + image.Digest + } + + container["image"] = name + tag + break + } + } + } + return nil +} + +func (pt *imageTransformer) findContainers(obj map[string]interface{}) error { + for key := range obj { + switch typedV := obj[key].(type) { + case map[string]interface{}: + err := pt.findAndReplaceImage(typedV) + if err != nil { + return err + } + case []interface{}: + for i := range typedV { + item := typedV[i] + typedItem, ok := item.(map[string]interface{}) + if ok { + err := pt.findAndReplaceImage(typedItem) + if err != nil { + return err + } + } + } + } + } + return nil +} + +func isImageMatched(s, t string) bool { + // Tag values are limited to [a-zA-Z0-9_.-]. + pattern, _ := regexp.Compile("^" + t + "(:[a-zA-Z0-9_.-]*)?$") + return pattern.MatchString(s) +} + +// split separates and returns the name and tag parts +// from the image string using either colon `:` or at `@` separators. +// Note that the returned tag keeps its separator. +func split(imageName string) (name string, tag string) { + ic := strings.LastIndex(imageName, ":") + ia := strings.LastIndex(imageName, "@") + if ic < 0 && ia < 0 { + return imageName, "" + } + + i := ic + if ic < 0 { + i = ia + } + + name = imageName[:i] + tag = imageName[i:] + return +} diff --git a/pkg/transformers/imagetag_test.go b/pkg/transformers/image_test.go similarity index 72% rename from pkg/transformers/imagetag_test.go rename to pkg/transformers/image_test.go index 179dab248..03ac2c707 100644 --- a/pkg/transformers/imagetag_test.go +++ b/pkg/transformers/image_test.go @@ -22,13 +22,13 @@ import ( "sigs.k8s.io/kustomize/k8sdeps/kunstruct" "sigs.k8s.io/kustomize/pkg/gvk" + "sigs.k8s.io/kustomize/pkg/image" "sigs.k8s.io/kustomize/pkg/resid" "sigs.k8s.io/kustomize/pkg/resmap" "sigs.k8s.io/kustomize/pkg/resource" - "sigs.k8s.io/kustomize/pkg/types" ) -func TestImageTagTransformer(t *testing.T) { +func TestImageTransformer(t *testing.T) { var rf = resource.NewFactory( kunstruct.NewKunstructuredFactoryImpl()) @@ -49,6 +49,10 @@ func TestImageTagTransformer(t *testing.T) { "name": "nginx2", "image": "my-nginx:1.8.0", }, + map[string]interface{}{ + "name": "init-alpine", + "image": "alpine:1.8.0", + }, }, "containers": []interface{}{ map[string]interface{}{ @@ -59,6 +63,10 @@ func TestImageTagTransformer(t *testing.T) { "name": "replaced-with-digest", "image": "foobar:1", }, + map[string]interface{}{ + "name": "postgresdb", + "image": "postgres:1.8.0", + }, }, }, }, @@ -98,6 +106,22 @@ func TestImageTagTransformer(t *testing.T) { }, }, }, + "spec3": map[string]interface{}{ + "template": map[string]interface{}{ + "spec": map[string]interface{}{ + "initContainers": []interface{}{ + map[string]interface{}{ + "name": "postgresdb", + "image": "postgres:alpine-9", + }, + map[string]interface{}{ + "name": "init-docker", + "image": "docker:17-git", + }, + }, + }, + }, + }, }), } expected := resmap.ResMap{ @@ -117,6 +141,10 @@ func TestImageTagTransformer(t *testing.T) { "name": "nginx2", "image": "my-nginx:previous", }, + map[string]interface{}{ + "name": "init-alpine", + "image": "myprivaterepohostname:1234/my/cool-alpine:1.8.0", + }, }, "containers": []interface{}{ map[string]interface{}{ @@ -127,6 +155,10 @@ func TestImageTagTransformer(t *testing.T) { "name": "replaced-with-digest", "image": "foobar@sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3", }, + map[string]interface{}{ + "name": "postgresdb", + "image": "my-postgres:v3", + }, }, }, }, @@ -166,14 +198,33 @@ func TestImageTagTransformer(t *testing.T) { }, }, }, + "spec3": map[string]interface{}{ + "template": map[string]interface{}{ + "spec": map[string]interface{}{ + "initContainers": []interface{}{ + map[string]interface{}{ + "name": "postgresdb", + "image": "my-postgres:v3", + }, + map[string]interface{}{ + "name": "init-docker", + "image": "my-docker@sha256:25a0d4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3", + }, + }, + }, + }, + }, }), } - it, err := NewImageTagTransformer([]types.ImageTag{ + it, err := NewImageTransformer([]image.Image{ {Name: "nginx", NewTag: "v2"}, {Name: "my-nginx", NewTag: "previous"}, {Name: "myprivaterepohostname:1234/my/image", NewTag: "v1.0.1"}, {Name: "foobar", Digest: "sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3"}, + {Name: "alpine", NewName: "myprivaterepohostname:1234/my/cool-alpine"}, + {Name: "postgres", NewName: "my-postgres", NewTag: "v3"}, + {Name: "docker", NewName: "my-docker", Digest: "sha256:25a0d4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3"}, }) if err != nil { t.Fatalf("unexpected error: %v", err) @@ -184,6 +235,6 @@ func TestImageTagTransformer(t *testing.T) { } if !reflect.DeepEqual(m, expected) { err = expected.ErrorIfNotEqual(m) - t.Fatalf("actual doesn't match expected: %v", err) + t.Fatalf("actual doesn't match expected: %v. Actual %+v", err, m) } } diff --git a/pkg/transformers/imagetag.go b/pkg/transformers/imagetag.go deleted file mode 100644 index ef1f7c279..000000000 --- a/pkg/transformers/imagetag.go +++ /dev/null @@ -1,126 +0,0 @@ -/* -Copyright 2018 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 transformers - -import ( - "regexp" - - "sigs.k8s.io/kustomize/pkg/resmap" - "sigs.k8s.io/kustomize/pkg/types" -) - -// imageTagTransformer replace image tags -type imageTagTransformer struct { - imageTags []types.ImageTag -} - -var _ Transformer = &imageTagTransformer{} - -// NewImageTagTransformer constructs a imageTagTransformer. -func NewImageTagTransformer(slice []types.ImageTag) (Transformer, error) { - return &imageTagTransformer{slice}, nil -} - -// Transform finds the matching images and replace the tag -func (pt *imageTagTransformer) Transform(resources resmap.ResMap) error { - if len(pt.imageTags) == 0 { - return nil - } - for _, res := range resources { - err := pt.findAndReplaceTag(res.Map()) - if err != nil { - return err - } - } - return nil -} - -/* - findAndReplaceTag replaces the image tags inside one object - It searches the object for container session - then loops though all images inside containers session, finds matched ones and update the tag name -*/ -func (pt *imageTagTransformer) findAndReplaceTag(obj map[string]interface{}) error { - paths := []string{"containers", "initContainers"} - found := false - for _, path := range paths { - _, found = obj[path] - if found { - err := pt.updateContainers(obj, path) - if err != nil { - return err - } - } - } - if !found { - return pt.findContainers(obj) - } - return nil -} - -func (pt *imageTagTransformer) updateContainers(obj map[string]interface{}, path string) error { - containers := obj[path].([]interface{}) - for i := range containers { - container := containers[i].(map[string]interface{}) - image, found := container["image"] - if !found { - continue - } - for _, imagetag := range pt.imageTags { - if isImageMatched(image.(string), imagetag.Name) { - container["image"] = imagetag.Name + ":" + imagetag.NewTag - - if imagetag.Digest != "" { - container["image"] = imagetag.Name + "@" + imagetag.Digest - } - - break - } - } - } - return nil -} - -func (pt *imageTagTransformer) findContainers(obj map[string]interface{}) error { - for key := range obj { - switch typedV := obj[key].(type) { - case map[string]interface{}: - err := pt.findAndReplaceTag(typedV) - if err != nil { - return err - } - case []interface{}: - for i := range typedV { - item := typedV[i] - typedItem, ok := item.(map[string]interface{}) - if ok { - err := pt.findAndReplaceTag(typedItem) - if err != nil { - return err - } - } - } - } - } - return nil -} - -func isImageMatched(s, t string) bool { - // Tag values are limited to [a-zA-Z0-9_.-]. - pattern, _ := regexp.Compile("^" + t + "(:[a-zA-Z0-9_.-]*)?$") - return pattern.MatchString(s) -} diff --git a/pkg/types/kustomization.go b/pkg/types/kustomization.go index 28dff3469..40733d8da 100644 --- a/pkg/types/kustomization.go +++ b/pkg/types/kustomization.go @@ -18,6 +18,7 @@ limitations under the License. package types import ( + "sigs.k8s.io/kustomize/pkg/image" "sigs.k8s.io/kustomize/pkg/patch" ) @@ -71,10 +72,10 @@ type Kustomization struct { // and http://jsonpatch.com PatchesJson6902 []patch.Json6902 `json:"patchesJson6902,omitempty" yaml:"patchesJson6902,omitempty"` - // ImageTags is a list of (image name, new tag) pairs for simply - // changing a an image tag. This can also be achieved with a + // Image is a list of (image name, new name, new tag or digest) + // for changing image names, tags or digests. This can also be achieved with a // patch, but this operator is simpler to specify. - ImageTags []ImageTag `json:"imageTags,omitempty" yaml:"imageTags,omitempty"` + Image []image.Image `json:"images,omitempty" yaml:"images,omitempty"` // Vars allow things modified by kustomize to be injected into a // container specification. A var is a name (e.g. FOO) associated @@ -134,6 +135,9 @@ type Kustomization struct { // Deprecated. Patches []string `json:"patches,omitempty" yaml:"patches,omitempty"` + + // Deprecated. Use `Image` + ImageTags []image.Tag `json:"imageTags,omitempty" yaml:"imageTags,omitempty"` } // DealWithDeprecatedFields should be called immediately after @@ -149,6 +153,13 @@ func (k *Kustomization) DealWithDeprecatedFields() { k.PatchesStrategicMerge, k.Patches...) k.Patches = []string{} } + + if len(k.ImageTags) > 0 { + // Transform `image.Tag` to `image.Image` + // for backwards compatibility + k.Image = image.Append( + k.Image, k.ImageTags...) + } } // DealWithMissingFields fills the missing fields @@ -261,19 +272,6 @@ type DataSources struct { EnvSource string `json:"env,omitempty" yaml:"env,omitempty"` } -// ImageTag contains an image and a new tag, which will replace the original tag. -type ImageTag struct { - // Name is a tag-less image name. - Name string `json:"name,omitempty" yaml:"name,omitempty"` - - // NewTag is the value to use in replacing the original tag. - NewTag string `json:"newTag,omitempty" yaml:"newTag,omitempty"` - - // Digest is the value used to replace the original image tag. - // If digest is present NewTag value is ignored. - Digest string `json:"digest,omitempty" yaml:"digest,omitempty"` -} - // GeneratorOptions modify behavior of all ConfigMap and Secret generators. type GeneratorOptions struct { // Labels to add to all generated resources. From 6d56c1750f65b4f648040959313c5004e5c351cb Mon Sep 17 00:00:00 2001 From: Nestor Date: Thu, 17 Jan 2019 15:49:35 +0100 Subject: [PATCH 2/3] fix issues from code review --- pkg/commands/edit/set/setimagetag.go | 10 ++++---- pkg/image/append.go | 6 ++--- pkg/image/image.go | 4 +++- pkg/image/imagetag.go | 8 +++---- pkg/target/kusttarget.go | 2 +- pkg/transformers/image.go | 4 ++-- pkg/transformers/image_test.go | 36 +++++++++++++++++++++------- pkg/types/kustomization.go | 10 ++++---- 8 files changed, 50 insertions(+), 30 deletions(-) diff --git a/pkg/commands/edit/set/setimagetag.go b/pkg/commands/edit/set/setimagetag.go index 730dc558d..43eb4b139 100644 --- a/pkg/commands/edit/set/setimagetag.go +++ b/pkg/commands/edit/set/setimagetag.go @@ -29,7 +29,7 @@ import ( ) type setImageTagOptions struct { - imageTagMap map[string]image.Tag + imageTagMap map[string]image.ImageTag } var pattern = regexp.MustCompile("^(.*):([a-zA-Z0-9._-]*)$") @@ -74,11 +74,11 @@ func (o *setImageTagOptions) Validate(args []string) error { return errors.New("no image specified") } - o.imageTagMap = make(map[string]image.Tag) + o.imageTagMap = make(map[string]image.ImageTag) for _, arg := range args { if s := strings.Split(arg, "@"); len(s) > 1 { - o.imageTagMap[s[0]] = image.Tag{ + o.imageTagMap[s[0]] = image.ImageTag{ Name: s[0], Digest: s[1], } @@ -89,7 +89,7 @@ func (o *setImageTagOptions) Validate(args []string) error { if len(s) != 3 { return errors.New("invalid format of imagetag, must specify it as : or @") } - o.imageTagMap[s[1]] = image.Tag{ + o.imageTagMap[s[1]] = image.ImageTag{ Name: s[1], NewTag: s[2], } @@ -116,7 +116,7 @@ func (o *setImageTagOptions) RunSetImageTags(fSys fs.FileSystem) error { o.imageTagMap[it.Name] = it } - var imageTags []image.Tag + var imageTags []image.ImageTag for _, v := range o.imageTagMap { imageTags = append(imageTags, v) } diff --git a/pkg/image/append.go b/pkg/image/append.go index 2edd03d16..ae479b0f1 100644 --- a/pkg/image/append.go +++ b/pkg/image/append.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +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. @@ -17,14 +17,14 @@ limitations under the License. package image // Append appends a slice of type Tag to slice of type Image -func Append(images []Image, tags ...Tag) []Image { +func Append(images []Image, tags ...ImageTag) []Image { for _, tag := range tags { images = append(images, toImage(tag)) } return images } -func toImage(tag Tag) Image { +func toImage(tag ImageTag) Image { return Image{ Name: tag.Name, NewTag: tag.NewTag, diff --git a/pkg/image/image.go b/pkg/image/image.go index 189319609..dbe3b8b17 100644 --- a/pkg/image/image.go +++ b/pkg/image/image.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +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. @@ -14,6 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ +// Package image provides struct definitions and libraries +// for image overwriting of names, tags and digest. package image // Image contains an image name, a new name, a new tag or digest, diff --git a/pkg/image/imagetag.go b/pkg/image/imagetag.go index 0a09ce19d..acff10a50 100644 --- a/pkg/image/imagetag.go +++ b/pkg/image/imagetag.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +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. @@ -16,9 +16,9 @@ limitations under the License. package image -// Tag contains an image and a new tag, which will replace the original tag. -// Tag usage is deprecated, instead use ImageTag. -type Tag struct { +// ImageTag contains an image and a new tag, which will replace the original tag. +// Deprecated, instead use Image. +type ImageTag struct { // Name is a tag-less image name. Name string `json:"name,omitempty" yaml:"name,omitempty"` diff --git a/pkg/target/kusttarget.go b/pkg/target/kusttarget.go index fadfcee01..6d8fb1cbc 100644 --- a/pkg/target/kusttarget.go +++ b/pkg/target/kusttarget.go @@ -302,7 +302,7 @@ func (kt *KustTarget) newTransformer( return nil, err } r = append(r, t) - t, err = transformers.NewImageTransformer(kt.kustomization.Image) + t, err = transformers.NewImageTransformer(kt.kustomization.Images) if err != nil { return nil, err } diff --git a/pkg/transformers/image.go b/pkg/transformers/image.go index eed3f0274..6dbc94412 100644 --- a/pkg/transformers/image.go +++ b/pkg/transformers/image.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +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. @@ -36,7 +36,7 @@ func NewImageTransformer(slice []image.Image) (Transformer, error) { return &imageTransformer{slice}, nil } -// Transform finds the matching images and replaces name and/or tag +// Transform finds the matching images and replaces name, tag and/or digest func (pt *imageTransformer) Transform(resources resmap.ResMap) error { if len(pt.images) == 0 { return nil diff --git a/pkg/transformers/image_test.go b/pkg/transformers/image_test.go index 03ac2c707..f1bf18351 100644 --- a/pkg/transformers/image_test.go +++ b/pkg/transformers/image_test.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +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. @@ -82,10 +82,6 @@ func TestImageTransformer(t *testing.T) { "name": "nginx1", "image": "nginx", }, - map[string]interface{}{ - "name": "myimage", - "image": "myprivaterepohostname:1234/my/image:latest", - }, }, }, }, @@ -118,6 +114,18 @@ func TestImageTransformer(t *testing.T) { "name": "init-docker", "image": "docker:17-git", }, + map[string]interface{}{ + "name": "myimage", + "image": "myprivaterepohostname:1234/my/image:latest", + }, + map[string]interface{}{ + "name": "my-app", + "image": "my-app-image:v1", + }, + map[string]interface{}{ + "name": "my-cool-app", + "image": "gcr.io:8080/my-project/my-cool-app:latest", + }, }, }, }, @@ -174,10 +182,6 @@ func TestImageTransformer(t *testing.T) { "name": "nginx1", "image": "nginx:v2", }, - map[string]interface{}{ - "name": "myimage", - "image": "myprivaterepohostname:1234/my/image:v1.0.1", - }, }, }, }, @@ -210,6 +214,18 @@ func TestImageTransformer(t *testing.T) { "name": "init-docker", "image": "my-docker@sha256:25a0d4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3", }, + map[string]interface{}{ + "name": "myimage", + "image": "myprivaterepohostname:1234/my/image:v1.0.1", + }, + map[string]interface{}{ + "name": "my-app", + "image": "gcr.io/my-project/my-app-image:v1", + }, + map[string]interface{}{ + "name": "my-cool-app", + "image": "my-cool-app:latest", + }, }, }, }, @@ -223,6 +239,8 @@ func TestImageTransformer(t *testing.T) { {Name: "myprivaterepohostname:1234/my/image", NewTag: "v1.0.1"}, {Name: "foobar", Digest: "sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3"}, {Name: "alpine", NewName: "myprivaterepohostname:1234/my/cool-alpine"}, + {Name: "my-app-image", NewName: "gcr.io/my-project/my-app-image"}, + {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:25a0d4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3"}, }) diff --git a/pkg/types/kustomization.go b/pkg/types/kustomization.go index 40733d8da..31b3a2147 100644 --- a/pkg/types/kustomization.go +++ b/pkg/types/kustomization.go @@ -72,10 +72,10 @@ type Kustomization struct { // and http://jsonpatch.com PatchesJson6902 []patch.Json6902 `json:"patchesJson6902,omitempty" yaml:"patchesJson6902,omitempty"` - // Image is a list of (image name, new name, new tag or digest) + // Images is a list of (image name, new name, new tag or digest) // for changing image names, tags or digests. This can also be achieved with a // patch, but this operator is simpler to specify. - Image []image.Image `json:"images,omitempty" yaml:"images,omitempty"` + Images []image.Image `json:"images,omitempty" yaml:"images,omitempty"` // Vars allow things modified by kustomize to be injected into a // container specification. A var is a name (e.g. FOO) associated @@ -137,7 +137,7 @@ type Kustomization struct { Patches []string `json:"patches,omitempty" yaml:"patches,omitempty"` // Deprecated. Use `Image` - ImageTags []image.Tag `json:"imageTags,omitempty" yaml:"imageTags,omitempty"` + ImageTags []image.ImageTag `json:"imageTags,omitempty" yaml:"imageTags,omitempty"` } // DealWithDeprecatedFields should be called immediately after @@ -157,8 +157,8 @@ func (k *Kustomization) DealWithDeprecatedFields() { if len(k.ImageTags) > 0 { // Transform `image.Tag` to `image.Image` // for backwards compatibility - k.Image = image.Append( - k.Image, k.ImageTags...) + k.Images = image.Append( + k.Images, k.ImageTags...) } } From 6616b25d66b9a04c70b6125801f929fb39ae2791 Mon Sep 17 00:00:00 2001 From: Nestor Date: Thu, 17 Jan 2019 16:02:14 +0100 Subject: [PATCH 3/3] fix comment --- pkg/types/kustomization.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/types/kustomization.go b/pkg/types/kustomization.go index 31b3a2147..26c689452 100644 --- a/pkg/types/kustomization.go +++ b/pkg/types/kustomization.go @@ -155,7 +155,7 @@ func (k *Kustomization) DealWithDeprecatedFields() { } if len(k.ImageTags) > 0 { - // Transform `image.Tag` to `image.Image` + // Transform `ImageTag` to `Image` // for backwards compatibility k.Images = image.Append( k.Images, k.ImageTags...)