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