132 lines
4.3 KiB
Go
132 lines
4.3 KiB
Go
package state
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/helmfile/helmfile/pkg/filesystem"
|
|
)
|
|
|
|
// TestIssue2182_ValuesTemplatingBugFix is an integration test that reproduces
|
|
// the exact scenario described in https://github.com/helmfile/helmfile/issues/2182
|
|
// and verifies that our fix works correctly.
|
|
func TestIssue2182_ValuesTemplatingBugFix(t *testing.T) {
|
|
// Simulate the exact scenario from the issue:
|
|
// environments:
|
|
// default:
|
|
// values:
|
|
// - values.yaml
|
|
// ---
|
|
// releases:
|
|
// - name: foo
|
|
// chart: charts/foo
|
|
// valuesTemplate:
|
|
// - {{ .Values | get "foo" (dict) | mergeOverwrite .Values | toYaml | nindent 8 }}
|
|
// - name: bar
|
|
// chart: charts/bar
|
|
// valuesTemplate:
|
|
// - {{ .Values | get "bar" (dict) | mergeOverwrite .Values | toYaml | nindent 8 }}
|
|
|
|
// Create test filesystem
|
|
fs := &filesystem.FileSystem{
|
|
Glob: func(pattern string) ([]string, error) {
|
|
return nil, nil
|
|
},
|
|
ReadFile: func(filename string) ([]byte, error) {
|
|
return nil, nil
|
|
},
|
|
}
|
|
|
|
// Simulate values.yaml content
|
|
valuesYaml := map[string]any{
|
|
"global": "shared-config",
|
|
"commonKey": "commonValue",
|
|
"foo": map[string]any{
|
|
"enabled": true,
|
|
"replicaCount": 2,
|
|
"image": "foo:1.0.0",
|
|
},
|
|
"bar": map[string]any{
|
|
"enabled": true,
|
|
"replicaCount": 1,
|
|
"image": "bar:2.0.0",
|
|
},
|
|
}
|
|
|
|
st := &HelmState{
|
|
fs: fs,
|
|
basePath: "/tmp",
|
|
FilePath: "helmfile.yaml",
|
|
RenderedValues: valuesYaml,
|
|
}
|
|
|
|
// Define the releases as they would appear in helmfile.yaml
|
|
fooRelease := &ReleaseSpec{
|
|
Name: "foo",
|
|
Chart: "charts/foo",
|
|
ValuesTemplate: []any{
|
|
`{{ .Values | get "foo" (dict) | mergeOverwrite .Values | toYaml | nindent 8 }}`,
|
|
},
|
|
}
|
|
|
|
barRelease := &ReleaseSpec{
|
|
Name: "bar",
|
|
Chart: "charts/bar",
|
|
ValuesTemplate: []any{
|
|
`{{ .Values | get "bar" (dict) | mergeOverwrite .Values | toYaml | nindent 8 }}`,
|
|
},
|
|
}
|
|
|
|
// Simulate ExecuteTemplates processing releases in order: foo then bar
|
|
releases1 := []ReleaseSpec{*fooRelease, *barRelease}
|
|
st.Releases = releases1
|
|
|
|
result1, err := st.ExecuteTemplates()
|
|
require.NoError(t, err, "ExecuteTemplates should succeed with foo then bar")
|
|
|
|
// Simulate ExecuteTemplates processing releases in reverse order: bar then foo
|
|
releases2 := []ReleaseSpec{*barRelease, *fooRelease}
|
|
st.Releases = releases2
|
|
|
|
result2, err := st.ExecuteTemplates()
|
|
require.NoError(t, err, "ExecuteTemplates should succeed with bar then foo")
|
|
|
|
// Extract the processed releases from both executions
|
|
fooRelease1 := result1.Releases[0] // foo from first execution (foo, bar)
|
|
barRelease1 := result1.Releases[1] // bar from first execution (foo, bar)
|
|
|
|
barRelease2 := result2.Releases[0] // bar from second execution (bar, foo)
|
|
fooRelease2 := result2.Releases[1] // foo from second execution (bar, foo)
|
|
|
|
// The critical assertion: Order should not matter!
|
|
// Before the fix, the second release would see modified values from the first release
|
|
require.Equal(t, fooRelease1.Values, fooRelease2.Values,
|
|
"foo release values should be identical regardless of processing order")
|
|
require.Equal(t, barRelease1.Values, barRelease2.Values,
|
|
"bar release values should be identical regardless of processing order")
|
|
|
|
// Verify that each release gets the expected merged values
|
|
// foo release should have foo-specific values merged into the root
|
|
fooVals1 := fooRelease1.Values[0]
|
|
require.Contains(t, fooVals1, "enabled")
|
|
require.Contains(t, fooVals1, "replicaCount")
|
|
require.Contains(t, fooVals1, "image")
|
|
require.Contains(t, fooVals1, "global") // Should preserve global values
|
|
require.Contains(t, fooVals1, "commonKey") // Should preserve common values
|
|
|
|
// bar release should have bar-specific values merged into the root
|
|
barVals1 := barRelease1.Values[0]
|
|
require.Contains(t, barVals1, "enabled")
|
|
require.Contains(t, barVals1, "replicaCount")
|
|
require.Contains(t, barVals1, "image")
|
|
require.Contains(t, barVals1, "global") // Should preserve global values
|
|
require.Contains(t, barVals1, "commonKey") // Should preserve common values
|
|
|
|
// Verify that the original values were not mutated
|
|
originalVals := st.Values()
|
|
require.Equal(t, valuesYaml, originalVals, "original values should remain unchanged")
|
|
|
|
t.Log("✅ Fix verified: Release order no longer affects values templating results")
|
|
}
|