Skip to content

Instantly share code, notes, and snippets.

@alexrecuenco
Forked from nimjor/argocd-labeler-plugin.md
Created January 14, 2025 23:45
Show Gist options
  • Save alexrecuenco/006aa8fa8c9acec520c68fb552e5cce2 to your computer and use it in GitHub Desktop.
Save alexrecuenco/006aa8fa8c9acec520c68fb552e5cce2 to your computer and use it in GitHub Desktop.
ArgoCD labeler plugin via kustomize

ArgoCD Labeler Plugin

Ever wish you could pass some label to an ArgoCD application and have every child resource pick up that label? This is probably of most interest to cluster operators who may not directly control the contents of manifests deployed to their clusters via ArgoCD, but need a way to enforce some standard labeling scheme.

The solution? A simple ArgoCD plugin, easier to setup than you might think.

Write the plugin.yaml

An ArgoCD plugin needs to be configured as a sidecar container of the argocd-repo-server deployment, and the container needs to have a plugin.yaml file that describes what it should do.

apiVersion: argoproj.io/v1alpha1
kind: ConfigManagementPlugin
metadata:
  # This is the name by which the plugin will be registered to ArgoCD and must be unique within the Argo instance.
  name: argocd-labeler
spec:
  generate:
    command: [sh, c]
    args:
      - |
        if [[ ! -f "kustomization.yaml" && ! -f "kustomization.yml" ]]; then
          kustomize create --autodetect --recursive
        fi
        kustomize edit add label "my_app_id:$ARGOCD_ENV_MY_APP_ID"
        kustomize build

This is a very simple plugin config. The full spec is explained in the docs.

Basically, we're running this plugin using an image that already contains kustomize, and then we're making use of kustomize's commonLabels to add a key:value pair, where the value comes from the environment.

Additional details:

  • When this plugin gets invoked, the context is the repo/location which contains the application manifests (basically the spec.source of the Application). Think of this as the working directory where we're calling kustomize.
  • The $ARGOCD_ENV_MY_APP_ID variable is going to come from an input on the Application manifest.
  • After making sure kustomize is properly set up, we call kustomize build to write the updated manifests to stdout.
  • If you don't want to include things like Service and Deployment selectors getting labeled, you can add the --without-selector flag to the kustomize edit add label command.

Patch the argocd-repo-server deployment to include the plugin sidecar

Use this as a kustomize strategic merge patch to add the plugin sidecar container to the argocd-repo-server:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: argocd-repo-server
spec:
  template:
    spec:
      containers:
        - name: argocd-labeler
          image: registry.k8s.io/kustomize/kustomize:v5.4.3
          command:
            - /var/run/argocd/argocd-cmp/server # starts a gRPC server that will receive calls to the plugin and execute the command defined in the plugin.yaml
          securityContext:
            runAsNonRoot: true
            runAsUser: 999 # must use 999 for the UID
          volumeMounts:
            - mountPath: /var/run/argocd
              name: var-files # this one should already be defined as a volume by a standard argocd-repo-server deployment
            - mountPath: /home/argocd/cmp-server/plugins
              name: plugins
            - mountPath: /home/argocd/cmp-server/config/plugin.yaml # must be mounted here and must be named plugin.yaml
              subPath: plugin.yaml
              name: argocd-labeler-plugin
            - mountPath: /tmp
              name: cmp-tmp
        volumes:
          - configMap:
              name: argocd-labeler-plugin
            name: argocd-labeler-plugin
          - emptyDir: {}
            name: cmp-tmp

Note

This assumes you have put the plugin.yaml in a ConfigMap named argocd-labeler-plugin in the ArgoCD namespace, and that ConfigMap has a data key named plugin.yaml, e.g.

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-labeler-plugin
data:
  plugin.yaml: |
    # contents from above

Use the plugin in an Application

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: foo-app
  namespace: argocd
spec:
  destination:
    namespace: default
    server: https://kubernetes.default.svc
  project: default
  source:
    repoURL: [email protected]:org/my-gitops-repo.git
    path: foo
    plugin:
      name: argocd-labeler
      env:
        - name: MY_APP_ID
          value: "foo-123"

In this simple application we call our argocd-labeler plugin and pass a value for an environment variable. Remember the $ARGOCD_ENV_MY_APP_ID variable we referenced in the plugin.yaml? This is where it comes from. ArgoCD will set the variables you define in your app's spec.source.plugin.env in the plugin environment, prefixed with ARGOCD_ENV_.

Now when my app syncs, all child resources will have a new label added like my_app_id:foo-123 ✅.

References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment