Skip to content

Commit 70e4d2e

Browse files
committed
fix: make labels handle -f flag same as commonLabels
1 parent bb7a280 commit 70e4d2e

File tree

2 files changed

+192
-43
lines changed

2 files changed

+192
-43
lines changed

kustomize/commands/edit/add/addmetadata.go

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -139,12 +139,7 @@ func (o *addMetadataOptions) addAnnotations(m *types.Kustomization) error {
139139

140140
func (o *addMetadataOptions) addLabels(m *types.Kustomization) error {
141141
if o.labelsWithoutSelector {
142-
m.Labels = append(m.Labels, types.Label{
143-
Pairs: make(map[string]string),
144-
IncludeSelectors: false,
145-
IncludeTemplates: o.includeTemplates,
146-
})
147-
return o.writeToMap(m.Labels[len(m.Labels)-1].Pairs, label)
142+
return o.writeToLabels(m, label)
148143
}
149144
if m.CommonLabels == nil {
150145
m.CommonLabels = make(map[string]string)
@@ -154,10 +149,67 @@ func (o *addMetadataOptions) addLabels(m *types.Kustomization) error {
154149

155150
func (o *addMetadataOptions) writeToMap(m map[string]string, kind kindOfAdd) error {
156151
for k, v := range o.metadata {
157-
if _, ok := m[k]; ok && !o.force {
158-
return fmt.Errorf("%s %s already in kustomization file", kind, k)
152+
if err := o.writeToMapEntry(m, k, v, kind); err != nil {
153+
return err
159154
}
160-
m[k] = v
161155
}
162156
return nil
163157
}
158+
159+
func (o *addMetadataOptions) writeToMapEntry(m map[string]string, k, v string, kind kindOfAdd) error {
160+
if _, ok := m[k]; ok && !o.force {
161+
return fmt.Errorf("%s %s already in kustomization file. Use --force to override.", kind, k)
162+
}
163+
m[k] = v
164+
return nil
165+
}
166+
167+
func (o *addMetadataOptions) writeToLabels(m *types.Kustomization, kind kindOfAdd) error {
168+
lbl := types.Label{
169+
Pairs: make(map[string]string),
170+
IncludeSelectors: false,
171+
IncludeTemplates: o.includeTemplates,
172+
}
173+
for k, v := range o.metadata {
174+
if i, ok := o.findLabelKeyIndex(m, lbl, k); ok {
175+
if err := o.writeToMapEntry(m.Labels[i].Pairs, k, v, kind); err != nil {
176+
return err
177+
}
178+
continue
179+
}
180+
if i, ok := o.findLabelIndex(m, lbl); ok {
181+
if err := o.writeToMapEntry(m.Labels[i].Pairs, k, v, kind); err != nil {
182+
return err
183+
}
184+
continue
185+
}
186+
if err := o.writeToMap(lbl.Pairs, kind); err != nil {
187+
return err
188+
}
189+
m.Labels = append(m.Labels, lbl)
190+
}
191+
return nil
192+
}
193+
194+
func (o *addMetadataOptions) matchLabelSettings(lbl1, lbl2 types.Label) bool {
195+
return lbl1.IncludeSelectors == lbl2.IncludeSelectors &&
196+
lbl1.IncludeTemplates == lbl2.IncludeTemplates
197+
}
198+
199+
func (o *addMetadataOptions) findLabelIndex(m *types.Kustomization, lbl types.Label) (int, bool) {
200+
for i, ml := range m.Labels {
201+
if o.matchLabelSettings(ml, lbl) {
202+
return i, true
203+
}
204+
}
205+
return 0, false
206+
}
207+
208+
func (o *addMetadataOptions) findLabelKeyIndex(m *types.Kustomization, lbl types.Label, key string) (int, bool) {
209+
if i, found := o.findLabelIndex(m, lbl); found {
210+
if _, ok := m.Labels[i].Pairs[key]; ok {
211+
return i, true
212+
}
213+
}
214+
return 0, false
215+
}

kustomize/commands/edit/add/addmetadata_test.go

Lines changed: 131 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ func TestAddAnnotationForce(t *testing.T) {
161161
err := cmd.RunE(cmd, args)
162162
v.VerifyCall()
163163
require.Error(t, err)
164-
assert.Equal(t, "annotation key already in kustomization file", err.Error())
164+
assert.Equal(t, "annotation key already in kustomization file. Use --force to override.", err.Error())
165165
// but trying to add it with --force should
166166
v = valtest_test.MakeHappyMapValidator(t)
167167
cmd = newCmdAddAnnotation(fSys, v.Validator)
@@ -265,7 +265,7 @@ func TestAddLabelForce(t *testing.T) {
265265
err := cmd.RunE(cmd, args)
266266
v.VerifyCall()
267267
require.Error(t, err)
268-
assert.Equal(t, "label key already in kustomization file", err.Error())
268+
assert.Equal(t, "label key already in kustomization file. Use --force to override.", err.Error())
269269
// but trying to add it with --force should
270270
v = valtest_test.MakeHappyMapValidator(t)
271271
cmd = newCmdAddLabel(fSys, v.Validator)
@@ -275,25 +275,6 @@ func TestAddLabelForce(t *testing.T) {
275275
v.VerifyCall()
276276
}
277277

278-
func TestAddLabelWithoutSelector(t *testing.T) {
279-
var o addMetadataOptions
280-
o.labelsWithoutSelector = true
281-
m := makeKustomization(t)
282-
o.metadata = map[string]string{"new": "label"}
283-
require.NoError(t, o.addLabels(m))
284-
assert.Equal(t, m.Labels[0], types.Label{Pairs: map[string]string{"new": "label"}})
285-
}
286-
287-
func TestAddLabelWithoutSelectorIncludeTemplates(t *testing.T) {
288-
var o addMetadataOptions
289-
o.labelsWithoutSelector = true
290-
m := makeKustomization(t)
291-
o.metadata = map[string]string{"new": "label"}
292-
o.includeTemplates = true
293-
require.NoError(t, o.addLabels(m))
294-
assert.Equal(t, m.Labels[0], types.Label{Pairs: map[string]string{"new": "label"}, IncludeTemplates: true})
295-
}
296-
297278
func TestAddLabelIncludeTemplatesWithoutRequiredFlag(t *testing.T) {
298279
fSys := filesys.MakeFsInMemory()
299280
v := valtest_test.MakeHappyMapValidator(t)
@@ -307,17 +288,133 @@ func TestAddLabelIncludeTemplatesWithoutRequiredFlag(t *testing.T) {
307288
require.Containsf(t, err.Error(), "--without-selector flag must be specified for --include-templates to work", "incorrect error: %s", err.Error())
308289
}
309290

310-
func TestAddLabelWithoutSelectorAddLabel(t *testing.T) {
311-
var o addMetadataOptions
312-
o.metadata = map[string]string{"owls": "cute", "otters": "adorable"}
313-
o.labelsWithoutSelector = true
314-
315-
m := makeKustomization(t)
316-
require.NoError(t, o.addLabels(m))
317-
// adding new labels should work
318-
o.metadata = map[string]string{"new": "label"}
319-
require.NoError(t, o.addLabels(m))
320-
321-
assert.Equal(t, m.Labels[0], types.Label{Pairs: map[string]string{"owls": "cute", "otters": "adorable"}})
322-
assert.Equal(t, m.Labels[1], types.Label{Pairs: map[string]string{"new": "label"}})
291+
func TestAddLabelWithoutSelector(t *testing.T) {
292+
tests := []struct {
293+
name string
294+
baseLabels []types.Label // original labels
295+
options addMetadataOptions // add labels
296+
metadata map[string]string // added labels
297+
expected []types.Label // expected labels
298+
expectedErr string
299+
}{
300+
{
301+
name: "add to empty labels",
302+
baseLabels: []types.Label{},
303+
options: addMetadataOptions{
304+
labelsWithoutSelector: true,
305+
metadata: map[string]string{"new": "label"},
306+
},
307+
expected: []types.Label{
308+
{
309+
Pairs: map[string]string{"new": "label"},
310+
},
311+
},
312+
},
313+
{
314+
name: "add to empty labels with IncludeTemplates",
315+
baseLabels: []types.Label{},
316+
options: addMetadataOptions{
317+
labelsWithoutSelector: true,
318+
includeTemplates: true,
319+
metadata: map[string]string{"new": "label"},
320+
},
321+
expected: []types.Label{
322+
{
323+
Pairs: map[string]string{"new": "label"},
324+
IncludeTemplates: true,
325+
},
326+
},
327+
},
328+
{
329+
name: "overwrite label requires force",
330+
baseLabels: []types.Label{
331+
{
332+
Pairs: map[string]string{"key1": "old-value1"},
333+
},
334+
},
335+
options: addMetadataOptions{
336+
labelsWithoutSelector: true,
337+
force: false,
338+
metadata: map[string]string{"key1": "new-value1"},
339+
},
340+
expectedErr: "label key1 already in kustomization file",
341+
},
342+
{
343+
name: "overwrite label",
344+
baseLabels: []types.Label{
345+
{
346+
Pairs: map[string]string{"key1": "old-value1"},
347+
},
348+
},
349+
options: addMetadataOptions{
350+
labelsWithoutSelector: true,
351+
force: true,
352+
metadata: map[string]string{"key1": "new-value1"},
353+
},
354+
expected: []types.Label{
355+
{
356+
Pairs: map[string]string{"key1": "new-value1"},
357+
},
358+
},
359+
},
360+
{
361+
name: "overwrite and add label",
362+
baseLabels: []types.Label{
363+
{
364+
Pairs: map[string]string{"key1": "old-value1"},
365+
},
366+
},
367+
options: addMetadataOptions{
368+
labelsWithoutSelector: true,
369+
force: true,
370+
metadata: map[string]string{"key1": "new-value1", "key2": "value2"},
371+
},
372+
expected: []types.Label{
373+
{
374+
Pairs: map[string]string{"key1": "new-value1", "key2": "value2"},
375+
},
376+
},
377+
},
378+
{
379+
name: "overwrite label with same settings",
380+
baseLabels: []types.Label{
381+
{
382+
Pairs: map[string]string{"key": "old-value"},
383+
},
384+
{
385+
IncludeTemplates: true,
386+
Pairs: map[string]string{"key": "old-value"},
387+
},
388+
},
389+
options: addMetadataOptions{
390+
labelsWithoutSelector: true,
391+
force: true,
392+
metadata: map[string]string{"key": "new-value"},
393+
includeTemplates: true,
394+
},
395+
expected: []types.Label{
396+
{
397+
Pairs: map[string]string{"key": "old-value"},
398+
},
399+
{
400+
IncludeTemplates: true,
401+
Pairs: map[string]string{"key": "new-value"},
402+
},
403+
},
404+
},
405+
}
406+
for _, tt := range tests {
407+
t.Run(tt.name, func(t *testing.T) {
408+
m := makeKustomization(t)
409+
m.Labels = tt.baseLabels
410+
err := tt.options.addLabels(m)
411+
if tt.expectedErr != "" {
412+
require.Error(t, err)
413+
assert.Contains(t, err.Error(), tt.expectedErr)
414+
} else {
415+
require.NoError(t, err)
416+
assert.Equal(t, tt.expected, m.Labels)
417+
}
418+
})
419+
}
323420
}

0 commit comments

Comments
 (0)