github.com/argoproj/argo-cd/v2@v2.10.9/docs/operator-manual/resource_actions.md (about)

     1  # Resource Actions
     2  
     3  ## Overview
     4  Argo CD allows operators to define custom actions which users can perform on specific resource types. This is used internally to provide actions like `restart` for a `DaemonSet`, or `retry` for an Argo Rollout.
     5  
     6  Operators can add actions to custom resources in form of a Lua script and expand those capabilities.
     7  
     8  ## Custom Resource Actions
     9  
    10  Argo CD supports custom resource actions written in [Lua](https://www.lua.org/). This is useful if you:
    11  
    12  * Have a custom resource for which Argo CD does not provide any built-in actions.
    13  * Have a commonly performed manual task that might be error prone if executed by users via `kubectl`
    14  
    15  The resource actions act on a single object.
    16  
    17  You can define your own custom resource actions in the `argocd-cm` ConfigMap.
    18  
    19  ### Custom Resource Action Types
    20  
    21  #### An action that modifies the source resource
    22  
    23  This action modifies and returns the source resource.
    24  This kind of action was the only one available till 2.8, and it is still supported.
    25  
    26  #### An action that produces a list of new or modified resources
    27  
    28  **An alpha feature, introduced in 2.8.**
    29  
    30  This action returns a list of impacted resources, each impacted resource has a K8S resource and an operation to perform on.   
    31  Currently supported operations are "create" and "patch", "patch" is only supported for the source resource.   
    32  Creating new resources is possible, by specifying a "create" operation for each such resource in the returned list.  
    33  One of the returned resources can be the modified source object, with a "patch" operation, if needed.   
    34  See the definition examples below.
    35  
    36  ### Define a Custom Resource Action in `argocd-cm` ConfigMap
    37  
    38  Custom resource actions can be defined in `resource.customizations.actions.<group_kind>` field of `argocd-cm`. Following example demonstrates a set of custom actions for `CronJob` resources, each such action returns the modified CronJob. 
    39  The customizations key is in the format of `resource.customizations.actions.<apiGroup_Kind>`.
    40  
    41  ```yaml
    42  resource.customizations.actions.batch_CronJob: |
    43    discovery.lua: |
    44      actions = {}
    45      actions["suspend"] = {["disabled"] = true}
    46      actions["resume"] = {["disabled"] = true}
    47    
    48      local suspend = false
    49      if obj.spec.suspend ~= nil then
    50          suspend = obj.spec.suspend
    51      end
    52      if suspend then
    53          actions["resume"]["disabled"] = false
    54      else
    55          actions["suspend"]["disabled"] = false
    56      end
    57      return actions
    58    definitions:
    59    - name: suspend
    60      action.lua: |
    61        obj.spec.suspend = true
    62        return obj
    63    - name: resume
    64      action.lua: |
    65        if obj.spec.suspend ~= nil and obj.spec.suspend then
    66            obj.spec.suspend = false
    67        end
    68        return obj
    69  ```
    70  
    71  The `discovery.lua` script must return a table where the key name represents the action name. You can optionally include logic to enable or disable certain actions based on the current object state.
    72  
    73  Each action name must be represented in the list of `definitions` with an accompanying `action.lua` script to control the resource modifications. The `obj` is a global variable which contains the resource. Each action script returns an optionally modified version of the resource. In this example, we are simply setting `.spec.suspend` to either `true` or `false`.
    74  
    75  #### Creating new resources with a custom action
    76  
    77  !!! important
    78      Creating resources via the Argo CD UI is an intentional, strategic departure from GitOps principles. We recommend 
    79      that you use this feature sparingly and only for resources that are not part of the desired state of the 
    80      application.
    81  
    82  The resource the action is invoked on would be referred to as the `source resource`.  
    83  The new resource and all the resources implicitly created as a result, must be permitted on the AppProject level, otherwise the creation will fail.
    84  
    85  ##### Creating a source resource child resources with a custom action
    86  
    87  If the new resource represents a k8s child of the source resource, the source resource ownerReference must be set on the new resource.  
    88  Here is an example Lua snippet, that takes care of constructing a Job resource that is a child of a source CronJob resource - the `obj` is a global variable, which contains the source resource:
    89  
    90  ```lua
    91  -- ...
    92  ownerRef = {}
    93  ownerRef.apiVersion = obj.apiVersion
    94  ownerRef.kind = obj.kind
    95  ownerRef.name = obj.metadata.name
    96  ownerRef.uid = obj.metadata.uid
    97  job = {}
    98  job.metadata = {}
    99  job.metadata.ownerReferences = {}
   100  job.metadata.ownerReferences[1] = ownerRef
   101  -- ...
   102  ```
   103  
   104  ##### Creating independent child resources with a custom action
   105  
   106  If the new resource is independent of the source resource, the default behavior of such new resource is that it is not known by the App of the source resource (as it is not part of the desired state and does not have an `ownerReference`).  
   107  To make the App aware of the new resource, the `app.kubernetes.io/instance` label (or other ArgoCD tracking label, if configured) must be set on the resource.   
   108  It can be copied from the source resource, like this:
   109  
   110  ```lua
   111  -- ...
   112  newObj = {}
   113  newObj.metadata = {}
   114  newObj.metadata.labels = {}
   115  newObj.metadata.labels["app.kubernetes.io/instance"] = obj.metadata.labels["app.kubernetes.io/instance"]
   116  -- ...
   117  ```   
   118  
   119  While the new resource will be part of the App with the tracking label in place, it will be immediately deleted if auto prune is set on the App.   
   120  To keep the resource, set `Prune=false` annotation on the resource, with this Lua snippet:
   121  
   122  ```lua
   123  -- ...
   124  newObj.metadata.annotations = {}
   125  newObj.metadata.annotations["argocd.argoproj.io/sync-options"] = "Prune=false"
   126  -- ...
   127  ```
   128  
   129  (If setting `Prune=false` behavior, the resource will not be deleted upon the deletion of the App, and will require a manual cleanup).
   130  
   131  The resource and the App will now appear out of sync - which is the expected ArgoCD behavior upon creating a resource that is not part of the desired state.
   132  
   133  If you wish to treat such an App as a synced one, add the following resource annotation in Lua code:
   134  
   135  ```lua
   136  -- ...
   137  newObj.metadata.annotations["argocd.argoproj.io/compare-options"] = "IgnoreExtraneous"
   138  -- ...
   139  ```
   140  
   141  #### An action that produces a list of resources - a complete example:
   142  
   143  ```yaml
   144  resource.customizations.actions.ConfigMap: |
   145    discovery.lua: |
   146      actions = {}
   147      actions["do-things"] = {}
   148      return actions
   149    definitions:
   150    - name: do-things
   151      action.lua: |
   152        -- Create a new ConfigMap
   153        cm1 = {}
   154        cm1.apiVersion = "v1"
   155        cm1.kind = "ConfigMap"
   156        cm1.metadata = {}
   157        cm1.metadata.name = "cm1"
   158        cm1.metadata.namespace = obj.metadata.namespace
   159        cm1.metadata.labels = {}
   160        -- Copy ArgoCD tracking label so that the resource is recognized by the App
   161        cm1.metadata.labels["app.kubernetes.io/instance"] = obj.metadata.labels["app.kubernetes.io/instance"]
   162        cm1.metadata.annotations = {}
   163        -- For Apps with auto-prune, set the prune false on the resource, so it does not get deleted
   164        cm1.metadata.annotations["argocd.argoproj.io/sync-options"] = "Prune=false"	  
   165        -- Keep the App synced even though it has a resource that is not in Git
   166        cm1.metadata.annotations["argocd.argoproj.io/compare-options"] = "IgnoreExtraneous"		  
   167        cm1.data = {}
   168        cm1.data.myKey1 = "myValue1"
   169        impactedResource1 = {}
   170        impactedResource1.operation = "create"
   171        impactedResource1.resource = cm1
   172  
   173        -- Patch the original cm
   174        obj.metadata.labels["aKey"] = "aValue"
   175        impactedResource2 = {}
   176        impactedResource2.operation = "patch"
   177        impactedResource2.resource = obj
   178  
   179        result = {}
   180        result[1] = impactedResource1
   181        result[2] = impactedResource2
   182        return result		  
   183  ```