helmfile/pkg/state/values_isolation_test.go

78 lines
2.5 KiB
Go

package state
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/helmfile/helmfile/pkg/filesystem"
)
// TestValuesMutationFix reproduces and tests the fix for the issue described in
// https://github.com/helmfile/helmfile/issues/2182
// where mergeOverwrite modifies the global .Values object instead of creating a local copy
func TestValuesMutationFix(t *testing.T) {
// Create test filesystem with no files
fs := &filesystem.FileSystem{
Glob: func(pattern string) ([]string, error) {
return nil, nil
},
ReadFile: func(filename string) ([]byte, error) {
return nil, nil
},
}
st := &HelmState{
fs: fs,
basePath: "/tmp",
RenderedValues: map[string]any{
"common": "value",
"foo": map[string]any{
"specific": "foo-value",
},
"bar": map[string]any{
"specific": "bar-value",
},
},
}
release := &ReleaseSpec{
Name: "test-release",
Chart: "test/chart",
}
// Create template data twice to simulate two different releases
vals1 := st.Values()
tmplData1, err := st.createReleaseTemplateData(release, vals1)
require.NoError(t, err, "first createReleaseTemplateData should not fail")
vals2 := st.Values()
tmplData2, err := st.createReleaseTemplateData(release, vals2)
require.NoError(t, err, "second createReleaseTemplateData should not fail")
// Verify that both template data have the same initial values
require.Equal(t, tmplData1.Values, tmplData2.Values, "both template data should start with identical values")
// Simulate mergeOverwrite operation on first template data
// This should not affect the second template data after our fix
fooSection, ok := tmplData1.Values["foo"].(map[string]any)
require.True(t, ok, "foo section should be a map")
// Manually perform what mergeOverwrite would do - add values from foo section to the root
for k, v := range fooSection {
tmplData1.Values[k] = v
}
// Verify that the modification only affected tmplData1, not tmplData2
_, hasSpecificInTmpl1 := tmplData1.Values["specific"]
_, hasSpecificInTmpl2 := tmplData2.Values["specific"]
require.True(t, hasSpecificInTmpl1, "tmplData1 should have the merged 'specific' key")
require.False(t, hasSpecificInTmpl2, "tmplData2 should NOT have the merged 'specific' key (values should be isolated)")
// Also verify that the original values are not affected
originalVals := st.Values()
_, hasSpecificInOriginal := originalVals["specific"]
require.False(t, hasSpecificInOriginal, "original Values should NOT be affected")
}