Argo-cd: How does arcocd support patching of existing resources

Created on 8 Oct 2019  Â·  21Comments  Â·  Source: argoproj/argo-cd

this is really more of a question rather than a feature request.
The use case for patching existing resources comes up pretty often when dealing with Kubernetes distributions that comes up with a some default settings.
It would be nice to have a way to declarative patch the default settings to a desired state. Examples are typically Kubernetes distribution-dependent, but one use case across the board is node labeling.

enhancement

Most helpful comment

I think it would be nice to support patch. There are valid use cases. For example, some resources are just cannot be created by users in any circumstance, like kube-system and default namespaces, kubernetes.default.svc.cluster.local service...

If I want to add a label to such object, shouldn't GitOps concept cover this use case?

All 21 comments

What about:

  1. argocd app patch
$  argocd app patch
Examples:
    # Update an application's source path using json patch
    argocd app patch myapplication --patch='[{"op": "replace", "path": "/spec/source/path", "value": "newPath"}]' --type json

    # Update an application's repository target revision using merge patch
    argocd app patch myapplication --patch '{"spec": { "source": { "targetRevision": "master" } }}' --type merge

Usage:
  argocd app patch APPNAME [flags]
  1. Deploying local manifest files by doing argocd app sync APPNAME --local [PATH_TO_LOCAL_DIRECTORY]. See the docs here: https://github.com/argoproj/argo-cd/blob/master/docs/user-guide/application_sources.md#development

Would either of these help?

@simster7 I am not trying to patch an application. I am asking if it is possible to patch an existing object.
For example let's say I need to create an Application which will patch node abc with label cde=123.
how do I do that?

Sorry meant to point you to argocd app patch-resource:

$ argocd app patch-resource
Usage:
  argocd app patch-resource APPNAME [flags]

Flags:
      --all                    Indicates whether to patch multiple matching of resources
      --group string           Group
  -h, --help                   help for patch-resource
      --kind string            Kind
      --namespace string       Namespace
      --patch string           Patch
      --patch-type string      Which Patching strategy to use: 'application/json-patch+json', 'application/merge-patch+json', or 'application/strategic-merge-patch+json'. Defaults to 'application/merge-patch+json' (default "application/merge-patch+json")
      --resource-name string   Name of resource

An example of this in action: https://github.com/argoproj/argocd-example-apps/tree/master/blue-green

You can also consider:

  1. Updating your deployment manifests from your GitOps repo and performing a new sync. This is the preferred way to do it when using Argo.
  2. Parametrizing the fields you want to change and editing them with argocd app set (the example above also uses this).
  3. Overriding your manifests with argocd app sync APPNAME --local as mentioned above. Keep in mind that this is an anti-pattern and should only be done for development purposes. Furthermore, this will only affect the current deployment and changes will be lost after a sync.
  4. As a last resort maybe consider patching the objects directly using kubectl patch.

@simster7 I am probably not explaining myself. A node object already exists and is not controlled by an argocd Application.
I'd like to be able to create an argocd Application that has the effect of patching a node.
So, basically we don't know what this node will look like and we want to change part of it, for example add a label.

Got it, I had misunderstood what you had meant.

The team should correct me if I'm wrong, but I am fairly certain that you won't be able to use Argo to patch resources that are not controlled by it—i.e. resources that are not declared on the deployment repo and deployed by Argo.

then if this is not possible, I'd like to formally request this feature to be added. Basically argocd should support a different templating model where the templates are actually patch fragments and they are applied and enforced to existing resources.

This looks like a config management issue. Argo CD intentionally avoids making any changes in user-provided manifests and only inject one label to support resource pruning.

It is really difficult to implement config management in the right way so instead, Argo CD integrates with existing config management tools like helm/kustomize etc

So I would suggest using kustomize to imlpement resource patching. @raffaelespazzoli please feel free to reopen ticket if necessary.

@alexmt I don't understand the answer you gave me. Kustomize for sure is not the answer to my problem because customize can only patch resources you own (and own the definition of).
I think having the ability to patch a resource you don't own is a good feature for a gitops operator. And I'd like to reopen this issue as a feature request. Ho do I do it?

Sorry @raffaelespazzoli , did not realize you cannot reopen the ticket. Looks like I misunderstood your question too. Do you mean patching existing resources in a cluster that were not created by Argo CD originally? This should be supported as long as such resources can be modified using "kubectl apply".

You would have to create an application which includes resource manifest with apiVersion/name of an existing resource and add fields which you want to manage. Argo CD should detect that object exist and run kubectl apply agains it.

@alexmt So yes the request is to be able to patch resources that are pre-existing and not originally created by argocd. If I understand you suggestion, you are proposing to have an application that includes those resources in full (original fields plus the added fields that we wanted to patch).

There are two problems with this approach:

  1. one might not know the full resource definition at the time of the writing of the application resource (think about the use case of adding a label to a node resource)
  2. this would not work well with upgrades, because by giving argocd the full definition of a resource if the actual owner needs to change the resource (for an upgrade for example) argocd would not allow it and would reset the resource to the declared desired state in the application.

So, I believe, we need the concept of patching or if you will the idea that argocd does not fully own a resource but instead on some of the fields of that resource.

@raffaelespazzoli is your question answered now? Can I close this?

yes the answer was that there is not support for enforcing a patch on a preexisting resource. Then I asked to add this as a feature. If you think there is value in a feature like that then this issue should be left open.

This would definitely come in handy. Like is was mentioned, setting up node labels via ArgoCD would be great. Currently only option that I found so far is basically set up e.g. ansible playbook, which performs kubectl patch.

@BostjanBozic I created an operator to enforce a patch[1], you can have argocd create the CR that informs that operator how to create the patch.

@raffaelespazzoli nice one! I will take a look. If I understand correctly you are basically feeding ArgoCD ResourceLocker CR, Argo sync it and then ResourceLocker actually patches resource?

correct.

On Thu, Jul 9, 2020 at 10:44 AM Bostjan Bozic notifications@github.com
wrote:

@raffaelespazzoli https://github.com/raffaelespazzoli nice one! I will
take a look. If I understand correctly you are basically feeding ArgoCD
ResourceLocker CR, Argo sync it and then ResourceLocker actually patches
resource?

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/argoproj/argo-cd/issues/2437#issuecomment-656170432,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/ABPERXHFHWOYXMSJQ3STGRLR2XJUNANCNFSM4I6U7M7A
.

--
ciao/bye
Raffaele

I think it would be nice to support patch. There are valid use cases. For example, some resources are just cannot be created by users in any circumstance, like kube-system and default namespaces, kubernetes.default.svc.cluster.local service...

If I want to add a label to such object, shouldn't GitOps concept cover this use case?

@alexmt Within openshift for example the default scc's (security context constraints) are owned by Openshift but there is a need to patch those scc with additional users and serviceaccounts (which is documented as a manual proces by doing oc adm or by oc patch (oc patch scc privileged --type=json -p '[{"op": "add", "path": "/users/0", "value":"system:serviceaccount:default:router"}]'). We need this to be possible within argocd because we want to add users and sa's dynamically based on the teams that have namespaces rolled out by argo.

I also would love this feature
My use case is configuring _workload identity_ for _Stackdriver Adapter_ that comes pre-installed in _gke_ clusters

Currently, I have to manually run alongside argocd

kubectl annotate serviceaccount --namespace custom-metrics \
  custom-metrics-stackdriver-adapter \
  iam.gke.io/gcp-service-account=<google-service-account>@<project-id>.iam.gserviceaccount.com
Was this page helpful?
0 / 5 - 0 ratings