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  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))