1
2
3
4 package kio_test
5
6 import (
7 "fmt"
8 "math/rand"
9 "os"
10 "path/filepath"
11 "runtime"
12 "testing"
13 "time"
14
15 "sigs.k8s.io/kustomize/kyaml/filesys"
16 "sigs.k8s.io/kustomize/kyaml/testutil"
17
18 "github.com/stretchr/testify/assert"
19 "github.com/stretchr/testify/require"
20 . "sigs.k8s.io/kustomize/kyaml/kio"
21 "sigs.k8s.io/kustomize/kyaml/yaml"
22 )
23
24
25
26 func TestLocalPackageWriter_Write(t *testing.T) {
27 testWriterOnDiskAndOnMem(t, func(t *testing.T, fs filesys.FileSystem) {
28 t.Helper()
29 d, node1, node2, node3, cleanup := getWriterInputs(t, fs)
30 defer cleanup()
31
32 w := LocalPackageWriter{
33 PackagePath: d,
34 FileSystem: filesys.FileSystemOrOnDisk{FileSystem: fs},
35 }
36 err := w.Write([]*yaml.RNode{node2, node1, node3})
37 require.NoError(t, err)
38
39 b, err := fs.ReadFile(filepath.Join(d, "a", "b", "a_test.yaml"))
40 require.NoError(t, err)
41 require.Equal(t, `a: b #first
42 ---
43 c: d # second
44 `, string(b))
45
46 b, err = fs.ReadFile(filepath.Join(d, "a", "b", "b_test.yaml"))
47 require.NoError(t, err)
48 require.Equal(t, `e: f
49 g:
50 h:
51 - i # has a list
52 - j
53 `, string(b))
54 })
55 }
56
57
58
59 func TestLocalPackageWriter_Write_keepReaderAnnotations(t *testing.T) {
60 testWriterOnDiskAndOnMem(t, func(t *testing.T, fs filesys.FileSystem) {
61 t.Helper()
62 d, node1, node2, node3, cleanup := getWriterInputs(t, fs)
63 defer cleanup()
64
65 w := LocalPackageWriter{
66 PackagePath: d,
67 KeepReaderAnnotations: true,
68 FileSystem: filesys.FileSystemOrOnDisk{FileSystem: fs},
69 }
70 err := w.Write([]*yaml.RNode{node2, node1, node3})
71 require.NoError(t, err)
72
73 b, err := fs.ReadFile(filepath.Join(d, "a", "b", "a_test.yaml"))
74 require.NoError(t, err)
75 require.Equal(t, `a: b #first
76 metadata:
77 annotations:
78 config.kubernetes.io/index: "0"
79 config.kubernetes.io/path: "a/b/a_test.yaml"
80 internal.config.kubernetes.io/path: 'a/b/a_test.yaml'
81 internal.config.kubernetes.io/index: '0'
82 ---
83 c: d # second
84 metadata:
85 annotations:
86 config.kubernetes.io/index: "1"
87 config.kubernetes.io/path: "a/b/a_test.yaml"
88 internal.config.kubernetes.io/path: 'a/b/a_test.yaml'
89 internal.config.kubernetes.io/index: '1'
90 `, string(b))
91
92 b, err = fs.ReadFile(filepath.Join(d, "a", "b", "b_test.yaml"))
93 require.NoError(t, err)
94 require.Equal(t, `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: "a/b/b_test.yaml"
103 internal.config.kubernetes.io/path: 'a/b/b_test.yaml'
104 internal.config.kubernetes.io/index: '0'
105 `, string(b))
106 })
107 }
108
109
110
111 func TestLocalPackageWriter_Write_clearAnnotations(t *testing.T) {
112 testWriterOnDiskAndOnMem(t, func(t *testing.T, fs filesys.FileSystem) {
113 t.Helper()
114 d, node1, node2, node3, cleanup := getWriterInputs(t, fs)
115 defer cleanup()
116
117 w := LocalPackageWriter{
118 PackagePath: d,
119 ClearAnnotations: []string{"config.kubernetes.io/mode"},
120 FileSystem: filesys.FileSystemOrOnDisk{FileSystem: fs},
121 }
122 err := w.Write([]*yaml.RNode{node2, node1, node3})
123 require.NoError(t, err)
124
125 b, err := fs.ReadFile(filepath.Join(d, "a", "b", "a_test.yaml"))
126 require.NoError(t, err)
127 require.Equal(t, `a: b #first
128 ---
129 c: d # second
130 `, string(b))
131
132 b, err = fs.ReadFile(filepath.Join(d, "a", "b", "b_test.yaml"))
133 require.NoError(t, err)
134 require.Equal(t, `e: f
135 g:
136 h:
137 - i # has a list
138 - j
139 `, string(b))
140 })
141 }
142
143
144
145 func TestLocalPackageWriter_Write_failRelativePath(t *testing.T) {
146 testWriterOnDiskAndOnMem(t, func(t *testing.T, fs filesys.FileSystem) {
147 t.Helper()
148 d, node1, node2, node3, cleanup := getWriterInputs(t, fs)
149 defer cleanup()
150
151 node4, err := yaml.Parse(`e: f
152 g:
153 h:
154 - i # has a list
155 - j
156 metadata:
157 annotations:
158 config.kubernetes.io/index: 0
159 config.kubernetes.io/path: "a/b/../../../b_test.yaml"
160 `)
161 require.NoError(t, err)
162
163 w := LocalPackageWriter{
164 PackagePath: d,
165 FileSystem: filesys.FileSystemOrOnDisk{FileSystem: fs},
166 }
167 err = w.Write([]*yaml.RNode{node2, node1, node3, node4})
168 if assert.Error(t, err) {
169 assert.Contains(t, err.Error(), "resource must be written under package")
170 }
171 })
172 }
173
174
175
176 func TestLocalPackageWriter_Write_invalidIndex(t *testing.T) {
177 testWriterOnDiskAndOnMem(t, func(t *testing.T, fs filesys.FileSystem) {
178 t.Helper()
179 d, node1, node2, node3, cleanup := getWriterInputs(t, fs)
180 defer cleanup()
181
182 node4, err := yaml.Parse(`e: f
183 g:
184 h:
185 - i # has a list
186 - j
187 metadata:
188 annotations:
189 config.kubernetes.io/index: a
190 config.kubernetes.io/path: "a/b/b_test.yaml" # use a different path, should still collide
191 `)
192 require.NoError(t, err)
193
194 w := LocalPackageWriter{
195 PackagePath: d,
196 FileSystem: filesys.FileSystemOrOnDisk{FileSystem: fs},
197 }
198 err = w.Write([]*yaml.RNode{node2, node1, node3, node4})
199 if assert.Error(t, err) {
200 assert.Contains(t, err.Error(), "unable to parse config.kubernetes.io/index")
201 }
202 })
203 }
204
205
206
207 func TestLocalPackageWriter_Write_absPath(t *testing.T) {
208 testWriterOnDiskAndOnMem(t, func(t *testing.T, fs filesys.FileSystem) {
209 t.Helper()
210 d, node1, node2, node3, cleanup := getWriterInputs(t, fs)
211 defer cleanup()
212
213 d = filepath.ToSlash(d)
214
215 n4 := fmt.Sprintf(`e: f
216 g:
217 h:
218 - i # has a list
219 - j
220 metadata:
221 annotations:
222 config.kubernetes.io/index: a
223 config.kubernetes.io/path: "%s/a/b/b_test.yaml" # use a different path, should still collide
224 `, d)
225 node4, err := yaml.Parse(n4)
226 testutil.AssertNoError(t, err, n4)
227
228 w := LocalPackageWriter{
229 PackagePath: d,
230 FileSystem: filesys.FileSystemOrOnDisk{FileSystem: fs},
231 }
232 err = w.Write([]*yaml.RNode{node2, node1, node3, node4})
233 testutil.AssertErrorContains(t, err, "package paths may not be absolute paths")
234 })
235 }
236
237
238
239 func TestLocalPackageWriter_Write_missingAnnotations(t *testing.T) {
240 testWriterOnDiskAndOnMem(t, func(t *testing.T, fs filesys.FileSystem) {
241 t.Helper()
242 d, node1, node2, node3, cleanup := getWriterInputs(t, fs)
243 defer cleanup()
244
245 node4String := `e: f
246 g:
247 h:
248 - i # has a list
249 - j
250 kind: Foo
251 metadata:
252 name: bar
253 `
254 node4, err := yaml.Parse(node4String)
255 require.NoError(t, err)
256
257 w := LocalPackageWriter{
258 PackagePath: d,
259 FileSystem: filesys.FileSystemOrOnDisk{FileSystem: fs},
260 }
261 err = w.Write([]*yaml.RNode{node2, node1, node3, node4})
262 require.NoError(t, err)
263 b, err := fs.ReadFile(filepath.Join(d, "foo_bar.yaml"))
264 require.NoError(t, err)
265 require.Equal(t, node4String, string(b))
266 })
267 }
268
269
270
271 func TestLocalPackageWriter_Write_pathIsDir(t *testing.T) {
272 testWriterOnDiskAndOnMem(t, func(t *testing.T, fs filesys.FileSystem) {
273 t.Helper()
274 d, node1, node2, node3, cleanup := getWriterInputs(t, fs)
275 defer cleanup()
276
277 node4, err := yaml.Parse(`e: f
278 g:
279 h:
280 - i # has a list
281 - j
282 metadata:
283 annotations:
284 config.kubernetes.io/path: a/
285 config.kubernetes.io/index: "0"
286 `)
287 require.NoError(t, err)
288
289 w := LocalPackageWriter{
290 PackagePath: d,
291 FileSystem: filesys.FileSystemOrOnDisk{FileSystem: fs},
292 }
293 err = w.Write([]*yaml.RNode{node2, node1, node3, node4})
294 require.Error(t, err)
295 require.Contains(t, err.Error(), "config.kubernetes.io/path cannot be a directory")
296 })
297 }
298
299 func testWriterOnDiskAndOnMem(t *testing.T, f func(t *testing.T, fs filesys.FileSystem)) {
300 t.Helper()
301 t.Run("on_disk", func(t *testing.T) { f(t, filesys.MakeFsOnDisk()) })
302
303 if runtime.GOOS != "windows" {
304 t.Run("on_mem", func(t *testing.T) { f(t, filesys.MakeFsInMemory()) })
305 }
306 }
307
308 func getWriterInputs(t *testing.T, mockFS filesys.FileSystem) (string, *yaml.RNode, *yaml.RNode, *yaml.RNode, func()) {
309 t.Helper()
310 node1, err := yaml.Parse(`a: b #first
311 metadata:
312 annotations:
313 config.kubernetes.io/index: "0"
314 config.kubernetes.io/path: "a/b/a_test.yaml"
315 `)
316 require.NoError(t, err)
317 node2, err := yaml.Parse(`c: d # second
318 metadata:
319 annotations:
320 config.kubernetes.io/index: "1"
321 config.kubernetes.io/path: "a/b/a_test.yaml"
322 `)
323 require.NoError(t, err)
324 node3, err := yaml.Parse(`e: f
325 g:
326 h:
327 - i # has a list
328 - j
329 metadata:
330 annotations:
331 config.kubernetes.io/index: "0"
332 config.kubernetes.io/path: "a/b/b_test.yaml"
333 `)
334 require.NoError(t, err)
335
336
337 rand.Seed(time.Now().Unix())
338 path := filepath.Join(os.TempDir(), fmt.Sprintf("kyaml-test%d", rand.Int31()))
339 require.NoError(t, mockFS.MkdirAll(filepath.Join(path, "a")))
340 return path, node1, node2, node3, func() { require.NoError(t, mockFS.RemoveAll(path)) }
341 }
342
View as plain text