Go Template
Introduction
ApplicationSet is able to use Go Text Template. To activate this feature, add goTemplate: true to your ApplicationSet manifest.
The Sprig function library (except for env, expandenv and getHostByName) is available in addition to the default Go Text Template functions.
An additional normalize function makes any string parameter usable as a valid DNS name by replacing invalid characters with hyphens and truncating at 253 characters. This is useful when making parameters safe for things like Application names.
If you want to customize options defined by text/template, you can add the goTemplateOptions: ["opt1", "opt2", ...] key to your ApplicationSet next to goTemplate: true. Note that at the time of writing, there is only one useful option defined, which is missingkey=error.
The recommended setting of goTemplateOptions is ["missingkey=error"], which ensures that if undefined values are looked up by your template then an error is reported instead of being ignored silently. This is not currently the default behavior, for backwards compatibility.
Motivation
Go Template is the Go Standard for string templating. It is also more powerful than fasttemplate (the default templating engine) as it allows doing complex templating logic.
Limitations
Go templates are applied on a per-field basis, and only on string fields. Here are some examples of what is not possible with Go text templates:
Templating a boolean field.
apiVersion: argoproj.io/v1alpha1kind: ApplicationSetspec:goTemplate: truegoTemplateOptions: ["missingkey=error"]template:spec:source:helm:useCredentials: "{{.useCredentials}}" # This field may NOT be templated, because it is a boolean field.
Templating an object field:
apiVersion: argoproj.io/v1alpha1kind: ApplicationSetspec:goTemplate: truegoTemplateOptions: ["missingkey=error"]template:spec:syncPolicy: "{{.syncPolicy}}" # This field may NOT be templated, because it is an object field.
Using control keywords across fields:
apiVersion: argoproj.io/v1alpha1kind: ApplicationSetspec:goTemplate: truegoTemplateOptions: ["missingkey=error"]template:spec:source:helm:parameters:# Each of these fields is evaluated as an independent template, so the first one will fail with an error.- name: "{{range .parameters}}"- name: "{{.name}}"value: "{{.value}}"- name: throw-awayvalue: "{{end}}"
Migration guide
Globals
All your templates must replace parameters with GoTemplate Syntax:
Example: {{ some.value }} becomes {{ .some.value }}
Cluster Generators
By activating Go Templating, {{ .metadata }} becomes an object.
{{ metadata.labels.my-label }}becomes{{ index .metadata.labels "my-label" }}{{ metadata.annotations.my/annotation }}becomes{{ index .metadata.annotations "my/annotation" }}
Git Generators
By activating Go Templating, {{ .path }} becomes an object. Therefore, some changes must be made to the Git generators’ templating:
{{ path }}becomes{{ .path.path }}{{ path.basename }}becomes{{ .path.basename }}{{ path.basenameNormalized }}becomes{{ .path.basenameNormalized }}{{ path.filename }}becomes{{ .path.filename }}{{ path.filenameNormalized }}becomes{{ .path.filenameNormalized }}{{ path[n] }}becomes{{ index .path.segments n }}{{ values }}if being used in the file generator becomes{{ .values }}
Here is an example:
apiVersion: argoproj.io/v1alpha1kind: ApplicationSetmetadata:name: cluster-addonsspec:generators:- git:repoURL: https://github.com/argoproj/argo-cd.gitrevision: HEADdirectories:- path: applicationset/examples/git-generator-directory/cluster-addons/*template:metadata:name: '{{path.basename}}'spec:project: defaultsource:repoURL: https://github.com/argoproj/argo-cd.gittargetRevision: HEADpath: '{{path}}'destination:server: https://kubernetes.default.svcnamespace: '{{path.basename}}'
becomes
apiVersion: argoproj.io/v1alpha1kind: ApplicationSetmetadata:name: cluster-addonsspec:goTemplate: truegoTemplateOptions: ["missingkey=error"]generators:- git:repoURL: https://github.com/argoproj/argo-cd.gitrevision: HEADdirectories:- path: applicationset/examples/git-generator-directory/cluster-addons/*template:metadata:name: '{{.path.basename}}'spec:project: defaultsource:repoURL: https://github.com/argoproj/argo-cd.gittargetRevision: HEADpath: '{{.path.path}}'destination:server: https://kubernetes.default.svcnamespace: '{{.path.basename}}'
It is also possible to use Sprig functions to construct the path variables manually:
with goTemplate: false | with goTemplate: true | with goTemplate: true + Sprig |
|---|---|---|
{{path}} | {{.path.path}} | {{.path.path}} |
{{path.basename}} | {{.path.basename}} | {{base .path.path}} |
{{path.filename}} | {{.path.filename}} | {{.path.filename}} |
{{path.basenameNormalized}} | {{.path.basenameNormalized}} | {{normalize .path.path}} |
{{path.filenameNormalized}} | {{.path.filenameNormalized}} | {{normalize .path.filename}} |
{{path[N]}} | - | {{index .path.segments N}} |
Available template functions
ApplicationSet controller provides:
- all sprig Go templates function except
env,expandenvandgetHostByName normalize: sanitizes the input so that it complies with the following rules:- contains no more than 253 characters
- contains only lowercase alphanumeric characters, ‘-‘ or ‘.’
- starts and ends with an alphanumeric character
toYaml/fromYaml/fromYamlArrayhelm like functions
Examples
Basic Go template usage
This example shows basic string parameter substitution.
apiVersion: argoproj.io/v1alpha1kind: ApplicationSetmetadata:name: guestbookspec:goTemplate: truegoTemplateOptions: ["missingkey=error"]generators:- list:elements:- cluster: engineering-devurl: https://1.2.3.4- cluster: engineering-produrl: https://2.4.6.8- cluster: finance-preprodurl: https://9.8.7.6template:metadata:name: '{{.cluster}}-guestbook'spec:project: my-projectsource:repoURL: https://github.com/infra-team/cluster-deployments.gittargetRevision: HEADpath: guestbook/{{.cluster}}destination:server: '{{.url}}'namespace: guestbook
Fallbacks for unset parameters
For some generators, a parameter of a certain name might not always be populated (for example, with the values generator or the git files generator). In these cases, you can use a Go template to provide a fallback value.
apiVersion: argoproj.io/v1alpha1kind: ApplicationSetmetadata:name: guestbookspec:goTemplate: truegoTemplateOptions: ["missingkey=error"]generators:- list:elements:- cluster: engineering-devurl: https://kubernetes.default.svc- cluster: engineering-produrl: https://kubernetes.default.svcnameSuffix: -my-name-suffixtemplate:metadata:name: '{{.cluster}}{{dig "nameSuffix" "" .}}'spec:project: defaultsource:repoURL: https://github.com/argoproj/argo-cd.gittargetRevision: HEADpath: applicationset/examples/list-generator/guestbook/{{.cluster}}destination:server: '{{.url}}'namespace: guestbook
This ApplicationSet will produce an Application called engineering-dev and another called engineering-prod-my-name-suffix.
Note that unset parameters are an error, so you need to avoid looking up a property that doesn’t exist. Instead, use template functions like dig to do the lookup with a default. If you prefer to have unset parameters default to zero, you can remove goTemplateOptions: ["missingkey=error"] or set it to goTemplateOptions: ["missingkey=invalid"]