github.com/argoproj/argo-cd/v2@v2.10.9/docs/operator-manual/applicationset/Generators-Git.md (about)

     1  # Git Generator
     2  
     3  The Git generator contains two subtypes: the Git directory generator, and Git file generator.
     4  
     5  !!! warning
     6      Git generators are often used to make it easier for (non-admin) developers to create Applications.
     7      If the `project` field in your ApplicationSet is templated, developers may be able to create Applications under Projects with excessive permissions.
     8      For ApplicationSets with a templated `project` field, [the source of truth _must_ be controlled by admins](./Security.md#templated-project-field)
     9      - in the case of git generators, PRs must require admin approval.
    10  
    11  ## Git Generator: Directories
    12  
    13  The Git directory generator, one of two subtypes of the Git generator, generates parameters using the directory structure of a specified Git repository.
    14  
    15  Suppose you have a Git repository with the following directory structure:
    16  ```
    17  ├── argo-workflows
    18  │   ├── kustomization.yaml
    19  │   └── namespace-install.yaml
    20  └── prometheus-operator
    21      ├── Chart.yaml
    22      ├── README.md
    23      ├── requirements.yaml
    24      └── values.yaml
    25  ```
    26  
    27  This repository contains two directories, one for each of the workloads to deploy:
    28  
    29  - an Argo Workflow controller kustomization YAML file
    30  - a Prometheus Operator Helm chart
    31  
    32  We can deploy both workloads, using this example:
    33  ```yaml
    34  apiVersion: argoproj.io/v1alpha1
    35  kind: ApplicationSet
    36  metadata:
    37    name: cluster-addons
    38    namespace: argocd
    39  spec:
    40    goTemplate: true
    41    goTemplateOptions: ["missingkey=error"]
    42    generators:
    43    - git:
    44        repoURL: https://github.com/argoproj/argo-cd.git
    45        revision: HEAD
    46        directories:
    47        - path: applicationset/examples/git-generator-directory/cluster-addons/*
    48    template:
    49      metadata:
    50        name: '{{.path.basename}}'
    51      spec:
    52        project: "my-project"
    53        source:
    54          repoURL: https://github.com/argoproj/argo-cd.git
    55          targetRevision: HEAD
    56          path: '{{.path.path}}'
    57        destination:
    58          server: https://kubernetes.default.svc
    59          namespace: '{{.path.basename}}'
    60        syncPolicy:
    61          syncOptions:
    62          - CreateNamespace=true
    63  ```
    64  (*The full example can be found [here](https://github.com/argoproj/argo-cd/tree/master/applicationset/examples/git-generator-directory).*)
    65  
    66  The generator parameters are:
    67  
    68  - `{{.path.path}}`: The directory paths within the Git repository that match the `path` wildcard.
    69  - `{{index .path.segments n}}`: The directory paths within the Git repository that match the `path` wildcard, split into array elements (`n` - array index)
    70  - `{{.path.basename}}`: For any directory path within the Git repository that matches the `path` wildcard, the right-most path name is extracted (e.g. `/directory/directory2` would produce `directory2`).
    71  - `{{.path.basenameNormalized}}`: This field is the same as `path.basename` with unsupported characters replaced with `-` (e.g. a `path` of `/directory/directory_2`, and `path.basename` of `directory_2` would produce `directory-2` here).
    72  
    73  **Note**: The right-most path name always becomes `{{.path.basename}}`. For example, for `- path: /one/two/three/four`, `{{.path.basename}}` is `four`.
    74  
    75  **Note**: If the `pathParamPrefix` option is specified, all `path`-related parameter names above will be prefixed with the specified value and a dot separator. E.g., if `pathParamPrefix` is `myRepo`, then the generated parameter name would be `.myRepo.path` instead of `.path`. Using this option is necessary in a Matrix generator where both child generators are Git generators (to avoid conflicts when merging the child generators’ items).
    76  
    77  Whenever a new Helm chart/Kustomize YAML/Application/plain subdirectory is added to the Git repository, the ApplicationSet controller will detect this change and automatically deploy the resulting manifests within new `Application` resources.
    78  
    79  As with other generators, clusters *must* already be defined within Argo CD, in order to generate Applications for them.
    80  
    81  ### Exclude directories
    82  
    83  The Git directory generator will automatically exclude directories that begin with `.` (such as `.git`).
    84  
    85  The Git directory generator also supports an `exclude` option in order to exclude directories in the repository from being scanned by the ApplicationSet controller:
    86  
    87  ```yaml
    88  apiVersion: argoproj.io/v1alpha1
    89  kind: ApplicationSet
    90  metadata:
    91    name: cluster-addons
    92    namespace: argocd
    93  spec:
    94    goTemplate: true
    95    goTemplateOptions: ["missingkey=error"]
    96    generators:
    97    - git:
    98        repoURL: https://github.com/argoproj/argo-cd.git
    99        revision: HEAD
   100        directories:
   101        - path: applicationset/examples/git-generator-directory/excludes/cluster-addons/*
   102        - path: applicationset/examples/git-generator-directory/excludes/cluster-addons/exclude-helm-guestbook
   103          exclude: true
   104    template:
   105      metadata:
   106        name: '{{.path.basename}}'
   107      spec:
   108        project: "my-project"
   109        source:
   110          repoURL: https://github.com/argoproj/argo-cd.git
   111          targetRevision: HEAD
   112          path: '{{.path.path}}'
   113        destination:
   114          server: https://kubernetes.default.svc
   115          namespace: '{{.path.basename}}'
   116  ```
   117  (*The full example can be found [here](https://github.com/argoproj/argo-cd/tree/master/applicationset/examples/git-generator-directory/excludes).*)
   118  
   119  This example excludes the `exclude-helm-guestbook` directory from the list of directories scanned for this `ApplicationSet` resource.
   120  
   121  !!! note "Exclude rules have higher priority than include rules"
   122  
   123      If a directory matches at least one `exclude` pattern, it will be excluded. Or, said another way, *exclude rules take precedence over include rules.*
   124  
   125      As a corollary, which directories are included/excluded is not affected by the order of `path`s in the `directories` field list (because, as above, exclude rules always take precedence over include rules). 
   126  
   127  For example, with these directories:
   128  
   129  ```
   130  .
   131  └── d
   132      ├── e
   133      ├── f
   134      └── g
   135  ```
   136  Say you want to include `/d/e`, but exclude `/d/f` and `/d/g`. This will *not* work:
   137  
   138  ```yaml
   139  - path: /d/e
   140    exclude: false
   141  - path: /d/*
   142    exclude: true
   143  ```
   144  Why? Because the exclude `/d/*` exclude rule will take precedence over the `/d/e` include rule. When the `/d/e` path in the Git repository is processed by the ApplicationSet controller, the controller detects that at least one exclude rule is matched, and thus that directory should not be scanned.
   145  
   146  You would instead need to do:
   147  
   148  ```yaml
   149  - path: /d/*
   150  - path: /d/f
   151    exclude: true
   152  - path: /d/g
   153    exclude: true
   154  ```
   155  
   156  Or, a shorter way (using [path.Match](https://golang.org/pkg/path/#Match) syntax) would be:
   157  
   158  ```yaml
   159  - path: /d/*
   160  - path: /d/[fg]
   161    exclude: true
   162  ```
   163  
   164  ### Root Of Git Repo
   165  
   166  The Git directory generator can be configured to deploy from the root of the git repository by providing `'*'` as the `path`.
   167  
   168  To exclude directories, you only need to put the name/[path.Match](https://golang.org/pkg/path/#Match) of the directory you do not want to deploy.
   169  
   170  ```yaml
   171  apiVersion: argoproj.io/v1alpha1
   172  kind: ApplicationSet
   173  metadata:
   174    name: cluster-addons
   175    namespace: argocd
   176  spec:
   177    goTemplate: true
   178    goTemplateOptions: ["missingkey=error"]
   179    generators:
   180    - git:
   181        repoURL: https://github.com/example/example-repo.git
   182        revision: HEAD
   183        directories:
   184        - path: '*'
   185        - path: donotdeploy
   186          exclude: true
   187    template:
   188      metadata:
   189        name: '{{.path.basename}}'
   190      spec:
   191        project: "my-project"
   192        source:
   193          repoURL: https://github.com/example/example-repo.git
   194          targetRevision: HEAD
   195          path: '{{.path.path}}'
   196        destination:
   197          server: https://kubernetes.default.svc
   198          namespace: '{{.path.basename}}'
   199  ```
   200  
   201  ### Pass additional key-value pairs via `values` field
   202  
   203  You may pass additional, arbitrary string key-value pairs via the `values` field of the git directory generator. Values added via the `values` field are added as `values.(field)`.
   204  
   205  In this example, a `cluster` parameter value is passed. It is interpolated from the `branch` and `path` variable, to then be used to determine the destination namespace.
   206  ```yaml
   207  apiVersion: argoproj.io/v1alpha1
   208  kind: ApplicationSet
   209  metadata:
   210    name: cluster-addons
   211    namespace: argocd
   212  spec:
   213    goTemplate: true
   214    goTemplateOptions: ["missingkey=error"]
   215    generators:
   216    - git:
   217        repoURL: https://github.com/example/example-repo.git
   218        revision: HEAD
   219        directories:
   220        - path: '*'
   221        values:
   222          cluster: '{{.branch}}-{{.path.basename}}'
   223    template:
   224      metadata:
   225        name: '{{.path.basename}}'
   226      spec:
   227        project: "my-project"
   228        source:
   229          repoURL: https://github.com/example/example-repo.git
   230          targetRevision: HEAD
   231          path: '{{.path.path}}'
   232        destination:
   233          server: https://kubernetes.default.svc
   234          namespace: '{{.values.cluster}}'
   235  ```
   236  
   237  !!! note
   238      The `values.` prefix is always prepended to values provided via `generators.git.values` field. Ensure you include this prefix in the parameter name within the `template` when using it.
   239  
   240  In `values` we can also interpolate all fields set by the git directory generator as mentioned above.
   241  
   242  ## Git Generator: Files
   243  
   244  The Git file generator is the second subtype of the Git generator. The Git file generator generates parameters using the contents of JSON/YAML files found within a specified repository.
   245  
   246  Suppose you have a Git repository with the following directory structure:
   247  ```
   248  ├── apps
   249  │   └── guestbook
   250  │       ├── guestbook-ui-deployment.yaml
   251  │       ├── guestbook-ui-svc.yaml
   252  │       └── kustomization.yaml
   253  ├── cluster-config
   254  │   └── engineering
   255  │       ├── dev
   256  │       │   └── config.json
   257  │       └── prod
   258  │           └── config.json
   259  └── git-generator-files.yaml
   260  ```
   261  
   262  The directories are:
   263  
   264  - `guestbook` contains the Kubernetes resources for a simple guestbook application
   265  - `cluster-config` contains JSON/YAML files describing the individual engineering clusters: one for `dev` and one for `prod`.
   266  - `git-generator-files.yaml` is the example `ApplicationSet` resource that deploys `guestbook` to the specified clusters.
   267  
   268  The `config.json` files contain information describing the cluster (along with extra sample data):
   269  ```json
   270  {
   271    "aws_account": "123456",
   272    "asset_id": "11223344",
   273    "cluster": {
   274      "owner": "cluster-admin@company.com",
   275      "name": "engineering-dev",
   276      "address": "https://1.2.3.4"
   277    }
   278  }
   279  ```
   280  
   281  Git commits containing changes to the `config.json` files are automatically discovered by the Git generator, and the contents of those files are parsed and converted into template parameters. Here are the parameters generated for the above JSON:
   282  ```text
   283  aws_account: 123456
   284  asset_id: 11223344
   285  cluster.owner: cluster-admin@company.com
   286  cluster.name: engineering-dev
   287  cluster.address: https://1.2.3.4
   288  ```
   289  
   290  
   291  And the generated parameters for all discovered `config.json` files will be substituted into ApplicationSet template:
   292  ```yaml
   293  apiVersion: argoproj.io/v1alpha1
   294  kind: ApplicationSet
   295  metadata:
   296    name: guestbook
   297    namespace: argocd
   298  spec:
   299    goTemplate: true
   300    goTemplateOptions: ["missingkey=error"]
   301    generators:
   302    - git:
   303        repoURL: https://github.com/argoproj/argo-cd.git
   304        revision: HEAD
   305        files:
   306        - path: "applicationset/examples/git-generator-files-discovery/cluster-config/**/config.json"
   307    template:
   308      metadata:
   309        name: '{{.cluster.name}}-guestbook'
   310      spec:
   311        project: default
   312        source:
   313          repoURL: https://github.com/argoproj/argo-cd.git
   314          targetRevision: HEAD
   315          path: "applicationset/examples/git-generator-files-discovery/apps/guestbook"
   316        destination:
   317          server: '{{.cluster.address}}'
   318          namespace: guestbook
   319  ```
   320  (*The full example can be found [here](https://github.com/argoproj/argo-cd/tree/master/applicationset/examples/git-generator-files-discovery).*)
   321  
   322  Any `config.json` files found under the `cluster-config` directory will be parameterized based on the `path` wildcard pattern specified. Within each file JSON fields are flattened into key/value pairs, with this ApplicationSet example using the `cluster.address` and `cluster.name` parameters in the template.
   323  
   324  As with other generators, clusters *must* already be defined within Argo CD, in order to generate Applications for them.
   325  
   326  In addition to the flattened key/value pairs from the configuration file, the following generator parameters are provided:
   327  
   328  - `{{.path.path}}`: The path to the directory containing matching configuration file within the Git repository. Example: `/clusters/clusterA`, if the config file was `/clusters/clusterA/config.json`
   329  - `{{index .path n}}`: The path to the matching configuration file within the Git repository, split into array elements (`n` - array index). Example: `index .path 0: clusters`, `index .path 1: clusterA`
   330  - `{{.path.basename}}`: Basename of the path to the directory containing the configuration file (e.g. `clusterA`, with the above example.)
   331  - `{{.path.basenameNormalized}}`: This field is the same as `.path.basename` with unsupported characters replaced with `-` (e.g. a `path` of `/directory/directory_2`, and `.path.basename` of `directory_2` would produce `directory-2` here).
   332  - `{{.path.filename}}`: The matched filename. e.g., `config.json` in the above example.
   333  - `{{.path.filenameNormalized}}`: The matched filename with unsupported characters replaced with `-`.
   334  
   335  **Note**: The right-most *directory* name always becomes `{{.path.basename}}`. For example, from `- path: /one/two/three/four/config.json`, `{{.path.basename}}` will be `four`. 
   336  The filename can always be accessed using `{{.path.filename}}`. 
   337  
   338  **Note**: If the `pathParamPrefix` option is specified, all `path`-related parameter names above will be prefixed with the specified value and a dot separator. E.g., if `pathParamPrefix` is `myRepo`, then the generated parameter name would be `myRepo.path` instead of `path`. Using this option is necessary in a Matrix generator where both child generators are Git generators (to avoid conflicts when merging the child generators’ items).
   339  
   340  **Note**: The default behavior of the Git file generator is very greedy. Please see [Git File Generator Globbing](./Generators-Git-File-Globbing.md) for more information.
   341  
   342  ### Pass additional key-value pairs via `values` field
   343  
   344  You may pass additional, arbitrary string key-value pairs via the `values` field of the git files generator. Values added via the `values` field are added as `values.(field)`.
   345  
   346  In this example, a `base_dir` parameter value is passed. It is interpolated from `path` segments, to then be used to determine the source path.
   347  ```yaml
   348  apiVersion: argoproj.io/v1alpha1
   349  kind: ApplicationSet
   350  metadata:
   351    name: guestbook
   352    namespace: argocd
   353  spec:
   354    goTemplate: true
   355    goTemplateOptions: ["missingkey=error"]
   356    generators:
   357    - git:
   358        repoURL: https://github.com/argoproj/argo-cd.git
   359        revision: HEAD
   360        files:
   361        - path: "applicationset/examples/git-generator-files-discovery/cluster-config/**/config.json"
   362        values:
   363          base_dir: "{{index .path 0}}/{{index .path 1}}/{{index .path 2}}"
   364    template:
   365      metadata:
   366        name: '{{.cluster.name}}-guestbook'
   367      spec:
   368        project: default
   369        source:
   370          repoURL: https://github.com/argoproj/argo-cd.git
   371          targetRevision: HEAD
   372          path: "{{.values.base_dir}}/apps/guestbook"
   373        destination:
   374          server: '{{.cluster.address}}'
   375          namespace: guestbook
   376  ```
   377  
   378  !!! note
   379      The `values.` prefix is always prepended to values provided via `generators.git.values` field. Ensure you include this prefix in the parameter name within the `template` when using it.
   380  
   381  In `values` we can also interpolate all fields set by the git files generator as mentioned above.
   382  
   383  ## Webhook Configuration
   384  
   385  When using a Git generator, ApplicationSet polls Git repositories every three minutes to detect changes. To eliminate
   386  this delay from polling, the ApplicationSet webhook server can be configured to receive webhook events. ApplicationSet supports
   387  Git webhook notifications from GitHub and GitLab. The following explains how to configure a Git webhook for GitHub, but the same process should be applicable to other providers.
   388  
   389  !!! note
   390      The ApplicationSet controller webhook does not use the same webhook as the API server as defined [here](../webhook.md). ApplicationSet exposes a webhook server as a service of type ClusterIP. An ApplicationSet specific Ingress resource needs to be created to expose this service to the webhook source.
   391  
   392  ### 1. Create the webhook in the Git provider
   393  
   394  In your Git provider, navigate to the settings page where webhooks can be configured. The payload
   395  URL configured in the Git provider should use the `/api/webhook` endpoint of your ApplicationSet instance
   396  (e.g. `https://applicationset.example.com/api/webhook`). If you wish to use a shared secret, input an
   397  arbitrary value in the secret. This value will be used when configuring the webhook in the next step.
   398  
   399  ![Add Webhook](../../assets/applicationset/webhook-config.png "Add Webhook")
   400  
   401  !!! note
   402      When creating the webhook in GitHub, the "Content type" needs to be set to "application/json". The default value "application/x-www-form-urlencoded" is not supported by the library used to handle the hooks
   403  
   404  ### 2. Configure ApplicationSet with the webhook secret (Optional)
   405  
   406  Configuring a webhook shared secret is optional, since ApplicationSet will still refresh applications
   407  generated by Git generators, even with unauthenticated webhook events. This is safe to do since
   408  the contents of webhook payloads are considered untrusted, and will only result in a refresh of the
   409  application (a process which already occurs at three-minute intervals). If ApplicationSet is publicly
   410  accessible, then configuring a webhook secret is recommended to prevent a DDoS attack.
   411  
   412  In the `argocd-secret` Kubernetes secret, include the Git provider's webhook secret configured in step 1.
   413  
   414  Edit the Argo CD Kubernetes secret:
   415  
   416  ```bash
   417  kubectl edit secret argocd-secret -n argocd
   418  ```
   419  
   420  TIP: for ease of entering secrets, Kubernetes supports inputting secrets in the `stringData` field,
   421  which saves you the trouble of base64 encoding the values and copying it to the `data` field.
   422  Simply copy the shared webhook secret created in step 1, to the corresponding
   423  GitHub/GitLab/BitBucket key under the `stringData` field:
   424  
   425  ```yaml
   426  apiVersion: v1
   427  kind: Secret
   428  metadata:
   429    name: argocd-secret
   430    namespace: argocd
   431  type: Opaque
   432  data:
   433  ...
   434  
   435  stringData:
   436    # github webhook secret
   437    webhook.github.secret: shhhh! it's a github secret
   438  
   439    # gitlab webhook secret
   440    webhook.gitlab.secret: shhhh! it's a gitlab secret
   441  ```
   442  
   443  After saving, please restart the ApplicationSet pod for the changes to take effect.