diff --git a/pkg/chartutil/coalesce.go b/pkg/chartutil/coalesce.go index 518dfd69e..d233674f3 100644 --- a/pkg/chartutil/coalesce.go +++ b/pkg/chartutil/coalesce.go @@ -184,6 +184,9 @@ func CoalesceTables(dst, src map[string]interface{}) map[string]interface{} { // values. for key, val := range src { if dv, ok := dst[key]; ok && dv == nil { + // When the YAML value is null, we remove the value's key. + // This allows Helm's various sources of values (value files or --set) to + // remove incompatible keys from any previous chart, file, or set values. delete(dst, key) } else if !ok { dst[key] = val @@ -209,17 +212,17 @@ func CoalesceTablesUpdate(dst, src map[string]interface{}) map[string]interface{ } // src values override dest values. for key, val := range src { - if istable(val) { - switch innerdst, ok := dst[key]; { - case !ok: - case istable(innerdst): - CoalesceTablesUpdate(innerdst.(map[string]interface{}), + // We do not remove the null values, to let value templates delete values of sub-charts + if dv, ok := dst[key]; !ok { + } else if istable(val) { + if istable(dv) { + CoalesceTablesUpdate(dv.(map[string]interface{}), val.(map[string]interface{})) continue - default: - log.Printf("warning: overwriting not table with table for %s (%v)", key, innerdst) + } else { + log.Printf("warning: overwriting not table with table for %s (%v)", key, dv) } - } else if dv, ok := dst[key]; ok && istable(dv) { + } else if istable(dv) { log.Printf("warning: overwriting table with non table for %s (%v)", key, dv) } dst[key] = val diff --git a/pkg/chartutil/coalesce_test.go b/pkg/chartutil/coalesce_test.go index 359712e67..41ceec3d7 100644 --- a/pkg/chartutil/coalesce_test.go +++ b/pkg/chartutil/coalesce_test.go @@ -176,7 +176,7 @@ func getSecondaryData() map[string]interface{} { } // Tests the coalessing of getMainData() and getSecondaryData() -func testCoalescedData(t *testing.T, dst map[string]interface{}) { +func testCoalescedData(t *testing.T, dst map[string]interface{}, cleanNil bool) { // What we expect is that anything in getMainData() overrides anything in // getSecondaryData(), but that otherwise the values are coalesced. if dst["name"] != "Ishmael" { @@ -203,8 +203,10 @@ func testCoalescedData(t *testing.T, dst map[string]interface{}) { t.Errorf("Unexpected state: %v", addr["state"]) } - if _, ok = addr["country"]; ok { + if n, ok := addr["country"]; cleanNil && ok { t.Error("The country is not left out.") + } else if !cleanNil && (!ok || n != nil) { + t.Error("The country is not nil.") } if det, ok := dst["details"].(map[string]interface{}); !ok { @@ -219,8 +221,10 @@ func testCoalescedData(t *testing.T, dst map[string]interface{}) { t.Errorf("Expected boat string, got %v", dst["boat"]) } - if _, ok = dst["hole"]; ok { + if n, ok := dst["hole"]; cleanNil && ok { t.Error("The hole still exists.") + } else if !cleanNil && (!ok || n != nil) { + t.Error("The hole is not nil.") } } @@ -230,7 +234,7 @@ func TestCoalesceTables(t *testing.T) { CoalesceTables(dst, src) - testCoalescedData(t, dst) + testCoalescedData(t, dst, true) } func TestCoalesceTablesUpdate(t *testing.T) { @@ -239,7 +243,7 @@ func TestCoalesceTablesUpdate(t *testing.T) { CoalesceTablesUpdate(dst, src) - testCoalescedData(t, dst) + testCoalescedData(t, dst, false) } func TestCoalesceDep(t *testing.T) { @@ -279,7 +283,7 @@ func TestCoalesceDep(t *testing.T) { t.Error("CoalesceDep must return subchart map.") } - testCoalescedData(t, dst) + testCoalescedData(t, dst, true) glob, ok := dst["global"].(map[string]interface{}) if !ok { @@ -318,5 +322,5 @@ func TestCoalesceRoot(t *testing.T) { CoalesceRoot(chart, dst) - testCoalescedData(t, dst) + testCoalescedData(t, dst, true) }