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