1
2
3
4 package kio_test
5
6 import (
7 "path/filepath"
8 "runtime"
9 "strings"
10 "testing"
11
12 "github.com/stretchr/testify/require"
13 "sigs.k8s.io/kustomize/kyaml/filesys"
14 . "sigs.k8s.io/kustomize/kyaml/kio"
15 )
16
17 var readFileA = []byte(`---
18 a: b #first
19 ---
20 c: d # second
21 `)
22
23 var readFileB = []byte(`# second thing
24 e: f
25 g:
26 h:
27 - i # has a list
28 - j
29 `)
30
31 var readFileC = []byte(`---
32 a: b #third
33 metadata:
34 annotations:
35 `)
36
37 var readFileD = []byte(`---
38 a: b #forth
39 metadata:
40 `)
41
42 var readFileE = []byte(`---
43 a: b #first
44 ---
45 - foo # second
46 - bar
47 `)
48
49 var pkgFile = []byte(``)
50
51 func TestLocalPackageReader_Read_empty(t *testing.T) {
52 var r LocalPackageReader
53 nodes, err := r.Read()
54 require.Error(t, err)
55 require.Contains(t, err.Error(), "must specify package path")
56 require.Nil(t, nodes)
57 }
58
59 func TestLocalPackageReader_Read_pkg(t *testing.T) {
60 testOnDiskAndOnMem(t, []mockFile{
61 {path: "a/b"},
62 {path: "a/c"},
63 {path: "a_test.yaml", content: readFileA},
64 {path: "b_test.yaml", content: readFileB},
65 {path: "c_test.yaml", content: readFileC},
66 {path: "d_test.yaml", content: readFileD},
67 }, func(t *testing.T, path string, mockFS filesys.FileSystem) {
68 t.Helper()
69 rfr := LocalPackageReader{
70 PackagePath: path,
71 FileSystem: filesys.FileSystemOrOnDisk{FileSystem: mockFS},
72 }
73 nodes, err := rfr.Read()
74 require.NoError(t, err)
75 require.Len(t, nodes, 5)
76 expected := []string{
77 `a: b #first
78 metadata:
79 annotations:
80 config.kubernetes.io/index: '0'
81 config.kubernetes.io/path: 'a_test.yaml'
82 internal.config.kubernetes.io/index: '0'
83 internal.config.kubernetes.io/path: 'a_test.yaml'
84 `,
85 `c: d # second
86 metadata:
87 annotations:
88 config.kubernetes.io/index: '1'
89 config.kubernetes.io/path: 'a_test.yaml'
90 internal.config.kubernetes.io/index: '1'
91 internal.config.kubernetes.io/path: 'a_test.yaml'
92 `,
93 `# second thing
94 e: f
95 g:
96 h:
97 - i # has a list
98 - j
99 metadata:
100 annotations:
101 config.kubernetes.io/index: '0'
102 config.kubernetes.io/path: 'b_test.yaml'
103 internal.config.kubernetes.io/index: '0'
104 internal.config.kubernetes.io/path: 'b_test.yaml'
105 `,
106 `a: b #third
107 metadata:
108 annotations:
109 config.kubernetes.io/index: '0'
110 config.kubernetes.io/path: 'c_test.yaml'
111 internal.config.kubernetes.io/index: '0'
112 internal.config.kubernetes.io/path: 'c_test.yaml'
113 `,
114 `a: b #forth
115 metadata:
116 annotations:
117 config.kubernetes.io/index: '0'
118 config.kubernetes.io/path: 'd_test.yaml'
119 internal.config.kubernetes.io/index: '0'
120 internal.config.kubernetes.io/path: 'd_test.yaml'
121 `,
122 }
123 for i := range nodes {
124 val, err := nodes[i].String()
125 require.NoError(t, err)
126 require.Equal(t, expected[i], val)
127 }
128 })
129 }
130
131 func TestLocalPackageReader_Read_pkgAndSkipFile(t *testing.T) {
132 testOnDiskAndOnMem(t, []mockFile{
133 {path: "a/b"},
134 {path: "a/c"},
135 {path: "a_test.yaml", content: readFileA},
136 {path: "b_test.yaml", content: readFileB},
137 {path: "c_test.yaml", content: readFileC},
138 {path: "d_test.yaml", content: readFileD},
139 }, func(t *testing.T, path string, mockFS filesys.FileSystem) {
140 t.Helper()
141 rfr := LocalPackageReader{
142 PackagePath: path,
143 FileSkipFunc: func(relPath string) bool { return relPath == "d_test.yaml" },
144 FileSystem: filesys.FileSystemOrOnDisk{FileSystem: mockFS},
145 }
146 nodes, err := rfr.Read()
147 require.NoError(t, err)
148 require.Len(t, nodes, 4)
149 expected := []string{
150 `a: b #first
151 metadata:
152 annotations:
153 config.kubernetes.io/index: '0'
154 config.kubernetes.io/path: 'a_test.yaml'
155 internal.config.kubernetes.io/index: '0'
156 internal.config.kubernetes.io/path: 'a_test.yaml'
157 `,
158 `c: d # second
159 metadata:
160 annotations:
161 config.kubernetes.io/index: '1'
162 config.kubernetes.io/path: 'a_test.yaml'
163 internal.config.kubernetes.io/index: '1'
164 internal.config.kubernetes.io/path: 'a_test.yaml'
165 `,
166 `# second thing
167 e: f
168 g:
169 h:
170 - i # has a list
171 - j
172 metadata:
173 annotations:
174 config.kubernetes.io/index: '0'
175 config.kubernetes.io/path: 'b_test.yaml'
176 internal.config.kubernetes.io/index: '0'
177 internal.config.kubernetes.io/path: 'b_test.yaml'
178 `,
179 `a: b #third
180 metadata:
181 annotations:
182 config.kubernetes.io/index: '0'
183 config.kubernetes.io/path: 'c_test.yaml'
184 internal.config.kubernetes.io/index: '0'
185 internal.config.kubernetes.io/path: 'c_test.yaml'
186 `,
187 }
188 for i := range nodes {
189 val, err := nodes[i].String()
190 require.NoError(t, err)
191 require.Equal(t, expected[i], val)
192 }
193 })
194 }
195
196 func TestLocalPackageReader_Read_JSON(t *testing.T) {
197 testOnDiskAndOnMem(t, []mockFile{
198 {path: "a/b"},
199 {path: "a/c"},
200 {path: "a_test.json", content: []byte(`{
201 "a": "b"
202 }`),
203 },
204 {path: "b_test.json", content: []byte(`{
205 "e": "f",
206 "g": {
207 "h": ["i", "j"]
208 }
209 }`),
210 },
211 }, func(t *testing.T, path string, mockFS filesys.FileSystem) {
212 t.Helper()
213 rfr := LocalPackageReader{
214 PackagePath: path,
215 MatchFilesGlob: []string{"*.json"},
216 FileSystem: filesys.FileSystemOrOnDisk{FileSystem: mockFS},
217 }
218 nodes, err := rfr.Read()
219 require.NoError(t, err)
220 require.Len(t, nodes, 2)
221 expected := []string{
222 `{"a": "b", ` +
223 `metadata: {annotations: {` +
224 `config.kubernetes.io/index: '0', ` +
225 `config.kubernetes.io/path: 'a_test.json', ` +
226 `internal.config.kubernetes.io/index: '0', ` +
227 `internal.config.kubernetes.io/path: 'a_test.json'}}}
228 `,
229 `{"e": "f", "g": {"h": ["i", "j"]}, ` +
230 `metadata: {annotations: {` +
231 `config.kubernetes.io/index: '0', ` +
232 `config.kubernetes.io/path: 'b_test.json', ` +
233 `internal.config.kubernetes.io/index: '0', ` +
234 `internal.config.kubernetes.io/path: 'b_test.json'}}}
235 `,
236 }
237 for i := range nodes {
238 val, err := nodes[i].String()
239 require.NoError(t, err)
240 require.Equal(t, expected[i], val)
241 }
242 })
243 }
244
245 func TestLocalPackageReader_Read_file(t *testing.T) {
246 testOnDiskAndOnMem(t, []mockFile{
247 {path: "a/b"},
248 {path: "a/c"},
249 {path: "a_test.yaml", content: readFileA},
250 {path: "b_test.yaml", content: readFileB},
251 }, func(t *testing.T, path string, mockFS filesys.FileSystem) {
252 t.Helper()
253 rfr := LocalPackageReader{
254 PackagePath: filepath.Join(path, "a_test.yaml"),
255 FileSystem: filesys.FileSystemOrOnDisk{FileSystem: mockFS},
256 }
257 nodes, err := rfr.Read()
258 require.NoError(t, err)
259 require.Len(t, nodes, 2)
260 expected := []string{
261 `a: b #first
262 metadata:
263 annotations:
264 config.kubernetes.io/index: '0'
265 config.kubernetes.io/path: 'a_test.yaml'
266 internal.config.kubernetes.io/index: '0'
267 internal.config.kubernetes.io/path: 'a_test.yaml'
268 `,
269 `c: d # second
270 metadata:
271 annotations:
272 config.kubernetes.io/index: '1'
273 config.kubernetes.io/path: 'a_test.yaml'
274 internal.config.kubernetes.io/index: '1'
275 internal.config.kubernetes.io/path: 'a_test.yaml'
276 `,
277 }
278 for i := range nodes {
279 val, err := nodes[i].String()
280 require.NoError(t, err)
281 require.Equal(t, expected[i], val)
282 }
283 })
284 }
285
286 func TestLocalPackageReader_Read_pkgOmitAnnotations(t *testing.T) {
287 testOnDiskAndOnMem(t, []mockFile{
288 {path: "a/b"},
289 {path: "a/c"},
290 {path: "a_test.yaml", content: readFileA},
291 {path: "b_test.yaml", content: readFileB},
292 }, func(t *testing.T, path string, mockFS filesys.FileSystem) {
293 t.Helper()
294 rfr := LocalPackageReader{
295 PackagePath: path,
296 OmitReaderAnnotations: true,
297 FileSystem: filesys.FileSystemOrOnDisk{FileSystem: mockFS},
298 }
299 nodes, err := rfr.Read()
300 require.NoError(t, err)
301 require.Len(t, nodes, 3)
302 expected := []string{
303 `a: b #first
304 `,
305 `c: d # second
306 `,
307 `# second thing
308 e: f
309 g:
310 h:
311 - i # has a list
312 - j
313 `,
314 }
315 for i := range nodes {
316 val, err := nodes[i].String()
317 require.NoError(t, err)
318 require.Equal(t, expected[i], val)
319 }
320 })
321 }
322
323 func TestLocalPackageReader_Read_PreserveSeqIndent(t *testing.T) {
324 testOnDiskAndOnMem(t, []mockFile{
325 {path: "a/b"},
326 {path: "a/c"},
327 {path: "a_test.yaml", content: readFileA},
328 {path: "b_test.yaml", content: readFileB},
329 }, func(t *testing.T, path string, mockFS filesys.FileSystem) {
330 t.Helper()
331 rfr := LocalPackageReader{
332 PackagePath: path,
333 PreserveSeqIndent: true,
334 FileSystem: filesys.FileSystemOrOnDisk{FileSystem: mockFS},
335 }
336 nodes, err := rfr.Read()
337 require.NoError(t, err)
338 require.Len(t, nodes, 3)
339 expected := []string{
340 `a: b #first
341 metadata:
342 annotations:
343 config.kubernetes.io/index: '0'
344 config.kubernetes.io/path: 'a_test.yaml'
345 internal.config.kubernetes.io/index: '0'
346 internal.config.kubernetes.io/path: 'a_test.yaml'
347 internal.config.kubernetes.io/seqindent: 'compact'
348 `,
349 `c: d # second
350 metadata:
351 annotations:
352 config.kubernetes.io/index: '1'
353 config.kubernetes.io/path: 'a_test.yaml'
354 internal.config.kubernetes.io/index: '1'
355 internal.config.kubernetes.io/path: 'a_test.yaml'
356 internal.config.kubernetes.io/seqindent: 'compact'
357 `,
358 `# second thing
359 e: f
360 g:
361 h:
362 - i # has a list
363 - j
364 metadata:
365 annotations:
366 config.kubernetes.io/index: '0'
367 config.kubernetes.io/path: 'b_test.yaml'
368 internal.config.kubernetes.io/index: '0'
369 internal.config.kubernetes.io/path: 'b_test.yaml'
370 internal.config.kubernetes.io/seqindent: 'compact'
371 `,
372 }
373 for i := range nodes {
374 val, err := nodes[i].String()
375 require.NoError(t, err)
376 require.Equal(t, expected[i], val)
377 }
378 })
379 }
380
381 func TestLocalPackageReader_Read_nestedDirs(t *testing.T) {
382 testOnDiskAndOnMem(t, []mockFile{
383 {path: "a/b"},
384 {path: "a/c"},
385 {path: "a/b/a_test.yaml", content: readFileA},
386 {path: "a/b/b_test.yaml", content: readFileB},
387 }, func(t *testing.T, path string, mockFS filesys.FileSystem) {
388 t.Helper()
389 rfr := LocalPackageReader{
390 PackagePath: path,
391 FileSystem: filesys.FileSystemOrOnDisk{FileSystem: mockFS},
392 }
393 nodes, err := rfr.Read()
394 require.NoError(t, err)
395 require.Len(t, nodes, 3)
396 expected := []string{
397 `a: b #first
398 metadata:
399 annotations:
400 config.kubernetes.io/index: '0'
401 config.kubernetes.io/path: 'a${SEP}b${SEP}a_test.yaml'
402 internal.config.kubernetes.io/index: '0'
403 internal.config.kubernetes.io/path: 'a${SEP}b${SEP}a_test.yaml'
404 `,
405 `c: d # second
406 metadata:
407 annotations:
408 config.kubernetes.io/index: '1'
409 config.kubernetes.io/path: 'a${SEP}b${SEP}a_test.yaml'
410 internal.config.kubernetes.io/index: '1'
411 internal.config.kubernetes.io/path: 'a${SEP}b${SEP}a_test.yaml'
412 `,
413 `# second thing
414 e: f
415 g:
416 h:
417 - i # has a list
418 - j
419 metadata:
420 annotations:
421 config.kubernetes.io/index: '0'
422 config.kubernetes.io/path: 'a${SEP}b${SEP}b_test.yaml'
423 internal.config.kubernetes.io/index: '0'
424 internal.config.kubernetes.io/path: 'a${SEP}b${SEP}b_test.yaml'
425 `,
426 }
427 for i := range nodes {
428 val, err := nodes[i].String()
429 require.NoError(t, err)
430 want := strings.ReplaceAll(expected[i], "${SEP}", string(filepath.Separator))
431 require.Equal(t, want, val)
432 }
433 })
434 }
435
436 func TestLocalPackageReader_Read_matchRegex(t *testing.T) {
437 testOnDiskAndOnMem(t, []mockFile{
438 {path: "a/b"},
439 {path: "a/c"},
440 {path: "a/b/a_test.yaml", content: readFileA},
441 {path: "a/b/b_test.yaml", content: readFileB},
442 }, func(t *testing.T, path string, mockFS filesys.FileSystem) {
443 t.Helper()
444 rfr := LocalPackageReader{
445 PackagePath: path,
446 MatchFilesGlob: []string{`a*.yaml`},
447 FileSystem: filesys.FileSystemOrOnDisk{FileSystem: mockFS},
448 }
449 nodes, err := rfr.Read()
450 require.NoError(t, err)
451 require.Len(t, nodes, 2)
452
453 expected := []string{
454 `a: b #first
455 metadata:
456 annotations:
457 config.kubernetes.io/index: '0'
458 config.kubernetes.io/path: 'a${SEP}b${SEP}a_test.yaml'
459 internal.config.kubernetes.io/index: '0'
460 internal.config.kubernetes.io/path: 'a${SEP}b${SEP}a_test.yaml'
461 `,
462 `c: d # second
463 metadata:
464 annotations:
465 config.kubernetes.io/index: '1'
466 config.kubernetes.io/path: 'a${SEP}b${SEP}a_test.yaml'
467 internal.config.kubernetes.io/index: '1'
468 internal.config.kubernetes.io/path: 'a${SEP}b${SEP}a_test.yaml'
469 `,
470 }
471
472 for i, node := range nodes {
473 val, err := node.String()
474 require.NoError(t, err)
475 want := strings.ReplaceAll(expected[i], "${SEP}", string(filepath.Separator))
476 require.Equal(t, want, val)
477 }
478 })
479 }
480
481 func TestLocalPackageReader_Read_skipSubpackage(t *testing.T) {
482 testOnDiskAndOnMem(t, []mockFile{
483 {path: "a/b"},
484 {path: "a/c"},
485 {path: "a/b/a_test.yaml", content: readFileA},
486 {path: "a/c/c_test.yaml", content: readFileB},
487 {path: "a/c/pkgFile", content: pkgFile},
488 }, func(t *testing.T, path string, mockFS filesys.FileSystem) {
489 t.Helper()
490 rfr := LocalPackageReader{
491 PackagePath: path,
492 PackageFileName: "pkgFile",
493 FileSystem: filesys.FileSystemOrOnDisk{FileSystem: mockFS},
494 }
495 nodes, err := rfr.Read()
496 require.NoError(t, err)
497 require.Len(t, nodes, 2)
498
499 expected := []string{
500 `a: b #first
501 metadata:
502 annotations:
503 config.kubernetes.io/index: '0'
504 config.kubernetes.io/path: 'a${SEP}b${SEP}a_test.yaml'
505 internal.config.kubernetes.io/index: '0'
506 internal.config.kubernetes.io/path: 'a${SEP}b${SEP}a_test.yaml'
507 `,
508 `c: d # second
509 metadata:
510 annotations:
511 config.kubernetes.io/index: '1'
512 config.kubernetes.io/path: 'a${SEP}b${SEP}a_test.yaml'
513 internal.config.kubernetes.io/index: '1'
514 internal.config.kubernetes.io/path: 'a${SEP}b${SEP}a_test.yaml'
515 `,
516 }
517
518 for i, node := range nodes {
519 val, err := node.String()
520 require.NoError(t, err)
521 want := strings.ReplaceAll(expected[i], "${SEP}", string(filepath.Separator))
522 require.Equal(t, want, val)
523 }
524 })
525 }
526
527 func TestLocalPackageReader_Read_includeSubpackage(t *testing.T) {
528 testOnDiskAndOnMem(t, []mockFile{
529 {path: "a/b"},
530 {path: "a/c"},
531 {path: "a/b/a_test.yaml", content: readFileA},
532 {path: "a/c/c_test.yaml", content: readFileB},
533 {path: "a/c/pkgFile", content: pkgFile},
534 }, func(t *testing.T, path string, mockFS filesys.FileSystem) {
535 t.Helper()
536 rfr := LocalPackageReader{
537 PackagePath: path,
538 IncludeSubpackages: true,
539 PackageFileName: "pkgFile",
540 FileSystem: filesys.FileSystemOrOnDisk{FileSystem: mockFS},
541 }
542 nodes, err := rfr.Read()
543 require.NoError(t, err)
544 require.Len(t, nodes, 3)
545
546 expected := []string{
547 `a: b #first
548 metadata:
549 annotations:
550 config.kubernetes.io/index: '0'
551 config.kubernetes.io/path: 'a${SEP}b${SEP}a_test.yaml'
552 internal.config.kubernetes.io/index: '0'
553 internal.config.kubernetes.io/path: 'a${SEP}b${SEP}a_test.yaml'
554 `,
555 `c: d # second
556 metadata:
557 annotations:
558 config.kubernetes.io/index: '1'
559 config.kubernetes.io/path: 'a${SEP}b${SEP}a_test.yaml'
560 internal.config.kubernetes.io/index: '1'
561 internal.config.kubernetes.io/path: 'a${SEP}b${SEP}a_test.yaml'
562 `,
563 `# second thing
564 e: f
565 g:
566 h:
567 - i # has a list
568 - j
569 metadata:
570 annotations:
571 config.kubernetes.io/index: '0'
572 config.kubernetes.io/path: 'a${SEP}c${SEP}c_test.yaml'
573 internal.config.kubernetes.io/index: '0'
574 internal.config.kubernetes.io/path: 'a${SEP}c${SEP}c_test.yaml'
575 `,
576 }
577
578 for i, node := range nodes {
579 val, err := node.String()
580 require.NoError(t, err)
581 want := strings.ReplaceAll(expected[i], "${SEP}", string(filepath.Separator))
582 require.Equal(t, want, val)
583 }
584 })
585 }
586
587 type mockFile struct {
588 path string
589
590 content []byte
591 }
592
593 func testOnDiskAndOnMem(t *testing.T, files []mockFile, f func(t *testing.T, path string, fs filesys.FileSystem)) {
594 t.Helper()
595 t.Run("on_disk", func(t *testing.T) {
596 var dirs []string
597 for _, file := range files {
598 if file.content == nil {
599 dirs = append(dirs, filepath.FromSlash(file.path))
600 }
601 }
602
603 s := SetupDirectories(t, dirs...)
604 defer s.Clean()
605 for _, file := range files {
606 if file.content != nil {
607 s.WriteFile(t, filepath.FromSlash(file.path), file.content)
608 }
609 }
610
611 f(t, "./", nil)
612 f(t, s.Root, nil)
613 })
614
615
616 if runtime.GOOS == "windows" {
617 return
618 }
619
620 t.Run("on_mem", func(t *testing.T) {
621 fs := filesys.MakeFsInMemory()
622 for _, file := range files {
623 path := filepath.FromSlash(file.path)
624 if file.content == nil {
625 require.NoError(t, fs.MkdirAll(path))
626 } else {
627 require.NoError(t, fs.WriteFile(path, file.content))
628 }
629 }
630
631 f(t, "/", fs)
632 })
633 }
634
635 func TestLocalPackageReader_ReadBareSeqNodes(t *testing.T) {
636 testOnDiskAndOnMem(t, []mockFile{
637 {path: "a/b"},
638 {path: "a/c"},
639 {path: "e_test.yaml", content: readFileE},
640 }, func(t *testing.T, path string, mockFS filesys.FileSystem) {
641 t.Helper()
642 rfr := LocalPackageReader{
643 PackagePath: path,
644 FileSystem: filesys.FileSystemOrOnDisk{FileSystem: mockFS},
645 WrapBareSeqNode: true,
646 }
647 nodes, err := rfr.Read()
648 require.NoError(t, err)
649 require.Len(t, nodes, 2)
650 expected := []string{
651 `a: b #first
652 metadata:
653 annotations:
654 config.kubernetes.io/index: '0'
655 config.kubernetes.io/path: 'e_test.yaml'
656 internal.config.kubernetes.io/index: '0'
657 internal.config.kubernetes.io/path: 'e_test.yaml'
658 `,
659 `bareSeqNodeWrappingKey:
660 - foo # second
661 - bar
662 metadata:
663 annotations:
664 config.kubernetes.io/index: '1'
665 config.kubernetes.io/path: 'e_test.yaml'
666 internal.config.kubernetes.io/index: '1'
667 internal.config.kubernetes.io/path: 'e_test.yaml'
668 `,
669 }
670 for i := range nodes {
671 val, err := nodes[i].String()
672 require.NoError(t, err)
673 require.Equal(t, expected[i], val)
674 }
675 })
676 }
677
View as plain text