ArgoCD 2.8 — Plugin Generator

Tal Hason
7 min readOct 4, 2023

--

ArgoCD introduced us to the concepts of ApplicatioSets and Generators sometime ago, it had several Generators, such as the git generator or the list generator. ( to get full details on those go to the ArgoCD Docs).

So in ArgoCD 2.8 ApplicationSet Controller has introduced to us a new type of generator, The Plugin Generator.

the idea behind this new generator is to provide users, developers, administrators, and platform teams to create their own flavor of generator with a basic web application server that exposes a POST path with a JSON body of the desired schema, read more here.

So why do I bring you all here, you may be asking

I have created a small plugin that uses a simple NodeJS application server and a HELM chart to Dynamically update, create, and delete those new applications from the applicationSet all in the GitOps style of practices.

so let's begin

the full repo that we will cover here can be found here, please fork and follow the README file on how to use and delicate.

What you need to make this work:

The sample application Project can be found Here, Please fork if you are planning to change stuff.

Repository Files and Folder:

here we have the following:

Let's explain the nodeJS folder

under it, we have:
- src folder, with the app.js file that contains our web application server
- src/config, here we store a default app.yaml file with basic config\
- argocd-plugin-app.postman_collection.json, Postman Collection to assist with testing the POST request.
- automation.sh, script to assist with build, test, and push the application image.
- Dockerfile, a Multi-stage Docker file to build the application container image.

Automation.sh file will make the working of running podman build/run/push more easy

The script accepts 2 running arguments the 1st is the commit message, and the 2nd is the desired operation:
- test, this will build and run the application image
- push, this will build and push the application image to the image registry, after it prompts to either update the HELM chart values file or not with the new image tag.
to work with the file create an environment variable named IMAGE_NAME with your _image.registry/repo_name/image_, if you forget the script will ask you for the image name in the first run.

I added a Swagger-UI to the Application to assist with testing the Payload on the fly directly from the server, for environments with limited resources (no Postman for example).
to access the Swagger-UI you need to navigate to the application route from your cluster i.e. https://plugin-argo-plugin-openshift-gitops.<<your cluster.fqdn>>/api-docs.
you should be presented with the Swagger-UI:

the API is protected with a simple bearer token, the deployment mechanism generating a new one after each commit so to get the latest token run the following:

oc get secrets plugin-argocd-app-set-plugin-token -n openshift-gitops -o yaml | yq eval '.data.token' | base64 -d

this will print the token to the terminal and you can click on the “Authorize” button on the top right of the Swagger-UI to enter it

Click login and you are all set.

The GitOps Folder

Under our GItops Folder, we find 2 Sub Folders:
- Argo-Plugin, Holds our HELM Chart with its values file to deploy our plugin web application
- ArgoApps, Holds all our argoCD objects with kustomaized.

I built it this way cause “Helm” is more flexible with application deployment manipulation and Kustomize is better with non-planned addons and changes, this way to duplicate the plug-in there a changes that need to be made I will explain later on.

Argo-Plugin Folder

Please read the README file to understand the Chart Options, it’s really basic.

Some Tricks and Tips:

Folders:
- Certificates, paste your domain Certificate and it will be added to the route that will be generated by the ingress.
- ApplicationFiles, This is the MOST Important folder, in which we will put our {Application}.yaml files like the following, the application supports multiple config files(i.e. batman.yaml, robin.yaml, joker.yaml …), and will merge them to a single JSON Paylod:

example: batman.yaml

GenerateApplication:
name: batman
project: gotham-demo
image: quay.io/gotham/batman
tag: 4a7050d
repoURL: https://github.com
branch: main
gitopsRepo: gotham-cd

each new Object in the GenerateApplication key will generate an Argo application via the application Set

