Bump sprig to v3.1.0 and mergo 3.11 (#1456)

* Bump sprig to v3.1.0
test for mergeOverwrite

* Let mergo not (accidentally) try to merge unexported fields

This is also a good chance separate `HelmState` with the config loaded from YAML, which I had been wanting to do for a long time.

Co-authored-by: Johannes Alkjær <johannes.alkjaer@wunderman.com>
Co-authored-by: Yusuke Kuoka <ykuoka@gmail.com>
This commit is contained in:
Johannes Alkjær
2020-09-04 09:58:54 +09:00
committed by GitHub
co-authored by Johannes Alkjær Yusuke Kuoka
parent efd26f288a
commit 9d2c0d4285
8 changed files with 188 additions and 112 deletions
+1 -1
View File
@@ -216,7 +216,7 @@ func (ld *desiredStateLoader) renderAndLoad(env, overrodeEnv *environment.Enviro
if finalState == nil {
finalState = currentState
} else {
if err := mergo.Merge(finalState, currentState, mergo.WithOverride); err != nil {
if err := mergo.Merge(&finalState.ReleaseSetSpec, &currentState.ReleaseSetSpec, mergo.WithOverride); err != nil {
return nil, err
}
}
+10 -2
View File
@@ -10,7 +10,11 @@ func TestGetArgs(t *testing.T) {
args := "--timeout=3600 --set app1.bootstrap=true --set app2.bootstrap=false --tiller-namespace ns"
defaultArgs := []string{"--recreate-pods", "--force"}
Helmdefaults := state.HelmSpec{KubeContext: "test", TillerNamespace: "test-namespace", Args: defaultArgs}
testState := &state.HelmState{HelmDefaults: Helmdefaults}
testState := &state.HelmState{
ReleaseSetSpec: state.ReleaseSetSpec{
HelmDefaults: Helmdefaults,
},
}
receivedArgs := GetArgs(args, testState)
expectedOutput := "--timeout=3600 --set app1.bootstrap=true --set app2.bootstrap=false --tiller-namespace ns --recreate-pods --force"
@@ -24,7 +28,11 @@ func Test2(t *testing.T) {
args := "--timeout=3600 --set app1.bootstrap=true --set app2.bootstrap=false,app3.bootstrap=true --tiller-namespace ns"
defaultArgs := []string{"--recreate-pods", "--force"}
Helmdefaults := state.HelmSpec{KubeContext: "test", TillerNamespace: "test-namespace", Args: defaultArgs}
testState := &state.HelmState{HelmDefaults: Helmdefaults}
testState := &state.HelmState{
ReleaseSetSpec: state.ReleaseSetSpec{
HelmDefaults: Helmdefaults,
},
}
receivedArgs := GetArgs(args, testState)
expectedOutput := "--timeout=3600 --set app1.bootstrap=true --set app2.bootstrap=false,app3.bootstrap=true --tiller-namespace ns --recreate-pods --force"
+14 -10
View File
@@ -40,11 +40,7 @@ const (
EmptyTimeout = -1
)
// HelmState structure for the helmfile
type HelmState struct {
basePath string
FilePath string
type ReleaseSetSpec struct {
DefaultHelmBinary string `yaml:"helmBinary,omitempty"`
// DefaultValues is the default values to be overrode by environment values and command-line overrides
@@ -71,6 +67,19 @@ type HelmState struct {
Env environment.Environment `yaml:"-"`
// If set to "Error", return an error when a subhelmfile points to a
// non-existent path. The default behavior is to print a warning. Note the
// differing default compared to other MissingFileHandlers.
MissingFileHandler string `yaml:"missingFileHandler"`
}
// HelmState structure for the helmfile
type HelmState struct {
basePath string
FilePath string
ReleaseSetSpec `yaml:",inline"`
logger *zap.SugaredLogger
readFile func(string) ([]byte, error)
@@ -82,11 +91,6 @@ type HelmState struct {
runner helmexec.Runner
valsRuntime vals.Evaluator
// If set to "Error", return an error when a subhelmfile points to a
// non-existent path. The default behavior is to print a warning. Note the
// differing default compared to other MissingFileHandlers.
MissingFileHandler string `yaml:"missingFileHandler"`
}
// SubHelmfileSpec defines the subhelmfile path and options
+20 -16
View File
@@ -135,14 +135,16 @@ func TestHelmState_executeTemplates(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
state := &HelmState{
basePath: ".",
HelmDefaults: HelmSpec{
KubeContext: "test_context",
},
Env: environment.Environment{Name: "test_env"},
OverrideNamespace: "test-namespace_",
Repositories: nil,
Releases: []ReleaseSpec{
tt.input,
ReleaseSetSpec: ReleaseSetSpec{
HelmDefaults: HelmSpec{
KubeContext: "test_context",
},
Env: environment.Environment{Name: "test_env"},
OverrideNamespace: "test-namespace_",
Repositories: nil,
Releases: []ReleaseSpec{
tt.input,
},
},
}
@@ -235,14 +237,16 @@ func TestHelmState_recursiveRefsTemplates(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
state := &HelmState{
basePath: ".",
HelmDefaults: HelmSpec{
KubeContext: "test_context",
},
Env: environment.Environment{Name: "test_env"},
OverrideNamespace: "test-namespace_",
Repositories: nil,
Releases: []ReleaseSpec{
tt.input,
ReleaseSetSpec: ReleaseSetSpec{
HelmDefaults: HelmSpec{
KubeContext: "test_context",
},
Env: environment.Environment{Name: "test_env"},
OverrideNamespace: "test-namespace_",
Repositories: nil,
Releases: []ReleaseSpec{
tt.input,
},
},
}
+113 -81
View File
@@ -127,12 +127,14 @@ func TestHelmState_applyDefaultsTo(t *testing.T) {
tt := tests[i]
t.Run(tt.name, func(t *testing.T) {
state := &HelmState{
basePath: tt.fields.BaseChartPath,
DeprecatedContext: tt.fields.Context,
DeprecatedReleases: tt.fields.DeprecatedReleases,
OverrideNamespace: tt.fields.Namespace,
Repositories: tt.fields.Repositories,
Releases: tt.fields.Releases,
basePath: tt.fields.BaseChartPath,
ReleaseSetSpec: ReleaseSetSpec{
DeprecatedContext: tt.fields.Context,
DeprecatedReleases: tt.fields.DeprecatedReleases,
OverrideNamespace: tt.fields.Namespace,
Repositories: tt.fields.Repositories,
Releases: tt.fields.Releases,
},
}
if state.ApplyOverrides(&tt.args.spec); !reflect.DeepEqual(tt.args.spec, tt.want) {
t.Errorf("HelmState.ApplyOverrides() = %v, want %v", tt.args.spec, tt.want)
@@ -695,11 +697,13 @@ func TestHelmState_flagsForUpgrade(t *testing.T) {
tt := tests[i]
t.Run(tt.name, func(t *testing.T) {
state := &HelmState{
basePath: "./",
DeprecatedContext: "default",
Releases: []ReleaseSpec{*tt.release},
HelmDefaults: tt.defaults,
valsRuntime: valsRuntime,
basePath: "./",
ReleaseSetSpec: ReleaseSetSpec{
DeprecatedContext: "default",
Releases: []ReleaseSpec{*tt.release},
HelmDefaults: tt.defaults,
},
valsRuntime: valsRuntime,
}
helm := &exectest.Helm{
Version: tt.version,
@@ -921,7 +925,9 @@ func TestHelmState_SyncRepos(t *testing.T) {
}
}
state := &HelmState{
Repositories: tt.repos,
ReleaseSetSpec: ReleaseSetSpec{
Repositories: tt.repos,
},
}
if _, _ = state.SyncRepos(tt.helm, map[string]bool{}); !reflect.DeepEqual(tt.helm.Repo, tt.want) {
t.Errorf("HelmState.SyncRepos() for [%s] = %v, want %v", tt.name, tt.helm.Repo, tt.want)
@@ -1032,7 +1038,9 @@ func TestHelmState_SyncReleases(t *testing.T) {
tt := tests[i]
t.Run(tt.name, func(t *testing.T) {
state := &HelmState{
Releases: tt.releases,
ReleaseSetSpec: ReleaseSetSpec{
Releases: tt.releases,
},
logger: logger,
valsRuntime: valsRuntime,
}
@@ -1135,8 +1143,10 @@ func TestHelmState_SyncReleases_MissingValuesFileForUndesiredRelease(t *testing.
tt := tests[i]
t.Run(tt.name, func(t *testing.T) {
state := &HelmState{
basePath: ".",
Releases: []ReleaseSpec{tt.release},
basePath: ".",
ReleaseSetSpec: ReleaseSetSpec{
Releases: []ReleaseSpec{tt.release},
},
logger: logger,
valsRuntime: valsRuntime,
}
@@ -1281,7 +1291,9 @@ func TestHelmState_SyncReleasesAffectedRealeases(t *testing.T) {
tt := tests[i]
t.Run(tt.name, func(t *testing.T) {
state := &HelmState{
Releases: tt.releases,
ReleaseSetSpec: ReleaseSetSpec{
Releases: tt.releases,
},
logger: logger,
valsRuntime: valsRuntime,
}
@@ -1383,7 +1395,9 @@ func TestGetDeployedVersion(t *testing.T) {
tt := tests[i]
t.Run(tt.name, func(t *testing.T) {
state := &HelmState{
Releases: []ReleaseSpec{tt.release},
ReleaseSetSpec: ReleaseSetSpec{
Releases: []ReleaseSpec{tt.release},
},
logger: logger,
valsRuntime: valsRuntime,
}
@@ -1510,7 +1524,9 @@ func TestHelmState_DiffReleases(t *testing.T) {
tt := tests[i]
t.Run(tt.name, func(t *testing.T) {
state := &HelmState{
Releases: tt.releases,
ReleaseSetSpec: ReleaseSetSpec{
Releases: tt.releases,
},
logger: logger,
valsRuntime: valsRuntime,
}
@@ -1582,7 +1598,9 @@ func TestHelmState_SyncReleasesCleanup(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
numRemovedFiles := 0
state := &HelmState{
Releases: tt.releases,
ReleaseSetSpec: ReleaseSetSpec{
Releases: tt.releases,
},
logger: logger,
valsRuntime: valsRuntime,
removeFile: func(f string) error {
@@ -1666,7 +1684,9 @@ func TestHelmState_DiffReleasesCleanup(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
numRemovedFiles := 0
state := &HelmState{
Releases: tt.releases,
ReleaseSetSpec: ReleaseSetSpec{
Releases: tt.releases,
},
logger: logger,
valsRuntime: valsRuntime,
removeFile: func(f string) error {
@@ -1728,35 +1748,37 @@ generated: 2019-05-16T15:42:45.50486+09:00
state := &HelmState{
basePath: "/src",
FilePath: "/src/helmfile.yaml",
Releases: []ReleaseSpec{
{
Chart: "./..",
ReleaseSetSpec: ReleaseSetSpec{
Releases: []ReleaseSpec{
{
Chart: "./..",
},
{
Chart: "../examples",
},
{
Chart: "../../helmfile",
},
{
Chart: "published",
},
{
Chart: "published/deeper",
},
{
Chart: "stable/envoy",
Version: "1.5.0",
},
{
Chart: "stable/envoy",
Version: "1.4.0",
},
},
{
Chart: "../examples",
},
{
Chart: "../../helmfile",
},
{
Chart: "published",
},
{
Chart: "published/deeper",
},
{
Chart: "stable/envoy",
Version: "1.5.0",
},
{
Chart: "stable/envoy",
Version: "1.4.0",
},
},
Repositories: []RepositorySpec{
{
Name: "stable",
URL: "https://kubernetes-charts.storage.googleapis.com",
Repositories: []RepositorySpec{
{
Name: "stable",
URL: "https://kubernetes-charts.storage.googleapis.com",
},
},
},
tempDir: tempDir,
@@ -1790,30 +1812,32 @@ func TestHelmState_ResolveDeps_NoLockFile(t *testing.T) {
state := &HelmState{
basePath: "/src",
FilePath: "/src/helmfile.yaml",
Releases: []ReleaseSpec{
{
Chart: "./..",
ReleaseSetSpec: ReleaseSetSpec{
Releases: []ReleaseSpec{
{
Chart: "./..",
},
{
Chart: "../examples",
},
{
Chart: "../../helmfile",
},
{
Chart: "published",
},
{
Chart: "published/deeper",
},
{
Chart: "stable/envoy",
},
},
{
Chart: "../examples",
},
{
Chart: "../../helmfile",
},
{
Chart: "published",
},
{
Chart: "published/deeper",
},
{
Chart: "stable/envoy",
},
},
Repositories: []RepositorySpec{
{
Name: "stable",
URL: "https://kubernetes-charts.storage.googleapis.com",
Repositories: []RepositorySpec{
{
Name: "stable",
URL: "https://kubernetes-charts.storage.googleapis.com",
},
},
},
logger: logger,
@@ -1906,8 +1930,10 @@ func TestHelmState_ReleaseStatuses(t *testing.T) {
tt := tests[i]
f := func(t *testing.T) {
state := &HelmState{
Releases: tt.releases,
logger: logger,
ReleaseSetSpec: ReleaseSetSpec{
Releases: tt.releases,
},
logger: logger,
fileExists: func(f string) (bool, error) {
if f != "foo.yaml" {
return false, fmt.Errorf("unexpected file: %s", f)
@@ -1991,8 +2017,10 @@ func TestHelmState_TestReleasesNoCleanUp(t *testing.T) {
tt := tests[i]
f := func(t *testing.T) {
state := &HelmState{
Releases: tt.releases,
logger: logger,
ReleaseSetSpec: ReleaseSetSpec{
Releases: tt.releases,
},
logger: logger,
}
errs := state.TestReleases(tt.helm, tt.cleanup, 1, 1)
if (errs != nil) != tt.wantErr {
@@ -2042,8 +2070,10 @@ func TestHelmState_NoReleaseMatched(t *testing.T) {
tt := tests[i]
f := func(t *testing.T) {
state := &HelmState{
Releases: releases,
logger: logger,
ReleaseSetSpec: ReleaseSetSpec{
Releases: releases,
},
logger: logger,
}
state.Selectors = []string{tt.labels}
errs := state.FilterReleases()
@@ -2208,11 +2238,13 @@ func TestHelmState_Delete(t *testing.T) {
release,
}
state := &HelmState{
HelmDefaults: HelmSpec{
KubeContext: tt.defKubeContext,
ReleaseSetSpec: ReleaseSetSpec{
HelmDefaults: HelmSpec{
KubeContext: tt.defKubeContext,
},
Releases: releases,
},
Releases: releases,
logger: logger,
logger: logger,
}
helm := &exectest.Helm{
Lists: map[exectest.ListKey]string{},
+23
View File
@@ -0,0 +1,23 @@
package tmpl
import (
"testing"
)
func TestMergeOverwrite(t *testing.T) {
ctx := &Context{}
buf, err := ctx.RenderTemplateToBuffer(`
{{- $v1 := dict "bool" true "int" 2 "str" "v1" "str2" "v1" -}}
{{- $v2 := dict "bool" false "int" 0 "str" "v2" "str2" "" -}}
{{- $mo1 := mergeOverwrite (dict) $v1 $v2 }}
{{- $mo1 -}}
`)
expected := "map[bool:false int:0 str:v2 str2:]"
if err != nil {
t.Errorf("unexpected error: %v", err)
}
actual := buf.String()
if actual != expected {
t.Errorf("unexpected result: expected=%v, actual=%v", expected, actual)
}
}