I have the following input:
alerts:
api_http_500:
default_config:
enabled: true
override:
user_1:
enabled: false
I wanna check if the enabled field exists for a user. If it not so I use the default one.
I'm using index and default
like follow:
{{ (index $alerts "alerts" "api_http_500" "override" "user_2" "enabled") | default (index $alerts "alerts" "api_http_500" "default_config" "enabled") }}
But I have this error <index $alerts "alerts" "user_2" "enabled">: error calling index: index of nil pointer
.
I don't know how to use the default value without a if/else structure.
The fundamental error is that there is no user_2
field in the data, so when you try to fetch it, you get nil
; you can't do deeper lookups in that. default
can still come to the rescue!
The Go text/template
language supports local variables. So we can set a local variable to what should be the user_2
value. If that's not present, the Sprig support library includes a dict
function that can produce an empty dictionary.
{{- $overrides := index $alerts "user_2" | default dict -}}
Now $overrides
is always a dictionary, so we can look up in that, or if there's nothing there, fall back to the defaults.
{{- $a := index $alerts.alerts "api_http_500" -}}
{{- $defaults := $a.default_config -}}
{{- $overrides := index $a.override "user_2" | default dict -}}
{{- $enabled := $overrides.enabled | default $defaults.enabled -}}
This looks good, but the one other problem is that default
doesn't distinguish present-but-false from absent; both are "falsey" and will get replaced with the default value. The standard template eq
requires values to have the same type, but Sprig's deepEqual
doesn't have this requirement.
This lets you write the detailed logical statement that the option should be enabled if the override is true, or if the override is not false (I don't think there's a way to spell out "nil" or "absent") and the default is true.
{{- $enabled := or $overrides.enabled (and (not (deepEqual $overrides.enabled false)) $defaults.enabled) -}}
(It is worth considering whether you want this much Go template logic, and whether you can either restructure your values file to simplify this, or use something like a Kubernetes operator that's in a more normal language and is more testable.)