mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-07-17 17:52:12 +00:00
Localize components (#4867)
This commit is contained in:
@@ -112,6 +112,13 @@ func (lc *localizer) localize() error {
|
|||||||
// localizeNativeFields localizes paths on kustomize-native fields, like configMapGenerator, that kustomize has a
|
// localizeNativeFields localizes paths on kustomize-native fields, like configMapGenerator, that kustomize has a
|
||||||
// built-in understanding of. This excludes helm-related fields, such as `helmGlobals` and `helmCharts`.
|
// built-in understanding of. This excludes helm-related fields, such as `helmGlobals` and `helmCharts`.
|
||||||
func (lc *localizer) localizeNativeFields(kust *types.Kustomization) error {
|
func (lc *localizer) localizeNativeFields(kust *types.Kustomization) error {
|
||||||
|
for i, path := range kust.Components {
|
||||||
|
newPath, err := lc.localizeDir(path)
|
||||||
|
if err != nil {
|
||||||
|
return errors.WrapPrefixf(err, "unable to localize components field")
|
||||||
|
}
|
||||||
|
kust.Components[i] = newPath
|
||||||
|
}
|
||||||
for i := range kust.Patches {
|
for i := range kust.Patches {
|
||||||
if kust.Patches[i].Path != "" {
|
if kust.Patches[i].Path != "" {
|
||||||
newPath, err := lc.localizeFile(kust.Patches[i].Path)
|
newPath, err := lc.localizeFile(kust.Patches[i].Path)
|
||||||
@@ -121,7 +128,7 @@ func (lc *localizer) localizeNativeFields(kust *types.Kustomization) error {
|
|||||||
kust.Patches[i].Path = newPath
|
kust.Patches[i].Path = newPath
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO(annasong): localize all other kustomization fields: resources, bases, components, crds, configurations,
|
// TODO(annasong): localize all other kustomization fields: resources, bases, crds, configurations,
|
||||||
// openapi, patchesJson6902, patchesStrategicMerge, replacements, configMapGenerators, secretGenerators
|
// openapi, patchesJson6902, patchesStrategicMerge, replacements, configMapGenerators, secretGenerators
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -160,6 +167,48 @@ func (lc *localizer) localizeFile(path string) (string, error) {
|
|||||||
return locPath, nil
|
return locPath, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// localizeDir localizes root path and returns the localized path
|
||||||
|
func (lc *localizer) localizeDir(path string) (string, error) {
|
||||||
|
ldr, err := lc.ldr.New(path)
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.Wrap(err)
|
||||||
|
}
|
||||||
|
defer func() { _ = ldr.Cleanup() }()
|
||||||
|
|
||||||
|
root, err := filesys.ConfirmDir(lc.fSys, ldr.Root())
|
||||||
|
if err != nil {
|
||||||
|
log.Panicf("unable to establish validated root reference %q: %s", path, err)
|
||||||
|
}
|
||||||
|
var locPath string
|
||||||
|
if repo := ldr.Repo(); repo != "" {
|
||||||
|
// TODO(annasong): You need to check if you can add a localize directory here to store
|
||||||
|
// the remote file content. There may be a directory that shares the localize directory name.
|
||||||
|
locPath = locRootPath(path, repo, root)
|
||||||
|
} else {
|
||||||
|
locPath, err = filepath.Rel(lc.root.String(), root.String())
|
||||||
|
if err != nil {
|
||||||
|
log.Panicf("cannot find relative path between scoped localize roots %q and %q: %s", lc.root, root, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newDst := filepath.Join(lc.dst, locPath)
|
||||||
|
if err = lc.fSys.MkdirAll(newDst); err != nil {
|
||||||
|
return "", errors.WrapPrefixf(err, "unable to create root %q in localize destination", path)
|
||||||
|
}
|
||||||
|
err = (&localizer{
|
||||||
|
fSys: lc.fSys,
|
||||||
|
validator: lc.validator,
|
||||||
|
rFactory: lc.rFactory,
|
||||||
|
pLdr: lc.pLdr,
|
||||||
|
ldr: ldr,
|
||||||
|
root: root,
|
||||||
|
dst: newDst,
|
||||||
|
}).localize()
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.WrapPrefixf(err, "unable to localize root %q", path)
|
||||||
|
}
|
||||||
|
return locPath, nil
|
||||||
|
}
|
||||||
|
|
||||||
// localizeBuiltinPlugins localizes built-in plugins on kust that can contain file paths. The built-in plugins
|
// localizeBuiltinPlugins localizes built-in plugins on kust that can contain file paths. The built-in plugins
|
||||||
// can be inline or in a file. This excludes the HelmChartInflationGenerator.
|
// can be inline or in a file. This excludes the HelmChartInflationGenerator.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -488,3 +488,170 @@ when parsing as filepath received error: %s`, test.errPrefix, test.inlineErrMsg,
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLocalizeDirInTarget(t *testing.T) {
|
||||||
|
type testCase struct {
|
||||||
|
name string
|
||||||
|
files map[string]string
|
||||||
|
}
|
||||||
|
for _, tc := range []testCase{
|
||||||
|
{
|
||||||
|
name: "multi_nested_child",
|
||||||
|
files: map[string]string{
|
||||||
|
"kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
components:
|
||||||
|
- delta/epsilon
|
||||||
|
kind: Kustomization
|
||||||
|
`,
|
||||||
|
"delta/epsilon/kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1alpha1
|
||||||
|
kind: Component
|
||||||
|
namespace: kustomize-namespace
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "recursive",
|
||||||
|
files: map[string]string{
|
||||||
|
"kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
components:
|
||||||
|
- delta
|
||||||
|
kind: Kustomization
|
||||||
|
`,
|
||||||
|
"delta/kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1alpha1
|
||||||
|
components:
|
||||||
|
- epsilon
|
||||||
|
kind: Component
|
||||||
|
`,
|
||||||
|
"delta/epsilon/kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1alpha1
|
||||||
|
kind: Component
|
||||||
|
namespace: kustomize-namespace
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "file_in_dir",
|
||||||
|
files: map[string]string{
|
||||||
|
"kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
components:
|
||||||
|
- delta
|
||||||
|
kind: Kustomization
|
||||||
|
`,
|
||||||
|
"delta/kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1alpha1
|
||||||
|
kind: Component
|
||||||
|
patches:
|
||||||
|
- path: patch.yaml
|
||||||
|
`,
|
||||||
|
"delta/patch.yaml": podConfiguration,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "multiple_calls",
|
||||||
|
files: map[string]string{
|
||||||
|
"kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
components:
|
||||||
|
- delta
|
||||||
|
- delta/epsilon
|
||||||
|
kind: Kustomization
|
||||||
|
`,
|
||||||
|
"delta/kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1alpha1
|
||||||
|
kind: Component
|
||||||
|
namespace: kustomize-namespace
|
||||||
|
`,
|
||||||
|
"delta/epsilon/kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1alpha1
|
||||||
|
buildMetadata:
|
||||||
|
- managedByLabel
|
||||||
|
kind: Component
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "localize_directory_name_when_no_remote",
|
||||||
|
files: map[string]string{
|
||||||
|
"kustomization.yaml": fmt.Sprintf(`apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
components:
|
||||||
|
- %s
|
||||||
|
kind: Kustomization
|
||||||
|
`, LocalizeDir),
|
||||||
|
fmt.Sprintf("%s/kustomization.yaml", LocalizeDir): `apiVersion: kustomize.config.k8s.io/v1alpha1
|
||||||
|
kind: Component
|
||||||
|
namespace: kustomize-namespace
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
fSys := makeMemoryFs(t)
|
||||||
|
addFiles(t, fSys, "/alpha/beta/gamma", tc.files)
|
||||||
|
|
||||||
|
err := Run("/alpha/beta/gamma", "/alpha/beta", "/dst", fSys)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
fSysExpected := makeMemoryFs(t)
|
||||||
|
addFiles(t, fSysExpected, "/alpha/beta/gamma", tc.files)
|
||||||
|
addFiles(t, fSysExpected, "/dst/gamma", tc.files)
|
||||||
|
checkFSys(t, fSysExpected, fSys)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizeDirCleanedSibling(t *testing.T) {
|
||||||
|
fSys := makeMemoryFs(t)
|
||||||
|
kustAndComponents := map[string]string{
|
||||||
|
// This test checks that winding paths that might traverse through directories
|
||||||
|
// outside of scope, which will not be present at destination, are cleaned.
|
||||||
|
"beta/gamma/kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
components:
|
||||||
|
- delta/../../../../a/b/../../alpha/beta/sibling
|
||||||
|
kind: Kustomization`,
|
||||||
|
"beta/sibling/kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1alpha1
|
||||||
|
kind: Component
|
||||||
|
namespace: kustomize-namespace
|
||||||
|
`,
|
||||||
|
}
|
||||||
|
addFiles(t, fSys, "/alpha", kustAndComponents)
|
||||||
|
|
||||||
|
err := Run("/alpha/beta/gamma", "/alpha", "/alpha/beta/dst", fSys)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
fSysExpected := makeMemoryFs(t)
|
||||||
|
addFiles(t, fSysExpected, "/alpha", kustAndComponents)
|
||||||
|
cleanedFiles := map[string]string{
|
||||||
|
"beta/gamma/kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
components:
|
||||||
|
- ../sibling
|
||||||
|
kind: Kustomization
|
||||||
|
`,
|
||||||
|
"beta/sibling/kustomization.yaml": kustAndComponents["beta/sibling/kustomization.yaml"],
|
||||||
|
}
|
||||||
|
addFiles(t, fSysExpected, "/alpha/beta/dst", cleanedFiles)
|
||||||
|
checkFSys(t, fSysExpected, fSys)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizeComponents(t *testing.T) {
|
||||||
|
fSys := makeMemoryFs(t)
|
||||||
|
kustAndComponents := map[string]string{
|
||||||
|
"kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
components:
|
||||||
|
- a
|
||||||
|
- alpha
|
||||||
|
kind: Kustomization
|
||||||
|
`,
|
||||||
|
"a/kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1alpha1
|
||||||
|
kind: Component
|
||||||
|
namePrefix: my-
|
||||||
|
`,
|
||||||
|
"alpha/kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1alpha1
|
||||||
|
kind: Component
|
||||||
|
nameSuffix: -test
|
||||||
|
`,
|
||||||
|
}
|
||||||
|
addFiles(t, fSys, "/", kustAndComponents)
|
||||||
|
|
||||||
|
err := Run("/", "", "", fSys)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
fSysExpected := makeMemoryFs(t)
|
||||||
|
addFiles(t, fSysExpected, "/", kustAndComponents)
|
||||||
|
addFiles(t, fSysExpected, "/localized", kustAndComponents)
|
||||||
|
checkFSys(t, fSysExpected, fSys)
|
||||||
|
}
|
||||||
|
|||||||
@@ -145,3 +145,12 @@ func locFilePath(fileURL string) string {
|
|||||||
// so we can use it as is.
|
// so we can use it as is.
|
||||||
return filepath.Join(LocalizeDir, u.Hostname(), path)
|
return filepath.Join(LocalizeDir, u.Hostname(), path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// locRootPath returns the relative localized path of the validated root url rootURL, where the local copy of its repo
|
||||||
|
// is at repoDir and the copy of its root is at rootDir
|
||||||
|
// TODO(annasong): implement
|
||||||
|
func locRootPath(rootURL string, repoDir string, rootDir filesys.ConfirmedDir) string {
|
||||||
|
_ = rootURL
|
||||||
|
_, _ = repoDir, rootDir
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user