Helm templates are powerful tools for defining Kubernetes manifests in a dynamic and reusable way. They leverage Go templating, enriched with a set of built-in functions that extend their capabilities significantly. This article provides a comprehensive guide to Helm template functions, focusing particularly on logic and flow control, string manipulation, and comparison functions, essential for crafting sophisticated and adaptable Helm charts.
Logic and Flow Control in Helm Templates
Conditional logic is crucial for creating flexible templates that adapt to different environments or configurations. Helm provides a suite of functions to manage flow control within your templates.
Boolean Logic: and
, or
, not
These fundamental functions allow you to combine boolean expressions:
-
and
: Returnstrue
if all arguments are non-empty (or boolean true). It returns the first empty argument or the last argument if all are non-empty.{{ and .Values.enabled .Values.debug }}
This example checks if both
.Values.enabled
and.Values.debug
are true. -
or
: Returnstrue
if at least one argument is non-empty (or boolean true). It returns the first non-empty argument or the last argument if all are empty.{{ or .Values.useStaging .Values.useProduction }}
This checks if either
.Values.useStaging
or.Values.useProduction
is true. -
not
: Returns the boolean negation of its argument.{{ if not .Values.isSecure }} # Run in insecure mode {{ end }}
This condition executes the block if
.Values.isSecure
is false or empty.
Equality and Comparison: eq
, ne
, lt
, le
, gt
, ge
These functions enable you to compare values:
-
eq
: Checks for equality (e.g.,Arg1 == Arg2
).{{ if eq .Values.environment "production" }} # Production specific configuration {{ end }}
-
ne
: Checks for inequality (e.g.,Arg1 != Arg2
).{{ if ne .Values.replicas 3 }} # Scale differently {{ end }}
-
lt
: Less than (e.g.,Arg1 < Arg2
). -
le
: Less than or equal to (e.g.,Arg1 <= Arg2
). -
gt
: Greater than (e.g.,Arg1 > Arg2
). -
ge
: Greater than or equal to (e.g.,Arg1 >= Arg2
).{{ if gt .Values.cpuCores 2 }} # Allocate more resources {{ end }}
Handling Empty Values: default
, required
, empty
, coalesce
Managing potentially missing or empty values is crucial for robust templates:
-
default
: Provides a default value if the input is empty.replicas: {{ default 1 .Values.replicaCount }}
If
.Values.replicaCount
is empty,replicas
will default to1
.“Empty” is defined contextually:
0
for numbers,""
for strings,[]
for lists,{}
for dictionaries,false
for booleans, andnil
. -
required
: Enforces that a value must be provided. If the value is empty, template rendering fails with an error message.ingressHostname: {{ required "Ingress hostname is required!" .Values.hostname }}
This ensures that
.Values.hostname
is set, preventing deployment with missing configurations. -
empty
: Checks if a value is considered empty based on the same definition asdefault
.{{ if empty .Values.imageTag }} # Use latest tag if not specified image: {{ .Values.image }}:latest {{ else }} image: {{ .Values.image }}:{{ .Values.imageTag }} {{ end }}
-
coalesce
: Returns the first non-empty value from a list of arguments.imageTag: {{ coalesce .Values.tagOverride .Values.imageTag "latest" }}
This will use
.Values.tagOverride
if set, otherwise.Values.imageTag
, and finally default to"latest"
if both are empty.
Error Handling: fail
fail
: Immediately stops template rendering and returns a custom error message. Useful for enforcing conditions that must be met for a valid chart.{{ if not .Values.licenseAccepted }} {{ fail "License must be accepted to deploy this chart." }} {{ end }}
Conditional Assignment: ternary
ternary
: A concise way to perform conditional value assignment, similar to a ternary operator in programming languages. It takes a ‘true value’, a ‘false value’, and a test condition.persistenceEnabled: {{ ternary "true" "false" .Values.persistence.enabled | quote }}
If
.Values.persistence.enabled
is true, it returns"true"
; otherwise, it returns"false"
. Thequote
function is used here to ensure the output is a string.
String Manipulation Functions in Helm Templates
Helm provides a rich set of string functions for transforming and manipulating text within your templates. These are essential for tasks like formatting names, generating labels, and processing string data.
Basic String Operations: print
, println
, printf
-
print
: Concatenates arguments into a single string.fullnameOverride: {{ print .Chart.Name "-" .Release.Name }}
This might produce something like
mychart-myrelease
. -
println
: Similar toprint
but adds a newline character at the end. -
printf
: Formats a string according to a format specifier, similar to C-styleprintf
.podName: {{ printf "%s-%s-pod" .Chart.Name .Release.Name }}
This allows for more controlled string formatting. Placeholders like
%s
(string),%d
(integer),%v
(default format) are supported, among others.
String Trimming and Case Conversion
-
trim
: Removes whitespace from both ends of a string. -
trimAll
: Removes specified characters from both ends of a string. -
trimPrefix
: Removes a prefix from a string. -
trimSuffix
: Removes a suffix from a string. -
lower
: Converts a string to lowercase. -
upper
: Converts a string to uppercase. -
title
: Converts a string to title case (capitalizes the first letter of each word). -
untitle
: Removes title casing.appLabel: {{ .Chart.Name | lower | trimSuffix "-" }}
This example converts the chart name to lowercase and removes a trailing hyphen if present, suitable for creating Kubernetes labels.
Substrings and Repetition
-
substr
: Extracts a substring given start and end indices.shortName: {{ substr 0 10 .Release.Name }}
This gets the first 10 characters of the release name.
-
repeat
: Repeats a string multiple times.indentation: {{ repeat 4 " " }} # Creates 4 spaces for indentation
String Manipulation and Formatting
nospace
: Removes all whitespace from a string.trunc
: Truncates a string to a specified length, optionally from the beginning or end.abbrev
: Truncates a string with ellipses (...
) if it exceeds a maximum length.abbrevboth
: Abbreviates both sides of a string with ellipses.initials
: Generates initials from a string of words.wrap
: Wraps text at a given column count.wrapWith
: Wraps text using a custom string.
String Matching and Searching
-
contains
: Checks if a string contains another string.{{ if contains "prod" .Values.environment }} # Apply production specific rules {{ end }}
-
hasPrefix
,hasSuffix
: Checks if a string starts or ends with a given prefix or suffix.
Quoting and Concatenation
quote
: Wraps a string in double quotes.squote
: Wraps a string in single quotes.cat
: Concatenates multiple strings with spaces in between.
Indentation and Replacement
indent
: Indents every line of a string by a specified number of spaces.nindent
: Similar toindent
, but prepends a newline.replace
: Performs simple string replacement.
Pluralization and Case Conversion
-
plural
: Provides basic pluralization based on a count.{{ len .Values.servers | plural "one server" "servers" }}
-
snakecase
: Converts camelCase to snake_case. -
camelcase
: Converts snake_case to CamelCase. -
kebabcase
: Converts camelCase to kebab-case. -
swapcase
: Swaps the case of characters in a string based on a word-based algorithm.
Randomization
shuffle
: Randomizes the characters in a string.randAlphaNum
,randAlpha
,randNumeric
,randAscii
: Generate cryptographically secure random strings with different character sets.
Comparing Strings and Semantic Versions in Helm
String comparison is fundamental for conditional logic, especially when dealing with versions or environment names. Helm enhances this with functions for semantic version comparison.
Basic String Comparisons
The logic functions like eq
, ne
, lt
, le
, gt
, ge
can be directly used for string comparisons. These perform lexicographical comparisons based on ASCII values.
{{ if eq .Values.appVersion "1.2.3" }}
# Version specific configurations
{{ end }}
Semantic Version Comparisons: semver
, semverCompare
For comparing software versions that follow Semantic Versioning (SemVer), Helm provides:
-
semver
: Parses a string into a SemVer object, allowing access to its components (Major, Minor, Patch, Prerelease, Metadata).{{ $version := semver .Values.appVersion }} {{ if ge $version.Major 2 }} # Apply configurations for version 2 and above {{ end }}
-
semverCompare
: Provides more advanced SemVer comparison, including support for version ranges and wildcards.{{ if semverCompare ">= 1.2.0 < 2.0.0" .Values.appVersion }} # Apply configurations for versions between 1.2.0 and 2.0.0 (exclusive) {{ end }}
semverCompare
supports operators like=
,!=
,>
,<
,>=
,<=
, as well as range notations like hyphen ranges (1.2 - 1.4.5
), wildcard (1.2.x
), tilde ranges (~1.2.3
), and caret ranges (^1.2.3
).
Example: Conditional Logic based on App Version
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-deployment
spec:
replicas: {{ .Values.replicas }}
selector:
matchLabels:
app: {{ .Chart.Name }}
template:
metadata:
labels:
app: {{ .Chart.Name }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image }}:{{ .Values.imageTag }}"
{{- if semverCompare ">= 2.0.0" .Values.appVersion }}
ports:
- containerPort: 8080 # Port for v2.0.0 and above
{{- else }}
ports:
- containerPort: 80 # Default port
{{- end }}
env:
- name: ENVIRONMENT
value: {{ .Values.environment | quote }}
In this example, the ports
section of the container configuration is conditionally defined based on the application version specified in .Values.appVersion
. If the version is 2.0.0 or higher, container port 8080
is used; otherwise, the default port 80
is applied. This demonstrates how Helm template functions for logic and version comparison can create highly adaptable deployments.
Conclusion
Helm template functions are indispensable for creating dynamic, configurable, and maintainable Kubernetes charts. By mastering functions for logic and flow control, string manipulation, and comparisons – especially semantic version comparisons – you can build sophisticated templates that handle diverse deployment scenarios and configurations effectively. This comprehensive function set empowers you to create Helm charts that are not only reusable but also intelligent and adaptable to varying needs and environments.