How to include nested value in helm template

Solved. I chatted with some people in #helm-users slack channel (kubernetes.slack.com), and so the value being provided to the template is a string value. So one needs to convert it to yaml object and indent it approriately. I solved this by changing it slightly to this

  # 1st priority, to route specific end-user to canary service
  - route:
    - destination:
        host: "{{.Values.app.name}}-global.{{.Release.Namespace}}.svc.cluster.local"
        subset: canary
    match: 
{{ toYaml .Values.infra.trafficRoute.canaryCondition | indent 4 }}

we discussed this solution earlier in k8s Slack. I noticed you posted your own answer, but I thought I might as well expand on it a bit in case someone else encounters the same problem.

The issue is that Helm chart templating does text templating instead of YAML templating. Therefore, the inserted YAML sub-tree (canaryCondition) is not automatically converted to YAML and elegantly placed under the match key, but instead it's converted to string and inserted directly where the template directive is. With simple values such as strings and integers, this works fine for most cases, but more complex values such as arrays and maps need to handled differently.

In order to insert YAML sub-trees in the template, you need to first convert the sub-tree to YAML using toYaml function, and then ensure that correct indentation level is used with the indent function.

{{ toYaml .Values.infra.trafficRoute.canaryCondition | indent 4 }}

See the NGINX template example for another example on how to insert YAML sub-trees in the template.

To get started in debugging Helm chart templating, you can use the helm template command to see the YAML that the Helm chart generates.


In case there is shared confusion around the indentation:

You can also use the left trim {{- toYaml ... }} and nindent (newline + indent) to get the correct indentation:

  # 1st priority, to route specific end-user to canary service
  - route:
    - destination:
        host: "{{.Values.app.name}}-global{{.Release.Namespace}}.svc.cluster.local"
        subset: canary
    match:
      {{- toYaml .Values.infra.trafficRoute.canaryCondition | nindent 4 }}