I have this values.yaml
microservices:
- name: service-1
- name: service-2
ingress:
enabled: false
I want to know if microservices.X.ingress.enabled exists.
This is because if don't exists I use a default value from another variable.
Now I use this:
{{ if and (hasKey . "ingress") (hasKey .ingress "enabled") }}
{{ $ingress = .ingress.enabled }}
{{ else }}
{{ $ingress = $.Values.common.ingress.enabled }}
{{ end }}
Is there a way to access it directly and don't have to use two conditions?
If I only use "(hasKey .ingress "enabled")" I get this error: "at <.ingress>: wrong type for value; expected map[string]interface {}; got interface {}" because service-1 don't have a map.
A useful trick with this sort of structure is to extract the structure one level at a time, defaulting to an empty dictionary if absent.
{{ $ingressSettings := .ingress | default dict }}
{{ ... $ingressSettings.enabled ... }}
For the particular construction you show here, you probably want to honor
common:
ingress:
enabled: true
microservices:
- name: without-ingress
enabled: false
The various helpers like default
treat both nil
and false
as "not present", which means you can't really use that to test a value that could be absent, or could be present-but-false. You need to do something longer-winded using hasKey
.
Probably if I wanted to write this, I'd use default dict
as shown above to get a value for the per-item ingress
dictionary, but then use the Helm ternary
function to have only a single assignment to the actual variable. That leads to the (dense) construction
{{- $ing := .ingress | default dict }}
{{- $ingress := hasKey $ing "enabled" | ternary $ing.enabled $.Values.common.ingress.enabled }}
The ternary
arguments are eagerly evaluated, but since $ing
should always be a dictionary, at worst $ing.enabled
will evaluate successfully to nil
.