github.com/argoproj/argo-cd/v3@v3.2.1/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      - Git generator does not support Signature Verification For ApplicationSets with a templated `project` field.
    11      - You must only use "non-scoped" repositories for ApplicationSets with a templated `project` field (see ["Repository Credentials for Applicationsets" below](#repository-credentials-for-applicationsets)).
    12      
    13  
    14  ## Git Generator: Directories
    15  
    16  The Git directory generator, one of two subtypes of the Git generator, generates parameters using the directory structure of a specified Git repository.
    17  
    18  Suppose you have a Git repository with the following directory structure:
    19  ```
    20  ├── argo-workflows
    21  │   ├── kustomization.yaml
    22  │   └── namespace-install.yaml
    23  └── prometheus-operator
    24      ├── Chart.yaml
    25      ├── README.md
    26      ├── requirements.yaml
    27      └── values.yaml
    28  ```
    29  
    30  This repository contains two directories, one for each of the workloads to deploy:
    31  
    32  - an Argo Workflow controller kustomization YAML file
    33  - a Prometheus Operator Helm chart
    34  
    35  We can deploy both workloads, using this example:
    36  ```yaml
    37  apiVersion: argoproj.io/v1alpha1
    38  kind: ApplicationSet
    39  metadata:
    40    name: cluster-addons
    41    namespace: argocd
    42  spec:
    43    goTemplate: true
    44    goTemplateOptions: ["missingkey=error"]
    45    generators:
    46    - git:
    47        repoURL: https://github.com/argoproj/argo-cd.git
    48        revision: HEAD
    49        directories:
    50        - path: applicationset/examples/git-generator-directory/cluster-addons/*
    51    template:
    52      metadata:
    53        name: '{{.path.basename}}'
    54      spec:
    55        project: "my-project"
    56        source:
    57          repoURL: https://github.com/argoproj/argo-cd.git
    58          targetRevision: HEAD
    59          path: '{{.path.path}}'
    60        destination:
    61          server: https://kubernetes.default.svc
    62          namespace: '{{.path.basename}}'
    63        syncPolicy:
    64          syncOptions:
    65          - CreateNamespace=true
    66  ```
    67  (*The full example can be found [here](https://github.com/argoproj/argo-cd/tree/master/applicationset/examples/git-generator-directory).*)
    68  
    69  The generator parameters are:
    70  
    71  - `{{.path.path}}`: The directory paths within the Git repository that match the `path` wildcard.
    72  - `{{index .path.segments n}}`: The directory paths within the Git repository that match the `path` wildcard, split into array elements (`n` - array index)
    73  - `{{.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`).
    74  - `{{.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).
    75  
    76  **Note**: The right-most path name always becomes `{{.path.basename}}`. For example, for `- path: /one/two/three/four`, `{{.path.basename}}` is `four`.
    77  
    78  **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).
    79  
    80  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.
    81  
    82  As with other generators, clusters *must* already be defined within Argo CD, in order to generate Applications for them.
    83  
    84  ### Exclude directories
    85  
    86  The Git directory generator will automatically exclude directories that begin with `.` (such as `.git`).
    87  
    88  The Git directory generator also supports an `exclude` option in order to exclude directories in the repository from being scanned by the ApplicationSet controller:
    89  
    90  ```yaml
    91  apiVersion: argoproj.io/v1alpha1
    92  kind: ApplicationSet
    93  metadata:
    94    name: cluster-addons
    95    namespace: argocd
    96  spec:
    97    goTemplate: true
    98    goTemplateOptions: ["missingkey=error"]
    99    generators:
   100    - git:
   101        repoURL: https://github.com/argoproj/argo-cd.git
   102        revision: HEAD
   103        directories:
   104        - path: applicationset/examples/git-generator-directory/excludes/cluster-addons/*
   105        - path: applicationset/examples/git-generator-directory/excludes/cluster-addons/exclude-helm-guestbook
   106          exclude: true
   107    template:
   108      metadata:
   109        name: '{{.path.basename}}'
   110      spec:
   111        project: "my-project"
   112        source:
   113          repoURL: https://github.com/argoproj/argo-cd.git
   114          targetRevision: HEAD
   115          path: '{{.path.path}}'
   116        destination:
   117          server: https://kubernetes.default.svc
   118          namespace: '{{.path.basename}}'
   119  ```
   120  (*The full example can be found [here](https://github.com/argoproj/argo-cd/tree/master/applicationset/examples/git-generator-directory/excludes).*)
   121  
   122  This example excludes the `exclude-helm-guestbook` directory from the list of directories scanned for this `ApplicationSet` resource.
   123  
   124  !!! note "Exclude rules have higher priority than include rules"
   125  
   126      If a directory matches at least one `exclude` pattern, it will be excluded. Or, said another way, *exclude rules take precedence over include rules.*
   127  
   128      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). 
   129  
   130  For example, with these directories:
   131  
   132  ```
   133  .
   134  └── d
   135      ├── e
   136      ├── f
   137      └── g
   138  ```
   139  Say you want to include `/d/e`, but exclude `/d/f` and `/d/g`. This will *not* work:
   140  
   141  ```yaml
   142  - path: /d/e
   143    exclude: false
   144  - path: /d/*
   145    exclude: true
   146  ```
   147  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.
   148  
   149  You would instead need to do:
   150  
   151  ```yaml
   152  - path: /d/*
   153  - path: /d/f
   154    exclude: true
   155  - path: /d/g
   156    exclude: true
   157  ```
   158  
   159  Or, a shorter way (using [path.Match](https://golang.org/pkg/path/#Match) syntax) would be:
   160  
   161  ```yaml
   162  - path: /d/*
   163  - path: /d/[fg]
   164    exclude: true
   165  ```
   166  
   167  ### Root Of Git Repo
   168  
   169  The Git directory generator can be configured to deploy from the root of the git repository by providing `'*'` as the `path`.
   170  
   171  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.
   172  
   173  ```yaml
   174  apiVersion: argoproj.io/v1alpha1
   175  kind: ApplicationSet
   176  metadata:
   177    name: cluster-addons
   178    namespace: argocd
   179  spec:
   180    goTemplate: true
   181    goTemplateOptions: ["missingkey=error"]
   182    generators:
   183    - git:
   184        repoURL: https://github.com/example/example-repo.git
   185        revision: HEAD
   186        directories:
   187        - path: '*'
   188        - path: donotdeploy
   189          exclude: true
   190    template:
   191      metadata:
   192        name: '{{.path.basename}}'
   193      spec:
   194        project: "my-project"
   195        source:
   196          repoURL: https://github.com/example/example-repo.git
   197          targetRevision: HEAD
   198          path: '{{.path.path}}'
   199        destination:
   200          server: https://kubernetes.default.svc
   201          namespace: '{{.path.basename}}'
   202  ```
   203  
   204  ### Pass additional key-value pairs via `values` field
   205  
   206  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)`.
   207  
   208  In this example, a `cluster` parameter value is passed. It is interpolated from the `path` variable, to then be used to determine the destination namespace.
   209  ```yaml
   210  apiVersion: argoproj.io/v1alpha1
   211  kind: ApplicationSet
   212  metadata:
   213    name: cluster-addons
   214    namespace: argocd
   215  spec:
   216    goTemplate: true
   217    goTemplateOptions: ["missingkey=error"]
   218    generators:
   219    - git:
   220        repoURL: https://github.com/example/example-repo.git
   221        revision: HEAD
   222        directories:
   223        - path: '*'
   224        values:
   225          cluster: '{{.path.basename}}'
   226    template:
   227      metadata:
   228        name: '{{.path.basename}}'
   229      spec:
   230        project: "my-project"
   231        source:
   232          repoURL: https://github.com/example/example-repo.git
   233          targetRevision: HEAD
   234          path: '{{.path.path}}'
   235        destination:
   236          server: https://kubernetes.default.svc
   237          namespace: '{{.values.cluster}}'
   238  ```
   239  
   240  !!! note
   241      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.
   242  
   243  In `values` we can also interpolate all fields set by the git directory generator as mentioned above.
   244  
   245  ## Git Generator: Files
   246  
   247  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.
   248  
   249  Suppose you have a Git repository with the following directory structure:
   250  ```
   251  ├── apps
   252  │   └── guestbook
   253  │       ├── guestbook-ui-deployment.yaml
   254  │       ├── guestbook-ui-svc.yaml
   255  │       └── kustomization.yaml
   256  ├── cluster-config
   257  │   └── engineering
   258  │       ├── dev
   259  │       │   └── config.json
   260  │       └── prod
   261  │           └── config.json
   262  └── git-generator-files.yaml
   263  ```
   264  
   265  The directories are:
   266  
   267  - `guestbook` contains the Kubernetes resources for a simple guestbook application
   268  - `cluster-config` contains JSON/YAML files describing the individual engineering clusters: one for `dev` and one for `prod`.
   269  - `git-generator-files.yaml` is the example `ApplicationSet` resource that deploys `guestbook` to the specified clusters.
   270  
   271  The `config.json` files contain information describing the cluster (along with extra sample data):
   272  ```json
   273  {
   274    "aws_account": "123456",
   275    "asset_id": "11223344",
   276    "cluster": {
   277      "owner": "cluster-admin@company.com",
   278      "name": "engineering-dev",
   279      "address": "https://1.2.3.4"
   280    }
   281  }
   282  ```
   283  
   284  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:
   285  ```text
   286  aws_account: 123456
   287  asset_id: 11223344
   288  cluster.owner: cluster-admin@company.com
   289  cluster.name: engineering-dev
   290  cluster.address: https://1.2.3.4
   291  ```
   292  
   293  
   294  And the generated parameters for all discovered `config.json` files will be substituted into ApplicationSet template:
   295  ```yaml
   296  apiVersion: argoproj.io/v1alpha1
   297  kind: ApplicationSet
   298  metadata:
   299    name: guestbook
   300    namespace: argocd
   301  spec:
   302    goTemplate: true
   303    goTemplateOptions: ["missingkey=error"]
   304    generators:
   305    - git:
   306        repoURL: https://github.com/argoproj/argo-cd.git
   307        revision: HEAD
   308        files:
   309        - path: "applicationset/examples/git-generator-files-discovery/cluster-config/**/config.json"
   310    template:
   311      metadata:
   312        name: '{{.cluster.name}}-guestbook'
   313      spec:
   314        project: default
   315        source:
   316          repoURL: https://github.com/argoproj/argo-cd.git
   317          targetRevision: HEAD
   318          path: "applicationset/examples/git-generator-files-discovery/apps/guestbook"
   319        destination:
   320          server: '{{.cluster.address}}'
   321          namespace: guestbook
   322  ```
   323  (*The full example can be found [here](https://github.com/argoproj/argo-cd/tree/master/applicationset/examples/git-generator-files-discovery).*)
   324  
   325  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.
   326  
   327  As with other generators, clusters *must* already be defined within Argo CD, in order to generate Applications for them.
   328  
   329  In addition to the flattened key/value pairs from the configuration file, the following generator parameters are provided:
   330  
   331  - `{{.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`
   332  - `{{index .path.segments n}}`: The path to the matching configuration file within the Git repository, split into array elements (`n` - array index). Example: `index .path.segments 0: clusters`, `index .path.segments 1: clusterA`
   333  - `{{.path.basename}}`: Basename of the path to the directory containing the configuration file (e.g. `clusterA`, with the above example.)
   334  - `{{.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).
   335  - `{{.path.filename}}`: The matched filename. e.g., `config.json` in the above example.
   336  - `{{.path.filenameNormalized}}`: The matched filename with unsupported characters replaced with `-`.
   337  
   338  **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`. 
   339  The filename can always be accessed using `{{.path.filename}}`. 
   340  
   341  **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).
   342  
   343  **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.
   344  
   345  ### Exclude files
   346  
   347  The Git file generator also supports an `exclude` option in order to exclude files in the repository from being scanned by the ApplicationSet controller:
   348  
   349  ```yaml
   350  apiVersion: argoproj.io/v1alpha1
   351  kind: ApplicationSet
   352  metadata:
   353    name: guestbook
   354  spec:
   355    goTemplate: true
   356    goTemplateOptions: ["missingkey=error"]
   357    generators:
   358      - git:
   359          repoURL: https://github.com/argoproj/argo-cd.git
   360          revision: HEAD
   361          files:
   362            - path: "applicationset/examples/git-generator-files-discovery/cluster-config/**/config.json"
   363            - path: "applicationset/examples/git-generator-files-discovery/cluster-config/*/dev/config.json"
   364              exclude: true
   365    template:
   366      metadata:
   367        name: '{{.cluster.name}}-guestbook'
   368      spec:
   369        project: default
   370        source:
   371          repoURL: https://github.com/argoproj/argo-cd.git
   372          targetRevision: HEAD
   373          path: "applicationset/examples/git-generator-files-discovery/apps/guestbook"
   374        destination:
   375          server: https://kubernetes.default.svc
   376          #server: '{{.cluster.address}}'
   377          namespace: guestbook
   378  ```
   379  
   380  This example excludes the `config.json` file in the `dev` directory from the list of files scanned for this `ApplicationSet` resource.
   381  
   382  (*The full example can be found [here](https://github.com/argoproj/argo-cd/tree/master/applicationset/examples/git-generator-files-discovery/excludes).*)
   383  
   384  ### Pass additional key-value pairs via `values` field
   385  
   386  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)`.
   387  
   388  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.
   389  ```yaml
   390  apiVersion: argoproj.io/v1alpha1
   391  kind: ApplicationSet
   392  metadata:
   393    name: guestbook
   394    namespace: argocd
   395  spec:
   396    goTemplate: true
   397    goTemplateOptions: ["missingkey=error"]
   398    generators:
   399    - git:
   400        repoURL: https://github.com/argoproj/argo-cd.git
   401        revision: HEAD
   402        files:
   403        - path: "applicationset/examples/git-generator-files-discovery/cluster-config/**/config.json"
   404        values:
   405          base_dir: "{{index .path.segments 0}}/{{index .path.segments 1}}/{{index .path.segments 2}}"
   406    template:
   407      metadata:
   408        name: '{{.cluster.name}}-guestbook'
   409      spec:
   410        project: default
   411        source:
   412          repoURL: https://github.com/argoproj/argo-cd.git
   413          targetRevision: HEAD
   414          path: "{{.values.base_dir}}/apps/guestbook"
   415        destination:
   416          server: '{{.cluster.address}}'
   417          namespace: guestbook
   418  ```
   419  
   420  !!! note
   421      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.
   422  
   423  In `values` we can also interpolate all fields set by the git files generator as mentioned above.
   424  
   425  ## Git Polling Interval
   426  
   427  When using a Git generator, the ApplicationSet controller polls Git
   428  repositories, by default, every 3 minutes to detect changes, unless
   429  different default value is set by the
   430  `ARGOCD_APPLICATIONSET_CONTROLLER_REQUEUE_AFTER` environment variable.
   431  You can customize this interval per ApplicationSet using
   432  `requeueAfterSeconds`.
   433  
   434  !!!note
   435      The Git generator uses the ArgoCD Repo Server to retrieve file
   436      and directory lists from Git. Therefore, the Git generator is
   437      affected by the Repo Server's Revision Cache Expiration setting
   438      (see the description of the `timeout.reconciliation` parameter in
   439      [argocd-cm.yaml](../argocd-cm-yaml.md/#:~:text=timeout.reconciliation%3A)).
   440      If this value exceeds the configured Git Polling Interval, the
   441      Git generator might not see files or directories from new commits
   442      until the previous cache entry expires.
   443   
   444  ## The `argocd.argoproj.io/application-set-refresh` Annotation
   445  
   446  Setting the `argocd.argoproj.io/application-set-refresh` annotation
   447  (to any value) triggers an ApplicationSet refresh. This annotation
   448  forces the Git provider to resolve Git references directly, bypassing
   449  the Revision Cache. The ApplicationSet controller removes this
   450  annotation after reconciliation.
   451  
   452  ## Webhook Configuration
   453  
   454  To eliminate the polling delay, the ApplicationSet webhook
   455  server can be configured to receive webhook events. ApplicationSet
   456  supports Git webhook notifications from GitHub and GitLab. The
   457  following explains how to configure a Git webhook for GitHub, but the
   458  same process should be applicable to other providers.
   459  
   460  ```yaml
   461  apiVersion: argoproj.io/v1alpha1
   462  kind: ApplicationSet
   463  metadata:
   464    name: guestbook
   465    namespace: argocd
   466  spec:
   467    goTemplate: true
   468    goTemplateOptions: ["missingkey=error"]
   469    generators:
   470    - git:
   471        # When using a Git generator, the ApplicationSet controller polls every `requeueAfterSeconds` interval (defaulting to every 3 minutes) to detect changes.
   472        requeueAfterSeconds: 180
   473        repoURL: https://github.com/argoproj/argo-cd.git
   474        revision: HEAD
   475        # ...
   476  ```
   477  
   478  !!! note
   479      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.
   480  
   481  ### 1. Create the webhook in the Git provider
   482  
   483  In your Git provider, navigate to the settings page where webhooks can be configured. The payload
   484  URL configured in the Git provider should use the `/api/webhook` endpoint of your ApplicationSet instance
   485  (e.g. `https://applicationset.example.com/api/webhook`). If you wish to use a shared secret, input an
   486  arbitrary value in the secret. This value will be used when configuring the webhook in the next step.
   487  
   488  ![Add Webhook](../../assets/applicationset/webhook-config.png "Add Webhook")
   489  
   490  !!! note
   491      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
   492  
   493  ### 2. Configure ApplicationSet with the webhook secret (Optional)
   494  
   495  Configuring a webhook shared secret is optional, since ApplicationSet will still refresh applications
   496  generated by Git generators, even with unauthenticated webhook events. This is safe to do since
   497  the contents of webhook payloads are considered untrusted, and will only result in a refresh of the
   498  application (a process which already occurs at three-minute intervals). If ApplicationSet is publicly
   499  accessible, then configuring a webhook secret is recommended to prevent a DDoS attack.
   500  
   501  In the `argocd-secret` Kubernetes secret, include the Git provider's webhook secret configured in step 1.
   502  
   503  Edit the Argo CD Kubernetes secret:
   504  
   505  ```bash
   506  kubectl edit secret argocd-secret -n argocd
   507  ```
   508  
   509  TIP: for ease of entering secrets, Kubernetes supports inputting secrets in the `stringData` field,
   510  which saves you the trouble of base64 encoding the values and copying it to the `data` field.
   511  Simply copy the shared webhook secret created in step 1, to the corresponding
   512  GitHub/GitLab/BitBucket key under the `stringData` field:
   513  
   514  ```yaml
   515  apiVersion: v1
   516  kind: Secret
   517  metadata:
   518    name: argocd-secret
   519    namespace: argocd
   520  type: Opaque
   521  data:
   522  ...
   523  
   524  stringData:
   525    # github webhook secret
   526    webhook.github.secret: shhhh! it's a github secret
   527  
   528    # gitlab webhook secret
   529    webhook.gitlab.secret: shhhh! it's a gitlab secret
   530  ```
   531  
   532  After saving, please restart the ApplicationSet pod for the changes to take effect.
   533  
   534  ## Repository credentials for ApplicationSets
   535  If your [ApplicationSets](index.md) uses a repository where you need credentials to be able to access it _and_ if the
   536  ApplicationSet project field is templated (i.e. the `project` field of the ApplicationSet contains `{{ ... }}`), you need to add the repository as a "non project scoped" repository.  
   537  - When doing that through the UI, set this to a **blank** value in the dropdown menu.
   538  - When doing that through the CLI, make sure you **DO NOT** supply the parameter `--project` ([argocd repo add docs](../../user-guide/commands/argocd_repo_add.md))
   539  - When doing that declaratively, make sure you **DO NOT** have `project:` defined under `stringData:` ([complete yaml example](../argocd-repositories-yaml.md))