Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add option to enable argo-rollout ui extension #1554

Merged
merged 9 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading