Skip to content

Commit 35ddd40

Browse files
committed
feat: support edit add/set label for labels and not only commonLabels
1 parent 9d5491c commit 35ddd40

File tree

6 files changed

+203
-19
lines changed

6 files changed

+203
-19
lines changed

kustomize/commands/edit/add/addmetadata.go

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,11 @@ func (k kindOfAdd) String() string {
3434
}
3535

3636
type addMetadataOptions struct {
37-
force bool
38-
metadata map[string]string
39-
mapValidator func(map[string]string) error
40-
kind kindOfAdd
37+
force bool
38+
includeSelectors bool
39+
metadata map[string]string
40+
mapValidator func(map[string]string) error
41+
kind kindOfAdd
4142
}
4243

4344
// newCmdAddAnnotation adds one or more commonAnnotations to the kustomization file.
@@ -68,16 +69,27 @@ func newCmdAddLabel(fSys filesys.FileSystem, v func(map[string]string) error) *c
6869
o.mapValidator = v
6970
cmd := &cobra.Command{
7071
Use: "label",
71-
Short: "Adds one or more commonLabels to " +
72+
Short: "Adds one or more labels or commonLabels to " +
7273
konfig.DefaultKustomizationFileName(),
7374
Example: `
74-
add label {labelKey1:labelValue1} {labelKey2:labelValue2}`,
75+
# Add commonLabels (default)
76+
add label {labelKey1:labelValue1} {labelKey2:labelValue2}
77+
78+
# Add commonLabels
79+
add label --include-selectors=true {labelKey1:labelValue1} {labelKey2:labelValue2}
80+
81+
# Add labels
82+
add label --include-selectors=false {labelKey1:labelValue1} {labelKey2:labelValue2}
83+
`,
7584
RunE: func(cmd *cobra.Command, args []string) error {
7685
return o.runE(args, fSys, o.addLabels)
7786
},
7887
}
7988
cmd.Flags().BoolVarP(&o.force, "force", "f", false,
80-
"overwrite commonLabel if it already exists",
89+
"overwrite label or commonLabel if it already exists",
90+
)
91+
cmd.Flags().BoolVarP(&o.includeSelectors, "include-selectors", "s", true,
92+
"include label in selectors",
8193
)
8294
return cmd
8395
}
@@ -127,10 +139,17 @@ func (o *addMetadataOptions) addAnnotations(m *types.Kustomization) error {
127139
}
128140

129141
func (o *addMetadataOptions) addLabels(m *types.Kustomization) error {
130-
if m.CommonLabels == nil {
131-
m.CommonLabels = make(map[string]string)
142+
if o.includeSelectors {
143+
if m.CommonLabels == nil {
144+
m.CommonLabels = make(map[string]string)
145+
}
146+
return o.writeToMap(m.CommonLabels, label)
147+
} else {
148+
if m.Labels == nil {
149+
m.Labels = make([]types.Label, 0)
150+
}
151+
return o.writeToLabelsSlice(&m.Labels)
132152
}
133-
return o.writeToMap(m.CommonLabels, label)
134153
}
135154

136155
func (o *addMetadataOptions) writeToMap(m map[string]string, kind kindOfAdd) error {
@@ -142,3 +161,26 @@ func (o *addMetadataOptions) writeToMap(m map[string]string, kind kindOfAdd) err
142161
}
143162
return nil
144163
}
164+
165+
func (o *addMetadataOptions) writeToLabelsSlice(klabels *[]types.Label) error {
166+
for k, v := range o.metadata {
167+
isPresent := false
168+
for _, kl := range *klabels {
169+
if _, isPresent = kl.Pairs[k]; isPresent && !o.force {
170+
return fmt.Errorf("%s %s already in kustomization file", label, k)
171+
} else if isPresent && o.force {
172+
kl.Pairs[k] = v
173+
break
174+
}
175+
}
176+
if !isPresent {
177+
*klabels = append(*klabels, types.Label{
178+
Pairs: map[string]string{
179+
k: v,
180+
},
181+
IncludeSelectors: o.includeSelectors,
182+
})
183+
}
184+
}
185+
return nil
186+
}

kustomize/commands/edit/add/addmetadata_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ func TestAddAnnotationForce(t *testing.T) {
174174
func TestRunAddLabel(t *testing.T) {
175175
var o addMetadataOptions
176176
o.metadata = map[string]string{"owls": "cute", "otters": "adorable"}
177+
o.includeSelectors = true
177178

178179
m := makeKustomization(t)
179180
assert.NoError(t, o.addLabels(m))
@@ -274,3 +275,34 @@ func TestAddLabelForce(t *testing.T) {
274275
assert.NoError(t, cmd.RunE(cmd, args))
275276
v.VerifyCall()
276277
}
278+
279+
func TestAddLabelNoSelector(t *testing.T) {
280+
fSys := filesys.MakeFsInMemory()
281+
testutils_test.WriteTestKustomization(fSys)
282+
v := valtest_test.MakeHappyMapValidator(t)
283+
cmd := newCmdAddLabel(fSys, v.Validator)
284+
err := cmd.Flag("include-selectors").Value.Set("false")
285+
require.NoError(t, err)
286+
args := []string{"key:foo"}
287+
assert.NoError(t, cmd.RunE(cmd, args))
288+
v.VerifyCall()
289+
// trying to add the same label again should not work
290+
args = []string{"key:bar"}
291+
v = valtest_test.MakeHappyMapValidator(t)
292+
cmd = newCmdAddLabel(fSys, v.Validator)
293+
err = cmd.Flag("include-selectors").Value.Set("false")
294+
require.NoError(t, err)
295+
err = cmd.RunE(cmd, args)
296+
v.VerifyCall()
297+
assert.Error(t, err)
298+
assert.Equal(t, "label key already in kustomization file", err.Error())
299+
// but trying to add it with --force should
300+
v = valtest_test.MakeHappyMapValidator(t)
301+
cmd = newCmdAddLabel(fSys, v.Validator)
302+
err = cmd.Flag("include-selectors").Value.Set("false")
303+
require.NoError(t, err)
304+
err = cmd.Flag("force").Value.Set("true")
305+
require.NoError(t, err)
306+
assert.NoError(t, cmd.RunE(cmd, args))
307+
v.VerifyCall()
308+
}

kustomize/commands/edit/add/all.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func NewCmdAdd(
3939
kustomize edit add base <filepath>
4040
kustomize edit add base <filepath1>,<filepath2>,<filepath3>
4141
42-
# Adds one or more commonLabels to the kustomization
42+
# Adds one or more labels or commonLabels to the kustomization
4343
kustomize edit add label {labelKey1:labelValue1},{labelKey2:labelValue2}
4444
4545
# Adds one or more commonAnnotations to the kustomization

kustomize/commands/edit/set/all.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ func NewCmdSet(fSys filesys.FileSystem, ldr ifc.KvLoader, v ifc.Validator) *cobr
2121
2222
# Sets the namesuffix field
2323
kustomize edit set namesuffix <suffix-value>
24+
25+
# Sets the labels or commonLabels field
26+
kustomize edit set label {labelKey1:labelValue1} {labelKey2:labelValue2}
2427
`,
2528
Args: cobra.MinimumNArgs(1),
2629
}

