Skip to content

Commit

Permalink
feat: add option to enable argo-rollout ui extension (#1554)
Browse files Browse the repository at this point in the history
* feat: add option to enable argo-rollout ui extension

Signed-off-by: saumeya <[email protected]>

* review comments and fixes

Signed-off-by: saumeya <[email protected]>

* add unit test

Signed-off-by: saumeya <[email protected]>

* doc update and e2e test

Signed-off-by: saumeya <[email protected]>

* review comments

Signed-off-by: saumeya <[email protected]>

* fix

Signed-off-by: saumeya <[email protected]>

* review changes, e2e fix

Signed-off-by: saumeya <[email protected]>

* review changes

Signed-off-by: saumeya <[email protected]>

* fix

Signed-off-by: saumeya <[email protected]>

---------

Signed-off-by: saumeya <[email protected]>
  • Loading branch information
saumeya authored Oct 16, 2024
1 parent 3334487 commit 833a92e
Show file tree
Hide file tree
Showing 15 changed files with 313 additions and 2 deletions.
3 changes: 3 additions & 0 deletions api/v1alpha1/argocd_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,9 @@ type ArgoCDServerSpec struct {
// Autoscale defines the autoscale options for the Argo CD Server component.
Autoscale ArgoCDServerAutoscaleSpec `json:"autoscale,omitempty"`

// EnableRolloutsUI will add the Argo Rollouts UI extension in ArgoCD Dashboard.
EnableRolloutsUI bool `json:"enableRolloutsUI,omitempty"`

// GRPC defines the state for the Argo CD Server GRPC options.
GRPC ArgoCDServerGRPCSpec `json:"grpc,omitempty"`

Expand Down
3 changes: 3 additions & 0 deletions api/v1beta1/argocd_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,9 @@ type ArgoCDServerSpec struct {
// Autoscale defines the autoscale options for the Argo CD Server component.
Autoscale ArgoCDServerAutoscaleSpec `json:"autoscale,omitempty"`

// EnableRolloutsUI will add the Argo Rollouts UI extension in ArgoCD Dashboard.
EnableRolloutsUI bool `json:"enableRolloutsUI,omitempty"`

// GRPC defines the state for the Argo CD Server GRPC options.
GRPC ArgoCDServerGRPCSpec `json:"grpc,omitempty"`

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-09-16T21:29:22Z"
createdAt: "2024-10-16T08:53:24Z"
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
8 changes: 8 additions & 0 deletions bundle/manifests/argoproj.io_argocds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6421,6 +6421,10 @@ spec:
required:
- enabled
type: object
enableRolloutsUI:
description: EnableRolloutsUI will add the Argo Rollouts UI extension
in ArgoCD Dashboard.
type: boolean
env:
description: Env lets you specify environment for API server pods
items:
Expand Down Expand Up @@ -17918,6 +17922,10 @@ spec:
required:
- enabled
type: object
enableRolloutsUI:
description: EnableRolloutsUI will add the Argo Rollouts UI extension
in ArgoCD Dashboard.
type: boolean
enabled:
description: Enabled is the flag to enable ArgoCD Server during
ArgoCD installation. (optional, default `true`)
Expand Down
6 changes: 6 additions & 0 deletions common/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,12 @@ const (
// ArgoCDDefaultResourceInclusions is the default resource inclusions.
ArgoCDDefaultResourceInclusions = ""

// ArgoCDExtensionInstallerImage is the default image for ArgoCD Extension Installer that can be used to install UI extensions like Rollouts extension.
ArgoCDExtensionInstallerImage = "quay.io/argoprojlabs/argocd-extension-installer:v0.0.8"

// ArgoRolloutsExtensionURL is the URL used to download the extension.js file from the latest rollout-extension tar release
ArgoRolloutsExtensionURL = "https://github.com/argoproj-labs/rollout-extension/releases/download/v0.3.6/extension.tar"

// ArgoCDDefaultRSAKeySize is the default RSA key size when not specified.
ArgoCDDefaultRSAKeySize = 2048

Expand Down
8 changes: 8 additions & 0 deletions config/crd/bases/argoproj.io_argocds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6410,6 +6410,10 @@ spec:
required:
- enabled
type: object
enableRolloutsUI:
description: EnableRolloutsUI will add the Argo Rollouts UI extension
in ArgoCD Dashboard.
type: boolean
env:
description: Env lets you specify environment for API server pods
items:
Expand Down Expand Up @@ -17907,6 +17911,10 @@ spec:
required:
- enabled
type: object
enableRolloutsUI:
description: EnableRolloutsUI will add the Argo Rollouts UI extension
in ArgoCD Dashboard.
type: boolean
enabled:
description: Enabled is the flag to enable ArgoCD Server during
ArgoCD installation. (optional, default `true`)
Expand Down
86 changes: 86 additions & 0 deletions controllers/argocd/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -1374,6 +1374,28 @@ func (r *ReconcileArgoCD) reconcileServerDeployment(cr *argoproj.ArgoCD, useTLSF

deploy.Spec.Template.Spec.Volumes = serverVolumes

if cr.Spec.Server.EnableRolloutsUI {

deploy.Spec.Template.Spec.InitContainers = append(deploy.Spec.Template.Spec.InitContainers, getRolloutInitContainer()...)

deploy.Spec.Template.Spec.Containers[0].VolumeMounts = append(deploy.Spec.Template.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{
Name: "extensions",
MountPath: "/tmp/extensions/",
})

deploy.Spec.Template.Spec.Volumes = append(deploy.Spec.Template.Spec.Volumes, corev1.Volume{
Name: "extensions",
VolumeSource: corev1.VolumeSource{
EmptyDir: &corev1.EmptyDirVolumeSource{},
},
})
} else if !cr.Spec.Server.EnableRolloutsUI {
deploy.Spec.Template.Spec.InitContainers = removeInitContainer(deploy.Spec.Template.Spec.InitContainers, "rollout-extension")
deploy.Spec.Template.Spec.Volumes = removeVolume(deploy.Spec.Template.Spec.Volumes, "extensions")
deploy.Spec.Template.Spec.Containers[0].VolumeMounts = removeVolumeMount(deploy.Spec.Template.Spec.Containers[0].VolumeMounts, "extensions")

}

if replicas := getArgoCDServerReplicas(cr); replicas != nil {
deploy.Spec.Replicas = replicas
}
Expand All @@ -1391,6 +1413,9 @@ func (r *ReconcileArgoCD) reconcileServerDeployment(cr *argoproj.ArgoCD, useTLSF
deploy.Spec.Template.Labels[key] = value
}
}
if err := applyReconcilerHook(cr, deploy, ""); err != nil {
return err
}

existing := newDeploymentWithSuffix("server", "server", cr)
if argoutil.IsObjectFound(r.Client, cr.Namespace, existing.Name, existing) {
Expand Down Expand Up @@ -1537,3 +1562,64 @@ func updateNodePlacement(existing *appsv1.Deployment, deploy *appsv1.Deployment,
*changed = true
}
}

func getRolloutInitContainer() []corev1.Container {
return []corev1.Container{
{
Name: "rollout-extension",
Image: common.ArgoCDExtensionInstallerImage,
Env: []corev1.EnvVar{
{
Name: "EXTENSION_URL",
Value: common.ArgoRolloutsExtensionURL,
},
},
VolumeMounts: []corev1.VolumeMount{
{
Name: "extensions",
MountPath: "/tmp/extensions/",
},
},
SecurityContext: &corev1.SecurityContext{
AllowPrivilegeEscalation: boolPtr(false),
Capabilities: &corev1.Capabilities{
Drop: []corev1.Capability{
"ALL",
},
},
SeccompProfile: &corev1.SeccompProfile{
Type: "RuntimeDefault",
},
},
},
}
}

func removeInitContainer(initContainers []corev1.Container, name string) []corev1.Container {
for i, container := range initContainers {
if container.Name == name {
// Remove the init container by slicing it out
return append(initContainers[:i], initContainers[i+1:]...)
}
}
// If the init container is not found, return the original list
return initContainers
}

func removeVolume(volumes []corev1.Volume, name string) []corev1.Volume {
for i, volume := range volumes {
if volume.Name == name {
return append(volumes[:i], volumes[i+1:]...)
}
}
return volumes
}

func removeVolumeMount(volumeMounts []corev1.VolumeMount, name string) []corev1.VolumeMount {
for i, volumeMount := range volumeMounts {
if volumeMount.Name == name {
return append(volumeMounts[:i], volumeMounts[i+1:]...)
}
}
return volumeMounts
}
63 changes: 63 additions & 0 deletions controllers/argocd/deployment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1427,6 +1427,69 @@ func TestReconcile_SidecarContainers(t *testing.T) {
assert.Len(t, deployment.Spec.Template.Spec.Containers, 1)
}

func TestReconcileServer_RolloutUI(t *testing.T) {
a := makeTestArgoCD(func(a *argoproj.ArgoCD) {
a.Spec.Server.EnableRolloutsUI = true
})

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.reconcileServerDeployment(a, false))

assert.NoError(t, r.Client.Get(
context.TODO(),
types.NamespacedName{
Name: "argocd-server",
Namespace: a.Namespace,
},
deployment))

// Check for the init container
assert.Len(t, deployment.Spec.Template.Spec.InitContainers, 1)
assert.Equal(t, "rollout-extension", deployment.Spec.Template.Spec.InitContainers[0].Name)
assert.Equal(t, common.ArgoCDExtensionInstallerImage, deployment.Spec.Template.Spec.InitContainers[0].Image)

// Check for the volume
foundVolume := false
for _, vol := range deployment.Spec.Template.Spec.Volumes {
if vol.Name == "extensions" {
foundVolume = true
assert.NotNil(t, vol.VolumeSource.EmptyDir)
}
}
assert.True(t, foundVolume, "expected volume 'extensions' to be present")

// Disable rollouts UI
a.Spec.Server.EnableRolloutsUI = false

assert.NoError(t, r.reconcileServerDeployment(a, false))
assert.NoError(t, r.Client.Get(
context.TODO(),
types.NamespacedName{
Name: "argocd-server",
Namespace: a.Namespace,
},
deployment))

assert.Len(t, deployment.Spec.Template.Spec.InitContainers, 0)
assert.Len(t, deployment.Spec.Template.Spec.Containers, 1)
// Check that volume is removed
foundVolume = false
for _, vol := range deployment.Spec.Template.Spec.Volumes {
if vol.Name == "extensions" {
foundVolume = true
}
}
assert.False(t, foundVolume, "expected volume 'extensions' to be removed")

}

func TestArgoCDServerCommand_isMergable(t *testing.T) {
cmd := []string{"--server", "foo.svc.cluster.local", "--path", "/bar"}
extraCMDArgs := []string{"--extra-path", "/"}
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-09-16T21:29:22Z"
createdAt: "2024-10-16T08:53:24Z"
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
Original file line number Diff line number Diff line change
Expand Up @@ -6421,6 +6421,10 @@ spec:
required:
- enabled
type: object
enableRolloutsUI:
description: EnableRolloutsUI will add the Argo Rollouts UI extension
in ArgoCD Dashboard.
type: boolean
env:
description: Env lets you specify environment for API server pods
items:
Expand Down Expand Up @@ -17918,6 +17922,10 @@ spec:
required:
- enabled
type: object
enableRolloutsUI:
description: EnableRolloutsUI will add the Argo Rollouts UI extension
in ArgoCD Dashboard.
type: boolean
enabled:
description: Enabled is the flag to enable ArgoCD Server during
ArgoCD installation. (optional, default `true`)
Expand Down
1 change: 1 addition & 0 deletions docs/reference/argocd.md
Original file line number Diff line number Diff line change
Expand Up @@ -1295,6 +1295,7 @@ The following properties are available for configuring the Argo CD Server compon
Name | Default | Description
--- | --- | ---
[Autoscale](#server-autoscale-options) | [Object] | Server autoscale configuration options.
EnableRolloutsUI | [Empty] | It enables/disables the extension for Argo Rollouts UI in ArgoCD UI when set to true/false.
[ExtraCommandArgs](#server-command-arguments) | [Empty] | List of arguments that will be added to the existing arguments set by the operator.
[GRPC](#server-grpc-options) | [Object] | GRPC configuration options.
Host | example-argocd | The hostname to use for Ingress/Route resources.
Expand Down
58 changes: 58 additions & 0 deletions tests/k8s/1-044_validate_rollout_extension/01-assert.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
apiVersion: argoproj.io/v1beta1
kind: ArgoCD
metadata:
name: argocd
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: argocd-server
spec:
selector:
matchLabels:
app.kubernetes.io/name: argocd-server
template:
spec:
initContainers:
- name: rollout-extension
image: quay.io/argoprojlabs/argocd-extension-installer:v0.0.8
env:
- name: EXTENSION_URL
value: https://github.com/argoproj-labs/rollout-extension/releases/download/v0.3.6/extension.tar
volumeMounts:
- name: extensions
mountPath: /tmp/extensions/
volumes:
- configMap:
defaultMode: 420
name: argocd-ssh-known-hosts-cm
name: ssh-known-hosts
- configMap:
defaultMode: 420
name: argocd-tls-certs-cm
name: tls-certs
- name: argocd-repo-server-tls
secret:
defaultMode: 420
optional: true
secretName: argocd-repo-server-tls
- name: argocd-operator-redis-tls
secret:
defaultMode: 420
optional: true
secretName: argocd-operator-redis-tls
- emptyDir: {}
name: extensions
containers:
- name: argocd-server
volumeMounts:
- mountPath: /app/config/ssh
name: ssh-known-hosts
- mountPath: /app/config/tls
name: tls-certs
- mountPath: /app/config/server/tls
name: argocd-repo-server-tls
- mountPath: /app/config/server/tls/redis
name: argocd-operator-redis-tls
- mountPath: /tmp/extensions/
name: extensions
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
apiVersion: argoproj.io/v1beta1
kind: ArgoCD
metadata:
name: argocd
spec:
server:
enableRolloutsUI: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
apiVersion: argoproj.io/v1beta1
kind: ArgoCD
metadata:
name: argocd
spec:
server:
enableRolloutsUI: false
Loading

0 comments on commit 833a92e

Please sign in to comment.