diff --git a/api/internal/localizer/localizer.go b/api/internal/localizer/localizer.go index 206c31a13..0db070176 100644 --- a/api/internal/localizer/localizer.go +++ b/api/internal/localizer/localizer.go @@ -38,10 +38,11 @@ type localizer struct { } // Run attempts to localize the kustomization root at target with the given localize arguments -func Run(target string, scope string, newDir string, fSys filesys.FileSystem) error { +// and returns the path to the created newDir. +func Run(target, scope, newDir string, fSys filesys.FileSystem) (string, error) { ldr, args, err := NewLoader(target, scope, newDir, fSys) if err != nil { - return errors.Wrap(err) + return "", errors.Wrap(err) } defer func() { _ = ldr.Cleanup() }() @@ -51,7 +52,7 @@ func Run(target string, scope string, newDir string, fSys filesys.FileSystem) er } dst := args.NewDir.Join(toDst) if err = fSys.MkdirAll(dst); err != nil { - return errors.WrapPrefixf(err, "unable to create directory in localize destination") + return "", errors.WrapPrefixf(err, "unable to create directory in localize destination") } err = (&localizer{ @@ -66,9 +67,9 @@ func Run(target string, scope string, newDir string, fSys filesys.FileSystem) er if errCleanup != nil { log.Printf("unable to clean localize destination: %s", errCleanup) } - return errors.WrapPrefixf(err, "unable to localize target %q", target) + return "", errors.WrapPrefixf(err, "unable to localize target %q", target) } - return nil + return args.NewDir.String(), nil } // localize localizes the root that lc is at diff --git a/api/internal/localizer/localizer_test.go b/api/internal/localizer/localizer_test.go index f86d059f8..af30100de 100644 --- a/api/internal/localizer/localizer_test.go +++ b/api/internal/localizer/localizer_test.go @@ -102,6 +102,14 @@ func addFiles(t *testing.T, fSys filesys.FileSystem, parentDir string, files map } } +func checkRun(t *testing.T, fSys filesys.FileSystem, target, scope, dst string) { + t.Helper() + + actualDst, err := Run(target, scope, dst, fSys) + require.NoError(t, err) + require.Equal(t, dst, actualDst) +} + func makeFileSystems(t *testing.T, target string, files map[string]string) (expected filesys.FileSystem, actual filesys.FileSystem) { t.Helper() @@ -161,9 +169,7 @@ func checkLocalizeInTargetSuccess(t *testing.T, files map[string]string) { fSys := makeMemoryFs(t) addFiles(t, fSys, "/a", files) - err := Run("/a", "/", "dst", fSys) - require.NoError(t, err) - + checkRun(t, fSys, "/a", "/", "/dst") fSysExpected := makeMemoryFs(t) addFiles(t, fSysExpected, "/a", files) addFiles(t, fSysExpected, "/dst/a", files) @@ -179,9 +185,7 @@ namePrefix: my- } fSysExpected, fSysActual := makeFileSystems(t, "/a", kustomization) - err := Run("/a", "", "/a/b/dst", fSysActual) - require.NoError(t, err) - + checkRun(t, fSysActual, "/a", "/a", "/a/b/dst") addFiles(t, fSysExpected, "/a/b/dst", kustomization) checkFSys(t, fSysExpected, fSysActual) } @@ -202,9 +206,7 @@ patches: } fSysExpected, fSysActual := makeFileSystems(t, "/a/b", kustomization) - err := Run("/a/b", "/", "/a/b/dst", fSysActual) - require.NoError(t, err) - + checkRun(t, fSysActual, "/a/b", "/", "/a/b/dst") addFiles(t, fSysExpected, "/a/b/dst/a/b", kustomization) checkFSys(t, fSysExpected, fSysActual) } @@ -259,7 +261,7 @@ func TestLoadUnknownKustFields(t *testing.T) { suffix: invalid`, }) - err := Run("/a", "", "", fSysTest) + _, err := Run("/a", "", "", fSysTest) require.EqualError(t, err, `unable to localize target "/a": invalid Kustomization: error unmarshaling JSON: while decoding JSON: json: unknown field "suffix"`) @@ -299,9 +301,7 @@ patches: } expected, actual := makeFileSystems(t, "/alpha/beta/gamma", kustAndPatch) - err := Run("/alpha/beta/gamma", "/", "", actual) - require.NoError(t, err) - + checkRun(t, actual, "/alpha/beta/gamma", "/", "/localized-gamma") addFiles(t, expected, "/localized-gamma/alpha/beta/gamma", map[string]string{ "kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization @@ -328,9 +328,7 @@ kind: Kustomization } expected, actual := makeFileSystems(t, "/alpha/beta", targetAndUnreferenced) - err := Run("/alpha/beta", "/alpha", "/beta", actual) - require.NoError(t, err) - + checkRun(t, actual, "/alpha/beta", "/alpha", "/beta") addFiles(t, expected, "/beta/beta", map[string]string{ "kustomization.yaml": targetAndUnreferenced["kustomization.yaml"], "env": targetAndUnreferenced["env"], @@ -586,7 +584,7 @@ patches: } expected, actual := makeFileSystems(t, "/a/b", kustAndPatch) - err := Run("/a/b", "", "/dst", actual) + _, err := Run("/a/b", "", "/dst", actual) require.EqualError(t, err, `unable to localize target "/a/b": unable to localize patches: invalid file reference: '/a/b/name-DNE.yaml' doesn't exist`) checkFSys(t, expected, actual) @@ -710,9 +708,7 @@ transformers: } expected, actual := makeFileSystems(t, "/a", kustAndPlugins) - err := Run("/a", "", "/dst", actual) - require.NoError(t, err) - + checkRun(t, actual, "/a", "/a", "/dst") addFiles(t, expected, "/dst", map[string]string{ "kustomization.yaml": kustAndPlugins["kustomization.yaml"], "patch.yaml": fmt.Sprintf(patchf, "patchSM.yaml"), @@ -971,7 +967,7 @@ metadata: t.Run(test.name, func(t *testing.T) { expected, actual := makeFileSystems(t, "/", test.files) - err := Run("/", "", "/dst", actual) + _, err := Run("/", "", "/dst", actual) var actualErr ResourceLoadError require.ErrorAs(t, err, &actualErr) @@ -1025,7 +1021,7 @@ func TestLocalizeBuiltinPlugins_Errors(t *testing.T) { } { t.Run(name, func(t *testing.T) { expected, actual := makeFileSystems(t, "/a", test.files) - err := Run("/a", "", "/dst", actual) + _, err := Run("/a", "", "/dst", actual) const errPrefix = `unable to localize target "/a"` require.EqualError(t, err, fmt.Sprintf( "%s: %s: %s", errPrefix, test.fieldSpecErr, test.locErr)) @@ -1145,9 +1141,7 @@ namespace: kustomize-namespace } expected, actual := makeFileSystems(t, "/alpha", kustAndComponents) - err := Run("/alpha/beta/gamma", "/alpha", "/alpha/beta/dst", actual) - require.NoError(t, err) - + checkRun(t, actual, "/alpha/beta/gamma", "/alpha", "/alpha/beta/dst") cleanedFiles := map[string]string{ "beta/gamma/kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1beta1 components: @@ -1210,9 +1204,7 @@ namePrefix: my- } expected, actual := makeFileSystems(t, "/a/b", kustAndResources) - err := Run("/a/b", "/", "", actual) - require.NoError(t, err) - + checkRun(t, actual, "/a/b", "/", "/localized-b") addFiles(t, expected, "/localized-b/a/b", kustAndResources) checkFSys(t, expected, actual) } @@ -1227,7 +1219,7 @@ resources: } expected, actual := makeFileSystems(t, "/a", kustAndResources) - err := Run("/a", "/", "", actual) + _, err := Run("/a", "/", "", actual) const expectedFileErr = `invalid file reference: '/a/b' must resolve to a file` const expectedRootErr = `unable to localize root "b": unable to find one of 'kustomization.yaml', 'kustomization.yml' or 'Kustomization' in directory '/a/b'` @@ -1324,9 +1316,7 @@ func TestLocalizeHelmChartsNoDefault(t *testing.T) { } expected, actual := makeFileSystems(t, "/a", files) - err := Run("/a", "", "/dst", actual) - require.NoError(t, err) - + checkRun(t, actual, "/a", "/a", "/dst") addFiles(t, expected, "/dst", map[string]string{ "kustomization.yaml": files["kustomization.yaml"], "home/name/values.yaml": valuesFile, @@ -1440,9 +1430,7 @@ helmGlobals: t.Run(name, func(t *testing.T) { expected, actual := makeFileSystems(t, "/a/b", test.files) - err := Run("/a/b", "/a/b", "/dst", actual) - require.NoError(t, err) - + checkRun(t, actual, "/a/b", "/a/b", "/dst") addFiles(t, expected, "/dst", test.copiedFiles) checkFSys(t, expected, actual) }) @@ -1459,9 +1447,7 @@ func TestCopyChartHomeEmpty(t *testing.T) { require.NoError(t, actual.Mkdir("/a/home")) require.NoError(t, expected.Mkdir("/a/home")) - err := Run("/a", "", "/dst", actual) - require.NoError(t, err) - + checkRun(t, actual, "/a", "/a", "/dst") addFiles(t, expected, "/dst", kustomization) require.NoError(t, expected.Mkdir("/dst/home")) checkFSys(t, expected, actual) @@ -1503,7 +1489,7 @@ func TestCopyChartHomeError(t *testing.T) { t.Run(name, func(t *testing.T) { expected, actual := makeFileSystems(t, "/", test.files) - err := Run("/a/b", "/a", "/dst", actual) + _, err := Run("/a/b", "/a", "/dst", actual) const prefix = `unable to localize target "/a/b"` require.EqualError(t, err, fmt.Sprintf("%s: %s", prefix, test.err)) @@ -1558,9 +1544,7 @@ metadata: } expected, actual := makeFileSystems(t, "/a", files) - err := Run("/a", "", "/dst", actual) - require.NoError(t, err) - + checkRun(t, actual, "/a", "/a", "/dst") addFiles(t, expected, "/dst", map[string]string{ "kustomization.yaml": files["kustomization.yaml"], "configMap.yaml": files["configMap.yaml"], diff --git a/api/krusty/localizer/runner.go b/api/krusty/localizer/runner.go index a6d831d0e..44d2a02c2 100644 --- a/api/krusty/localizer/runner.go +++ b/api/krusty/localizer/runner.go @@ -9,7 +9,9 @@ import ( "sigs.k8s.io/kustomize/kyaml/filesys" ) -// Run `kustomize localize`s files referenced by kustomization target in scope to destination newDir on fSys. -func Run(fSys filesys.FileSystem, target, scope, newDir string) error { - return errors.Wrap(localizer.Run(target, scope, newDir, fSys)) +// Run executes `kustomize localize` on fSys given the `localize` arguments and +// returns the path to the created newDir. +func Run(fSys filesys.FileSystem, target, scope, newDir string) (string, error) { + dst, err := localizer.Run(target, scope, newDir, fSys) + return dst, errors.Wrap(err) } diff --git a/api/krusty/localizer/runner_test.go b/api/krusty/localizer/runner_test.go index 2472b726d..faef9648c 100644 --- a/api/krusty/localizer/runner_test.go +++ b/api/krusty/localizer/runner_test.go @@ -264,10 +264,11 @@ func TestWorkingDir(t *testing.T) { fsExpected, fsActual, wd := PrepareFs(t, []string{"target", "base"}, files) SetWorkingDir(t, wd.String()) - err := localizer.Run(fsActual, "target", ".", "") + dst, err := localizer.Run(fsActual, "target", ".", "") require.NoError(t, err) + require.Equal(t, wd.Join("localized-target"), dst) - SetupDir(t, fsExpected, wd.Join("localized-target"), files) + SetupDir(t, fsExpected, dst, files) CheckFs(t, wd.String(), fsExpected, fsActual) } @@ -301,10 +302,10 @@ func TestLoaderSymlinks(t *testing.T) { }) SetWorkingDir(t, testDir.String()) - err := localizer.Run(fsActual, "target-link", "target", "") + dst, err := localizer.Run(fsActual, "target-link", "target", "") require.NoError(t, err) + require.Equal(t, testDir.Join("localized-target"), dst) - dst := testDir.Join("localized-target") SetupDir(t, fsExpected, dst, map[string]string{ "kustomization.yaml": fmt.Sprintf(`resources: - %s @@ -322,10 +323,10 @@ func TestRemoteTargetDefaultDst(t *testing.T) { SetWorkingDir(t, testDir.String()) const target = simpleURL + urlQuery - err := localizer.Run(fsActual, target, "", "") + dst, err := localizer.Run(fsActual, target, "", "") require.NoError(t, err) + require.Equal(t, testDir.Join("localized-simple-kustomize-v4.5.7"), dst) - dst := testDir.Join("localized-simple-kustomize-v4.5.7") _, files := simplePathAndFiles(t) SetupDir(t, fsExpected, filepath.Join(dst, "api", "krusty", "testdata", "localize", "simple"), @@ -364,7 +365,7 @@ func TestBadArgs(t *testing.T) { fsExpected, fsActual, testDir := PrepareFs(t, nil, kust) SetWorkingDir(t, testDir.String()) - err := localizer.Run(fsActual, test.target, test.scope, test.dst) + _, err := localizer.Run(fsActual, test.target, test.scope, test.dst) require.EqualError(t, err, test.err) SetupDir(t, fsExpected, testDir.String(), kust) @@ -383,9 +384,10 @@ openapi: "kustomization.yaml": fmt.Sprintf(kustf, `https://raw.githubusercontent.com/kubernetes-sigs/kustomize/kustomize/v4.5.7/api/krusty/testdata/customschema.json`), }) - dst := testDir.Join("dst") - err := localizer.Run(fsActual, testDir.String(), "", dst) + newDir := testDir.Join("dst") + dst, err := localizer.Run(fsActual, testDir.String(), "", newDir) require.NoError(t, err) + require.Equal(t, newDir, dst) localizedPath := filepath.Join(LocalizeDir, "raw.githubusercontent.com", "kubernetes-sigs", "kustomize", "kustomize", "v4.5.7", "api", "krusty", @@ -404,9 +406,10 @@ func TestRemoteRoot(t *testing.T) { `, simpleURL+urlQuery), }) - dst := testDir.Join("dst") - err := localizer.Run(fsActual, testDir.String(), "", dst) + newDir := testDir.Join("dst") + dst, err := localizer.Run(fsActual, testDir.String(), "", newDir) require.NoError(t, err) + require.Equal(t, newDir, dst) localizedPath, files := simplePathAndFiles(t) SetupDir(t, fsExpected, dst, map[string]string{ @@ -427,9 +430,10 @@ func TestNestedRemoteRoots(t *testing.T) { `, }) - dst := testDir.Join("dst") - err := localizer.Run(fsActual, testDir.String(), "", dst) + newDir := testDir.Join("dst") + dst, err := localizer.Run(fsActual, testDir.String(), "", newDir) require.NoError(t, err) + require.Equal(t, newDir, dst) localizedPath, files := remotePathAndFiles(t) SetupDir(t, fsExpected, dst, map[string]string{ @@ -450,7 +454,7 @@ func TestResourcesRepoNotFile(t *testing.T) { } fsExpected, fsActual, testDir := PrepareFs(t, nil, kustomization) - err := localizer.Run(fsActual, testDir.String(), "", testDir.Join("dst")) + _, err := localizer.Run(fsActual, testDir.String(), "", testDir.Join("dst")) fileErr := fmt.Sprintf(`invalid resource at file "%s": MalformedYAMLError`, repo) rootErr := fmt.Sprintf(`unable to localize root "%s": unable to find one of 'kustomization.yaml', 'kustomization.yml' or 'Kustomization'`, repo) @@ -473,7 +477,7 @@ func TestRemoteRootNoRef(t *testing.T) { } fsExpected, fsActual, testDir := PrepareFs(t, nil, kustomization) - err := localizer.Run(fsActual, testDir.String(), "", testDir.Join("dst")) + _, err := localizer.Run(fsActual, testDir.String(), "", testDir.Join("dst")) const fileErr = "invalid file reference: URL is a git repository" rootErr := fmt.Sprintf(`localize remote root "%s" missing ref query string parameter`, root) @@ -497,7 +501,7 @@ func TestExistingCacheDir(t *testing.T) { } fsExpected, fsActual, testDir := PrepareFs(t, []string{LocalizeDir}, file) - err := localizer.Run(fsActual, testDir.String(), "", testDir.Join("dst")) + _, err := localizer.Run(fsActual, testDir.String(), "", testDir.Join("dst")) require.ErrorContains(t, err, fmt.Sprintf(`already contains localized-files needed to store file "%s"`, remoteFile)) SetupDir(t, fsExpected, testDir.String(), file) @@ -518,9 +522,10 @@ minecraftServer: filepath.Join("nested", "dirs", "home", "name"), }, files) - dst := testDir.Join("dst") - err := localizer.Run(fsActual, testDir.String(), "", dst) + newDir := testDir.Join("dst") + dst, err := localizer.Run(fsActual, testDir.String(), "", newDir) require.NoError(t, err) + require.Equal(t, newDir, dst) SetupDir(t, fsExpected, dst, files) CheckFs(t, dst, fsExpected, fsActual) @@ -553,9 +558,10 @@ helmGlobals: filepath.Join("target", "home-link"): "home", }) - dst := scope.Join("dst") - err := localizer.Run(fsActual, scope.Join("target"), scope.String(), dst) + newDir := scope.Join("dst") + dst, err := localizer.Run(fsActual, scope.Join("target"), scope.String(), newDir) require.NoError(t, err) + require.Equal(t, newDir, dst) SetupDir(t, fsExpected, dst, map[string]string{ filepath.Join("target", "Kustomization"): fmt.Sprintf(`helmCharts: @@ -592,9 +598,10 @@ helmChartInflationGenerator: }) link(t, target, map[string]string{"charts": "home"}) - dst := target.Join("dst") - err := localizer.Run(fsActual, target.String(), "", dst) + newDir := target.Join("dst") + dst, err := localizer.Run(fsActual, target.String(), "", newDir) require.NoError(t, err) + require.Equal(t, newDir, dst) SetupDir(t, fsExpected, dst, map[string]string{ "kustomization.yaml": `helmChartInflationGenerator: @@ -632,9 +639,10 @@ func TestHelmHomeEscapesScope(t *testing.T) { filepath.Join("target", "home", "file-link"): "file", }) - dst := testDir.Join("dst") - err := localizer.Run(fsActual, testDir.Join("target"), "", dst) + newDir := testDir.Join("dst") + dst, err := localizer.Run(fsActual, testDir.Join("target"), "", newDir) require.NoError(t, err) + require.Equal(t, newDir, dst) SetupDir(t, fsExpected, dst, map[string]string{ "kustomization.yaml": `helmGlobals: @@ -661,9 +669,10 @@ func TestSymlinkedFileSource(t *testing.T) { "filename-used-as-key-in-configMap": "different-key", }) - dst := target.Join("dst") - err := localizer.Run(fsActual, target.String(), "", dst) + newDir := target.Join("dst") + dst, err := localizer.Run(fsActual, target.String(), "", newDir) require.NoError(t, err) + require.Equal(t, newDir, dst) SetupDir(t, fsExpected, dst, map[string]string{ "kustomization.yaml": `configMapGenerator: