-
Notifications
You must be signed in to change notification settings - Fork 2.2k
/
setimage.go
243 lines (199 loc) · 5.36 KB
/
setimage.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package set
import (
"errors"
"regexp"
"sort"
"strings"
"sigs.k8s.io/kustomize/api/image"
"sigs.k8s.io/kustomize/api/types"
"github.com/spf13/cobra"
"sigs.k8s.io/kustomize/kustomize/v5/commands/internal/kustfile"
"sigs.k8s.io/kustomize/kyaml/filesys"
)
type setImageOptions struct {
imageMap map[string]types.Image
}
var pattern = regexp.MustCompile(`^(.*):([a-zA-Z0-9._-]*|\*)$`)
var preserveSeparator = "*"
// errors
var (
errImageNoArgs = errors.New("no image specified")
errImageInvalidArgs = errors.New(`invalid format of image, use one of the following options:
- <image>=<newimage>:<newtag>
- <image>=<newimage>@<digest>
- <image>=<newimage>:<newtag>@<digest>
- <image>=<newimage>
- <image>:<newtag>
- <image>:<newtag>@<digest>
- <image>@<digest>`)
)
const separator = "="
// newCmdSetImage sets the new names, tags or digests for images in the kustomization.
func newCmdSetImage(fSys filesys.FileSystem) *cobra.Command {
var o setImageOptions
cmd := &cobra.Command{
Use: "image",
Short: `Sets images and their new names, new tags or digests in the kustomization file`,
Example: `
The command
set image postgres=eu.gcr.io/my-project/postgres:latest my-app=my-registry/my-app@sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3
will add
images:
- name: postgres
newName: eu.gcr.io/my-project/postgres
newTag: latest
- digest: sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3
name: my-app
newName: my-registry/my-app
to the kustomization file if it doesn't exist,
and overwrite the previous ones if the image name exists.
The command
set image node:8.15.0 mysql=mariadb alpine@sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3
will add
images:
- name: node
newTag: 8.15.0
- name: mysql
newName: mariadb
- digest: sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3
name: alpine
to the kustomization file if it doesn't exist,
and overwrite the previous ones if the image name exists.
The image tag can only contain alphanumeric, '.', '_' and '-'. Passing * (asterisk) either as the new name,
the new tag, or the digest will preserve the appropriate values from the kustomization file.
`,
RunE: func(cmd *cobra.Command, args []string) error {
err := o.Validate(args)
if err != nil {
return err
}
return o.RunSetImage(fSys)
},
}
return cmd
}
type overwrite struct {
name string
digest string
tag string
}
// Validate validates setImage command.
func (o *setImageOptions) Validate(args []string) error {
if len(args) == 0 {
return errImageNoArgs
}
o.imageMap = make(map[string]types.Image)
for _, arg := range args {
img, err := parse(arg)
if err != nil {
return err
}
o.imageMap[img.Name] = img
}
return nil
}
// RunSetImage runs setImage command.
func (o *setImageOptions) RunSetImage(fSys filesys.FileSystem) error {
mf, err := kustfile.NewKustomizationFile(fSys)
if err != nil {
return err
}
m, err := mf.Read()
if err != nil {
return err
}
// append only new images from kustomize file
for _, im := range m.Images {
if argIm, ok := o.imageMap[im.Name]; ok {
// Reuse the existing new name when asterisk new name is passed
if argIm.NewName == preserveSeparator {
argIm = replaceNewName(argIm, im.NewName)
}
// Reuse the existing new tag when asterisk new tag is passed
if argIm.NewTag == preserveSeparator {
argIm = replaceNewTag(argIm, im.NewTag)
}
// Reuse the existing digest when asterisk disgest is passed
if argIm.Digest == preserveSeparator {
argIm = replaceDigest(argIm, im.Digest)
}
o.imageMap[im.Name] = argIm
continue
}
o.imageMap[im.Name] = im
}
var images []types.Image
for _, v := range o.imageMap {
if v.NewName == preserveSeparator {
v = replaceNewName(v, "")
}
if v.NewTag == preserveSeparator {
v = replaceNewTag(v, "")
}
if v.Digest == preserveSeparator {
v = replaceDigest(v, "")
}
images = append(images, v)
}
sort.Slice(images, func(i, j int) bool {
return images[i].Name < images[j].Name
})
m.Images = images
return mf.Write(m)
}
func replaceNewName(image types.Image, newName string) types.Image {
return types.Image{
Name: image.Name,
NewName: newName,
NewTag: image.NewTag,
Digest: image.Digest,
}
}
func replaceNewTag(image types.Image, newTag string) types.Image {
return types.Image{
Name: image.Name,
NewName: image.NewName,
NewTag: newTag,
Digest: image.Digest,
}
}
func replaceDigest(image types.Image, digest string) types.Image {
return types.Image{
Name: image.Name,
NewName: image.NewName,
NewTag: image.NewTag,
Digest: digest,
}
}
func parse(arg string) (types.Image, error) {
key, value, err := imageArgParse(arg)
if err != nil {
return types.Image{}, err
}
name, tag, digest := image.Split(value)
if name == arg {
return types.Image{}, errImageInvalidArgs
}
newImage := types.Image{
NewTag: tag,
Digest: digest,
}
if key == "" {
newImage.Name = name
} else {
newImage.Name = key
newImage.NewName = name
}
return newImage, nil
}
func imageArgParse(arg string) (key string, value string, err error) {
s := strings.SplitN(arg, separator, 2)
if len(s) == 2 {
return s[0], s[1], nil
} else if len(s) == 1 {
return "", s[0], nil
}
return "", "", errImageInvalidArgs
}