mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-14 10:30:59 +00:00
Localize ConfigMapGenerator, SecretGenerator
This commit is contained in:
@@ -32,6 +32,22 @@ func (lbp *localizeBuiltinPlugins) Filter(plugins []*yaml.RNode) ([]*yaml.RNode,
|
|||||||
for _, singlePlugin := range plugins {
|
for _, singlePlugin := range plugins {
|
||||||
err := singlePlugin.PipeE(fsslice.Filter{
|
err := singlePlugin.PipeE(fsslice.Filter{
|
||||||
FsSlice: types.FsSlice{
|
FsSlice: types.FsSlice{
|
||||||
|
types.FieldSpec{
|
||||||
|
Gvk: resid.Gvk{Version: konfig.BuiltinPluginApiVersion, Kind: builtinhelpers.ConfigMapGenerator.String()},
|
||||||
|
Path: "env",
|
||||||
|
},
|
||||||
|
types.FieldSpec{
|
||||||
|
Gvk: resid.Gvk{Version: konfig.BuiltinPluginApiVersion, Kind: builtinhelpers.ConfigMapGenerator.String()},
|
||||||
|
Path: "envs",
|
||||||
|
},
|
||||||
|
types.FieldSpec{
|
||||||
|
Gvk: resid.Gvk{Version: konfig.BuiltinPluginApiVersion, Kind: builtinhelpers.SecretGenerator.String()},
|
||||||
|
Path: "env",
|
||||||
|
},
|
||||||
|
types.FieldSpec{
|
||||||
|
Gvk: resid.Gvk{Version: konfig.BuiltinPluginApiVersion, Kind: builtinhelpers.SecretGenerator.String()},
|
||||||
|
Path: "envs",
|
||||||
|
},
|
||||||
types.FieldSpec{
|
types.FieldSpec{
|
||||||
Gvk: resid.Gvk{Version: konfig.BuiltinPluginApiVersion, Kind: builtinhelpers.PatchTransformer.String()},
|
Gvk: resid.Gvk{Version: konfig.BuiltinPluginApiVersion, Kind: builtinhelpers.PatchTransformer.String()},
|
||||||
Path: "path",
|
Path: "path",
|
||||||
@@ -47,20 +63,36 @@ func (lbp *localizeBuiltinPlugins) Filter(plugins []*yaml.RNode) ([]*yaml.RNode,
|
|||||||
},
|
},
|
||||||
SetValue: func(node *yaml.RNode) error {
|
SetValue: func(node *yaml.RNode) error {
|
||||||
lbp.locPathFn = lbp.lc.localizeFile
|
lbp.locPathFn = lbp.lc.localizeFile
|
||||||
return lbp.localizeNode(node)
|
return lbp.localizeAll(node)
|
||||||
},
|
},
|
||||||
}, fieldspec.Filter{
|
},
|
||||||
FieldSpec: types.FieldSpec{
|
fsslice.Filter{
|
||||||
Gvk: resid.Gvk{Version: konfig.BuiltinPluginApiVersion, Kind: builtinhelpers.PatchStrategicMergeTransformer.String()},
|
FsSlice: types.FsSlice{
|
||||||
Path: "paths",
|
types.FieldSpec{
|
||||||
|
Gvk: resid.Gvk{Version: konfig.BuiltinPluginApiVersion, Kind: builtinhelpers.ConfigMapGenerator.String()},
|
||||||
|
Path: "files",
|
||||||
|
},
|
||||||
|
types.FieldSpec{
|
||||||
|
Gvk: resid.Gvk{Version: konfig.BuiltinPluginApiVersion, Kind: builtinhelpers.SecretGenerator.String()},
|
||||||
|
Path: "files",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
SetValue: func(node *yaml.RNode) error {
|
||||||
|
lbp.locPathFn = lbp.lc.localizeFileSource
|
||||||
|
return lbp.localizeAll(node)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
SetValue: func(node *yaml.RNode) error {
|
fieldspec.Filter{
|
||||||
lbp.locPathFn = lbp.lc.localizeK8sResource
|
FieldSpec: types.FieldSpec{
|
||||||
return errors.Wrap(node.VisitElements(lbp.localizeNode))
|
Gvk: resid.Gvk{Version: konfig.BuiltinPluginApiVersion, Kind: builtinhelpers.PatchStrategicMergeTransformer.String()},
|
||||||
},
|
Path: "paths",
|
||||||
})
|
},
|
||||||
// TODO(annasong): localize ConfigMapGenerator, SecretGenerator,
|
SetValue: func(node *yaml.RNode) error {
|
||||||
// HelmChartInflationGenerator
|
lbp.locPathFn = lbp.lc.localizeK8sResource
|
||||||
|
return lbp.localizeAll(node)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
// TODO(annasong): localize HelmChartInflationGenerator
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err)
|
return nil, errors.Wrap(err)
|
||||||
}
|
}
|
||||||
@@ -68,14 +100,27 @@ func (lbp *localizeBuiltinPlugins) Filter(plugins []*yaml.RNode) ([]*yaml.RNode,
|
|||||||
return plugins, nil
|
return plugins, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// localizeNode sets the scalar node to its value localized by locPathFn.
|
// localizeAll sets each entry in node to its value localized by locPathFn.
|
||||||
func (lbp *localizeBuiltinPlugins) localizeNode(node *yaml.RNode) error {
|
// Node is a sequence or scalar value.
|
||||||
|
func (lbp *localizeBuiltinPlugins) localizeAll(node *yaml.RNode) error {
|
||||||
|
// We rely on the build command to throw errors for nodes in
|
||||||
|
// built-in plugins that are sequences when expected to be scalar,
|
||||||
|
// and vice versa.
|
||||||
|
switch node.YNode().Kind {
|
||||||
|
case yaml.SequenceNode:
|
||||||
|
return errors.Wrap(node.VisitElements(lbp.localizeScalar))
|
||||||
|
case yaml.ScalarNode:
|
||||||
|
return lbp.localizeScalar(node)
|
||||||
|
default:
|
||||||
|
return errors.Errorf("expected sequence or scalar node")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// localizeScalar sets the scalar node to its value localized by locPathFn.
|
||||||
|
func (lbp *localizeBuiltinPlugins) localizeScalar(node *yaml.RNode) error {
|
||||||
localizedPath, err := lbp.locPathFn(node.YNode().Value)
|
localizedPath, err := lbp.locPathFn(node.YNode().Value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if localizedPath != "" {
|
return filtersutil.SetScalar(localizedPath)(node)
|
||||||
err = filtersutil.SetScalar(localizedPath)(node)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -193,9 +193,7 @@ func (lc *localizer) localizeNativeFields(kust *types.Kustomization) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WrapPrefixf(err, "unable to localize patchesStrategicMerge entry")
|
return errors.WrapPrefixf(err, "unable to localize patchesStrategicMerge entry")
|
||||||
}
|
}
|
||||||
if locPath != "" {
|
kust.PatchesStrategicMerge[i] = types.PatchStrategicMerge(locPath)
|
||||||
kust.PatchesStrategicMerge[i] = types.PatchStrategicMerge(locPath)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for i, replacement := range kust.Replacements {
|
for i, replacement := range kust.Replacements {
|
||||||
locPath, err := lc.localizeFile(replacement.Path)
|
locPath, err := lc.localizeFile(replacement.Path)
|
||||||
@@ -222,18 +220,10 @@ func (lc *localizer) localizeGenerator(generator *types.GeneratorArgs) error {
|
|||||||
}
|
}
|
||||||
locFiles := make([]string, len(generator.FileSources))
|
locFiles := make([]string, len(generator.FileSources))
|
||||||
for i, file := range generator.FileSources {
|
for i, file := range generator.FileSources {
|
||||||
k, f, err := generators.ParseFileSource(file)
|
locFiles[i], err = lc.localizeFileSource(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WrapPrefixf(err, "unable to parse generator files entry %q", file)
|
return err
|
||||||
}
|
}
|
||||||
newFile, err := lc.localizeFile(f)
|
|
||||||
if err != nil {
|
|
||||||
return errors.WrapPrefixf(err, "unable to localize generator files path in entry %q", file)
|
|
||||||
}
|
|
||||||
if f != file {
|
|
||||||
newFile = k + "=" + newFile
|
|
||||||
}
|
|
||||||
locFiles[i] = newFile
|
|
||||||
}
|
}
|
||||||
generator.EnvSource = locEnvSrc
|
generator.EnvSource = locEnvSrc
|
||||||
generator.EnvSources = locEnvs
|
generator.EnvSources = locEnvs
|
||||||
@@ -241,6 +231,26 @@ func (lc *localizer) localizeGenerator(generator *types.GeneratorArgs) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// localizeFileSource returns the localized file source found in configMap and
|
||||||
|
// secretGenerators.
|
||||||
|
func (lc *localizer) localizeFileSource(source string) (string, error) {
|
||||||
|
key, file, err := generators.ParseFileSource(source)
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.Wrap(err)
|
||||||
|
}
|
||||||
|
locFile, err := lc.localizeFile(file)
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.WrapPrefixf(err, "invalid file source %q", source)
|
||||||
|
}
|
||||||
|
var locSource string
|
||||||
|
if source == file {
|
||||||
|
locSource = locFile
|
||||||
|
} else {
|
||||||
|
locSource = key + "=" + locFile
|
||||||
|
}
|
||||||
|
return locSource, nil
|
||||||
|
}
|
||||||
|
|
||||||
// localizeHelmInflationGenerator localizes helmChartInflationGenerator on kust.
|
// localizeHelmInflationGenerator localizes helmChartInflationGenerator on kust.
|
||||||
// localizeHelmInflationGenerator localizes values files and copies local chart homes.
|
// localizeHelmInflationGenerator localizes values files and copies local chart homes.
|
||||||
func (lc *localizer) localizeHelmInflationGenerator(kust *types.Kustomization) error {
|
func (lc *localizer) localizeHelmInflationGenerator(kust *types.Kustomization) error {
|
||||||
@@ -559,10 +569,9 @@ func (lc *localizer) localizeBuiltinPlugins(kust *types.Kustomization) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// localizeK8sResource returns the localized file path if resourceEntry is a
|
// localizeK8sResource returns the localized resourceEntry if it is a file
|
||||||
// file containing a kubernetes resource.
|
// containing a kubernetes resource.
|
||||||
// localizeK8sResource returns the empty string if resourceEntry is an inline
|
// localizeK8sResource returns resourceEntry if it is an inline resource.
|
||||||
// resource.
|
|
||||||
func (lc *localizer) localizeK8sResource(resourceEntry string) (string, error) {
|
func (lc *localizer) localizeK8sResource(resourceEntry string) (string, error) {
|
||||||
_, isFile, err := lc.loadK8sResource(resourceEntry)
|
_, isFile, err := lc.loadK8sResource(resourceEntry)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -571,7 +580,7 @@ func (lc *localizer) localizeK8sResource(resourceEntry string) (string, error) {
|
|||||||
if isFile {
|
if isFile {
|
||||||
return lc.localizeFile(resourceEntry)
|
return lc.localizeFile(resourceEntry)
|
||||||
}
|
}
|
||||||
return "", nil
|
return resourceEntry, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// loadK8sResource tries to load resourceEntry as a file path or inline
|
// loadK8sResource tries to load resourceEntry as a file path or inline
|
||||||
|
|||||||
@@ -670,37 +670,61 @@ transformers:
|
|||||||
checkFSys(t, expected, actual)
|
checkFSys(t, expected, actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLocalizeGenerators(t *testing.T) {
|
func TestLocalizeGeneratorsConfigMap(t *testing.T) {
|
||||||
kustAndPlugins := map[string]string{
|
files := map[string]string{
|
||||||
"kustomization.yaml": `apiVersion: kustomize.config.k8s.io/v1beta1
|
"kustomization.yaml": `generators:
|
||||||
generators:
|
- configMapGenerator
|
||||||
- plugin.yaml
|
|
||||||
- |
|
|
||||||
apiVersion: builtin
|
|
||||||
behavior: create
|
|
||||||
kind: ConfigMapGenerator
|
|
||||||
literals:
|
|
||||||
- APPLE=orange
|
|
||||||
metadata:
|
|
||||||
name: another-map
|
|
||||||
---
|
|
||||||
apiVersion: builtin
|
|
||||||
kind: SecretGenerator
|
|
||||||
literals:
|
|
||||||
- APPLE=b3Jhbmdl
|
|
||||||
metadata:
|
|
||||||
name: secret
|
|
||||||
options:
|
|
||||||
disableNameSuffixHash: true
|
|
||||||
kind: Kustomization
|
|
||||||
`,
|
`,
|
||||||
"plugin.yaml": `apiVersion: builtin
|
"configMapGenerator": `apiVersion: builtin
|
||||||
|
behavior: create
|
||||||
|
env: one.env
|
||||||
|
envs:
|
||||||
|
- two.env
|
||||||
|
- three.env
|
||||||
|
files:
|
||||||
|
- four.properties
|
||||||
|
- key=five.properties
|
||||||
kind: ConfigMapGenerator
|
kind: ConfigMapGenerator
|
||||||
metadata:
|
metadata:
|
||||||
name: map
|
name: custom-generator
|
||||||
|
options:
|
||||||
|
disableNameSuffix: true
|
||||||
`,
|
`,
|
||||||
|
"one.env": "key1=value1",
|
||||||
|
"two.env": "key2=value2",
|
||||||
|
"three.env": "key3=value3",
|
||||||
|
"four.properties": "key4=value4",
|
||||||
|
"five.properties": "key5=value5",
|
||||||
}
|
}
|
||||||
checkLocalizeInTargetSuccess(t, kustAndPlugins)
|
checkLocalizeInTargetSuccess(t, files)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizeGeneratorsSecret(t *testing.T) {
|
||||||
|
files := map[string]string{
|
||||||
|
"kustomization.yaml": `generators:
|
||||||
|
- secretGenerator
|
||||||
|
`,
|
||||||
|
"secretGenerator": `apiVersion: builtin
|
||||||
|
env: one.env
|
||||||
|
envs:
|
||||||
|
- two.env
|
||||||
|
- three.env
|
||||||
|
files:
|
||||||
|
- four.properties
|
||||||
|
- key=five.properties
|
||||||
|
kind: SecretGenerator
|
||||||
|
literals:
|
||||||
|
- key6=value6
|
||||||
|
metadata:
|
||||||
|
name: custom-generator
|
||||||
|
`,
|
||||||
|
"one.env": "key1=value1",
|
||||||
|
"two.env": "key2=value2",
|
||||||
|
"three.env": "key3=value3",
|
||||||
|
"four.properties": "key4=value4",
|
||||||
|
"five.properties": "key5=value5",
|
||||||
|
}
|
||||||
|
checkLocalizeInTargetSuccess(t, files)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLocalizeTransformersPatch(t *testing.T) {
|
func TestLocalizeTransformersPatch(t *testing.T) {
|
||||||
@@ -833,7 +857,23 @@ validators:
|
|||||||
checkLocalizeInTargetSuccess(t, kustAndPlugin)
|
checkLocalizeInTargetSuccess(t, kustAndPlugin)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLocalizeBuiltinPluginsNotResource(t *testing.T) {
|
func TestLocalizeBuiltinPlugins_SequenceScalarEquivalence(t *testing.T) {
|
||||||
|
kustomization := map[string]string{
|
||||||
|
"kustomization.yaml": `transformers:
|
||||||
|
- |
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: PatchTransformer
|
||||||
|
metadata:
|
||||||
|
name: path-should-be-scalar-but-accept-sequence
|
||||||
|
path:
|
||||||
|
- patchSM.yaml
|
||||||
|
`,
|
||||||
|
"patchSM.yaml": podConfiguration,
|
||||||
|
}
|
||||||
|
checkLocalizeInTargetSuccess(t, kustomization)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalizeBuiltinPlugins_NotResource(t *testing.T) {
|
||||||
type testCase struct {
|
type testCase struct {
|
||||||
name string
|
name string
|
||||||
files map[string]string
|
files map[string]string
|
||||||
@@ -895,24 +935,52 @@ when parsing as filepath received error: %s`, test.errPrefix, test.inlineErrMsg,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLocalizeBuiltinPluginsFileError(t *testing.T) {
|
func TestLocalizeBuiltinPlugins_Errors(t *testing.T) {
|
||||||
kustAndPatches := map[string]string{
|
for name, test := range map[string]struct {
|
||||||
"kustomization.yaml": `transformers:
|
files map[string]string
|
||||||
- patch.yaml
|
fieldSpecErr string
|
||||||
|
locErr string
|
||||||
|
}{
|
||||||
|
"file_dne": {
|
||||||
|
files: map[string]string{
|
||||||
|
"kustomization.yaml": `transformers:
|
||||||
|
- |
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: PatchTransformer
|
||||||
|
metadata:
|
||||||
|
name: file-does-not-exist
|
||||||
|
path: patchSM.yaml
|
||||||
`,
|
`,
|
||||||
"patch.yaml": `apiVersion: builtin
|
},
|
||||||
kind: PatchTransformer
|
fieldSpecErr: "considering field 'path' of object PatchTransformer.builtin.[noGrp]/file-does-not-exist.[noNs]",
|
||||||
metadata:
|
locErr: "invalid file reference: '/a/patchSM.yaml' doesn't exist",
|
||||||
name: my-patch
|
},
|
||||||
path: patchSM.yaml
|
"not_sequence_or_scalar": {
|
||||||
|
files: map[string]string{
|
||||||
|
"kustomization.yaml": `transformers:
|
||||||
|
- |
|
||||||
|
apiVersion: builtin
|
||||||
|
kind: PatchTransformer
|
||||||
|
metadata:
|
||||||
|
name: path-node-has-wrong-kind
|
||||||
|
path:
|
||||||
|
mappingNode: patchSM.yaml
|
||||||
`,
|
`,
|
||||||
|
"patchSM.yaml": podConfiguration,
|
||||||
|
},
|
||||||
|
fieldSpecErr: "considering field 'path' of object PatchTransformer.builtin.[noGrp]/path-node-has-wrong-kind.[noNs]",
|
||||||
|
locErr: "expected sequence or scalar node",
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
expected, actual := makeFileSystems(t, "/a", test.files)
|
||||||
|
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))
|
||||||
|
checkFSys(t, expected, actual)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
_, actual := makeFileSystems(t, "/a", kustAndPatches)
|
|
||||||
|
|
||||||
err := Run("/a", "", "/dst", actual)
|
|
||||||
require.EqualError(t, err, "unable to localize target \"/a\": "+
|
|
||||||
"considering field 'path' of object PatchTransformer.builtin.[noGrp]/my-patch.[noNs]: "+
|
|
||||||
"invalid file reference: '/a/patchSM.yaml' doesn't exist")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLocalizeDirInTarget(t *testing.T) {
|
func TestLocalizeDirInTarget(t *testing.T) {
|
||||||
|
|||||||
@@ -646,3 +646,33 @@ func TestHelmHomeEscapesScope(t *testing.T) {
|
|||||||
require.NoError(t, fsExpected.Mkdir(filepath.Join(dst, "home")))
|
require.NoError(t, fsExpected.Mkdir(filepath.Join(dst, "home")))
|
||||||
CheckFs(t, dst, fsExpected, fsActual)
|
CheckFs(t, dst, fsExpected, fsActual)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSymlinkedFileSource(t *testing.T) {
|
||||||
|
// target (and scope)
|
||||||
|
// - kustomization
|
||||||
|
// - file
|
||||||
|
// - link to file
|
||||||
|
fsExpected, fsActual, target := PrepareFs(t, nil, map[string]string{
|
||||||
|
"kustomization.yaml": `configMapGenerator:
|
||||||
|
- files:
|
||||||
|
- filename-used-as-key-in-configMap
|
||||||
|
`,
|
||||||
|
"different-key": "properties",
|
||||||
|
})
|
||||||
|
link(t, target, map[string]string{
|
||||||
|
"filename-used-as-key-in-configMap": "different-key",
|
||||||
|
})
|
||||||
|
|
||||||
|
dst := target.Join("dst")
|
||||||
|
err := localizer.Run(fsActual, target.String(), "", dst)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
SetupDir(t, fsExpected, dst, map[string]string{
|
||||||
|
"kustomization.yaml": `configMapGenerator:
|
||||||
|
- files:
|
||||||
|
- different-key
|
||||||
|
`,
|
||||||
|
"different-key": "properties",
|
||||||
|
})
|
||||||
|
CheckFs(t, dst, fsExpected, fsActual)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user