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