fix(values): do not copy chart-default nils into coalesced values

Only user-supplied nils should survive coalescing. Chart-default nils
defaults, not just user overrides. This caused:
- %!s(<nil>) in templates using Bitnami common.secrets.key (#31919)
- pluck fallbacks returning nil instead of falling through to globals
  (#31971)

Fixes #31919
Fixes #31971

Signed-off-by: Johannes Lohmer <jojo.dev@lohmer.com>
pull/31979/head
Johannes Lohmer 2 weeks ago
parent 2ee439ac68
commit 04c6d5cd75

@ -251,6 +251,12 @@ func coalesceValues(printf printFn, c chart.Charter, v map[string]any, prefix st
// If the key is a child chart, coalesce tables with Merge set to true
merge := childChartMergeTrue(c, key, merge)
// When coalescing, clean nils from chart defaults before merging
// so they don't leak into the result.
if !merge {
cleanNilValues(src)
}
// Because v has higher precedence than nv, dest values override src
// values.
coalesceTablesFullKey(printf, dest, src, concatPrefix(subPrefix, key), merge)
@ -258,6 +264,16 @@ func coalesceValues(printf printFn, c chart.Charter, v map[string]any, prefix st
}
} else {
// If the key is not in v, copy it from nv.
// When coalescing, skip chart default nils and clean nils from
// nested maps so they don't shadow globals or produce %!s(<nil>).
if !merge {
if val == nil {
continue
}
if sub, ok := val.(map[string]any); ok {
cleanNilValues(sub)
}
}
v[key] = val
}
}
@ -326,7 +342,6 @@ func coalesceTablesFullKey(printf printFn, dst, src map[string]any, prefix strin
// But if src also has nil (or key not in src), preserve the nil
delete(dst, key)
} else if !ok {
// key not in user values, preserve src value (including nil)
dst[key] = val
} else if istable(val) {
if istable(dv) {
@ -341,6 +356,18 @@ func coalesceTablesFullKey(printf printFn, dst, src map[string]any, prefix strin
return dst
}
// cleanNilValues recursively removes nil entries from a map so that chart
// default nils don't leak into the coalesced result.
func cleanNilValues(m map[string]any) {
for key, val := range m {
if val == nil {
delete(m, key)
} else if sub, ok := val.(map[string]any); ok {
cleanNilValues(sub)
}
}
}
// istable is a special-purpose function to see if the present thing matches the definition of a YAML table.
func istable(v any) bool {
_, ok := v.(map[string]any)

@ -2,11 +2,15 @@
# Source: issue-9027/charts/subchart/templates/values.yaml
global:
hash:
key1: 1
key2: 2
key3: 13
key4: 4
key5: 5
key6: 6
hash:
key1: 1
key2: 2
key3: 13
key4: 4
key5: 5
@ -15,17 +19,19 @@ hash:
# Source: issue-9027/templates/values.yaml
global:
hash:
key1: null
key2: null
key3: 13
subchart:
global:
hash:
key1: 1
key2: 2
key3: 13
key4: 4
key5: 5
key6: 6
hash:
key1: 1
key2: 2
key3: 13
key4: 4
key5: 5

Loading…
Cancel
Save