From d66e6dbdadedf84e1066cdc2e3d0daa8066298a2 Mon Sep 17 00:00:00 2001 From: John Pitman Date: Tue, 19 Nov 2024 14:11:03 -0500 Subject: [PATCH] feat: make specifying sidecar plugin image optional Signed-off-by: John Pitman --- controllers/argocd/deployment.go | 16 +++- controllers/argocd/deployment_test.go | 45 +++++++++++ tests/k8s/1-0017_validate_cmp/02-assert.yaml | 30 ++++++++ .../02-cmp2-default-image.yaml | 77 +++++++++++++++++++ tests/k8s/1-0017_validate_cmp/99-delete.yaml | 5 +- 5 files changed, 171 insertions(+), 2 deletions(-) create mode 100644 tests/k8s/1-0017_validate_cmp/02-assert.yaml create mode 100644 tests/k8s/1-0017_validate_cmp/02-cmp2-default-image.yaml diff --git a/controllers/argocd/deployment.go b/controllers/argocd/deployment.go index baf91fca6..05116f2b6 100644 --- a/controllers/argocd/deployment.go +++ b/controllers/argocd/deployment.go @@ -1017,7 +1017,21 @@ func (r *ReconcileArgoCD) reconcileRepoDeployment(cr *argoproj.ArgoCD, useTLSFor }} if cr.Spec.Repo.SidecarContainers != nil { - deploy.Spec.Template.Spec.Containers = append(deploy.Spec.Template.Spec.Containers, cr.Spec.Repo.SidecarContainers...) + // If no image is specified for a sidecar container, use the default + // argo cd repo server image. Copy the containers to avoid changing the + // original CR. + containers := []corev1.Container{} + containers = append(containers, cr.Spec.Repo.SidecarContainers...) + image := getRepoServerContainerImage(cr) + for i := range containers { + if len(containers[i].Image) == 0 { + containers[i].Image = image + msg := fmt.Sprintf("no image specified for sidecar container \"%s\" in ArgoCD custom resource \"%s/%s\", using default image", + containers[i].Name, cr.Namespace, cr.Name) + log.Info(msg) + } + } + deploy.Spec.Template.Spec.Containers = append(deploy.Spec.Template.Spec.Containers, containers...) } repoServerVolumes := []corev1.Volume{ diff --git a/controllers/argocd/deployment_test.go b/controllers/argocd/deployment_test.go index 83122d71f..4841f7244 100644 --- a/controllers/argocd/deployment_test.go +++ b/controllers/argocd/deployment_test.go @@ -2356,6 +2356,51 @@ func TestReconcileArgoCD_reconcileRepoDeployment_serviceAccount(t *testing.T) { } } +func TestReconcileArgoCD_reconcileRepoDeployment_sidecarContainerImage(t *testing.T) { + logf.SetLogger(ZapLogger(true)) + + a := makeTestArgoCD(func(a *argoproj.ArgoCD) { + a.Spec.Repo.SidecarContainers = []corev1.Container{ + { + Name: "test-sidecar1", + }, + { + Name: "test-sidecar2", + }, + { + Name: "test-sidecar3", + Image: "test-image", + }, + } + }) + + resObjs := []client.Object{a} + subresObjs := []client.Object{a} + runtimeObjs := []runtime.Object{} + sch := makeTestReconcilerScheme(argoproj.AddToScheme) + cl := makeTestReconcilerClient(sch, resObjs, subresObjs, runtimeObjs) + r := makeTestReconciler(cl, sch) + + deployment := &appsv1.Deployment{} + assert.NoError(t, r.reconcileRepoDeployment(a, false)) + + assert.NoError(t, r.Client.Get( + context.TODO(), + types.NamespacedName{ + Name: "argocd-repo-server", + Namespace: a.Namespace, + }, + deployment)) + + assert.Len(t, deployment.Spec.Template.Spec.Containers, 4) + assert.Equal(t, "test-sidecar1", deployment.Spec.Template.Spec.Containers[1].Name) + assert.Equal(t, getRepoServerContainerImage(a), deployment.Spec.Template.Spec.Containers[1].Image) + assert.Equal(t, "test-sidecar2", deployment.Spec.Template.Spec.Containers[2].Name) + assert.Equal(t, getRepoServerContainerImage(a), deployment.Spec.Template.Spec.Containers[2].Image) + assert.Equal(t, "test-sidecar3", deployment.Spec.Template.Spec.Containers[3].Name) + assert.Equal(t, "test-image", deployment.Spec.Template.Spec.Containers[3].Image) +} + // If `remote` field is used in CR, then the component resources should not be created func TestReconcileArgoCD_reconcileRedisWithRemote(t *testing.T) { cr := makeTestArgoCD() diff --git a/tests/k8s/1-0017_validate_cmp/02-assert.yaml b/tests/k8s/1-0017_validate_cmp/02-assert.yaml new file mode 100644 index 000000000..480123763 --- /dev/null +++ b/tests/k8s/1-0017_validate_cmp/02-assert.yaml @@ -0,0 +1,30 @@ +# Increase the timeout for the first test because it needs to download +# a number of container images +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 720 +--- +apiVersion: argoproj.io/v1alpha1 +kind: ArgoCD +metadata: + name: example-argocd + namespace: test-2-17-custom +status: + phase: Available +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: example-argocd-repo-server + namespace: test-2-17-custom +status: + readyReplicas: 1 +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: guestbook + namespace: test-2-17-custom + annotations: + Bar: baz + Foo: myfoo diff --git a/tests/k8s/1-0017_validate_cmp/02-cmp2-default-image.yaml b/tests/k8s/1-0017_validate_cmp/02-cmp2-default-image.yaml new file mode 100644 index 000000000..a1a70bc7b --- /dev/null +++ b/tests/k8s/1-0017_validate_cmp/02-cmp2-default-image.yaml @@ -0,0 +1,77 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: test-2-17-custom +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: cmp-plugin + namespace: test-2-17-custom +data: + plugin.yaml: | + apiVersion: argoproj.io/v1alpha1 + kind: ConfigManagementPlugin + metadata: + name: cmp-plugin + spec: + version: v1.0 + generate: + command: [sh, -c, 'echo "{\"kind\": \"ConfigMap\", \"apiVersion\": \"v1\", \"metadata\": { \"name\": \"$ARGOCD_APP_NAME\", \"namespace\": \"$ARGOCD_APP_NAMESPACE\", \"annotations\": {\"Foo\": \"$ARGOCD_ENV_FOO\", \"Bar\": \"baz\"}}}"'] + discover: + find: + command: [sh, -c, 'echo "FOUND"; exit 0'] + allowConcurrency: true + lockRepo: true +--- +apiVersion: argoproj.io/v1alpha1 +kind: ArgoCD +metadata: + name: example-argocd + namespace: test-2-17-custom +spec: + server: + route: + enabled: true + repo: + sidecarContainers: + - name: cmp + command: [/var/run/argocd/argocd-cmp-server] + securityContext: + runAsNonRoot: true + runAsUser: 999 + volumeMounts: + - mountPath: /var/run/argocd + name: var-files + - mountPath: /home/argocd/cmp-server/plugins + name: plugins + - mountPath: /tmp + name: tmp + - mountPath: /home/argocd/cmp-server/config/plugin.yaml + subPath: plugin.yaml + name: cmp-plugin + volumes: + - configMap: + name: cmp-plugin + name: cmp-plugin +--- +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: guestbook + namespace: test-2-17-custom +spec: + project: default + source: + repoURL: 'https://github.com/argoproj/argocd-example-apps.git' + path: guestbook + targetRevision: HEAD + plugin: + env: + - name: FOO + value: myfoo + destination: + server: 'https://kubernetes.default.svc' + namespace: test-2-17-custom + syncPolicy: + automated: {} diff --git a/tests/k8s/1-0017_validate_cmp/99-delete.yaml b/tests/k8s/1-0017_validate_cmp/99-delete.yaml index 9b61ceb8f..eebca110d 100644 --- a/tests/k8s/1-0017_validate_cmp/99-delete.yaml +++ b/tests/k8s/1-0017_validate_cmp/99-delete.yaml @@ -4,4 +4,7 @@ kind: TestStep delete: - apiVersion: v1 kind: Namespace - name: test-1-17-custom \ No newline at end of file + name: test-1-17-custom +- apiVersion: v1 + kind: Namespace + name: test-2-17-custom