From 909de5c94ac88f931ab28b489614ba003c2fae31 Mon Sep 17 00:00:00 2001 From: Jingfang Liu Date: Mon, 23 Jul 2018 09:25:17 -0700 Subject: [PATCH] Add set imagetag command --- pkg/commands/commands.go | 1 + pkg/commands/setimagetag.go | 120 +++++++++++++++++++++++++++++++ pkg/commands/setimagetag_test.go | 97 +++++++++++++++++++++++++ 3 files changed, 218 insertions(+) create mode 100644 pkg/commands/setimagetag.go create mode 100644 pkg/commands/setimagetag_test.go diff --git a/pkg/commands/commands.go b/pkg/commands/commands.go index 9c7b2c36e..7a887fc47 100644 --- a/pkg/commands/commands.go +++ b/pkg/commands/commands.go @@ -123,6 +123,7 @@ func newCmdSet(fsys fs.FileSystem) *cobra.Command { c.AddCommand( newCmdSetNamePrefix(fsys), + newCmdSetImageTag(fsys), ) return c } diff --git a/pkg/commands/setimagetag.go b/pkg/commands/setimagetag.go new file mode 100644 index 000000000..ba2f51d0c --- /dev/null +++ b/pkg/commands/setimagetag.go @@ -0,0 +1,120 @@ +/* +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 commands + +import ( + "errors" + "strings" + + "github.com/spf13/cobra" + + "github.com/kubernetes-sigs/kustomize/pkg/constants" + "github.com/kubernetes-sigs/kustomize/pkg/fs" + "github.com/kubernetes-sigs/kustomize/pkg/types" + "sort" +) + +type setImageTagOptions struct { + imageTagMap map[string]string +} + +// newCmdSetImageTag sets the new tags for images in the kustomization. +func newCmdSetImageTag(fsys fs.FileSystem) *cobra.Command { + var o setImageTagOptions + + cmd := &cobra.Command{ + Use: "imagetag", + Short: "Sets images and their new tags in the kustomization file", + Example: ` +The command + set imagetag nginx:1.8.0 my-app:latest +will add + +imageTags: +- name: nginx + newTag: 1.8.0 +- name: my-app + newTag: latest + +to the kustomization file if it doesn't exist, +and overwrite the previous newTag if the image name exists. +`, + RunE: func(cmd *cobra.Command, args []string) error { + err := o.Validate(args) + if err != nil { + return err + } + err = o.Complete(cmd, args) + if err != nil { + return err + } + return o.RunSetImageTags(fsys) + }, + } + return cmd +} + +// Validate validates setImageTag command. +func (o *setImageTagOptions) Validate(args []string) error { + if len(args) == 0 { + return errors.New("No image and newTag specified.") + } + o.imageTagMap = make(map[string]string) + for _, arg := range args { + imagetag := strings.Split(arg, ":") + if len(imagetag) != 2 { + return errors.New("Invalid format of imagetag, must specify it as :") + } + o.imageTagMap[imagetag[0]] = imagetag[1] + } + return nil +} + +// Complete completes setImageTag command. +func (o *setImageTagOptions) Complete(cmd *cobra.Command, args []string) error { + return nil +} + +// RunSetImageTags runs setImageTags command (does real work). +func (o *setImageTagOptions) RunSetImageTags(fsys fs.FileSystem) error { + mf, err := newKustomizationFile(constants.KustomizationFileName, fsys) + if err != nil { + return err + } + m, err := mf.read() + if err != nil { + return err + } + imageTagMap := map[string]string{} + for _, it := range m.ImageTags { + imageTagMap[it.Name] = it.NewTag + } + for key, value := range o.imageTagMap { + imageTagMap[key] = value + } + var imageTags []types.ImageTag + for key, value := range imageTagMap { + imageTags = append(imageTags, types.ImageTag{Name: key, NewTag: value}) + } + sort.Slice(imageTags, func(i, j int) bool { + return imageTags[i].Name < imageTags[j].Name + }) + + m.ImageTags = imageTags + + return mf.write(m) +} diff --git a/pkg/commands/setimagetag_test.go b/pkg/commands/setimagetag_test.go new file mode 100644 index 000000000..7a7287fc6 --- /dev/null +++ b/pkg/commands/setimagetag_test.go @@ -0,0 +1,97 @@ +/* +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 commands + +import ( + "strings" + "testing" + + "github.com/kubernetes-sigs/kustomize/pkg/constants" + "github.com/kubernetes-sigs/kustomize/pkg/fs" +) + +func TestSetImageTagsHappyPath(t *testing.T) { + fakeFS := fs.MakeFakeFS() + fakeFS.WriteFile(constants.KustomizationFileName, []byte(kustomizationContent)) + + cmd := newCmdSetImageTag(fakeFS) + args := []string{"image1:tag1", "image2:tag2"} + err := cmd.RunE(cmd, args) + if err != nil { + t.Errorf("unexpected cmd error: %v", err) + } + content, err := fakeFS.ReadFile(constants.KustomizationFileName) + if err != nil { + t.Errorf("unexpected read error: %v", err) + } + expected := []byte(` +imageTags: +- name: image1 + newTag: tag1 +- name: image2 + newTag: tag2 +`) + if !strings.Contains(string(content), string(expected)) { + t.Errorf("expected imageTags in kustomization file") + } +} + +func TestSetImageTagsOverride(t *testing.T) { + fakeFS := fs.MakeFakeFS() + fakeFS.WriteFile(constants.KustomizationFileName, []byte(kustomizationContent)) + + cmd := newCmdSetImageTag(fakeFS) + args := []string{"image1:tag1", "image2:tag1"} + err := cmd.RunE(cmd, args) + if err != nil { + t.Errorf("unexpected cmd error: %v", err) + } + args = []string{"image2:tag2", "image3:tag3"} + err = cmd.RunE(cmd, args) + if err != nil { + t.Errorf("unexpected cmd error: %v", err) + } + content, err := fakeFS.ReadFile(constants.KustomizationFileName) + if err != nil { + t.Errorf("unexpected read error: %v", err) + } + expected := []byte(` +imageTags: +- name: image1 + newTag: tag1 +- name: image2 + newTag: tag2 +- name: image3 + newTag: tag3 +`) + if !strings.Contains(string(content), string(expected)) { + t.Errorf("expected imageTags in kustomization file %s", string(content)) + } +} + +func TestSetImageTagsNoArgs(t *testing.T) { + fakeFS := fs.MakeFakeFS() + + cmd := newCmdSetImageTag(fakeFS) + err := cmd.Execute() + if err == nil { + t.Errorf("expected error: %v", err) + } + if err.Error() != "No image and newTag specified." { + t.Errorf("incorrect error: %v", err.Error()) + } +}