github.com/argoproj/argo-cd/v3@v3.2.1/docs/operator-manual/applicationset/Controlling-Resource-Modification.md (about) 1 # Controlling if/when the ApplicationSet controller modifies `Application` resources 2 3 The ApplicationSet controller supports a number of settings that limit the ability of the controller to make changes to generated Applications, for example, preventing the controller from deleting child Applications. 4 5 These settings allow you to exert control over when, and how, changes are made to your Applications, and to their corresponding cluster resources (`Deployments`, `Services`, etc). 6 7 Here are some of the controller settings that may be modified to alter the ApplicationSet controller's resource-handling behaviour. 8 9 ## Dry run: prevent ApplicationSet from creating, modifying, or deleting all Applications 10 11 To prevent the ApplicationSet controller from creating, modifying, or deleting any `Application` resources, you may enable `dry-run` mode. This essentially switches the controller into a "read only" mode, where the controller Reconcile loop will run, but no resources will be modified. 12 13 To enable dry-run, add `--dryrun true` to the ApplicationSet Deployment's container launch parameters. 14 15 See 'How to modify ApplicationSet container parameters' below for detailed steps on how to add this parameter to the controller. 16 17 ## Managed Applications modification Policies 18 19 The ApplicationSet controller supports a parameter `--policy`, which is specified on launch (within the controller Deployment container), and which restricts what types of modifications will be made to managed Argo CD `Application` resources. 20 21 The `--policy` parameter takes four values: `sync`, `create-only`, `create-delete`, and `create-update`. (`sync` is the default, which is used if the `--policy` parameter is not specified; the other policies are described below). 22 23 It is also possible to set this policy per ApplicationSet. 24 25 ```yaml 26 apiVersion: argoproj.io/v1alpha1 27 kind: ApplicationSet 28 spec: 29 # (...) 30 syncPolicy: 31 applicationsSync: create-only # create-update, create-delete sync 32 33 ``` 34 35 - Policy `create-only`: Prevents ApplicationSet controller from modifying or deleting Applications. **WARNING**: It doesn't prevent Application controller from deleting Applications according to [ownerReferences](https://kubernetes.io/docs/concepts/overview/working-with-objects/owners-dependents/) when deleting ApplicationSet. 36 - Policy `create-update`: Prevents ApplicationSet controller from deleting Applications. Update is allowed. **WARNING**: It doesn't prevent Application controller from deleting Applications according to [ownerReferences](https://kubernetes.io/docs/concepts/overview/working-with-objects/owners-dependents/) when deleting ApplicationSet. 37 - Policy `create-delete`: Prevents ApplicationSet controller from modifying Applications. Delete is allowed. 38 - Policy `sync`: Create, Update and Delete are allowed. 39 40 If the controller parameter `--policy` is set, it takes precedence on the field `applicationsSync`. It is possible to allow per ApplicationSet sync policy by setting variable `ARGOCD_APPLICATIONSET_CONTROLLER_ENABLE_POLICY_OVERRIDE` to argocd-cmd-params-cm `applicationsetcontroller.enable.policy.override` or directly with controller parameter `--enable-policy-override` (default to `false`). 41 42 ### Policy - `create-only`: Prevent ApplicationSet controller from modifying and deleting Applications 43 44 To allow the ApplicationSet controller to *create* `Application` resources, but prevent any further modification, such as *deletion*, or modification of Application fields, add this parameter in the ApplicationSet controller: 45 46 **WARNING**: "*deletion*" indicates the case as the result of comparing generated Application between before and after, there are Applications which no longer exist. It doesn't indicate the case Applications are deleted according to ownerReferences to ApplicationSet. See [How to prevent Application controller from deleting Applications when deleting ApplicationSet](#how-to-prevent-application-controller-from-deleting-applications-when-deleting-applicationset) 47 48 ``` 49 --policy create-only 50 ``` 51 52 At ApplicationSet level 53 54 ```yaml 55 apiVersion: argoproj.io/v1alpha1 56 kind: ApplicationSet 57 spec: 58 # (...) 59 syncPolicy: 60 applicationsSync: create-only 61 ``` 62 63 ### Policy - `create-update`: Prevent ApplicationSet controller from deleting Applications 64 65 To allow the ApplicationSet controller to create or modify `Application` resources, but prevent Applications from being deleted, add the following parameter to the ApplicationSet controller `Deployment`: 66 67 **WARNING**: "*deletion*" indicates the case as the result of comparing generated Application between before and after, there are Applications which no longer exist. It doesn't indicate the case Applications are deleted according to ownerReferences to ApplicationSet. See [How to prevent Application controller from deleting Applications when deleting ApplicationSet](#how-to-prevent-application-controller-from-deleting-applications-when-deleting-applicationset) 68 69 ``` 70 --policy create-update 71 ``` 72 73 This may be useful to users looking for additional protection against deletion of the Applications generated by the controller. 74 75 At ApplicationSet level 76 77 ```yaml 78 apiVersion: argoproj.io/v1alpha1 79 kind: ApplicationSet 80 spec: 81 # (...) 82 syncPolicy: 83 applicationsSync: create-update 84 ``` 85 86 ### How to prevent Application controller from deleting Applications when deleting ApplicationSet 87 88 By default, `create-only` and `create-update` policy isn't effective against preventing deletion of Applications when deleting ApplicationSet. 89 You must set the finalizer to ApplicationSet to prevent deletion in such case, and use background cascading deletion. 90 If you use foreground cascading deletion, there's no guarantee to preserve applications. 91 92 ```yaml 93 apiVersion: argoproj.io/v1alpha1 94 kind: ApplicationSet 95 metadata: 96 finalizers: 97 - resources-finalizer.argocd.argoproj.io 98 spec: 99 # (...) 100 ``` 101 102 ## Ignore certain changes to Applications 103 104 The ApplicationSet spec includes an `ignoreApplicationDifferences` field, which allows you to specify which fields of 105 the ApplicationSet should be ignored when comparing Applications. 106 107 The field supports multiple ignore rules. Each ignore rule may specify a list of either `jsonPointers` or 108 `jqPathExpressions` to ignore. 109 110 You may optionally also specify a `name` to apply the ignore rule to a specific Application, or omit the `name` to apply 111 the ignore rule to all Applications. 112 113 ```yaml 114 apiVersion: argoproj.io/v1alpha1 115 kind: ApplicationSet 116 spec: 117 ignoreApplicationDifferences: 118 - jsonPointers: 119 - /spec/source/targetRevision 120 - name: some-app 121 jqPathExpressions: 122 - .spec.source.helm.values 123 ``` 124 125 ### Allow temporarily toggling auto-sync 126 127 One of the most common use cases for ignoring differences is to allow temporarily toggling auto-sync for an Application. 128 129 For example, if you have an ApplicationSet that is configured to automatically sync Applications, you may want to temporarily 130 disable auto-sync for a specific Application. You can do this by adding an ignore rule for the `spec.syncPolicy.automated` field. 131 132 ```yaml 133 apiVersion: argoproj.io/v1alpha1 134 kind: ApplicationSet 135 spec: 136 ignoreApplicationDifferences: 137 - jsonPointers: 138 - /spec/syncPolicy 139 ``` 140 141 ### Limitations of `ignoreApplicationDifferences` 142 143 When an ApplicationSet is reconciled, the controller will compare the ApplicationSet spec with the spec of each Application 144 that it manages. If there are any differences, the controller will generate a patch to update the Application to match the 145 ApplicationSet spec. 146 147 The generated patch is a MergePatch. According to the MergePatch documentation, "existing lists will be completely 148 replaced by new lists" when there is a change to the list. 149 150 This limits the effectiveness of `ignoreApplicationDifferences` when the ignored field is in a list. For example, if you 151 have an application with multiple sources, and you want to ignore changes to the `targetRevision` of one of the sources, 152 changes in other fields or in other sources will cause the entire `sources` list to be replaced, and the `targetRevision` 153 field will be reset to the value defined in the ApplicationSet. 154 155 For example, consider this ApplicationSet: 156 157 ```yaml 158 apiVersion: argoproj.io/v1alpha1 159 kind: ApplicationSet 160 spec: 161 ignoreApplicationDifferences: 162 - jqPathExpressions: 163 - .spec.sources[] | select(.repoURL == "https://git.example.com/org/repo1").targetRevision 164 template: 165 spec: 166 sources: 167 - repoURL: https://git.example.com/org/repo1 168 targetRevision: main 169 - repoURL: https://git.example.com/org/repo2 170 targetRevision: main 171 ``` 172 173 You can freely change the `targetRevision` of the `repo1` source, and the ApplicationSet controller will not overwrite 174 your change. 175 176 ```yaml 177 apiVersion: argoproj.io/v1alpha1 178 kind: Application 179 spec: 180 sources: 181 - repoURL: https://git.example.com/org/repo1 182 targetRevision: fix/bug-123 183 - repoURL: https://git.example.com/org/repo2 184 targetRevision: main 185 ``` 186 187 However, if you change the `targetRevision` of the `repo2` source, the ApplicationSet controller will overwrite the entire 188 `sources` field. 189 190 ```yaml 191 apiVersion: argoproj.io/v1alpha1 192 kind: Application 193 spec: 194 sources: 195 - repoURL: https://git.example.com/org/repo1 196 targetRevision: main 197 - repoURL: https://git.example.com/org/repo2 198 targetRevision: main 199 ``` 200 201 !!! note 202 [Future improvements](https://github.com/argoproj/argo-cd/issues/15975) to the ApplicationSet controller may 203 eliminate this problem. For example, the `ref` field might be made a merge key, allowing the ApplicationSet 204 controller to generate and use a StrategicMergePatch instead of a MergePatch. You could then target a specific 205 source by `ref`, ignore changes to a field in that source, and changes to other sources would not cause the ignored 206 field to be overwritten. 207 208 ## Prevent an `Application`'s child resources from being deleted, when the parent Application is deleted 209 210 By default, when an `Application` resource is deleted by the ApplicationSet controller, all of the child resources of the Application will be deleted as well (such as, all of the Application's `Deployments`, `Services`, etc). 211 212 To prevent an Application's child resources from being deleted when the parent Application is deleted, add the `preserveResourcesOnDeletion: true` field to the `syncPolicy` of the ApplicationSet: 213 ```yaml 214 apiVersion: argoproj.io/v1alpha1 215 kind: ApplicationSet 216 spec: 217 # (...) 218 syncPolicy: 219 preserveResourcesOnDeletion: true 220 ``` 221 222 More information on the specific behaviour of `preserveResourcesOnDeletion`, and deletion in ApplicationSet controller and Argo CD in general, can be found on the [Application Deletion](Application-Deletion.md) page. 223 224 225 ## Prevent an Application's child resources from being modified 226 227 Changes made to the ApplicationSet will propagate to the Applications managed by the ApplicationSet, and then Argo CD will propagate the Application changes to the underlying cluster resources (as per [Argo CD Integration](Argo-CD-Integration.md)). 228 229 The propagation of Application changes to the cluster is managed by the [automated sync settings](../../user-guide/auto_sync.md), which are referenced in the ApplicationSet `template` field: 230 231 - `spec.template.syncPolicy.automated`: If enabled, changes to Applications will automatically propagate to the cluster resources of the cluster. 232 - Unset this within the ApplicationSet template to 'pause' updates to cluster resources managed by the `Application` resource. 233 - `spec.template.syncPolicy.automated.prune`: By default, Automated sync will not delete resources when Argo CD detects the resource is no longer defined in Git. 234 - For extra safety, set this to false to prevent unexpected changes to the backing Git repository from affecting cluster resources. 235 236 237 ## How to modify ApplicationSet container launch parameters 238 239 There are a couple of ways to modify the ApplicationSet container parameters, so as to enable the above settings. 240 241 ### A) Use `kubectl edit` to modify the deployment on the cluster 242 243 Edit the applicationset-controller `Deployment` resource on the cluster: 244 ``` 245 kubectl edit deployment/argocd-applicationset-controller -n argocd 246 ``` 247 248 Locate the `.spec.template.spec.containers[0].command` field, and add the required parameter(s): 249 ```yaml 250 spec: 251 # (...) 252 template: 253 # (...) 254 spec: 255 containers: 256 - command: 257 - entrypoint.sh 258 - argocd-applicationset-controller 259 # Insert new parameters here, for example: 260 # --policy create-only 261 # (...) 262 ``` 263 264 Save and exit the editor. Wait for a new `Pod` to start containing the updated parameters. 265 266 ### Or, B) Edit the `install.yaml` manifest for the ApplicationSet installation 267 268 Rather than directly editing the cluster resource, you may instead choose to modify the installation YAML that is used to install the ApplicationSet controller: 269 270 Applicable for applicationset versions less than 0.4.0. 271 ```bash 272 # Clone the repository 273 274 git clone https://github.com/argoproj/applicationset 275 276 # Checkout the version that corresponds to the one you have installed. 277 git checkout "(version of applicationset)" 278 # example: git checkout "0.1.0" 279 280 cd applicationset/manifests 281 282 # open 'install.yaml' in a text editor, make the same modifications to Deployment 283 # as described in the previous section. 284 285 # Apply the change to the cluster 286 kubectl apply -n argocd -f install.yaml 287 ``` 288 289 ## Preserving changes made to an Applications annotations and labels 290 291 !!! note 292 The same behavior can be achieved on a per-app basis using the [`ignoreApplicationDifferences`](#ignore-certain-changes-to-applications) 293 feature described above. However, preserved fields may be configured globally, a feature that is not yet available 294 for `ignoreApplicationDifferences`. 295 296 It is common practice in Kubernetes to store state in annotations, operators will often make use of this. To allow for this, it is possible to configure a list of annotations that the ApplicationSet should preserve when reconciling. 297 298 For example, imagine that we have an Application created from an ApplicationSet, but a custom annotation and label has since been added (to the Application) that does not exist in the `ApplicationSet` resource: 299 ```yaml 300 apiVersion: argoproj.io/v1alpha1 301 kind: Application 302 metadata: 303 # This annotation and label exists only on this Application, and not in 304 # the parent ApplicationSet template: 305 annotations: 306 my-custom-annotation: some-value 307 labels: 308 my-custom-label: some-value 309 spec: 310 # (...) 311 ``` 312 313 To preserve this annotation and label we can use the `preservedFields` property of the `ApplicationSet` like so: 314 ```yaml 315 apiVersion: argoproj.io/v1alpha1 316 kind: ApplicationSet 317 spec: 318 # (...) 319 preservedFields: 320 annotations: ["my-custom-annotation"] 321 labels: ["my-custom-label"] 322 ``` 323 324 The ApplicationSet controller will leave this annotation and label as-is when reconciling, even though it is not defined in the metadata of the ApplicationSet itself. 325 326 By default, the Argo CD notifications and the Argo CD refresh type annotations are also preserved. 327 328 !!!note 329 One can also set global preserved fields for the controller by passing a comma separated list of annotations and labels to 330 `ARGOCD_APPLICATIONSET_CONTROLLER_GLOBAL_PRESERVED_ANNOTATIONS` and `ARGOCD_APPLICATIONSET_CONTROLLER_GLOBAL_PRESERVED_LABELS` respectively. 331 332 ## Debugging unexpected changes to Applications 333 334 When the ApplicationSet controller makes a change to an application, it logs the patch at the debug level. To see these 335 logs, set the log level to debug in the `argocd-cmd-params-cm` ConfigMap in the `argocd` namespace: 336 337 ```yaml 338 apiVersion: v1 339 kind: ConfigMap 340 metadata: 341 name: argocd-cmd-params-cm 342 namespace: argocd 343 data: 344 applicationsetcontroller.log.level: debug 345 ``` 346 347 ## Previewing changes 348 349 To preview changes that the ApplicationSet controller would make to Applications, you can create the AppSet in dry-run 350 mode. This works whether the AppSet already exists or not. 351 352 ```shell 353 argocd appset create --dry-run ./appset.yaml -o json | jq -r '.status.resources[].name' 354 ``` 355 356 The dry-run will populate the returned ApplicationSet's status with the Applications which would be managed with the 357 given config. You can compare to the existing Applications to see what would change.