v1: Fix --state-values-set to override values of environments colocated with releases (#705)
This commit is contained in:
parent
522392c08c
commit
95c56d87fc
|
|
@ -117,8 +117,8 @@ func setGlobalOptionsForRootCmd(fs *pflag.FlagSet, globalOptions *config.GlobalO
|
||||||
fs.StringVarP(&globalOptions.HelmBinary, "helm-binary", "b", app.DefaultHelmBinary, "Path to the helm binary")
|
fs.StringVarP(&globalOptions.HelmBinary, "helm-binary", "b", app.DefaultHelmBinary, "Path to the helm binary")
|
||||||
fs.StringVarP(&globalOptions.File, "file", "f", "", "load config from file or directory. defaults to `helmfile.yaml` or `helmfile.yaml.gotmpl` or `helmfile.d`(means `helmfile.d/*.yaml` or `helmfile.d/*.yaml.gotmpl`) in this preference. Specify - to load the config from the standard input.")
|
fs.StringVarP(&globalOptions.File, "file", "f", "", "load config from file or directory. defaults to `helmfile.yaml` or `helmfile.yaml.gotmpl` or `helmfile.d`(means `helmfile.d/*.yaml` or `helmfile.d/*.yaml.gotmpl`) in this preference. Specify - to load the config from the standard input.")
|
||||||
fs.StringVarP(&globalOptions.Environment, "environment", "e", "", `specify the environment name. defaults to "default"`)
|
fs.StringVarP(&globalOptions.Environment, "environment", "e", "", `specify the environment name. defaults to "default"`)
|
||||||
fs.StringArrayVar(&globalOptions.StateValuesSet, "state-values-set", nil, "set state values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
|
fs.StringArrayVar(&globalOptions.StateValuesSet, "state-values-set", nil, "set state values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). Used to override .Values within the helmfile template (not values template).")
|
||||||
fs.StringArrayVar(&globalOptions.StateValuesFile, "state-values-file", nil, "specify state values in a YAML file")
|
fs.StringArrayVar(&globalOptions.StateValuesFile, "state-values-file", nil, "specify state values in a YAML file. Used to override .Values within the helmfile template (not values template).")
|
||||||
fs.BoolVarP(&globalOptions.Quiet, "quiet", "q", false, "Silence output. Equivalent to log-level warn")
|
fs.BoolVarP(&globalOptions.Quiet, "quiet", "q", false, "Silence output. Equivalent to log-level warn")
|
||||||
fs.StringVar(&globalOptions.KubeContext, "kube-context", "", "Set kubectl context. Uses current context by default")
|
fs.StringVar(&globalOptions.KubeContext, "kube-context", "", "Set kubectl context. Uses current context by default")
|
||||||
fs.BoolVar(&globalOptions.Debug, "debug", false, "Enable verbose output for Helm and set log-level to debug, this disables --quiet/-q effect")
|
fs.BoolVar(&globalOptions.Debug, "debug", false, "Enable verbose output for Helm and set log-level to debug, this disables --quiet/-q effect")
|
||||||
|
|
|
||||||
|
|
@ -553,8 +553,8 @@ Flags:
|
||||||
A release must match all labels in a group in order to be used. Multiple groups can be specified at once.
|
A release must match all labels in a group in order to be used. Multiple groups can be specified at once.
|
||||||
"--selector tier=frontend,tier!=proxy --selector tier=backend" will match all frontend, non-proxy releases AND all backend releases.
|
"--selector tier=frontend,tier!=proxy --selector tier=backend" will match all frontend, non-proxy releases AND all backend releases.
|
||||||
The name of a release can be used as a label: "--selector name=myrelease"
|
The name of a release can be used as a label: "--selector name=myrelease"
|
||||||
--state-values-file stringArray specify state values in a YAML file
|
--state-values-file stringArray specify state values in a YAML file. Used to override .Values within the helmfile template (not values template).
|
||||||
--state-values-set stringArray set state values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)
|
--state-values-set stringArray set state values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2). Used to override .Values within the helmfile template (not values template).
|
||||||
-v, --version version for helmfile
|
-v, --version version for helmfile
|
||||||
|
|
||||||
Use "helmfile [command] --help" for more information about a command.
|
Use "helmfile [command] --help" for more information about a command.
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ func (ld *desiredStateLoader) Load(f string, opts LoadOpts) (*state.HelmState, e
|
||||||
return st, nil
|
return st, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ld *desiredStateLoader) loadFile(inheritedEnv *environment.Environment, baseDir, file string, evaluateBases bool) (*state.HelmState, error) {
|
func (ld *desiredStateLoader) loadFile(inheritedEnv, overrodeEnv *environment.Environment, baseDir, file string, evaluateBases bool) (*state.HelmState, error) {
|
||||||
path, err := ld.remote.Locate(file)
|
path, err := ld.remote.Locate(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("locate: %v", err)
|
return nil, fmt.Errorf("locate: %v", err)
|
||||||
|
|
@ -109,7 +109,7 @@ func (ld *desiredStateLoader) loadFile(inheritedEnv *environment.Environment, ba
|
||||||
ld.logger.Debugf("fetched remote \"%s\" to local cache \"%s\" and loading the latter...", file, path)
|
ld.logger.Debugf("fetched remote \"%s\" to local cache \"%s\" and loading the latter...", file, path)
|
||||||
}
|
}
|
||||||
file = path
|
file = path
|
||||||
return ld.loadFileWithOverrides(inheritedEnv, nil, baseDir, file, evaluateBases)
|
return ld.loadFileWithOverrides(inheritedEnv, overrodeEnv, baseDir, file, evaluateBases)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ld *desiredStateLoader) loadFileWithOverrides(inheritedEnv, overrodeEnv *environment.Environment, baseDir, file string, evaluateBases bool) (*state.HelmState, error) {
|
func (ld *desiredStateLoader) loadFileWithOverrides(inheritedEnv, overrodeEnv *environment.Environment, baseDir, file string, evaluateBases bool) (*state.HelmState, error) {
|
||||||
|
|
@ -157,16 +157,24 @@ func (a *desiredStateLoader) underlying() *state.StateCreator {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *desiredStateLoader) rawLoad(yaml []byte, baseDir, file string, evaluateBases bool, env, overrodeEnv *environment.Environment) (*state.HelmState, error) {
|
func (a *desiredStateLoader) rawLoad(yaml []byte, baseDir, file string, evaluateBases bool, env, overrodeEnv *environment.Environment) (*state.HelmState, error) {
|
||||||
|
var st *state.HelmState
|
||||||
|
var err error
|
||||||
|
if runtime.V1Mode {
|
||||||
|
st, err = a.underlying().ParseAndLoad(yaml, baseDir, file, a.env, evaluateBases, env, overrodeEnv)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
merged, err := env.Merge(overrodeEnv)
|
merged, err := env.Merge(overrodeEnv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
st, err := a.underlying().ParseAndLoad(yaml, baseDir, file, a.env, evaluateBases, merged)
|
st, err = a.underlying().ParseAndLoad(yaml, baseDir, file, a.env, evaluateBases, merged, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
helmfiles, err := st.ExpandedHelmfiles()
|
helmfiles, err := st.ExpandedHelmfiles()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,12 @@ func prependLineNumbers(text string) string {
|
||||||
return buf.String()
|
return buf.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *desiredStateLoader) renderPrestate(firstPassEnv *environment.Environment, baseDir, filename string, content []byte) (*environment.Environment, *state.HelmState) {
|
func (r *desiredStateLoader) renderPrestate(firstPassEnv, overrode *environment.Environment, baseDir, filename string, content []byte) (*environment.Environment, *state.HelmState) {
|
||||||
tmplData := state.NewEnvironmentTemplateData(*firstPassEnv, r.namespace, map[string]interface{}{})
|
initEnv, err := firstPassEnv.Merge(overrode)
|
||||||
|
if err != nil {
|
||||||
|
return firstPassEnv, nil
|
||||||
|
}
|
||||||
|
tmplData := state.NewEnvironmentTemplateData(*initEnv, r.namespace, map[string]interface{}{})
|
||||||
firstPassRenderer := tmpl.NewFirstPassRenderer(baseDir, tmplData)
|
firstPassRenderer := tmpl.NewFirstPassRenderer(baseDir, tmplData)
|
||||||
|
|
||||||
// parse as much as we can, tolerate errors, this is a preparse
|
// parse as much as we can, tolerate errors, this is a preparse
|
||||||
|
|
@ -49,7 +53,7 @@ func (r *desiredStateLoader) renderPrestate(firstPassEnv *environment.Environmen
|
||||||
c := r.underlying()
|
c := r.underlying()
|
||||||
c.Strict = false
|
c.Strict = false
|
||||||
// create preliminary state, as we may have an environment. Tolerate errors.
|
// create preliminary state, as we may have an environment. Tolerate errors.
|
||||||
prestate, err := c.ParseAndLoad([]byte(sanitized), baseDir, filename, r.env, false, firstPassEnv)
|
prestate, err := c.ParseAndLoad([]byte(sanitized), baseDir, filename, r.env, false, firstPassEnv, overrode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if _, ok := err.(*state.StateLoadError); ok {
|
if _, ok := err.(*state.StateLoadError); ok {
|
||||||
r.logger.Debugf("could not deduce `environment:` block, configuring only .Environment.Name. error: %v", err)
|
r.logger.Debugf("could not deduce `environment:` block, configuring only .Environment.Name. error: %v", err)
|
||||||
|
|
@ -85,7 +89,7 @@ func (r *desiredStateLoader) twoPassRenderTemplateToYaml(inherited, overrode *en
|
||||||
}
|
}
|
||||||
r.logger.Debugf("%srendering starting for \"%s\": inherited=%v, overrode=%v", phase, filename, inherited, overrode)
|
r.logger.Debugf("%srendering starting for \"%s\": inherited=%v, overrode=%v", phase, filename, inherited, overrode)
|
||||||
|
|
||||||
initEnv, err := inherited.Merge(overrode)
|
initEnv, err := inherited.Merge(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -99,7 +103,10 @@ func (r *desiredStateLoader) twoPassRenderTemplateToYaml(inherited, overrode *en
|
||||||
if runtime.V1Mode {
|
if runtime.V1Mode {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
finalEnv = initEnv
|
finalEnv, err = initEnv.Merge(overrode)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
vals, err = finalEnv.GetMergedValues()
|
vals, err = finalEnv.GetMergedValues()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -107,8 +114,11 @@ func (r *desiredStateLoader) twoPassRenderTemplateToYaml(inherited, overrode *en
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
r.logger.Debugf("first-pass uses: %v", initEnv)
|
r.logger.Debugf("first-pass uses: %v", initEnv)
|
||||||
|
firstPassEnv, err := initEnv.Merge(nil)
|
||||||
renderedEnv, prestate := r.renderPrestate(initEnv, baseDir, filename, content)
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
renderedEnv, prestate := r.renderPrestate(firstPassEnv, overrode, baseDir, filename, content)
|
||||||
|
|
||||||
r.logger.Debugf("first-pass produced: %v", renderedEnv)
|
r.logger.Debugf("first-pass produced: %v", renderedEnv)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ type StateCreator struct {
|
||||||
|
|
||||||
Strict bool
|
Strict bool
|
||||||
|
|
||||||
LoadFile func(inheritedEnv *environment.Environment, baseDir, file string, evaluateBases bool) (*HelmState, error)
|
LoadFile func(inheritedEnv, overrodeEnv *environment.Environment, baseDir, file string, evaluateBases bool) (*HelmState, error)
|
||||||
|
|
||||||
getHelm func(*HelmState) helmexec.Interface
|
getHelm func(*HelmState) helmexec.Interface
|
||||||
|
|
||||||
|
|
@ -138,10 +138,10 @@ func (c *StateCreator) Parse(content []byte, baseDir, file string) (*HelmState,
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadEnvValues loads environment values files relative to the `baseDir`
|
// LoadEnvValues loads environment values files relative to the `baseDir`
|
||||||
func (c *StateCreator) LoadEnvValues(target *HelmState, env string, ctxEnv *environment.Environment, failOnMissingEnv bool) (*HelmState, error) {
|
func (c *StateCreator) LoadEnvValues(target *HelmState, env string, ctxEnv, overrode *environment.Environment, failOnMissingEnv bool) (*HelmState, error) {
|
||||||
state := *target
|
state := *target
|
||||||
|
|
||||||
e, err := c.loadEnvValues(&state, env, failOnMissingEnv, ctxEnv)
|
e, err := c.loadEnvValues(&state, env, failOnMissingEnv, ctxEnv, overrode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, &StateLoadError{fmt.Sprintf("failed to read %s", state.FilePath), err}
|
return nil, &StateLoadError{fmt.Sprintf("failed to read %s", state.FilePath), err}
|
||||||
}
|
}
|
||||||
|
|
@ -162,7 +162,7 @@ func (c *StateCreator) LoadEnvValues(target *HelmState, env string, ctxEnv *envi
|
||||||
|
|
||||||
// Parses YAML into HelmState, while loading environment values files relative to the `baseDir`
|
// Parses YAML into HelmState, while loading environment values files relative to the `baseDir`
|
||||||
// evaluateBases=true means that this is NOT a base helmfile
|
// evaluateBases=true means that this is NOT a base helmfile
|
||||||
func (c *StateCreator) ParseAndLoad(content []byte, baseDir, file string, envName string, evaluateBases bool, envValues *environment.Environment) (*HelmState, error) {
|
func (c *StateCreator) ParseAndLoad(content []byte, baseDir, file string, envName string, evaluateBases bool, envValues, overrode *environment.Environment) (*HelmState, error) {
|
||||||
state, err := c.Parse(content, baseDir, file)
|
state, err := c.Parse(content, baseDir, file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -173,13 +173,13 @@ func (c *StateCreator) ParseAndLoad(content []byte, baseDir, file string, envNam
|
||||||
return nil, errors.New("nested `base` helmfile is unsupported. please submit a feature request if you need this!")
|
return nil, errors.New("nested `base` helmfile is unsupported. please submit a feature request if you need this!")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
state, err = c.loadBases(envValues, state, baseDir)
|
state, err = c.loadBases(envValues, overrode, state, baseDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state, err = c.LoadEnvValues(state, envName, envValues, evaluateBases)
|
state, err = c.LoadEnvValues(state, envName, envValues, overrode, evaluateBases)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -195,10 +195,10 @@ func (c *StateCreator) ParseAndLoad(content []byte, baseDir, file string, envNam
|
||||||
return state, nil
|
return state, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *StateCreator) loadBases(envValues *environment.Environment, st *HelmState, baseDir string) (*HelmState, error) {
|
func (c *StateCreator) loadBases(envValues, overrodeEnv *environment.Environment, st *HelmState, baseDir string) (*HelmState, error) {
|
||||||
layers := []*HelmState{}
|
layers := []*HelmState{}
|
||||||
for _, b := range st.Bases {
|
for _, b := range st.Bases {
|
||||||
base, err := c.LoadFile(envValues, baseDir, b, false)
|
base, err := c.LoadFile(envValues, overrodeEnv, baseDir, b, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -216,7 +216,7 @@ func (c *StateCreator) loadBases(envValues *environment.Environment, st *HelmSta
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint: unparam
|
// nolint: unparam
|
||||||
func (c *StateCreator) loadEnvValues(st *HelmState, name string, failOnMissingEnv bool, ctxEnv *environment.Environment) (*environment.Environment, error) {
|
func (c *StateCreator) loadEnvValues(st *HelmState, name string, failOnMissingEnv bool, ctxEnv, overrode *environment.Environment) (*environment.Environment, error) {
|
||||||
envVals := map[string]interface{}{}
|
envVals := map[string]interface{}{}
|
||||||
envSpec, ok := st.Environments[name]
|
envSpec, ok := st.Environments[name]
|
||||||
if ok {
|
if ok {
|
||||||
|
|
@ -250,13 +250,23 @@ func (c *StateCreator) loadEnvValues(st *HelmState, name string, failOnMissingEn
|
||||||
newEnv := &environment.Environment{Name: name, Values: envVals}
|
newEnv := &environment.Environment{Name: name, Values: envVals}
|
||||||
|
|
||||||
if ctxEnv != nil {
|
if ctxEnv != nil {
|
||||||
intEnv := *ctxEnv
|
intCtxEnv := *ctxEnv
|
||||||
|
|
||||||
if err := mergo.Merge(&intEnv, newEnv, mergo.WithOverride, mergo.WithOverwriteWithEmptyValue); err != nil {
|
if err := mergo.Merge(&intCtxEnv, newEnv, mergo.WithOverride, mergo.WithOverwriteWithEmptyValue); err != nil {
|
||||||
return nil, fmt.Errorf("error while merging environment values for \"%s\": %v", name, err)
|
return nil, fmt.Errorf("error while merging environment values for \"%s\": %v", name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
newEnv = &intEnv
|
newEnv = &intCtxEnv
|
||||||
|
}
|
||||||
|
|
||||||
|
if overrode != nil {
|
||||||
|
intOverrodeEnv := *newEnv
|
||||||
|
|
||||||
|
if err := mergo.Merge(&intOverrodeEnv, overrode, mergo.WithOverride, mergo.WithOverwriteWithEmptyValue); err != nil {
|
||||||
|
return nil, fmt.Errorf("error while merging environment overrode values for \"%s\": %v", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
newEnv = &intOverrodeEnv
|
||||||
}
|
}
|
||||||
|
|
||||||
return newEnv, nil
|
return newEnv, nil
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ func createFromYaml(content []byte, file string, env string, logger *zap.Sugared
|
||||||
fs: filesystem.DefaultFileSystem(),
|
fs: filesystem.DefaultFileSystem(),
|
||||||
Strict: true,
|
Strict: true,
|
||||||
}
|
}
|
||||||
return c.ParseAndLoad(content, filepath.Dir(file), file, env, true, nil)
|
return c.ParseAndLoad(content, filepath.Dir(file), file, env, true, nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReadFromYaml(t *testing.T) {
|
func TestReadFromYaml(t *testing.T) {
|
||||||
|
|
@ -84,7 +84,7 @@ func (testEnv stateTestEnv) MustLoadStateWithEnableLiveOutput(t *testing.T, file
|
||||||
|
|
||||||
r := remote.NewRemote(logger, testFs.Cwd, testFs.ToFileSystem())
|
r := remote.NewRemote(logger, testFs.Cwd, testFs.ToFileSystem())
|
||||||
state, err := NewCreator(logger, testFs.ToFileSystem(), nil, nil, "", r, enableLiveOutput, "").
|
state, err := NewCreator(logger, testFs.ToFileSystem(), nil, nil, "", r, enableLiveOutput, "").
|
||||||
ParseAndLoad([]byte(yamlContent), filepath.Dir(file), file, envName, true, nil)
|
ParseAndLoad([]byte(yamlContent), filepath.Dir(file), file, envName, true, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -154,7 +154,7 @@ releaseNamespace: mynamespace
|
||||||
Name: "production",
|
Name: "production",
|
||||||
}
|
}
|
||||||
state, err := NewCreator(logger, testFs.ToFileSystem(), nil, nil, "", r, false, "").
|
state, err := NewCreator(logger, testFs.ToFileSystem(), nil, nil, "", r, false, "").
|
||||||
ParseAndLoad(yamlContent, filepath.Dir(yamlFile), yamlFile, "production", true, &env)
|
ParseAndLoad(yamlContent, filepath.Dir(yamlFile), yamlFile, "production", true, &env, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -241,7 +241,7 @@ overrideNamespace: myns
|
||||||
|
|
||||||
r := remote.NewRemote(logger, testFs.Cwd, testFs.ToFileSystem())
|
r := remote.NewRemote(logger, testFs.Cwd, testFs.ToFileSystem())
|
||||||
state, err := NewCreator(logger, testFs.ToFileSystem(), nil, nil, "", r, false, "").
|
state, err := NewCreator(logger, testFs.ToFileSystem(), nil, nil, "", r, false, "").
|
||||||
ParseAndLoad(yamlContent, filepath.Dir(yamlFile), yamlFile, "production", true, nil)
|
ParseAndLoad(yamlContent, filepath.Dir(yamlFile), yamlFile, "production", true, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
cli-overwrite-environment-values_input_dir="${cases_dir}/cli-overwrite-environment-values/input"
|
||||||
|
cli-overwrite-environment-values_output_dir="${cases_dir}/cli-overwrite-environment-values/output"
|
||||||
|
|
||||||
|
cli_overwrite_environment_values_tmp=$(mktemp -d)
|
||||||
|
cli_overwrite_environment_values_reverse=${cli_overwrite_environment_values_tmp}/cli.environment.override.build.yaml
|
||||||
|
|
||||||
|
case_title="cli overwrite environment values"
|
||||||
|
|
||||||
|
if [[ ${HELMFILE_V1MODE} = true ]]; then
|
||||||
|
test_start "$case_title for v1"
|
||||||
|
info "Comparing ${case_title} for v1 output ${cli_overwrite_environment_values_reverse} with ${cli-overwrite-environment-values_output_dir}/overwritten.yaml"
|
||||||
|
for i in $(seq 10); do
|
||||||
|
info "Comparing build/cli-overwrite-environment-values #$i"
|
||||||
|
${helmfile} -f ${cli-overwrite-environment-values_input_dir}/input_v1.yaml.gotmpl template --state-values-set ns=test3 > ${cli_overwrite_environment_values_reverse} || fail "\"helmfile template\" shouldn't fail"
|
||||||
|
diff -u ${cli-overwrite-environment-values_output_dir}/output_v1.yaml ${cli_overwrite_environment_values_reverse} || fail "\"helmfile template\" should be consistent"
|
||||||
|
echo code=$?
|
||||||
|
done
|
||||||
|
test_pass "cli overwrite environment values for v1"
|
||||||
|
else
|
||||||
|
test_start "${case_title}"
|
||||||
|
info "Comparing ${case_title} output ${cli_overwrite_environment_values_reverse} with ${cli-overwrite-environment-values_output_dir}/overwritten.yaml"
|
||||||
|
for i in $(seq 10); do
|
||||||
|
info "Comparing build/cli-overwrite-environment-values #$i"
|
||||||
|
${helmfile} -f ${cli-overwrite-environment-values_input_dir}/input_v1.yaml.gotmpl template --state-values-set ns=test3 > ${cli_overwrite_environment_values_reverse} || fail "\"helmfile template\" shouldn't fail"
|
||||||
|
diff -u ${cli-overwrite-environment-values_output_dir}/output_v1.yaml ${cli_overwrite_environment_values_reverse} || fail "\"helmfile template\" should be consistent"
|
||||||
|
echo code=$?
|
||||||
|
done
|
||||||
|
test_pass "${case_title}"
|
||||||
|
fi
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
ns: test1
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
chartifyTempDir: environment_overwrite_values
|
||||||
|
helmfileArgs:
|
||||||
|
- template
|
||||||
|
- --state-values-set
|
||||||
|
- ns=test3
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
environments:
|
||||||
|
default:
|
||||||
|
values:
|
||||||
|
- base.yaml
|
||||||
|
- override.yaml
|
||||||
|
|
||||||
|
repositories:
|
||||||
|
- name: bitnami
|
||||||
|
url: https://charts.bitnami.com/bitnami
|
||||||
|
|
||||||
|
releases:
|
||||||
|
- name: test
|
||||||
|
chart: bitnami/nginx
|
||||||
|
namespace: {{ .Values.ns }}
|
||||||
|
version: 13.2.27
|
||||||
|
values:
|
||||||
|
- values.yaml.gotmpl
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
environments:
|
||||||
|
default:
|
||||||
|
values:
|
||||||
|
- base.yaml
|
||||||
|
- override.yaml
|
||||||
|
---
|
||||||
|
repositories:
|
||||||
|
- name: bitnami
|
||||||
|
url: https://charts.bitnami.com/bitnami
|
||||||
|
|
||||||
|
releases:
|
||||||
|
- name: test
|
||||||
|
chart: bitnami/nginx
|
||||||
|
namespace: {{ .Values.ns }}
|
||||||
|
version: 13.2.27
|
||||||
|
values:
|
||||||
|
- values.yaml.gotmpl
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
ns: test2
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
image:
|
||||||
|
tag: {{ .Values.ns }}
|
||||||
|
|
@ -0,0 +1,116 @@
|
||||||
|
Warning: environments and releases cannot be defined within the same YAML part. Use --- to extract the environments into a dedicated part
|
||||||
|
Warning: environments and releases cannot be defined within the same YAML part. Use --- to extract the environments into a dedicated part
|
||||||
|
Adding repo bitnami https://charts.bitnami.com/bitnami
|
||||||
|
"bitnami" has been added to your repositories
|
||||||
|
|
||||||
|
Templating release=test, chart=bitnami/nginx
|
||||||
|
---
|
||||||
|
# Source: nginx/templates/svc.yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: test-nginx
|
||||||
|
namespace: "test3"
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: nginx
|
||||||
|
helm.sh/chart: nginx-13.2.27
|
||||||
|
app.kubernetes.io/instance: test
|
||||||
|
app.kubernetes.io/managed-by: Helm
|
||||||
|
annotations:
|
||||||
|
spec:
|
||||||
|
type: LoadBalancer
|
||||||
|
sessionAffinity: None
|
||||||
|
externalTrafficPolicy: "Cluster"
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 80
|
||||||
|
targetPort: http
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/name: nginx
|
||||||
|
app.kubernetes.io/instance: test
|
||||||
|
---
|
||||||
|
# Source: nginx/templates/deployment.yaml
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: test-nginx
|
||||||
|
namespace: "test3"
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: nginx
|
||||||
|
helm.sh/chart: nginx-13.2.27
|
||||||
|
app.kubernetes.io/instance: test
|
||||||
|
app.kubernetes.io/managed-by: Helm
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
strategy:
|
||||||
|
rollingUpdate: {}
|
||||||
|
type: RollingUpdate
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: nginx
|
||||||
|
app.kubernetes.io/instance: test
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: nginx
|
||||||
|
helm.sh/chart: nginx-13.2.27
|
||||||
|
app.kubernetes.io/instance: test
|
||||||
|
app.kubernetes.io/managed-by: Helm
|
||||||
|
annotations:
|
||||||
|
spec:
|
||||||
|
|
||||||
|
automountServiceAccountToken: false
|
||||||
|
shareProcessNamespace: false
|
||||||
|
serviceAccountName: default
|
||||||
|
affinity:
|
||||||
|
podAffinity:
|
||||||
|
|
||||||
|
podAntiAffinity:
|
||||||
|
preferredDuringSchedulingIgnoredDuringExecution:
|
||||||
|
- podAffinityTerm:
|
||||||
|
labelSelector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: nginx
|
||||||
|
app.kubernetes.io/instance: test
|
||||||
|
topologyKey: kubernetes.io/hostname
|
||||||
|
weight: 1
|
||||||
|
nodeAffinity:
|
||||||
|
|
||||||
|
hostNetwork: false
|
||||||
|
hostIPC: false
|
||||||
|
initContainers:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: docker.io/bitnami/nginx:test3
|
||||||
|
imagePullPolicy: "IfNotPresent"
|
||||||
|
env:
|
||||||
|
- name: BITNAMI_DEBUG
|
||||||
|
value: "false"
|
||||||
|
- name: NGINX_HTTP_PORT_NUMBER
|
||||||
|
value: "8080"
|
||||||
|
envFrom:
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 8080
|
||||||
|
livenessProbe:
|
||||||
|
failureThreshold: 6
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
periodSeconds: 10
|
||||||
|
successThreshold: 1
|
||||||
|
timeoutSeconds: 5
|
||||||
|
tcpSocket:
|
||||||
|
port: http
|
||||||
|
readinessProbe:
|
||||||
|
failureThreshold: 3
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
periodSeconds: 5
|
||||||
|
successThreshold: 1
|
||||||
|
timeoutSeconds: 3
|
||||||
|
tcpSocket:
|
||||||
|
port: http
|
||||||
|
resources:
|
||||||
|
limits: {}
|
||||||
|
requests: {}
|
||||||
|
volumeMounts:
|
||||||
|
volumes:
|
||||||
|
|
||||||
|
|
@ -0,0 +1,110 @@
|
||||||
|
---
|
||||||
|
# Source: nginx/templates/svc.yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: test-nginx
|
||||||
|
namespace: "test3"
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: nginx
|
||||||
|
helm.sh/chart: nginx-13.2.27
|
||||||
|
app.kubernetes.io/instance: test
|
||||||
|
app.kubernetes.io/managed-by: Helm
|
||||||
|
annotations:
|
||||||
|
spec:
|
||||||
|
type: LoadBalancer
|
||||||
|
sessionAffinity: None
|
||||||
|
externalTrafficPolicy: "Cluster"
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 80
|
||||||
|
targetPort: http
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/name: nginx
|
||||||
|
app.kubernetes.io/instance: test
|
||||||
|
---
|
||||||
|
# Source: nginx/templates/deployment.yaml
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: test-nginx
|
||||||
|
namespace: "test3"
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: nginx
|
||||||
|
helm.sh/chart: nginx-13.2.27
|
||||||
|
app.kubernetes.io/instance: test
|
||||||
|
app.kubernetes.io/managed-by: Helm
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
strategy:
|
||||||
|
rollingUpdate: {}
|
||||||
|
type: RollingUpdate
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: nginx
|
||||||
|
app.kubernetes.io/instance: test
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: nginx
|
||||||
|
helm.sh/chart: nginx-13.2.27
|
||||||
|
app.kubernetes.io/instance: test
|
||||||
|
app.kubernetes.io/managed-by: Helm
|
||||||
|
annotations:
|
||||||
|
spec:
|
||||||
|
|
||||||
|
automountServiceAccountToken: false
|
||||||
|
shareProcessNamespace: false
|
||||||
|
serviceAccountName: default
|
||||||
|
affinity:
|
||||||
|
podAffinity:
|
||||||
|
|
||||||
|
podAntiAffinity:
|
||||||
|
preferredDuringSchedulingIgnoredDuringExecution:
|
||||||
|
- podAffinityTerm:
|
||||||
|
labelSelector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: nginx
|
||||||
|
app.kubernetes.io/instance: test
|
||||||
|
topologyKey: kubernetes.io/hostname
|
||||||
|
weight: 1
|
||||||
|
nodeAffinity:
|
||||||
|
|
||||||
|
hostNetwork: false
|
||||||
|
hostIPC: false
|
||||||
|
initContainers:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: docker.io/bitnami/nginx:test3
|
||||||
|
imagePullPolicy: "IfNotPresent"
|
||||||
|
env:
|
||||||
|
- name: BITNAMI_DEBUG
|
||||||
|
value: "false"
|
||||||
|
- name: NGINX_HTTP_PORT_NUMBER
|
||||||
|
value: "8080"
|
||||||
|
envFrom:
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 8080
|
||||||
|
livenessProbe:
|
||||||
|
failureThreshold: 6
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
periodSeconds: 10
|
||||||
|
successThreshold: 1
|
||||||
|
timeoutSeconds: 5
|
||||||
|
tcpSocket:
|
||||||
|
port: http
|
||||||
|
readinessProbe:
|
||||||
|
failureThreshold: 3
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
periodSeconds: 5
|
||||||
|
successThreshold: 1
|
||||||
|
timeoutSeconds: 3
|
||||||
|
tcpSocket:
|
||||||
|
port: http
|
||||||
|
resources:
|
||||||
|
limits: {}
|
||||||
|
requests: {}
|
||||||
|
volumeMounts:
|
||||||
|
volumes:
|
||||||
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
https://github.com/helmfile/helmfile/issues/700
|
||||||
Loading…
Reference in New Issue