helmfile/pkg/state/issue_2182_test.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")
}