How to use template-ized value in the range function in Helm

2/15/2020

I am using helm chart for Prometheus and am planning to provide different set of alert manager files for different environments. Extracted portion of existing Chart:

{{- $root := . -}}
{{- range $key, $value := .Values.alertmanagerFiles }}
  {{ $key }}: |
{{ toYaml $value | default "{}" | indent 4 }}
{{- end -}}

To override this part, I have a defined template variable

{{- define "prometheus.alertmanagerFiles" -}}
{{- if .Values.alertmanagerFiles.custom -}}
    {{- printf "alertmanagerFiles_%s" .Values.cluster.env }}
{{- else -}}
    {{- default "default" .Values.alertmanagerFiles -}}
{{- end -}}
{{- end -}}

With this, I have a new variable per environment - example: alertmanagerFiles_dev for development but am clueless because of my lack of knowledge, I don't know about how to use template-ized variable in the range function.

Tried this but does not work:

{{- $root := . -}}
{{- range $key, $value := template "prometheus.alertmanagerFiles" . }}
  {{ $key }}: |
{{ toYaml $value | default "{}" | indent 4 }}
{{- end -}}

any help, clue or direction will help me here.

-- Tech Junkie
kubernetes-helm
prometheus

1 Answer

2/18/2020

You don't need to customize the chart for this. Instead, you can provide a different set of values per environment when you helm install or helm upgrade the chart

helm upgrade prometheus stable/prometheus --install -f values.dev.yaml

This is generally much easier and preferable to putting a layer of indirection inside the template code.

If you do want to use the layer of indirection as you've shown, you're limited by the possible return types of the Go templating. The standard Go template directive only writes to output and never returns anything. Helm has an include function that instead returns the content of the rendered template as a string. That's the only thing it's possible to return from a template, though.

In your case the prometheus.alertmanagerFiles template produces a string, so you can include it to get the name of the top-level value you want to include. Then you can use the standard Go template index function to pluck that item out of .Values. This roughly looks like:

{{- $fileKey := include "prometheus.alertmanagerFiles" . }}
{{- range $key, $value := index .Values $fileKey }}
...
{{- end -}}
-- David Maze
Source: StackOverflow