diff --git a/pkg/chartutil/values.go b/pkg/chartutil/values.go index 16e1ae9b4dd9f95f8f9b95b0208f389387a0e9f7..a4cb1a2221e071f37b3d34522affe12555495950 100644 --- a/pkg/chartutil/values.go +++ b/pkg/chartutil/values.go @@ -216,15 +216,30 @@ func coalesceGlobals(dest, src map[string]interface{}) map[string]interface{} { return dg } - // We manually copy (instead of using coalesceTables) because (a) we need - // to prevent loops, and (b) we disallow nesting tables under globals. - // Globals should _just_ be k/v pairs. + // EXPERIMENTAL: In the past, we have disallowed globals to test tables. This + // reverses that decision. It may somehow be possible to introduce a loop + // here, but I haven't found a way. So for the time being, let's allow + // tables in globals. for key, val := range sg { if istable(val) { - log.Printf("warning: nested values are illegal in globals (%s)", key) - continue + vv := copyMap(val.(map[string]interface{})) + if destv, ok := dg[key]; ok { + if destvmap, ok := destv.(map[string]interface{}); ok { + // Basically, we reverse order of coalesce here to merge + // top-down. + coalesceTables(vv, destvmap) + dg[key] = vv + continue + } else { + log.Printf("Conflict: cannot merge map onto non-map for %q. Skipping.", key) + } + } else { + // Here there is no merge. We're just adding. + dg[key] = vv + } } else if dv, ok := dg[key]; ok && istable(dv) { - log.Printf("warning: nested values are illegal in globals (%s)", key) + // It's not clear if this condition can actually ever trigger. + log.Printf("key %s is table. Skipping", key) continue } // TODO: Do we need to do any additional checking on the value? @@ -232,7 +247,14 @@ func coalesceGlobals(dest, src map[string]interface{}) map[string]interface{} { } dest[GlobalKey] = dg return dest +} +func copyMap(src map[string]interface{}) map[string]interface{} { + dest := make(map[string]interface{}, len(src)) + for k, v := range src { + dest[k] = v + } + return dest } // coalesceValues builds up a values map for a particular chart. diff --git a/pkg/chartutil/values_test.go b/pkg/chartutil/values_test.go index 0cb86e6efbd138e629c4bd576b4a37d099d2a112..e7b120924b947a5ac52700c79012624e793fcfb3 100644 --- a/pkg/chartutil/values_test.go +++ b/pkg/chartutil/values_test.go @@ -263,11 +263,16 @@ top: yup global: name: Ishmael subject: Queequeg + nested: + boat: true pequod: global: name: Stinky harpooner: Tashtego + nested: + boat: false + sail: true ahab: scope: whale ` @@ -307,6 +312,12 @@ func TestCoalesceValues(t *testing.T) { {"{{.pequod.global.subject}}", "Queequeg"}, {"{{.spouter.global.name}}", "Ishmael"}, {"{{.spouter.global.harpooner}}", "<no value>"}, + + {"{{.global.nested.boat}}", "true"}, + {"{{.pequod.global.nested.boat}}", "true"}, + {"{{.spouter.global.nested.boat}}", "true"}, + {"{{.pequod.global.nested.sail}}", "true"}, + {"{{.spouter.global.nested.sail}}", "<no value>"}, } for _, tt := range tests {