1
2
3
4 package resmap_test
5
6 import (
7 "bytes"
8 "fmt"
9 "reflect"
10 "strings"
11 "testing"
12
13 "github.com/stretchr/testify/assert"
14 "github.com/stretchr/testify/require"
15 "sigs.k8s.io/kustomize/api/filters/labels"
16 "sigs.k8s.io/kustomize/api/provider"
17 . "sigs.k8s.io/kustomize/api/resmap"
18 "sigs.k8s.io/kustomize/api/resource"
19 kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
20 resmaptest_test "sigs.k8s.io/kustomize/api/testutils/resmaptest"
21 "sigs.k8s.io/kustomize/api/types"
22 "sigs.k8s.io/kustomize/kyaml/kio"
23 "sigs.k8s.io/kustomize/kyaml/resid"
24 "sigs.k8s.io/kustomize/kyaml/yaml"
25 )
26
27 var depProvider = provider.NewDefaultDepProvider()
28 var rf = depProvider.GetResourceFactory()
29 var rmF = NewFactory(rf)
30 var origin1 = &resource.Origin{
31 Repo: "github.com/myrepo",
32 Ref: "master",
33 ConfiguredIn: "config.yaml",
34 ConfiguredBy: yaml.ResourceIdentifier{
35 TypeMeta: yaml.TypeMeta{
36 APIVersion: "builtin",
37 Kind: "Generator",
38 },
39 NameMeta: yaml.NameMeta{
40 Name: "my-name",
41 Namespace: "my-namespace",
42 },
43 },
44 }
45 var origin2 = &resource.Origin{
46 ConfiguredIn: "../base/config.yaml",
47 ConfiguredBy: yaml.ResourceIdentifier{
48 TypeMeta: yaml.TypeMeta{
49 APIVersion: "builtin",
50 Kind: "Generator",
51 },
52 NameMeta: yaml.NameMeta{
53 Name: "my-name",
54 Namespace: "my-namespace",
55 },
56 },
57 }
58
59 func doAppend(t *testing.T, w ResMap, r *resource.Resource) {
60 t.Helper()
61 err := w.Append(r)
62 if err != nil {
63 t.Fatalf("append error: %v", err)
64 }
65 }
66 func doRemove(t *testing.T, w ResMap, id resid.ResId) {
67 t.Helper()
68 err := w.Remove(id)
69 if err != nil {
70 t.Fatalf("remove error: %v", err)
71 }
72 }
73
74
75 func makeCm(i int) *resource.Resource {
76 return rf.FromMap(
77 map[string]interface{}{
78 "apiVersion": "v1",
79 "kind": "ConfigMap",
80 "metadata": map[string]interface{}{
81 "name": fmt.Sprintf("cm%03d", i),
82 },
83 })
84 }
85
86
87
88 func TestAppendRejectsDuplicateResId(t *testing.T) {
89 w := New()
90 if err := w.Append(makeCm(1)); err != nil {
91 t.Fatalf("append error: %v", err)
92 }
93 err := w.Append(makeCm(1))
94 if err == nil {
95 t.Fatalf("expected append error")
96 }
97 if !strings.Contains(
98 err.Error(),
99 "may not add resource with an already registered id") {
100 t.Fatalf("unexpected error: %v", err)
101 }
102 }
103
104 func TestAppendRemove(t *testing.T) {
105 w1 := New()
106 doAppend(t, w1, makeCm(1))
107 doAppend(t, w1, makeCm(2))
108 doAppend(t, w1, makeCm(3))
109 doAppend(t, w1, makeCm(4))
110 doAppend(t, w1, makeCm(5))
111 doAppend(t, w1, makeCm(6))
112 doAppend(t, w1, makeCm(7))
113 doRemove(t, w1, makeCm(1).OrgId())
114 doRemove(t, w1, makeCm(3).OrgId())
115 doRemove(t, w1, makeCm(5).OrgId())
116 doRemove(t, w1, makeCm(7).OrgId())
117
118 w2 := New()
119 doAppend(t, w2, makeCm(2))
120 doAppend(t, w2, makeCm(4))
121 doAppend(t, w2, makeCm(6))
122 if !reflect.DeepEqual(w1, w2) {
123 w1.Debug("w1")
124 w2.Debug("w2")
125 t.Fatalf("mismatch")
126 }
127
128 err := w2.Append(makeCm(6))
129 if err == nil {
130 t.Fatalf("expected error")
131 }
132 }
133
134 func TestRemove(t *testing.T) {
135 w := New()
136 r := makeCm(1)
137 err := w.Remove(r.OrgId())
138 if err == nil {
139 t.Fatalf("expected error")
140 }
141 err = w.Append(r)
142 if err != nil {
143 t.Fatalf("unexpected error: %v", err)
144 }
145 err = w.Remove(r.OrgId())
146 if err != nil {
147 t.Fatalf("unexpected error: %v", err)
148 }
149 err = w.Remove(r.OrgId())
150 if err == nil {
151 t.Fatalf("expected error")
152 }
153 }
154
155 func TestReplace(t *testing.T) {
156 cm5 := makeCm(5)
157 cm700 := makeCm(700)
158 otherCm5 := makeCm(5)
159
160 w := New()
161 doAppend(t, w, makeCm(1))
162 doAppend(t, w, makeCm(2))
163 doAppend(t, w, makeCm(3))
164 doAppend(t, w, makeCm(4))
165 doAppend(t, w, cm5)
166 doAppend(t, w, makeCm(6))
167 doAppend(t, w, makeCm(7))
168
169 oldSize := w.Size()
170 _, err := w.Replace(otherCm5)
171 if err != nil {
172 t.Fatalf("unexpected error: %v", err)
173 }
174 if w.Size() != oldSize {
175 t.Fatalf("unexpected size %d", w.Size())
176 }
177 if r, err := w.GetByCurrentId(cm5.OrgId()); err != nil || r != otherCm5 {
178 t.Fatalf("unexpected result r=%s, err=%v", r.CurId(), err)
179 }
180 if err := w.Append(cm5); err == nil {
181 t.Fatalf("expected id already there error")
182 }
183 if err := w.Remove(cm5.OrgId()); err != nil {
184 t.Fatalf("unexpected err: %v", err)
185 }
186 if err := w.Append(cm700); err != nil {
187 t.Fatalf("unexpected err: %v", err)
188 }
189 if err := w.Append(cm5); err != nil {
190 t.Fatalf("unexpected err: %v", err)
191 }
192 }
193
194 func TestEncodeAsYaml(t *testing.T) {
195 encoded := []byte(`apiVersion: v1
196 kind: ConfigMap
197 metadata:
198 name: cm1
199 ---
200 apiVersion: v1
201 kind: ConfigMap
202 metadata:
203 name: cm2
204 `)
205 input := resmaptest_test.NewRmBuilder(t, rf).Add(
206 map[string]interface{}{
207 "apiVersion": "v1",
208 "kind": "ConfigMap",
209 "metadata": map[string]interface{}{
210 "name": "cm1",
211 },
212 }).Add(
213 map[string]interface{}{
214 "apiVersion": "v1",
215 "kind": "ConfigMap",
216 "metadata": map[string]interface{}{
217 "name": "cm2",
218 },
219 }).ResMap()
220 out, err := input.AsYaml()
221 if err != nil {
222 t.Fatalf("unexpected error: %v", err)
223 }
224 if !reflect.DeepEqual(out, encoded) {
225 t.Fatalf("%s doesn't match expected %s", out, encoded)
226 }
227 }
228
229 func TestGetMatchingResourcesByCurrentId(t *testing.T) {
230 cmap := resid.NewGvk("", "v1", "ConfigMap")
231
232 r1 := rf.FromMap(
233 map[string]interface{}{
234 "apiVersion": "v1",
235 "kind": "ConfigMap",
236 "metadata": map[string]interface{}{
237 "name": "alice",
238 },
239 })
240 r2 := rf.FromMap(
241 map[string]interface{}{
242 "apiVersion": "v1",
243 "kind": "ConfigMap",
244 "metadata": map[string]interface{}{
245 "name": "bob",
246 },
247 })
248 r3 := rf.FromMap(
249 map[string]interface{}{
250 "apiVersion": "v1",
251 "kind": "ConfigMap",
252 "metadata": map[string]interface{}{
253 "name": "bob",
254 "namespace": "happy",
255 },
256 })
257 r4 := rf.FromMap(
258 map[string]interface{}{
259 "apiVersion": "v1",
260 "kind": "ConfigMap",
261 "metadata": map[string]interface{}{
262 "name": "charlie",
263 "namespace": "happy",
264 },
265 })
266 r5 := rf.FromMap(
267 map[string]interface{}{
268 "apiVersion": "v1",
269 "kind": "Deployment",
270 "metadata": map[string]interface{}{
271 "name": "charlie",
272 "namespace": "happy",
273 },
274 })
275
276 m := resmaptest_test.NewRmBuilder(t, rf).
277 AddR(r1).AddR(r2).AddR(r3).AddR(r4).AddR(r5).ResMap()
278
279 result := m.GetMatchingResourcesByCurrentId(
280 resid.NewResId(cmap, "alice").GvknEquals)
281 if len(result) != 1 {
282 t.Fatalf("Expected single map entry but got %v", result)
283 }
284 result = m.GetMatchingResourcesByCurrentId(
285 resid.NewResId(cmap, "bob").GvknEquals)
286 if len(result) != 2 {
287 t.Fatalf("Expected two, got %v", result)
288 }
289 result = m.GetMatchingResourcesByCurrentId(
290 resid.NewResIdWithNamespace(cmap, "bob", "system").GvknEquals)
291 if len(result) != 2 {
292 t.Fatalf("Expected two but got %v", result)
293 }
294 result = m.GetMatchingResourcesByCurrentId(
295 resid.NewResIdWithNamespace(cmap, "bob", "happy").Equals)
296 if len(result) != 1 {
297 t.Fatalf("Expected single map entry but got %v", result)
298 }
299 result = m.GetMatchingResourcesByCurrentId(
300 resid.NewResId(cmap, "charlie").GvknEquals)
301 if len(result) != 1 {
302 t.Fatalf("Expected single map entry but got %v", result)
303 }
304
305
306 tests := []struct {
307 name string
308 matcher IdMatcher
309 count int
310 }{
311 {
312 "match everything",
313 func(resid.ResId) bool { return true },
314 5,
315 },
316 {
317 "match nothing",
318 func(resid.ResId) bool { return false },
319 0,
320 },
321 {
322 "name is alice",
323 func(x resid.ResId) bool { return x.Name == "alice" },
324 1,
325 },
326 {
327 "name is charlie",
328 func(x resid.ResId) bool { return x.Name == "charlie" },
329 2,
330 },
331 {
332 "name is bob",
333 func(x resid.ResId) bool { return x.Name == "bob" },
334 2,
335 },
336 {
337 "happy namespace",
338 func(x resid.ResId) bool {
339 return x.Namespace == "happy"
340 },
341 3,
342 },
343 {
344 "happy deployment",
345 func(x resid.ResId) bool {
346 return x.Namespace == "happy" &&
347 x.Gvk.Kind == "Deployment"
348 },
349 1,
350 },
351 {
352 "happy ConfigMap",
353 func(x resid.ResId) bool {
354 return x.Namespace == "happy" &&
355 x.Gvk.Kind == "ConfigMap"
356 },
357 2,
358 },
359 }
360 for _, tst := range tests {
361 result := m.GetMatchingResourcesByCurrentId(tst.matcher)
362 if len(result) != tst.count {
363 t.Fatalf("test '%s'; actual: %d, expected: %d",
364 tst.name, len(result), tst.count)
365 }
366 }
367 }
368
369 func TestGetMatchingResourcesByAnyId(t *testing.T) {
370 r1 := rf.FromMap(
371 map[string]interface{}{
372 "apiVersion": "v1",
373 "kind": "ConfigMap",
374 "metadata": map[string]interface{}{
375 "name": "new-alice",
376 "annotations": map[string]interface{}{
377 "internal.config.kubernetes.io/previousKinds": "ConfigMap",
378 "internal.config.kubernetes.io/previousNames": "alice",
379 "internal.config.kubernetes.io/previousNamespaces": "default",
380 },
381 },
382 })
383 r2 := rf.FromMap(
384 map[string]interface{}{
385 "apiVersion": "v1",
386 "kind": "ConfigMap",
387 "metadata": map[string]interface{}{
388 "name": "new-bob",
389 "annotations": map[string]interface{}{
390 "internal.config.kubernetes.io/previousKinds": "ConfigMap,ConfigMap",
391 "internal.config.kubernetes.io/previousNames": "bob,bob2",
392 "internal.config.kubernetes.io/previousNamespaces": "default,default",
393 },
394 },
395 })
396 r3 := rf.FromMap(
397 map[string]interface{}{
398 "apiVersion": "v1",
399 "kind": "ConfigMap",
400 "metadata": map[string]interface{}{
401 "name": "new-bob",
402 "namespace": "new-happy",
403 "annotations": map[string]interface{}{
404 "internal.config.kubernetes.io/previousKinds": "ConfigMap",
405 "internal.config.kubernetes.io/previousNames": "bob",
406 "internal.config.kubernetes.io/previousNamespaces": "happy",
407 },
408 },
409 })
410 r4 := rf.FromMap(
411 map[string]interface{}{
412 "apiVersion": "v1",
413 "kind": "ConfigMap",
414 "metadata": map[string]interface{}{
415 "name": "charlie",
416 "namespace": "happy",
417 "annotations": map[string]interface{}{
418 "internal.config.kubernetes.io/previousKinds": "ConfigMap",
419 "internal.config.kubernetes.io/previousNames": "charlie",
420 "internal.config.kubernetes.io/previousNamespaces": "default",
421 },
422 },
423 })
424 r5 := rf.FromMap(
425 map[string]interface{}{
426 "apiVersion": "v1",
427 "kind": "Deployment",
428 "metadata": map[string]interface{}{
429 "name": "charlie",
430 "namespace": "happy",
431 },
432 })
433
434 m := resmaptest_test.NewRmBuilder(t, rf).
435 AddR(r1).AddR(r2).AddR(r3).AddR(r4).AddR(r5).ResMap()
436
437 tests := []struct {
438 name string
439 matcher IdMatcher
440 count int
441 }{
442 {
443 "match everything",
444 func(resid.ResId) bool { return true },
445 5,
446 },
447 {
448 "match nothing",
449 func(resid.ResId) bool { return false },
450 0,
451 },
452 {
453 "name is alice",
454 func(x resid.ResId) bool { return x.Name == "alice" },
455 1,
456 },
457 {
458 "name is charlie",
459 func(x resid.ResId) bool { return x.Name == "charlie" },
460 2,
461 },
462 {
463 "name is bob",
464 func(x resid.ResId) bool { return x.Name == "bob" },
465 2,
466 },
467 {
468 "happy namespace",
469 func(x resid.ResId) bool {
470 return x.Namespace == "happy"
471 },
472 3,
473 },
474 {
475 "happy deployment",
476 func(x resid.ResId) bool {
477 return x.Namespace == "happy" &&
478 x.Gvk.Kind == "Deployment"
479 },
480 1,
481 },
482 {
483 "happy ConfigMap",
484 func(x resid.ResId) bool {
485 return x.Namespace == "happy" &&
486 x.Gvk.Kind == "ConfigMap"
487 },
488 2,
489 },
490 }
491 for _, tst := range tests {
492 result := m.GetMatchingResourcesByAnyId(tst.matcher)
493 if len(result) != tst.count {
494 t.Fatalf("test '%s'; actual: %d, expected: %d",
495 tst.name, len(result), tst.count)
496 }
497 }
498 }
499
500 func TestSubsetThatCouldBeReferencedByResource(t *testing.T) {
501 r1 := rf.FromMap(
502 map[string]interface{}{
503 "apiVersion": "v1",
504 "kind": "ConfigMap",
505 "metadata": map[string]interface{}{
506 "name": "alice",
507 },
508 })
509 r2 := rf.FromMap(
510 map[string]interface{}{
511 "apiVersion": "v1",
512 "kind": "ConfigMap",
513 "metadata": map[string]interface{}{
514 "name": "bob",
515 },
516 })
517 r3 := rf.FromMap(
518 map[string]interface{}{
519 "apiVersion": "v1",
520 "kind": "ConfigMap",
521 "metadata": map[string]interface{}{
522 "name": "bob",
523 "namespace": "happy",
524 },
525 })
526 r4 := rf.FromMap(
527 map[string]interface{}{
528 "apiVersion": "apps/v1",
529 "kind": "Deployment",
530 "metadata": map[string]interface{}{
531 "name": "charlie",
532 "namespace": "happy",
533 },
534 })
535 r5 := rf.FromMap(
536 map[string]interface{}{
537 "apiVersion": "v1",
538 "kind": "ConfigMap",
539 "metadata": map[string]interface{}{
540 "name": "charlie",
541 "namespace": "happy",
542 },
543 })
544 r5.AddNamePrefix("little-")
545 r6 := rf.FromMap(
546 map[string]interface{}{
547 "apiVersion": "apps/v1",
548 "kind": "Deployment",
549 "metadata": map[string]interface{}{
550 "name": "domino",
551 "namespace": "happy",
552 },
553 })
554 r6.AddNamePrefix("little-")
555 r7 := rf.FromMap(
556 map[string]interface{}{
557 "apiVersion": "rbac.authorization.k8s.io/v1",
558 "kind": "ClusterRoleBinding",
559 "metadata": map[string]interface{}{
560 "name": "meh",
561 },
562 })
563
564 tests := map[string]struct {
565 filter *resource.Resource
566 expected ResMap
567 }{
568 "default namespace 1": {
569 filter: r2,
570 expected: resmaptest_test.NewRmBuilder(t, rf).
571 AddR(r1).AddR(r2).AddR(r7).ResMap(),
572 },
573 "default namespace 2": {
574 filter: r1,
575 expected: resmaptest_test.NewRmBuilder(t, rf).
576 AddR(r1).AddR(r2).AddR(r7).ResMap(),
577 },
578 "happy namespace no prefix": {
579 filter: r3,
580 expected: resmaptest_test.NewRmBuilder(t, rf).
581 AddR(r3).AddR(r4).AddR(r5).AddR(r6).AddR(r7).ResMap(),
582 },
583 "happy namespace with prefix": {
584 filter: r5,
585 expected: resmaptest_test.NewRmBuilder(t, rf).
586 AddR(r3).AddR(r4).AddR(r5).AddR(r6).AddR(r7).ResMap(),
587 },
588 "cluster level": {
589 filter: r7,
590 expected: resmaptest_test.NewRmBuilder(t, rf).
591 AddR(r1).AddR(r2).AddR(r3).AddR(r4).AddR(r5).AddR(r6).AddR(r7).ResMap(),
592 },
593 }
594 m := resmaptest_test.NewRmBuilder(t, rf).
595 AddR(r1).AddR(r2).AddR(r3).AddR(r4).AddR(r5).AddR(r6).AddR(r7).ResMap()
596 for name, test := range tests {
597 test := test
598 t.Run(name, func(t *testing.T) {
599 got, err1 := m.SubsetThatCouldBeReferencedByResource(test.filter)
600 if err1 != nil {
601 t.Fatalf("Expected error %v: ", err1)
602 }
603 err := test.expected.ErrorIfNotEqualLists(got)
604 if err != nil {
605 test.expected.Debug("expected")
606 got.Debug("actual")
607 t.Fatalf("Expected match")
608 }
609 })
610 }
611 }
612
613 func TestDeepCopy(t *testing.T) {
614 rm1 := resmaptest_test.NewRmBuilder(t, rf).Add(
615 map[string]interface{}{
616 "apiVersion": "v1",
617 "kind": "ConfigMap",
618 "metadata": map[string]interface{}{
619 "name": "cm1",
620 },
621 }).Add(
622 map[string]interface{}{
623 "apiVersion": "v1",
624 "kind": "ConfigMap",
625 "metadata": map[string]interface{}{
626 "name": "cm2",
627 },
628 }).ResMap()
629
630 rm2 := rm1.DeepCopy()
631
632 if &rm1 == &rm2 {
633 t.Fatal("DeepCopy returned a reference to itself instead of a copy")
634 }
635 err := rm1.ErrorIfNotEqualLists(rm1)
636 if err != nil {
637 t.Fatal(err)
638 }
639 }
640
641 func TestErrorIfNotEqualSets(t *testing.T) {
642 r1 := rf.FromMap(
643 map[string]interface{}{
644 "apiVersion": "v1",
645 "kind": "ConfigMap",
646 "metadata": map[string]interface{}{
647 "name": "cm1",
648 },
649 })
650 r2 := rf.FromMap(
651 map[string]interface{}{
652 "apiVersion": "v1",
653 "kind": "ConfigMap",
654 "metadata": map[string]interface{}{
655 "name": "cm2",
656 },
657 })
658 r3 := rf.FromMap(
659 map[string]interface{}{
660 "apiVersion": "v1",
661 "kind": "ConfigMap",
662 "metadata": map[string]interface{}{
663 "name": "cm2",
664 "namespace": "system",
665 },
666 })
667
668 m1 := resmaptest_test.NewRmBuilder(t, rf).AddR(r1).AddR(r2).AddR(r3).ResMap()
669 if err := m1.ErrorIfNotEqualSets(m1); err != nil {
670 t.Fatalf("object should equal itself %v", err)
671 }
672
673 m2 := resmaptest_test.NewRmBuilder(t, rf).AddR(r1).ResMap()
674 if err := m1.ErrorIfNotEqualSets(m2); err == nil {
675 t.Fatalf("%v should not equal %v %v", m1, m2, err)
676 }
677
678 m3 := resmaptest_test.NewRmBuilder(t, rf).AddR(r2).ResMap()
679 if err := m2.ErrorIfNotEqualSets(m3); err == nil {
680 t.Fatalf("%v should not equal %v %v", m2, m3, err)
681 }
682
683 m3 = resmaptest_test.NewRmBuilder(t, rf).Add(
684 map[string]interface{}{
685 "apiVersion": "v1",
686 "kind": "ConfigMap",
687 "metadata": map[string]interface{}{
688 "name": "cm1",
689 }}).ResMap()
690 if err := m2.ErrorIfNotEqualSets(m3); err != nil {
691 t.Fatalf("%v should equal %v %v", m2, m3, err)
692 }
693
694 m4 := resmaptest_test.NewRmBuilder(t, rf).AddR(r1).AddR(r2).AddR(r3).ResMap()
695 if err := m1.ErrorIfNotEqualSets(m4); err != nil {
696 t.Fatalf("expected equality between %v and %v, %v", m1, m4, err)
697 }
698
699 m4 = resmaptest_test.NewRmBuilder(t, rf).AddR(r3).AddR(r1).AddR(r2).ResMap()
700 if err := m1.ErrorIfNotEqualSets(m4); err != nil {
701 t.Fatalf("expected equality between %v and %v, %v", m1, m4, err)
702 }
703
704 m4 = m1.ShallowCopy()
705 if err := m1.ErrorIfNotEqualSets(m4); err != nil {
706 t.Fatalf("expected equality between %v and %v, %v", m1, m4, err)
707 }
708 m4 = m1.DeepCopy()
709 if err := m1.ErrorIfNotEqualSets(m4); err != nil {
710 t.Fatalf("expected equality between %v and %v, %v", m1, m4, err)
711 }
712 }
713
714 func TestErrorIfNotEqualLists(t *testing.T) {
715 r1 := rf.FromMap(
716 map[string]interface{}{
717 "apiVersion": "v1",
718 "kind": "ConfigMap",
719 "metadata": map[string]interface{}{
720 "name": "cm1",
721 },
722 })
723 r2 := rf.FromMap(
724 map[string]interface{}{
725 "apiVersion": "v1",
726 "kind": "ConfigMap",
727 "metadata": map[string]interface{}{
728 "name": "cm2",
729 },
730 })
731 r3 := rf.FromMap(
732 map[string]interface{}{
733 "apiVersion": "v1",
734 "kind": "ConfigMap",
735 "metadata": map[string]interface{}{
736 "name": "cm2",
737 "namespace": "system",
738 },
739 })
740
741 m1 := resmaptest_test.NewRmBuilder(t, rf).AddR(r1).AddR(r2).AddR(r3).ResMap()
742 if err := m1.ErrorIfNotEqualLists(m1); err != nil {
743 t.Fatalf("object should equal itself %v", err)
744 }
745
746 m2 := resmaptest_test.NewRmBuilder(t, rf).AddR(r1).ResMap()
747 if err := m1.ErrorIfNotEqualLists(m2); err == nil {
748 t.Fatalf("%v should not equal %v %v", m1, m2, err)
749 }
750
751 m3 := resmaptest_test.NewRmBuilder(t, rf).Add(
752 map[string]interface{}{
753 "apiVersion": "v1",
754 "kind": "ConfigMap",
755 "metadata": map[string]interface{}{
756 "name": "cm1",
757 }}).ResMap()
758 if err := m2.ErrorIfNotEqualLists(m3); err != nil {
759 t.Fatalf("%v should equal %v %v", m2, m3, err)
760 }
761
762 m4 := resmaptest_test.NewRmBuilder(t, rf).AddR(r1).AddR(r2).AddR(r3).ResMap()
763 if err := m1.ErrorIfNotEqualLists(m4); err != nil {
764 t.Fatalf("expected equality between %v and %v, %v", m1, m4, err)
765 }
766
767 m4 = resmaptest_test.NewRmBuilder(t, rf).AddR(r3).AddR(r1).AddR(r2).ResMap()
768 if err := m1.ErrorIfNotEqualLists(m4); err == nil {
769 t.Fatalf("expected inequality between %v and %v, %v", m1, m4, err)
770 }
771
772 m4 = m1.ShallowCopy()
773 if err := m1.ErrorIfNotEqualLists(m4); err != nil {
774 t.Fatalf("expected equality between %v and %v, %v", m1, m4, err)
775 }
776 m4 = m1.DeepCopy()
777 if err := m1.ErrorIfNotEqualLists(m4); err != nil {
778 t.Fatalf("expected equality between %v and %v, %v", m1, m4, err)
779 }
780 }
781
782 func TestAppendAll(t *testing.T) {
783 r1 := rf.FromMap(
784 map[string]interface{}{
785 "apiVersion": "apps/v1",
786 "kind": "Deployment",
787 "metadata": map[string]interface{}{
788 "name": "foo-deploy1",
789 },
790 })
791 input1 := rmF.FromResource(r1)
792 r2 := rf.FromMap(
793 map[string]interface{}{
794 "apiVersion": "apps/v1",
795 "kind": "StatefulSet",
796 "metadata": map[string]interface{}{
797 "name": "bar-stateful",
798 },
799 })
800 input2 := rmF.FromResource(r2)
801
802 expected := New()
803 if err := expected.Append(r1); err != nil {
804 t.Fatalf("unexpected error: %v", err)
805 }
806 if err := expected.Append(r2); err != nil {
807 t.Fatalf("unexpected error: %v", err)
808 }
809
810 if err := input1.AppendAll(input2); err != nil {
811 t.Fatalf("unexpected error: %v", err)
812 }
813 if err := expected.ErrorIfNotEqualLists(input1); err != nil {
814 input1.Debug("1")
815 expected.Debug("ex")
816 t.Fatalf("%#v doesn't equal expected %#v", input1, expected)
817 }
818 if err := input1.AppendAll(nil); err != nil {
819 t.Fatalf("unexpected error: %v", err)
820 }
821 if err := expected.ErrorIfNotEqualLists(input1); err != nil {
822 t.Fatalf("%#v doesn't equal expected %#v", input1, expected)
823 }
824 }
825
826 func makeMap1(t *testing.T) ResMap {
827 t.Helper()
828 r, err := rf.FromMapAndOption(
829 map[string]interface{}{
830 "apiVersion": "apps/v1",
831 "kind": "ConfigMap",
832 "metadata": map[string]interface{}{
833 "name": "cmap",
834 },
835 "data": map[string]interface{}{
836 "a": "x",
837 "b": "y",
838 },
839 }, &types.GeneratorArgs{
840 Behavior: "create",
841 })
842 if err != nil {
843 t.Fatalf("expected new intance with an options but got error: %v", err)
844 }
845 return rmF.FromResource(r)
846 }
847
848 func makeMap2(t *testing.T, b types.GenerationBehavior) ResMap {
849 t.Helper()
850 r, err := rf.FromMapAndOption(
851 map[string]interface{}{
852 "apiVersion": "apps/v1",
853 "kind": "ConfigMap",
854 "metadata": map[string]interface{}{
855 "name": "cmap",
856 },
857 "data": map[string]interface{}{
858 "a": "u",
859 "b": "v",
860 "c": "w",
861 },
862 }, &types.GeneratorArgs{
863 Behavior: b.String(),
864 })
865 if err != nil {
866 t.Fatalf("expected new intance with an options but got error: %v", err)
867 }
868 return rmF.FromResource(r)
869 }
870
871 func TestAbsorbAll(t *testing.T) {
872 metadata := map[string]interface{}{
873 "name": "cmap",
874 }
875
876 r, err := rf.FromMapAndOption(
877 map[string]interface{}{
878 "apiVersion": "apps/v1",
879 "kind": "ConfigMap",
880 "metadata": metadata,
881 "data": map[string]interface{}{
882 "a": "u",
883 "b": "v",
884 "c": "w",
885 },
886 },
887 &types.GeneratorArgs{
888 Behavior: "create",
889 })
890 if err != nil {
891 t.Fatalf("expected new intance with an options but got error: %v", err)
892 }
893 expected := rmF.FromResource(r)
894 w := makeMap1(t)
895 require.NoError(t, w.AbsorbAll(makeMap2(t, types.BehaviorMerge)))
896 expected.RemoveBuildAnnotations()
897 w.RemoveBuildAnnotations()
898 require.NoError(t, expected.ErrorIfNotEqualLists(w))
899 w = makeMap1(t)
900 require.NoError(t, w.AbsorbAll(nil))
901 require.NoError(t, w.ErrorIfNotEqualLists(makeMap1(t)))
902
903 w = makeMap1(t)
904 w2 := makeMap2(t, types.BehaviorReplace)
905 require.NoError(t, w.AbsorbAll(w2))
906 w2.RemoveBuildAnnotations()
907 require.NoError(t, w2.ErrorIfNotEqualLists(w))
908 err = makeMap1(t).AbsorbAll(makeMap2(t, types.BehaviorUnspecified))
909 require.Error(t, err)
910 assert.True(
911 t, strings.Contains(err.Error(), "behavior must be merge or replace"))
912 }
913
914 func TestToRNodeSlice(t *testing.T) {
915 input := `apiVersion: rbac.authorization.k8s.io/v1
916 kind: ClusterRole
917 metadata:
918 name: namespace-reader
919 rules:
920 - apiGroups:
921 - ""
922 resources:
923 - namespaces
924 verbs:
925 - get
926 - watch
927 - list
928 `
929 rm, err := rmF.NewResMapFromBytes([]byte(input))
930 if err != nil {
931 t.Fatalf("unexpected error: %v", err)
932 }
933 b := bytes.NewBufferString("")
934 for i, n := range rm.ToRNodeSlice() {
935 if i != 0 {
936 b.WriteString("---\n")
937 }
938 s, err := n.String()
939 if err != nil {
940 t.Fatalf("unexpected error: %v", err)
941 }
942 b.WriteString(s)
943 }
944
945 if !reflect.DeepEqual(input, b.String()) {
946 t.Fatalf("actual doesn't match expected.\nActual:\n%s\n===\nExpected:\n%s\n",
947 b.String(), input)
948 }
949 }
950
951 func TestDeAnchorSingleDoc(t *testing.T) {
952 input := `apiVersion: v1
953 kind: ConfigMap
954 metadata:
955 name: wildcard
956 data:
957 color: &color-used blue
958 feeling: *color-used
959 `
960 rm, err := rmF.NewResMapFromBytes([]byte(input))
961 require.NoError(t, err)
962 require.NoError(t, rm.DeAnchor())
963 yaml, err := rm.AsYaml()
964 require.NoError(t, err)
965 assert.Equal(t, strings.TrimSpace(`
966 apiVersion: v1
967 data:
968 color: blue
969 feeling: blue
970 kind: ConfigMap
971 metadata:
972 name: wildcard
973 `), strings.TrimSpace(string(yaml)))
974 }
975
976 func TestDeAnchorIntoDoc(t *testing.T) {
977 input := `apiVersion: apps/v1
978 kind: Deployment
979 metadata:
980 name: probes-test
981 spec:
982 template:
983 spec:
984 readinessProbe: &probe
985 periodSeconds: 5
986 timeoutSeconds: 3
987 failureThreshold: 3
988 httpGet:
989 port: http
990 path: /health
991 livenessProbe:
992 <<: *probe
993 `
994 rm, err := rmF.NewResMapFromBytes([]byte(input))
995 require.NoError(t, err)
996 require.NoError(t, rm.DeAnchor())
997 yaml, err := rm.AsYaml()
998 require.NoError(t, err)
999 assert.Equal(t, strings.TrimSpace(`apiVersion: apps/v1
1000 kind: Deployment
1001 metadata:
1002 name: probes-test
1003 spec:
1004 template:
1005 spec:
1006 livenessProbe:
1007 failureThreshold: 3
1008 httpGet:
1009 path: /health
1010 port: http
1011 periodSeconds: 5
1012 timeoutSeconds: 3
1013 readinessProbe:
1014 failureThreshold: 3
1015 httpGet:
1016 path: /health
1017 port: http
1018 periodSeconds: 5
1019 timeoutSeconds: 3
1020 `), strings.TrimSpace(string(yaml)))
1021 }
1022
1023
1024 func TestDeAnchorMultiDoc(t *testing.T) {
1025 input := `apiVersion: v1
1026 kind: ConfigMap
1027 metadata:
1028 name: betty
1029 data:
1030 color: &color-used blue
1031 feeling: *color-used
1032 ---
1033 apiVersion: v1
1034 kind: ConfigMap
1035 metadata:
1036 name: bob
1037 data:
1038 color: red
1039 feeling: *color-used
1040 `
1041 _, err := rmF.NewResMapFromBytes([]byte(input))
1042 require.Error(t, err)
1043 assert.Contains(t, err.Error(), "unknown anchor 'color-used' referenced")
1044 }
1045
1046
1047 func TestDeAnchorResourceList(t *testing.T) {
1048 input := `apiVersion: config.kubernetes.io/v1
1049 kind: ResourceList
1050 metadata:
1051 name: aShortList
1052 items:
1053 - apiVersion: v1
1054 kind: ConfigMap
1055 metadata:
1056 name: betty
1057 data:
1058 color: &color-used blue
1059 feeling: *color-used
1060 - apiVersion: v1
1061 kind: ConfigMap
1062 metadata:
1063 name: bob
1064 data:
1065 color: red
1066 feeling: *color-used
1067 `
1068 rm, err := rmF.NewResMapFromBytes([]byte(input))
1069 require.NoError(t, err)
1070 require.NoError(t, rm.DeAnchor())
1071 yaml, err := rm.AsYaml()
1072 require.NoError(t, err)
1073 assert.Equal(t, strings.TrimSpace(`
1074 apiVersion: v1
1075 data:
1076 color: blue
1077 feeling: blue
1078 kind: ConfigMap
1079 metadata:
1080 name: betty
1081 ---
1082 apiVersion: v1
1083 data:
1084 color: red
1085 feeling: blue
1086 kind: ConfigMap
1087 metadata:
1088 name: bob
1089 `), strings.TrimSpace(string(yaml)))
1090 }
1091
1092 func TestApplySmPatch_General(t *testing.T) {
1093 const (
1094 myDeployment = "Deployment"
1095 myCRD = "myCRD"
1096 expectedResultSMP = `apiVersion: apps/v1
1097 kind: Deployment
1098 metadata:
1099 name: deploy1
1100 spec:
1101 template:
1102 metadata:
1103 labels:
1104 old-label: old-value
1105 some-label: some-value
1106 spec:
1107 containers:
1108 - env:
1109 - name: SOMEENV
1110 value: SOMEVALUE
1111 image: nginx
1112 name: nginx
1113 `
1114 )
1115 tests := map[string]struct {
1116 base []string
1117 patches []string
1118 expected []string
1119 errorExpected bool
1120 errorMsg string
1121 }{
1122 "clown": {
1123 base: []string{`apiVersion: v1
1124 kind: Deployment
1125 metadata:
1126 name: clown
1127 spec:
1128 numReplicas: 1
1129 `,
1130 },
1131 patches: []string{`apiVersion: v1
1132 kind: Deployment
1133 metadata:
1134 name: clown
1135 spec:
1136 numReplicas: 999
1137 `,
1138 },
1139 errorExpected: false,
1140 expected: []string{
1141 `apiVersion: v1
1142 kind: Deployment
1143 metadata:
1144 name: clown
1145 spec:
1146 numReplicas: 999
1147 `,
1148 },
1149 },
1150 "confusion": {
1151 base: []string{`apiVersion: example.com/v1
1152 kind: Foo
1153 metadata:
1154 name: my-foo
1155 spec:
1156 bar:
1157 A: X
1158 B: Y
1159 `,
1160 },
1161 patches: []string{`apiVersion: example.com/v1
1162 kind: Foo
1163 metadata:
1164 name: my-foo
1165 spec:
1166 bar:
1167 B:
1168 C: Z
1169 `, `apiVersion: example.com/v1
1170 kind: Foo
1171 metadata:
1172 name: my-foo
1173 spec:
1174 bar:
1175 C: Z
1176 D: W
1177 baz:
1178 hello: world
1179 `,
1180 },
1181 errorExpected: false,
1182 expected: []string{
1183 `apiVersion: example.com/v1
1184 kind: Foo
1185 metadata:
1186 name: my-foo
1187 spec:
1188 bar:
1189 A: X
1190 C: Z
1191 D: W
1192 baz:
1193 hello: world
1194 `,
1195 },
1196 },
1197 "withschema-ns1-ns2-one": {
1198 base: []string{
1199 addNamespace("ns1", baseResource(myDeployment)),
1200 addNamespace("ns2", baseResource(myDeployment)),
1201 },
1202 patches: []string{
1203 addNamespace("ns1", addLabelAndEnvPatch(myDeployment)),
1204 addNamespace("ns2", addLabelAndEnvPatch(myDeployment)),
1205 },
1206 errorExpected: false,
1207 expected: []string{
1208 addNamespace("ns1", expectedResultSMP),
1209 addNamespace("ns2", expectedResultSMP),
1210 },
1211 },
1212 "withschema-ns1-ns2-two": {
1213 base: []string{
1214 addNamespace("ns1", baseResource(myDeployment)),
1215 },
1216 patches: []string{
1217 addNamespace("ns2", changeImagePatch(myDeployment)),
1218 },
1219 expected: []string{
1220 addNamespace("ns1", baseResource(myDeployment)),
1221 },
1222 },
1223 "withschema-ns1-ns2-three": {
1224 base: []string{
1225 addNamespace("ns1", baseResource(myDeployment)),
1226 },
1227 patches: []string{
1228 addNamespace("ns1", changeImagePatch(myDeployment)),
1229 },
1230 expected: []string{
1231 `apiVersion: apps/v1
1232 kind: Deployment
1233 metadata:
1234 name: deploy1
1235 namespace: ns1
1236 spec:
1237 template:
1238 metadata:
1239 labels:
1240 old-label: old-value
1241 spec:
1242 containers:
1243 - image: nginx:1.7.9
1244 name: nginx
1245 `,
1246 },
1247 },
1248 "withschema-nil-ns2": {
1249 base: []string{
1250 baseResource(myDeployment),
1251 },
1252 patches: []string{
1253 addNamespace("ns2", changeImagePatch(myDeployment)),
1254 },
1255 expected: []string{
1256 baseResource(myDeployment),
1257 },
1258 },
1259 "withschema-ns1-nil": {
1260 base: []string{
1261 addNamespace("ns1", baseResource(myDeployment)),
1262 },
1263 patches: []string{
1264 changeImagePatch(myDeployment),
1265 },
1266 expected: []string{
1267 addNamespace("ns1", baseResource(myDeployment)),
1268 },
1269 },
1270 "noschema-ns1-ns2-one": {
1271 base: []string{
1272 addNamespace("ns1", baseResource(myCRD)),
1273 addNamespace("ns2", baseResource(myCRD)),
1274 },
1275 patches: []string{
1276 addNamespace("ns1", addLabelAndEnvPatch(myCRD)),
1277 addNamespace("ns2", addLabelAndEnvPatch(myCRD)),
1278 },
1279 errorExpected: false,
1280 expected: []string{
1281 addNamespace("ns1", expectedResultJMP("")),
1282 addNamespace("ns2", expectedResultJMP("")),
1283 },
1284 },
1285 "noschema-ns1-ns2-two": {
1286 base: []string{addNamespace("ns1", baseResource(myCRD))},
1287 patches: []string{addNamespace("ns2", changeImagePatch(myCRD))},
1288 expected: []string{addNamespace("ns1", baseResource(myCRD))},
1289 },
1290 "noschema-nil-ns2": {
1291 base: []string{baseResource(myCRD)},
1292 patches: []string{addNamespace("ns2", changeImagePatch(myCRD))},
1293 expected: []string{baseResource(myCRD)},
1294 },
1295 "noschema-ns1-nil": {
1296 base: []string{addNamespace("ns1", baseResource(myCRD))},
1297 patches: []string{changeImagePatch(myCRD)},
1298 expected: []string{addNamespace("ns1", baseResource(myCRD))},
1299 },
1300 }
1301 for n := range tests {
1302 tc := tests[n]
1303 t.Run(n, func(t *testing.T) {
1304 m, err := rmF.NewResMapFromBytes([]byte(strings.Join(tc.base, "\n---\n")))
1305 require.NoError(t, err)
1306 foundError := false
1307 for _, patch := range tc.patches {
1308 rp, err := rf.FromBytes([]byte(patch))
1309 require.NoError(t, err)
1310 idSet := resource.MakeIdSet([]*resource.Resource{rp})
1311 if err = m.ApplySmPatch(idSet, rp); err != nil {
1312 foundError = true
1313 break
1314 }
1315 }
1316 if foundError {
1317 assert.True(t, tc.errorExpected)
1318
1319 return
1320 }
1321 assert.False(t, tc.errorExpected)
1322 m.RemoveBuildAnnotations()
1323 yml, err := m.AsYaml()
1324 require.NoError(t, err)
1325 assert.Equal(t, strings.Join(tc.expected, "---\n"), string(yml))
1326 })
1327 }
1328 }
1329
1330
1331
1332
1333 func addNamespace(namespace string, base string) string {
1334 res := strings.Replace(base,
1335 "\nspec:\n",
1336 "\n namespace: "+namespace+"\nspec:\n",
1337 1)
1338 return res
1339 }
1340
1341
1342
1343 type DeleteOddsFilter struct{}
1344
1345 func (f DeleteOddsFilter) Filter(
1346 nodes []*yaml.RNode) (result []*yaml.RNode, err error) {
1347 for i := range nodes {
1348 if i%2 == 0 {
1349
1350 result = append(result, nodes[i])
1351 }
1352 }
1353 return
1354 }
1355
1356
1357
1358
1359 type CloneOddsFilter struct{}
1360
1361 func (f CloneOddsFilter) Filter(
1362 nodes []*yaml.RNode) (result []*yaml.RNode, err error) {
1363 for i := range nodes {
1364 if i%2 != 0 {
1365 newNode := nodes[i].Copy()
1366
1367 newNode.SetName(newNode.GetName() + "Clone")
1368
1369 result = append(result, nodes[i], newNode)
1370 }
1371 }
1372 return
1373 }
1374
1375 func TestApplyFilter(t *testing.T) {
1376 tests := map[string]struct {
1377 input string
1378 f kio.Filter
1379 expected string
1380 }{
1381 "labels": {
1382 input: `
1383 apiVersion: example.com/v1
1384 kind: Beans
1385 metadata:
1386 name: myBeans
1387 ---
1388 apiVersion: example.com/v1
1389 kind: Franks
1390 metadata:
1391 name: myFranks
1392 `,
1393 f: labels.Filter{
1394 Labels: map[string]string{
1395 "a": "foo",
1396 "b": "bar",
1397 },
1398 FsSlice: types.FsSlice{
1399 {
1400 Gvk: resid.NewGvk("example.com", "v1", "Beans"),
1401 Path: "metadata/labels",
1402 CreateIfNotPresent: true,
1403 },
1404 },
1405 },
1406 expected: `
1407 apiVersion: example.com/v1
1408 kind: Beans
1409 metadata:
1410 labels:
1411 a: foo
1412 b: bar
1413 name: myBeans
1414 ---
1415 apiVersion: example.com/v1
1416 kind: Franks
1417 metadata:
1418 name: myFranks
1419 `,
1420 },
1421 "deleteOddNodes": {
1422 input: `
1423 apiVersion: example.com/v1
1424 kind: Zero
1425 metadata:
1426 name: r0
1427 ---
1428 apiVersion: example.com/v1
1429 kind: One
1430 metadata:
1431 name: r1
1432 ---
1433 apiVersion: example.com/v1
1434 kind: Two
1435 metadata:
1436 name: r2
1437 ---
1438 apiVersion: example.com/v1
1439 kind: Three
1440 metadata:
1441 name: r3
1442 `,
1443 f: DeleteOddsFilter{},
1444 expected: `
1445 apiVersion: example.com/v1
1446 kind: Zero
1447 metadata:
1448 name: r0
1449 ---
1450 apiVersion: example.com/v1
1451 kind: Two
1452 metadata:
1453 name: r2
1454 `,
1455 },
1456 "cloneOddNodes": {
1457
1458 input: `
1459 apiVersion: example.com/v1
1460 kind: Zero
1461 metadata:
1462 name: r0
1463 ---
1464 apiVersion: example.com/v1
1465 kind: One
1466 metadata:
1467 name: r1
1468 ---
1469 apiVersion: example.com/v1
1470 kind: Two
1471 metadata:
1472 name: r2
1473 ---
1474 apiVersion: example.com/v1
1475 kind: Three
1476 metadata:
1477 name: r3
1478 ---
1479 apiVersion: example.com/v1
1480 kind: Four
1481 metadata:
1482 name: r4
1483 `,
1484 f: CloneOddsFilter{},
1485
1486 expected: `
1487 apiVersion: example.com/v1
1488 kind: One
1489 metadata:
1490 name: r1
1491 ---
1492 apiVersion: example.com/v1
1493 kind: One
1494 metadata:
1495 name: r1Clone
1496 ---
1497 apiVersion: example.com/v1
1498 kind: Three
1499 metadata:
1500 name: r3
1501 ---
1502 apiVersion: example.com/v1
1503 kind: Three
1504 metadata:
1505 name: r3Clone
1506 `,
1507 },
1508 }
1509 for name := range tests {
1510 tc := tests[name]
1511 t.Run(name, func(t *testing.T) {
1512 m, err := rmF.NewResMapFromBytes([]byte(tc.input))
1513 require.NoError(t, err)
1514 require.NoError(t, m.ApplyFilter(tc.f))
1515 kusttest_test.AssertActualEqualsExpectedWithTweak(
1516 t, m, nil, tc.expected)
1517 })
1518 }
1519 }
1520
1521 func TestApplySmPatch_Deletion(t *testing.T) {
1522 target := `
1523 apiVersion: apps/v1
1524 metadata:
1525 name: myDeploy
1526 kind: Deployment
1527 spec:
1528 replica: 2
1529 template:
1530 metadata:
1531 labels:
1532 old-label: old-value
1533 spec:
1534 containers:
1535 - name: nginx
1536 image: nginx
1537 `
1538 tests := map[string]struct {
1539 patch string
1540 expected string
1541 finalMapSize int
1542 }{
1543 "delete1": {
1544 patch: `apiVersion: apps/v1
1545 metadata:
1546 name: myDeploy
1547 kind: Deployment
1548 spec:
1549 replica: 2
1550 template:
1551 $patch: delete
1552 metadata:
1553 labels:
1554 old-label: old-value
1555 spec:
1556 containers:
1557 - name: nginx
1558 image: nginx
1559 `,
1560 expected: `apiVersion: apps/v1
1561 kind: Deployment
1562 metadata:
1563 name: myDeploy
1564 spec:
1565 replica: 2
1566 `,
1567 finalMapSize: 1,
1568 },
1569 "delete2": {
1570 patch: `apiVersion: apps/v1
1571 metadata:
1572 name: myDeploy
1573 kind: Deployment
1574 spec:
1575 $patch: delete
1576 replica: 2
1577 template:
1578 metadata:
1579 labels:
1580 old-label: old-value
1581 spec:
1582 containers:
1583 - name: nginx
1584 image: nginx
1585 `,
1586 expected: `apiVersion: apps/v1
1587 kind: Deployment
1588 metadata:
1589 name: myDeploy
1590 `,
1591 finalMapSize: 1,
1592 },
1593 "delete3": {
1594 patch: `apiVersion: apps/v1
1595 metadata:
1596 name: myDeploy
1597 kind: Deployment
1598 $patch: delete
1599 `,
1600 expected: "",
1601 finalMapSize: 0,
1602 },
1603 }
1604 for name := range tests {
1605 tc := tests[name]
1606 t.Run(name, func(t *testing.T) {
1607 m, err := rmF.NewResMapFromBytes([]byte(target))
1608 require.NoError(t, err, name)
1609 idSet := resource.MakeIdSet(m.Resources())
1610 assert.Equal(t, 1, idSet.Size(), name)
1611 p, err := rf.FromBytes([]byte(tc.patch))
1612 require.NoError(t, err, name)
1613 require.NoError(t, m.ApplySmPatch(idSet, p), name)
1614 assert.Equal(t, tc.finalMapSize, m.Size(), name)
1615 m.RemoveBuildAnnotations()
1616 yml, err := m.AsYaml()
1617 require.NoError(t, err, name)
1618 assert.Equal(t, tc.expected, string(yml), name)
1619 })
1620 }
1621 }
1622
1623 func TestOriginAnnotations(t *testing.T) {
1624 w := New()
1625 for i := 0; i < 3; i++ {
1626 require.NoError(t, w.Append(makeCm(i)))
1627 }
1628
1629 require.NoError(t, w.AddOriginAnnotation(origin1))
1630 resources := w.Resources()
1631 for _, res := range resources {
1632 or, err := res.GetOrigin()
1633 require.NoError(t, err)
1634 assert.Equal(t, origin1, or)
1635 }
1636
1637 require.NoError(t, w.AddOriginAnnotation(origin2))
1638 for _, res := range resources {
1639 or, err := res.GetOrigin()
1640 require.NoError(t, err)
1641 assert.Equal(t, origin1, or)
1642 }
1643
1644 require.NoError(t, w.RemoveOriginAnnotations())
1645 for _, res := range resources {
1646 or, err := res.GetOrigin()
1647 require.NoError(t, err)
1648 assert.Nil(t, or)
1649 }
1650 }
1651
1652 func TestTransformerAnnotations(t *testing.T) {
1653 w := New()
1654 for i := 0; i < 3; i++ {
1655 require.NoError(t, w.Append(makeCm(i)))
1656 }
1657
1658 require.NoError(t, w.AddTransformerAnnotation(origin1))
1659 resources := w.Resources()
1660 for _, res := range resources {
1661 or, err := res.GetOrigin()
1662 require.NoError(t, err)
1663 assert.Equal(t, origin1, or)
1664 }
1665
1666 require.NoError(t, w.AddTransformerAnnotation(origin2))
1667 for _, res := range resources {
1668 or, err := res.GetOrigin()
1669 require.NoError(t, err)
1670 assert.Equal(t, origin1, or)
1671 tr, err := res.GetTransformations()
1672 require.NoError(t, err)
1673 assert.Equal(t, resource.Transformations{origin2}, tr)
1674 }
1675
1676 require.NoError(t, w.RemoveTransformerAnnotations())
1677 for _, res := range resources {
1678 tr, err := res.GetTransformations()
1679 require.NoError(t, err)
1680 assert.Nil(t, tr)
1681 }
1682 }
1683
1684
1685
1686
1687
1688
1689 func baseResource(kind string) string {
1690 return fmt.Sprintf(`apiVersion: apps/v1
1691 kind: %s
1692 metadata:
1693 name: deploy1
1694 spec:
1695 template:
1696 metadata:
1697 labels:
1698 old-label: old-value
1699 spec:
1700 containers:
1701 - image: nginx
1702 name: nginx
1703 `, kind)
1704 }
1705
1706
1707
1708
1709
1710
1711 func addLabelAndEnvPatch(kind string) string {
1712 return fmt.Sprintf(`apiVersion: apps/v1
1713 kind: %s
1714 metadata:
1715 name: deploy1
1716 spec:
1717 template:
1718 metadata:
1719 labels:
1720 some-label: some-value
1721 spec:
1722 containers:
1723 - name: nginx
1724 env:
1725 - name: SOMEENV
1726 value: SOMEVALUE`, kind)
1727 }
1728
1729
1730
1731
1732
1733 func changeImagePatch(kind string) string {
1734 return fmt.Sprintf(`apiVersion: apps/v1
1735 kind: %s
1736 metadata:
1737 name: deploy1
1738 spec:
1739 template:
1740 spec:
1741 containers:
1742 - name: nginx
1743 image: "nginx:1.7.9"`, kind)
1744 }
1745
1746
1747
1748
1749
1750 func expectedResultJMP(imagename string) string {
1751 if imagename == "" {
1752 return `apiVersion: apps/v1
1753 kind: myCRD
1754 metadata:
1755 name: deploy1
1756 spec:
1757 template:
1758 metadata:
1759 labels:
1760 old-label: old-value
1761 some-label: some-value
1762 spec:
1763 containers:
1764 - env:
1765 - name: SOMEENV
1766 value: SOMEVALUE
1767 name: nginx
1768 `
1769 }
1770 return fmt.Sprintf(`apiVersion: apps/v1
1771 kind: myCRD
1772 metadata:
1773 name: deploy1
1774 spec:
1775 template:
1776 metadata:
1777 labels:
1778 old-label: old-value
1779 some-label: some-value
1780 spec:
1781 containers:
1782 - image: %s
1783 name: nginx
1784 `, imagename)
1785 }
1786
View as plain text