fix(tller): allow deep merge of global maps

This reverts a previous decision to only do shallow merges of globals.
It allows globals to be nested maps.
parent 6c0c4ce3
...@@ -216,15 +216,30 @@ func coalesceGlobals(dest, src map[string]interface{}) map[string]interface{} { ...@@ -216,15 +216,30 @@ func coalesceGlobals(dest, src map[string]interface{}) map[string]interface{} {
return dg return dg
} }
// We manually copy (instead of using coalesceTables) because (a) we need // EXPERIMENTAL: In the past, we have disallowed globals to test tables. This
// to prevent loops, and (b) we disallow nesting tables under globals. // reverses that decision. It may somehow be possible to introduce a loop
// Globals should _just_ be k/v pairs. // here, but I haven't found a way. So for the time being, let's allow
// tables in globals.
for key, val := range sg { for key, val := range sg {
if istable(val) { if istable(val) {
log.Printf("warning: nested values are illegal in globals (%s)", key) 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 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) { } 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 continue
} }
// TODO: Do we need to do any additional checking on the value? // 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{} { ...@@ -232,7 +247,14 @@ func coalesceGlobals(dest, src map[string]interface{}) map[string]interface{} {
} }
dest[GlobalKey] = dg dest[GlobalKey] = dg
return dest 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. // coalesceValues builds up a values map for a particular chart.
......
...@@ -251,11 +251,16 @@ top: yup ...@@ -251,11 +251,16 @@ top: yup
global: global:
name: Ishmael name: Ishmael
subject: Queequeg subject: Queequeg
nested:
boat: true
pequod: pequod:
global: global:
name: Stinky name: Stinky
harpooner: Tashtego harpooner: Tashtego
nested:
boat: false
sail: true
ahab: ahab:
scope: whale scope: whale
` `
...@@ -295,6 +300,12 @@ func TestCoalesceValues(t *testing.T) { ...@@ -295,6 +300,12 @@ func TestCoalesceValues(t *testing.T) {
{"{{.pequod.global.subject}}", "Queequeg"}, {"{{.pequod.global.subject}}", "Queequeg"},
{"{{.spouter.global.name}}", "Ishmael"}, {"{{.spouter.global.name}}", "Ishmael"},
{"{{.spouter.global.harpooner}}", "<no value>"}, {"{{.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 { for _, tt := range tests {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment