github.com/argoproj/argo-cd/v3@v3.2.1/docs/operator-manual/applicationset/GoTemplate.md (about) 1 # Go Template 2 3 ## Introduction 4 5 ApplicationSet is able to use [Go Text Template](https://pkg.go.dev/text/template). To activate this feature, add 6 `goTemplate: true` to your ApplicationSet manifest. 7 8 The [Sprig function library](https://masterminds.github.io/sprig/) (except for `env`, `expandenv` and `getHostByName`) 9 is available in addition to the default Go Text Template functions. 10 11 An additional `normalize` function makes any string parameter usable as a valid DNS name by replacing invalid characters 12 with hyphens and truncating at 253 characters. This is useful when making parameters safe for things like Application 13 names. 14 15 Another `slugify` function has been added which, by default, sanitizes and smart truncates (it doesn't cut a word into 2). This function accepts a couple of arguments: 16 17 - The first argument (if provided) is an integer specifying the maximum length of the slug. 18 - The second argument (if provided) is a boolean indicating whether smart truncation is enabled. 19 - The last argument (if provided) is the input name that needs to be slugified. 20 21 #### Usage example 22 23 ``` 24 apiVersion: argoproj.io/v1alpha1 25 kind: ApplicationSet 26 metadata: 27 name: test-appset 28 spec: 29 ... 30 template: 31 metadata: 32 name: 'hellos3-{{.name}}-{{ cat .branch | slugify 23 }}' 33 annotations: 34 label-1: '{{ cat .branch | slugify }}' 35 label-2: '{{ cat .branch | slugify 23 }}' 36 label-3: '{{ cat .branch | slugify 50 false }}' 37 ``` 38 39 If you want to customize [options defined by text/template](https://pkg.go.dev/text/template#Template.Option), you can 40 add the `goTemplateOptions: ["opt1", "opt2", ...]` key to your ApplicationSet next to `goTemplate: true`. Note that at 41 the time of writing, there is only one useful option defined, which is `missingkey=error`. 42 43 The recommended setting of `goTemplateOptions` is `["missingkey=error"]`, which ensures that if undefined values are 44 looked up by your template then an error is reported instead of being ignored silently. This is not currently the default 45 behavior, for backwards compatibility. 46 47 ## Motivation 48 49 Go Template is the Go Standard for string templating. It is also more powerful than fasttemplate (the default templating 50 engine) as it allows doing complex templating logic. 51 52 ## Limitations 53 54 Go templates are applied on a per-field basis, and only on string fields. Here are some examples of what is **not** 55 possible with Go text templates: 56 57 - Templating a boolean field. 58 59 ::yaml 60 apiVersion: argoproj.io/v1alpha1 61 kind: ApplicationSet 62 spec: 63 goTemplate: true 64 goTemplateOptions: ["missingkey=error"] 65 template: 66 spec: 67 source: 68 helm: 69 useCredentials: "{{.useCredentials}}" # This field may NOT be templated, because it is a boolean field. 70 71 - Templating an object field: 72 73 ::yaml 74 apiVersion: argoproj.io/v1alpha1 75 kind: ApplicationSet 76 spec: 77 goTemplate: true 78 goTemplateOptions: ["missingkey=error"] 79 template: 80 spec: 81 syncPolicy: "{{.syncPolicy}}" # This field may NOT be templated, because it is an object field. 82 83 - Using control keywords across fields: 84 85 ::yaml 86 apiVersion: argoproj.io/v1alpha1 87 kind: ApplicationSet 88 spec: 89 goTemplate: true 90 goTemplateOptions: ["missingkey=error"] 91 template: 92 spec: 93 source: 94 helm: 95 parameters: 96 # Each of these fields is evaluated as an independent template, so the first one will fail with an error. 97 - name: "{{range .parameters}}" 98 - name: "{{.name}}" 99 value: "{{.value}}" 100 - name: throw-away 101 value: "{{end}}" 102 103 - Signature verification is not supported for the templated `project` field when using the Git generator. 104 105 ::yaml 106 apiVersion: argoproj.io/v1alpha1 107 kind: ApplicationSet 108 spec: 109 goTemplate: true 110 template: 111 spec: 112 project: {{.project}} 113 114 115 ## Migration guide 116 117 ### Globals 118 119 All your templates must replace parameters with GoTemplate Syntax: 120 121 Example: `{{ some.value }}` becomes `{{ .some.value }}` 122 123 ### Cluster Generators 124 125 By activating Go Templating, `{{ .metadata }}` becomes an object. 126 127 - `{{ metadata.labels.my-label }}` becomes `{{ index .metadata.labels "my-label" }}` 128 - `{{ metadata.annotations.my/annotation }}` becomes `{{ index .metadata.annotations "my/annotation" }}` 129 130 ### Git Generators 131 132 By activating Go Templating, `{{ .path }}` becomes an object. Therefore, some changes must be made to the Git 133 generators' templating: 134 135 - `{{ path }}` becomes `{{ .path.path }}` 136 - `{{ path.basename }}` becomes `{{ .path.basename }}` 137 - `{{ path.basenameNormalized }}` becomes `{{ .path.basenameNormalized }}` 138 - `{{ path.filename }}` becomes `{{ .path.filename }}` 139 - `{{ path.filenameNormalized }}` becomes `{{ .path.filenameNormalized }}` 140 - `{{ path[n] }}` becomes `{{ index .path.segments n }}` 141 - `{{ values }}` if being used in the file generator becomes `{{ .values }}` 142 143 Here is an example: 144 145 ```yaml 146 apiVersion: argoproj.io/v1alpha1 147 kind: ApplicationSet 148 metadata: 149 name: cluster-addons 150 spec: 151 generators: 152 - git: 153 repoURL: https://github.com/argoproj/argo-cd.git 154 revision: HEAD 155 directories: 156 - path: applicationset/examples/git-generator-directory/cluster-addons/* 157 template: 158 metadata: 159 name: '{{path.basename}}' 160 spec: 161 project: default 162 source: 163 repoURL: https://github.com/argoproj/argo-cd.git 164 targetRevision: HEAD 165 path: '{{path}}' 166 destination: 167 server: https://kubernetes.default.svc 168 namespace: '{{path.basename}}' 169 ``` 170 171 becomes 172 173 ```yaml 174 apiVersion: argoproj.io/v1alpha1 175 kind: ApplicationSet 176 metadata: 177 name: cluster-addons 178 spec: 179 goTemplate: true 180 goTemplateOptions: ["missingkey=error"] 181 generators: 182 - git: 183 repoURL: https://github.com/argoproj/argo-cd.git 184 revision: HEAD 185 directories: 186 - path: applicationset/examples/git-generator-directory/cluster-addons/* 187 template: 188 metadata: 189 name: '{{.path.basename}}' 190 spec: 191 project: default 192 source: 193 repoURL: https://github.com/argoproj/argo-cd.git 194 targetRevision: HEAD 195 path: '{{.path.path}}' 196 destination: 197 server: https://kubernetes.default.svc 198 namespace: '{{.path.basename}}' 199 ``` 200 201 It is also possible to use Sprig functions to construct the path variables manually: 202 203 | with `goTemplate: false` | with `goTemplate: true` | with `goTemplate: true` + Sprig | 204 | ------------ | ----------- | --------------------- | 205 | `{{path}}` | `{{.path.path}}` | `{{.path.path}}` | 206 | `{{path.basename}}` | `{{.path.basename}}` | `{{base .path.path}}` | 207 | `{{path.filename}}` | `{{.path.filename}}` | `{{.path.filename}}` | 208 | `{{path.basenameNormalized}}` | `{{.path.basenameNormalized}}` | `{{normalize .path.path}}` | 209 | `{{path.filenameNormalized}}` | `{{.path.filenameNormalized}}` | `{{normalize .path.filename}}` | 210 | `{{path[N]}}` | `-` | `{{index .path.segments N}}` | 211 212 ## Available template functions 213 214 ApplicationSet controller provides: 215 216 - all [sprig](http://masterminds.github.io/sprig/) Go templates function except `env`, `expandenv` and `getHostByName` 217 - `normalize`: sanitizes the input so that it complies with the following rules: 218 1. contains no more than 253 characters 219 2. contains only lowercase alphanumeric characters, '-' or '.' 220 3. starts and ends with an alphanumeric character 221 222 - `slugify`: sanitizes like `normalize` and smart truncates (it doesn't cut a word into 2) like described in the [introduction](#introduction) section. 223 - `toYaml` / `fromYaml` / `fromYamlArray` helm like functions 224 225 226 ## Examples 227 228 ### Basic Go template usage 229 230 This example shows basic string parameter substitution. 231 232 ```yaml 233 apiVersion: argoproj.io/v1alpha1 234 kind: ApplicationSet 235 metadata: 236 name: guestbook 237 spec: 238 goTemplate: true 239 goTemplateOptions: ["missingkey=error"] 240 generators: 241 - list: 242 elements: 243 - cluster: engineering-dev 244 url: https://1.2.3.4 245 - cluster: engineering-prod 246 url: https://2.4.6.8 247 - cluster: finance-preprod 248 url: https://9.8.7.6 249 template: 250 metadata: 251 name: '{{.cluster}}-guestbook' 252 spec: 253 project: my-project 254 source: 255 repoURL: https://github.com/infra-team/cluster-deployments.git 256 targetRevision: HEAD 257 path: guestbook/{{.cluster}} 258 destination: 259 server: '{{.url}}' 260 namespace: guestbook 261 ``` 262 263 ### Fallbacks for unset parameters 264 265 For some generators, a parameter of a certain name might not always be populated (for example, with the values generator 266 or the git files generator). In these cases, you can use a Go template to provide a fallback value. 267 268 ```yaml 269 apiVersion: argoproj.io/v1alpha1 270 kind: ApplicationSet 271 metadata: 272 name: guestbook 273 spec: 274 goTemplate: true 275 goTemplateOptions: ["missingkey=error"] 276 generators: 277 - list: 278 elements: 279 - cluster: engineering-dev 280 url: https://kubernetes.default.svc 281 - cluster: engineering-prod 282 url: https://kubernetes.default.svc 283 nameSuffix: -my-name-suffix 284 template: 285 metadata: 286 name: '{{.cluster}}{{dig "nameSuffix" "" .}}' 287 spec: 288 project: default 289 source: 290 repoURL: https://github.com/argoproj/argo-cd.git 291 targetRevision: HEAD 292 path: applicationset/examples/list-generator/guestbook/{{.cluster}} 293 destination: 294 server: '{{.url}}' 295 namespace: guestbook 296 ``` 297 298 This ApplicationSet will produce an Application called `engineering-dev` and another called 299 `engineering-prod-my-name-suffix`. 300 301 Note that unset parameters are an error, so you need to avoid looking up a property that doesn't exist. Instead, use 302 template functions like `dig` to do the lookup with a default. If you prefer to have unset parameters default to zero, 303 you can remove `goTemplateOptions: ["missingkey=error"]` or set it to `goTemplateOptions: ["missingkey=invalid"]`