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"]`