Control flow and named templates

Helm · Practical · 12 min

Optional features and repeated label blocks need conditionals and reusable templates.

Control structures:

  • {{ if .Values.ingress.enabled }} ... {{ else }} ... {{ end }}: values that are false, 0, empty strings, empty lists/maps and nil are false. Combine with and, or, not, eq.
  • {{ with .Values.nodeSelector }} ... {{ end }}: runs the block only if the value is non-empty, and sets . to it.
  • {{ range .Values.hosts }} ... {{ end }} loops over lists; {{ range $key, $val := .Values.env }} loops over maps in sorted key order.
  • Variables: {{ $name := .Release.Name }}. Inside with and range the dot changes, so use $ for the root context ($.Release.Name).

Named templates avoid copy-paste. Define them in templates/_helpers.tpl:

{{- define "shop.labels" -}} ... {{- end }}

and use them with {{ include "shop.labels" . | nindent 4 }}. Prefix names with the chart name, because template names are global across a chart and its subcharts. Prefer include over the built-in template action, because include returns a string you can pipe to nindent.

Pass the right context: include "x" . passes the current dot; inside a range you may need include "x" $ or a dict with several values.

Example

{{/* templates/_helpers.tpl */}}
{{- define "shop.labels" -}}
app.kubernetes.io/name: {{ .Chart.Name }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}

{{/* templates/configmap.yaml */}}
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-env
  labels:
    {{- include "shop.labels" . | nindent 4 }}
data:
  {{- range $key, $val := .Values.env }}
  {{ $key }}: {{ $val | quote }}
  {{- end }}
  {{- with .Values.extraConfig }}
  extra.conf: {{ . | quote }}
  {{- end }}

Remember

  • if/with/range with Go truthiness; $ is the root inside with/range
  • define in _helpers.tpl, use with include ... | nindent
  • Prefix template names with the chart name

Watch out for

  • Using .Release.Name inside a range block, where the dot is the current item; use $.Release.Name.

Check yourself

  1. Inside {{ range .Values.hosts }}, how do you reach the release name?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: helm.sh/docs/chart_template_guide/control_structures/