Search code examples
kuberneteskubernetes-helmgo-templates

How know if a submap has a key on Helm


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.


Solution

  • 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.