From ca6dd7a60f3d3b5e1c70cd8023ea7f493214dc2d Mon Sep 17 00:00:00 2001 From: pjotre86 Date: Thu, 4 Nov 2021 02:04:01 +0100 Subject: [PATCH] Make .Environment values available in .gotmpl files. (#2000) Currently it's not possible to use `.Environment` values in `*.gomtpl` files. The documentation states the opposite: https://github.com/roboll/helmfile#environment (2nd paragraph). The problem is already described in #1090. This PR fixes this bug. Fixes #1090 Co-authored-by: Peter Aichinger --- pkg/app/desired_state_file_loader.go | 2 +- pkg/state/create.go | 8 ++++---- pkg/state/create_test.go | 8 +++++++- pkg/state/envvals_loader.go | 13 ++++++++++--- pkg/state/envvals_loader_test.go | 15 ++++++++------- 5 files changed, 30 insertions(+), 16 deletions(-) diff --git a/pkg/app/desired_state_file_loader.go b/pkg/app/desired_state_file_loader.go index 9e5bc485..4cbffd00 100644 --- a/pkg/app/desired_state_file_loader.go +++ b/pkg/app/desired_state_file_loader.go @@ -52,7 +52,7 @@ func (ld *desiredStateLoader) Load(f string, opts LoadOpts) (*state.HelmState, e storage := state.NewStorage(opts.CalleePath, ld.logger, ld.glob) envld := state.NewEnvironmentValuesLoader(storage, ld.readFile, ld.logger, ld.remote) handler := state.MissingFileHandlerError - vals, err := envld.LoadEnvironmentValues(&handler, args) + vals, err := envld.LoadEnvironmentValues(&handler, args, &environment.EmptyEnvironment) if err != nil { return nil, err } diff --git a/pkg/state/create.go b/pkg/state/create.go index a1830fae..9ad20be1 100644 --- a/pkg/state/create.go +++ b/pkg/state/create.go @@ -153,7 +153,7 @@ func (c *StateCreator) LoadEnvValues(target *HelmState, env string, ctxEnv *envi return nil, &StateLoadError{fmt.Sprintf("failed to read %s", state.FilePath), err} } - newDefaults, err := state.loadValuesEntries(nil, state.DefaultValues, c.remote) + newDefaults, err := state.loadValuesEntries(nil, state.DefaultValues, c.remote, ctxEnv) if err != nil { return nil, err } @@ -227,7 +227,7 @@ func (c *StateCreator) loadEnvValues(st *HelmState, name string, failOnMissingEn envSpec, ok := st.Environments[name] if ok { var err error - envVals, err = st.loadValuesEntries(envSpec.MissingFileHandler, envSpec.Values, c.remote) + envVals, err = st.loadValuesEntries(envSpec.MissingFileHandler, envSpec.Values, c.remote, ctxEnv) if err != nil { return nil, err } @@ -363,13 +363,13 @@ func (c *StateCreator) scatterGatherEnvSecretFiles(st *HelmState, envSecretFiles return nil } -func (st *HelmState) loadValuesEntries(missingFileHandler *string, entries []interface{}, remote *remote.Remote) (map[string]interface{}, error) { +func (st *HelmState) loadValuesEntries(missingFileHandler *string, entries []interface{}, remote *remote.Remote, ctxEnv *environment.Environment) (map[string]interface{}, error) { envVals := map[string]interface{}{} valuesEntries := append([]interface{}{}, entries...) ld := NewEnvironmentValuesLoader(st.storage(), st.readFile, st.logger, remote) var err error - envVals, err = ld.LoadEnvironmentValues(missingFileHandler, valuesEntries) + envVals, err = ld.LoadEnvironmentValues(missingFileHandler, valuesEntries, ctxEnv) if err != nil { return nil, err } diff --git a/pkg/state/create_test.go b/pkg/state/create_test.go index 656fc119..5322d5f6 100644 --- a/pkg/state/create_test.go +++ b/pkg/state/create_test.go @@ -7,6 +7,7 @@ import ( "reflect" "testing" + "github.com/roboll/helmfile/pkg/environment" "github.com/roboll/helmfile/pkg/remote" "github.com/roboll/helmfile/pkg/testhelper" @@ -117,6 +118,7 @@ baz: "{{ readFile \"baz.txt\" }}"`) barYamlFile := "/example/path/to/bar.yaml.gotmpl" barYamlContent := []byte(`foo: FOO bar: {{ readFile "bar.txt" }} +env: {{ .Environment.Name }} `) barTextFile := "/example/path/to/bar.txt" @@ -127,6 +129,7 @@ bar: {{ readFile "bar.txt" }} "bar": "BAR", // As the file doesn't have an file extension ".gotmpl", this template expression should not be evaluated "baz": "{{ readFile \"baz.txt\" }}", + "env": "production", } valuesFile := "/example/path/to/values.yaml.gotmpl" @@ -149,8 +152,11 @@ releaseNamespace: mynamespace testFs.Cwd = "/example/path/to" r := remote.NewRemote(logger, testFs.Cwd, testFs.ReadFile, testFs.DirectoryExistsAt, testFs.FileExistsAt) + env := environment.Environment{ + Name: "production", + } state, err := NewCreator(logger, testFs.ReadFile, testFs.FileExists, testFs.Abs, testFs.Glob, testFs.DirectoryExistsAt, nil, nil, "", r). - ParseAndLoad(yamlContent, filepath.Dir(yamlFile), yamlFile, "production", true, nil) + ParseAndLoad(yamlContent, filepath.Dir(yamlFile), yamlFile, "production", true, &env) if err != nil { t.Fatalf("unexpected error: %v", err) } diff --git a/pkg/state/envvals_loader.go b/pkg/state/envvals_loader.go index 53d605a9..cd73ed3a 100644 --- a/pkg/state/envvals_loader.go +++ b/pkg/state/envvals_loader.go @@ -2,6 +2,8 @@ package state import ( "fmt" + "path/filepath" + "github.com/imdario/mergo" "github.com/roboll/helmfile/pkg/environment" "github.com/roboll/helmfile/pkg/maputil" @@ -9,7 +11,6 @@ import ( "github.com/roboll/helmfile/pkg/tmpl" "go.uber.org/zap" "gopkg.in/yaml.v2" - "path/filepath" ) type EnvironmentValuesLoader struct { @@ -31,7 +32,7 @@ func NewEnvironmentValuesLoader(storage *Storage, readFile func(string) ([]byte, } } -func (ld *EnvironmentValuesLoader) LoadEnvironmentValues(missingFileHandler *string, valuesEntries []interface{}) (map[string]interface{}, error) { +func (ld *EnvironmentValuesLoader) LoadEnvironmentValues(missingFileHandler *string, valuesEntries []interface{}, ctxEnv *environment.Environment) (map[string]interface{}, error) { result := map[string]interface{}{} for _, entry := range valuesEntries { @@ -54,7 +55,13 @@ func (ld *EnvironmentValuesLoader) LoadEnvironmentValues(missingFileHandler *str } for _, f := range files { - tmplData := EnvironmentTemplateData{environment.EmptyEnvironment, "", map[string]interface{}{}} + var env environment.Environment + if ctxEnv == nil { + env = environment.EmptyEnvironment + } else { + env = *ctxEnv + } + tmplData := EnvironmentTemplateData{env, "", map[string]interface{}{}} r := tmpl.NewFileRenderer(ld.readFile, filepath.Dir(f), tmplData) bytes, err := r.RenderToBytes(f) if err != nil { diff --git a/pkg/state/envvals_loader_test.go b/pkg/state/envvals_loader_test.go index bb6feb20..264591e0 100644 --- a/pkg/state/envvals_loader_test.go +++ b/pkg/state/envvals_loader_test.go @@ -1,12 +1,13 @@ package state import ( - "github.com/google/go-cmp/cmp" - "github.com/roboll/helmfile/pkg/remote" - "go.uber.org/zap" "io/ioutil" "path/filepath" "testing" + + "github.com/google/go-cmp/cmp" + "github.com/roboll/helmfile/pkg/remote" + "go.uber.org/zap" ) func newLoader() *EnvironmentValuesLoader { @@ -34,7 +35,7 @@ func newLoader() *EnvironmentValuesLoader { func TestEnvValsLoad_SingleValuesFile(t *testing.T) { l := newLoader() - actual, err := l.LoadEnvironmentValues(nil, []interface{}{"testdata/values.5.yaml"}) + actual, err := l.LoadEnvironmentValues(nil, []interface{}{"testdata/values.5.yaml"}, nil) if err != nil { t.Fatal(err) } @@ -52,7 +53,7 @@ func TestEnvValsLoad_SingleValuesFile(t *testing.T) { func TestEnvValsLoad_OverwriteNilValue_Issue1150(t *testing.T) { l := newLoader() - actual, err := l.LoadEnvironmentValues(nil, []interface{}{"testdata/values.1.yaml", "testdata/values.2.yaml"}) + actual, err := l.LoadEnvironmentValues(nil, []interface{}{"testdata/values.1.yaml", "testdata/values.2.yaml"}, nil) if err != nil { t.Fatal(err) } @@ -74,7 +75,7 @@ func TestEnvValsLoad_OverwriteNilValue_Issue1150(t *testing.T) { func TestEnvValsLoad_OverwriteWithNilValue_Issue1154(t *testing.T) { l := newLoader() - actual, err := l.LoadEnvironmentValues(nil, []interface{}{"testdata/values.3.yaml", "testdata/values.4.yaml"}) + actual, err := l.LoadEnvironmentValues(nil, []interface{}{"testdata/values.3.yaml", "testdata/values.4.yaml"}, nil) if err != nil { t.Fatal(err) } @@ -97,7 +98,7 @@ func TestEnvValsLoad_OverwriteWithNilValue_Issue1154(t *testing.T) { func TestEnvValsLoad_OverwriteEmptyValue_Issue1168(t *testing.T) { l := newLoader() - actual, err := l.LoadEnvironmentValues(nil, []interface{}{"testdata/issues/1168/addons.yaml", "testdata/issues/1168/addons2.yaml"}) + actual, err := l.LoadEnvironmentValues(nil, []interface{}{"testdata/issues/1168/addons.yaml", "testdata/issues/1168/addons2.yaml"}, nil) if err != nil { t.Fatal(err) }