1
2
3
4 package kio_test
5
6 import (
7 "bytes"
8 "strings"
9 "testing"
10
11 "github.com/stretchr/testify/assert"
12 "github.com/stretchr/testify/require"
13 . "sigs.k8s.io/kustomize/kyaml/kio"
14 "sigs.k8s.io/kustomize/kyaml/kio/kioutil"
15 "sigs.k8s.io/kustomize/kyaml/yaml"
16 )
17
18 func TestByteReader(t *testing.T) {
19 type testCase struct {
20 name string
21 input string
22 err string
23 expectedItems []string
24 expectedFunctionConfig string
25 expectedResults string
26 wrappingAPIVersion string
27 wrappingAPIKind string
28 instance ByteReader
29 }
30
31 testCases := []testCase{
32
33
34
35 {
36 name: "wrapped_resource_list",
37 input: `apiVersion: config.kubernetes.io/v1
38 kind: ResourceList
39 items:
40 - kind: Deployment
41 spec:
42 replicas: 1
43 - kind: Service
44 spec:
45 selectors:
46 foo: bar
47 `,
48 expectedItems: []string{
49 `kind: Deployment
50 spec:
51 replicas: 1
52 `,
53 `kind: Service
54 spec:
55 selectors:
56 foo: bar
57 `,
58 },
59 wrappingAPIVersion: ResourceListAPIVersion,
60 wrappingAPIKind: ResourceListKind,
61 },
62
63
64
65
66 {
67 name: "wrapped_resource_list_function_config",
68 input: `apiVersion: config.kubernetes.io/v1
69 kind: ResourceList
70 functionConfig:
71 foo: bar
72 elems:
73 - a
74 - b
75 - c
76 items:
77 - kind: Deployment
78 spec:
79 replicas: 1
80 - kind: Service
81 spec:
82 selectors:
83 foo: bar
84 `,
85 expectedItems: []string{
86 `kind: Deployment
87 spec:
88 replicas: 1
89 `,
90 `kind: Service
91 spec:
92 selectors:
93 foo: bar
94 `,
95 },
96 expectedFunctionConfig: `foo: bar
97 elems:
98 - a
99 - b
100 - c`,
101 wrappingAPIVersion: ResourceListAPIVersion,
102 wrappingAPIKind: ResourceListKind,
103 },
104
105
106
107 {
108 name: "wrapped_resource_list_function_config_without_items",
109 input: `apiVersion: config.kubernetes.io/v1
110 kind: ResourceList
111 functionConfig:
112 foo: bar
113 elems:
114 - a
115 - b
116 - c
117 `,
118 expectedItems: []string{},
119 expectedFunctionConfig: `foo: bar
120 elems:
121 - a
122 - b
123 - c`,
124 wrappingAPIVersion: ResourceListAPIVersion,
125 wrappingAPIKind: ResourceListKind,
126 },
127
128
129
130
131 {
132 name: "wrapped_list",
133 input: `
134 apiVersion: v1
135 kind: List
136 items:
137 - kind: Deployment
138 spec:
139 replicas: 1
140 - kind: Service
141 spec:
142 selectors:
143 foo: bar
144 `,
145 expectedItems: []string{
146 `
147 kind: Deployment
148 spec:
149 replicas: 1
150 `,
151 `
152 kind: Service
153 spec:
154 selectors:
155 foo: bar
156 `,
157 },
158 wrappingAPIKind: "List",
159 wrappingAPIVersion: "v1",
160 },
161
162
163
164
165 {
166 name: "unwrapped_items",
167 input: `
168 ---
169 a: b # first resource
170 c: d
171 ---
172 # second resource
173 e: f
174 g:
175 - h
176 ---
177 ---
178 i: j
179 `,
180 expectedItems: []string{
181 `a: b # first resource
182 c: d
183 metadata:
184 annotations:
185 config.kubernetes.io/index: '0'
186 internal.config.kubernetes.io/index: '0'
187 `,
188 `# second resource
189 e: f
190 g:
191 - h
192 metadata:
193 annotations:
194 config.kubernetes.io/index: '1'
195 internal.config.kubernetes.io/index: '1'
196 `,
197 `i: j
198 metadata:
199 annotations:
200 config.kubernetes.io/index: '2'
201 internal.config.kubernetes.io/index: '2'
202 `,
203 },
204 },
205
206
207
208
209 {
210 name: "omit_annotations",
211 input: `
212 ---
213 a: b # first resource
214 c: d
215 ---
216 # second resource
217 e: f
218 g:
219 - h
220 ---
221 ---
222 i: j
223 `,
224 expectedItems: []string{
225 `
226 a: b # first resource
227 c: d
228 `,
229 `
230 # second resource
231 e: f
232 g:
233 - h
234 `,
235 `
236 i: j
237 `,
238 },
239 instance: ByteReader{OmitReaderAnnotations: true},
240 },
241
242
243
244
245 {
246 name: "no_omit_annotations",
247 input: `
248 ---
249 a: b # first resource
250 c: d
251 ---
252 # second resource
253 e: f
254 g:
255 - h
256 ---
257 ---
258 i: j
259 `,
260 expectedItems: []string{
261 `
262 a: b # first resource
263 c: d
264 metadata:
265 annotations:
266 config.kubernetes.io/index: '0'
267 internal.config.kubernetes.io/index: '0'
268 `,
269 `
270 # second resource
271 e: f
272 g:
273 - h
274 metadata:
275 annotations:
276 config.kubernetes.io/index: '1'
277 internal.config.kubernetes.io/index: '1'
278 `,
279 `
280 i: j
281 metadata:
282 annotations:
283 config.kubernetes.io/index: '2'
284 internal.config.kubernetes.io/index: '2'
285 `,
286 },
287 instance: ByteReader{},
288 },
289
290
291
292
293 {
294 name: "set_annotation",
295 input: `
296 ---
297 a: b # first resource
298 c: d
299 ---
300 # second resource
301 e: f
302 g:
303 - h
304 ---
305 ---
306 i: j
307 `,
308 expectedItems: []string{
309 `a: b # first resource
310 c: d
311 metadata:
312 annotations:
313 foo: 'bar'
314 `,
315 `# second resource
316 e: f
317 g:
318 - h
319 metadata:
320 annotations:
321 foo: 'bar'
322 `,
323 `i: j
324 metadata:
325 annotations:
326 foo: 'bar'
327 `,
328 },
329 instance: ByteReader{
330 OmitReaderAnnotations: true,
331 SetAnnotations: map[string]string{"foo": "bar"}},
332 },
333
334
335
336
337 {
338 name: "windows_line_ending",
339 input: "\r\n---\r\na: b # first resource\r\nc: d\r\n---\r\n# second resource\r\ne: f\r\ng:\r\n- h\r\n---\r\n\r\n---\r\n i: j",
340 expectedItems: []string{
341 `a: b # first resource
342 c: d
343 metadata:
344 annotations:
345 foo: 'bar'
346 `,
347 `# second resource
348 e: f
349 g:
350 - h
351 metadata:
352 annotations:
353 foo: 'bar'
354 `,
355 `i: j
356 metadata:
357 annotations:
358 foo: 'bar'
359 `,
360 },
361 instance: ByteReader{
362 OmitReaderAnnotations: true,
363 SetAnnotations: map[string]string{"foo": "bar"}},
364 },
365
366
367
368
369 {
370 name: "json",
371 input: `
372 {
373 "a": "b",
374 "c": [1, 2]
375 }
376 `,
377 expectedItems: []string{
378 `
379 {"a": "b", "c": [1, 2], metadata: {annotations: {config.kubernetes.io/index: '0', internal.config.kubernetes.io/index: '0'}}}
380 `,
381 },
382 instance: ByteReader{},
383 },
384
385
386
387
388 {
389 name: "white_space_after_document_separator_should_be_ignored",
390 input: `
391 a: b
392 ---
393 c: d
394 `,
395 expectedItems: []string{
396 `
397 a: b
398 `,
399 `
400 c: d
401 `,
402 },
403 instance: ByteReader{OmitReaderAnnotations: true},
404 },
405
406
407
408
409 {
410 name: "comment_after_document_separator_should_be_ignored",
411 input: `
412 a: b
413 --- #foo
414 c: d
415 `,
416 expectedItems: []string{
417 `
418 a: b
419 `,
420 `
421 c: d
422 `,
423 },
424 instance: ByteReader{OmitReaderAnnotations: true},
425 },
426
427
428
429
430 {
431 name: "anything_after_document_separator_other_than_white_space_or_comment_is_an_error",
432 input: `
433 a: b
434 --- foo
435 c: d
436 `,
437 err: "invalid document separator: --- foo",
438 instance: ByteReader{OmitReaderAnnotations: true},
439 },
440 }
441
442 for i := range testCases {
443 tc := testCases[i]
444 t.Run(tc.name, func(t *testing.T) {
445 r := tc.instance
446 r.Reader = bytes.NewBufferString(tc.input)
447 nodes, err := r.Read()
448 if tc.err != "" {
449 if !assert.EqualError(t, err, tc.err) {
450 t.FailNow()
451 }
452 return
453 }
454
455 if !assert.NoError(t, err) {
456 t.FailNow()
457 }
458
459
460 if !assert.Len(t, nodes, len(tc.expectedItems)) {
461 t.FailNow()
462 }
463 for i := range nodes {
464 actual, err := nodes[i].String()
465 if !assert.NoError(t, err) {
466 t.FailNow()
467 }
468 if !assert.Equal(t,
469 strings.TrimSpace(tc.expectedItems[i]),
470 strings.TrimSpace(actual)) {
471 t.FailNow()
472 }
473 }
474
475
476 if tc.expectedFunctionConfig != "" {
477 actual, err := r.FunctionConfig.String()
478 if !assert.NoError(t, err) {
479 t.FailNow()
480 }
481 if !assert.Equal(t,
482 strings.TrimSpace(tc.expectedFunctionConfig),
483 strings.TrimSpace(actual)) {
484 t.FailNow()
485 }
486 } else if !assert.Nil(t, r.FunctionConfig) {
487 t.FailNow()
488 }
489
490 if tc.expectedResults != "" {
491 actual, err := r.Results.String()
492 actual = strings.TrimSpace(actual)
493 if !assert.NoError(t, err) {
494 t.FailNow()
495 }
496
497 tc.expectedResults = strings.TrimSpace(tc.expectedResults)
498 if !assert.Equal(t, tc.expectedResults, actual) {
499 t.FailNow()
500 }
501 } else if !assert.Nil(t, r.Results) {
502 t.FailNow()
503 }
504
505 if !assert.Equal(t, tc.wrappingAPIKind, r.WrappingKind) {
506 t.FailNow()
507 }
508 if !assert.Equal(t, tc.wrappingAPIVersion, r.WrappingAPIVersion) {
509 t.FailNow()
510 }
511 })
512 }
513 }
514
515 func TestFromBytes(t *testing.T) {
516 type expected struct {
517 isErr bool
518 sOut []string
519 }
520
521 testCases := map[string]struct {
522 input []byte
523 exp expected
524 }{
525 "garbage": {
526 input: []byte("garbageIn: garbageOut"),
527 exp: expected{
528 sOut: []string{"garbageIn: garbageOut"},
529 },
530 },
531 "noBytes": {
532 input: []byte{},
533 exp: expected{
534 sOut: []string{},
535 },
536 },
537 "goodJson": {
538 input: []byte(`
539 {"apiVersion":"v1","kind":"ConfigMap","metadata":{"name":"winnie"}}
540 `),
541 exp: expected{
542 sOut: []string{`
543 {"apiVersion": "v1", "kind": "ConfigMap", "metadata": {"name": "winnie"}}
544 `},
545 },
546 },
547 "goodYaml1": {
548 input: []byte(`
549 apiVersion: v1
550 kind: ConfigMap
551 metadata:
552 name: winnie
553 `),
554 exp: expected{
555 sOut: []string{`
556 apiVersion: v1
557 kind: ConfigMap
558 metadata:
559 name: winnie
560 `},
561 },
562 },
563 "goodYaml2": {
564 input: []byte(`
565 apiVersion: v1
566 kind: ConfigMap
567 metadata:
568 name: winnie
569 ---
570 apiVersion: v1
571 kind: ConfigMap
572 metadata:
573 name: winnie
574 `),
575 exp: expected{
576 sOut: []string{`
577 apiVersion: v1
578 kind: ConfigMap
579 metadata:
580 name: winnie
581 `, `
582 apiVersion: v1
583 kind: ConfigMap
584 metadata:
585 name: winnie
586 `},
587 },
588 },
589 "localConfigYaml": {
590 input: []byte(`
591 apiVersion: v1
592 kind: ConfigMap
593 metadata:
594 name: winnie-skip
595 annotations:
596 # this annotation causes the Resource to be ignored by kustomize
597 config.kubernetes.io/local-config: ""
598 ---
599 apiVersion: v1
600 kind: ConfigMap
601 metadata:
602 name: winnie
603 `),
604 exp: expected{
605 sOut: []string{`
606 apiVersion: v1
607 kind: ConfigMap
608 metadata:
609 name: winnie-skip
610 annotations:
611 # this annotation causes the Resource to be ignored by kustomize
612 config.kubernetes.io/local-config: ""
613 `,
614 `
615 apiVersion: v1
616 kind: ConfigMap
617 metadata:
618 name: winnie
619 `},
620 },
621 },
622 "garbageInOneOfTwoObjects": {
623 input: []byte(`
624 apiVersion: v1
625 kind: ConfigMap
626 metadata:
627 name: winnie
628 ---
629 WOOOOOOOOOOOOOOOOOOOOOOOOT: woot
630 `),
631 exp: expected{
632 sOut: []string{`
633 apiVersion: v1
634 kind: ConfigMap
635 metadata:
636 name: winnie
637 `,
638 `
639 WOOOOOOOOOOOOOOOOOOOOOOOOT: woot
640 `},
641 },
642 },
643 "emptyObjects": {
644 input: []byte(`
645 ---
646 #a comment
647
648 ---
649
650 `),
651 exp: expected{
652 sOut: []string{},
653 },
654 },
655 "Missing .metadata.name in object": {
656 input: []byte(`
657 apiVersion: v1
658 kind: Namespace
659 metadata:
660 annotations:
661 foo: bar
662 `),
663 exp: expected{
664 sOut: []string{`
665 apiVersion: v1
666 kind: Namespace
667 metadata:
668 annotations:
669 foo: bar
670 `},
671 },
672 },
673 "nil value in list": {
674 input: []byte(`
675 apiVersion: builtin
676 kind: ConfigMapGenerator
677 metadata:
678 name: kube100-site
679 labels:
680 app: web
681 testList:
682 - testA
683 -
684 `),
685 exp: expected{
686 isErr: true,
687 },
688 },
689 "List": {
690 input: []byte(`
691 apiVersion: v1
692 kind: List
693 items:
694 - apiVersion: v1
695 kind: ConfigMap
696 metadata:
697 name: winnie
698 - apiVersion: v1
699 kind: ConfigMap
700 metadata:
701 name: winnie
702 `),
703 exp: expected{
704 sOut: []string{`
705 apiVersion: v1
706 kind: ConfigMap
707 metadata:
708 name: winnie
709 `, `
710 apiVersion: v1
711 kind: ConfigMap
712 metadata:
713 name: winnie
714 `},
715 },
716 },
717 "ConfigMapList": {
718 input: []byte(`
719 apiVersion: v1
720 kind: ConfigMapList
721 items:
722 - apiVersion: v1
723 kind: ConfigMap
724 metadata:
725 name: winnie
726 - apiVersion: v1
727 kind: ConfigMap
728 metadata:
729 name: winnie
730 `),
731 exp: expected{
732 sOut: []string{`
733 apiVersion: v1
734 kind: ConfigMapList
735 items:
736 - apiVersion: v1
737 kind: ConfigMap
738 metadata:
739 name: winnie
740 - apiVersion: v1
741 kind: ConfigMap
742 metadata:
743 name: winnie
744 `},
745 },
746 },
747 "mergeAnchors": {
748 input: []byte(`
749 apiVersion: v1
750 kind: DeploymentList
751 items:
752 - apiVersion: apps/v1
753 kind: Deployment
754 metadata:
755 name: deployment-a
756 spec: &hostAliases
757 template:
758 spec:
759 hostAliases:
760 - hostnames:
761 - a.example.com
762 ip: 8.8.8.8
763 - apiVersion: apps/v1
764 kind: Deployment
765 metadata:
766 name: deployment-b
767 spec:
768 <<: *hostAliases
769 `),
770 exp: expected{
771 sOut: []string{`
772 apiVersion: v1
773 kind: DeploymentList
774 items:
775 - apiVersion: apps/v1
776 kind: Deployment
777 metadata:
778 name: deployment-a
779 spec:
780 template:
781 spec:
782 hostAliases:
783 - hostnames:
784 - a.example.com
785 ip: 8.8.8.8
786 - apiVersion: apps/v1
787 kind: Deployment
788 metadata:
789 name: deployment-b
790 spec:
791 template:
792 spec:
793 hostAliases:
794 - hostnames:
795 - a.example.com
796 ip: 8.8.8.8
797 `},
798 },
799 },
800 "listWithAnchors": {
801 input: []byte(`
802 apiVersion: v1
803 kind: DeploymentList
804 items:
805 - apiVersion: apps/v1
806 kind: Deployment
807 metadata:
808 name: deployment-a
809 spec: &hostAliases
810 template:
811 spec:
812 hostAliases:
813 - hostnames:
814 - a.example.com
815 ip: 8.8.8.8
816 - apiVersion: apps/v1
817 kind: Deployment
818 metadata:
819 name: deployment-b
820 spec: *hostAliases
821 `),
822 exp: expected{
823 sOut: []string{`
824 apiVersion: v1
825 kind: DeploymentList
826 items:
827 - apiVersion: apps/v1
828 kind: Deployment
829 metadata:
830 name: deployment-a
831 spec:
832 template:
833 spec:
834 hostAliases:
835 - hostnames:
836 - a.example.com
837 ip: 8.8.8.8
838 - apiVersion: apps/v1
839 kind: Deployment
840 metadata:
841 name: deployment-b
842 spec:
843 template:
844 spec:
845 hostAliases:
846 - hostnames:
847 - a.example.com
848 ip: 8.8.8.8
849 `},
850 },
851 },
852 }
853
854 for n := range testCases {
855 tc := testCases[n]
856 t.Run(n, func(t *testing.T) {
857 rNodes, err := FromBytes(tc.input)
858 if err != nil {
859 assert.True(t, tc.exp.isErr)
860 return
861 }
862 assert.False(t, tc.exp.isErr)
863 assert.Equal(t, len(tc.exp.sOut), len(rNodes))
864 for i, n := range rNodes {
865 json, err := n.String()
866 require.NoError(t, err)
867 assert.Equal(
868 t, strings.TrimSpace(tc.exp.sOut[i]),
869 strings.TrimSpace(json), n)
870 }
871 })
872 }
873 }
874
875
876
877 func TestByteReader_AnchorsAweigh(t *testing.T) {
878 const input = `
879 data:
880 color: &color-used blue
881 feeling: *color-used
882 `
883 var rNode *yaml.RNode
884 {
885 rNodes, err := (&ByteReader{
886 OmitReaderAnnotations: true,
887 AnchorsAweigh: false,
888 Reader: bytes.NewBuffer([]byte(input)),
889 }).Read()
890 require.NoError(t, err)
891 assert.Equal(t, 1, len(rNodes))
892 rNode = rNodes[0]
893 }
894
895 {
896 yNode := rNode.YNode()
897
898
899 assert.Equal(t, yaml.NodeTagMap, yNode.Tag)
900
901 yNodes := yNode.Content
902 assert.Equal(t, 2, len(yNodes))
903
904
905 assert.Equal(t, yaml.NodeTagString, yNodes[0].Tag)
906 assert.Equal(t, "data", yNodes[0].Value)
907
908 assert.Equal(t, yaml.NodeTagMap, yNodes[1].Tag)
909
910
911 yNodes = yNodes[1].Content
912
913 assert.Equal(t, 4, len(yNodes))
914
915 assert.Equal(t, yaml.ScalarNode, yNodes[0].Kind)
916 assert.Equal(t, yaml.NodeTagString, yNodes[0].Tag)
917 assert.Equal(t, "color", yNodes[0].Value)
918 assert.Empty(t, yNodes[0].Anchor)
919 assert.Nil(t, yNodes[0].Alias)
920
921 assert.Equal(t, yaml.ScalarNode, yNodes[1].Kind)
922 assert.Equal(t, yaml.NodeTagString, yNodes[1].Tag)
923 assert.Equal(t, "blue", yNodes[1].Value)
924 assert.Equal(t, "color-used", yNodes[1].Anchor)
925 assert.Nil(t, yNodes[1].Alias)
926
927 assert.Equal(t, yaml.ScalarNode, yNodes[2].Kind)
928 assert.Equal(t, yaml.NodeTagString, yNodes[2].Tag)
929 assert.Equal(t, "feeling", yNodes[2].Value)
930 assert.Empty(t, yNodes[2].Anchor)
931 assert.Nil(t, yNodes[2].Alias)
932
933 assert.Equal(t, yaml.AliasNode, yNodes[3].Kind)
934 assert.Empty(t, yNodes[3].Tag)
935 assert.Equal(t, "color-used", yNodes[3].Value)
936 assert.Empty(t, yNodes[3].Anchor)
937 assert.NotNil(t, yNodes[3].Alias)
938 }
939
940 str, err := rNode.String()
941 require.NoError(t, err)
942
943 assert.Equal(t, strings.TrimSpace(input), strings.TrimSpace(str))
944
945
946 {
947 rNodes, err := (&ByteReader{
948 OmitReaderAnnotations: true,
949 AnchorsAweigh: true,
950 Reader: bytes.NewBuffer([]byte(input)),
951 }).Read()
952 require.NoError(t, err)
953 assert.Equal(t, 1, len(rNodes))
954 rNode = rNodes[0]
955 }
956
957 {
958 yNode := rNode.YNode()
959
960 assert.Equal(t, yaml.NodeTagMap, yNode.Tag)
961
962 yNodes := yNode.Content
963 assert.Equal(t, 2, len(yNodes))
964
965 assert.Equal(t, yaml.NodeTagString, yNodes[0].Tag)
966 assert.Equal(t, "data", yNodes[0].Value)
967
968 assert.Equal(t, yaml.NodeTagMap, yNodes[1].Tag)
969
970 yNodes = yNodes[1].Content
971 assert.Equal(t, 4, len(yNodes))
972
973 assert.Equal(t, yaml.ScalarNode, yNodes[0].Kind)
974 assert.Equal(t, yaml.NodeTagString, yNodes[0].Tag)
975 assert.Equal(t, "color", yNodes[0].Value)
976 assert.Empty(t, yNodes[0].Anchor)
977 assert.Nil(t, yNodes[0].Alias)
978
979 assert.Equal(t, yaml.ScalarNode, yNodes[1].Kind)
980 assert.Equal(t, yaml.NodeTagString, yNodes[1].Tag)
981 assert.Equal(t, "blue", yNodes[1].Value)
982 assert.Empty(t, yNodes[1].Anchor)
983 assert.Nil(t, yNodes[1].Alias)
984
985 assert.Equal(t, yaml.ScalarNode, yNodes[2].Kind)
986 assert.Equal(t, yaml.NodeTagString, yNodes[2].Tag)
987 assert.Equal(t, "feeling", yNodes[2].Value)
988 assert.Empty(t, yNodes[2].Anchor)
989 assert.Nil(t, yNodes[2].Alias)
990
991 assert.Equal(t, yaml.ScalarNode, yNodes[3].Kind)
992 assert.Equal(t, yaml.NodeTagString, yNodes[3].Tag)
993 assert.Equal(t, "blue", yNodes[3].Value)
994 assert.Empty(t, yNodes[3].Anchor)
995 assert.Nil(t, yNodes[3].Alias)
996 }
997
998 str, err = rNode.String()
999 require.NoError(t, err)
1000
1001 assert.Equal(t, strings.TrimSpace(`
1002 data:
1003 color: blue
1004 feeling: blue
1005 `), strings.TrimSpace(str))
1006 }
1007
1008
1009
1010 func TestByteReader_AddSeqIndentAnnotation(t *testing.T) {
1011 type testCase struct {
1012 name string
1013 err string
1014 input string
1015 expectedAnnoValue string
1016 OmitReaderAnnotations bool
1017 }
1018
1019 testCases := []testCase{
1020 {
1021 name: "read with wide indentation",
1022 input: `apiVersion: apps/v1
1023 kind: Deployment
1024 spec:
1025 - foo
1026 - bar
1027 - baz
1028 `,
1029 expectedAnnoValue: "wide",
1030 },
1031 {
1032 name: "read with compact indentation",
1033 input: `apiVersion: apps/v1
1034 kind: Deployment
1035 spec:
1036 - foo
1037 - bar
1038 - baz
1039 `,
1040 expectedAnnoValue: "compact",
1041 },
1042 {
1043 name: "read with mixed indentation, wide wins",
1044 input: `apiVersion: apps/v1
1045 kind: Deployment
1046 spec:
1047 - foo
1048 - bar
1049 - baz
1050 env:
1051 - foo
1052 - bar
1053 `,
1054 expectedAnnoValue: "wide",
1055 },
1056 {
1057 name: "read with mixed indentation, compact wins",
1058 input: `apiVersion: apps/v1
1059 kind: Deployment
1060 spec:
1061 - foo
1062 - bar
1063 - baz
1064 env:
1065 - foo
1066 - bar
1067 `,
1068 expectedAnnoValue: "compact",
1069 },
1070 {
1071 name: "error if conflicting options",
1072 input: `apiVersion: apps/v1
1073 kind: Deployment
1074 spec:
1075 - foo
1076 - bar
1077 - baz
1078 env:
1079 - foo
1080 - bar
1081 `,
1082 OmitReaderAnnotations: true,
1083 err: `"PreserveSeqIndent" option adds a reader annotation, please set "OmitReaderAnnotations" to false`,
1084 },
1085 }
1086
1087 for i := range testCases {
1088 tc := testCases[i]
1089 t.Run(tc.name, func(t *testing.T) {
1090 rNodes, err := (&ByteReader{
1091 OmitReaderAnnotations: tc.OmitReaderAnnotations,
1092 PreserveSeqIndent: true,
1093 Reader: bytes.NewBuffer([]byte(tc.input)),
1094 }).Read()
1095 if tc.err != "" {
1096 require.Error(t, err)
1097 assert.Equal(t, tc.err, err.Error())
1098 return
1099 }
1100 require.NoError(t, err)
1101 actual := rNodes[0].GetAnnotations()[kioutil.SeqIndentAnnotation]
1102 assert.Equal(t, tc.expectedAnnoValue, actual)
1103 })
1104 }
1105 }
1106
View as plain text