Skip to content

Commit da4e881

Browse files
authored
Add accumulateResources error tests for local files (#5225)
* Add accumulateResources error tests for local files. Add tests demonstrating accumulateResources errors when the resource is a local file. Works to address #4807. * Improve readability
1 parent 878cda7 commit da4e881

File tree

3 files changed

+164
-53
lines changed

3 files changed

+164
-53
lines changed

api/krusty/accumulation_test.go

Lines changed: 109 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,18 @@ import (
1717
kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
1818
)
1919

20+
const validResource = `
21+
apiVersion: v1
22+
kind: Service
23+
metadata:
24+
name: myService
25+
spec:
26+
selector:
27+
backend: bungie
28+
ports:
29+
- port: 7002
30+
`
31+
2032
func TestTargetMustHaveKustomizationFile(t *testing.T) {
2133
th := kusttest_test.MakeHarness(t)
2234
th.WriteF("service.yaml", `
@@ -63,17 +75,7 @@ func TestBaseMustHaveKustomizationFile(t *testing.T) {
6375
resources:
6476
- base
6577
`)
66-
th.WriteF("base/service.yaml", `
67-
apiVersion: v1
68-
kind: Service
69-
metadata:
70-
name: myService
71-
spec:
72-
selector:
73-
backend: bungie
74-
ports:
75-
- port: 7002
76-
`)
78+
th.WriteF("base/service.yaml", validResource)
7779
err := th.RunWithErr(".", th.MakeDefaultOptions())
7880
if err == nil {
7981
t.Fatalf("expected an error")
@@ -167,12 +169,35 @@ spec:
167169

168170
func TestAccumulateResourcesErrors(t *testing.T) {
169171
type testcase struct {
170-
name string
171-
resource string
172-
// regex error message that is output when kustomize tries to
173-
// accumulate resource as file and dir, respectively
172+
name string
173+
resource string
174+
isAbsolute bool
175+
files map[string]string
176+
// errFile, errDir are regex for the expected error message output
177+
// when kustomize tries to accumulate resource as file and dir,
178+
// respectively. The test substitutes occurrences of "%s" in the
179+
// error strings with the absolute path where kustomize looks for it.
174180
errFile, errDir string
175181
}
182+
populateAbsolutePaths := func(tc testcase, dir string) testcase {
183+
filePaths := make(map[string]string, len(tc.files)+1)
184+
for file, content := range tc.files {
185+
filePaths[filepath.Join(dir, file)] = content
186+
}
187+
resourcePath := filepath.Join(dir, tc.resource)
188+
if tc.isAbsolute {
189+
tc.resource = resourcePath
190+
}
191+
filePaths[filepath.Join(dir, "kustomization.yaml")] = fmt.Sprintf(`
192+
resources:
193+
- %s
194+
`, tc.resource)
195+
tc.files = filePaths
196+
regPath := regexp.QuoteMeta(resourcePath)
197+
tc.errFile = strings.ReplaceAll(tc.errFile, "%s", regPath)
198+
tc.errDir = strings.ReplaceAll(tc.errDir, "%s", regPath)
199+
return tc
200+
}
176201
buildError := func(tc testcase) string {
177202
const (
178203
prefix = "accumulating resources"
@@ -196,39 +221,89 @@ func TestAccumulateResourcesErrors(t *testing.T) {
196221
for _, test := range []testcase{
197222
{
198223
name: "remote file not considered repo",
199-
// This url is too short to be considered a remote repo.
200-
resource: "https://raw.githubusercontent.com/kustomize",
201-
// It is acceptable that the error for a remote file-like reference
202-
// (that is not long enough to be considered a repo) does not
203-
// indicate said reference is not a local directory.
204-
// Though it is possible for the remote file-like reference to be
205-
// a local directory, it is very unlikely.
206-
errFile: `HTTP Error: status code 400 \(Bad Request\)\z`,
224+
// The example.com second-level domain is reserved and
225+
// safe to access, see RFC 2606.
226+
resource: "https://example.com/segments-too-few-to-be-repo",
227+
// It's acceptable for the error output of a remote file-like
228+
// resource to not indicate the resource's status as a
229+
// local directory. Though it is possible for a remote file-like
230+
// resource to be a local directory, it is very unlikely.
231+
errFile: `HTTP Error: status code 404 \(Not Found\)\z`,
207232
},
208233
{
209234
name: "remote file qualifies as repo",
210-
resource: "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/kustomize/v5.0.0/examples/helloWorld/configMap",
235+
resource: "https://example.com/long/enough/to/have/org/and/repo",
211236
// TODO(4788): This error message is technically wrong. Just
212-
// because we fail to GET a reference does not mean the reference is
213-
// not a remote file. We should return the GET status code instead.
237+
// because we fail to GET a resource does not mean the resource is
238+
// not a remote file. We should return the GET status code as well.
214239
errFile: "URL is a git repository",
215240
errDir: `failed to run \S+/git fetch --depth=1 .+`,
216241
},
242+
{
243+
name: "local file qualifies as repo",
244+
// The .example top level domain is reserved for example purposes,
245+
// see RFC 2606.
246+
resource: "[email protected]/configs/base",
247+
errFile: `evalsymlink failure on '%s' .+`,
248+
errDir: `failed to run \S+/git fetch --depth=1 .+`,
249+
},
250+
{
251+
name: "relative path does not exist",
252+
resource: "file-or-directory",
253+
errFile: `evalsymlink failure on '%s' .+`,
254+
errDir: `must build at directory: not a valid directory: evalsymlink failure .+`,
255+
},
256+
{
257+
name: "absolute path does not exist",
258+
resource: "file-or-directory",
259+
isAbsolute: true,
260+
errFile: `evalsymlink failure on '%s' .+`,
261+
errDir: `new root '%s' cannot be absolute`,
262+
},
263+
{
264+
name: "relative file violates restrictions",
265+
resource: "../base/resource.yaml",
266+
files: map[string]string{
267+
"../base/resource.yaml": validResource,
268+
},
269+
errFile: "security; file '%s' is not in or below .+",
270+
// TODO(4348): Over-inclusion of directory error message when we
271+
// know resource is file.
272+
errDir: "must build at directory: '%s': file is not directory",
273+
},
274+
{
275+
name: "absolute file violates restrictions",
276+
resource: "../base/resource.yaml",
277+
isAbsolute: true,
278+
files: map[string]string{
279+
"../base/resource.yaml": validResource,
280+
},
281+
errFile: "security; file '%s' is not in or below .+",
282+
// TODO(4348): Over-inclusion of directory error message when we
283+
// know resource is file.
284+
errDir: `new root '%s' cannot be absolute`,
285+
},
217286
} {
218287
t.Run(test.name, func(t *testing.T) {
219-
// should use real file system to indicate that we are creating
220-
// new temporary directories on disk when we attempt to fetch repos
221-
fSys, tmpDir := kusttest_test.CreateKustDir(t, fmt.Sprintf(`
222-
resources:
223-
- %s
224-
`, test.resource))
288+
// Should use real file system to indicate that we are creating
289+
// new temporary directories on disk when we attempt to fetch repos.
290+
fs, tmpDir := kusttest_test.Setup(t)
291+
root := tmpDir.Join("root")
292+
require.NoError(t, fs.Mkdir(root))
293+
294+
test = populateAbsolutePaths(test, root)
295+
for file, content := range test.files {
296+
dir := filepath.Dir(file)
297+
require.NoError(t, fs.MkdirAll(dir))
298+
require.NoError(t, fs.WriteFile(file, []byte(content)))
299+
}
300+
225301
b := krusty.MakeKustomizer(krusty.MakeDefaultOptions())
226-
_, err := b.Run(fSys, tmpDir.String())
302+
_, err := b.Run(fs, root)
227303
require.Regexp(t, buildError(test), err.Error())
228304
})
229305
}
230306
// TODO(annasong): add tests that check accumulateResources errors for
231-
// - local files
232307
// - repos
233308
// - local directories
234309
// - files that yield malformed yaml errors

api/loader/fileloader_test.go

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ func TestIsRemoteFile(t *testing.T) {
3131
"https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/examples/helloWorld/configMap.yaml",
3232
true,
3333
},
34+
"malformed https": {
35+
// TODO(annasong): Maybe we want to fix this. Needs more research.
36+
"https:/raw.githubusercontent.com/kubernetes-sigs/kustomize/master/examples/helloWorld/configMap.yaml",
37+
true,
38+
},
3439
"https dir": {
3540
"https://github.com/kubernetes-sigs/kustomize//examples/helloWorld/",
3641
true,
@@ -201,23 +206,44 @@ func TestNewEmptyLoader(t *testing.T) {
201206
require.Error(t, err)
202207
}
203208

204-
func TestNewLoaderHTTP(t *testing.T) {
205-
t.Run("doesn't exist", func(t *testing.T) {
206-
_, err := makeLoader().New("https://google.com/project")
207-
require.Error(t, err)
209+
func TestNewRemoteLoaderDoesNotExist(t *testing.T) {
210+
_, err := makeLoader().New("https://example.com/org/repo")
211+
require.ErrorContains(t, err, "fetch")
212+
}
213+
214+
func TestLoaderLocalScheme(t *testing.T) {
215+
// It is unlikely but possible for a reference with a url scheme to
216+
// actually refer to a local file or directory.
217+
t.Run("file", func(t *testing.T) {
218+
fSys, dir := setupOnDisk(t)
219+
parts := []string{
220+
"ssh:",
221+
"resource.yaml",
222+
}
223+
require.NoError(t, fSys.Mkdir(dir.Join(parts[0])))
224+
const content = "resource config"
225+
require.NoError(t, fSys.WriteFile(
226+
dir.Join(filepath.Join(parts...)),
227+
[]byte(content),
228+
))
229+
actualContent, err := newLoaderOrDie(RestrictionRootOnly,
230+
fSys,
231+
dir.String(),
232+
).Load(strings.Join(parts, "//"))
233+
require.NoError(t, err)
234+
require.Equal(t, content, string(actualContent))
208235
})
209-
// Though it is unlikely and we do not weigh this use case in our designs,
210-
// it is possible for a reference that is considered a remote file to
211-
// actually be a directory
212-
t.Run("exists", func(t *testing.T) {
213-
const remoteFileLikeRoot = "https://domain"
214-
require.True(t, IsRemoteFile(remoteFileLikeRoot))
236+
t.Run("directory", func(t *testing.T) {
215237
fSys, dir := setupOnDisk(t)
216-
require.NoError(t, fSys.MkdirAll(dir.Join("https:/domain")))
238+
parts := []string{
239+
"https:",
240+
"root",
241+
}
242+
require.NoError(t, fSys.MkdirAll(dir.Join(filepath.Join(parts...))))
217243
ldr, err := newLoaderOrDie(RestrictionRootOnly,
218244
fSys,
219245
dir.String(),
220-
).New(remoteFileLikeRoot)
246+
).New(strings.Join(parts, "//"))
221247
require.NoError(t, err)
222248
require.Empty(t, ldr.Repo())
223249
})
@@ -635,6 +661,8 @@ func TestLoaderHTTP(t *testing.T) {
635661

636662
// setupOnDisk sets up a file system on disk and directory that is cleaned after
637663
// test completion.
664+
// TODO(annasong): Move all loader tests that require real file system into
665+
// api/krusty.
638666
func setupOnDisk(t *testing.T) (filesys.FileSystem, filesys.ConfirmedDir) {
639667
t.Helper()
640668

api/testutils/kusttest/ondisk.go

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,27 @@ import (
1111
"sigs.k8s.io/kustomize/kyaml/filesys"
1212
)
1313

14-
// CreateKustDir creates a file system on disk and a new directory
15-
// that holds a kustomization file with content. The directory is removed on
14+
// Setup sets up a file system on disk and directory that is cleaned after
1615
// test completion.
17-
func CreateKustDir(t *testing.T, content string) (filesys.FileSystem, filesys.ConfirmedDir) {
16+
func Setup(t *testing.T) (filesys.FileSystem, filesys.ConfirmedDir) {
1817
t.Helper()
1918

2019
fSys := filesys.MakeFsOnDisk()
21-
tmpDir, err := filesys.NewTmpConfirmedDir()
20+
dir, err := filesys.NewTmpConfirmedDir()
2221
require.NoError(t, err)
23-
require.NoError(t, fSys.WriteFile(filepath.Join(tmpDir.String(), "kustomization.yaml"), []byte(content)))
24-
2522
t.Cleanup(func() {
26-
require.NoError(t, fSys.RemoveAll(tmpDir.String()))
23+
_ = fSys.RemoveAll(dir.String())
2724
})
25+
return fSys, dir
26+
}
27+
28+
// CreateKustDir creates a file system on disk and a new directory
29+
// that holds a kustomization file with content. The directory is removed on
30+
// test completion.
31+
func CreateKustDir(t *testing.T, content string) (filesys.FileSystem, filesys.ConfirmedDir) {
32+
t.Helper()
33+
34+
fSys, tmpDir := Setup(t)
35+
require.NoError(t, fSys.WriteFile(filepath.Join(tmpDir.String(), "kustomization.yaml"), []byte(content)))
2836
return fSys, tmpDir
2937
}

0 commit comments

Comments
 (0)