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 <petera@topdesk.com>
This commit is contained in:
parent
9354c38a0a
commit
ca6dd7a60f
|
|
@ -52,7 +52,7 @@ func (ld *desiredStateLoader) Load(f string, opts LoadOpts) (*state.HelmState, e
|
||||||
storage := state.NewStorage(opts.CalleePath, ld.logger, ld.glob)
|
storage := state.NewStorage(opts.CalleePath, ld.logger, ld.glob)
|
||||||
envld := state.NewEnvironmentValuesLoader(storage, ld.readFile, ld.logger, ld.remote)
|
envld := state.NewEnvironmentValuesLoader(storage, ld.readFile, ld.logger, ld.remote)
|
||||||
handler := state.MissingFileHandlerError
|
handler := state.MissingFileHandlerError
|
||||||
vals, err := envld.LoadEnvironmentValues(&handler, args)
|
vals, err := envld.LoadEnvironmentValues(&handler, args, &environment.EmptyEnvironment)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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}
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -227,7 +227,7 @@ func (c *StateCreator) loadEnvValues(st *HelmState, name string, failOnMissingEn
|
||||||
envSpec, ok := st.Environments[name]
|
envSpec, ok := st.Environments[name]
|
||||||
if ok {
|
if ok {
|
||||||
var err error
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -363,13 +363,13 @@ func (c *StateCreator) scatterGatherEnvSecretFiles(st *HelmState, envSecretFiles
|
||||||
return nil
|
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{}{}
|
envVals := map[string]interface{}{}
|
||||||
|
|
||||||
valuesEntries := append([]interface{}{}, entries...)
|
valuesEntries := append([]interface{}{}, entries...)
|
||||||
ld := NewEnvironmentValuesLoader(st.storage(), st.readFile, st.logger, remote)
|
ld := NewEnvironmentValuesLoader(st.storage(), st.readFile, st.logger, remote)
|
||||||
var err error
|
var err error
|
||||||
envVals, err = ld.LoadEnvironmentValues(missingFileHandler, valuesEntries)
|
envVals, err = ld.LoadEnvironmentValues(missingFileHandler, valuesEntries, ctxEnv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/roboll/helmfile/pkg/environment"
|
||||||
"github.com/roboll/helmfile/pkg/remote"
|
"github.com/roboll/helmfile/pkg/remote"
|
||||||
|
|
||||||
"github.com/roboll/helmfile/pkg/testhelper"
|
"github.com/roboll/helmfile/pkg/testhelper"
|
||||||
|
|
@ -117,6 +118,7 @@ baz: "{{ readFile \"baz.txt\" }}"`)
|
||||||
barYamlFile := "/example/path/to/bar.yaml.gotmpl"
|
barYamlFile := "/example/path/to/bar.yaml.gotmpl"
|
||||||
barYamlContent := []byte(`foo: FOO
|
barYamlContent := []byte(`foo: FOO
|
||||||
bar: {{ readFile "bar.txt" }}
|
bar: {{ readFile "bar.txt" }}
|
||||||
|
env: {{ .Environment.Name }}
|
||||||
`)
|
`)
|
||||||
|
|
||||||
barTextFile := "/example/path/to/bar.txt"
|
barTextFile := "/example/path/to/bar.txt"
|
||||||
|
|
@ -127,6 +129,7 @@ bar: {{ readFile "bar.txt" }}
|
||||||
"bar": "BAR",
|
"bar": "BAR",
|
||||||
// As the file doesn't have an file extension ".gotmpl", this template expression should not be evaluated
|
// As the file doesn't have an file extension ".gotmpl", this template expression should not be evaluated
|
||||||
"baz": "{{ readFile \"baz.txt\" }}",
|
"baz": "{{ readFile \"baz.txt\" }}",
|
||||||
|
"env": "production",
|
||||||
}
|
}
|
||||||
|
|
||||||
valuesFile := "/example/path/to/values.yaml.gotmpl"
|
valuesFile := "/example/path/to/values.yaml.gotmpl"
|
||||||
|
|
@ -149,8 +152,11 @@ releaseNamespace: mynamespace
|
||||||
testFs.Cwd = "/example/path/to"
|
testFs.Cwd = "/example/path/to"
|
||||||
|
|
||||||
r := remote.NewRemote(logger, testFs.Cwd, testFs.ReadFile, testFs.DirectoryExistsAt, testFs.FileExistsAt)
|
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).
|
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 {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ package state
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/imdario/mergo"
|
"github.com/imdario/mergo"
|
||||||
"github.com/roboll/helmfile/pkg/environment"
|
"github.com/roboll/helmfile/pkg/environment"
|
||||||
"github.com/roboll/helmfile/pkg/maputil"
|
"github.com/roboll/helmfile/pkg/maputil"
|
||||||
|
|
@ -9,7 +11,6 @@ import (
|
||||||
"github.com/roboll/helmfile/pkg/tmpl"
|
"github.com/roboll/helmfile/pkg/tmpl"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
"path/filepath"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type EnvironmentValuesLoader struct {
|
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{}{}
|
result := map[string]interface{}{}
|
||||||
|
|
||||||
for _, entry := range valuesEntries {
|
for _, entry := range valuesEntries {
|
||||||
|
|
@ -54,7 +55,13 @@ func (ld *EnvironmentValuesLoader) LoadEnvironmentValues(missingFileHandler *str
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, f := range files {
|
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)
|
r := tmpl.NewFileRenderer(ld.readFile, filepath.Dir(f), tmplData)
|
||||||
bytes, err := r.RenderToBytes(f)
|
bytes, err := r.RenderToBytes(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
package state
|
package state
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/google/go-cmp/cmp"
|
|
||||||
"github.com/roboll/helmfile/pkg/remote"
|
|
||||||
"go.uber.org/zap"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
"github.com/roboll/helmfile/pkg/remote"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newLoader() *EnvironmentValuesLoader {
|
func newLoader() *EnvironmentValuesLoader {
|
||||||
|
|
@ -34,7 +35,7 @@ func newLoader() *EnvironmentValuesLoader {
|
||||||
func TestEnvValsLoad_SingleValuesFile(t *testing.T) {
|
func TestEnvValsLoad_SingleValuesFile(t *testing.T) {
|
||||||
l := newLoader()
|
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 {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -52,7 +53,7 @@ func TestEnvValsLoad_SingleValuesFile(t *testing.T) {
|
||||||
func TestEnvValsLoad_OverwriteNilValue_Issue1150(t *testing.T) {
|
func TestEnvValsLoad_OverwriteNilValue_Issue1150(t *testing.T) {
|
||||||
l := newLoader()
|
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 {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -74,7 +75,7 @@ func TestEnvValsLoad_OverwriteNilValue_Issue1150(t *testing.T) {
|
||||||
func TestEnvValsLoad_OverwriteWithNilValue_Issue1154(t *testing.T) {
|
func TestEnvValsLoad_OverwriteWithNilValue_Issue1154(t *testing.T) {
|
||||||
l := newLoader()
|
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 {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -97,7 +98,7 @@ func TestEnvValsLoad_OverwriteWithNilValue_Issue1154(t *testing.T) {
|
||||||
func TestEnvValsLoad_OverwriteEmptyValue_Issue1168(t *testing.T) {
|
func TestEnvValsLoad_OverwriteEmptyValue_Issue1168(t *testing.T) {
|
||||||
l := newLoader()
|
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 {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue