Skip to content

Commit

Permalink
feat: Support volumes for appset deployment (#1563)
Browse files Browse the repository at this point in the history
* Adds volumes and volumeMounts to argocd types
* Adds volumes ans volumeMounts to appset deployment and pod
* Updates generated files
* Updates docs
* Adds unit tests
* Adds e2e-test

Signed-off-by: appiepollo14 <[email protected]>
  • Loading branch information
appiepollo14 authored Oct 17, 2024
1 parent 833a92e commit 8278397
Show file tree
Hide file tree
Showing 11 changed files with 5,186 additions and 34 deletions.
6 changes: 6 additions & 0 deletions api/v1beta1/argocd_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,12 @@ type ArgoCDApplicationSet struct {

// Custom labels to pods deployed by the operator
Labels map[string]string `json:"labels,omitempty"`

// Volumes adds volumes to the Argo CD ApplicationSet Controller container.
Volumes []corev1.Volume `json:"volumes,omitempty"`

// VolumeMounts adds volumeMounts to the Argo CD ApplicationSet Controller container.
VolumeMounts []corev1.VolumeMount `json:"volumeMounts,omitempty"`
}

func (a *ArgoCDApplicationSet) IsEnabled() bool {
Expand Down
14 changes: 14 additions & 0 deletions api/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1,655 changes: 1,655 additions & 0 deletions bundle/manifests/argoproj.io_argocds.yaml

Large diffs are not rendered by default.

1,655 changes: 1,655 additions & 0 deletions config/crd/bases/argoproj.io_argocds.yaml

Large diffs are not rendered by default.

72 changes: 43 additions & 29 deletions controllers/argocd/applicationset.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,8 @@ func (r *ReconcileArgoCD) reconcileApplicationSetDeployment(cr *argoproj.ArgoCD,
if sa != nil {
podSpec.ServiceAccountName = sa.ObjectMeta.Name
}
podSpec.Volumes = []corev1.Volume{

serverVolumes := []corev1.Volume{
{
Name: "ssh-known-hosts",
VolumeSource: corev1.VolumeSource{
Expand Down Expand Up @@ -228,6 +229,10 @@ func (r *ReconcileArgoCD) reconcileApplicationSetDeployment(cr *argoproj.ArgoCD,
},
},
}
if cr.Spec.ApplicationSet.Volumes != nil {
serverVolumes = append(serverVolumes, cr.Spec.ApplicationSet.Volumes...)
}
podSpec.Volumes = serverVolumes
addSCMGitlabVolumeMount := false
if scmRootCAConfigMapName := getSCMRootCAConfigMapName(cr); scmRootCAConfigMapName != "" {
cm := newConfigMapWithName(scmRootCAConfigMapName, cr)
Expand Down Expand Up @@ -322,35 +327,50 @@ func (r *ReconcileArgoCD) applicationSetContainer(cr *argoproj.ArgoCD, addSCMGit
// Environment specified in the CR take precedence over everything else
appSetEnv = argoutil.EnvMerge(appSetEnv, proxyEnvVars(), false)

// Default VolumeMounts for ApplicationSetController
serverVolumeMounts := []corev1.VolumeMount{
{
Name: "ssh-known-hosts",
MountPath: "/app/config/ssh",
},
{
Name: "tls-certs",
MountPath: "/app/config/tls",
},
{
Name: "gpg-keys",
MountPath: "/app/config/gpg/source",
},
{
Name: "gpg-keyring",
MountPath: "/app/config/gpg/keys",
},
{
Name: "tmp",
MountPath: "/tmp",
},
}

// Optional extra VolumeMounts for ApplicationSetController
if cr.Spec.ApplicationSet.VolumeMounts != nil {
serverVolumeMounts = append(serverVolumeMounts, cr.Spec.ApplicationSet.VolumeMounts...)
}

if addSCMGitlabVolumeMount {
serverVolumeMounts = append(serverVolumeMounts, corev1.VolumeMount{
Name: "appset-gitlab-scm-tls-cert",
MountPath: ApplicationSetGitlabSCMTlsMountPath,
})
}

container := corev1.Container{
Command: r.getArgoApplicationSetCommand(cr),
Env: appSetEnv,
Image: getApplicationSetContainerImage(cr),
ImagePullPolicy: corev1.PullAlways,
Name: "argocd-applicationset-controller",
Resources: getApplicationSetResources(cr),
VolumeMounts: []corev1.VolumeMount{
{
Name: "ssh-known-hosts",
MountPath: "/app/config/ssh",
},
{
Name: "tls-certs",
MountPath: "/app/config/tls",
},
{
Name: "gpg-keys",
MountPath: "/app/config/gpg/source",
},
{
Name: "gpg-keyring",
MountPath: "/app/config/gpg/keys",
},
{
Name: "tmp",
MountPath: "/tmp",
},
},
VolumeMounts: serverVolumeMounts,
Ports: []corev1.ContainerPort{
{
ContainerPort: 7000,
Expand All @@ -375,12 +395,6 @@ func (r *ReconcileArgoCD) applicationSetContainer(cr *argoproj.ArgoCD, addSCMGit
},
},
}
if addSCMGitlabVolumeMount {
container.VolumeMounts = append(container.VolumeMounts, corev1.VolumeMount{
Name: "appset-gitlab-scm-tls-cert",
MountPath: ApplicationSetGitlabSCMTlsMountPath,
})
}
return container
}

Expand Down
99 changes: 95 additions & 4 deletions controllers/argocd/applicationset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,10 @@ func TestReconcileApplicationSet_CreateDeployments(t *testing.T) {
deployment))

// Ensure the created Deployment has the expected properties
checkExpectedDeploymentValues(t, r, deployment, &sa, a)
checkExpectedDeploymentValues(t, r, deployment, &sa, nil, nil, a)
}

func checkExpectedDeploymentValues(t *testing.T, r *ReconcileArgoCD, deployment *appsv1.Deployment, sa *corev1.ServiceAccount, a *argoproj.ArgoCD) {
func checkExpectedDeploymentValues(t *testing.T, r *ReconcileArgoCD, deployment *appsv1.Deployment, sa *corev1.ServiceAccount, extraVolumes *[]corev1.Volume, extraVolumeMounts *[]corev1.VolumeMount, a *argoproj.ArgoCD) {
assert.Equal(t, deployment.Spec.Template.Spec.ServiceAccountName, sa.ObjectMeta.Name)
appsetAssertExpectedLabels(t, &deployment.ObjectMeta)

Expand Down Expand Up @@ -174,10 +174,46 @@ func checkExpectedDeploymentValues(t *testing.T, r *ReconcileArgoCD, deployment
})
}

if extraVolumes != nil {
volumes = append(volumes, *extraVolumes...)
}

if diff := cmp.Diff(volumes, deployment.Spec.Template.Spec.Volumes); diff != "" {
t.Fatalf("failed to reconcile applicationset-controller deployment volumes:\n%s", diff)
}

volumeMounts := []corev1.VolumeMount{
{
Name: "ssh-known-hosts",
MountPath: "/app/config/ssh",
},
{
Name: "tls-certs",
MountPath: "/app/config/tls",
},
{
Name: "gpg-keys",
MountPath: "/app/config/gpg/source",
},
{
Name: "gpg-keyring",
MountPath: "/app/config/gpg/keys",
},
{
Name: "tmp",
MountPath: "/tmp",
},
}

if extraVolumeMounts != nil {
volumeMounts = append(volumeMounts, *extraVolumeMounts...)
}

// Verify VolumeMounts
if diff := cmp.Diff(volumeMounts, deployment.Spec.Template.Spec.Containers[0].VolumeMounts); diff != "" {
t.Fatalf("failed to reconcile applicationset-controller deployment volume mounts:\n%s", diff)
}

expectedSelector := &metav1.LabelSelector{
MatchLabels: map[string]string{
common.ArgoCDKeyName: deployment.Name,
Expand Down Expand Up @@ -249,6 +285,61 @@ func TestReconcileApplicationSetProxyConfiguration(t *testing.T) {

}

func TestReconcileApplicationSetVolumes(t *testing.T) {
logf.SetLogger(ZapLogger(true))

extraVolumes := []corev1.Volume{
{
Name: "example-volume",
VolumeSource: corev1.VolumeSource{
EmptyDir: &corev1.EmptyDirVolumeSource{},
},
},
}

extraVolumeMounts := []corev1.VolumeMount{
{
Name: "example-volume",
MountPath: "/mnt/data",
},
}

a := makeTestArgoCD()
a.Spec.ApplicationSet = &argoproj.ArgoCDApplicationSet{
Volumes: extraVolumes,
VolumeMounts: extraVolumeMounts,
}

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)

sa := corev1.ServiceAccount{}

// Reconcile the ApplicationSet deployment
assert.NoError(t, r.reconcileApplicationSetDeployment(a, &sa))

// Get the deployment after reconciliation
deployment := &appsv1.Deployment{}
err := r.Client.Get(
context.TODO(),
types.NamespacedName{
Name: "argocd-applicationset-controller",
Namespace: a.Namespace,
},
deployment,
)
if err != nil {
t.Fatalf("failed to get deployment: %v", err)
}

// Ensure the created Deployment has the expected properties
checkExpectedDeploymentValues(t, r, deployment, &sa, &extraVolumes, &extraVolumeMounts, a)
}

func TestReconcileApplicationSet_UpdateExistingDeployments(t *testing.T) {
logf.SetLogger(ZapLogger(true))
a := makeTestArgoCD()
Expand Down Expand Up @@ -294,7 +385,7 @@ func TestReconcileApplicationSet_UpdateExistingDeployments(t *testing.T) {
deployment))

// Ensure the updated Deployment has the expected properties
checkExpectedDeploymentValues(t, r, deployment, &sa, a)
checkExpectedDeploymentValues(t, r, deployment, &sa, nil, nil, a)

}

Expand Down Expand Up @@ -454,7 +545,7 @@ func TestReconcileApplicationSet_Deployments_SpecOverride(t *testing.T) {

specImage := deployment.Spec.Template.Spec.Containers[0].Image
assert.Equal(t, test.expectedContainerImage, specImage)
checkExpectedDeploymentValues(t, r, deployment, &sa, a)
checkExpectedDeploymentValues(t, r, deployment, &sa, nil, nil, a)
})
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ metadata:
capabilities: Deep Insights
categories: Integration & Delivery
certified: "false"
createdAt: "2024-10-16T08:53:24Z"
createdAt: "2024-10-14T02:57:43Z"
description: Argo CD is a declarative, GitOps continuous delivery tool for Kubernetes.
operators.operatorframework.io/builder: operator-sdk-v1.35.0
operators.operatorframework.io/project_layout: go.kubebuilder.io/v4
Expand Down
Loading

0 comments on commit 8278397

Please sign in to comment.