diff --git a/api/internal/builtins/HelmChartInflationGenerator.go b/api/internal/builtins/HelmChartInflationGenerator.go index 40437a2155..be69576363 100644 --- a/api/internal/builtins/HelmChartInflationGenerator.go +++ b/api/internal/builtins/HelmChartInflationGenerator.go @@ -101,6 +101,14 @@ func (p *HelmChartInflationGeneratorPlugin) validateArgs() (err error) { // the additional values filepaths must be relative to the kust root p.AdditionalValuesFiles[i] = filepath.Join(p.h.Loader().Root(), file) } + for key, file := range p.SetFile { + // use Load() to enforce root restrictions + if _, err := p.h.Loader().Load(file); err != nil { + return errors.WrapPrefixf(err, "could not load file '%s' specified in SetFile", file) + } + // the filepaths must be relative to the kust root + p.SetFile[key] = filepath.Join(p.h.Loader().Root(), file) + } if err = p.errIfIllegalValuesMerge(); err != nil { return err diff --git a/api/krusty/helmchartinflationgenerator_test.go b/api/krusty/helmchartinflationgenerator_test.go index daffa16a0a..52c446a2bd 100644 --- a/api/krusty/helmchartinflationgenerator_test.go +++ b/api/krusty/helmchartinflationgenerator_test.go @@ -436,6 +436,84 @@ metadata: `) } +func TestHelmChartInflationGeneratorSetFile(t *testing.T) { + th := kusttest_test.MakeEnhancedHarnessWithTmpRoot(t) + defer th.Reset() + if err := th.ErrIfNoHelm(); err != nil { + t.Skip("skipping: " + err.Error()) + } + + copyValuesFilesTestChartsIntoHarness(t, th) + + th.WriteF(filepath.Join(th.GetRoot(), "game.properties"), ` +enemy.types=aliens,monsters +player.maximum-lives=5 +`) + + th.WriteF(filepath.Join(th.GetRoot(), "user-interface.yaml"), ` +color: + good: purple + bad: yellow +allow: + textmode: true +`) + + th.WriteK(th.GetRoot(), ` +helmCharts: + - name: test-chart + releaseName: test-chart + setFile: + config.game: game.properties + config.ui: user-interface.yaml +`) + + m := th.Run(th.GetRoot(), th.MakeOptionsPluginsEnabled()) + asYaml, err := m.AsYaml() + require.NoError(t, err) + require.Equal(t, string(asYaml), `apiVersion: v1 +data: + game.properties: |2 + + enemy.types=aliens,monsters + player.maximum-lives=5 + user-interface.yaml: |2 + + color: + good: purple + bad: yellow + allow: + textmode: true +kind: ConfigMap +metadata: + name: game-demo +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + chart: test-1.0.0 + name: my-deploy + namespace: default +spec: + replicas: 1 + selector: + matchLabels: + app: test + template: + spec: + containers: + - image: test-image:v1.0.0 + imagePullPolicy: Always +--- +apiVersion: apps/v1 +kind: Pod +metadata: + annotations: + helm.sh/hook: test + name: test-chart +`) +} + func TestHelmChartInflationGeneratorApiVersions(t *testing.T) { th := kusttest_test.MakeEnhancedHarnessWithTmpRoot(t) defer th.Reset() diff --git a/api/krusty/testdata/helmcharts/test-chart/templates/configmap.yaml b/api/krusty/testdata/helmcharts/test-chart/templates/configmap.yaml new file mode 100644 index 0000000000..c2be4708ed --- /dev/null +++ b/api/krusty/testdata/helmcharts/test-chart/templates/configmap.yaml @@ -0,0 +1,11 @@ +--- +{{- if .Values.config }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: game-demo +data: + # file-like keys + game.properties: {{ .Values.config.game | toYaml | indent 2 }} + user-interface.yaml: {{ .Values.config.ui | toYaml | indent 2 }} +{{- end }} \ No newline at end of file diff --git a/api/types/helmchartargs.go b/api/types/helmchartargs.go index 15ea7178fb..7c948b4844 100644 --- a/api/types/helmchartargs.go +++ b/api/types/helmchartargs.go @@ -63,6 +63,11 @@ type HelmChart struct { // addition to either the default values file or the values specified in ValuesFile. AdditionalValuesFiles []string `json:"additionalValuesFiles,omitempty" yaml:"additionalValuesFiles,omitempty"` + // SetFile holds value mappings where the value is specified in a file. + // This allows setting values from respective files. The file's content + // will become the value's content. + SetFile map[string]string `json:"setFile,omitempty" yaml:"setFile,omitempty"` + // ValuesFile is a local file path to a values file to use _instead of_ // the default values that accompanied the chart. // The default values are in '{ChartHome}/{Name}/values.yaml'. @@ -168,6 +173,9 @@ func (h HelmChart) AsHelmArgs(absChartHome string) []string { for _, valuesFile := range h.AdditionalValuesFiles { args = append(args, "-f", valuesFile) } + for key, file := range h.SetFile { + args = append(args, "--set-file", key+"="+file) + } for _, apiVer := range h.ApiVersions { args = append(args, "--api-versions", apiVer) diff --git a/plugin/builtin/helmchartinflationgenerator/HelmChartInflationGenerator.go b/plugin/builtin/helmchartinflationgenerator/HelmChartInflationGenerator.go index 01adb29f5b..3f8d832365 100644 --- a/plugin/builtin/helmchartinflationgenerator/HelmChartInflationGenerator.go +++ b/plugin/builtin/helmchartinflationgenerator/HelmChartInflationGenerator.go @@ -107,6 +107,14 @@ func (p *plugin) validateArgs() (err error) { // the additional values filepaths must be relative to the kust root p.AdditionalValuesFiles[i] = filepath.Join(p.h.Loader().Root(), file) } + for key, file := range p.SetFile { + // use Load() to enforce root restrictions + if _, err := p.h.Loader().Load(file); err != nil { + return errors.WrapPrefixf(err, "could not load file '%s' specified in SetFile", file) + } + // the filepaths must be relative to the kust root + p.SetFile[key] = filepath.Join(p.h.Loader().Root(), file) + } if err = p.errIfIllegalValuesMerge(); err != nil { return err diff --git a/plugin/builtin/helmchartinflationgenerator/HelmChartInflationGenerator_test.go b/plugin/builtin/helmchartinflationgenerator/HelmChartInflationGenerator_test.go index d75b44d1dc..d4cfb0e9c0 100644 --- a/plugin/builtin/helmchartinflationgenerator/HelmChartInflationGenerator_test.go +++ b/plugin/builtin/helmchartinflationgenerator/HelmChartInflationGenerator_test.go @@ -430,6 +430,62 @@ valuesFile: myValues.yaml )) } +func TestHelmChartInflationGeneratorSetFile(t *testing.T) { + th := kusttest_test.MakeEnhancedHarnessWithTmpRoot(t). + PrepBuiltin("HelmChartInflationGenerator") + defer th.Reset() + if err := th.ErrIfNoHelm(); err != nil { + t.Skip("skipping: " + err.Error()) + } + + copyTestChartsIntoHarness(t, th) + + th.WriteF(filepath.Join(th.GetRoot(), "game.properties"), ` +enemy.types=aliens,monsters +player.maximum-lives=5 +`) + + th.WriteF(filepath.Join(th.GetRoot(), "user-interface.yaml"), ` +color: + good: purple + bad: yellow +allow: + textmode: true +`) + + rm := th.LoadAndRunGenerator(` +apiVersion: builtin +kind: HelmChartInflationGenerator +metadata: + name: test-chart +name: test-chart +releaseName: test-chart +chartHome: ./charts +setFile: + config.game: game.properties + config.ui: user-interface.yaml +`) + + th.AssertActualEqualsExpected(rm, ` +apiVersion: v1 +data: + game.properties: |2 + + enemy.types=aliens,monsters + player.maximum-lives=5 + user-interface.yaml: |2 + + color: + good: purple + bad: yellow + allow: + textmode: true +kind: ConfigMap +metadata: + name: bar +`) +} + func TestHelmChartInflationGeneratorWithInLineReplace(t *testing.T) { th := kusttest_test.MakeEnhancedHarnessWithTmpRoot(t). PrepBuiltin("HelmChartInflationGenerator") diff --git a/plugin/builtin/helmchartinflationgenerator/testdata/charts/test-chart/README.md b/plugin/builtin/helmchartinflationgenerator/testdata/charts/test-chart/README.md new file mode 100644 index 0000000000..3b1383634c --- /dev/null +++ b/plugin/builtin/helmchartinflationgenerator/testdata/charts/test-chart/README.md @@ -0,0 +1 @@ +This is a simple test chart. \ No newline at end of file diff --git a/plugin/builtin/helmchartinflationgenerator/testdata/charts/test-chart/templates/configmap.yaml b/plugin/builtin/helmchartinflationgenerator/testdata/charts/test-chart/templates/configmap.yaml index b7c8ef451a..733229214d 100644 --- a/plugin/builtin/helmchartinflationgenerator/testdata/charts/test-chart/templates/configmap.yaml +++ b/plugin/builtin/helmchartinflationgenerator/testdata/charts/test-chart/templates/configmap.yaml @@ -2,3 +2,9 @@ apiVersion: v1 kind: ConfigMap metadata: name: {{ .Values.foo }} +{{- if .Values.config }} +data: + # file-like keys + game.properties: {{ .Values.config.game | toYaml | indent 2 }} + user-interface.yaml: {{ .Values.config.ui | toYaml | indent 2 }} +{{- end }}