Implementing Template Flow Control
1. Using Conditional Statements
Example: if/else if/else
{{- if eq .Values.env "prod" }}
replicas: 5
{{- else if eq .Values.env "staging" }}
replicas: 2
{{- else }}
replicas: 1
{{- end }}
| Operator | Meaning |
|---|---|
eq / ne | Equal / not equal |
lt / le / gt / ge | Numeric comparison |
and / or / not | Boolean logic |
2. Implementing Loops
Example: range over list and map
env:
{{- range .Values.env }}
- name: {{ .name }}
value: {{ .value | quote }}
{{- end }}
annotations:
{{- range $key, $value := .Values.annotations }}
{{ $key }}: {{ $value | quote }}
{{- end }}
3. Using with Scope
Example: Rebind dot
{{- with .Values.image }}
image: "{{ .repository }}:{{ .tag }}"
imagePullPolicy: {{ .pullPolicy }}
{{- end }}
Warning: Inside
with, . is rebound. Use $ to access the root, or $.Release.Name.4. Defining Variables
| Syntax | Effect |
|---|---|
{{- $name := "myapp" }} | Declare variable |
{{- $name = "other" }} | Reassign (Go template 1.11+) |
{{ range $i, $v := .Values.list }} | Index + value |
$ | Always refers to root context |
5. Checking Value Existence
Example: Safe access patterns
{{- if .Values.tls }}
{{- if .Values.tls.enabled }}
tls: enabled
{{- end }}
{{- end }}
{{/* Or use hasKey */}}
{{- if hasKey .Values "feature" }}
feature: {{ .Values.feature }}
{{- end }}
{{/* Required with custom message */}}
secret: {{ required "secret value is required" .Values.secret }}
6. Using Boolean Logic
| Expression | Behavior |
|---|---|
and .a .b | True if all truthy |
or .a .b | True if any truthy |
not .a | Invert |
and (eq .x 1) (gt .y 0) | Group with parens |
Note: Empty string, 0, false, nil, empty list/map are all falsy.
7. Comparing Values
| Function | Use |
|---|---|
eq a b | Type + value equality |
deepEqual a b | Recursive equality (Sprig) |
semver "1.2.0" | (semver .Chart.Version).LessThan | SemVer comparison |
semverCompare ">=1.0.0" .Chart.Version | Constraint match |
8. Breaking Loop Iteration
Note: Go templates have no native
break/continue. Filter the slice first or use if inside range to skip.| Pattern | Implementation |
|---|---|
| Skip items | {{- range .items }}{{- if .enabled }}…{{- end }}{{- end }} |
| Filter then range | Pre-process via helper template returning filtered list |
| Early exit | Not supported; refactor to fail on condition |
9. Handling Empty Values
Example: Avoid emitting empty fields
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 2 }}
{{- end }}
{{- if .Values.annotations }}
annotations:
{{- toYaml .Values.annotations | nindent 2 }}
{{- end }}
10. Using Complex Conditionals
Example: Combined predicate
{{- if and .Values.ingress.enabled (or (eq .Values.env "prod") (eq .Values.env "staging")) }}
{{- include "myapp.ingress" . }}
{{- end }}
11. Implementing Dynamic Resource Creation
Example: Generate one ConfigMap per entry
{{- range $name, $data := .Values.configs }}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "myapp.fullname" $ }}-{{ $name }}
labels: {{- include "myapp.labels" $ | nindent 4 }}
data:
{{- range $k, $v := $data }}
{{ $k }}: {{ $v | quote }}
{{- end }}
{{- end }}