kustomize/commands/edit/set/setlabel.go

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ import (
1515
)
1616

1717
type setLabelOptions struct {
18-
metadata map[string]string
19-
mapValidator func(map[string]string) error
18+
metadata map[string]string
19+
mapValidator func(map[string]string) error
20+
includeSelectors bool
2021
}
2122

2223
// newCmdSetLabel sets one or more commonLabels to the kustomization file.
@@ -25,14 +26,25 @@ func newCmdSetLabel(fSys filesys.FileSystem, v func(map[string]string) error) *c
2526
o.mapValidator = v
2627
cmd := &cobra.Command{
2728
Use: "label",
28-
Short: "Sets one or more commonLabels in " +
29+
Short: "Sets one or more labels or commonLabels in " +
2930
konfig.DefaultKustomizationFileName(),
3031
Example: `
31-
set label {labelKey1:labelValue1} {labelKey2:labelValue2}`,
32+
# Set commonLabels (default)
33+
set label {labelKey1:labelValue1} {labelKey2:labelValue2}
34+
35+
# Set commonLabels
36+
set label --include-selectors=true {labelKey1:labelValue1} {labelKey2:labelValue2}
37+
38+
# Set labels
39+
set label --include-selectors=false {labelKey1:labelValue1} {labelKey2:labelValue2}
40+
`,
3241
RunE: func(cmd *cobra.Command, args []string) error {
3342
return o.runE(args, fSys, o.setLabels)
3443
},
3544
}
45+
cmd.Flags().BoolVarP(&o.includeSelectors, "include-selectors", "s", true,
46+
"include label in selectors",
47+
)
3648
return cmd
3749
}
3850

@@ -74,10 +86,17 @@ func (o *setLabelOptions) validateAndParse(args []string) error {
7486
}
7587

7688
func (o *setLabelOptions) setLabels(m *types.Kustomization) error {
77-
if m.CommonLabels == nil {
78-
m.CommonLabels = make(map[string]string)
89+
if o.includeSelectors {
90+
if m.CommonLabels == nil {
91+
m.CommonLabels = make(map[string]string)
92+
}
93+
return o.writeToMap(m.CommonLabels)
94+
} else {
95+
if m.Labels == nil {
96+
m.Labels = make([]types.Label, 0)
97+
}
98+
return o.writeToLabelsSlice(&m.Labels)
7999
}
80-
return o.writeToMap(m.CommonLabels)
81100
}
82101

83102
func (o *setLabelOptions) writeToMap(m map[string]string) error {
@@ -86,3 +105,24 @@ func (o *setLabelOptions) writeToMap(m map[string]string) error {
86105
}
87106
return nil
88107
}
108+
109+
func (o *setLabelOptions) writeToLabelsSlice(klabels *[]types.Label) error {
110+
for k, v := range o.metadata {
111+
isPresent := false
112+
for _, kl := range *klabels {
113+
if _, isPresent = kl.Pairs[k]; isPresent {
114+
kl.Pairs[k] = v
115+
break
116+
}
117+
}
118+
if !isPresent {
119+
*klabels = append(*klabels, types.Label{
120+
Pairs: map[string]string{
121+
k: v,
122+
},
123+
IncludeSelectors: o.includeSelectors,
124+
})
125+
}
126+
}
127+
return nil
128+
}

kustomize/commands/edit/set/setlabel_test.go

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package set
55

66
import (
7+
"reflect"
78
"testing"
89

910
valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
@@ -28,26 +29,92 @@ func makeKustomization(t *testing.T) *types.Kustomization {
2829
return m
2930
}
3031

31-
func TestRunSetLabel(t *testing.T) {
32+
func TestRunSetLabels(t *testing.T) {
3233
var o setLabelOptions
34+
o.includeSelectors = true
3335
o.metadata = map[string]string{"owls": "cute", "otters": "adorable"}
3436

3537
m := makeKustomization(t)
3638
err := o.setLabels(m)
3739
if err != nil {
3840
t.Errorf("unexpected error: could not write to kustomization file")
3941
}
42+
43+
// assert content
44+
expectedContent := map[string]string{"app": "helloworld", "owls": "cute", "otters": "adorable"}
45+
if !reflect.DeepEqual(m.CommonLabels, expectedContent) {
46+
t.Log("m.CommonLabels", m.CommonLabels)
47+
t.Log("expectedContent", expectedContent)
48+
t.Errorf("commonLabels does not contain expected content")
49+
}
50+
51+
// adding the same test input should work
52+
err = o.setLabels(m)
53+
if err != nil {
54+
t.Errorf("unexpected error: could not write to kustomization file")
55+
}
56+
// adding new labels should work
57+
o.metadata = map[string]string{"new": "label", "owls": "not cute"}
58+
err = o.setLabels(m)
59+
if err != nil {
60+
t.Errorf("unexpected error: could not write to kustomization file")
61+
}
62+
}
63+
64+
func TestRunSetLabelsNoSelector(t *testing.T) {
65+
var o setLabelOptions
66+
o.includeSelectors = false
67+
o.metadata = map[string]string{"owls": "cute", "otters": "adorable"}
68+
69+
m := makeKustomization(t)
70+
err := o.setLabels(m)
71+
if err != nil {
72+
t.Errorf("unexpected error: could not write to kustomization file")
73+
}
74+
75+
// assert content
76+
expectedContent := make([]types.Label, 2)
77+
expectedContent[0] = types.Label{Pairs: map[string]string{"owls": "cute"}, IncludeSelectors: false}
78+
expectedContent[1] = types.Label{Pairs: map[string]string{"otters": "adorable"}, IncludeSelectors: false}
79+
if !reflect.DeepEqual(m.Labels, expectedContent) {
80+
t.Log("m.Labels", m.Labels)
81+
t.Log("expectedContent", expectedContent)
82+
t.Errorf("labels does not contain expected content")
83+
}
84+
4085
// adding the same test input should work
4186
err = o.setLabels(m)
4287
if err != nil {
4388
t.Errorf("unexpected error: could not write to kustomization file")
4489
}
90+
91+
// assert content
92+
expectedContent2 := make([]types.Label, 2)
93+
expectedContent2[0] = types.Label{Pairs: map[string]string{"owls": "cute"}, IncludeSelectors: false}
94+
expectedContent2[1] = types.Label{Pairs: map[string]string{"otters": "adorable"}, IncludeSelectors: false}
95+
if !reflect.DeepEqual(m.Labels, expectedContent2) {
96+
t.Log("m.Labels", m.Labels)
97+
t.Log("expectedContent", expectedContent2)
98+
t.Errorf("labels does not contain expected content")
99+
}
100+
45101
// adding new labels should work
46102
o.metadata = map[string]string{"new": "label", "owls": "not cute"}
47103
err = o.setLabels(m)
48104
if err != nil {
49105
t.Errorf("unexpected error: could not write to kustomization file")
50106
}
107+
108+
// assert content
109+
expectedContent3 := make([]types.Label, 3)
110+
expectedContent3[0] = types.Label{Pairs: map[string]string{"owls": "not cute"}, IncludeSelectors: false}
111+
expectedContent3[1] = types.Label{Pairs: map[string]string{"otters": "adorable"}, IncludeSelectors: false}
112+
expectedContent3[2] = types.Label{Pairs: map[string]string{"new": "label"}, IncludeSelectors: false}
113+
if !reflect.DeepEqual(m.Labels, expectedContent3) {
114+
t.Log("m.Labels", m.Labels)
115+
t.Log("expectedContent", expectedContent3)
116+
t.Errorf("labels does not contain expected content")
117+
}
51118
}
52119

53120
func TestSetLabelNoArgs(t *testing.T) {

0 commit comments

Comments
 (0)