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.