1
2
3
4 package krusty_test
5
6 import (
7 "fmt"
8 "net/http"
9 "net/http/httptest"
10 "path/filepath"
11 "regexp"
12 "strings"
13 "testing"
14
15 "github.com/stretchr/testify/require"
16 . "sigs.k8s.io/kustomize/api/internal/target"
17 "sigs.k8s.io/kustomize/api/konfig"
18 "sigs.k8s.io/kustomize/api/krusty"
19 kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
20 )
21
22 const validResource = `
23 apiVersion: v1
24 kind: Service
25 metadata:
26 name: myService
27 spec:
28 selector:
29 backend: bungie
30 ports:
31 - port: 7002
32 `
33
34 func TestTargetMustHaveKustomizationFile(t *testing.T) {
35 th := kusttest_test.MakeHarness(t)
36 th.WriteF("service.yaml", `
37 apiVersion: v1
38 kind: Service
39 metadata:
40 name: aService
41 `)
42 th.WriteF("deeper/service.yaml", `
43 apiVersion: v1
44 kind: Service
45 metadata:
46 name: anotherService
47 `)
48 err := th.RunWithErr(".", th.MakeDefaultOptions())
49 if err == nil {
50 t.Fatalf("expected an error")
51 }
52 if !IsMissingKustomizationFileError(err) {
53 t.Fatalf("unexpected error: %q", err)
54 }
55 }
56
57 func TestTargetMustHaveOnlyOneKustomizationFile(t *testing.T) {
58 th := kusttest_test.MakeHarness(t)
59 for _, n := range konfig.RecognizedKustomizationFileNames() {
60 th.WriteF(filepath.Join(".", n), `
61 apiVersion: kustomize.config.k8s.io/v1beta1
62 kind: Kustomization
63 `)
64 }
65 err := th.RunWithErr(".", th.MakeDefaultOptions())
66 if err == nil {
67 t.Fatalf("expected an error")
68 }
69 if !strings.Contains(err.Error(), "Found multiple kustomization files") {
70 t.Fatalf("unexpected error: %q", err)
71 }
72 }
73
74 func TestBaseMustHaveKustomizationFile(t *testing.T) {
75 th := kusttest_test.MakeHarness(t)
76 th.WriteK(".", `
77 resources:
78 - base
79 `)
80 th.WriteF("base/service.yaml", validResource)
81 err := th.RunWithErr(".", th.MakeDefaultOptions())
82 if err == nil {
83 t.Fatalf("expected an error")
84 }
85 if !strings.Contains(err.Error(), "accumulating resources") {
86 t.Fatalf("unexpected error: %q", err)
87 }
88 }
89
90 func TestResourceNotFound(t *testing.T) {
91 th := kusttest_test.MakeHarness(t)
92 th.WriteK(".", `
93 resources:
94 - deployment.yaml
95 `)
96 err := th.RunWithErr(".", th.MakeDefaultOptions())
97 if err == nil {
98 t.Fatalf("expected an error")
99 }
100 if !strings.Contains(err.Error(), "accumulating resources") {
101 t.Fatalf("unexpected error: %q", err)
102 }
103 }
104
105 func TestResourceHasAnchor(t *testing.T) {
106 th := kusttest_test.MakeHarness(t)
107 th.WriteK(".", `
108 resources:
109 - ingress.yaml
110 `)
111 th.WriteF("ingress.yaml", `
112 apiVersion: networking.k8s.io/v1
113 kind: Ingress
114 metadata:
115 name: blog
116 spec:
117 tls:
118 - hosts:
119 - xyz.me
120 - www.xyz.me
121 secretName: cert-tls
122 rules:
123 - host: xyz.me
124 http: &xxx_rules
125 paths:
126 - path: /
127 pathType: Prefix
128 backend:
129 service:
130 name: service
131 port:
132 number: 80
133 - host: www.xyz.me
134 http: *xxx_rules
135 `)
136 m := th.Run(".", th.MakeDefaultOptions())
137 th.AssertActualEqualsExpected(m, `
138 apiVersion: networking.k8s.io/v1
139 kind: Ingress
140 metadata:
141 name: blog
142 spec:
143 rules:
144 - host: xyz.me
145 http:
146 paths:
147 - backend:
148 service:
149 name: service
150 port:
151 number: 80
152 path: /
153 pathType: Prefix
154 - host: www.xyz.me
155 http:
156 paths:
157 - backend:
158 service:
159 name: service
160 port:
161 number: 80
162 path: /
163 pathType: Prefix
164 tls:
165 - hosts:
166 - xyz.me
167 - www.xyz.me
168 secretName: cert-tls
169 `)
170 }
171
172 func TestAccumulateResourcesErrors(t *testing.T) {
173 type testcase struct {
174 name string
175 resource string
176
177
178 resourceFunc func(string) string
179
180 resourceServerSetup func(*http.ServeMux)
181 isAbsolute bool
182 files map[string]string
183
184
185
186
187 errFile, errDir string
188 }
189 populateAbsolutePaths := func(tc testcase, dir string) testcase {
190 filePaths := make(map[string]string, len(tc.files)+1)
191 for file, content := range tc.files {
192 filePaths[filepath.Join(dir, file)] = content
193 }
194 resourcePath := filepath.Join(dir, tc.resource)
195 if tc.isAbsolute {
196 tc.resource = resourcePath
197 }
198 filePaths[filepath.Join(dir, "kustomization.yaml")] = fmt.Sprintf(`
199 resources:
200 - %s
201 `, tc.resource)
202 tc.files = filePaths
203 regPath := regexp.QuoteMeta(resourcePath)
204 tc.errFile = strings.ReplaceAll(tc.errFile, "%s", regPath)
205 tc.errDir = strings.ReplaceAll(tc.errDir, "%s", regPath)
206 return tc
207 }
208 buildError := func(tc testcase) string {
209 const (
210 prefix = "accumulating resources"
211 filePrefixf = "accumulating resources from '%s'"
212 fileWrapperIfDirf = "accumulation err='%s'"
213 separator = ": "
214 )
215 parts := []string{
216 prefix,
217 strings.Join([]string{
218 fmt.Sprintf(filePrefixf, regexp.QuoteMeta(tc.resource)),
219 tc.errFile,
220 }, separator),
221 }
222 if tc.errDir != "" {
223 parts[1] = fmt.Sprintf(fileWrapperIfDirf, parts[1])
224 parts = append(parts, tc.errDir)
225 }
226 return strings.Join(parts, separator)
227 }
228 for _, test := range []testcase{
229 {
230 name: "remote file not considered repo",
231 resourceFunc: func(url string) string {
232 return fmt.Sprintf("%s/segments-too-few-to-be-repo", url)
233 },
234 resourceServerSetup: func(server *http.ServeMux) {
235 server.HandleFunc("/", func(out http.ResponseWriter, req *http.Request) {
236 out.WriteHeader(http.StatusNotFound)
237 })
238 },
239
240
241
242
243 errFile: `HTTP Error: status code 404 \(Not Found\)\z`,
244 },
245 {
246 name: "remote file qualifies as repo",
247 resourceFunc: func(url string) string {
248 return fmt.Sprintf("%s/long/enough/to/have/org/and/repo", url)
249 },
250 resourceServerSetup: func(server *http.ServeMux) {
251 server.HandleFunc("/", func(out http.ResponseWriter, req *http.Request) {
252 out.WriteHeader(http.StatusInternalServerError)
253 })
254 },
255
256
257
258 errFile: "URL is a git repository",
259 errDir: `failed to run \S+/git fetch --depth=1 .+`,
260 },
261 {
262 name: "local file qualifies as repo",
263
264
265 resource: "package@v1.28.0.example/configs/base",
266 errFile: `evalsymlink failure on '%s' .+`,
267 errDir: `failed to run \S+/git fetch --depth=1 .+`,
268 },
269 {
270 name: "relative path does not exist",
271 resource: "file-or-directory",
272 errFile: `evalsymlink failure on '%s' .+`,
273 errDir: `must build at directory: not a valid directory: evalsymlink failure .+`,
274 },
275 {
276 name: "absolute path does not exist",
277 resource: "file-or-directory",
278 isAbsolute: true,
279 errFile: `evalsymlink failure on '%s' .+`,
280 errDir: `new root '%s' cannot be absolute`,
281 },
282 {
283 name: "relative file violates restrictions",
284 resource: "../base/resource.yaml",
285 files: map[string]string{
286 "../base/resource.yaml": validResource,
287 },
288 errFile: "security; file '%s' is not in or below .+",
289
290
291 errDir: "must build at directory: '%s': file is not directory",
292 },
293 {
294 name: "absolute file violates restrictions",
295 resource: "../base/resource.yaml",
296 isAbsolute: true,
297 files: map[string]string{
298 "../base/resource.yaml": validResource,
299 },
300 errFile: "security; file '%s' is not in or below .+",
301
302
303 errDir: `new root '%s' cannot be absolute`,
304 },
305 } {
306 t.Run(test.name, func(t *testing.T) {
307 if test.resourceFunc != nil {
308
309 handler := http.NewServeMux()
310 if test.resourceServerSetup != nil {
311 test.resourceServerSetup(handler)
312 }
313
314 svr := httptest.NewServer(handler)
315 defer svr.Close()
316
317 test.resource = test.resourceFunc(svr.URL)
318 }
319
320
321
322 fs, tmpDir := kusttest_test.Setup(t)
323 root := tmpDir.Join("root")
324 require.NoError(t, fs.Mkdir(root))
325
326 test = populateAbsolutePaths(test, root)
327 for file, content := range test.files {
328 dir := filepath.Dir(file)
329 require.NoError(t, fs.MkdirAll(dir))
330 require.NoError(t, fs.WriteFile(file, []byte(content)))
331 }
332
333 b := krusty.MakeKustomizer(krusty.MakeDefaultOptions())
334 _, err := b.Run(fs, root)
335 require.Regexp(t, buildError(test), err.Error())
336 })
337 }
338
339
340
341
342 }
343
View as plain text