Add string collections deep copying to CoalesceTables

Signed-off-by: Michał Słapek <28485371+mslapek@users.noreply.github.com>
pull/12091/head
Michał Słapek 1 year ago
parent 1c4885fce7
commit 680f3d2244

@ -153,6 +153,25 @@ func copyMap(src map[string]interface{}) map[string]interface{} {
return m
}
// stringCollectionsDeepCopy makes deep copy for string maps and lists.
// For other types performs shallow copy.
func stringCollectionsDeepCopy(src any) any {
switch t := src.(type) {
case map[string]any:
r := make(map[string]interface{}, len(t))
for k, v := range t {
r[k] = stringCollectionsDeepCopy(v)
}
return r
case []string:
r := make([]string, len(t))
copy(r, t)
return r
default:
return t
}
}
// coalesceValues builds up a values map for a particular chart.
//
// Values in v will override the values in the chart.
@ -212,7 +231,7 @@ func coalesceTablesFullKey(printf printFn, dst, src map[string]interface{}, pref
if dv, ok := dst[key]; ok && dv == nil {
delete(dst, key)
} else if !ok {
dst[key] = val
dst[key] = stringCollectionsDeepCopy(val)
} else if istable(val) {
if istable(dv) {
coalesceTablesFullKey(printf, dv.(map[string]interface{}), val.(map[string]interface{}), fullkey)

@ -17,6 +17,7 @@ limitations under the License.
package chartutil
import (
"bytes"
"encoding/json"
"fmt"
"testing"
@ -63,6 +64,16 @@ func withDeps(c *chart.Chart, deps ...*chart.Chart) *chart.Chart {
return c
}
func assertIsEqualToJSON(t *testing.T, name string, val any, expectedJson []byte) {
j, err := json.Marshal(val)
if err != nil {
t.Fatalf("JSON marshal failed: %v", err)
}
if !bytes.Equal(j, expectedJson) {
t.Errorf("%s contents changed, got: %v", name, string(j))
}
}
func TestCoalesceValues(t *testing.T) {
is := assert.New(t)
@ -233,12 +244,21 @@ func TestCoalesceTables(t *testing.T) {
"state": "MA",
"street": "234 Spouter Inn Ct.",
"country": "US",
"weather": map[string]interface{}{
"clouds": true,
},
},
"details": "empty",
"boat": map[string]interface{}{
"mast": true,
},
"hole": "black",
"hole": "black",
"grass": []string{"green", "yellow"},
}
srcJson, err := json.Marshal(src)
if err != nil {
t.Fatalf("JSON marshal failed: %v", err)
}
// What we expect is that anything in dst overrides anything in src, but that
@ -287,6 +307,11 @@ func TestCoalesceTables(t *testing.T) {
t.Error("The hole still exists.")
}
// change in dst shouldn't make a change in src
dst["grass"].([]string)[1] = "blue"
dst["address"].(map[string]interface{})["weather"].(map[string]interface{})["clouds"] = "no"
assertIsEqualToJSON(t, "src", src, srcJson)
dst2 := map[string]interface{}{
"name": "Ishmael",
"address": map[string]interface{}{
@ -407,3 +432,34 @@ func TestConcatPrefix(t *testing.T) {
assert.Equal(t, "b", concatPrefix("", "b"))
assert.Equal(t, "a.b", concatPrefix("a", "b"))
}
func TestTwoFollowingCoalesceTables(t *testing.T) {
update := map[string]interface{}{
"mango": map[string]interface{}{
"fruit": "cool",
},
}
main := map[string]interface{}{
"mango": map[string]interface{}{
"fruit": "super",
"color": "orange",
"taste": "ok",
},
}
updateJson, err := json.Marshal(update)
if err != nil {
t.Fatalf("JSON marshal failed: %v", err)
}
mainJson, err := json.Marshal(main)
if err != nil {
t.Fatalf("JSON marshal failed: %v", err)
}
vals := CoalesceTables(make(map[string]interface{}, len(update)), update)
vals = CoalesceTables(vals, main)
_ = vals
assertIsEqualToJSON(t, "update", update, updateJson)
assertIsEqualToJSON(t, "main", main, mainJson)
}

Loading…
Cancel
Save