argoproj/applicationset

Plugin Generator throws `ApplicationSet: strict decoding error: unknown field "spec.generators[0].plugin"`

jessebot opened this issue · 4 comments

Not sure if this should be opened here or in the argocd repo, since it's documented in the argocd docs here, but I can't seem to use the plugin generator for ApplicationSets. I only yesterday started playing with this and it would solve the issue of not being able to use an environment variable in argocd Applications or applicationSets until/unless that is implemented. Perhaps I'm doing something wrong?

To reproduce:

Example ApplicationSet yaml:

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: vouch
spec:
  goTemplate: true
  generators:
  - plugin:
      configMapRef:
        name: argocd-generator-plugin-cm
      input:
        parameters:
          key1: value1
  template:
    metadata:
      name: vouch
    spec:
      project: default
      source:
        repoURL: 'https://vouch.github.io/helm-charts/'
        targetRevision: 3.1.0
        chart: vouch
        helm:
          values: |
            image:
              tag: 0.39.0
            existingSecretName: vouch-existing-secret
            ingress:
              enabled: true
              annotations:
                kubernetes.io/ingress.class: nginx
                cert-manager.io/cluster-issuer: letsencrypt-staging
              paths:
                - /
              hosts:
                - {{.vouch_hostname}}
              tls:
                - secretName: vouch-tls
                  hosts:
                    - {{.vouch_hostname}}
      destination:
        server: "https://kubernetes.default.svc"
        namespace: vouch

use kubectl apply -f to apply the above ApplicationSet and get this:

Error from server (BadRequest):
error when creating "argocd/manifests/test-applicationset/vouch.yaml":
ApplicationSet in version "v1alpha1" cannot be handled as a ApplicationSet:
strict decoding error: unknown field "spec.generators[0].plugin"

I am using this configmap:

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-generator-plugin-cm
  namespace: argocd
data:
  # $<some_K8S_secret>:plugin.myplugin.token
  token: "$arogocd-generator-plugin-token:token"
  baseUrl: "http://argocd-generator-plugin.argocd.svc.cluster.local."

I'm installing Argo CD and the applicationset controller via the helm chart (chart version is 5.42.1 which is app version v2.7.10):

helm list
NAME    NAMESPACE       REVISION        UPDATED                                      STATUS   CHART           APP VERSION
argocd  argocd          1               2023-08-04 11:38:29.343108143 +0200 CEST     deployed argo-cd-5.42.1  v2.7.10

Is there anything I'm missing?

my generator plugin deployment and service

This is sucessfully deployed in the argocd namespace

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: argocd-generator-plugin
  namespace: argocd
  labels:
    app: argocd-generator-plugin
spec:
  replicas: 1
  selector:
    matchLabels:
      app: argocd-generator-plugin
  template:
    metadata:
      labels:
        app: argocd-generator-plugin
    spec:
      containers:
        - name: argocd-generator-plugin
          image: jessebot/argocd-env-var-generator-plugin:0.1.0
          imagePullPolicy: Always
          ports:
            - containerPort: 4355
          env:
            - name: TOKEN
              valueFrom:
                secretKeyRef:
                  name: arogocd-generator-plugin-token
                  key: token
          envFrom:
            - secretRef:
                name: argocd-hostname-vars      
---
apiVersion: v1
kind: Service
metadata:
  name: argocd-generator-plugin
  namespace: argocd
spec:
  ports:
    - port: 80 # the port that this service should serve on
      # the container on each pod to connect to, can be a name
      # (e.g. 'www') or a number (e.g. 80)
      targetPort: 4355
      protocol: TCP
  # just like the selector in the deployment,
  # but this time it identifies the set of pods to load balance
  # traffic to.
  selector:
    app: argocd-generator-plugin
plugin Dockerfile
FROM python:3.11-slim-bookworm

