From 1d49edcec48865d4150ffe007f2b975de2a5ac92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20Gond=C5=BEa?= Date: Mon, 26 Oct 2026 17:48:13 +0100 Subject: [PATCH 1/5] test(e2e): Unify 1-020_validate_redis_ha_nonha_test.go from argocd-operator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Oliver Gondža --- .../1-020_validate_redis_ha_nonha_test.go | 232 ------------------ .../1-020_validate_redis_ha_nonha_test.go | 111 ++++++--- 2 files changed, 72 insertions(+), 271 deletions(-) delete mode 100644 argocd-operator/tests/ginkgo/sequential/1-020_validate_redis_ha_nonha_test.go diff --git a/argocd-operator/tests/ginkgo/sequential/1-020_validate_redis_ha_nonha_test.go b/argocd-operator/tests/ginkgo/sequential/1-020_validate_redis_ha_nonha_test.go deleted file mode 100644 index fcc0df8fbd4..00000000000 --- a/argocd-operator/tests/ginkgo/sequential/1-020_validate_redis_ha_nonha_test.go +++ /dev/null @@ -1,232 +0,0 @@ -/* -Copyright 2025. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package sequential - -import ( - "context" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - "sigs.k8s.io/controller-runtime/pkg/client" - - argov1beta1api "github.com/redhat-developer/gitops-operator/argocd-operator/api/v1beta1" - "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture" - argocdFixture "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture/argocd" - deploymentFixture "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture/deployment" - k8sFixture "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture/k8s" - nodeFixture "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture/node" - statefulsetFixture "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture/statefulset" - "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture/utils" - - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/intstr" -) - -var _ = Describe("GitOps Operator Sequential E2E Tests", func() { - - Context("1-020_validate_redis_ha_nonha", func() { - - BeforeEach(func() { - fixture.EnsureSequentialCleanSlate() - }) - - var ( - k8sClient client.Client - ctx context.Context - cleanupFunc func() - ns *corev1.Namespace - ) - - BeforeEach(func() { - - fixture.EnsureSequentialCleanSlate() - k8sClient, _ = utils.GetE2ETestKubeClient() - ctx = context.Background() - }) - - AfterEach(func() { - fixture.OutputDebugOnFail(ns) - if ns != nil { - cleanupFunc() - } - }) - - It("validates Redis HA and Non-HA", func() { - - // This test enables HA, so it needs to be running on a cluster with at least 3 nodes - nodeFixture.ExpectHasAtLeastXNodes(3) - - By("creating simple namespace-scoped Argo CD instance") - ns, cleanupFunc = fixture.CreateRandomE2ETestNamespaceWithCleanupFunc() - - argoCDInstance := &argov1beta1api.ArgoCD{ - ObjectMeta: metav1.ObjectMeta{Name: "example-argocd", Namespace: ns.Name, - Labels: map[string]string{"example": "basic"}}, - Spec: argov1beta1api.ArgoCDSpec{}, - } - Expect(k8sClient.Create(ctx, argoCDInstance)).To(Succeed()) - - Eventually(argoCDInstance, "5m", "5s").Should(argocdFixture.BeAvailable()) - Eventually(argoCDInstance).Should(argocdFixture.HaveRedisStatus("Running")) - - By("verifying various expected resources exist in namespace") - Eventually(&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis", Namespace: ns.Name}}).Should(k8sFixture.ExistByName()) - - depl := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis", Namespace: ns.Name}} - Eventually(depl).Should(k8sFixture.ExistByName()) - Eventually(depl).Should(deploymentFixture.HaveReadyReplicas(1)) - - By("verifies Redis HA resources should not exist since we are in non-HA mode") - - Consistently(&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis-ha", Namespace: ns.Name}}).Should(k8sFixture.NotExistByName()) - - Consistently(&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis-ha-haproxy", Namespace: ns.Name}}).Should(k8sFixture.NotExistByName()) - - Consistently(&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis-ha-haproxy", Namespace: ns.Name}}).Should(k8sFixture.NotExistByName()) - - Consistently(&appsv1.StatefulSet{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis-ha-server", Namespace: ns.Name}}).Should(k8sFixture.NotExistByName()) - - By("enabling HA on Argo CD instance") - argocdFixture.Update(argoCDInstance, func(argocd *argov1beta1api.ArgoCD) { - argocd.Spec.HA.Enabled = true - }) - - By("verifying expected HA resources are eventually created after we enabled HA") - - Eventually(&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis-ha", Namespace: ns.Name}}).Should(k8sFixture.ExistByName()) - - Eventually(&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis-ha-haproxy", Namespace: ns.Name}}).Should(k8sFixture.ExistByName()) - - Eventually(argoCDInstance, "4m", "5s").Should(argocdFixture.HavePhase("Available")) - Eventually(argoCDInstance).Should(argocdFixture.HaveRedisStatus("Running")) - - statefulSet := &appsv1.StatefulSet{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis-ha-server", Namespace: ns.Name}} - Eventually(statefulSet).Should(statefulsetFixture.HaveReadyReplicas(3)) - Expect(statefulSet.Spec.Template.Spec.Affinity).To(Equal( - &corev1.Affinity{ - PodAntiAffinity: &corev1.PodAntiAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: []corev1.PodAffinityTerm{ - { - LabelSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "app.kubernetes.io/name": argoCDInstance.Name + "-redis-ha", - }, - }, - TopologyKey: "kubernetes.io/hostname", - }, - }, - }, - })) - - Eventually(&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis-ha-haproxy", Namespace: ns.Name}}, "60s", "5s").Should(deploymentFixture.HaveReadyReplicas(3)) - - By("verifying non-HA resources no longer exist, since HA is enabled") - - Expect(&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis", Namespace: ns.Name}}).To(k8sFixture.NotExistByName()) - - Expect(&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis", Namespace: ns.Name}}).To(k8sFixture.NotExistByName()) - - By("updating ArgoCD CR to add cpu and memory resource request and limits to HA workloads") - - argocdFixture.Update(argoCDInstance, func(argocd *argov1beta1api.ArgoCD) { - argocd.Spec.HA.Enabled = true - argocd.Spec.HA.Resources = &corev1.ResourceRequirements{ - Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("500m"), - corev1.ResourceMemory: resource.MustParse("256Mi"), - }, - Requests: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse("200m"), - corev1.ResourceMemory: resource.MustParse("128Mi"), - }, - } - }) - - By("Argo CD should eventually be ready after updating the resource requirements") - Eventually(argoCDInstance, "5m", "5s").Should(argocdFixture.BeAvailable()) // it can take a while to schedule the Pods - Eventually(argoCDInstance, "5m", "5s").Should(argocdFixture.HaveRedisStatus("Running")) - - By("verifying Deployment and StatefulSet have expected resources that we set in previous step") - - depl = &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis-ha-haproxy", Namespace: ns.Name}} - Eventually(depl, "2m", "5s").Should(deploymentFixture.HaveReadyReplicas(3)) - Expect(depl.Spec.Strategy.RollingUpdate.MaxSurge).To(Equal(&intstr.IntOrString{IntVal: 0})) - - haProxyContainer := deploymentFixture.GetTemplateSpecContainerByName("haproxy", *depl) - - Expect(haProxyContainer).ToNot(BeNil()) - Expect(haProxyContainer.Resources.Limits.Cpu().AsDec().String()).To(Equal("0.500")) - Expect(haProxyContainer.Resources.Limits.Memory().AsDec().String()).To(Equal("268435456")) // 256Mib in bytes - Expect(haProxyContainer.Resources.Requests.Cpu().AsDec().String()).To(Equal("0.200")) - Expect(haProxyContainer.Resources.Requests.Memory().AsDec().String()).To(Equal("134217728")) // 128MiB in bytes - - configInitContainer := deploymentFixture.GetTemplateSpecInitContainerByName("config-init", *depl) - - Expect(configInitContainer.Resources.Limits.Cpu().AsDec().String()).To(Equal("0.500")) - Expect(configInitContainer.Resources.Limits.Memory().AsDec().String()).To(Equal("268435456")) - Expect(configInitContainer.Resources.Requests.Cpu().AsDec().String()).To(Equal("0.200")) - Expect(configInitContainer.Resources.Requests.Memory().AsDec().String()).To(Equal("134217728")) - - ss := &appsv1.StatefulSet{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis-ha-server", Namespace: ns.Name}} - Eventually(ss, "4m", "5s").Should(statefulsetFixture.HaveReadyReplicas(3)) - - redisContainer := statefulsetFixture.GetTemplateSpecContainerByName("redis", *ss) - Expect(redisContainer).ToNot(BeNil()) - Expect(redisContainer.Resources.Limits.Cpu().AsDec().String()).To(Equal("0.500")) - Expect(redisContainer.Resources.Limits.Memory().AsDec().String()).To(Equal("268435456")) - Expect(redisContainer.Resources.Requests.Cpu().AsDec().String()).To(Equal("0.200")) - Expect(redisContainer.Resources.Requests.Memory().AsDec().String()).To(Equal("134217728")) - - sentinelContainer := statefulsetFixture.GetTemplateSpecContainerByName("sentinel", *ss) - Expect(sentinelContainer).ToNot(BeNil()) - Expect(sentinelContainer.Resources.Limits.Cpu().AsDec().String()).To(Equal("0.500")) - Expect(sentinelContainer.Resources.Limits.Memory().AsDec().String()).To(Equal("268435456")) - Expect(sentinelContainer.Resources.Requests.Cpu().AsDec().String()).To(Equal("0.200")) - Expect(sentinelContainer.Resources.Requests.Memory().AsDec().String()).To(Equal("134217728")) - - configInitContainer = statefulsetFixture.GetTemplateSpecInitContainerByName("config-init", *ss) - Expect(configInitContainer.Resources.Limits.Cpu().AsDec().String()).To(Equal("0.500")) - Expect(configInitContainer.Resources.Limits.Memory().AsDec().String()).To(Equal("268435456")) - Expect(configInitContainer.Resources.Requests.Cpu().AsDec().String()).To(Equal("0.200")) - Expect(configInitContainer.Resources.Requests.Memory().AsDec().String()).To(Equal("134217728")) - - By("disabling HA on ArgoCD CR") - - argocdFixture.Update(argoCDInstance, func(argocd *argov1beta1api.ArgoCD) { - argocd.Spec.HA.Enabled = false - }) - - By("verifying Argo CD becomes ready again after HA is disabled") - - Eventually(argoCDInstance, "5m", "5s").Should(argocdFixture.BeAvailable()) - Eventually(argoCDInstance, "60s", "5s").Should(argocdFixture.HaveRedisStatus("Running")) - - By("verifying expected non-HA resources exist again and HA resources no longer exist") - depl = &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis", Namespace: ns.Name}} - Eventually(depl).Should(k8sFixture.ExistByName()) - Eventually(depl).Should(deploymentFixture.HaveReadyReplicas(1)) - - Consistently(&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis-ha-haproxy", Namespace: ns.Name}}).Should(k8sFixture.NotExistByName()) - - Consistently(&appsv1.StatefulSet{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis-ha-server", Namespace: ns.Name}}).Should(k8sFixture.NotExistByName()) - - }) - }) -}) diff --git a/test/openshift/e2e/ginkgo/sequential/1-020_validate_redis_ha_nonha_test.go b/test/openshift/e2e/ginkgo/sequential/1-020_validate_redis_ha_nonha_test.go index 4f5459403bc..ecc10529e77 100644 --- a/test/openshift/e2e/ginkgo/sequential/1-020_validate_redis_ha_nonha_test.go +++ b/test/openshift/e2e/ginkgo/sequential/1-020_validate_redis_ha_nonha_test.go @@ -17,20 +17,26 @@ limitations under the License. package sequential import ( + "context" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - "github.com/redhat-developer/gitops-operator/argocd-operator/api/v1beta1" + "sigs.k8s.io/controller-runtime/pkg/client" + + argov1beta1api "github.com/redhat-developer/gitops-operator/argocd-operator/api/v1beta1" "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture" argocdFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/argocd" deploymentFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/deployment" k8sFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/k8s" nodeFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/node" statefulsetFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/statefulset" + "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/utils" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" ) var _ = Describe("GitOps Operator Sequential E2E Tests", func() { @@ -41,51 +47,77 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { fixture.EnsureSequentialCleanSlate() }) + var ( + k8sClient client.Client + ctx context.Context + cleanupFunc func() + ns *corev1.Namespace + ) + + BeforeEach(func() { + + fixture.EnsureSequentialCleanSlate() + k8sClient, _ = utils.GetE2ETestKubeClient() + ctx = context.Background() + }) + + AfterEach(func() { + fixture.OutputDebugOnFail(ns) + if ns != nil { + cleanupFunc() + } + }) + It("validates Redis HA and Non-HA", func() { // This test enables HA, so it needs to be running on a cluster with at least 3 nodes nodeFixture.ExpectHasAtLeastXNodes(3) - ns, cleanupFunc := fixture.CreateRandomE2ETestNamespaceWithCleanupFunc() - defer cleanupFunc() + By("creating simple namespace-scoped Argo CD instance") + ns, cleanupFunc = fixture.CreateRandomE2ETestNamespaceWithCleanupFunc() + + argoCDInstance := &argov1beta1api.ArgoCD{ + ObjectMeta: metav1.ObjectMeta{Name: "example-argocd", Namespace: ns.Name, + Labels: map[string]string{"example": "basic"}}, + Spec: argov1beta1api.ArgoCDSpec{}, + } + Expect(k8sClient.Create(ctx, argoCDInstance)).To(Succeed()) - By("creating a new Argo CD instance and waiting for it to be ready") - argoCD := argocdFixture.CreateNewArgoCDInstance("argocd-020", ns.Name) - Eventually(argoCD, "5m", "5s").Should(argocdFixture.BeAvailable()) - Eventually(argoCD).Should(argocdFixture.HaveRedisStatus("Running")) + Eventually(argoCDInstance, "5m", "5s").Should(argocdFixture.BeAvailable()) + Eventually(argoCDInstance).Should(argocdFixture.HaveRedisStatus("Running")) By("verifying various expected resources exist in namespace") - Eventually(&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: "argocd-020-redis", Namespace: ns.Name}}).Should(k8sFixture.ExistByName()) + Eventually(&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis", Namespace: ns.Name}}).Should(k8sFixture.ExistByName()) - depl := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: "argocd-020-redis", Namespace: ns.Name}} + depl := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis", Namespace: ns.Name}} Eventually(depl).Should(k8sFixture.ExistByName()) Eventually(depl).Should(deploymentFixture.HaveReadyReplicas(1)) By("verifies Redis HA resources should not exist since we are in non-HA mode") - Consistently(&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: "argocd-020-redis-ha", Namespace: ns.Name}}).Should(k8sFixture.NotExistByName()) + Consistently(&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis-ha", Namespace: ns.Name}}).Should(k8sFixture.NotExistByName()) - Consistently(&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: "argocd-020-redis-ha-haproxy", Namespace: ns.Name}}).Should(k8sFixture.NotExistByName()) + Consistently(&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis-ha-haproxy", Namespace: ns.Name}}).Should(k8sFixture.NotExistByName()) - Consistently(&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: "argocd-020-redis-ha-haproxy", Namespace: ns.Name}}).Should(k8sFixture.NotExistByName()) + Consistently(&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis-ha-haproxy", Namespace: ns.Name}}).Should(k8sFixture.NotExistByName()) - Consistently(&appsv1.StatefulSet{ObjectMeta: metav1.ObjectMeta{Name: "argocd-020-redis-ha-server", Namespace: ns.Name}}).Should(k8sFixture.NotExistByName()) + Consistently(&appsv1.StatefulSet{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis-ha-server", Namespace: ns.Name}}).Should(k8sFixture.NotExistByName()) By("enabling HA on Argo CD instance") - argocdFixture.Update(argoCD, func(ac *v1beta1.ArgoCD) { - ac.Spec.HA.Enabled = true + argocdFixture.Update(argoCDInstance, func(argocd *argov1beta1api.ArgoCD) { + argocd.Spec.HA.Enabled = true }) By("verifying expected HA resources are eventually created after we enabled HA") - Eventually(&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: "argocd-020-redis-ha", Namespace: ns.Name}}).Should(k8sFixture.ExistByName()) + Eventually(&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis-ha", Namespace: ns.Name}}).Should(k8sFixture.ExistByName()) - Eventually(&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: "argocd-020-redis-ha-haproxy", Namespace: ns.Name}}).Should(k8sFixture.ExistByName()) + Eventually(&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis-ha-haproxy", Namespace: ns.Name}}).Should(k8sFixture.ExistByName()) - Eventually(argoCD, "4m", "5s").Should(argocdFixture.HavePhase("Available")) - Eventually(argoCD).Should(argocdFixture.HaveRedisStatus("Running")) + Eventually(argoCDInstance, "4m", "5s").Should(argocdFixture.HavePhase("Available")) + Eventually(argoCDInstance).Should(argocdFixture.HaveRedisStatus("Running")) - statefulSet := &appsv1.StatefulSet{ObjectMeta: metav1.ObjectMeta{Name: "argocd-020-redis-ha-server", Namespace: ns.Name}} + statefulSet := &appsv1.StatefulSet{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis-ha-server", Namespace: ns.Name}} Eventually(statefulSet).Should(statefulsetFixture.HaveReadyReplicas(3)) Expect(statefulSet.Spec.Template.Spec.Affinity).To(Equal( &corev1.Affinity{ @@ -94,7 +126,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { { LabelSelector: &metav1.LabelSelector{ MatchLabels: map[string]string{ - "app.kubernetes.io/name": "argocd-020-redis-ha", + "app.kubernetes.io/name": argoCDInstance.Name + "-redis-ha", }, }, TopologyKey: "kubernetes.io/hostname", @@ -103,19 +135,19 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { }, })) - Eventually(&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: "argocd-020-redis-ha-haproxy", Namespace: ns.Name}}, "60s", "5s").Should(deploymentFixture.HaveReadyReplicas(3)) + Eventually(&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis-ha-haproxy", Namespace: ns.Name}}, "60s", "5s").Should(deploymentFixture.HaveReadyReplicas(3)) By("verifying non-HA resources no longer exist, since HA is enabled") - Expect(&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: "argocd-020-redis", Namespace: ns.Name}}).To(k8sFixture.NotExistByName()) + Expect(&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis", Namespace: ns.Name}}).To(k8sFixture.NotExistByName()) - Expect(&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: "argocd-020-redis", Namespace: ns.Name}}).To(k8sFixture.NotExistByName()) + Expect(&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis", Namespace: ns.Name}}).To(k8sFixture.NotExistByName()) By("updating ArgoCD CR to add cpu and memory resource request and limits to HA workloads") - argocdFixture.Update(argoCD, func(ac *v1beta1.ArgoCD) { - ac.Spec.HA.Enabled = true - ac.Spec.HA.Resources = &corev1.ResourceRequirements{ + argocdFixture.Update(argoCDInstance, func(argocd *argov1beta1api.ArgoCD) { + argocd.Spec.HA.Enabled = true + argocd.Spec.HA.Resources = &corev1.ResourceRequirements{ Limits: corev1.ResourceList{ corev1.ResourceCPU: resource.MustParse("500m"), corev1.ResourceMemory: resource.MustParse("256Mi"), @@ -128,13 +160,14 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { }) By("Argo CD should eventually be ready after updating the resource requirements") - Eventually(argoCD, "5m", "5s").Should(argocdFixture.BeAvailable()) // it can take a while to schedule the Pods - Eventually(argoCD, "5m", "5s").Should(argocdFixture.HaveRedisStatus("Running")) + Eventually(argoCDInstance, "5m", "5s").Should(argocdFixture.BeAvailable()) // it can take a while to schedule the Pods + Eventually(argoCDInstance, "5m", "5s").Should(argocdFixture.HaveRedisStatus("Running")) By("verifying Deployment and StatefulSet have expected resources that we set in previous step") - depl = &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: "argocd-020-redis-ha-haproxy", Namespace: ns.Name}} + depl = &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis-ha-haproxy", Namespace: ns.Name}} Eventually(depl, "2m", "5s").Should(deploymentFixture.HaveReadyReplicas(3)) + Expect(depl.Spec.Strategy.RollingUpdate.MaxSurge).To(Equal(&intstr.IntOrString{IntVal: 0})) haProxyContainer := deploymentFixture.GetTemplateSpecContainerByName("haproxy", *depl) @@ -151,8 +184,8 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { Expect(configInitContainer.Resources.Requests.Cpu().AsDec().String()).To(Equal("0.200")) Expect(configInitContainer.Resources.Requests.Memory().AsDec().String()).To(Equal("134217728")) - ss := &appsv1.StatefulSet{ObjectMeta: metav1.ObjectMeta{Name: "argocd-020-redis-ha-server", Namespace: ns.Name}} - Eventually(ss, "2m", "5s").Should(statefulsetFixture.HaveReadyReplicas(3)) + ss := &appsv1.StatefulSet{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis-ha-server", Namespace: ns.Name}} + Eventually(ss, "4m", "5s").Should(statefulsetFixture.HaveReadyReplicas(3)) redisContainer := statefulsetFixture.GetTemplateSpecContainerByName("redis", *ss) Expect(redisContainer).ToNot(BeNil()) @@ -176,23 +209,23 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { By("disabling HA on ArgoCD CR") - argocdFixture.Update(argoCD, func(ac *v1beta1.ArgoCD) { - ac.Spec.HA.Enabled = false + argocdFixture.Update(argoCDInstance, func(argocd *argov1beta1api.ArgoCD) { + argocd.Spec.HA.Enabled = false }) By("verifying Argo CD becomes ready again after HA is disabled") - Eventually(argoCD, "5m", "5s").Should(argocdFixture.BeAvailable()) - Eventually(argoCD, "60s", "5s").Should(argocdFixture.HaveRedisStatus("Running")) + Eventually(argoCDInstance, "5m", "5s").Should(argocdFixture.BeAvailable()) + Eventually(argoCDInstance, "60s", "5s").Should(argocdFixture.HaveRedisStatus("Running")) By("verifying expected non-HA resources exist again and HA resources no longer exist") - depl = &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: "argocd-020-redis", Namespace: ns.Name}} + depl = &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis", Namespace: ns.Name}} Eventually(depl).Should(k8sFixture.ExistByName()) Eventually(depl).Should(deploymentFixture.HaveReadyReplicas(1)) - Consistently(&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: "argocd-020-redis-ha-haproxy", Namespace: ns.Name}}).Should(k8sFixture.NotExistByName()) + Consistently(&appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis-ha-haproxy", Namespace: ns.Name}}).Should(k8sFixture.NotExistByName()) - Consistently(&appsv1.StatefulSet{ObjectMeta: metav1.ObjectMeta{Name: "argocd-020-redis-ha-server", Namespace: ns.Name}}).Should(k8sFixture.NotExistByName()) + Consistently(&appsv1.StatefulSet{ObjectMeta: metav1.ObjectMeta{Name: argoCDInstance.Name + "-redis-ha-server", Namespace: ns.Name}}).Should(k8sFixture.NotExistByName()) }) }) From ec672ba0c1391f674ee0a8275b64c951cf704325 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20Gond=C5=BEa?= Date: Mon, 26 Oct 2026 19:31:04 +0100 Subject: [PATCH 2/5] test(e2e): Unify 1-037_validate_applicationset_in_any_namespace_test.go from argocd-operator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Oliver Gondža --- ...te_applicationset_in_any_namespace_test.go | 1500 ----------------- ...te_applicationset_in_any_namespace_test.go | 84 +- 2 files changed, 81 insertions(+), 1503 deletions(-) delete mode 100644 argocd-operator/tests/ginkgo/sequential/1-037_validate_applicationset_in_any_namespace_test.go diff --git a/argocd-operator/tests/ginkgo/sequential/1-037_validate_applicationset_in_any_namespace_test.go b/argocd-operator/tests/ginkgo/sequential/1-037_validate_applicationset_in_any_namespace_test.go deleted file mode 100644 index 87af8d1c03a..00000000000 --- a/argocd-operator/tests/ginkgo/sequential/1-037_validate_applicationset_in_any_namespace_test.go +++ /dev/null @@ -1,1500 +0,0 @@ -package sequential - -import ( - "context" - "fmt" - "slices" - "strings" - - "github.com/argoproj/argo-cd/gitops-engine/pkg/health" - appv1alpha1 "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1" - - "github.com/redhat-developer/gitops-operator/argocd-operator/api/v1beta1" - "github.com/redhat-developer/gitops-operator/argocd-operator/common" - "github.com/redhat-developer/gitops-operator/argocd-operator/controllers/argocd" - "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture" - applicationFixture "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture/application" - appprojectFixture "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture/appproject" - argocdFixture "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture/argocd" - clusterroleFixture "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture/clusterrole" - configmapFixture "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture/configmap" - deploymentFixture "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture/deployment" - k8sFixture "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture/k8s" - namespaceFixture "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture/namespace" - roleFixture "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture/role" - "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture/utils" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - rbacv1 "k8s.io/api/rbac/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "sigs.k8s.io/controller-runtime/pkg/client" -) - -var _ = Describe("GitOps Operator Sequential E2E Tests", func() { - - Context("1-037_validate_applicationset_in_any_namespace", func() { - - var ( - ctx context.Context - k8sClient client.Client - cleanupFunctions = []func(){} // we create various namespaces in this test, these functions will clean them up when the test is done - - ) - - BeforeEach(func() { - - fixture.EnsureSequentialCleanSlate() - k8sClient, _ = utils.GetE2ETestKubeClient() - ctx = context.Background() - }) - - AfterEach(func() { - - fixture.OutputDebugOnFail("appset-argocd", "appset-old-ns", "appset-new-ns", "appset-namespace-scoped", "target-ns-1-037", - "team-1", "team-2", "team-frontend", "team-backend", "team-3", "other-ns", "appset-argocd-clusterrole", "appset-target-ns") - - // Clean up namespaces created - for _, namespaceCleanupFunction := range cleanupFunctions { - namespaceCleanupFunction() - } - - }) - - It("verifying that ArgoCD CR '.spec.applicationset.sourcenamespaces' and '.spec.sourcenamespaces' correctly control role/rolebindings within the managed namespaces", func() { - - By("0) create namespaces: appset-argocd, appset-old-ns, appset-new-ns") - - appset_argocdNS, cleanupFunc := fixture.CreateNamespaceWithCleanupFunc("appset-argocd") - cleanupFunctions = append(cleanupFunctions, cleanupFunc) - - appset_old_nsNS, cleanupFunc := fixture.CreateNamespaceWithCleanupFunc("appset-old-ns") - cleanupFunctions = append(cleanupFunctions, cleanupFunc) - - appset_new_nsNS, cleanupFunc := fixture.CreateNamespaceWithCleanupFunc("appset-new-ns") - cleanupFunctions = append(cleanupFunctions, cleanupFunc) - - // ----- - - By("1) create Argo CD instance with no source namespaces") - - argoCD := &v1beta1.ArgoCD{ - ObjectMeta: metav1.ObjectMeta{ - Name: "example", - Namespace: appset_argocdNS.Name, - }, - Spec: v1beta1.ArgoCDSpec{ - ApplicationSet: &v1beta1.ArgoCDApplicationSet{ - SCMProviders: []string{ - "github.com", - }, - }, - }, - } - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - By("verifying that the appset deployment does not contains 'applications in any namespace' parameter, since no source namespaces are specified") - appsetDeployment := &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "example-applicationset-controller", - Namespace: argoCD.Namespace, - }, - } - Eventually(appsetDeployment).Should(k8sFixture.ExistByName()) - Expect(appsetDeployment).ShouldNot(deploymentFixture.HaveContainerCommandSubstring("--applicationset-namespaces", 0)) - - Eventually(argoCD, "5m", "5s").Should(argocdFixture.BeAvailable()) - Eventually(argoCD).Should(argocdFixture.HaveApplicationSetControllerStatus("Running")) - - // Verifies that the role/rolebindings in the specified namespace are not managed by application controller or appset, in the given namespace - expectRoleAndRoleBindingAndNamespaceToNotBeManaged := func(names []string, namespaceName string) { - - By(fmt.Sprintf("verifying that expected Role/Rolebindings %v exist in %s", names, namespaceName)) - for _, roleAndRoleBindingName := range names { - - By("verifying '" + roleAndRoleBindingName + "'") - - role := &rbacv1.Role{ - ObjectMeta: metav1.ObjectMeta{ - Name: roleAndRoleBindingName, - Namespace: namespaceName, - }, - } - Eventually(role).Should(k8sFixture.NotExistByName()) - Consistently(role).Should(k8sFixture.NotExistByName()) - - roleBinding := &rbacv1.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: roleAndRoleBindingName, - Namespace: namespaceName, - }, - } - Eventually(roleBinding).Should(k8sFixture.NotExistByName()) - Consistently(roleBinding).Should(k8sFixture.NotExistByName()) - - } - - nsToCheck := &corev1.Namespace{ - ObjectMeta: metav1.ObjectMeta{ - Name: namespaceName, - }, - } - - By("verifying that namespace" + namespaceName + " does not have label 'argocd.argoproj.io/applicationset-managed-by-cluster-argocd': 'appset-argocd'") - Eventually(nsToCheck).ShouldNot(namespaceFixture.HaveLabel("argocd.argoproj.io/applicationset-managed-by-cluster-argocd", "appset-argocd")) - Consistently(nsToCheck).ShouldNot(namespaceFixture.HaveLabel("argocd.argoproj.io/applicationset-managed-by-cluster-argocd", "appset-argocd")) - - } - - expectRoleAndRoleBindingAndNamespaceToNotBeManaged([]string{"example_appset-old-ns", "example-appset-argocd-applicationset"}, appset_old_nsNS.Name) - - // ---- - - By("2) modifying ArgoCD to have one sourceNamespace: appset-old-ns") - - argocdFixture.Update(argoCD, func(ac *v1beta1.ArgoCD) { - - ac.Spec.ApplicationSet.SourceNamespaces = []string{ - "appset-old-ns", - } - - ac.Spec.ApplicationSet.SCMProviders = []string{ - "github.com", - } - - }) - - Eventually(argoCD, "5m", "5s").Should(argocdFixture.BeAvailable()) - - By("verifying that the appset deployment does not contain 'applications in any namespace' parameter, because .spec.sourceNamespaces is not specified") - appsetDeployment = &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "example-applicationset-controller", - Namespace: argoCD.Namespace, - }, - } - Eventually(appsetDeployment).Should(k8sFixture.ExistByName()) - Eventually(appsetDeployment).ShouldNot(deploymentFixture.HaveContainerCommandSubstring("--applicationset-namespaces", 0)) - - expectRoleAndRoleBindingAndNamespaceToNotBeManaged([]string{"example_appset-old-ns", "example-appset-argocd-applicationset"}, appset_old_nsNS.Name) - - // ---- - - By("3) modifying ArgoCD to have 2 sourceNamespaces: appset-old-ns, appset-new-ns") - - argocdFixture.Update(argoCD, func(ac *v1beta1.ArgoCD) { - - ac.Spec.ApplicationSet.SourceNamespaces = []string{ - "appset-old-ns", - "appset-new-ns", - } - - ac.Spec.ApplicationSet.SCMProviders = []string{ - "github.com", - } - - }) - - Eventually(argoCD, "5m", "5s").Should(argocdFixture.BeAvailable()) - - expectRoleAndRoleBindingAndNamespaceToNotBeManaged([]string{"example_appset-new-ns", "example-appset-argocd-applicationset"}, appset_new_nsNS.Name) - expectRoleAndRoleBindingAndNamespaceToNotBeManaged([]string{"example_appset-old-ns", "example-appset-argocd-applicationset"}, appset_old_nsNS.Name) - - // ---- - - By("4) Add a sourceNamespace of 'appset-new-ns' to ArgoCD CR") - - argocdFixture.Update(argoCD, func(ac *v1beta1.ArgoCD) { - - ac.Spec.SourceNamespaces = []string{ - "appset-new-ns", - } - - ac.Spec.ApplicationSet.SourceNamespaces = []string{ - "appset-old-ns", - "appset-new-ns", - } - - ac.Spec.ApplicationSet.SCMProviders = []string{ - "github.com", - } - }) - - By("verifying appset namespaces parameter exists, and it points to only the namespace specified in .spec.sourceNamespaces") - Eventually(appsetDeployment).Should(k8sFixture.ExistByName()) - Eventually(appsetDeployment).Should(deploymentFixture.HaveContainerCommandSubstring("--applicationset-namespaces appset-new-ns", 0)) - - By("verifying that Role in appset-new-ns has expected RBAC permissions: ability to modify applications, batch, and applicationsets") - example_appset_new_nsRole := &rbacv1.Role{ - ObjectMeta: metav1.ObjectMeta{Name: "example_appset-new-ns", Namespace: appset_new_nsNS.Name}, - } - Eventually(example_appset_new_nsRole).Should(k8sFixture.ExistByName()) - - Eventually(example_appset_new_nsRole).Should(roleFixture.HaveRules([]rbacv1.PolicyRule{ - { - APIGroups: []string{"argoproj.io"}, - Resources: []string{"applications"}, - Verbs: []string{ - "create", - "get", - "list", - "patch", - "update", - "watch", - "delete", - }, - }, - { - APIGroups: []string{"argoproj.io"}, - Resources: []string{"applicationsets"}, - Verbs: []string{ - "create", - "get", - "list", - "patch", - "update", - "watch", - "delete", - }, - }, - })) - - By("verifying RoleBinding for argocd-server and argocd-application-controller exists in appset-new-ns namespace") - example_appset_new_nsRoleBinding := &rbacv1.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: "example_appset-new-ns", - Namespace: appset_new_nsNS.Name, - }, - } - Eventually(example_appset_new_nsRoleBinding).Should(k8sFixture.ExistByName()) - Expect(example_appset_new_nsRoleBinding.RoleRef).To(Equal(rbacv1.RoleRef{ - - APIGroup: "rbac.authorization.k8s.io", - Kind: "Role", - Name: "example_appset-new-ns", - })) - Expect(example_appset_new_nsRoleBinding.Subjects).To(Equal([]rbacv1.Subject{ - { - Kind: "ServiceAccount", - Name: "example-argocd-server", - Namespace: "appset-argocd", - }, - { - Kind: "ServiceAccount", - Name: "example-argocd-application-controller", - Namespace: "appset-argocd", - }, - })) - - example_appset_argocd_applicationsetRole := &rbacv1.Role{ - ObjectMeta: metav1.ObjectMeta{ - Name: "example-appset-argocd-applicationset", - Namespace: "appset-new-ns", - }, - } - Eventually(example_appset_argocd_applicationsetRole).Should(k8sFixture.ExistByName()) - - example_appset_argocd_applicationsetRoleBinding := &rbacv1.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: "example-appset-argocd-applicationset", - Namespace: "appset-new-ns", - }, - } - Eventually(example_appset_argocd_applicationsetRoleBinding).Should(k8sFixture.ExistByName()) - - By("verifying appset-new-ns namespace is managed as both a source namespace and an application set source namespace") - - Eventually(appset_new_nsNS).Should(namespaceFixture.HaveLabel("argocd.argoproj.io/applicationset-managed-by-cluster-argocd", "appset-argocd")) - - Eventually(appset_new_nsNS).Should(namespaceFixture.HaveLabel("argocd.argoproj.io/managed-by-cluster-argocd", "appset-argocd")) - - expectRoleAndRoleBindingAndNamespaceToNotBeManaged([]string{"example_appset-old-ns", "example-appset-argocd-applicationset"}, appset_old_nsNS.Name) - - // ---- - - // appset resources should be created in appset-old-ns namespace as it is now a subset of sourceNamespaces i.e apps in any ns is enabled on appset-old-ns namespace - By("5) Adds 'appset-old-ns' to spec.sourceNamespace") - - argocdFixture.Update(argoCD, func(ac *v1beta1.ArgoCD) { - - ac.Spec.SourceNamespaces = []string{ - "appset-new-ns", - "appset-old-ns", - } - - ac.Spec.ApplicationSet.SourceNamespaces = []string{ - "appset-old-ns", - "appset-new-ns", - } - - ac.Spec.ApplicationSet.SCMProviders = []string{ - "github.com", - } - }) - - Eventually(appsetDeployment).Should(k8sFixture.ExistByName()) - Eventually(appsetDeployment).Should(deploymentFixture.HaveContainerCommandSubstring("--applicationset-namespaces appset-new-ns,appset-old-ns", 0)) - - By("verifying that appset-old-ns gains Role/RoleBindings similar to appset-new-ns") - example_appset_old_nsRole := &rbacv1.Role{ - ObjectMeta: metav1.ObjectMeta{ - Name: "example_appset-old-ns", - Namespace: appset_old_nsNS.Name, - }, - } - - Eventually(example_appset_old_nsRole).Should(roleFixture.HaveRules([]rbacv1.PolicyRule{ - { - APIGroups: []string{"argoproj.io"}, - Resources: []string{"applications"}, - Verbs: []string{ - "create", - "get", - "list", - "patch", - "update", - "watch", - "delete", - }, - }, - { - APIGroups: []string{"argoproj.io"}, - Resources: []string{ - "applicationsets", - }, - Verbs: []string{ - "create", - "get", - "list", - "patch", - "update", - "watch", - "delete", - }, - }, - })) - - example_appset_old_nsRoleBinding := &rbacv1.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: "example_appset-old-ns", - Namespace: appset_old_nsNS.Name, - }, - } - - Eventually(example_appset_old_nsRoleBinding).Should(k8sFixture.ExistByName()) - Expect(example_appset_old_nsRoleBinding.RoleRef).To(Equal(rbacv1.RoleRef{ - - APIGroup: "rbac.authorization.k8s.io", - Kind: "Role", - Name: "example_appset-old-ns", - })) - Expect(example_appset_old_nsRoleBinding.Subjects).To(Equal([]rbacv1.Subject{ - { - Kind: "ServiceAccount", - Name: "example-argocd-server", - Namespace: "appset-argocd", - }, - { - Kind: "ServiceAccount", - Name: "example-argocd-application-controller", - Namespace: "appset-argocd", - }, - })) - - oldExample_appset_argocd_applicationsetRole := &rbacv1.Role{ - ObjectMeta: metav1.ObjectMeta{ - Name: "example-appset-argocd-applicationset", - Namespace: "appset-old-ns", - }, - } - Eventually(oldExample_appset_argocd_applicationsetRole).Should(k8sFixture.ExistByName()) - - oldExample_appset_argocd_applicationsetRoleBinding := &rbacv1.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: "example-appset-argocd-applicationset", - Namespace: "appset-old-ns", - }, - } - Eventually(oldExample_appset_argocd_applicationsetRoleBinding).Should(k8sFixture.ExistByName()) - - Eventually(appset_old_nsNS).Should(namespaceFixture.HaveLabel("argocd.argoproj.io/applicationset-managed-by-cluster-argocd", "appset-argocd")) - Consistently(appset_old_nsNS).Should(namespaceFixture.HaveLabel("argocd.argoproj.io/managed-by-cluster-argocd", "appset-argocd")) - - Eventually(example_appset_new_nsRole).Should(k8sFixture.ExistByName()) - - Eventually(example_appset_new_nsRole).Should(roleFixture.HaveRules([]rbacv1.PolicyRule{ - { - APIGroups: []string{"argoproj.io"}, - Resources: []string{"applications"}, - Verbs: []string{ - "create", - "get", - "list", - "patch", - "update", - "watch", - "delete", - }, - }, - { - APIGroups: []string{"argoproj.io"}, - Resources: []string{ - "applicationsets", - }, - Verbs: []string{ - "create", - "get", - "list", - "patch", - "update", - "watch", - "delete", - }, - }, - })) - - Eventually(example_appset_new_nsRoleBinding).Should(k8sFixture.ExistByName()) - Expect(example_appset_new_nsRoleBinding.RoleRef).To(Equal(rbacv1.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Kind: "Role", - Name: "example_appset-new-ns", - })) - Expect(example_appset_new_nsRoleBinding.Subjects).To(Equal([]rbacv1.Subject{ - { - Kind: "ServiceAccount", - Name: "example-argocd-server", - Namespace: "appset-argocd", - }, - { - Kind: "ServiceAccount", - Name: "example-argocd-application-controller", - Namespace: "appset-argocd", - }, - })) - - Eventually(example_appset_argocd_applicationsetRole).Should(k8sFixture.ExistByName()) - Consistently(example_appset_argocd_applicationsetRole).Should(k8sFixture.ExistByName()) - - Eventually(appset_new_nsNS).Should(namespaceFixture.HaveLabel("argocd.argoproj.io/managed-by-cluster-argocd", "appset-argocd")) - - Eventually(appset_new_nsNS).Should(namespaceFixture.HaveLabel("argocd.argoproj.io/applicationset-managed-by-cluster-argocd", "appset-argocd")) - - /// ------------- - - // Appset resources should be removed and server role in target namespace should be update to remove appset permissions - - By("6) Remove 'appset-new-ns' from .spec.appliationSet.sourceNamespaces") - - argocdFixture.Update(argoCD, func(ac *v1beta1.ArgoCD) { - - ac.Spec.SourceNamespaces = []string{ - "appset-new-ns", - "appset-old-ns", - } - - ac.Spec.ApplicationSet.SourceNamespaces = []string{ - "appset-old-ns", - } - - ac.Spec.ApplicationSet.SCMProviders = []string{ - "github.com", - } - }) - - By("verifying that applicationsets has been removed from Role") - Eventually(example_appset_new_nsRole).Should(k8sFixture.ExistByName()) - Eventually(example_appset_new_nsRole).Should(roleFixture.HaveRules([]rbacv1.PolicyRule{ - { - APIGroups: []string{"argoproj.io"}, - Resources: []string{"applications"}, - Verbs: []string{ - "create", - "get", - "list", - "patch", - "update", - "watch", - "delete", - }, - }, - })) - - By("verifying RoleBinding still has expected role and subjects") - Eventually(example_appset_new_nsRoleBinding).Should(k8sFixture.ExistByName()) - Expect(example_appset_new_nsRoleBinding.RoleRef).To(Equal(rbacv1.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Kind: "Role", - Name: "example_appset-new-ns", - })) - Expect(example_appset_new_nsRoleBinding.Subjects).To(Equal([]rbacv1.Subject{ - { - Kind: "ServiceAccount", - Name: "example-argocd-server", - Namespace: "appset-argocd", - }, - { - Kind: "ServiceAccount", - Name: "example-argocd-application-controller", - Namespace: "appset-argocd", - }, - })) - - By("verifying appset-new-ns namespace should still be managed-by-cluster-argocd") - Eventually(appset_new_nsNS).Should(namespaceFixture.HaveLabel("argocd.argoproj.io/managed-by-cluster-argocd", "appset-argocd")) - - By("verifying appset-new-ns applicationset role/binding no longer exists in the namespace") - Eventually(example_appset_argocd_applicationsetRole).Should(k8sFixture.NotExistByName()) - Consistently(example_appset_argocd_applicationsetRole).Should(k8sFixture.NotExistByName()) - - Eventually(example_appset_argocd_applicationsetRoleBinding).Should(k8sFixture.NotExistByName()) - Consistently(example_appset_argocd_applicationsetRoleBinding).Should(k8sFixture.NotExistByName()) - - By("verifying appset-new-ns applicationset is not applicationset-managed-by Argo CD instance") - Eventually(appset_new_nsNS).ShouldNot(namespaceFixture.HaveLabel("argocd.argoproj.io/applicationset-managed-by-cluster-argocd", "appset-argocd")) - Consistently(appset_new_nsNS).ShouldNot(namespaceFixture.HaveLabel("argocd.argoproj.io/applicationset-managed-by-cluster-argocd", "appset-argocd")) - - // --- - - By("7) Remove all .spec.sourceNamespaces") - - argocdFixture.Update(argoCD, func(ac *v1beta1.ArgoCD) { - - ac.Spec.SourceNamespaces = []string{} - - ac.Spec.ApplicationSet.SourceNamespaces = []string{ - "appset-old-ns", - } - - ac.Spec.ApplicationSet.SCMProviders = []string{ - "github.com", - } - }) - - By("verifying role/rolebinding no longer exists in any namespace") - Eventually(example_appset_new_nsRole).Should(k8sFixture.NotExistByName()) - Consistently(example_appset_new_nsRole).Should(k8sFixture.NotExistByName()) - Eventually(example_appset_new_nsRoleBinding).Should(k8sFixture.NotExistByName()) - Consistently(example_appset_new_nsRoleBinding).Should(k8sFixture.NotExistByName()) - - Eventually(example_appset_old_nsRole).Should(k8sFixture.NotExistByName()) - Consistently(example_appset_old_nsRole).Should(k8sFixture.NotExistByName()) - Eventually(example_appset_old_nsRoleBinding).Should(k8sFixture.NotExistByName()) - Consistently(example_appset_old_nsRoleBinding).Should(k8sFixture.NotExistByName()) - - Eventually(oldExample_appset_argocd_applicationsetRole).Should(k8sFixture.NotExistByName()) - Consistently(oldExample_appset_argocd_applicationsetRole).Should(k8sFixture.NotExistByName()) - Eventually(oldExample_appset_argocd_applicationsetRoleBinding).Should(k8sFixture.NotExistByName()) - Consistently(oldExample_appset_argocd_applicationsetRoleBinding).Should(k8sFixture.NotExistByName()) - - By("verifying applicationset-managed-by and managed-by are not set on any namespace") - Eventually(appset_old_nsNS).ShouldNot(namespaceFixture.HaveLabel("argocd.argoproj.io/applicationset-managed-by-cluster-argocd", "appset-argocd")) - Consistently(appset_old_nsNS).ShouldNot(namespaceFixture.HaveLabel("argocd.argoproj.io/applicationset-managed-by-cluster-argocd", "appset-argocd")) - - Eventually(appset_old_nsNS).ShouldNot(namespaceFixture.HaveLabel("argocd.argoproj.io/managed-by-cluster-argocd", "appset-argocd")) - Consistently(appset_old_nsNS).ShouldNot(namespaceFixture.HaveLabel("argocd.argoproj.io/managed-by-cluster-argocd", "appset-argocd")) - - Eventually(appset_new_nsNS).ShouldNot(namespaceFixture.HaveLabel("argocd.argoproj.io/managed-by-cluster-argocd", "appset-argocd")) - Consistently(appset_new_nsNS).ShouldNot(namespaceFixture.HaveLabel("argocd.argoproj.io/managed-by-cluster-argocd", "appset-argocd")) - - }) - - It("verifies that ApplicationSet reconcile is blocked when namespace list fails and retry adds --applicationset-namespaces after RBAC restore", func() { - if fixture.EnvLocalRun() { - Skip("Skipping RBAC test for LOCAL_RUN - operator runs locally without cluster ClusterRole") - } - - By("finding operator deployment") - operatorDeployment := &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "argocd-operator-controller-manager", - Namespace: "argocd-operator-system", - }, - } - if err := k8sClient.Get(ctx, client.ObjectKeyFromObject(operatorDeployment), operatorDeployment); err != nil { - var nsList corev1.NamespaceList - Expect(k8sClient.List(ctx, &nsList)).To(Succeed()) - found := false - for i := range nsList.Items { - dep := &appsv1.Deployment{} - if getErr := k8sClient.Get(ctx, client.ObjectKey{Namespace: nsList.Items[i].Name, Name: "argocd-operator-controller-manager"}, dep); getErr == nil { - operatorDeployment = dep - found = true - break - } - } - if !found { - Skip("Operator deployment not found - test requires operator running in cluster") - } - } - - By("revoking operator list namespaces permission") - saName := operatorDeployment.Spec.Template.Spec.ServiceAccountName - if saName == "" { - saName = "default" - } - var crbList rbacv1.ClusterRoleBindingList - Expect(k8sClient.List(ctx, &crbList)).To(Succeed()) - var operatorClusterRoleName string - for i := range crbList.Items { - for _, subj := range crbList.Items[i].Subjects { - if subj.Kind == "ServiceAccount" && subj.Namespace == operatorDeployment.Namespace && subj.Name == saName { - operatorClusterRoleName = crbList.Items[i].RoleRef.Name - break - } - } - if operatorClusterRoleName != "" { - break - } - } - if operatorClusterRoleName == "" { - Skip("Operator ClusterRoleBinding not found") - } - operatorClusterRole := &rbacv1.ClusterRole{ObjectMeta: metav1.ObjectMeta{Name: operatorClusterRoleName}} - Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(operatorClusterRole), operatorClusterRole)).To(Succeed()) - originalRules := make([]rbacv1.PolicyRule, len(operatorClusterRole.Rules)) - copy(originalRules, operatorClusterRole.Rules) - var modifiedRules []rbacv1.PolicyRule - removedListFromNamespaces := false - for _, r := range operatorClusterRole.Rules { - replaced := false - if slices.Contains(r.Resources, "namespaces") { - replaced = true - if slices.Contains(r.Verbs, "list") { - removedListFromNamespaces = true - } - var newVerbs []string - for _, v := range r.Verbs { - if v != "list" { - newVerbs = append(newVerbs, v) - } - } - if len(newVerbs) > 0 { - modifiedRules = append(modifiedRules, rbacv1.PolicyRule{ - APIGroups: r.APIGroups, Resources: r.Resources, Verbs: newVerbs, - ResourceNames: r.ResourceNames, NonResourceURLs: r.NonResourceURLs, - }) - } - } - if !replaced { - modifiedRules = append(modifiedRules, r) - } - } - if !removedListFromNamespaces { - Skip("Operator ClusterRole has no namespaces list verb to revoke") - } - clusterroleFixture.Update(operatorClusterRole, func(cr *rbacv1.ClusterRole) { cr.Rules = modifiedRules }) - rbacRestored := false - defer func() { - if !rbacRestored { - clusterroleFixture.Update(operatorClusterRole, func(cr *rbacv1.ClusterRole) { cr.Rules = originalRules }) - } - }() - - By("creating Argo CD with ApplicationSet and source namespaces") - argocdNS, cleanupArgocd := fixture.CreateNamespaceWithCleanupFunc("appset-argocd-err") - cleanupFunctions = append(cleanupFunctions, cleanupArgocd) - targetNS, cleanupTarget := fixture.CreateNamespaceWithCleanupFunc("appset-target-err") - cleanupFunctions = append(cleanupFunctions, cleanupTarget) - argoCD := &v1beta1.ArgoCD{ - ObjectMeta: metav1.ObjectMeta{ - Name: "example", - Namespace: argocdNS.Name, - }, - Spec: v1beta1.ArgoCDSpec{ - SourceNamespaces: []string{targetNS.Name}, - ApplicationSet: &v1beta1.ArgoCDApplicationSet{ - SourceNamespaces: []string{targetNS.Name}, - }, - }, - } - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - appsetDeployment := &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "example-applicationset-controller", - Namespace: argoCD.Namespace, - }, - } - - By("verifying ApplicationSet deployment is not created while namespace list fails (blocked reconcile)") - Consistently(appsetDeployment, "10s", "2s").Should(k8sFixture.NotExistByName()) - - By("restoring operator list namespaces permission") - clusterroleFixture.Update(operatorClusterRole, func(cr *rbacv1.ClusterRole) { cr.Rules = originalRules }) - rbacRestored = true - - By("verifying retry creates deployment with --applicationset-namespaces") - Eventually(appsetDeployment, "2m", "5s").Should(k8sFixture.ExistByName()) - Eventually(appsetDeployment).Should(deploymentFixture.HaveContainerCommandSubstring("--applicationset-namespaces "+targetNS.Name, 0)) - }) - - It("verifies that ArgoCD sourcenamespaces resources are cleaned up automatically", func() { - - By("creating Argo CD namespace and appset source namespace") - targetNS, cleanupFunc := fixture.CreateNamespaceWithCleanupFunc("target-ns-1-037") - cleanupFunctions = append(cleanupFunctions, cleanupFunc) - - appset_argocdNS, cleanupFunc := fixture.CreateNamespaceWithCleanupFunc("appset-namespace-scoped") - cleanupFunctions = append(cleanupFunctions, cleanupFunc) - - By("creating ArgoCD instance with target ns as a source NS, BUT note the ArgoCD instance is namespace-scoped") - argoCD := &v1beta1.ArgoCD{ - ObjectMeta: metav1.ObjectMeta{ - Name: "example", - Namespace: appset_argocdNS.Name, - }, - Spec: v1beta1.ArgoCDSpec{ - ApplicationSet: &v1beta1.ArgoCDApplicationSet{ - SourceNamespaces: []string{targetNS.Name}, - }, - SourceNamespaces: []string{targetNS.Name}, - }, - } - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - Eventually(argoCD).Should(argocdFixture.HaveApplicationSetControllerStatus("Running")) - - By("verifying that the appset deplomyent does not contain 'applications in any namespace' parameter") - appsetDeployment := &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "example-applicationset-controller", - Namespace: argoCD.Namespace, - }, - } - Eventually(appsetDeployment).Should(k8sFixture.ExistByName()) - Expect(appsetDeployment).ShouldNot(deploymentFixture.HaveContainerCommandSubstring("--applicationset-namespaces", 0)) - - By("first verify that the ClusterRole was not automatically created for the Argo CD instance") - clusterRole := &rbacv1.ClusterRole{ - ObjectMeta: metav1.ObjectMeta{ - Name: argocd.GenerateUniqueResourceName(common.ArgoCDApplicationSetControllerComponent, argoCD), - Annotations: common.DefaultAnnotations(argoCD.Name, argoCD.Namespace), - }, - } - Consistently(clusterRole).Should(k8sFixture.NotExistByName()) - - By("creating ClusterRole and then ensuring it is automatically cleaned up") - Expect(k8sClient.Create(ctx, clusterRole)).To(Succeed()) - Eventually(clusterRole).ShouldNot(k8sFixture.ExistByName()) - - By("first verify that ClusterRoleBinding was not automatically created for the Argo CD instance") - clusterRoleBinding := &rbacv1.ClusterRoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: argocd.GenerateUniqueResourceName(common.ArgoCDApplicationSetControllerComponent, argoCD), - Annotations: common.DefaultAnnotations(argoCD.Name, argoCD.Namespace), - }, - Subjects: []rbacv1.Subject{ - { - Kind: "ServiceAccount", - Name: "sa", - Namespace: argoCD.Namespace, - }, - }, - RoleRef: rbacv1.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Kind: "ClusterRole", - Name: clusterRole.Name, - }, - } - Consistently(clusterRoleBinding).Should(k8sFixture.NotExistByName()) - By("creating ClusterRoleBinding and then ensuring it is automatically cleaned up") - Expect(k8sClient.Create(ctx, clusterRoleBinding)).To(Succeed()) - Eventually(clusterRoleBinding).ShouldNot(k8sFixture.ExistByName()) - - By("first verifying that Role does not exist in namespace specified in appset sourceNamespaces field") - roleInTargetNS := &rbacv1.Role{ - ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%s-%s-applicationset", argoCD.Name, argoCD.Namespace), - Namespace: targetNS.Name, - }, - } - Consistently(roleInTargetNS).Should(k8sFixture.NotExistByName()) - By("creating Role in source NS and verifying it is not cleaned up (yet)") - Expect(k8sClient.Create(ctx, roleInTargetNS)).To(Succeed()) - Consistently(roleInTargetNS).Should(k8sFixture.ExistByName()) - - By("verifying that there exist no rolebindings that point to the namespace-scoped argocd instance namespace") - Consistently(func() bool { - var roleBindings rbacv1.RoleBindingList - if err := k8sClient.List(ctx, &roleBindings, client.InNamespace(targetNS.Name)); err != nil { - GinkgoWriter.Println(err) - return false - } - for _, crb := range roleBindings.Items { - for _, subject := range crb.Subjects { - if subject.Namespace == argoCD.Namespace { - GinkgoWriter.Println("detected an RB that pointed to namespace scoped ArgoCD instance. This shouldn't happen:", crb.Name) - return false - } - } - } - return true - - }).Should(BeTrue()) - - By("first verifying that RoleBinding does not exist in source namespace") - roleBindingInTargetNS := &rbacv1.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%s-%s-applicationset", argoCD.Name, argoCD.Namespace), - Namespace: targetNS.Name, - }, - Subjects: []rbacv1.Subject{ - { - Kind: "ServiceAccount", - Name: "sa", - Namespace: argoCD.Namespace, - }, - }, - RoleRef: rbacv1.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Kind: "Role", - Name: roleInTargetNS.Name, - }, - } - Consistently(roleBindingInTargetNS).Should(k8sFixture.NotExistByName()) - By("creating RoleBinding in source NS and verifying it is not cleaned up (yet)") - Expect(k8sClient.Create(ctx, roleBindingInTargetNS)).To(Succeed()) - Consistently(roleBindingInTargetNS).Should(k8sFixture.ExistByName()) - - By("adding ArgoCDApplicationSetManagedByClusterArgoCDLabel label to target NS") - namespaceFixture.Update(targetNS, func(n *corev1.Namespace) { - if n.Labels == nil { - n.Labels = map[string]string{} - } - n.Labels[common.ArgoCDApplicationSetManagedByClusterArgoCDLabel] = argoCD.Namespace - }) - - By("verifying the label is automatically removed") - Eventually(targetNS).Should(k8sFixture.NotHaveLabelWithValue(common.ArgoCDApplicationSetManagedByClusterArgoCDLabel, argoCD.Namespace)) - - By("verifying that the roles/rolebindings we created in the previous steps are now automatically cleaned up, because the namespace had the ArgoCDApplicationSetManagedByClusterArgoCDLabel") - Eventually(roleBindingInTargetNS).Should(k8sFixture.NotExistByName()) - Eventually(roleInTargetNS).Should(k8sFixture.NotExistByName()) - }) - - It("verifies that wildcard patterns in .spec.applicationSet.sourceNamespaces correctly match and manage multiple namespaces", func() { - - By("0) create namespaces: appset-argocd, team-1, team-2, team-frontend, team-backend, other-ns") - - appset_wildcard_argocdNS, cleanupFunc := fixture.CreateNamespaceWithCleanupFunc("appset-argocd") - cleanupFunctions = append(cleanupFunctions, cleanupFunc) - - team1NS, cleanupFunc := fixture.CreateNamespaceWithCleanupFunc("team-1") - cleanupFunctions = append(cleanupFunctions, cleanupFunc) - - team2NS, cleanupFunc := fixture.CreateNamespaceWithCleanupFunc("team-2") - cleanupFunctions = append(cleanupFunctions, cleanupFunc) - - teamFrontendNS, cleanupFunc := fixture.CreateNamespaceWithCleanupFunc("team-frontend") - cleanupFunctions = append(cleanupFunctions, cleanupFunc) - - teamBackendNS, cleanupFunc := fixture.CreateNamespaceWithCleanupFunc("team-backend") - cleanupFunctions = append(cleanupFunctions, cleanupFunc) - - otherNS, cleanupFunc := fixture.CreateNamespaceWithCleanupFunc("other-ns") - cleanupFunctions = append(cleanupFunctions, cleanupFunc) - - // ----- - - By("1) create Argo CD instance with wildcard pattern 'team-*' in both sourceNamespaces and applicationSet.sourceNamespaces") - - argoCD := &v1beta1.ArgoCD{ - ObjectMeta: metav1.ObjectMeta{ - Name: "wildcard-example", - Namespace: appset_wildcard_argocdNS.Name, - }, - Spec: v1beta1.ArgoCDSpec{ - SourceNamespaces: []string{ - "team-*", - }, - ApplicationSet: &v1beta1.ArgoCDApplicationSet{ - SourceNamespaces: []string{ - "team-*", - }, - SCMProviders: []string{ - "github.com", - }, - }, - }, - } - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - Eventually(argoCD, "5m", "5s").Should(argocdFixture.BeAvailable()) - Eventually(argoCD).Should(argocdFixture.HaveApplicationSetControllerStatus("Running")) - - By("2) verifying that the appset deployment contains all matching namespaces in the command") - appsetDeployment := &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "wildcard-example-applicationset-controller", - Namespace: argoCD.Namespace, - }, - } - Eventually(appsetDeployment).Should(k8sFixture.ExistByName()) - - // Verify that all team-* namespaces are included (order may vary) - Eventually(appsetDeployment).Should(deploymentFixture.HaveContainerCommandSubstring("--applicationset-namespaces", 0)) - Eventually(func() bool { - if err := k8sClient.Get(ctx, client.ObjectKeyFromObject(appsetDeployment), appsetDeployment); err != nil { - return false - } - if len(appsetDeployment.Spec.Template.Spec.Containers) == 0 { - return false - } - cmd := appsetDeployment.Spec.Template.Spec.Containers[0].Command - cmdStr := strings.Join(cmd, " ") - if strings.Contains(cmdStr, "--applicationset-namespaces") { - // Check that all team-* namespaces are present - return strings.Contains(cmdStr, "team-1") && - strings.Contains(cmdStr, "team-2") && - strings.Contains(cmdStr, "team-frontend") && - strings.Contains(cmdStr, "team-backend") - } - return false - }).Should(BeTrue()) - - By("3) verifying that Role and RoleBinding are created in all matching team-* namespaces") - verifyAppSetResourcesInNamespace := func(namespaceName string) { - appsetRole := &rbacv1.Role{ - ObjectMeta: metav1.ObjectMeta{ - Name: "wildcard-example-appset-argocd-applicationset", - Namespace: namespaceName, - }, - } - Eventually(appsetRole).Should(k8sFixture.ExistByName()) - - appsetRoleBinding := &rbacv1.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: "wildcard-example-appset-argocd-applicationset", - Namespace: namespaceName, - }, - } - Eventually(appsetRoleBinding).Should(k8sFixture.ExistByName()) - Expect(appsetRoleBinding.RoleRef).To(Equal(rbacv1.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Kind: "Role", - Name: "wildcard-example-appset-argocd-applicationset", - })) - Expect(appsetRoleBinding.Subjects).To(ContainElement(rbacv1.Subject{ - Kind: "ServiceAccount", - Name: "wildcard-example-applicationset-controller", - Namespace: appset_wildcard_argocdNS.Name, - })) - } - - verifyAppSetResourcesInNamespace(team1NS.Name) - verifyAppSetResourcesInNamespace(team2NS.Name) - verifyAppSetResourcesInNamespace(teamFrontendNS.Name) - verifyAppSetResourcesInNamespace(teamBackendNS.Name) - - By("4) verifying that namespace labels are set correctly for all matching namespaces") - Eventually(team1NS).Should(namespaceFixture.HaveLabel("argocd.argoproj.io/applicationset-managed-by-cluster-argocd", appset_wildcard_argocdNS.Name)) - Eventually(team2NS).Should(namespaceFixture.HaveLabel("argocd.argoproj.io/applicationset-managed-by-cluster-argocd", appset_wildcard_argocdNS.Name)) - Eventually(teamFrontendNS).Should(namespaceFixture.HaveLabel("argocd.argoproj.io/applicationset-managed-by-cluster-argocd", appset_wildcard_argocdNS.Name)) - Eventually(teamBackendNS).Should(namespaceFixture.HaveLabel("argocd.argoproj.io/applicationset-managed-by-cluster-argocd", appset_wildcard_argocdNS.Name)) - - By("5) verifying that non-matching namespace (other-ns) does NOT have appset resources") - otherNSAppSetRole := &rbacv1.Role{ - ObjectMeta: metav1.ObjectMeta{ - Name: "wildcard-example-appset-argocd-applicationset", - Namespace: otherNS.Name, - }, - } - Consistently(otherNSAppSetRole).Should(k8sFixture.NotExistByName()) - - otherNSAppSetRoleBinding := &rbacv1.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: "wildcard-example-appset-argocd-applicationset", - Namespace: otherNS.Name, - }, - } - Consistently(otherNSAppSetRoleBinding).Should(k8sFixture.NotExistByName()) - - Consistently(otherNS).ShouldNot(namespaceFixture.HaveLabel("argocd.argoproj.io/applicationset-managed-by-cluster-argocd", appset_wildcard_argocdNS.Name)) - - By("6) creating a new namespace that matches the pattern and verifying it gets resources automatically") - team3NS, cleanupFunc := fixture.CreateNamespaceWithCleanupFunc("team-3") - cleanupFunctions = append(cleanupFunctions, cleanupFunc) - - // Wait for reconciliation to pick up the new namespace - Eventually(func() bool { - appsetRole := &rbacv1.Role{ - ObjectMeta: metav1.ObjectMeta{ - Name: "wildcard-example-appset-argocd-applicationset", - Namespace: team3NS.Name, - }, - } - return k8sClient.Get(ctx, client.ObjectKeyFromObject(appsetRole), appsetRole) == nil - }, "2m", "5s").Should(BeTrue()) - - verifyAppSetResourcesInNamespace(team3NS.Name) - Eventually(team3NS).Should(namespaceFixture.HaveLabel("argocd.argoproj.io/applicationset-managed-by-cluster-argocd", appset_wildcard_argocdNS.Name)) - - By("7) updating ArgoCD to use a more specific pattern 'team-*' -> 'team-1' and verifying cleanup") - argocdFixture.Update(argoCD, func(ac *v1beta1.ArgoCD) { - ac.Spec.SourceNamespaces = []string{ - "team-1", - } - ac.Spec.ApplicationSet.SourceNamespaces = []string{ - "team-1", - } - ac.Spec.ApplicationSet.SCMProviders = []string{ - "github.com", - } - }) - - Eventually(argoCD, "5m", "5s").Should(argocdFixture.BeAvailable()) - - By("8) verifying that team-1 still has resources") - team1AppSetRole := &rbacv1.Role{ - ObjectMeta: metav1.ObjectMeta{ - Name: "wildcard-example-appset-argocd-applicationset", - Namespace: team1NS.Name, - }, - } - Eventually(team1AppSetRole).Should(k8sFixture.ExistByName()) - - By("9) verifying that other team-* namespaces have resources cleaned up") - team2AppSetRole := &rbacv1.Role{ - ObjectMeta: metav1.ObjectMeta{ - Name: "wildcard-example-appset-argocd-applicationset", - Namespace: team2NS.Name, - }, - } - Eventually(team2AppSetRole).Should(k8sFixture.NotExistByName()) - Consistently(team2AppSetRole).Should(k8sFixture.NotExistByName()) - - team3AppSetRole := &rbacv1.Role{ - ObjectMeta: metav1.ObjectMeta{ - Name: "wildcard-example-appset-argocd-applicationset", - Namespace: team3NS.Name, - }, - } - Eventually(team3AppSetRole).Should(k8sFixture.NotExistByName()) - Consistently(team3AppSetRole).Should(k8sFixture.NotExistByName()) - - teamFrontendAppSetRole := &rbacv1.Role{ - ObjectMeta: metav1.ObjectMeta{ - Name: "wildcard-example-appset-argocd-applicationset", - Namespace: teamFrontendNS.Name, - }, - } - Eventually(teamFrontendAppSetRole).Should(k8sFixture.NotExistByName()) - Consistently(teamFrontendAppSetRole).Should(k8sFixture.NotExistByName()) - - By("10) verifying that labels are removed from namespaces that no longer match") - Eventually(team2NS).ShouldNot(namespaceFixture.HaveLabel("argocd.argoproj.io/applicationset-managed-by-cluster-argocd", appset_wildcard_argocdNS.Name)) - Eventually(team3NS).ShouldNot(namespaceFixture.HaveLabel("argocd.argoproj.io/applicationset-managed-by-cluster-argocd", appset_wildcard_argocdNS.Name)) - Eventually(teamFrontendNS).ShouldNot(namespaceFixture.HaveLabel("argocd.argoproj.io/applicationset-managed-by-cluster-argocd", appset_wildcard_argocdNS.Name)) - - By("11) verifying deployment command only includes team-1") - Eventually(func() bool { - if err := k8sClient.Get(ctx, client.ObjectKeyFromObject(appsetDeployment), appsetDeployment); err != nil { - return false - } - if len(appsetDeployment.Spec.Template.Spec.Containers) == 0 { - return false - } - cmd := appsetDeployment.Spec.Template.Spec.Containers[0].Command - cmdStr := strings.Join(cmd, " ") - if strings.Contains(cmdStr, "--applicationset-namespaces") { - return strings.Contains(cmdStr, "team-1") && - !strings.Contains(cmdStr, "team-2") && - !strings.Contains(cmdStr, "team-3") && - !strings.Contains(cmdStr, "team-frontend") - } - return false - }).Should(BeTrue()) - - }) - - It("verifies ApplicationSet clusterrole rules and creates appset/app in another namespace", func() { - - By("creating Argo CD namespace and target source namespace") - argoNamespace, cleanupFunc := fixture.CreateNamespaceWithCleanupFunc("appset-argocd-clusterrole") - cleanupFunctions = append(cleanupFunctions, cleanupFunc) - - targetNS, cleanupFunc := fixture.CreateNamespaceWithCleanupFunc("appset-target-ns") - cleanupFunctions = append(cleanupFunctions, cleanupFunc) - - By("creating Argo CD instance with source namespaces") - argoCD := &v1beta1.ArgoCD{ - ObjectMeta: metav1.ObjectMeta{ - Name: "appset-example", - Namespace: argoNamespace.Name, - }, - Spec: v1beta1.ArgoCDSpec{ - SourceNamespaces: []string{ - targetNS.Name, - }, - ApplicationSet: &v1beta1.ArgoCDApplicationSet{ - SourceNamespaces: []string{ - targetNS.Name, - }, - SCMProviders: []string{ - "github.com", - }, - }, - }, - } - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - Eventually(argoCD, "5m", "5s").Should(argocdFixture.BeAvailable()) - Eventually(argoCD).Should(argocdFixture.HaveApplicationSetControllerStatus("Running")) - - By("2) verifying that the appset deployment contains matching namespace in the command") - appsetDeployment := &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: "appset-example-applicationset-controller", - Namespace: argoCD.Namespace, - }, - } - Eventually(appsetDeployment).Should(k8sFixture.ExistByName()) - - // Verify that target namespace is included - Eventually(appsetDeployment).Should(deploymentFixture.HaveContainerCommandSubstring("--applicationset-namespaces", 0)) - - appProject := &appv1alpha1.AppProject{ - ObjectMeta: metav1.ObjectMeta{ - Name: "default", - Namespace: argoCD.Namespace, - }, - } - Eventually(appProject).Should(k8sFixture.ExistByName()) - appprojectFixture.Update(appProject, func(appProject *appv1alpha1.AppProject) { - appProject.Spec.SourceNamespaces = append(appProject.Spec.SourceNamespaces, targetNS.Name) - }) - - By("verifying ApplicationSet controller ClusterRole has expected rules") - appsetClusterRole := &rbacv1.ClusterRole{ - ObjectMeta: metav1.ObjectMeta{ - Name: argocd.GenerateUniqueResourceName(common.ArgoCDApplicationSetControllerComponent, argoCD), - }, - } - Eventually(appsetClusterRole, "5m", "10s").Should(k8sFixture.ExistByName()) - Eventually(appsetClusterRole, "5m", "10s").Should(clusterroleFixture.HaveRules([]rbacv1.PolicyRule{ - { - APIGroups: []string{"argoproj.io"}, - Resources: []string{ - "applications", - "applicationsets", - "applicationsets/finalizers", - }, - Verbs: []string{ - "create", - "delete", - "get", - "list", - "patch", - "update", - "watch", - }, - }, - { - APIGroups: []string{"argoproj.io"}, - Resources: []string{ - "appprojects", - }, - Verbs: []string{ - "get", - "list", - "watch", - }, - }, - { - APIGroups: []string{"argoproj.io"}, - Resources: []string{ - "applicationsets/status", - }, - Verbs: []string{ - "get", - "patch", - "update", - }, - }, - { - APIGroups: []string{""}, - Resources: []string{ - "events", - }, - Verbs: []string{ - "create", - "get", - "list", - "patch", - "watch", - }, - }, - { - APIGroups: []string{""}, - Resources: []string{ - "secrets", - "configmaps", - }, - Verbs: []string{ - "get", - "list", - "watch", - }, - }, - { - APIGroups: []string{"coordination.k8s.io"}, - Resources: []string{ - "leases", - }, - Verbs: []string{ - "create", - }, - }, - { - APIGroups: []string{"coordination.k8s.io"}, - Resources: []string{ - "leases", - }, - Verbs: []string{ - "get", - "update", - "create", - }, - ResourceNames: []string{ - "58ac56fa.applicationsets.argoproj.io", - }, - }, - })) - - By("creating an ApplicationSet in the target namespace") - appset := &unstructured.Unstructured{ - Object: map[string]any{ - "apiVersion": "argoproj.io/v1alpha1", - "kind": "ApplicationSet", - "metadata": map[string]any{ - "name": "guestbook-appset", - "namespace": targetNS.Name, - }, - "spec": map[string]any{ - "generators": []any{ - map[string]any{ - "list": map[string]any{ - "elements": []any{ - map[string]any{ - "name": "guestbook", - }, - }, - }, - }, - }, - "template": map[string]any{ - "metadata": map[string]any{ - "name": "{{name}}", - }, - "spec": map[string]any{ - "project": "default", - "source": map[string]any{ - "repoURL": "https://github.com/argoproj/argocd-example-apps.git", - "targetRevision": "HEAD", - "path": "guestbook", - }, - "destination": map[string]any{ - "server": "https://kubernetes.default.svc", - "namespace": targetNS.Name, - }, - }, - }, - }, - }, - } - Expect(k8sClient.Create(ctx, appset)).To(Succeed()) - Eventually(appset).Should(k8sFixture.ExistByName()) - - By("verifying ApplicationSet generates Application in target namespace") - generatedApp := &appv1alpha1.Application{ - ObjectMeta: metav1.ObjectMeta{ - Name: "guestbook", - Namespace: targetNS.Name, - }, - } - Eventually(generatedApp, "5m", "10s").Should(k8sFixture.ExistByName()) - Eventually(generatedApp, "5m", "10s").Should(applicationFixture.HaveHealthStatusCode(health.HealthStatusMissing)) - Eventually(generatedApp, "5m", "10s").Should(applicationFixture.HaveSyncStatusCode(appv1alpha1.SyncStatusCodeOutOfSync)) - By("Cleaning up the ApplicationSet") - Expect(k8sClient.Delete(ctx, appset)).To(Succeed()) - Eventually(appset).Should(k8sFixture.NotExistByName()) - }) - - It("defaults tokenRef strict mode to true when applicationSet sourceNamespaces are configured", func() { - appsetArgocdNS, cleanupFunc := fixture.CreateNamespaceWithCleanupFunc("appset-argocd") - cleanupFunctions = append(cleanupFunctions, cleanupFunc) - - targetNS, cleanupFunc := fixture.CreateNamespaceWithCleanupFunc("appset-target-ns") - cleanupFunctions = append(cleanupFunctions, cleanupFunc) - - argoCD := &v1beta1.ArgoCD{ - ObjectMeta: metav1.ObjectMeta{ - Name: "tokenref-strict-true", - Namespace: appsetArgocdNS.Name, - }, - Spec: v1beta1.ArgoCDSpec{ - ApplicationSet: &v1beta1.ArgoCDApplicationSet{ - SourceNamespaces: []string{targetNS.Name}, - }, - }, - } - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - cmdParamsCM := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: common.ArgoCDCmdParamsConfigMapName, - Namespace: argoCD.Namespace, - }, - } - Eventually(cmdParamsCM, "3m", "5s").Should(configmapFixture.HaveStringDataKeyValue(common.ArgoCDApplicationSetControllerTokenRefStrictModeCmdParamKey, "true")) - }) - - It("defaults tokenRef strict mode to false when applicationSet sourceNamespaces are empty on create", func() { - appsetArgocdNS, cleanupFunc := fixture.CreateNamespaceWithCleanupFunc("appset-argocd") - cleanupFunctions = append(cleanupFunctions, cleanupFunc) - - argoCD := &v1beta1.ArgoCD{ - ObjectMeta: metav1.ObjectMeta{ - Name: "tokenref-strict-false-empty", - Namespace: appsetArgocdNS.Name, - }, - Spec: v1beta1.ArgoCDSpec{ - ApplicationSet: &v1beta1.ArgoCDApplicationSet{ - SourceNamespaces: []string{}, - }, - }, - } - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - cmdParamsCM := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: common.ArgoCDCmdParamsConfigMapName, - Namespace: argoCD.Namespace, - }, - } - Eventually(cmdParamsCM, "3m", "5s").Should(configmapFixture.HaveStringDataKeyValue(common.ArgoCDApplicationSetControllerTokenRefStrictModeCmdParamKey, "false")) - }) - - It("defaults tokenRef strict mode to false when applicationSet sourceNamespaces are removed", func() { - appsetArgocdNS, cleanupFunc := fixture.CreateNamespaceWithCleanupFunc("appset-argocd") - cleanupFunctions = append(cleanupFunctions, cleanupFunc) - - targetNS, cleanupFunc := fixture.CreateNamespaceWithCleanupFunc("appset-target-ns") - cleanupFunctions = append(cleanupFunctions, cleanupFunc) - - argoCD := &v1beta1.ArgoCD{ - ObjectMeta: metav1.ObjectMeta{ - Name: "tokenref-strict-false-removed", - Namespace: appsetArgocdNS.Name, - }, - Spec: v1beta1.ArgoCDSpec{ - ApplicationSet: &v1beta1.ArgoCDApplicationSet{ - SourceNamespaces: []string{targetNS.Name}, - }, - }, - } - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - cmdParamsCM := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: common.ArgoCDCmdParamsConfigMapName, - Namespace: argoCD.Namespace, - }, - } - Eventually(cmdParamsCM, "3m", "5s").Should(configmapFixture.HaveStringDataKeyValue(common.ArgoCDApplicationSetControllerTokenRefStrictModeCmdParamKey, "true")) - - argocdFixture.Update(argoCD, func(ac *v1beta1.ArgoCD) { - ac.Spec.ApplicationSet.SourceNamespaces = []string{} - }) - Eventually(cmdParamsCM, "3m", "5s").Should(configmapFixture.HaveStringDataKeyValue(common.ArgoCDApplicationSetControllerTokenRefStrictModeCmdParamKey, "false")) - }) - - It("reconciles tokenRef strict mode cmd-params drift when applicationSet sourceNamespaces remain configured", func() { - appsetArgocdNS, cleanupFunc := fixture.CreateNamespaceWithCleanupFunc("appset-argocd") - cleanupFunctions = append(cleanupFunctions, cleanupFunc) - - targetNS, cleanupFunc := fixture.CreateNamespaceWithCleanupFunc("appset-target-ns") - cleanupFunctions = append(cleanupFunctions, cleanupFunc) - - argoCD := &v1beta1.ArgoCD{ - ObjectMeta: metav1.ObjectMeta{ - Name: "tokenref-strict-drift", - Namespace: appsetArgocdNS.Name, - }, - Spec: v1beta1.ArgoCDSpec{ - ApplicationSet: &v1beta1.ArgoCDApplicationSet{ - SourceNamespaces: []string{targetNS.Name}, - }, - }, - } - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - cmdParamsCM := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: common.ArgoCDCmdParamsConfigMapName, - Namespace: argoCD.Namespace, - }, - } - Eventually(cmdParamsCM, "3m", "5s").Should(configmapFixture.HaveStringDataKeyValue(common.ArgoCDApplicationSetControllerTokenRefStrictModeCmdParamKey, "true")) - - configmapFixture.Update(cmdParamsCM, func(cm *corev1.ConfigMap) { - cm.Data[common.ArgoCDApplicationSetControllerTokenRefStrictModeCmdParamKey] = "false" - }) - Eventually(cmdParamsCM, "3m", "5s").Should(configmapFixture.HaveStringDataKeyValue(common.ArgoCDApplicationSetControllerTokenRefStrictModeCmdParamKey, "false")) - - By("triggering reconciliation via ArgoCD metadata change") - argocdFixture.Update(argoCD, func(ac *v1beta1.ArgoCD) { - if ac.Annotations == nil { - ac.Annotations = map[string]string{} - } - ac.Annotations["argocds.argoproj.io/e2e-reconcile-touch"] = "1" - }) - Eventually(cmdParamsCM, "3m", "5s").Should(configmapFixture.HaveStringDataKeyValue(common.ArgoCDApplicationSetControllerTokenRefStrictModeCmdParamKey, "true")) - }) - - It("spec.cmdParams overrides tokenRef strict mode default", func() { - appsetArgocdNS, cleanupFunc := fixture.CreateNamespaceWithCleanupFunc("appset-argocd") - cleanupFunctions = append(cleanupFunctions, cleanupFunc) - - targetNS, cleanupFunc := fixture.CreateNamespaceWithCleanupFunc("appset-target-ns") - cleanupFunctions = append(cleanupFunctions, cleanupFunc) - - argoCD := &v1beta1.ArgoCD{ - ObjectMeta: metav1.ObjectMeta{ - Name: "tokenref-strict-optout", - Namespace: appsetArgocdNS.Name, - }, - Spec: v1beta1.ArgoCDSpec{ - ApplicationSet: &v1beta1.ArgoCDApplicationSet{ - SourceNamespaces: []string{targetNS.Name}, - }, - CmdParams: map[string]string{ - common.ArgoCDApplicationSetControllerTokenRefStrictModeCmdParamKey: "false", - }, - }, - } - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - cmdParamsCM := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: common.ArgoCDCmdParamsConfigMapName, - Namespace: argoCD.Namespace, - }, - } - Eventually(cmdParamsCM, "3m", "5s").Should(configmapFixture.HaveStringDataKeyValue(common.ArgoCDApplicationSetControllerTokenRefStrictModeCmdParamKey, "false")) - - By("triggering reconcile by updating ArgoCD spec.cmdParams and verifying opt-out persists") - argocdFixture.Update(argoCD, func(ac *v1beta1.ArgoCD) { - if ac.Spec.CmdParams == nil { - ac.Spec.CmdParams = map[string]string{} - } - ac.Spec.CmdParams[common.ArgoCDApplicationSetControllerTokenRefStrictModeCmdParamKey] = "false" - }) - Eventually(cmdParamsCM, "3m", "5s").Should(configmapFixture.HaveStringDataKeyValue(common.ArgoCDApplicationSetControllerTokenRefStrictModeCmdParamKey, "false")) - }) - - }) -}) diff --git a/test/openshift/e2e/ginkgo/sequential/1-037_validate_applicationset_in_any_namespace_test.go b/test/openshift/e2e/ginkgo/sequential/1-037_validate_applicationset_in_any_namespace_test.go index b5f607c16a5..f00e4211552 100644 --- a/test/openshift/e2e/ginkgo/sequential/1-037_validate_applicationset_in_any_namespace_test.go +++ b/test/openshift/e2e/ginkgo/sequential/1-037_validate_applicationset_in_any_namespace_test.go @@ -11,6 +11,7 @@ import ( . "github.com/onsi/gomega" "github.com/redhat-developer/gitops-operator/argocd-operator/api/v1beta1" "github.com/redhat-developer/gitops-operator/argocd-operator/common" + "github.com/redhat-developer/gitops-operator/argocd-operator/controllers/argocd" "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture" applicationFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/application" appprojectFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/appproject" @@ -742,7 +743,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { By("first verify that the ClusterRole was not automatically created for the Argo CD instance") clusterRole := &rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{ - Name: argoCD.Name + "-" + argoCD.Namespace + "-" + common.ArgoCDApplicationSetControllerComponent, + Name: argocd.GenerateUniqueResourceName(common.ArgoCDApplicationSetControllerComponent, argoCD), Annotations: common.DefaultAnnotations(argoCD.Name, argoCD.Namespace), }, } @@ -755,7 +756,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { By("first verify that ClusterRoleBinding was not automatically created for the Argo CD instance") clusterRoleBinding := &rbacv1.ClusterRoleBinding{ ObjectMeta: metav1.ObjectMeta{ - Name: argoCD.Name + "-" + argoCD.Namespace + "-" + common.ArgoCDApplicationSetControllerComponent, + Name: argocd.GenerateUniqueResourceName(common.ArgoCDApplicationSetControllerComponent, argoCD), Annotations: common.DefaultAnnotations(argoCD.Name, argoCD.Namespace), }, Subjects: []rbacv1.Subject{ @@ -1142,7 +1143,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { By("verifying ApplicationSet controller ClusterRole has expected rules") appsetClusterRole := &rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{ - Name: argoCD.Name + "-" + argoCD.Namespace + "-" + common.ArgoCDApplicationSetControllerComponent, + Name: argocd.GenerateUniqueResourceName(common.ArgoCDApplicationSetControllerComponent, argoCD), }, } Eventually(appsetClusterRole, "5m", "10s").Should(k8sFixture.ExistByName()) @@ -1350,6 +1351,74 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { Eventually(cmdParamsCM, "3m", "5s").Should(configmapFixture.HaveStringDataKeyValue(common.ArgoCDApplicationSetControllerTokenRefStrictModeCmdParamKey, "false")) }) + It("defaults tokenRef strict mode to false when applicationSet sourceNamespaces are removed", func() { + appsetArgocdNS, cleanupFunc := fixture.CreateNamespaceWithCleanupFunc("appset-argocd") + cleanupFunctions = append(cleanupFunctions, cleanupFunc) + + targetNS, cleanupFunc := fixture.CreateNamespaceWithCleanupFunc("appset-target-ns") + cleanupFunctions = append(cleanupFunctions, cleanupFunc) + + argoCD := &v1beta1.ArgoCD{ + ObjectMeta: metav1.ObjectMeta{ + Name: "tokenref-strict-false-removed", + Namespace: appsetArgocdNS.Name, + }, + Spec: v1beta1.ArgoCDSpec{ + ApplicationSet: &v1beta1.ArgoCDApplicationSet{ + SourceNamespaces: []string{targetNS.Name}, + }, + }, + } + Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) + + cmdParamsCM := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: common.ArgoCDCmdParamsConfigMapName, + Namespace: argoCD.Namespace, + }, + } + Eventually(cmdParamsCM, "3m", "5s").Should(configmapFixture.HaveStringDataKeyValue(common.ArgoCDApplicationSetControllerTokenRefStrictModeCmdParamKey, "true")) + + argocdFixture.Update(argoCD, func(ac *v1beta1.ArgoCD) { + ac.Spec.ApplicationSet.SourceNamespaces = []string{} + }) + Eventually(cmdParamsCM, "3m", "5s").Should(configmapFixture.HaveStringDataKeyValue(common.ArgoCDApplicationSetControllerTokenRefStrictModeCmdParamKey, "false")) + }) + + It("reconciles tokenRef strict mode cmd-params drift when applicationSet sourceNamespaces remain configured", func() { + appsetArgocdNS, cleanupFunc := fixture.CreateNamespaceWithCleanupFunc("appset-argocd") + cleanupFunctions = append(cleanupFunctions, cleanupFunc) + + targetNS, cleanupFunc := fixture.CreateNamespaceWithCleanupFunc("appset-target-ns") + cleanupFunctions = append(cleanupFunctions, cleanupFunc) + + argoCD := &v1beta1.ArgoCD{ + ObjectMeta: metav1.ObjectMeta{ + Name: "tokenref-strict-drift", + Namespace: appsetArgocdNS.Name, + }, + Spec: v1beta1.ArgoCDSpec{ + ApplicationSet: &v1beta1.ArgoCDApplicationSet{ + SourceNamespaces: []string{targetNS.Name}, + }, + }, + } + Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) + + cmdParamsCM := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: common.ArgoCDCmdParamsConfigMapName, + Namespace: argoCD.Namespace, + }, + } + Eventually(cmdParamsCM, "3m", "5s").Should(configmapFixture.HaveStringDataKeyValue(common.ArgoCDApplicationSetControllerTokenRefStrictModeCmdParamKey, "true")) + + configmapFixture.Update(cmdParamsCM, func(cm *corev1.ConfigMap) { + cm.Data[common.ArgoCDApplicationSetControllerTokenRefStrictModeCmdParamKey] = "nonsense" + }) + Eventually(cmdParamsCM, "30s", "5s").Should(configmapFixture.HaveStringDataKeyValue(common.ArgoCDApplicationSetControllerTokenRefStrictModeCmdParamKey, "true")) + }) + It("spec.cmdParams overrides tokenRef strict mode default", func() { appsetArgocdNS, cleanupFunc := fixture.CreateNamespaceWithCleanupFunc("appset-argocd") cleanupFunctions = append(cleanupFunctions, cleanupFunc) @@ -1380,6 +1449,15 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { }, } Eventually(cmdParamsCM, "3m", "5s").Should(configmapFixture.HaveStringDataKeyValue(common.ArgoCDApplicationSetControllerTokenRefStrictModeCmdParamKey, "false")) + + By("triggering reconcile by updating ArgoCD spec.cmdParams and verifying opt-out persists") + argocdFixture.Update(argoCD, func(ac *v1beta1.ArgoCD) { + if ac.Spec.CmdParams == nil { + ac.Spec.CmdParams = map[string]string{} + } + ac.Spec.CmdParams[common.ArgoCDApplicationSetControllerTokenRefStrictModeCmdParamKey] = "true" + }) + Eventually(cmdParamsCM, "30s", "5s").Should(configmapFixture.HaveStringDataKeyValue(common.ArgoCDApplicationSetControllerTokenRefStrictModeCmdParamKey, "true")) }) }) From 459e497a9fc213e1bdf55d7c3a54326b9d2fccda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20Gond=C5=BEa?= Date: Tue, 27 Oct 2026 14:18:50 +0100 Subject: [PATCH 3/5] tests(E2E): Port 1-051_validate_argocd_agent_principal_test.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Oliver Gondža --- ...51_validate_argocd_agent_principal_test.go | 1158 ----------------- ...51_validate_argocd_agent_principal_test.go | 69 +- 2 files changed, 58 insertions(+), 1169 deletions(-) delete mode 100644 argocd-operator/tests/ginkgo/sequential/1-051_validate_argocd_agent_principal_test.go diff --git a/argocd-operator/tests/ginkgo/sequential/1-051_validate_argocd_agent_principal_test.go b/argocd-operator/tests/ginkgo/sequential/1-051_validate_argocd_agent_principal_test.go deleted file mode 100644 index 1abccf296a3..00000000000 --- a/argocd-operator/tests/ginkgo/sequential/1-051_validate_argocd_agent_principal_test.go +++ /dev/null @@ -1,1158 +0,0 @@ -/* -Copyright 2025. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package sequential - -import ( - "context" - "fmt" - "slices" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - routev1 "github.com/openshift/api/route/v1" - monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - networkingv1 "k8s.io/api/networking/v1" - rbacv1 "k8s.io/api/rbac/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "sigs.k8s.io/controller-runtime/pkg/client" - - argov1beta1api "github.com/redhat-developer/gitops-operator/argocd-operator/api/v1beta1" - "github.com/redhat-developer/gitops-operator/argocd-operator/common" - "github.com/redhat-developer/gitops-operator/argocd-operator/controllers/argocdagent" - "github.com/redhat-developer/gitops-operator/argocd-operator/controllers/argoutil" - "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture" - agentFixture "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture/agent" - argocdFixture "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture/argocd" - deploymentFixture "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture/deployment" - k8sFixture "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture/k8s" - fixtureUtils "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture/utils" -) - -var _ = Describe("GitOps Operator Sequential E2E Tests", func() { - const ( - argoCDName = "example" - argoCDAgentPrincipalName = "example-agent-principal" // argoCDName + "-agent-principal" - principalMetricsServiceFmt = "%s-agent-principal-metrics" - principalRedisProxyServiceFmt = "%s-agent-principal-redisproxy" - principalHealthzServiceFmt = "%s-agent-principal-healthz" - - // Secret names - agentJWTSecretName = "argocd-agent-jwt" - agentPrincipalTLSSecretName = "argocd-agent-principal-tls" - agentRootCASecretName = "argocd-agent-ca" - agentResourceProxyTLSSecretName = "argocd-agent-resource-proxy-tls" - ) - - Context("1-051_validate_argocd_agent_principal", func() { - var ( - k8sClient client.Client - ctx context.Context - argoCD *argov1beta1api.ArgoCD - ns *corev1.Namespace - cleanupFunc func() - serviceAccount *corev1.ServiceAccount - role *rbacv1.Role - roleBinding *rbacv1.RoleBinding - clusterRole *rbacv1.ClusterRole - clusterRoleBinding *rbacv1.ClusterRoleBinding - serviceNames []string - deploymentNames []string - principalDeployment *appsv1.Deployment - expectedEnvVariables map[string]string - secretNames agentFixture.AgentSecretNames - principalRoute *routev1.Route - principalNetworkPolicy *networkingv1.NetworkPolicy - resourceProxyServiceName string - principalResources agentFixture.PrincipalResources - ) - - BeforeEach(func() { - fixture.EnsureSequentialCleanSlate() - k8sClient, _ = fixtureUtils.GetE2ETestKubeClient() - ctx = context.Background() - ns, cleanupFunc = fixture.CreateNamespaceWithCleanupFunc("argocd-agent-principal-1-051") - - // Define ArgoCD CR with principal enabled - argoCD = &argov1beta1api.ArgoCD{ - ObjectMeta: metav1.ObjectMeta{ - Name: argoCDName, - Namespace: ns.Name, - }, - Spec: argov1beta1api.ArgoCDSpec{ - Controller: argov1beta1api.ArgoCDApplicationControllerSpec{ - Enabled: new(false), - }, - ArgoCDAgent: &argov1beta1api.ArgoCDAgentSpec{ - Principal: &argov1beta1api.PrincipalSpec{ - Enabled: new(true), - Auth: "mtls:CN=([^,]+)", - LogLevel: "info", - Namespace: &argov1beta1api.PrincipalNamespaceSpec{ - AllowedNamespaces: []string{ - "*", - }, - }, - LabelSelector: "argocd-agent=true", - TLS: &argov1beta1api.PrincipalTLSSpec{ - InsecureGenerate: new(true), - }, - JWT: &argov1beta1api.PrincipalJWTSpec{ - InsecureGenerate: new(true), - }, - Server: &argov1beta1api.PrincipalServerSpec{ - KeepAliveMinInterval: "30s", - }, - }, - }, - SourceNamespaces: []string{ - "agent-managed", - "agent-autonomous", - }, - }, - } - - // Define required resources for principal pod - serviceAccount = &corev1.ServiceAccount{ - ObjectMeta: metav1.ObjectMeta{ - Name: argoCDAgentPrincipalName, - Namespace: ns.Name, - }, - } - - role = &rbacv1.Role{ - ObjectMeta: metav1.ObjectMeta{ - Name: argoCDAgentPrincipalName, - Namespace: ns.Name, - }, - } - - roleBinding = &rbacv1.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: argoCDAgentPrincipalName, - Namespace: ns.Name, - }, - } - - clusterRole = &rbacv1.ClusterRole{ - ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%s-%s-agent-principal", argoCDName, ns.Name), - }, - } - - clusterRoleBinding = &rbacv1.ClusterRoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%s-%s-agent-principal", argoCDName, ns.Name), - }, - } - - // List required secrets for principal pod - secretNames = agentFixture.AgentSecretNames{ - JWTSecretName: agentJWTSecretName, - PrincipalTLSSecretName: agentPrincipalTLSSecretName, - RootCASecretName: agentRootCASecretName, - ResourceProxyTLSSecretName: agentResourceProxyTLSSecretName, - RedisInitialPasswordSecretName: "example-redis-initial-password", - } - - resourceProxyServiceName = fmt.Sprintf("%s-agent-principal-resource-proxy", argoCDName) - serviceNames = []string{ - argoCDAgentPrincipalName, - fmt.Sprintf(principalMetricsServiceFmt, argoCDName), - fmt.Sprintf("%s-redis", argoCDName), - fmt.Sprintf("%s-repo-server", argoCDName), - fmt.Sprintf("%s-server", argoCDName), - fmt.Sprintf(principalRedisProxyServiceFmt, argoCDName), - resourceProxyServiceName, - fmt.Sprintf(principalHealthzServiceFmt, argoCDName), - } - deploymentNames = []string{fmt.Sprintf("%s-redis", argoCDName), fmt.Sprintf("%s-repo-server", argoCDName), fmt.Sprintf("%s-server", argoCDName)} - - principalDeployment = &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: argoCDAgentPrincipalName, - Namespace: ns.Name, - }, - } - - principalRoute = &routev1.Route{ - ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%s-agent-principal", argoCDName), - Namespace: ns.Name, - }, - } - - principalNetworkPolicy = &networkingv1.NetworkPolicy{ - ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%s-agent-principal-network-policy", argoCDName), - Namespace: ns.Name, - }, - } - - // List environment variables with expected values for the principal deployment - expectedEnvVariables = map[string]string{ - argocdagent.EnvArgoCDPrincipalLogLevel: "info", - argocdagent.EnvArgoCDPrincipalNamespace: ns.Name, - argocdagent.EnvArgoCDPrincipalAllowedNamespaces: "*", - argocdagent.EnvArgoCDPrincipalNamespaceCreateEnable: "false", - argocdagent.EnvArgoCDPrincipalNamespaceCreatePattern: "", - argocdagent.EnvArgoCDPrincipalNamespaceCreateLabels: "", - argocdagent.EnvArgoCDPrincipalTLSServerAllowGenerate: "true", - argocdagent.EnvArgoCDPrincipalJWTAllowGenerate: "true", - argocdagent.EnvArgoCDPrincipalAuth: "mtls:CN=([^,]+)", - argocdagent.EnvArgoCDPrincipalEnableResourceProxy: "true", - argocdagent.EnvArgoCDPrincipalKeepAliveMinInterval: "30s", - argocdagent.EnvArgoCDPrincipalRedisServerAddress: fmt.Sprintf("%s-%s:%d", argoCDName, "redis", common.ArgoCDDefaultRedisPort), - argocdagent.EnvArgoCDPrincipalRedisCompressionType: "gzip", - argocdagent.EnvArgoCDPrincipalLogFormat: "text", - argocdagent.EnvArgoCDPrincipalEnableWebSocket: "false", - argocdagent.EnvArgoCDPrincipalTLSSecretName: agentPrincipalTLSSecretName, - argocdagent.EnvArgoCDPrincipalTLSServerRootCASecretName: agentRootCASecretName, - argocdagent.EnvArgoCDPrincipalResourceProxySecretName: agentResourceProxyTLSSecretName, - argocdagent.EnvArgoCDPrincipalResourceProxyCaSecretName: agentRootCASecretName, - argocdagent.EnvArgoCDPrincipalJwtSecretName: agentJWTSecretName, - argocdagent.EnvArgoCDPrincipalLabelSelector: "argocd-agent=true", - argocdagent.EnvArgoCDPrincipalEnableSelfClusterRegistration: "false", - argocdagent.EnvArgoCDPrincipalSelfRegistrationClientCertSecret: "", - argocdagent.EnvArgoCDPrincipalResourceProxyAddress: fmt.Sprintf("%s-agent-principal-resource-proxy:%d", argoCDName, argocdagent.PrincipalResourceProxyServicePort), - } - - principalResources = agentFixture.PrincipalResources{ - PrincipalNamespaceName: ns.Name, - ArgoCDAgentPrincipalName: argoCDAgentPrincipalName, - ArgoCDName: argoCDName, - ServiceAccount: serviceAccount, - Role: role, - RoleBinding: roleBinding, - ClusterRole: clusterRole, - ClusterRoleBinding: clusterRoleBinding, - PrincipalDeployment: principalDeployment, - PrincipalRoute: principalRoute, - PrincipalNetworkPolicy: principalNetworkPolicy, - ServicesToDelete: []string{ - argoCDAgentPrincipalName, - fmt.Sprintf(principalMetricsServiceFmt, argoCDName), - fmt.Sprintf(principalRedisProxyServiceFmt, argoCDName), - resourceProxyServiceName, - fmt.Sprintf(principalHealthzServiceFmt, argoCDName), - }, - } - }) - - AfterEach(func() { - By("Cleanup cluster-scoped resources") - _ = k8sClient.Delete(ctx, clusterRole) - _ = k8sClient.Delete(ctx, clusterRoleBinding) - - By("Cleanup namespace") - if cleanupFunc != nil { - cleanupFunc() - } - }) - - createRequiredSecrets := func(namespace *corev1.Namespace, additionalPrincipalSANs ...string) { - agentFixture.CreateRequiredSecrets(agentFixture.PrincipalSecretsConfig{ - PrincipalNamespaceName: namespace.Name, - PrincipalServiceName: argoCDAgentPrincipalName, - ResourceProxyServiceName: resourceProxyServiceName, - JWTSecretName: secretNames.JWTSecretName, - PrincipalTLSSecretName: secretNames.PrincipalTLSSecretName, - RootCASecretName: secretNames.RootCASecretName, - ResourceProxyTLSSecretName: secretNames.ResourceProxyTLSSecretName, - AdditionalPrincipalSANs: additionalPrincipalSANs, - }) - } - - verifyExpectedResourcesExist := func(namespace *corev1.Namespace, expectRoute ...bool) { - var expectRoutePtr *bool - if len(expectRoute) > 0 { - expectRoutePtr = new(expectRoute[0]) - } - - agentFixture.VerifyExpectedResourcesExist(agentFixture.VerifyExpectedResourcesExistParams{ - Namespace: namespace, - ArgoCDAgentPrincipalName: argoCDAgentPrincipalName, - ArgoCDName: argoCDName, - ServiceAccount: serviceAccount, - Role: role, - RoleBinding: roleBinding, - ClusterRole: clusterRole, - ClusterRoleBinding: clusterRoleBinding, - PrincipalDeployment: principalDeployment, - PrincipalRoute: principalRoute, - SecretNames: secretNames, - ServiceNames: serviceNames, - PrincipalNetworkPolicy: principalNetworkPolicy, - DeploymentNames: deploymentNames, - ExpectRoute: expectRoutePtr, - }) - } - - verifyResourcesDeleted := func() { - agentFixture.VerifyResourcesDeleted(principalResources) - } - - It("should create argocd agent principal resources, but pod should fail to start as image does not exist", func() { - // Change log level to trace and custom image name - argoCD.Spec.ArgoCDAgent.Principal.LogLevel = "trace" - argoCD.Spec.ArgoCDAgent.Principal.Image = "quay.io/user/argocd-agent:v1" - - By("Create ArgoCD instance") - - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - By("Verify expected resources are created for principal pod") - - verifyExpectedResourcesExist(ns) - - By("Verify principal has the custom image we specified in ArgoCD CR") - - container := deploymentFixture.GetTemplateSpecContainerByName(argoCDAgentPrincipalName, *principalDeployment) - Expect(container).ToNot(BeNil()) - Expect(container.Image).To(Equal("quay.io/user/argocd-agent:v1")) - - By("Verify environment variables are set correctly") - - // update expected value in default environment variables according to ArgoCD CR in the test - expectedEnvVariables[argocdagent.EnvArgoCDPrincipalLogLevel] = "trace" - - for key, value := range expectedEnvVariables { - Expect(container.Env).To(ContainElement(corev1.EnvVar{Name: key, Value: value}), "Environment variable %s should be set to %s", key, value) - } - - By("Disable principal") - - Expect(k8sClient.Get(ctx, client.ObjectKey{Name: argoCDName, Namespace: ns.Name}, argoCD)).To(Succeed()) - - argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) { - ac.Spec.ArgoCDAgent.Principal.Enabled = new(false) - }) - - By("Verify principal resources are deleted") - - verifyResourcesDeleted() - }) - - It("should create argocd agent principal resources, and pod should start successfully with default image", func() { - // Add a custom environment variable to the principal server - argoCD.Spec.ArgoCDAgent.Principal.Env = []corev1.EnvVar{{Name: "TEST_ENV", Value: "test_value"}} - - By("Create ArgoCD instance") - - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - By("Verify expected resources are created for principal pod") - - verifyExpectedResourcesExist(ns) - - By("Verify principal uses the default agent image") - - container := deploymentFixture.GetTemplateSpecContainerByName(argoCDAgentPrincipalName, *principalDeployment) - Expect(container).ToNot(BeNil()) - Expect(container.Image).To(Equal(common.ArgoCDAgentPrincipalDefaultImageName)) - - By("Create required secrets and certificates for principal pod to start properly") - - createRequiredSecrets(ns) - - By("Verify principal pod starts successfully by checking logs") - - agentFixture.VerifyLogs(argoCDAgentPrincipalName, ns.Name, []string{ - "Starting metrics server", - "Redis proxy started", - "Application informer synced and ready", - "AppProject informer synced and ready", - "Resource proxy started", - "Namespace informer synced and ready", - "Starting healthz server", - }) - - By("verify that deployment is in Ready state") - - Eventually(principalDeployment, "120s", "5s").Should(deploymentFixture.HaveReadyReplicas(1), "Principal deployment should become ready") - - By("Verify environment variables are set correctly") - - for key, value := range expectedEnvVariables { - Expect(container.Env).To(ContainElement(corev1.EnvVar{Name: key, Value: value}), "Environment variable %s should be set to %s", key, value) - } - - Expect(container.Env).NotTo(ContainElement( - HaveField("Name", "REDIS_PASSWORD"), - ), "REDIS_PASSWORD should not be set") - - By("Disable principal") - - Expect(k8sClient.Get(ctx, client.ObjectKey{Name: argoCDName, Namespace: ns.Name}, argoCD)).To(Succeed()) - - argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) { - ac.Spec.ArgoCDAgent.Principal.Enabled = nil - }) - - By("Verify principal resources are deleted") - - verifyResourcesDeleted() - }) - - It("Should reflect configuration changes from ArgoCD CR to the principal deployment", func() { - By("Create ArgoCD instance") - - argoCD.Spec.ArgoCDAgent.Principal.Image = common.ArgoCDAgentPrincipalDefaultImageName - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - By("Verify expected resources are created for principal pod") - - verifyExpectedResourcesExist(ns) - - By("Verify principal has the custom image we specified in ArgoCD CR") - - container := deploymentFixture.GetTemplateSpecContainerByName(argoCDAgentPrincipalName, *principalDeployment) - Expect(container).ToNot(BeNil()) - Expect(container.Image).To(Equal(common.ArgoCDAgentPrincipalDefaultImageName)) - - By("Verify environment variables are set correctly") - - // update expected value in default environment variables according to ArgoCD CR in the test - for key, value := range expectedEnvVariables { - Expect(container.Env).To(ContainElement(corev1.EnvVar{Name: key, Value: value}), "Environment variable %s should be set to %s", key, value) - } - - By("Update ArgoCD CR with new configuration") - - Expect(k8sClient.Get(ctx, client.ObjectKey{Name: argoCDName, Namespace: ns.Name}, argoCD)).To(Succeed()) - - argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) { - ac.Spec.ArgoCDAgent.Principal.LogLevel = "trace" - ac.Spec.ArgoCDAgent.Principal.LogFormat = "json" - ac.Spec.ArgoCDAgent.Principal.Server.KeepAliveMinInterval = "60s" - ac.Spec.ArgoCDAgent.Principal.Server.EnableWebSocket = new(true) - ac.Spec.ArgoCDAgent.Principal.Image = "quay.io/argoprojlabs/argocd-agent:v0.5.1" - ac.Spec.ArgoCDAgent.Principal.LabelSelector = "env=staging" - - ac.Spec.ArgoCDAgent.Principal.Namespace.AllowedNamespaces = []string{"agent-managed", "agent-autonomous"} - ac.Spec.ArgoCDAgent.Principal.Namespace.EnableNamespaceCreate = new(true) - ac.Spec.ArgoCDAgent.Principal.Namespace.NamespaceCreatePattern = "agent-.*" - ac.Spec.ArgoCDAgent.Principal.Namespace.NamespaceCreateLabels = []string{"environment=agent"} - - ac.Spec.ArgoCDAgent.Principal.TLS.InsecureGenerate = new(false) - ac.Spec.ArgoCDAgent.Principal.TLS.SecretName = "argocd-agent-principal-tls-v2" - ac.Spec.ArgoCDAgent.Principal.TLS.RootCASecretName = "argocd-agent-ca-v2" - - ac.Spec.ArgoCDAgent.Principal.JWT.InsecureGenerate = new(false) - ac.Spec.ArgoCDAgent.Principal.JWT.SecretName = "argocd-agent-jwt-v2" - - ac.Spec.ArgoCDAgent.Principal.ResourceProxy = &argov1beta1api.PrincipalResourceProxySpec{ - SecretName: "argocd-agent-resource-proxy-tls-v2", - CASecretName: "argocd-agent-ca-v2", - } - }) - - By("Create required secrets and certificates for principal pod to start properly") - - // Update secret names according to ArgoCD CR - secretNames = agentFixture.AgentSecretNames{ - JWTSecretName: "argocd-agent-jwt-v2", - PrincipalTLSSecretName: "argocd-agent-principal-tls-v2", - RootCASecretName: "argocd-agent-ca-v2", - ResourceProxyTLSSecretName: "argocd-agent-resource-proxy-tls-v2", - } - createRequiredSecrets(ns) - - By("Verify principal has the updated image we specified in ArgoCD CR") - - Eventually(principalDeployment).Should(k8sFixture.ExistByName()) - Eventually( - func() bool { - // Fetch the latest deployment from the cluster - err := k8sClient.Get(ctx, client.ObjectKey{Name: argoCDAgentPrincipalName, Namespace: ns.Name}, principalDeployment) - if err != nil { - GinkgoWriter.Println("Error getting deployment for image check: ", err) - return false - } - container = deploymentFixture.GetTemplateSpecContainerByName(argoCDAgentPrincipalName, *principalDeployment) - if container == nil { - return false - } - return container.Image == "quay.io/argoprojlabs/argocd-agent:v0.5.1" - }, "120s", "5s").Should(BeTrue(), "Principal deployment should have the updated image") - - By("verify that deployment is in Ready state") - - Eventually(principalDeployment, "120s", "5s").Should(deploymentFixture.HaveReadyReplicas(1), "Principal deployment should become ready") - - By("Verify environment variables are updated correctly") - - expectedEnvVariables[argocdagent.EnvArgoCDPrincipalLogLevel] = "trace" - expectedEnvVariables[argocdagent.EnvArgoCDPrincipalLogFormat] = "json" - expectedEnvVariables[argocdagent.EnvArgoCDPrincipalKeepAliveMinInterval] = "60s" - expectedEnvVariables[argocdagent.EnvArgoCDPrincipalEnableWebSocket] = "true" - expectedEnvVariables[argocdagent.EnvArgoCDPrincipalAllowedNamespaces] = "agent-managed,agent-autonomous" - expectedEnvVariables[argocdagent.EnvArgoCDPrincipalNamespaceCreateEnable] = "true" - expectedEnvVariables[argocdagent.EnvArgoCDPrincipalNamespaceCreatePattern] = "agent-.*" - expectedEnvVariables[argocdagent.EnvArgoCDPrincipalNamespaceCreateLabels] = "environment=agent" - expectedEnvVariables[argocdagent.EnvArgoCDPrincipalTLSServerAllowGenerate] = "false" - expectedEnvVariables[argocdagent.EnvArgoCDPrincipalJWTAllowGenerate] = "false" - expectedEnvVariables[argocdagent.EnvArgoCDPrincipalResourceProxySecretName] = "argocd-agent-resource-proxy-tls-v2" - expectedEnvVariables[argocdagent.EnvArgoCDPrincipalResourceProxyCaSecretName] = "argocd-agent-ca-v2" - expectedEnvVariables[argocdagent.EnvArgoCDPrincipalTLSSecretName] = "argocd-agent-principal-tls-v2" - expectedEnvVariables[argocdagent.EnvArgoCDPrincipalTLSServerRootCASecretName] = "argocd-agent-ca-v2" - expectedEnvVariables[argocdagent.EnvArgoCDPrincipalJwtSecretName] = "argocd-agent-jwt-v2" - expectedEnvVariables[argocdagent.EnvArgoCDPrincipalLabelSelector] = "env=staging" - - for key, value := range expectedEnvVariables { - Expect(container.Env).To(ContainElement(corev1.EnvVar{Name: key, Value: value}), "Environment variable %s should be set to %s", key, value) - } - }) - - It("Should restore Redis Auth volume and mount if removed from principal deployment", func() { - By("Creating ArgoCD instance normally") - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - Eventually(argoCD, "5m", "5s").Should(argocdFixture.BeAvailable()) - Eventually(principalDeployment).Should(k8sFixture.ExistByName()) - - By("Removing Redis Auth volume and mount from the deployment") - err := k8sClient.Get(ctx, client.ObjectKey{Name: argoCDAgentPrincipalName, Namespace: ns.Name}, principalDeployment) - Expect(err).ToNot(HaveOccurred()) - - deploymentFixture.Update(principalDeployment, func(p *appsv1.Deployment) { - volLen := len(p.Spec.Template.Spec.Volumes) - mountLen := len(p.Spec.Template.Spec.Containers[0].VolumeMounts) - p.Spec.Template.Spec.Volumes = slices.DeleteFunc(p.Spec.Template.Spec.Volumes, func(v corev1.Volume) bool { - return v.Name == argoutil.RedisAuthVolumeName - }) - p.Spec.Template.Spec.Containers[0].VolumeMounts = slices.DeleteFunc(p.Spec.Template.Spec.Containers[0].VolumeMounts, func(vm corev1.VolumeMount) bool { - return vm.Name == argoutil.RedisAuthVolumeName - }) - // Double check we have actually removed the volume and mount - Expect(p.Spec.Template.Spec.Volumes).To(HaveLen(volLen - 1)) - Expect(p.Spec.Template.Spec.Containers[0].VolumeMounts).To(HaveLen(mountLen - 1)) - }) - - By("Redis Auth volume and mount are re-added by the operator") - Eventually(func() bool { - err := k8sClient.Get(ctx, client.ObjectKey{Name: argoCDAgentPrincipalName, Namespace: ns.Name}, principalDeployment) - if err != nil { - return false - } - volFound := slices.ContainsFunc(principalDeployment.Spec.Template.Spec.Volumes, func(v corev1.Volume) bool { - return v.Name == argoutil.RedisAuthVolumeName - }) - mountFound := slices.ContainsFunc(principalDeployment.Spec.Template.Spec.Containers[0].VolumeMounts, func(vm corev1.VolumeMount) bool { - return vm.Name == argoutil.RedisAuthVolumeName - }) - return volFound && mountFound - }, "10s", "1s").Should(BeTrue(), "Redis Auth volume and mount should be restored to the principal deployment") - }) - - It("should handle route disabled configuration correctly", func() { - By("Create ArgoCD instance with route disabled") - - argoCD.Spec.ArgoCDAgent.Principal.Server.Route = argov1beta1api.ArgoCDAgentPrincipalRouteSpec{ - Enabled: new(false), - } - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - By("Verify expected resources are created for principal pod") - - verifyExpectedResourcesExist(ns, false) - - By("Verify Route for principal does not exist") - - if fixture.RunningOnOpenShift() { - Consistently(principalRoute, "10s", "1s").Should(k8sFixture.NotExistByName()) - } - }) - - It("should handle route enabled configuration correctly", func() { - By("Create ArgoCD instance with route enabled") - - argoCD.Spec.ArgoCDAgent.Principal.Server.Route = argov1beta1api.ArgoCDAgentPrincipalRouteSpec{ - Enabled: new(true), - } - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - By("Verify expected resources are created for principal pod") - - verifyExpectedResourcesExist(ns) - - By("Verify Route for principal exists") - - if fixture.RunningOnOpenShift() { - Eventually(principalRoute).Should(k8sFixture.ExistByName()) - } - }) - - It("should handle route toggle from enabled to disabled correctly", func() { - By("Create ArgoCD instance with route enabled") - - argoCD.Spec.ArgoCDAgent.Principal.Server.Route = argov1beta1api.ArgoCDAgentPrincipalRouteSpec{ - Enabled: new(true), - } - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - By("Verify expected resources are created for principal pod") - - verifyExpectedResourcesExist(ns) - - By("Verify Route for principal exists") - - if fixture.RunningOnOpenShift() { - Eventually(principalRoute).Should(k8sFixture.ExistByName()) - } - - By("Disable route while keeping principal enabled") - - Expect(k8sClient.Get(ctx, client.ObjectKey{Name: argoCDName, Namespace: ns.Name}, argoCD)).To(Succeed()) - argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) { - ac.Spec.ArgoCDAgent.Principal.Server.Route.Enabled = new(false) - }) - - By("Verify Route for principal is deleted") - - if fixture.RunningOnOpenShift() { - Eventually(principalRoute).Should(k8sFixture.NotExistByName()) - } - - By("Verify other principal resources still exist") - - Eventually(principalDeployment).Should(k8sFixture.ExistByName()) - - for _, serviceName := range []string{ - fmt.Sprintf("%s-agent-principal", argoCDName), - fmt.Sprintf(principalMetricsServiceFmt, argoCDName), - fmt.Sprintf(principalRedisProxyServiceFmt, argoCDName), - fmt.Sprintf("%s-agent-principal-resource-proxy", argoCDName), - fmt.Sprintf(principalHealthzServiceFmt, argoCDName), - } { - service := &corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: serviceName, - Namespace: ns.Name, - }, - } - Eventually(service, "30s", "2s").Should(k8sFixture.ExistByName(), "Service '%s' should exist in namespace '%s'", serviceName, ns.Name) - } - - By("Re-enable route") - - Expect(k8sClient.Get(ctx, client.ObjectKey{Name: argoCDName, Namespace: ns.Name}, argoCD)).To(Succeed()) - argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) { - ac.Spec.ArgoCDAgent.Principal.Server.Route.Enabled = new(true) - }) - - By("Verify Route for principal is recreated") - - if fixture.RunningOnOpenShift() { - Eventually(principalRoute).Should(k8sFixture.ExistByName()) - } - }) - - It("should handle service type ClusterIP configuration correctly", func() { - By("Create ArgoCD instance with service type ClusterIP") - - argoCD.Spec.ArgoCDAgent.Principal.Server.Service = argov1beta1api.ArgoCDAgentPrincipalServiceSpec{ - Type: corev1.ServiceTypeClusterIP, - } - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - By("Verify expected resources are created for principal pod") - - verifyExpectedResourcesExist(ns) - - By("Verify principal service has ClusterIP type") - - principalService := &corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: argoCDAgentPrincipalName, - Namespace: ns.Name, - }, - } - Eventually(principalService).Should(k8sFixture.ExistByName()) - Expect(principalService.Spec.Type).To(Equal(corev1.ServiceTypeClusterIP)) - }) - - It("should handle service type LoadBalancer configuration correctly", func() { - By("Create ArgoCD instance with service type LoadBalancer") - - argoCD.Spec.ArgoCDAgent.Principal.Server.Service = argov1beta1api.ArgoCDAgentPrincipalServiceSpec{ - Type: corev1.ServiceTypeLoadBalancer, - Annotations: map[string]string{ - "test.argocd.io/annotation": "test", - }, - } - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - By("Verify expected resources are created for principal pod") - - verifyExpectedResourcesExist(ns) - - By("Verify principal service has LoadBalancer type") - - principalService := &corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: argoCDAgentPrincipalName, - Namespace: ns.Name, - }, - } - Eventually(principalService).Should(k8sFixture.ExistByName()) - Eventually(principalService.Spec.Type).Should(Equal(corev1.ServiceTypeLoadBalancer)) - Eventually(func() map[string]string { - err := k8sClient.Get(ctx, client.ObjectKey{Name: argoCDAgentPrincipalName, Namespace: ns.Name}, principalService) - if err != nil { - return nil - } - return principalService.Annotations - }, "30s", "2s").Should(HaveKeyWithValue("test.argocd.io/annotation", "test")) - - By("Update service annotations") - Expect(k8sClient.Get(ctx, client.ObjectKey{Name: argoCDName, Namespace: ns.Name}, argoCD)).To(Succeed()) - - argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) { - ac.Spec.ArgoCDAgent.Principal.Server.Service.Annotations = map[string]string{ - "test.argocd.io/annotation": "test2", - } - }) - - By("Verify principal service has updated annotations") - - principalService = &corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: argoCDAgentPrincipalName, - Namespace: ns.Name, - }, - } - Eventually(principalService).Should(k8sFixture.ExistByName()) - Eventually(func() map[string]string { - err := k8sClient.Get(ctx, client.ObjectKey{Name: argoCDAgentPrincipalName, Namespace: ns.Name}, principalService) - if err != nil { - return nil - } - return principalService.Annotations - }, "30s", "2s").Should(HaveKeyWithValue("test.argocd.io/annotation", "test2")) - - By("Remove service annotations") - Expect(k8sClient.Get(ctx, client.ObjectKey{Name: argoCDName, Namespace: ns.Name}, argoCD)).To(Succeed()) - - argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) { - ac.Spec.ArgoCDAgent.Principal.Server.Service = argov1beta1api.ArgoCDAgentPrincipalServiceSpec{ - Type: corev1.ServiceTypeLoadBalancer, - } - }) - - By("Verify principal service has no annotations") - - principalService = &corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: argoCDAgentPrincipalName, - Namespace: ns.Name, - }, - } - - Eventually(principalService).Should(k8sFixture.ExistByName()) - Eventually(func() map[string]string { - err := k8sClient.Get(ctx, client.ObjectKey{Name: argoCDAgentPrincipalName, Namespace: ns.Name}, principalService) - if err != nil { - return nil - } - return principalService.Annotations - }, "30s", "2s").ShouldNot(HaveKey("test.argocd.io/annotation")) - - }) - - It("should handle service type updates correctly", func() { - By("Create ArgoCD instance with service type ClusterIP") - - argoCD.Spec.ArgoCDAgent.Principal.Server.Service = argov1beta1api.ArgoCDAgentPrincipalServiceSpec{ - Type: corev1.ServiceTypeClusterIP, - } - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - By("Verify expected resources are created for principal pod") - - verifyExpectedResourcesExist(ns) - - By("Verify principal service has ClusterIP type initially") - - principalService := &corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: argoCDAgentPrincipalName, - Namespace: ns.Name, - }, - } - Eventually(principalService).Should(k8sFixture.ExistByName()) - Expect(principalService.Spec.Type).To(Equal(corev1.ServiceTypeClusterIP)) - - By("Update service type to LoadBalancer") - - Expect(k8sClient.Get(ctx, client.ObjectKey{Name: argoCDName, Namespace: ns.Name}, argoCD)).To(Succeed()) - argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) { - ac.Spec.ArgoCDAgent.Principal.Server.Service.Type = corev1.ServiceTypeLoadBalancer - }) - - By("Verify principal service type is updated to LoadBalancer") - - Eventually(func() corev1.ServiceType { - err := k8sClient.Get(ctx, client.ObjectKey{Name: argoCDAgentPrincipalName, Namespace: ns.Name}, principalService) - if err != nil { - return "" - } - return principalService.Spec.Type - }, "30s", "2s").Should(Equal(corev1.ServiceTypeLoadBalancer)) - }) - - It("should deploy principal via namespace-scoped ArgoCD instance and verify cluster role and cluster role binding are not created", func() { - By("Create namespace-scoped ArgoCD instance") - - // Create namespace for hosting namespace-scoped ArgoCD instance with principal - nsScoped, cleanupFuncScoped := fixture.CreateNamespaceWithCleanupFunc("argocd-agent-principal-ns-scoped-1-051") - defer cleanupFuncScoped() - - // Update namespace in ArgoCD CR - argoCD.Namespace = nsScoped.Name - - // Update namespace in resource references - serviceAccount.Namespace = nsScoped.Name - role.Namespace = nsScoped.Name - roleBinding.Namespace = nsScoped.Name - principalDeployment.Namespace = nsScoped.Name - principalRoute.Namespace = nsScoped.Name - clusterRole.Name = fmt.Sprintf("%s-%s-agent-principal", argoCDName, nsScoped.Name) - clusterRoleBinding.Name = fmt.Sprintf("%s-%s-agent-principal", argoCDName, nsScoped.Name) - - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - By("Verify namespace-scoped resources are created for principal") - - Eventually(serviceAccount, "30s", "2s").Should(k8sFixture.ExistByName()) - Eventually(role, "30s", "2s").Should(k8sFixture.ExistByName()) - Eventually(roleBinding, "30s", "2s").Should(k8sFixture.ExistByName()) - Eventually(principalDeployment, "30s", "2s").Should(k8sFixture.ExistByName()) - for _, serviceName := range serviceNames { - service := &corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: serviceName, - Namespace: nsScoped.Name, - }, - } - Eventually(service, "30s", "2s").Should(k8sFixture.ExistByName(), - "Service '%s' should exist in namespace '%s'", serviceName, nsScoped.Name) - } - - By("Verify ClusterRole and ClusterRoleBinding are not created") - Consistently(clusterRole, "10s", "1s").Should(k8sFixture.NotExistByName(), - "ClusterRole '%s' should not exist for namespace-scoped ArgoCD instance", clusterRole.Name) - - Consistently(clusterRoleBinding, "10s", "1s").Should(k8sFixture.NotExistByName(), - "ClusterRoleBinding '%s' should not exist for namespace-scoped ArgoCD instance", clusterRoleBinding.Name) - - By("Delete ArgoCD instance") - Expect(k8sClient.Delete(ctx, argoCD)).To(Succeed()) - Eventually(func() bool { - err := k8sClient.Get(ctx, client.ObjectKey{Name: argoCD.Name, Namespace: argoCD.Namespace}, argoCD) - return err != nil - }, "60s", "2s").Should(BeTrue(), "ArgoCD should be deleted") - }) - - It("should delete existing cluster role and cluster role binding if ArgoCD instance is namespace-scoped", func() { - By("Create namespace-scoped ArgoCD instance namespace") - - // Create namespace for hosting namespace-scoped ArgoCD instance with principal - nsScoped, cleanupFuncScoped := fixture.CreateNamespaceWithCleanupFunc("argocd-agent-principal-ns-scoped-1-051") - defer cleanupFuncScoped() - - // Update namespace in ArgoCD CR - argoCD.Namespace = nsScoped.Name - - // Update namespace in resource references - serviceAccount.Namespace = nsScoped.Name - role.Namespace = nsScoped.Name - roleBinding.Namespace = nsScoped.Name - principalDeployment.Namespace = nsScoped.Name - principalRoute.Namespace = nsScoped.Name - clusterRole.Name = fmt.Sprintf("%s-%s-agent-principal", argoCDName, nsScoped.Name) - clusterRoleBinding.Name = fmt.Sprintf("%s-%s-agent-principal", argoCDName, nsScoped.Name) - - By("Pre-create ClusterRole and ClusterRoleBinding before ArgoCD instance") - - preExistingClusterRole := &rbacv1.ClusterRole{ - ObjectMeta: metav1.ObjectMeta{ - Name: clusterRole.Name, - Labels: map[string]string{ - "app.kubernetes.io/name": "test", - }, - }, - } - Expect(k8sClient.Create(ctx, preExistingClusterRole)).To(Succeed()) - - preExistingClusterRoleBinding := &rbacv1.ClusterRoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: clusterRoleBinding.Name, - Labels: map[string]string{ - "app.kubernetes.io/name": "test", - }, - }, - Subjects: []rbacv1.Subject{ - { - Kind: rbacv1.ServiceAccountKind, - Name: "default", - Namespace: nsScoped.Name, - }, - }, - RoleRef: rbacv1.RoleRef{ - APIGroup: rbacv1.GroupName, - Kind: "ClusterRole", - Name: clusterRole.Name, - }, - } - Expect(k8sClient.Create(ctx, preExistingClusterRoleBinding)).To(Succeed()) - - By("Verify pre-existing ClusterRole and ClusterRoleBinding exist") - - Eventually(clusterRole, "30s", "1s").Should(k8sFixture.ExistByName(), - "Pre-existing ClusterRole '%s' should exist before ArgoCD instance creation", clusterRole.Name) - Eventually(clusterRoleBinding, "30s", "1s").Should(k8sFixture.ExistByName(), - "Pre-existing ClusterRoleBinding '%s' should exist before ArgoCD instance creation", clusterRoleBinding.Name) - - By("Create namespace-scoped ArgoCD instance with principal") - - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - By("Verify pre-existing ClusterRole and ClusterRoleBinding are deleted") - - Eventually(clusterRole, "60s", "2s").Should(k8sFixture.NotExistByName(), - "ClusterRole '%s' should be deleted for namespace-scoped ArgoCD instance", clusterRole.Name) - - Eventually(clusterRoleBinding, "60s", "2s").Should(k8sFixture.NotExistByName(), - "ClusterRoleBinding '%s' should be deleted for namespace-scoped ArgoCD instance", clusterRoleBinding.Name) - - By("Delete ArgoCD instance") - Expect(k8sClient.Delete(ctx, argoCD)).To(Succeed()) - Eventually(func() bool { - err := k8sClient.Get(ctx, client.ObjectKey{Name: argoCD.Name, Namespace: argoCD.Namespace}, argoCD) - return err != nil - }, "60s", "2s").Should(BeTrue(), "ArgoCD should be deleted") - }) - - It("should create principal NetworkPolicy if principal is enabled", func() { - By("Create ArgoCD instance with principal enabled") - - argoCD.Spec.ArgoCDAgent.Principal.Enabled = new(true) - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - verifyExpectedResourcesExist(ns) - By("Verify principal NetworkPolicy exists and has expected policy addresses and ports") - - Expect(principalNetworkPolicy.Spec.PodSelector.MatchLabels[common.ArgoCDKeyName]).To(Equal(argoCDAgentPrincipalName)) - Expect(principalNetworkPolicy.Spec.PolicyTypes).To(ContainElement(networkingv1.PolicyTypeIngress)) - Expect(principalNetworkPolicy.Spec.Ingress).To(HaveLen(2)) - - ing := principalNetworkPolicy.Spec.Ingress[0] - Expect(ing.From).To(HaveLen(1)) - Expect(ing.From[0].NamespaceSelector).ToNot(BeNil()) - Expect(*ing.From[0].NamespaceSelector).To(Equal(metav1.LabelSelector{})) - - // Ports the principal exposes (see argocdagent deployment/service code) - expectedPorts := map[int32]bool{ - 8443: true, // principal HTTPS target port - 8000: true, // metrics - 6379: true, // redis proxy - 9090: true, // resource proxy - 8003: true, // healthz - } - Expect(ing.Ports).To(HaveLen(len(expectedPorts))) - for _, p := range ing.Ports { - Expect(p.Port).ToNot(BeNil()) - Expect(expectedPorts[p.Port.IntVal]).To(BeTrue(), "unexpected ingress port %d", p.Port.IntVal) - } - Expect(principalNetworkPolicy.Spec.Ingress[1].From).To(HaveLen(1)) - - Expect(*principalNetworkPolicy.Spec.Ingress[1].From[0].IPBlock).To(Equal(networkingv1.IPBlock{CIDR: "0.0.0.0/0"})) - Expect(principalNetworkPolicy.Spec.Ingress[1].Ports).To(HaveLen(2)) - Expect(principalNetworkPolicy.Spec.Ingress[1].Ports[0].Port.IntVal).To(Equal(int32(8443))) - Expect(principalNetworkPolicy.Spec.Ingress[1].Ports[1].Port.IntVal).To(Equal(int32(443))) - - By("Verify principal NetworkPolicy is deleted when principal instance is disabled") - - argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) { - ac.Spec.ArgoCDAgent.Principal.Enabled = nil - }) - - Eventually(principalNetworkPolicy).Should(k8sFixture.NotExistByName()) - - By("Verify principal NetworkPolicy is created when principal instance is enabled and network policy is enabled") - - argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) { - ac.Spec.ArgoCDAgent.Principal.Enabled = new(true) - ac.Spec.NetworkPolicy.Enabled = new(true) - }) - Eventually(principalNetworkPolicy).Should(k8sFixture.ExistByName()) - - By("Verify principal NetworkPolicy is not created when network policy is disabled") - - argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) { - ac.Spec.NetworkPolicy.Enabled = new(false) - }) - - Eventually(principalNetworkPolicy).Should(k8sFixture.NotExistByName()) - }) - - It("should create and delete principal ServiceMonitor based on prometheus enabled flag", func() { - By("Create ArgoCD instance with principal enabled and prometheus enabled") - - argoCD.Spec.Prometheus.Enabled = true - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - By("Verify expected resources are created for principal pod") - - verifyExpectedResourcesExist(ns) - - By("Verify principal ServiceMonitor is created") - - principalServiceMonitor := &monitoringv1.ServiceMonitor{ - ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%s-agent-principal-metrics", argoCDName), - Namespace: ns.Name, - }, - } - Eventually(principalServiceMonitor, "2m", "2s").Should(k8sFixture.ExistByName()) - - By("Disable prometheus and verify ServiceMonitor is deleted") - - Expect(k8sClient.Get(ctx, client.ObjectKey{Name: argoCDName, Namespace: ns.Name}, argoCD)).To(Succeed()) - argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) { - ac.Spec.Prometheus.Enabled = false - }) - - Eventually(principalServiceMonitor, "2m", "2s").Should(k8sFixture.NotExistByName()) - - By("Re-enable prometheus and verify ServiceMonitor is recreated") - - Expect(k8sClient.Get(ctx, client.ObjectKey{Name: argoCDName, Namespace: ns.Name}, argoCD)).To(Succeed()) - argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) { - ac.Spec.Prometheus.Enabled = true - }) - - Eventually(principalServiceMonitor, "2m", "2s").Should(k8sFixture.ExistByName()) - - By("Disable principal and verify ServiceMonitor is deleted") - - Expect(k8sClient.Get(ctx, client.ObjectKey{Name: argoCDName, Namespace: ns.Name}, argoCD)).To(Succeed()) - argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) { - ac.Spec.ArgoCDAgent.Principal.Enabled = new(false) - }) - - Eventually(principalServiceMonitor, "2m", "2s").Should(k8sFixture.NotExistByName()) - }) - - It("shouldn't create ClusterRole and ClusterRoleBinding for principal if spec.DefaultClusterScopedRoleDisabled is set", func() { - By("Create ArgoCD instance with principal enabled and DefaultClusterScopedRoleDisabled is true") - argoCD.Spec.DefaultClusterScopedRoleDisabled = true - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - By("Verify Argo CD CR is reconciled") - Eventually(principalDeployment).Should(k8sFixture.ExistByName()) - - By("Verify ClusterRole and ClusterRoleBinding do not exist") - Eventually(clusterRole, "60s", "2s").Should(k8sFixture.NotExistByName()) - Eventually(clusterRoleBinding, "60s", "2s").Should(k8sFixture.NotExistByName()) - - Consistently(clusterRole, "10s", "2s").Should(k8sFixture.NotExistByName()) - Consistently(clusterRoleBinding, "10s", "2s").Should(k8sFixture.NotExistByName()) - - By("Namespaced RBAC objects should still exist") - Eventually(role, "60s", "2s").Should(k8sFixture.ExistByName()) - Eventually(roleBinding, "60s", "2s").Should(k8sFixture.ExistByName()) - - By("Unset DefaultClusterScopedRoleDisabled and make sure cluster scoped RBAC objects are created") - argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) { - ac.Spec.DefaultClusterScopedRoleDisabled = false - }) - Eventually(clusterRole, "60s", "2s").Should(k8sFixture.ExistByName()) - Eventually(clusterRoleBinding, "60s", "2s").Should(k8sFixture.ExistByName()) - - By("Setting DefaultClusterScopedRoleDisabled again deletes clusterRole and clusterRoleBinding") - argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) { - ac.Spec.DefaultClusterScopedRoleDisabled = true - }) - Eventually(clusterRole, "60s", "2s").Should(k8sFixture.NotExistByName()) - Eventually(clusterRoleBinding, "60s", "2s").Should(k8sFixture.NotExistByName()) - Consistently(clusterRole, "10s", "2s").Should(k8sFixture.NotExistByName()) - Consistently(clusterRoleBinding, "10s", "2s").Should(k8sFixture.NotExistByName()) - }) - - It("should propagate self-registration configuration to principal deployment env vars", func() { - By("Create ArgoCD instance with self-registration enabled") - - argoCD.Spec.ArgoCDAgent.Principal.SelfRegistration = &argov1beta1api.PrincipalSelfRegistrationSpec{ - Enabled: new(true), - ClientCertSecretName: "argocd-agent-shared-client-cert", - } - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - By("Verify expected resources are created for principal pod") - - verifyExpectedResourcesExist(ns) - - By("Verify self-registration environment variables are set correctly") - - container := deploymentFixture.GetTemplateSpecContainerByName(argoCDAgentPrincipalName, *principalDeployment) - Expect(container).ToNot(BeNil()) - - expectedEnvVariables[argocdagent.EnvArgoCDPrincipalEnableSelfClusterRegistration] = "true" - expectedEnvVariables[argocdagent.EnvArgoCDPrincipalSelfRegistrationClientCertSecret] = "argocd-agent-shared-client-cert" - - for key, value := range expectedEnvVariables { - Expect(container.Env).To(ContainElement(corev1.EnvVar{Name: key, Value: value}), "Environment variable %s should be set to %s", key, value) - } - - By("Update self-registration configuration: disable and change client cert secret") - - Expect(k8sClient.Get(ctx, client.ObjectKey{Name: argoCDName, Namespace: ns.Name}, argoCD)).To(Succeed()) - argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) { - ac.Spec.ArgoCDAgent.Principal.SelfRegistration.Enabled = new(false) - ac.Spec.ArgoCDAgent.Principal.SelfRegistration.ClientCertSecretName = "updated-client-cert" - }) - - By("Wait for the client cert secret update to propagate, then verify all env vars") - - Eventually(func() bool { - err := k8sClient.Get(ctx, client.ObjectKey{Name: argoCDAgentPrincipalName, Namespace: ns.Name}, principalDeployment) - if err != nil { - return false - } - container = deploymentFixture.GetTemplateSpecContainerByName(argoCDAgentPrincipalName, *principalDeployment) - if container == nil { - return false - } - for _, env := range container.Env { - if env.Name == argocdagent.EnvArgoCDPrincipalSelfRegistrationClientCertSecret { - return env.Value == "updated-client-cert" - } - } - return false - }, "120s", "5s").Should(BeTrue(), "Self-registration client cert secret should be updated") - - expectedEnvVariables[argocdagent.EnvArgoCDPrincipalEnableSelfClusterRegistration] = "false" - expectedEnvVariables[argocdagent.EnvArgoCDPrincipalSelfRegistrationClientCertSecret] = "updated-client-cert" - - for key, value := range expectedEnvVariables { - Expect(container.Env).To(ContainElement(corev1.EnvVar{Name: key, Value: value}), "Environment variable %s should be set to %s", key, value) - } - }) - }) -}) diff --git a/test/openshift/e2e/ginkgo/sequential/1-051_validate_argocd_agent_principal_test.go b/test/openshift/e2e/ginkgo/sequential/1-051_validate_argocd_agent_principal_test.go index d7eacd6794d..7170d1e892d 100644 --- a/test/openshift/e2e/ginkgo/sequential/1-051_validate_argocd_agent_principal_test.go +++ b/test/openshift/e2e/ginkgo/sequential/1-051_validate_argocd_agent_principal_test.go @@ -19,6 +19,7 @@ package sequential import ( "context" "fmt" + "slices" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -34,6 +35,7 @@ import ( argov1beta1api "github.com/redhat-developer/gitops-operator/argocd-operator/api/v1beta1" "github.com/redhat-developer/gitops-operator/argocd-operator/common" "github.com/redhat-developer/gitops-operator/argocd-operator/controllers/argocdagent" + "github.com/redhat-developer/gitops-operator/argocd-operator/controllers/argoutil" "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture" agentFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/agent" argocdFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/argocd" @@ -102,6 +104,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { "*", }, }, + LabelSelector: "argocd-agent=true", TLS: &argov1beta1api.PrincipalTLSSpec{ InsecureGenerate: new(true), }, @@ -219,6 +222,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { argocdagent.EnvArgoCDPrincipalResourceProxySecretName: agentResourceProxyTLSSecretName, argocdagent.EnvArgoCDPrincipalResourceProxyCaSecretName: agentRootCASecretName, argocdagent.EnvArgoCDPrincipalJwtSecretName: agentJWTSecretName, + argocdagent.EnvArgoCDPrincipalLabelSelector: "argocd-agent=true", argocdagent.EnvArgoCDPrincipalEnableSelfClusterRegistration: "false", argocdagent.EnvArgoCDPrincipalSelfRegistrationClientCertSecret: "", argocdagent.EnvArgoCDPrincipalResourceProxyAddress: fmt.Sprintf("%s-agent-principal-resource-proxy:%d", argoCDName, argocdagent.PrincipalResourceProxyServicePort), @@ -341,7 +345,6 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { }) It("should create argocd agent principal resources, and pod should start successfully with default image", func() { - // Add a custom environment variable to the principal server argoCD.Spec.ArgoCDAgent.Principal.Env = []corev1.EnvVar{{Name: "TEST_ENV", Value: "test_value"}} @@ -357,7 +360,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { container := deploymentFixture.GetTemplateSpecContainerByName(argoCDAgentPrincipalName, *principalDeployment) Expect(container).ToNot(BeNil()) - Expect(container.Image).To(ContainSubstring("argocd-agent")) + Expect(container.Image).To(Equal(common.ArgoCDAgentPrincipalDefaultImageName)) By("Create required secrets and certificates for principal pod to start properly") @@ -403,9 +406,9 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { }) It("Should reflect configuration changes from ArgoCD CR to the principal deployment", func() { - By("Create ArgoCD instance") + argoCD.Spec.ArgoCDAgent.Principal.Image = common.ArgoCDAgentPrincipalDefaultImageName Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) By("Verify expected resources are created for principal pod") @@ -416,7 +419,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { container := deploymentFixture.GetTemplateSpecContainerByName(argoCDAgentPrincipalName, *principalDeployment) Expect(container).ToNot(BeNil()) - Expect(container.Image).To(ContainSubstring("argocd-agent")) + Expect(container.Image).To(Equal(common.ArgoCDAgentPrincipalDefaultImageName)) By("Verify environment variables are set correctly") @@ -434,7 +437,8 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { ac.Spec.ArgoCDAgent.Principal.LogFormat = "json" ac.Spec.ArgoCDAgent.Principal.Server.KeepAliveMinInterval = "60s" ac.Spec.ArgoCDAgent.Principal.Server.EnableWebSocket = new(true) - ac.Spec.ArgoCDAgent.Principal.Image = "quay.io/argoprojlabs/argocd-agent:v0.8.1" + ac.Spec.ArgoCDAgent.Principal.Image = common.ArgoCDAgentPrincipalDefaultImageName + ac.Spec.ArgoCDAgent.Principal.LabelSelector = "env=staging" ac.Spec.ArgoCDAgent.Principal.Namespace.AllowedNamespaces = []string{"agent-managed", "agent-autonomous"} ac.Spec.ArgoCDAgent.Principal.Namespace.EnableNamespaceCreate = new(true) @@ -480,7 +484,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { if container == nil { return false } - return container.Image == "quay.io/argoprojlabs/argocd-agent:v0.8.1" + return container.Image == common.ArgoCDAgentPrincipalDefaultImageName }, "120s", "5s").Should(BeTrue(), "Principal deployment should have the updated image") By("verify that deployment is in Ready state") @@ -504,12 +508,53 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { expectedEnvVariables[argocdagent.EnvArgoCDPrincipalTLSSecretName] = "argocd-agent-principal-tls-v2" expectedEnvVariables[argocdagent.EnvArgoCDPrincipalTLSServerRootCASecretName] = "argocd-agent-ca-v2" expectedEnvVariables[argocdagent.EnvArgoCDPrincipalJwtSecretName] = "argocd-agent-jwt-v2" + expectedEnvVariables[argocdagent.EnvArgoCDPrincipalLabelSelector] = "env=staging" for key, value := range expectedEnvVariables { Expect(container.Env).To(ContainElement(corev1.EnvVar{Name: key, Value: value}), "Environment variable %s should be set to %s", key, value) } }) + It("Should restore Redis Auth volume and mount if removed from principal deployment", func() { + By("Creating ArgoCD instance normally") + Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) + Eventually(argoCD, "5m", "5s").Should(argocdFixture.BeAvailable()) + Eventually(principalDeployment).Should(k8sFixture.ExistByName()) + + By("Removing Redis Auth volume and mount from the deployment") + err := k8sClient.Get(ctx, client.ObjectKey{Name: argoCDAgentPrincipalName, Namespace: ns.Name}, principalDeployment) + Expect(err).ToNot(HaveOccurred()) + + deploymentFixture.Update(principalDeployment, func(p *appsv1.Deployment) { + volLen := len(p.Spec.Template.Spec.Volumes) + mountLen := len(p.Spec.Template.Spec.Containers[0].VolumeMounts) + p.Spec.Template.Spec.Volumes = slices.DeleteFunc(p.Spec.Template.Spec.Volumes, func(v corev1.Volume) bool { + return v.Name == argoutil.RedisAuthVolumeName + }) + p.Spec.Template.Spec.Containers[0].VolumeMounts = slices.DeleteFunc(p.Spec.Template.Spec.Containers[0].VolumeMounts, func(vm corev1.VolumeMount) bool { + return vm.Name == argoutil.RedisAuthVolumeName + }) + // Double check we have actually removed the volume and mount + Expect(p.Spec.Template.Spec.Volumes).To(HaveLen(volLen - 1)) + Expect(p.Spec.Template.Spec.Containers[0].VolumeMounts).To(HaveLen(mountLen - 1)) + }) + + By("Redis Auth volume and mount are re-added by the operator") + Eventually(func() bool { + err := k8sClient.Get(ctx, client.ObjectKey{Name: argoCDAgentPrincipalName, Namespace: ns.Name}, principalDeployment) + if err != nil { + return false + } + volFound := slices.ContainsFunc(principalDeployment.Spec.Template.Spec.Volumes, func(v corev1.Volume) bool { + return v.Name == argoutil.RedisAuthVolumeName + }) + mountFound := slices.ContainsFunc(principalDeployment.Spec.Template.Spec.Containers[0].VolumeMounts, func(vm corev1.VolumeMount) bool { + return vm.Name == argoutil.RedisAuthVolumeName + }) + return volFound && mountFound + }, "10s", "1s").Should(BeTrue(), "Redis Auth volume and mount should be restored to the principal deployment") + }) + It("should handle route disabled configuration correctly", func() { By("Create ArgoCD instance with route disabled") @@ -664,9 +709,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { }, } Eventually(principalService).Should(k8sFixture.ExistByName()) - Expect(principalService.Spec.Type).To(Equal(corev1.ServiceTypeLoadBalancer)) - - By("Verify principal service has expected annotations") + Eventually(principalService.Spec.Type).Should(Equal(corev1.ServiceTypeLoadBalancer)) Eventually(func() map[string]string { err := k8sClient.Get(ctx, client.ObjectKey{Name: argoCDAgentPrincipalName, Namespace: ns.Name}, principalService) if err != nil { @@ -720,10 +763,14 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { } Eventually(principalService).Should(k8sFixture.ExistByName()) - Eventually(func() (map[string]string, error) { + Eventually(func() map[string]string { err := k8sClient.Get(ctx, client.ObjectKey{Name: argoCDAgentPrincipalName, Namespace: ns.Name}, principalService) - return principalService.Annotations, err + if err != nil { + return nil + } + return principalService.Annotations }, "30s", "2s").ShouldNot(HaveKey("test.argocd.io/annotation")) + }) It("should handle service type updates correctly", func() { From 8d6ad467f0ddcd1e1789e8bf4ee1d832767830f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20Gond=C5=BEa?= Date: Fri, 30 Oct 2026 12:12:25 +0100 Subject: [PATCH 4/5] tests(E2E): Port 1-052_validate_argocd_agent_agent_test.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Oliver Gondža --- .../1-052_validate_argocd_agent_agent_test.go | 668 ------------------ .../1-052_validate_argocd_agent_agent_test.go | 24 +- 2 files changed, 15 insertions(+), 677 deletions(-) delete mode 100644 argocd-operator/tests/ginkgo/sequential/1-052_validate_argocd_agent_agent_test.go diff --git a/argocd-operator/tests/ginkgo/sequential/1-052_validate_argocd_agent_agent_test.go b/argocd-operator/tests/ginkgo/sequential/1-052_validate_argocd_agent_agent_test.go deleted file mode 100644 index 667c71a8ac9..00000000000 --- a/argocd-operator/tests/ginkgo/sequential/1-052_validate_argocd_agent_agent_test.go +++ /dev/null @@ -1,668 +0,0 @@ -/* -Copyright 2025. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package sequential - -import ( - "context" - "fmt" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - rbacv1 "k8s.io/api/rbac/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "sigs.k8s.io/controller-runtime/pkg/client" - - argov1beta1api "github.com/redhat-developer/gitops-operator/argocd-operator/api/v1beta1" - "github.com/redhat-developer/gitops-operator/argocd-operator/common" - "github.com/redhat-developer/gitops-operator/argocd-operator/controllers/argocdagent/agent" - "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture" - argocdFixture "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture/argocd" - deploymentFixture "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture/deployment" - k8sFixture "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture/k8s" - fixtureUtils "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture/utils" -) - -var _ = Describe("GitOps Operator Sequential E2E Tests", func() { - const ( - argoCDName = "example" - argoCDAgentAgentName = "example-agent-agent" // argoCDName + "-agent-agent" - - // Secret names - agentRootCASecretName = "argocd-agent-ca" - agentClientTLSSecretName = "argocd-agent-client-tls" - ) - - Context("1-052_validate_argocd_agent_agent", func() { - var ( - k8sClient client.Client - ctx context.Context - argoCD *argov1beta1api.ArgoCD - ns *corev1.Namespace - cleanupFunc func() - serviceAccount *corev1.ServiceAccount - role *rbacv1.Role - roleBinding *rbacv1.RoleBinding - clusterRole *rbacv1.ClusterRole - clusterRoleBinding *rbacv1.ClusterRoleBinding - serviceNames []string - deploymentNames []string - agentDeployment *appsv1.Deployment - expectedEnvVariables map[string]string - secretNames []string - ) - - BeforeEach(func() { - fixture.EnsureSequentialCleanSlate() - k8sClient, _ = fixtureUtils.GetE2ETestKubeClient() - ctx = context.Background() - ns, cleanupFunc = fixture.CreateNamespaceWithCleanupFunc("argocd-agent-agent-1-052") - - // Define ArgoCD CR with agent enabled - argoCD = &argov1beta1api.ArgoCD{ - ObjectMeta: metav1.ObjectMeta{ - Name: argoCDName, - Namespace: ns.Name, - }, - Spec: argov1beta1api.ArgoCDSpec{ - Controller: argov1beta1api.ArgoCDApplicationControllerSpec{ - Enabled: new(false), - }, - Server: argov1beta1api.ArgoCDServerSpec{ - Enabled: new(false), - }, - ArgoCDAgent: &argov1beta1api.ArgoCDAgentSpec{ - Agent: &argov1beta1api.AgentSpec{ - Enabled: new(true), - Creds: "mtls:any", - LogLevel: "info", - LogFormat: "text", - LabelSelector: "argocd-agent=true", - Client: &argov1beta1api.AgentClientSpec{ - PrincipalServerAddress: "argocd-agent-principal.example.com", - PrincipalServerPort: "443", - Mode: string(argov1beta1api.AgentModeManaged), - EnableWebSocket: new(false), - EnableCompression: new(false), - KeepAliveInterval: "30s", - }, - TLS: &argov1beta1api.AgentTLSSpec{ - SecretName: agentClientTLSSecretName, - RootCASecretName: agentRootCASecretName, - Insecure: new(false), - }, - Redis: &argov1beta1api.AgentRedisSpec{ - ServerAddress: fmt.Sprintf("%s-%s:%d", argoCDName, "redis", common.ArgoCDDefaultRedisPort), - }, - }, - }, - }, - } - - // Define required resources for agent pod - serviceAccount = &corev1.ServiceAccount{ - ObjectMeta: metav1.ObjectMeta{ - Name: argoCDAgentAgentName, - Namespace: ns.Name, - }, - } - - role = &rbacv1.Role{ - ObjectMeta: metav1.ObjectMeta{ - Name: argoCDAgentAgentName, - Namespace: ns.Name, - }, - } - - roleBinding = &rbacv1.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: argoCDAgentAgentName, - Namespace: ns.Name, - }, - } - - clusterRole = &rbacv1.ClusterRole{ - ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%s-%s-agent-agent", argoCDName, ns.Name), - }, - } - - clusterRoleBinding = &rbacv1.ClusterRoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%s-%s-agent-agent", argoCDName, ns.Name), - }, - } - - // List required secrets for agent pod - secretNames = []string{ - agentClientTLSSecretName, - agentRootCASecretName, - "example-redis-initial-password", - } - - serviceNames = []string{ - fmt.Sprintf("%s-agent-agent-metrics", argoCDName), - fmt.Sprintf("%s-agent-agent-healthz", argoCDName), - fmt.Sprintf("%s-redis", argoCDName), - } - deploymentNames = []string{fmt.Sprintf("%s-redis", argoCDName)} - - agentDeployment = &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: argoCDAgentAgentName, - Namespace: ns.Name, - }, - } - - // List environment variables with expected values for the agent deployment - expectedEnvVariables = map[string]string{ - agent.EnvArgoCDAgentLogLevel: "info", - agent.EnvArgoCDAgentNamespace: ns.Name, - agent.EnvArgoCDAgentServerAddress: "argocd-agent-principal.example.com", - agent.EnvArgoCDAgentServerPort: "443", - agent.EnvArgoCDAgentLogFormat: "text", - agent.EnvArgoCDAgentTLSSecretName: agentClientTLSSecretName, - agent.EnvArgoCDAgentTLSInsecure: "false", - agent.EnvArgoCDAgentTLSRootCASecretName: agentRootCASecretName, - agent.EnvArgoCDAgentMode: string(argov1beta1api.AgentModeManaged), - agent.EnvArgoCDAgentCreds: "mtls:any", - agent.EnvArgoCDAgentEnableWebSocket: "false", - agent.EnvArgoCDAgentEnableCompression: "false", - agent.EnvArgoCDAgentKeepAliveInterval: "30s", - agent.EnvArgoCDAgentRedisAddress: fmt.Sprintf("%s-%s:%d", argoCDName, "redis", common.ArgoCDDefaultRedisPort), - agent.EnvArgoCDAgentEnableResourceProxy: "true", - agent.EnvArgoCDAgentLabelSelector: "argocd-agent=true", - } - }) - - AfterEach(func() { - By("Cleanup cluster-scoped resources") - _ = k8sClient.Delete(ctx, clusterRole) - _ = k8sClient.Delete(ctx, clusterRoleBinding) - - By("Cleanup namespace") - if cleanupFunc != nil { - cleanupFunc() - } - }) - - // verifyExpectedResourcesExist will verify that the resources that are created for agent and ArgoCD are created. - verifyExpectedResourcesExist := func(ns *corev1.Namespace) { - By("verifying expected resources exist") - Eventually(&corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: secretNames[2], Namespace: ns.Name, - }, - }, "60s", "2s").Should(k8sFixture.ExistByName()) - Eventually(serviceAccount).Should(k8sFixture.ExistByName()) - Eventually(role).Should(k8sFixture.ExistByName()) - Eventually(roleBinding).Should(k8sFixture.ExistByName()) - Eventually(clusterRole).Should(k8sFixture.ExistByName()) - defer func() { - _ = k8sClient.Delete(ctx, clusterRole) - }() - - Eventually(clusterRoleBinding).Should(k8sFixture.ExistByName()) - defer func() { - _ = k8sClient.Delete(ctx, clusterRoleBinding) - }() - - for _, serviceName := range serviceNames { - - By("verifying Service '" + serviceName + "' exists and is a LoadBalancer or ClusterIP depending on which service") - - service := &corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: serviceName, - Namespace: ns.Name, - }, - } - Eventually(service).Should(k8sFixture.ExistByName()) - Expect(string(service.Spec.Type)).To(Equal("ClusterIP")) - } - - for _, deploymentName := range deploymentNames { - - By("verifying Deployment '" + deploymentName + "' exists and is ready") - - depl := &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: deploymentName, - Namespace: ns.Name, - }, - } - Eventually(depl).Should(k8sFixture.ExistByName()) - } - - By("verifying primary agent Deployment has expected values") - - Eventually(agentDeployment).Should(k8sFixture.ExistByName()) - Eventually(agentDeployment).Should(k8sFixture.HaveLabelWithValue("app.kubernetes.io/component", string(argov1beta1api.AgentComponentTypeAgent))) - Eventually(agentDeployment).Should(k8sFixture.HaveLabelWithValue("app.kubernetes.io/managed-by", argoCDName)) - Eventually(agentDeployment).Should(k8sFixture.HaveLabelWithValue("app.kubernetes.io/name", argoCDAgentAgentName)) - Eventually(agentDeployment).Should(k8sFixture.HaveLabelWithValue("app.kubernetes.io/part-of", "argocd-agent")) - } - - // verifyResourcesDeleted will verify that the various resources that are created for agent are deleted. - verifyResourcesDeleted := func() { - By("verifying resources are deleted for agent pod") - - Eventually(serviceAccount).Should(k8sFixture.NotExistByName()) - Eventually(role).Should(k8sFixture.NotExistByName()) - Eventually(roleBinding).Should(k8sFixture.NotExistByName()) - Eventually(clusterRole).Should(k8sFixture.NotExistByName()) - Eventually(clusterRoleBinding).Should(k8sFixture.NotExistByName()) - Eventually(agentDeployment).Should(k8sFixture.NotExistByName()) - - for _, serviceName := range []string{fmt.Sprintf("%s-agent-agent-metrics", argoCDName), fmt.Sprintf("%s-agent-agent-healthz", argoCDName)} { - service := &corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: serviceName, - Namespace: ns.Name, - }, - } - Eventually(service).Should(k8sFixture.NotExistByName()) - } - } - - It("should create argocd agent agent resources, but pod should not be expected to run successfully without principal", func() { - // Change log level to trace and custom image name - argoCD.Spec.ArgoCDAgent.Agent.LogLevel = "trace" - argoCD.Spec.ArgoCDAgent.Agent.Image = "quay.io/user/argocd-agent:v1" - - By("Create ArgoCD instance") - - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - By("Verify expected resources are created for agent pod") - - verifyExpectedResourcesExist(ns) - - By("Verify agent has the custom image we specified in ArgoCD CR") - - container := deploymentFixture.GetTemplateSpecContainerByName(argoCDAgentAgentName, *agentDeployment) - Expect(container).ToNot(BeNil()) - Expect(container.Image).To(Equal("quay.io/user/argocd-agent:v1")) - - By("Verify environment variables are set correctly") - - // update expected value in default environment variables according to ArgoCD CR in the test - expectedEnvVariables[agent.EnvArgoCDAgentLogLevel] = "trace" - - for key, value := range expectedEnvVariables { - Expect(container.Env).To(ContainElement(corev1.EnvVar{Name: key, Value: value}), "Environment variable %s should be set to %s", key, value) - } - - By("Disable agent") - - Expect(k8sClient.Get(ctx, client.ObjectKey{Name: argoCDName, Namespace: ns.Name}, argoCD)).To(Succeed()) - - argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) { - ac.Spec.ArgoCDAgent.Agent.Enabled = new(false) - }) - - By("Verify agent resources are deleted") - - verifyResourcesDeleted() - }) - - It("should create argocd agent agent resources with default image, but pod will not start without principal", func() { - // Add a custom environment variable to the agent client - argoCD.Spec.ArgoCDAgent.Agent.Env = []corev1.EnvVar{{Name: "TEST_ENV", Value: "test_value"}} - - By("Create ArgoCD instance") - - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - By("Verify expected resources are created for agent pod") - - verifyExpectedResourcesExist(ns) - - By("Verify agent uses the default agent image") - - container := deploymentFixture.GetTemplateSpecContainerByName(argoCDAgentAgentName, *agentDeployment) - Expect(container).ToNot(BeNil()) - Expect(container.Image).To(Equal(common.ArgoCDAgentAgentDefaultImageName)) - - By("Verify environment variables are set correctly") - - for key, value := range expectedEnvVariables { - Expect(container.Env).To(ContainElement(corev1.EnvVar{Name: key, Value: value}), "Environment variable %s should be set to %s", key, value) - } - - Expect(container.Env).NotTo(ContainElement( - HaveField("Name", "REDIS_PASSWORD"), - ), "REDIS_PASSWORD should not be set") - - By("Verify custom environment variable is present") - - Expect(container.Env).To(ContainElement(corev1.EnvVar{Name: "TEST_ENV", Value: "test_value"}), "Custom environment variable TEST_ENV should be set") - - By("Disable agent") - - Expect(k8sClient.Get(ctx, client.ObjectKey{Name: argoCDName, Namespace: ns.Name}, argoCD)).To(Succeed()) - - argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) { - ac.Spec.ArgoCDAgent.Agent.Enabled = nil - }) - - By("Verify agent resources are deleted") - - verifyResourcesDeleted() - }) - - It("Should reflect configuration changes from ArgoCD CR to the agent deployment", func() { - By("Create ArgoCD instance") - - argoCD.Spec.ArgoCDAgent.Agent.Image = common.ArgoCDAgentAgentDefaultImageName - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - By("Verify expected resources are created for agent pod") - - verifyExpectedResourcesExist(ns) - - By("Verify agent has the custom image we specified in ArgoCD CR") - - container := deploymentFixture.GetTemplateSpecContainerByName(argoCDAgentAgentName, *agentDeployment) - Expect(container).ToNot(BeNil()) - Expect(container.Image).To(Equal(common.ArgoCDAgentAgentDefaultImageName)) - - By("Verify environment variables are set correctly") - - // update expected value in default environment variables according to ArgoCD CR in the test - for key, value := range expectedEnvVariables { - Expect(container.Env).To(ContainElement(corev1.EnvVar{Name: key, Value: value}), "Environment variable %s should be set to %s", key, value) - } - - By("Update ArgoCD CR with new configuration") - - Expect(k8sClient.Get(ctx, client.ObjectKey{Name: argoCDName, Namespace: ns.Name}, argoCD)).To(Succeed()) - - argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) { - ac.Spec.ArgoCDAgent.Agent.LogLevel = "trace" - ac.Spec.ArgoCDAgent.Agent.LogFormat = "json" - ac.Spec.ArgoCDAgent.Agent.Image = "quay.io/argoprojlabs/argocd-agent:v0.5.1" - ac.Spec.ArgoCDAgent.Agent.LabelSelector = "env=staging" - - ac.Spec.ArgoCDAgent.Agent.Client.KeepAliveInterval = "60s" - ac.Spec.ArgoCDAgent.Agent.Client.EnableWebSocket = new(true) - ac.Spec.ArgoCDAgent.Agent.Client.EnableCompression = new(true) - ac.Spec.ArgoCDAgent.Agent.Client.Mode = string(argov1beta1api.AgentModeAutonomous) - ac.Spec.ArgoCDAgent.Agent.Client.PrincipalServerAddress = "argocd-agent-principal-updated.example.com" - ac.Spec.ArgoCDAgent.Agent.Client.PrincipalServerPort = "8443" - - ac.Spec.ArgoCDAgent.Agent.TLS.Insecure = new(true) - ac.Spec.ArgoCDAgent.Agent.TLS.SecretName = "argocd-agent-client-tls-v2" - ac.Spec.ArgoCDAgent.Agent.TLS.RootCASecretName = "argocd-agent-ca-v2" - }) - - By("Verify agent has the updated image we specified in ArgoCD CR") - - Eventually(agentDeployment).Should(k8sFixture.ExistByName()) - Eventually( - func() bool { - // Fetch the latest deployment from the cluster - err := k8sClient.Get(ctx, client.ObjectKey{Name: argoCDAgentAgentName, Namespace: ns.Name}, agentDeployment) - if err != nil { - GinkgoWriter.Println("Error getting deployment for image check: ", err) - return false - } - container = deploymentFixture.GetTemplateSpecContainerByName(argoCDAgentAgentName, *agentDeployment) - if container == nil { - return false - } - return container.Image == "quay.io/argoprojlabs/argocd-agent:v0.5.1" - }, "120s", "5s").Should(BeTrue(), "Agent deployment should have the updated image") - - By("Verify environment variables are updated correctly") - - expectedEnvVariables[agent.EnvArgoCDAgentLogLevel] = "trace" - expectedEnvVariables[agent.EnvArgoCDAgentLogFormat] = "json" - expectedEnvVariables[agent.EnvArgoCDAgentKeepAliveInterval] = "60s" - expectedEnvVariables[agent.EnvArgoCDAgentEnableWebSocket] = "true" - expectedEnvVariables[agent.EnvArgoCDAgentEnableCompression] = "true" - expectedEnvVariables[agent.EnvArgoCDAgentMode] = string(argov1beta1api.AgentModeAutonomous) - expectedEnvVariables[agent.EnvArgoCDAgentServerAddress] = "argocd-agent-principal-updated.example.com" - expectedEnvVariables[agent.EnvArgoCDAgentServerPort] = "8443" - expectedEnvVariables[agent.EnvArgoCDAgentTLSInsecure] = "true" - expectedEnvVariables[agent.EnvArgoCDAgentTLSSecretName] = "argocd-agent-client-tls-v2" - expectedEnvVariables[agent.EnvArgoCDAgentTLSRootCASecretName] = "argocd-agent-ca-v2" - expectedEnvVariables[agent.EnvArgoCDAgentLabelSelector] = "env=staging" - - for key, value := range expectedEnvVariables { - Expect(container.Env).To(ContainElement(corev1.EnvVar{Name: key, Value: value}), "Environment variable %s should be set to %s", key, value) - } - }) - - It("should deploy agent via namespace-scoped ArgoCD instance and verify cluster role and cluster role binding are not created", func() { - By("Create namespace-scoped ArgoCD instance") - - // Create namespace for hosting namespace-scoped ArgoCD instance with agent - nsScoped, cleanupFuncScoped := fixture.CreateNamespaceWithCleanupFunc("argocd-agent-agent-ns-scoped-1-052") - defer cleanupFuncScoped() - - // Update namespace in ArgoCD CR - argoCD.Namespace = nsScoped.Name - - // Update namespace in resource references - serviceAccount.Namespace = nsScoped.Name - role.Namespace = nsScoped.Name - roleBinding.Namespace = nsScoped.Name - agentDeployment.Namespace = nsScoped.Name - clusterRole.Name = fmt.Sprintf("%s-%s-agent-agent", argoCDName, nsScoped.Name) - clusterRoleBinding.Name = fmt.Sprintf("%s-%s-agent-agent", argoCDName, nsScoped.Name) - - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - By("Verify namespace-scoped resources are created for agent") - - Eventually(serviceAccount, "30s", "2s").Should(k8sFixture.ExistByName()) - Eventually(role, "30s", "2s").Should(k8sFixture.ExistByName()) - Eventually(roleBinding, "30s", "2s").Should(k8sFixture.ExistByName()) - Eventually(agentDeployment, "30s", "2s").Should(k8sFixture.ExistByName()) - for _, serviceName := range serviceNames { - service := &corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: serviceName, - Namespace: nsScoped.Name, - }, - } - Eventually(service, "30s", "2s").Should(k8sFixture.ExistByName(), - "Service '%s' should exist in namespace '%s'", serviceName, nsScoped.Name) - } - - By("Verify ClusterRole and ClusterRoleBinding are not created") - - Consistently(clusterRole, "10s", "1s").Should(k8sFixture.NotExistByName(), - "ClusterRole '%s' should not exist for namespace-scoped ArgoCD instance", clusterRole.Name) - - Consistently(clusterRoleBinding, "10s", "1s").Should(k8sFixture.NotExistByName(), - "ClusterRoleBinding '%s' should not exist for namespace-scoped ArgoCD instance", clusterRoleBinding.Name) - - By("Delete ArgoCD instance") - Expect(k8sClient.Delete(ctx, argoCD)).To(Succeed()) - Eventually(func() bool { - err := k8sClient.Get(ctx, client.ObjectKey{Name: argoCD.Name, Namespace: argoCD.Namespace}, argoCD) - return err != nil - }, "60s", "2s").Should(BeTrue(), "ArgoCD should be deleted") - }) - - It("should delete existing cluster role and cluster role binding if ArgoCD instance is namespace-scoped", func() { - By("Create namespace-scoped ArgoCD instance namespace") - - // Create namespace for hosting namespace-scoped ArgoCD instance with agent - nsScoped, cleanupFuncScoped := fixture.CreateNamespaceWithCleanupFunc("argocd-agent-agent-ns-scoped-1-052") - defer cleanupFuncScoped() - - // Update namespace in ArgoCD CR - argoCD.Namespace = nsScoped.Name - - // Update namespace in resource references - serviceAccount.Namespace = nsScoped.Name - role.Namespace = nsScoped.Name - roleBinding.Namespace = nsScoped.Name - agentDeployment.Namespace = nsScoped.Name - clusterRole.Name = fmt.Sprintf("%s-%s-agent-agent", argoCDName, nsScoped.Name) - clusterRoleBinding.Name = fmt.Sprintf("%s-%s-agent-agent", argoCDName, nsScoped.Name) - - By("Pre-create ClusterRole and ClusterRoleBinding before ArgoCD instance") - - preExistingClusterRole := &rbacv1.ClusterRole{ - ObjectMeta: metav1.ObjectMeta{ - Name: clusterRole.Name, - Labels: map[string]string{ - "app.kubernetes.io/name": "test", - }, - }, - } - Expect(k8sClient.Create(ctx, preExistingClusterRole)).To(Succeed()) - - preExistingClusterRoleBinding := &rbacv1.ClusterRoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: clusterRoleBinding.Name, - Labels: map[string]string{ - "app.kubernetes.io/name": "test", - }, - }, - Subjects: []rbacv1.Subject{ - { - Kind: rbacv1.ServiceAccountKind, - Name: "default", - Namespace: nsScoped.Name, - }, - }, - RoleRef: rbacv1.RoleRef{ - APIGroup: rbacv1.GroupName, - Kind: "ClusterRole", - Name: clusterRole.Name, - }, - } - Expect(k8sClient.Create(ctx, preExistingClusterRoleBinding)).To(Succeed()) - - By("Verify pre-existing ClusterRole and ClusterRoleBinding exist") - - Eventually(clusterRole, "10s", "1s").Should(k8sFixture.ExistByName(), - "Pre-existing ClusterRole '%s' should exist before ArgoCD instance creation", clusterRole.Name) - Eventually(clusterRoleBinding, "10s", "1s").Should(k8sFixture.ExistByName(), - "Pre-existing ClusterRoleBinding '%s' should exist before ArgoCD instance creation", clusterRoleBinding.Name) - - By("Create namespace-scoped ArgoCD instance with agent") - - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - By("Verify pre-existing ClusterRole and ClusterRoleBinding are deleted") - - Eventually(clusterRole, "60s", "2s").Should(k8sFixture.NotExistByName(), - "ClusterRole '%s' should be deleted for namespace-scoped ArgoCD instance", clusterRole.Name) - - Eventually(clusterRoleBinding, "60s", "2s").Should(k8sFixture.NotExistByName(), - "ClusterRoleBinding '%s' should be deleted for namespace-scoped ArgoCD instance", clusterRoleBinding.Name) - - By("Delete ArgoCD instance") - Expect(k8sClient.Delete(ctx, argoCD)).To(Succeed()) - Eventually(func() bool { - err := k8sClient.Get(ctx, client.ObjectKey{Name: argoCD.Name, Namespace: argoCD.Namespace}, argoCD) - return err != nil - }, "60s", "2s").Should(BeTrue(), "ArgoCD should be deleted") - }) - - It("should create and delete agent ServiceMonitor based on prometheus enabled flag", func() { - By("Create ArgoCD instance with agent enabled and prometheus enabled") - - argoCD.Spec.Prometheus.Enabled = true - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - By("Verify expected resources are created for agent pod") - - verifyExpectedResourcesExist(ns) - - By("Verify agent ServiceMonitor is created") - - agentServiceMonitor := &monitoringv1.ServiceMonitor{ - ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%s-agent-agent-metrics", argoCDName), - Namespace: ns.Name, - }, - } - Eventually(agentServiceMonitor, "2m", "2s").Should(k8sFixture.ExistByName()) - - By("Disable prometheus and verify ServiceMonitor is deleted") - - Expect(k8sClient.Get(ctx, client.ObjectKey{Name: argoCDName, Namespace: ns.Name}, argoCD)).To(Succeed()) - argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) { - ac.Spec.Prometheus.Enabled = false - }) - - Eventually(agentServiceMonitor, "2m", "2s").Should(k8sFixture.NotExistByName()) - - By("Re-enable prometheus and verify ServiceMonitor is recreated") - - Expect(k8sClient.Get(ctx, client.ObjectKey{Name: argoCDName, Namespace: ns.Name}, argoCD)).To(Succeed()) - argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) { - ac.Spec.Prometheus.Enabled = true - }) - - Eventually(agentServiceMonitor, "2m", "2s").Should(k8sFixture.ExistByName()) - - By("Disable agent and verify ServiceMonitor is deleted") - - Expect(k8sClient.Get(ctx, client.ObjectKey{Name: argoCDName, Namespace: ns.Name}, argoCD)).To(Succeed()) - argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) { - ac.Spec.ArgoCDAgent.Agent.Enabled = new(false) - }) - - Eventually(agentServiceMonitor, "2m", "2s").Should(k8sFixture.NotExistByName()) - }) - - It("shouldn't create ClusterRole and ClusterRoleBinding for agent if spec.DefaultClusterScopedRoleDisabled is set", func() { - By("Create ArgoCD instance with principal enabled and DefaultClusterScopedRoleDisabled is true") - argoCD.Spec.DefaultClusterScopedRoleDisabled = true - Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) - - By("Verify Argo CD becomes available") - Eventually(argoCD, "5m", "5s").Should(argocdFixture.BeAvailable()) - - By("Verify ClusterRole and ClusterRoleBinding do not exist") - Eventually(clusterRole, "60s", "2s").Should(k8sFixture.NotExistByName()) - Eventually(clusterRoleBinding, "60s", "2s").Should(k8sFixture.NotExistByName()) - Consistently(clusterRole, "10s", "2s").Should(k8sFixture.NotExistByName()) - Consistently(clusterRoleBinding, "10s", "2s").Should(k8sFixture.NotExistByName()) - - By("Namespaced RBAC objects should still exist") - Eventually(role, "60s", "2s").Should(k8sFixture.ExistByName()) - Eventually(roleBinding, "60s", "2s").Should(k8sFixture.ExistByName()) - - By("Unset DefaultClusterScopedRoleDisabled and make sure cluster scoped RBAC objects are created") - argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) { - ac.Spec.DefaultClusterScopedRoleDisabled = false - }) - Eventually(clusterRole, "60s", "2s").Should(k8sFixture.ExistByName()) - Eventually(clusterRoleBinding, "60s", "2s").Should(k8sFixture.ExistByName()) - - By("Setting DefaultClusterScopedRoleDisabled again deletes clusterRole and clusterRoleBinding") - argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) { - ac.Spec.DefaultClusterScopedRoleDisabled = true - }) - Eventually(clusterRole, "60s", "2s").Should(k8sFixture.NotExistByName()) - Eventually(clusterRoleBinding, "60s", "2s").Should(k8sFixture.NotExistByName()) - Consistently(clusterRole, "10s", "2s").Should(k8sFixture.NotExistByName()) - Consistently(clusterRoleBinding, "10s", "2s").Should(k8sFixture.NotExistByName()) - }) - }) -}) diff --git a/test/openshift/e2e/ginkgo/sequential/1-052_validate_argocd_agent_agent_test.go b/test/openshift/e2e/ginkgo/sequential/1-052_validate_argocd_agent_agent_test.go index 5dc59fd121c..b8b13e20c62 100644 --- a/test/openshift/e2e/ginkgo/sequential/1-052_validate_argocd_agent_agent_test.go +++ b/test/openshift/e2e/ginkgo/sequential/1-052_validate_argocd_agent_agent_test.go @@ -87,10 +87,11 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { }, ArgoCDAgent: &argov1beta1api.ArgoCDAgentSpec{ Agent: &argov1beta1api.AgentSpec{ - Enabled: new(true), - Creds: "mtls:any", - LogLevel: "info", - LogFormat: "text", + Enabled: new(true), + Creds: "mtls:any", + LogLevel: "info", + LogFormat: "text", + LabelSelector: "argocd-agent=true", Client: &argov1beta1api.AgentClientSpec{ PrincipalServerAddress: "argocd-agent-principal.example.com", PrincipalServerPort: "443", @@ -184,6 +185,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { agent.EnvArgoCDAgentKeepAliveInterval: "30s", agent.EnvArgoCDAgentRedisAddress: fmt.Sprintf("%s-%s:%d", argoCDName, "redis", common.ArgoCDDefaultRedisPort), agent.EnvArgoCDAgentEnableResourceProxy: "true", + agent.EnvArgoCDAgentLabelSelector: "argocd-agent=true", } }) @@ -318,7 +320,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { verifyResourcesDeleted() }) - It("should create argocd agent agent resources, but pod will not start without principal", func() { + It("should create argocd agent agent resources with default image, but pod will not start without principal", func() { // Add a custom environment variable to the agent client argoCD.Spec.ArgoCDAgent.Agent.Env = []corev1.EnvVar{{Name: "TEST_ENV", Value: "test_value"}} @@ -334,7 +336,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { container := deploymentFixture.GetTemplateSpecContainerByName(argoCDAgentAgentName, *agentDeployment) Expect(container).ToNot(BeNil()) - Expect(container.Image).To(ContainSubstring("argocd-agent")) + Expect(container.Image).To(Equal(common.ArgoCDAgentAgentDefaultImageName)) By("Verify environment variables are set correctly") @@ -366,6 +368,8 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { It("Should reflect configuration changes from ArgoCD CR to the agent deployment", func() { By("Create ArgoCD instance") + + argoCD.Spec.ArgoCDAgent.Agent.Image = common.ArgoCDAgentAgentDefaultImageName Expect(k8sClient.Create(ctx, argoCD)).To(Succeed()) By("Verify expected resources are created for agent pod") @@ -376,7 +380,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { container := deploymentFixture.GetTemplateSpecContainerByName(argoCDAgentAgentName, *agentDeployment) Expect(container).ToNot(BeNil()) - Expect(container.Image).To(ContainSubstring("argocd-agent")) + Expect(container.Image).To(Equal(common.ArgoCDAgentAgentDefaultImageName)) By("Verify environment variables are set correctly") @@ -392,7 +396,8 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { argocdFixture.Update(argoCD, func(ac *argov1beta1api.ArgoCD) { ac.Spec.ArgoCDAgent.Agent.LogLevel = "trace" ac.Spec.ArgoCDAgent.Agent.LogFormat = "json" - ac.Spec.ArgoCDAgent.Agent.Image = "quay.io/argoprojlabs/argocd-agent:v0.8.1" + ac.Spec.ArgoCDAgent.Agent.Image = "quay.io/argoprojlabs/argocd-agent:v0.5.1" + ac.Spec.ArgoCDAgent.Agent.LabelSelector = "env=staging" ac.Spec.ArgoCDAgent.Agent.Client.KeepAliveInterval = "60s" ac.Spec.ArgoCDAgent.Agent.Client.EnableWebSocket = new(true) @@ -421,7 +426,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { if container == nil { return false } - return container.Image == "quay.io/argoprojlabs/argocd-agent:v0.8.1" + return container.Image == "quay.io/argoprojlabs/argocd-agent:v0.5.1" }, "120s", "5s").Should(BeTrue(), "Agent deployment should have the updated image") By("Verify environment variables are updated correctly") @@ -437,6 +442,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { expectedEnvVariables[agent.EnvArgoCDAgentTLSInsecure] = "true" expectedEnvVariables[agent.EnvArgoCDAgentTLSSecretName] = "argocd-agent-client-tls-v2" expectedEnvVariables[agent.EnvArgoCDAgentTLSRootCASecretName] = "argocd-agent-ca-v2" + expectedEnvVariables[agent.EnvArgoCDAgentLabelSelector] = "env=staging" for key, value := range expectedEnvVariables { Expect(container.Env).To(ContainElement(corev1.EnvVar{Name: key, Value: value}), "Environment variable %s should be set to %s", key, value) From d073367698cf98ecbf58eafa38158c4d64468859 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20Gond=C5=BEa?= Date: Fri, 30 Oct 2026 12:20:57 +0100 Subject: [PATCH 5/5] Delete 1-002_validate_cluster_config_test.go forgotten in https://github.com/redhat-developer/gitops-operator/pull/1398 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Oliver Gondža --- .../1-002_validate_cluster_config_test.go | 139 ------------------ 1 file changed, 139 deletions(-) delete mode 100644 argocd-operator/tests/ginkgo/sequential/1-002_validate_cluster_config_test.go diff --git a/argocd-operator/tests/ginkgo/sequential/1-002_validate_cluster_config_test.go b/argocd-operator/tests/ginkgo/sequential/1-002_validate_cluster_config_test.go deleted file mode 100644 index b0e00c277a6..00000000000 --- a/argocd-operator/tests/ginkgo/sequential/1-002_validate_cluster_config_test.go +++ /dev/null @@ -1,139 +0,0 @@ -/* -Copyright 2025. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package sequential - -import ( - "context" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - "sigs.k8s.io/controller-runtime/pkg/client" - - argov1beta1api "github.com/redhat-developer/gitops-operator/argocd-operator/api/v1beta1" - "github.com/redhat-developer/gitops-operator/argocd-operator/common" - "github.com/redhat-developer/gitops-operator/argocd-operator/controllers/argocd" - "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture" - argocdFixture "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture/argocd" - "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture/configmap" - k8sFixture "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture/k8s" - "github.com/redhat-developer/gitops-operator/argocd-operator/tests/ginkgo/fixture/utils" - - corev1 "k8s.io/api/core/v1" - rbacv1 "k8s.io/api/rbac/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -var _ = Describe("GitOps Operator Sequential E2E Tests", func() { - - Context("1-002_validate_cluster_config", func() { - - var ( - k8sClient client.Client - ctx context.Context - ) - - BeforeEach(func() { - - fixture.EnsureSequentialCleanSlate() - k8sClient, _ = utils.GetE2ETestKubeClient() - ctx = context.Background() - }) - - It("ensures that cluster roles and role bindings are created for cluster-scoped ArgoCD instance, and that values set in initialSSHKnownHosts will be set in ConfigMap", func() { - - By("creating simple cluster-scoped Argo CD instance with initialSSHKnownHosts set") - ns, cleanupFunc := fixture.CreateNamespaceWithCleanupFunc("argocd-e2e-cluster-config") - defer cleanupFunc() - - argoCDInstance := &argov1beta1api.ArgoCD{ - ObjectMeta: metav1.ObjectMeta{Name: "example-argocd", Namespace: ns.Name}, - Spec: argov1beta1api.ArgoCDSpec{ - InitialSSHKnownHosts: argov1beta1api.SSHHostsSpec{ - ExcludeDefaultHosts: true, - Keys: "github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==", - }, - }, - } - Expect(k8sClient.Create(ctx, argoCDInstance)).To(Succeed()) - - Eventually(argoCDInstance, "5m", "5s").Should(argocdFixture.BeAvailable()) - Eventually(argoCDInstance, "5m", "5s").Should(argocdFixture.HaveServerStatus("Running")) - - By("verifying ClusterRole/Bindings exist") - appcontrollerCRB := &rbacv1.ClusterRoleBinding{ - ObjectMeta: metav1.ObjectMeta{Name: argocd.GenerateUniqueResourceName(common.ArgoCDApplicationControllerComponent, argoCDInstance)}, - } - Eventually(appcontrollerCRB).Should(k8sFixture.ExistByName()) - - serverCRB := &rbacv1.ClusterRoleBinding{ - ObjectMeta: metav1.ObjectMeta{Name: argocd.GenerateUniqueResourceName(common.ArgoCDServerComponent, argoCDInstance)}, - } - Eventually(serverCRB).Should(k8sFixture.ExistByName()) - - appControllerCR := &rbacv1.ClusterRole{ - ObjectMeta: metav1.ObjectMeta{ - Name: argocd.GenerateUniqueResourceName(common.ArgoCDApplicationControllerComponent, argoCDInstance), - }, - } - Eventually(appControllerCR).Should(k8sFixture.ExistByName()) - - serverCR := &rbacv1.ClusterRole{ - ObjectMeta: metav1.ObjectMeta{ - Name: argocd.GenerateUniqueResourceName(common.ArgoCDServerComponent, argoCDInstance), - }, - } - Eventually(serverCR).Should(k8sFixture.ExistByName()) - - By("verifying ConfigMap 'argocd-ssh-known-hosts-cm' has the value from InitialSSHKnownHosts") - - knownHostsCM := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: "argocd-ssh-known-hosts-cm", - Namespace: ns.Name, - }, - } - Eventually(knownHostsCM).Should(k8sFixture.ExistByName()) - Eventually(knownHostsCM).Should(configmap.HaveStringDataKeyValue("ssh_known_hosts", "github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==")) - - By("enabling applicationset and setting sourceNamespaces and SCMProviders") - - argocdFixture.Update(argoCDInstance, func(ac *argov1beta1api.ArgoCD) { - ac.Spec.ApplicationSet = &argov1beta1api.ArgoCDApplicationSet{ - SourceNamespaces: []string{"some-namespace", "some-other-namespace"}, - SCMProviders: []string{"github.com"}, - } - }) - - By("verifying ClusterRole/Bindings exist") - - Eventually(argoCDInstance, "5m", "5s").Should(argocdFixture.HaveApplicationSetControllerStatus("Running")) - - appSetClusterRole := &rbacv1.ClusterRole{ - ObjectMeta: metav1.ObjectMeta{Name: argocd.GenerateUniqueResourceName(common.ArgoCDApplicationSetControllerComponent, argoCDInstance)}, - } - Eventually(appSetClusterRole).Should(k8sFixture.ExistByName()) - - appSetCRB := &rbacv1.ClusterRoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: argocd.GenerateUniqueResourceName(common.ArgoCDApplicationSetControllerComponent, argoCDInstance), - }, - } - Eventually(appSetCRB).Should(k8sFixture.ExistByName()) - - }) - }) -})