github.com/argoproj/argo-cd/v2@v2.10.9/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. Prevents Application controller from deleting Applications according to [ownerReferences](https://kubernetes.io/docs/concepts/overview/working-with-objects/owners-dependents/).
    36  - Policy `create-update`: Prevents ApplicationSet controller from deleting Applications. Update is allowed. Prevents Application controller from deleting Applications according to [ownerReferences](https://kubernetes.io/docs/concepts/overview/working-with-objects/owners-dependents/).
    37  - Policy `create-delete`: Prevents ApplicationSet controller from modifying Applications. Delete is allowed.
    38  - Policy `sync`: 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  ### Controller parameter
    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  --policy create-only
    47  ```
    48  
    49  At ApplicationSet level
    50  
    51  ```yaml
    52  apiVersion: argoproj.io/v1alpha1
    53  kind: ApplicationSet
    54  spec:
    55    # (...)
    56    syncPolicy:
    57      applicationsSync: create-only
    58  ```
    59  
    60  ## Policy - `create-update`: Prevent ApplicationSet controller from deleting Applications
    61  
    62  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`:
    63  ```
    64  --policy create-update
    65  ```
    66  
    67  This may be useful to users looking for additional protection against deletion of the Applications generated by the controller.
    68  
    69  At ApplicationSet level
    70  
    71  ```yaml
    72  apiVersion: argoproj.io/v1alpha1
    73  kind: ApplicationSet
    74  spec:
    75    # (...)
    76    syncPolicy:
    77      applicationsSync: create-update
    78  ```
    79  
    80  ## Ignore certain changes to Applications
    81  
    82  The ApplicationSet spec includes an `ignoreApplicationDifferences` field, which allows you to specify which fields of 
    83  the ApplicationSet should be ignored when comparing Applications.
    84  
    85  The field supports multiple ignore rules. Each ignore rule may specify a list of either `jsonPointers` or 
    86  `jqPathExpressions` to ignore.
    87  
    88  You may optionally also specify a `name` to apply the ignore rule to a specific Application, or omit the `name` to apply
    89  the ignore rule to all Applications.
    90  
    91  ```yaml
    92  apiVersion: argoproj.io/v1alpha1
    93  kind: ApplicationSet
    94  spec:
    95    ignoreApplicationDifferences:
    96      - jsonPointers:
    97          - /spec/source/targetRevision
    98      - name: some-app
    99        jqPathExpressions:
   100          - .spec.source.helm.values
   101  ```
   102  
   103  ### Allow temporarily toggling auto-sync
   104  
   105  One of the most common use cases for ignoring differences is to allow temporarily toggling auto-sync for an Application.
   106  
   107  For example, if you have an ApplicationSet that is configured to automatically sync Applications, you may want to temporarily
   108  disable auto-sync for a specific Application. You can do this by adding an ignore rule for the `spec.syncPolicy.automated` field.
   109  
   110  ```yaml
   111  apiVersion: argoproj.io/v1alpha1
   112  kind: ApplicationSet
   113  spec:
   114    ignoreApplicationDifferences:
   115      - jsonPointers:
   116          - /spec/syncPolicy
   117  ```
   118  
   119  ### Limitations of `ignoreApplicationDifferences`
   120  
   121  When an ApplicationSet is reconciled, the controller will compare the ApplicationSet spec with the spec of each Application
   122  that it manages. If there are any differences, the controller will generate a patch to update the Application to match the
   123  ApplicationSet spec.
   124  
   125  The generated patch is a MergePatch. According to the MergePatch documentation, "existing lists will be completely 
   126  replaced by new lists" when there is a change to the list.
   127  
   128  This limits the effectiveness of `ignoreApplicationDifferences` when the ignored field is in a list. For example, if you
   129  have an application with multiple sources, and you want to ignore changes to the `targetRevision` of one of the sources,
   130  changes in other fields or in other sources will cause the entire `sources` list to be replaced, and the `targetRevision`
   131  field will be reset to the value defined in the ApplicationSet.
   132  
   133  For example, consider this ApplicationSet:
   134  
   135  ```yaml
   136  apiVersion: argoproj.io/v1alpha1
   137  kind: ApplicationSet
   138  spec:
   139    ignoreApplicationDifferences:
   140      - jqPathExpressions:
   141          - .spec.sources[] | select(.repoURL == "https://git.example.com/org/repo1").targetRevision
   142    template:
   143      spec:
   144        sources:
   145        - repoURL: https://git.example.com/org/repo1
   146          targetRevision: main
   147        - repoURL: https://git.example.com/org/repo2
   148          targetRevision: main
   149  ```
   150  
   151  You can freely change the `targetRevision` of the `repo1` source, and the ApplicationSet controller will not overwrite
   152  your change.
   153  
   154  ```yaml
   155  apiVersion: argoproj.io/v1alpha1
   156  kind: Application
   157  spec:
   158    sources:
   159    - repoURL: https://git.example.com/org/repo1
   160      targetRevision: fix/bug-123
   161    - repoURL: https://git.example.com/org/repo2
   162      targetRevision: main
   163  ```
   164  
   165  However, if you change the `targetRevision` of the `repo2` source, the ApplicationSet controller will overwrite the entire
   166  `sources` field.
   167  
   168  ```yaml
   169  apiVersion: argoproj.io/v1alpha1
   170  kind: Application
   171  spec:
   172    sources:
   173    - repoURL: https://git.example.com/org/repo1
   174      targetRevision: main
   175    - repoURL: https://git.example.com/org/repo2
   176      targetRevision: main
   177  ```
   178  
   179  !!! note
   180      [Future improvements](https://github.com/argoproj/argo-cd/issues/15975) to the ApplicationSet controller may 
   181      eliminate this problem. For example, the `ref` field might be made a merge key, allowing the ApplicationSet 
   182      controller to generate and use a StrategicMergePatch instead of a MergePatch. You could then target a specific 
   183      source by `ref`, ignore changes to a field in that source, and changes to other sources would not cause the ignored 
   184      field to be overwritten.
   185  
   186  ## Prevent an `Application`'s child resources from being deleted, when the parent Application is deleted
   187  
   188  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).
   189  
   190  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:
   191  ```yaml
   192  apiVersion: argoproj.io/v1alpha1
   193  kind: ApplicationSet
   194  spec:
   195    # (...)
   196    syncPolicy:
   197      preserveResourcesOnDeletion: true
   198  ```
   199  
   200  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.
   201  
   202  
   203  ## Prevent an Application's child resources from being modified
   204  
   205  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)).
   206  
   207  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:
   208  
   209  - `spec.template.syncPolicy.automated`: If enabled, changes to Applications will automatically propagate to the cluster resources of the cluster. 
   210      - Unset this within the ApplicationSet template to 'pause' updates to cluster resources managed by the `Application` resource.
   211  - `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.
   212      - For extra safety, set this to false to prevent unexpected changes to the backing Git repository from affecting cluster resources.
   213  
   214  
   215  ## How to modify ApplicationSet container launch parameters
   216  
   217  There are a couple of ways to modify the ApplicationSet container parameters, so as to enable the above settings.
   218  
   219  ### A) Use `kubectl edit` to modify the deployment on the cluster
   220  
   221  Edit the applicationset-controller `Deployment` resource on the cluster:
   222  ```
   223  kubectl edit deployment/argocd-applicationset-controller -n argocd
   224  ```
   225  
   226  Locate the `.spec.template.spec.containers[0].command` field, and add the required parameter(s):
   227  ```yaml
   228  spec:
   229      # (...)
   230    template:
   231      # (...)
   232      spec:
   233        containers:
   234        - command:
   235          - entrypoint.sh
   236          - argocd-applicationset-controller
   237          # Insert new parameters here, for example:
   238          # --policy create-only
   239      # (...)
   240  ```
   241  
   242  Save and exit the editor. Wait for a new `Pod` to start containing the updated parameters.
   243  
   244  ### Or, B) Edit the `install.yaml` manifest for the ApplicationSet installation
   245  
   246  Rather than directly editing the cluster resource, you may instead choose to modify the installation YAML that is used to install the ApplicationSet controller:
   247  
   248  Applicable for applicationset versions less than 0.4.0. 
   249  ```bash
   250  # Clone the repository
   251  
   252  git clone https://github.com/argoproj/applicationset
   253  
   254  # Checkout the version that corresponds to the one you have installed.
   255  git checkout "(version of applicationset)"
   256  # example: git checkout "0.1.0"
   257  
   258  cd applicationset/manifests
   259  
   260  # open 'install.yaml' in a text editor, make the same modifications to Deployment 
   261  # as described in the previous section.
   262  
   263  # Apply the change to the cluster
   264  kubectl apply -n argocd -f install.yaml
   265  ```
   266  
   267  ## Preserving changes made to an Applications annotations and labels
   268  
   269  !!! note
   270      The same behavior can be achieved on a per-app basis using the [`ignoreApplicationDifferences`](#ignore-certain-changes-to-applications) 
   271      feature described above. However, preserved fields may be configured globally, a feature that is not yet available
   272      for `ignoreApplicationDifferences`.
   273  
   274  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.
   275  
   276  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:
   277  ```yaml
   278  apiVersion: argoproj.io/v1alpha1
   279  kind: Application
   280  metadata:
   281    # This annotation and label exists only on this Application, and not in 
   282    # the parent ApplicationSet template:
   283    annotations: 
   284      my-custom-annotation: some-value
   285    labels:
   286      my-custom-label: some-value
   287  spec:
   288    # (...)
   289  ```
   290  
   291  To preserve this annotation and label we can use the `preservedFields` property of the `ApplicationSet` like so:
   292  ```yaml
   293  apiVersion: argoproj.io/v1alpha1
   294  kind: ApplicationSet
   295  spec:
   296    # (...)
   297    preservedFields:
   298      annotations: ["my-custom-annotation"]
   299      labels: ["my-custom-label"]
   300  ```
   301  
   302  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.
   303  
   304  By default, the Argo CD notifications and the Argo CD refresh type annotations are also preserved.
   305  
   306  !!!note
   307    One can also set global preserved fields for the controller by passing a comma separated list of annotations and labels to 
   308    `ARGOCD_APPLICATIONSET_CONTROLLER_GLOBAL_PRESERVED_ANNOTATIONS` and `ARGOCD_APPLICATIONSET_CONTROLLER_GLOBAL_PRESERVED_LABELS` respectively.
   309  
   310  ## Debugging unexpected changes to Applications
   311  
   312  When the ApplicationSet controller makes a change to an application, it logs the patch at the debug level. To see these
   313  logs, set the log level to debug in the `argocd-cmd-params-cm` ConfigMap in the `argocd` namespace:
   314  
   315  ```yaml
   316  apiVersion: v1
   317  kind: ConfigMap
   318  metadata:
   319    name: argocd-cmd-params-cm
   320    namespace: argocd
   321  data:
   322    applicationsetcontroller.log.level: debug
   323  ```