# install any security updates we need
RUN apt-get update && \
    apt list --upgradeable | grep security | cut -f1 -d '/' | xargs apt-get install --no-install-recommends -y && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/* && \
    rm -rf /tmp/*

COPY python_plugin.py /python_plugin.py

ENTRYPOINT ["python", "/python_plugin.py"]
plugin python script
import json
from http.server import BaseHTTPRequestHandler, HTTPServer
from os import environ
import logging as log

PLUGIN_TOKEN = environ.get("TOKEN")


class Plugin(BaseHTTPRequestHandler):

    def args(self):
        return json.loads(self.rfile.read(int(self.headers.get('Content-Length'))))

    def reply(self, reply):
        """
        return 200 HTTP code (success) if auth everything checks out
        """
        self.send_response(200)
        self.end_headers()
        self.wfile.write(json.dumps(reply).encode("UTF-8"))

    def forbidden(self):
        """
        return 403 HTTP (forbidden) code if authorization fails
        """
        self.send_response(403)
        self.end_headers()

    def unsupported(self):
        """
        return 404 HTTP code if we are asked for any other path than getparams
        """
        self.send_response(404)
        self.end_headers()

    def do_POST(self):
        if self.headers.get("Authorization") != "Bearer " + PLUGIN_TOKEN:
            self.forbidden()

        if self.path == '/api/v1/getparams.execute':
            args = self.args()

            # just log the args for now
            for argument in args:
                log.info(f"Argument recieved: {argument}")

            # for now, just get the vouch hostname
            vouch_hostname = environ.get("VOUCH_HOSTNAME")

            # reply with just the vouch hostname
            self.reply({
                "output": {
                    "parameters": [
                        {
                            "vouch_hostname": vouch_hostname,
                        }
                    ]
                }
            })
        else:
            self.unsupported()


if __name__ == '__main__':
    httpd = HTTPServer(('', 4355), Plugin)
    httpd.serve_forever()

To be absolutely sure this is not working (at least in my environment), I created a repo from the argoproj-labs/applicationset-hello-plugin template repo here, and it still seems to have returned the same error:

$ kustomize build | kubectl apply -f -
namespace/applicationset-hello-plugin created
configmap/hello-plugin-script-k5g94b88g8 created
configmap/applicationset-hello-plugin created
secret/applicationset-hello-plugin created
secret/applicationset-hello-plugin created
service/applicationset-hello-plugin created
deployment.apps/applicationset-hello-plugin created

$ kubectl apply -f test_applicationset.yaml
Error from server (BadRequest): error when creating "test_applicationset.yaml": ApplicationSet in version "v1alpha1" cannot be handled as a ApplicationSet: strict decoding error: unknown field "spec.generators[0].plugin"

test_applicationset.yaml is the one from the README here:

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: myplugin
spec:
  generators:
    - plugin:
        configMapRef:
          name: applicationset-hello-plugin
  template:
    metadata:
      name: "from-appset-{{hello}}"
    spec:
      project: default
      source:
        repoURL: https://github.com/argoproj/argocd-example-apps.git
        path: .
      destination:
        server: https://kubernetes.default.svc
        namespace: default

Is there something I need to update in the main argocd configmap or anything to make it work? Maybe I just missed a setting 🤔

Oh no, I just realized I was looking at the v:latest documentation this whole time because it has syntax highlighting and v:stable does not. This feature isn't in stable and I'm running a stable image version 🤦

Let me try latest, because I have a good test environment with k3s where I can just wipe the cluster and try fresh and I want to experiment anyway :)

oh double no.... how did I not notice the blatant deprecation notice on this repo 🤦

Will reopen in the argocd repo, if this is an issue in stable 2.8.

Minor suggestion to use the GitHub public archive feature though, so it's clear at the top of repo that this is not active. I feel silly for not reading the README here though :)

For anyone else who may have gotten lost:
It works in v2.8.0-rc7 by setting global.image.tag in values.yaml for your helm install to v2.8.0-rc7 and then applying this CRD. :)