you can add more or even change the schema, just adapt the applicationSet.yaml file to the current schema.

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: plugin-applicationset
namespace: openshift-gitops
spec:
generators:
- plugin:
configMapRef:
name: plugin-config
requeueAfterSeconds: 30
template:
metadata:
name: "{{name}}-{{project}}"
spec:
project: argocd-plugin
source:
helm:
valueFiles:
- '{{project}}/develop/values-{{name}}.yaml'
parameters:
- name: "image.name"
value: '{{image}}'
- name: "image.tag"
value: '{{tag}}'
- name: "global.namespace"
value: 'plugin-test'
repoURL: '{{repoURL}}/{{project}}/{{gitopsRepo}}.git'
targetRevision: '{{branch}}'
path: Application
destination:
server: https://kubernetes.default.svc
namespace: plugin-test
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true

- {{name}} — this is the name object from each item in the GenerateApplication array. (i.e. the name of the application or whatever you think is relevant)
- {{project}} — this is the project object from each item in the GenerateApplication array. (i.e. the organization name in GitHub)
- {{image}} — this is the image object from each item in the GenerateApplication array. (i.e. quay.io/gotham/batman)
- {{tag}} — this is the tag object from each item in the GenerateApplication array. (i.e. v1.0.1)
- {{repoURL}} — this is the repoURL object from each item in the GenerateApplication array (i.e. <http://www.github.com>).
- {{branch}} — this is the branch object from each item in the GenerateApplication array. (i.e. the branch name for the GitOps Repo)
- {{gitopsRepo}} — this is the gitopsRepo object from each item in the GenerateApplication array. (i.e. the Repository name for the GitOps Repo).

all those fields are for my example you can create any fields you want or need just remember they all have to be consistent in all the files.

Secrets:

we have 2 secrets in the template:

  1. secret-ca-cert.yaml, which will be generated with the ingress (i.e. deploy.ingress.enabled=true)
  2. header-secret.yaml, this secret auto-generates the bearer Token for the web application and the applicationSet.
apiVersion: v1
kind: Secret
metadata:
name: '{{ .Values.global.serviceName }}-argocd-app-set-plugin-token'
labels:
{{- include "app.labels" . | nindent 4 }}
app.kubernetes.io/part-of: argocd
annotations:
helm.sh/hook: "pre-install"
helm.sh/hook-delete-policy: "before-hook-creation"
type: Opaque
data:
token: '{{ randAlphaNum 14 | b64enc }}'

Notes:
— the secret will generate a new token each time a new commit is created, so always double-check your token if you testing with the Swagger or Postman
— if the Secret has been changed the Deployment will roll out and reload the new token.
the name of the token is part of the plugin config in the ConfigMap plugin-config

ArgoApps Folder

Under the ArgoApps folder have the following:

- Plugin folder, that holds the plugin Argo Application that directs to the git repo to the HELM Chart folder.
- Project.yaml, an Argo Project.
- AppofApps.yaml, An app of apps application to bootstrap the plugin and application set
- kustomization.yaml, an easy way to deploy all YAMLs in one command.

to bootstrap the plugin generator just run the following command, from the root of the repo:

oc apply -k GitOps/ArgoApps 

this will install the Argo Project and the app of apps and then the Plugin application and the applicationSet

How To create support for multiple schemas and patterns:

So this plugin supports a single schema that is defined in our YAML file under the ApplicationFiles in the Helm chart folder, if we want to support multiple patterns we can easily just duplicate our Helm chart and create a new schema in it, how to do it:

  • you need to duplicate the Argo-Plugin folder under GitOps Folder and rename it.
  • Update the Chart.yaml with the new folder name under name:
  • Under ArgoApps/Plugin Duplicate the ApplicationSet-Plugin.yaml and the Plugin-Application.yaml, rename them and update the paths to your new plugin deployment under the GitOps folder.
  • update the values.yaml file under your newly created folder with global.serviceName={new name}.
  • In the application set adjust the template to the new schema that you apply in the new config files, and update the config name to the new config, ConfigMap name (Tip: the configMap name has the service name at the beginning).
  • sync the app of apps and a new plugin will be created with a new applicationSet.

Now you can add your new Application YAML files into it and see your application generated.

Let’s see it in action:

Hope you enjoyed, reading and gave some thoughts about what is possible with this new feature, feel free to add suggestions and issues to my Git repo

--

--