From c14353394ddbbbaf587e9912a8b407cc0166f734 Mon Sep 17 00:00:00 2001 From: Rizwana777 Date: Mon, 18 Aug 2025 16:47:10 +0530 Subject: [PATCH 1/6] Add e2e tests for namespaceManagement Signed-off-by: Rizwana777 --- test/openshift/e2e/ginkgo/fixture/fixture.go | 2 +- ...1-113_validate_namespacemanagement_test.go | 146 ++++++++++++++++++ 2 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 test/openshift/e2e/ginkgo/sequential/1-113_validate_namespacemanagement_test.go diff --git a/test/openshift/e2e/ginkgo/fixture/fixture.go b/test/openshift/e2e/ginkgo/fixture/fixture.go index f5cf8e9a211..c9822d78cc6 100644 --- a/test/openshift/e2e/ginkgo/fixture/fixture.go +++ b/test/openshift/e2e/ginkgo/fixture/fixture.go @@ -510,7 +510,7 @@ func RestoreSubcriptionToDefault() { Expect(err).ToNot(HaveOccurred()) // optionalEnvVarsToRemove is a non-exhaustive list of environment variables that are known to be added to Subscription or operator Deployment by tests - optionalEnvVarsToRemove := []string{"DISABLE_DEFAULT_ARGOCD_CONSOLELINK", "CONTROLLER_CLUSTER_ROLE", "SERVER_CLUSTER_ROLE", "ARGOCD_LABEL_SELECTOR"} + optionalEnvVarsToRemove := []string{"DISABLE_DEFAULT_ARGOCD_CONSOLELINK", "CONTROLLER_CLUSTER_ROLE", "SERVER_CLUSTER_ROLE", "ARGOCD_LABEL_SELECTOR", "ALLOW_NAMESPACE_MANAGEMENT_IN_NAMESPACE_SCOPED_INSTANCES"} if EnvNonOLM() { diff --git a/test/openshift/e2e/ginkgo/sequential/1-113_validate_namespacemanagement_test.go b/test/openshift/e2e/ginkgo/sequential/1-113_validate_namespacemanagement_test.go new file mode 100644 index 00000000000..a81319829f9 --- /dev/null +++ b/test/openshift/e2e/ginkgo/sequential/1-113_validate_namespacemanagement_test.go @@ -0,0 +1,146 @@ +package sequential + +import ( + "context" + + argov1beta1api "github.com/argoproj-labs/argocd-operator/api/v1beta1" + argocdv1alpha1 "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1" + "github.com/argoproj/gitops-engine/pkg/health" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture" + appFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/application" + argocdFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/argocd" + k8sFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/k8s" + secretFixture "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/secret" + "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/utils" + 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" +) + +var _ = Describe("GitOps Operator Sequential E2E Tests", func() { + + Context("1-113_validate_namespacemanagement", func() { + + var ( + ctx context.Context + k8sClient client.Client + nmName string = "nm-test" + ) + + BeforeEach(func() { + fixture.EnsureSequentialCleanSlate() + k8sClient, _ = utils.GetE2ETestKubeClient() + ctx = context.Background() + + }) + + AfterEach(func() { + fixture.RestoreSubcriptionToDefault() // revert Subscription at end of test + }) + + It("should create Roles/RoleBindings when namespaceManagement is enabled from ArgoCD NamespaceManagement field", func() { + if fixture.EnvLocalRun() { + Skip("This test modifies the Subscription/operator deployment env vars, which requires the operator be running on the cluster.") + return + } + + By("Enabling namespaceManagement via env var") + fixture.SetEnvInOperatorSubscriptionOrDeployment("ALLOW_NAMESPACE_MANAGEMENT_IN_NAMESPACE_SCOPED_INSTANCES", "true") + + nsTest_1_9_custom, cleanupFunc1 := fixture.CreateNamespaceWithCleanupFunc("test-1-9-custom") + defer cleanupFunc1() + + randomNS, cleanupFunc2 := fixture.CreateRandomE2ETestNamespaceWithCleanupFunc() + defer cleanupFunc2() + + By("creating simple namespace-scoped Argo CD") + argoCDInRandomNS := &argov1beta1api.ArgoCD{ + ObjectMeta: metav1.ObjectMeta{Name: "argocd", Namespace: randomNS.Name}, + Spec: argov1beta1api.ArgoCDSpec{ + NamespaceManagement: []argov1beta1api.ManagedNamespaces{ + { + Name: nsTest_1_9_custom.Name, + AllowManagedBy: true, + }, + }, + }, + } + + Expect(k8sClient.Create(ctx, argoCDInRandomNS)).To(Succeed()) + + By("waiting for Argo CD to be available") + Eventually(argoCDInRandomNS, "5m", "5s").Should(argocdFixture.BeAvailable()) + + By("Create namespaceManagement CR with the namespace which needs to be managed") + nm := argov1beta1api.NamespaceManagement{ + ObjectMeta: metav1.ObjectMeta{Name: nmName, Namespace: nsTest_1_9_custom.Name}, + Spec: argov1beta1api.NamespaceManagementSpec{ManagedBy: argoCDInRandomNS.Namespace}, + } + Expect(k8sClient.Create(ctx, &nm)).To(Succeed()) + + By("verifying that new roles/rolebindings have be created in the new namespace, that allow the Argo CD instance to manage it") + argoCDServerRole := &rbacv1.Role{ + ObjectMeta: metav1.ObjectMeta{Name: "argocd-argocd-server", Namespace: nsTest_1_9_custom.Name}, + } + Eventually(argoCDServerRole).Should(k8sFixture.ExistByName()) + + argoCDAppControllerRole := &rbacv1.Role{ + ObjectMeta: metav1.ObjectMeta{Name: "argocd-argocd-application-controller", Namespace: nsTest_1_9_custom.Name}, + } + Eventually(argoCDAppControllerRole).Should(k8sFixture.ExistByName()) + + argoCDServerRB := &rbacv1.RoleBinding{ + ObjectMeta: metav1.ObjectMeta{Name: "argocd-argocd-server", Namespace: nsTest_1_9_custom.Name}, + } + Eventually(argoCDServerRB).Should(k8sFixture.ExistByName()) + Expect(argoCDServerRB.RoleRef).To(Equal(rbacv1.RoleRef{ + APIGroup: "rbac.authorization.k8s.io", + Kind: "Role", + Name: "argocd-argocd-server", + })) + + By("verifying that Argo CD eventually includes this other namespace in its Secret list of managed namespaces") + defaultClusterConfigSecret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "argocd-default-cluster-config", + Namespace: argoCDInRandomNS.Namespace, + }, + } + Eventually(defaultClusterConfigSecret, "2m", "5s").Should(k8sFixture.ExistByName()) + + Eventually(defaultClusterConfigSecret).Should( + secretFixture.HaveStringDataKeyValue("namespaces", argoCDInRandomNS.Namespace+","+nsTest_1_9_custom.Name)) + + By("creating Argo CD Application targeting the other namespace") + app := &argocdv1alpha1.Application{ + ObjectMeta: metav1.ObjectMeta{Name: "test-1-9-custom", Namespace: argoCDInRandomNS.Namespace}, + Spec: argocdv1alpha1.ApplicationSpec{ + Source: &argocdv1alpha1.ApplicationSource{ + Path: "test/examples/nginx", + RepoURL: "https://github.com/redhat-developer/gitops-operator", + TargetRevision: "HEAD", + }, + Destination: argocdv1alpha1.ApplicationDestination{ + Namespace: nsTest_1_9_custom.Name, + Server: "https://kubernetes.default.svc", + }, + Project: "default", + SyncPolicy: &argocdv1alpha1.SyncPolicy{ + Automated: &argocdv1alpha1.SyncPolicyAutomated{}, + }, + }, + } + Expect(k8sClient.Create(ctx, app)).To(Succeed()) + defer func() { // cleanup on test exit + Expect(k8sClient.Delete(ctx, app)).To(Succeed()) + }() + + By("verifying that Argo CD is able to deploy to that other namespace") + Eventually(app, "4m", "5s").Should(appFixture.HaveHealthStatusCode(health.HealthStatusHealthy)) + Eventually(app, "4m", "5s").Should(appFixture.HaveSyncStatusCode(argocdv1alpha1.SyncStatusCodeSynced)) + }) + }) +}) From 3089e5772a0b2534e8d26d92f20f21fa2f15645c Mon Sep 17 00:00:00 2001 From: Rizwana777 Date: Mon, 25 Aug 2025 14:48:38 +0530 Subject: [PATCH 2/6] Add namespacemanagement/status to RBAC, and tweak test contents Signed-off-by: Rizwana777 --- ...gitops-operator.clusterserviceversion.yaml | 3 ++- config/rbac/role.yaml | 1 + controllers/gitopsservice_controller.go | 2 +- ...1-113_validate_namespacemanagement_test.go | 21 ++++++++++++------- 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/bundle/manifests/gitops-operator.clusterserviceversion.yaml b/bundle/manifests/gitops-operator.clusterserviceversion.yaml index b3537200afe..1ef532faea4 100644 --- a/bundle/manifests/gitops-operator.clusterserviceversion.yaml +++ b/bundle/manifests/gitops-operator.clusterserviceversion.yaml @@ -180,7 +180,7 @@ metadata: capabilities: Deep Insights console.openshift.io/plugins: '["gitops-plugin"]' containerImage: quay.io/redhat-developer/gitops-operator - createdAt: "2025-08-20T01:09:37Z" + createdAt: "2025-08-21T01:20:45Z" description: Enables teams to adopt GitOps principles for managing cluster configurations and application delivery across hybrid multi-cluster Kubernetes environments. features.operators.openshift.io/disconnected: "true" @@ -494,6 +494,7 @@ spec: - experiments - experiments/finalizers - namespacemanagements + - namespacemanagements/status - rollouts - rollouts/finalizers - rollouts/scale diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index bf79b75119f..b833f3a92ee 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -143,6 +143,7 @@ rules: - experiments - experiments/finalizers - namespacemanagements + - namespacemanagements/status - rollouts - rollouts/finalizers - rollouts/scale diff --git a/controllers/gitopsservice_controller.go b/controllers/gitopsservice_controller.go index bd5d31d935e..df62b5ba795 100644 --- a/controllers/gitopsservice_controller.go +++ b/controllers/gitopsservice_controller.go @@ -198,7 +198,7 @@ type ReconcileGitopsService struct { //+kubebuilder:rbac:groups=argoproj.io,resources=notificationsconfigurations;notificationsconfigurations/finalizers,verbs=* //+kubebuilder:rbac:groups=apiextensions.k8s.io,resources=customresourcedefinitions,verbs=get;list;watch; //+kubebuilder:rbac:groups="apiregistration.k8s.io",resources="apiservices",verbs=get;list -//+kubebuilder:rbac:groups="argoproj.io",resources=namespacemanagements,verbs=create;get;list;watch;update;patch;delete;deletecollection +//+kubebuilder:rbac:groups="argoproj.io",resources=namespacemanagements;namespacemanagements/status,verbs=create;get;list;watch;update;patch;delete;deletecollection // Reconcile reads that state of the cluster for a GitopsService object and makes changes based on the state read // and what is in the GitopsService.Spec diff --git a/test/openshift/e2e/ginkgo/sequential/1-113_validate_namespacemanagement_test.go b/test/openshift/e2e/ginkgo/sequential/1-113_validate_namespacemanagement_test.go index a81319829f9..0f9d88a65f4 100644 --- a/test/openshift/e2e/ginkgo/sequential/1-113_validate_namespacemanagement_test.go +++ b/test/openshift/e2e/ginkgo/sequential/1-113_validate_namespacemanagement_test.go @@ -28,12 +28,24 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { ctx context.Context k8sClient client.Client nmName string = "nm-test" + + randomNS *corev1.Namespace + nsTest_1_9_custom *corev1.Namespace + cleanupFunc1 func() + cleanupFunc2 func() ) BeforeEach(func() { fixture.EnsureSequentialCleanSlate() k8sClient, _ = utils.GetE2ETestKubeClient() ctx = context.Background() + }) + + AfterEach(func() { + defer cleanupFunc1() + defer cleanupFunc2() + + fixture.OutputDebugOnFail(randomNS.Name, nsTest_1_9_custom.Name) }) @@ -50,11 +62,9 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { By("Enabling namespaceManagement via env var") fixture.SetEnvInOperatorSubscriptionOrDeployment("ALLOW_NAMESPACE_MANAGEMENT_IN_NAMESPACE_SCOPED_INSTANCES", "true") - nsTest_1_9_custom, cleanupFunc1 := fixture.CreateNamespaceWithCleanupFunc("test-1-9-custom") - defer cleanupFunc1() + nsTest_1_9_custom, cleanupFunc1 = fixture.CreateNamespaceWithCleanupFunc("test-1-9-custom") - randomNS, cleanupFunc2 := fixture.CreateRandomE2ETestNamespaceWithCleanupFunc() - defer cleanupFunc2() + randomNS, cleanupFunc2 = fixture.CreateRandomE2ETestNamespaceWithCleanupFunc() By("creating simple namespace-scoped Argo CD") argoCDInRandomNS := &argov1beta1api.ArgoCD{ @@ -134,9 +144,6 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { }, } Expect(k8sClient.Create(ctx, app)).To(Succeed()) - defer func() { // cleanup on test exit - Expect(k8sClient.Delete(ctx, app)).To(Succeed()) - }() By("verifying that Argo CD is able to deploy to that other namespace") Eventually(app, "4m", "5s").Should(appFixture.HaveHealthStatusCode(health.HealthStatusHealthy)) From 9bf3f3eff80615b1024453a27d09c48c5b88f87e Mon Sep 17 00:00:00 2001 From: Rizwana777 Date: Wed, 27 Aug 2025 23:53:16 +0530 Subject: [PATCH 3/6] Fix merge conflicts Signed-off-by: Rizwana777 --- go.mod | 2 +- go.sum | 4 ++-- .../1-113_validate_namespacemanagement_test.go | 11 ++++++----- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index c17462dab6f..abd6e90e5fe 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.24.4 require ( github.com/argoproj-labs/argo-rollouts-manager v0.0.6-0.20250731075119-a100fc1d88b8 - github.com/argoproj-labs/argocd-operator v0.14.0-rc1.0.20250825094300-73f08c092df7 + github.com/argoproj-labs/argocd-operator v0.14.0-rc1.0.20250821121807-51b61c04008d github.com/argoproj/argo-cd/v3 v3.1.0-rc2 github.com/argoproj/gitops-engine v0.7.1-0.20250617174952-093aef0dad58 github.com/go-logr/logr v1.4.3 diff --git a/go.sum b/go.sum index 422c39816be..388e1a9220c 100644 --- a/go.sum +++ b/go.sum @@ -31,8 +31,8 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFI github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/argoproj-labs/argo-rollouts-manager v0.0.6-0.20250731075119-a100fc1d88b8 h1:6+eo7BKrNkSIhQ1nnyCUloSNrGzghlb8r8e7GokoeBo= github.com/argoproj-labs/argo-rollouts-manager v0.0.6-0.20250731075119-a100fc1d88b8/go.mod h1:yTwzKUV79YyI764hkXdVojGYBA9yKJk3qXx5mRuQ2Xc= -github.com/argoproj-labs/argocd-operator v0.14.0-rc1.0.20250825094300-73f08c092df7 h1:Y7UmKUW707B7xVLjfnBVkQgM00Dmi7JOCxB9WZ092zE= -github.com/argoproj-labs/argocd-operator v0.14.0-rc1.0.20250825094300-73f08c092df7/go.mod h1:7zgj/iHFq1r1OZmLX9yxUAarttxnklMbqZb/63euXA8= +github.com/argoproj-labs/argocd-operator v0.14.0-rc1.0.20250821121807-51b61c04008d h1:0PTqF4kGLabrlo8SouzcsqmEwHye20mbLUgr642gKg0= +github.com/argoproj-labs/argocd-operator v0.14.0-rc1.0.20250821121807-51b61c04008d/go.mod h1:7zgj/iHFq1r1OZmLX9yxUAarttxnklMbqZb/63euXA8= github.com/argoproj/argo-cd/v3 v3.1.0-rc2 h1:oT9whFw3tShGkW1WrHJReFkAJvmsgS2KGJkcRIFSnt8= github.com/argoproj/argo-cd/v3 v3.1.0-rc2/go.mod h1:vrxw1sapzdI3nnkwRKP84cMTzYjOKP7XsEy5fW1FQgg= github.com/argoproj/gitops-engine v0.7.1-0.20250617174952-093aef0dad58 h1:9ESamu44v3dR9j/I4/4Aa1Fx3QSIE8ElK1CR8Z285uk= diff --git a/test/openshift/e2e/ginkgo/sequential/1-113_validate_namespacemanagement_test.go b/test/openshift/e2e/ginkgo/sequential/1-113_validate_namespacemanagement_test.go index 0f9d88a65f4..0a766f2140f 100644 --- a/test/openshift/e2e/ginkgo/sequential/1-113_validate_namespacemanagement_test.go +++ b/test/openshift/e2e/ginkgo/sequential/1-113_validate_namespacemanagement_test.go @@ -59,16 +59,14 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { return } - By("Enabling namespaceManagement via env var") - fixture.SetEnvInOperatorSubscriptionOrDeployment("ALLOW_NAMESPACE_MANAGEMENT_IN_NAMESPACE_SCOPED_INSTANCES", "true") - nsTest_1_9_custom, cleanupFunc1 = fixture.CreateNamespaceWithCleanupFunc("test-1-9-custom") - randomNS, cleanupFunc2 = fixture.CreateRandomE2ETestNamespaceWithCleanupFunc() By("creating simple namespace-scoped Argo CD") argoCDInRandomNS := &argov1beta1api.ArgoCD{ - ObjectMeta: metav1.ObjectMeta{Name: "argocd", Namespace: randomNS.Name}, + ObjectMeta: metav1.ObjectMeta{ + Name: "argocd", + Namespace: randomNS.Name}, Spec: argov1beta1api.ArgoCDSpec{ NamespaceManagement: []argov1beta1api.ManagedNamespaces{ { @@ -84,6 +82,9 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { By("waiting for Argo CD to be available") Eventually(argoCDInRandomNS, "5m", "5s").Should(argocdFixture.BeAvailable()) + By("Enabling namespaceManagement via env var") + fixture.SetEnvInOperatorSubscriptionOrDeployment("ALLOW_NAMESPACE_MANAGEMENT_IN_NAMESPACE_SCOPED_INSTANCES", "true") + By("Create namespaceManagement CR with the namespace which needs to be managed") nm := argov1beta1api.NamespaceManagement{ ObjectMeta: metav1.ObjectMeta{Name: nmName, Namespace: nsTest_1_9_custom.Name}, From a545d2781cbe8766d15369b1087c307b8a4087c3 Mon Sep 17 00:00:00 2001 From: Rizwana777 Date: Tue, 26 Aug 2025 16:13:37 +0530 Subject: [PATCH 4/6] Add remaining namespaceManagement tests Signed-off-by: Rizwana777 --- go.mod | 2 +- go.sum | 4 +- ...1-113_validate_namespacemanagement_test.go | 379 +++++++++++++++--- 3 files changed, 316 insertions(+), 69 deletions(-) diff --git a/go.mod b/go.mod index abd6e90e5fe..c17462dab6f 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.24.4 require ( github.com/argoproj-labs/argo-rollouts-manager v0.0.6-0.20250731075119-a100fc1d88b8 - github.com/argoproj-labs/argocd-operator v0.14.0-rc1.0.20250821121807-51b61c04008d + github.com/argoproj-labs/argocd-operator v0.14.0-rc1.0.20250825094300-73f08c092df7 github.com/argoproj/argo-cd/v3 v3.1.0-rc2 github.com/argoproj/gitops-engine v0.7.1-0.20250617174952-093aef0dad58 github.com/go-logr/logr v1.4.3 diff --git a/go.sum b/go.sum index 388e1a9220c..422c39816be 100644 --- a/go.sum +++ b/go.sum @@ -31,8 +31,8 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFI github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/argoproj-labs/argo-rollouts-manager v0.0.6-0.20250731075119-a100fc1d88b8 h1:6+eo7BKrNkSIhQ1nnyCUloSNrGzghlb8r8e7GokoeBo= github.com/argoproj-labs/argo-rollouts-manager v0.0.6-0.20250731075119-a100fc1d88b8/go.mod h1:yTwzKUV79YyI764hkXdVojGYBA9yKJk3qXx5mRuQ2Xc= -github.com/argoproj-labs/argocd-operator v0.14.0-rc1.0.20250821121807-51b61c04008d h1:0PTqF4kGLabrlo8SouzcsqmEwHye20mbLUgr642gKg0= -github.com/argoproj-labs/argocd-operator v0.14.0-rc1.0.20250821121807-51b61c04008d/go.mod h1:7zgj/iHFq1r1OZmLX9yxUAarttxnklMbqZb/63euXA8= +github.com/argoproj-labs/argocd-operator v0.14.0-rc1.0.20250825094300-73f08c092df7 h1:Y7UmKUW707B7xVLjfnBVkQgM00Dmi7JOCxB9WZ092zE= +github.com/argoproj-labs/argocd-operator v0.14.0-rc1.0.20250825094300-73f08c092df7/go.mod h1:7zgj/iHFq1r1OZmLX9yxUAarttxnklMbqZb/63euXA8= github.com/argoproj/argo-cd/v3 v3.1.0-rc2 h1:oT9whFw3tShGkW1WrHJReFkAJvmsgS2KGJkcRIFSnt8= github.com/argoproj/argo-cd/v3 v3.1.0-rc2/go.mod h1:vrxw1sapzdI3nnkwRKP84cMTzYjOKP7XsEy5fW1FQgg= github.com/argoproj/gitops-engine v0.7.1-0.20250617174952-093aef0dad58 h1:9ESamu44v3dR9j/I4/4Aa1Fx3QSIE8ElK1CR8Z285uk= diff --git a/test/openshift/e2e/ginkgo/sequential/1-113_validate_namespacemanagement_test.go b/test/openshift/e2e/ginkgo/sequential/1-113_validate_namespacemanagement_test.go index 0a766f2140f..1a86c5f3caf 100644 --- a/test/openshift/e2e/ginkgo/sequential/1-113_validate_namespacemanagement_test.go +++ b/test/openshift/e2e/ginkgo/sequential/1-113_validate_namespacemanagement_test.go @@ -2,6 +2,7 @@ package sequential import ( "context" + "strings" argov1beta1api "github.com/argoproj-labs/argocd-operator/api/v1beta1" argocdv1alpha1 "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1" @@ -16,6 +17,7 @@ import ( "github.com/redhat-developer/gitops-operator/test/openshift/e2e/ginkgo/fixture/utils" corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -27,107 +29,107 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { var ( ctx context.Context k8sClient client.Client - nmName string = "nm-test" + randomNS *corev1.Namespace + nsCustom *corev1.Namespace + targetNs *corev1.Namespace - randomNS *corev1.Namespace - nsTest_1_9_custom *corev1.Namespace - cleanupFunc1 func() - cleanupFunc2 func() + cleanupFunc1 func() + cleanupFunc2 func() + cleanupFunc3 func() + nmName string = "nm-test" ) BeforeEach(func() { fixture.EnsureSequentialCleanSlate() k8sClient, _ = utils.GetE2ETestKubeClient() ctx = context.Background() - }) - - AfterEach(func() { - defer cleanupFunc1() - defer cleanupFunc2() - fixture.OutputDebugOnFail(randomNS.Name, nsTest_1_9_custom.Name) + nsCustom, cleanupFunc1 = fixture.CreateNamespaceWithCleanupFunc("test-113-custom") + randomNS, cleanupFunc2 = fixture.CreateRandomE2ETestNamespaceWithCleanupFunc() + targetNs, cleanupFunc3 = fixture.CreateNamespaceWithCleanupFunc("test-second-nms") }) AfterEach(func() { - fixture.RestoreSubcriptionToDefault() // revert Subscription at end of test - }) - It("should create Roles/RoleBindings when namespaceManagement is enabled from ArgoCD NamespaceManagement field", func() { - if fixture.EnvLocalRun() { - Skip("This test modifies the Subscription/operator deployment env vars, which requires the operator be running on the cluster.") - return - } + defer cleanupFunc1() + defer cleanupFunc2() + defer cleanupFunc3() - nsTest_1_9_custom, cleanupFunc1 = fixture.CreateNamespaceWithCleanupFunc("test-1-9-custom") - randomNS, cleanupFunc2 = fixture.CreateRandomE2ETestNamespaceWithCleanupFunc() + defer fixture.RestoreSubcriptionToDefault() // revert Subscription at end of test + fixture.OutputDebugOnFail(randomNS.Name, nsCustom.Name) + }) - By("creating simple namespace-scoped Argo CD") + deployArgoCD := func(namespace string, managedNamespaces []argov1beta1api.ManagedNamespaces) *argov1beta1api.ArgoCD { argoCDInRandomNS := &argov1beta1api.ArgoCD{ - ObjectMeta: metav1.ObjectMeta{ - Name: "argocd", - Namespace: randomNS.Name}, + ObjectMeta: metav1.ObjectMeta{Name: "argocd", Namespace: namespace}, Spec: argov1beta1api.ArgoCDSpec{ - NamespaceManagement: []argov1beta1api.ManagedNamespaces{ - { - Name: nsTest_1_9_custom.Name, - AllowManagedBy: true, - }, - }, + NamespaceManagement: managedNamespaces, }, } - Expect(k8sClient.Create(ctx, argoCDInRandomNS)).To(Succeed()) By("waiting for Argo CD to be available") Eventually(argoCDInRandomNS, "5m", "5s").Should(argocdFixture.BeAvailable()) - By("Enabling namespaceManagement via env var") - fixture.SetEnvInOperatorSubscriptionOrDeployment("ALLOW_NAMESPACE_MANAGEMENT_IN_NAMESPACE_SCOPED_INSTANCES", "true") + return argoCDInRandomNS + } - By("Create namespaceManagement CR with the namespace which needs to be managed") - nm := argov1beta1api.NamespaceManagement{ - ObjectMeta: metav1.ObjectMeta{Name: nmName, Namespace: nsTest_1_9_custom.Name}, - Spec: argov1beta1api.NamespaceManagementSpec{ManagedBy: argoCDInRandomNS.Namespace}, + checkRolesBindings := func(ns string, shouldExist bool) { + roles := []string{ + "argocd-argocd-server", + "argocd-argocd-application-controller", } - Expect(k8sClient.Create(ctx, &nm)).To(Succeed()) - - By("verifying that new roles/rolebindings have be created in the new namespace, that allow the Argo CD instance to manage it") - argoCDServerRole := &rbacv1.Role{ - ObjectMeta: metav1.ObjectMeta{Name: "argocd-argocd-server", Namespace: nsTest_1_9_custom.Name}, - } - Eventually(argoCDServerRole).Should(k8sFixture.ExistByName()) - - argoCDAppControllerRole := &rbacv1.Role{ - ObjectMeta: metav1.ObjectMeta{Name: "argocd-argocd-application-controller", Namespace: nsTest_1_9_custom.Name}, + for _, r := range roles { + role := &rbacv1.Role{ObjectMeta: metav1.ObjectMeta{Name: r, Namespace: ns}} + if shouldExist { + Eventually(role, "90s", "5s").Should(k8sFixture.ExistByName()) + } else { + Eventually(role, "3m", "5s").ShouldNot(k8sFixture.ExistByName()) + } } - Eventually(argoCDAppControllerRole).Should(k8sFixture.ExistByName()) - argoCDServerRB := &rbacv1.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{Name: "argocd-argocd-server", Namespace: nsTest_1_9_custom.Name}, + rb := &rbacv1.RoleBinding{ObjectMeta: metav1.ObjectMeta{Name: "argocd-argocd-server", Namespace: ns}} + if shouldExist { + Eventually(rb, "90s", "5s").Should(k8sFixture.ExistByName()) + } else { + Eventually(rb, "3m", "5s").ShouldNot(k8sFixture.ExistByName()) } - Eventually(argoCDServerRB).Should(k8sFixture.ExistByName()) - Expect(argoCDServerRB.RoleRef).To(Equal(rbacv1.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Kind: "Role", - Name: "argocd-argocd-server", - })) + } + verifyNamespaceManagementSecretAndApplication := func(argoCD *argov1beta1api.ArgoCD, nsCustom *corev1.Namespace, enabled bool, expectedNamespaces []string) { By("verifying that Argo CD eventually includes this other namespace in its Secret list of managed namespaces") defaultClusterConfigSecret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: "argocd-default-cluster-config", - Namespace: argoCDInRandomNS.Namespace, + Namespace: argoCD.Namespace, }, } - Eventually(defaultClusterConfigSecret, "2m", "5s").Should(k8sFixture.ExistByName()) + Eventually(defaultClusterConfigSecret, "90s", "5s").Should(k8sFixture.ExistByName()) - Eventually(defaultClusterConfigSecret).Should( - secretFixture.HaveStringDataKeyValue("namespaces", argoCDInRandomNS.Namespace+","+nsTest_1_9_custom.Name)) + // check the "namespaces" key in the Secret + if enabled { + Eventually(defaultClusterConfigSecret, "90s", "5s").Should( + secretFixture.HaveStringDataKeyValue( + "namespaces", + strings.Join(expectedNamespaces, ","), + ), + ) + } else { + Eventually(defaultClusterConfigSecret, "90s", "5s").Should( + secretFixture.HaveStringDataKeyValue( + "namespaces", + argoCD.Namespace, + ), + ) + } By("creating Argo CD Application targeting the other namespace") app := &argocdv1alpha1.Application{ - ObjectMeta: metav1.ObjectMeta{Name: "test-1-9-custom", Namespace: argoCDInRandomNS.Namespace}, + ObjectMeta: metav1.ObjectMeta{ + Name: "test-113-custom", + Namespace: argoCD.Namespace, + }, Spec: argocdv1alpha1.ApplicationSpec{ Source: &argocdv1alpha1.ApplicationSource{ Path: "test/examples/nginx", @@ -135,7 +137,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { TargetRevision: "HEAD", }, Destination: argocdv1alpha1.ApplicationDestination{ - Namespace: nsTest_1_9_custom.Name, + Namespace: nsCustom.Name, Server: "https://kubernetes.default.svc", }, Project: "default", @@ -144,11 +146,256 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { }, }, } - Expect(k8sClient.Create(ctx, app)).To(Succeed()) - By("verifying that Argo CD is able to deploy to that other namespace") - Eventually(app, "4m", "5s").Should(appFixture.HaveHealthStatusCode(health.HealthStatusHealthy)) - Eventually(app, "4m", "5s").Should(appFixture.HaveSyncStatusCode(argocdv1alpha1.SyncStatusCodeSynced)) + existing := &argocdv1alpha1.Application{} + err := k8sClient.Get(ctx, client.ObjectKey{Name: app.Name, Namespace: app.Namespace}, existing) + if apierrors.IsNotFound(err) { + Expect(k8sClient.Create(ctx, app)).To(Succeed()) + } else { + Expect(err).NotTo(HaveOccurred()) + } + + if enabled { + By("verifying that Argo CD is able to deploy to that other namespace") + Eventually(app, "4m", "5s").Should(appFixture.HaveHealthStatusCode(health.HealthStatusHealthy)) + Eventually(app, "4m", "5s").Should(appFixture.HaveSyncStatusCode(argocdv1alpha1.SyncStatusCodeSynced)) + } else { + By("verifying that Argo CD is NOT able to deploy to that other namespace") + Eventually(app, "4m", "5s").ShouldNot(appFixture.HaveSyncStatusCode(argocdv1alpha1.SyncStatusCodeSynced)) + } + } + + It("should create Roles/RoleBindings when namespaceManagement is enabled from ArgoCD NamespaceManagement field", func() { + if fixture.EnvLocalRun() { + Skip("This test modifies the Subscription/operator deployment env vars, which requires the operator be running on the cluster.") + return + } + + By("Create ArgoCD with namespaceManagement field set to true") + argoCD := deployArgoCD(randomNS.Name, []argov1beta1api.ManagedNamespaces{ + {Name: nsCustom.Name, AllowManagedBy: true}, + }) + + By("Enabling namespaceManagement via env var") + fixture.SetEnvInOperatorSubscriptionOrDeployment("ALLOW_NAMESPACE_MANAGEMENT_IN_NAMESPACE_SCOPED_INSTANCES", "true") + + By("Create namespaceManagement CR with the namespace which needs to be managed") + nm := argov1beta1api.NamespaceManagement{ + ObjectMeta: metav1.ObjectMeta{Name: nmName, Namespace: nsCustom.Name}, + Spec: argov1beta1api.NamespaceManagementSpec{ManagedBy: randomNS.Name}, + } + Expect(k8sClient.Create(ctx, &nm)).To(Succeed()) + + By("Verify Roles/RoleBindings are created for managed namespace") + checkRolesBindings(nsCustom.Name, true) + + By("Verify Application and Secret of managed namespace") + verifyNamespaceManagementSecretAndApplication(argoCD, nsCustom, true, []string{argoCD.Namespace, nsCustom.Name}) + }) + + It("should not create roles when namespaceManagement env var is not set", func() { + if fixture.EnvLocalRun() { + Skip("This test modifies the Subscription/operator deployment env vars, which requires the operator be running on the cluster.") + return + } + + By("Create ArgoCD with namespaceManagement field set to true") + argoCD := deployArgoCD(randomNS.Name, []argov1beta1api.ManagedNamespaces{ + {Name: nsCustom.Name, AllowManagedBy: true}, + }) + + By("Enabling namespaceManagement via env var") + fixture.SetEnvInOperatorSubscriptionOrDeployment("ALLOW_NAMESPACE_MANAGEMENT_IN_NAMESPACE_SCOPED_INSTANCES", "false") + + By("Create namespaceManagement CR with the namespace which needs to be managed") + nm := argov1beta1api.NamespaceManagement{ + ObjectMeta: metav1.ObjectMeta{Name: nmName, Namespace: nsCustom.Name}, + Spec: argov1beta1api.NamespaceManagementSpec{ManagedBy: randomNS.Name}, + } + Expect(k8sClient.Create(ctx, &nm)).To(Succeed()) + + By("Verify Roles/RoleBindings are created for managed namespace") + checkRolesBindings(nsCustom.Name, false) + + By("Verify Application and Secret of managed namespace") + verifyNamespaceManagementSecretAndApplication(argoCD, nsCustom, false, []string{}) + }) + + It("should delete Roles/RoleBindings when namespace management is disabled from ArgoCD NamespaceManagement field", func() { + if fixture.EnvLocalRun() { + Skip("This test modifies the Subscription/operator deployment env vars, which requires the operator be running on the cluster.") + return + } + + By("Create ArgoCD with namespaceManagement field set to false") + argoCD := deployArgoCD(randomNS.Name, []argov1beta1api.ManagedNamespaces{ + {Name: nsCustom.Name, AllowManagedBy: false}, + }) + + By("Enabling namespace management via env var") + fixture.SetEnvInOperatorSubscriptionOrDeployment("ALLOW_NAMESPACE_MANAGEMENT_IN_NAMESPACE_SCOPED_INSTANCES", "true") + + By("Create namespaceManagement CR") + nsm := argov1beta1api.NamespaceManagement{ + ObjectMeta: metav1.ObjectMeta{Name: nmName, Namespace: nsCustom.Name}, + Spec: argov1beta1api.NamespaceManagementSpec{ManagedBy: randomNS.Name}, + } + Expect(k8sClient.Create(ctx, &nsm)).To(Succeed()) + + By("Verify Roles/RoleBindings are deleted from managed namespace") + checkRolesBindings(nsCustom.Name, false) + + By("Verify Application and Secret of managed namespace") + verifyNamespaceManagementSecretAndApplication(argoCD, nsCustom, false, []string{argoCD.Namespace, nsCustom.Name}) + }) + + It("should support glob pattern(test-*) matching for managed namespaces", func() { + if fixture.EnvLocalRun() { + Skip("This test modifies the Subscription/operator deployment env vars, which requires the operator be running on the cluster.") + return + } + + By("Create ArgoCD with namespaceManagement field set to true") + argoCD := deployArgoCD(randomNS.Name, []argov1beta1api.ManagedNamespaces{ + {Name: "test-*", AllowManagedBy: true}, + }) + + By("Enabling namespace management via env var") + fixture.SetEnvInOperatorSubscriptionOrDeployment("ALLOW_NAMESPACE_MANAGEMENT_IN_NAMESPACE_SCOPED_INSTANCES", "true") + + By("Create namespaceManagement CR") + nsm := argov1beta1api.NamespaceManagement{ + ObjectMeta: metav1.ObjectMeta{Name: nmName, Namespace: nsCustom.Name}, + Spec: argov1beta1api.NamespaceManagementSpec{ManagedBy: randomNS.Name}, + } + Expect(k8sClient.Create(ctx, &nsm)).To(Succeed()) + + By("Verify Roles/RoleBindings are created for managed namespace test-113-custom") + checkRolesBindings(nsCustom.Name, true) // matches pattern + + By("Create namespaceManagement CR 2") + nsm1 := argov1beta1api.NamespaceManagement{ + ObjectMeta: metav1.ObjectMeta{Name: "nm-test-1", Namespace: targetNs.Name}, + Spec: argov1beta1api.NamespaceManagementSpec{ManagedBy: randomNS.Name}, + } + Expect(k8sClient.Create(ctx, &nsm1)).To(Succeed()) + + By("Verify Roles/RoleBindings are created for managed namespace test-second-nms") + checkRolesBindings(nsm1.Namespace, true) // matches pattern + + By("Verify Application and Secret of managed namespace test-113-custom") + verifyNamespaceManagementSecretAndApplication(argoCD, nsCustom, true, []string{argoCD.Namespace, nsCustom.Name, targetNs.Name}) + + By("Verify Application and Secret of managed namespace test-second-nms") + verifyNamespaceManagementSecretAndApplication(argoCD, targetNs, true, []string{argoCD.Namespace, nsCustom.Name, targetNs.Name}) + }) + + It("should clean up Roles/Rolebindings when NamespaceManagement is removed from ArgoCD", func() { + if fixture.EnvLocalRun() { + Skip("This test modifies the Subscription/operator deployment env vars, which requires the operator be running on the cluster.") + return + } + + By("Create ArgoCD with namespaceManagement field set to true") + argoCD := deployArgoCD(randomNS.Name, []argov1beta1api.ManagedNamespaces{ + {Name: nsCustom.Name, AllowManagedBy: true}, + }) + + By("Enabling namespace management via env var") + fixture.SetEnvInOperatorSubscriptionOrDeployment("ALLOW_NAMESPACE_MANAGEMENT_IN_NAMESPACE_SCOPED_INSTANCES", "true") + + By("Create namespaceManagement CR") + nsm := argov1beta1api.NamespaceManagement{ + ObjectMeta: metav1.ObjectMeta{Name: nmName, Namespace: nsCustom.Name}, + Spec: argov1beta1api.NamespaceManagementSpec{ManagedBy: randomNS.Name}, + } + Expect(k8sClient.Create(ctx, &nsm)).To(Succeed()) + + By("Role/Rolebindings should be created for managed namespace if namespaceManagement CR is present") + checkRolesBindings(nsCustom.Name, true) + + By("Remove NamespaceManagement to check cleanup of Roles/Rolebindings") + Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(argoCD), argoCD)).To(Succeed()) + argoCD.Spec.NamespaceManagement = nil + Expect(k8sClient.Update(ctx, argoCD)).To(Succeed()) + + By("Verify Roles/RoleBindings are deleted from managed namespace") + Eventually(func() bool { + checkRolesBindings(nsCustom.Name, false) + return true + }, "2m", "5s").Should(BeTrue()) + + By("Verify Application and Secret of managed namespace when nm is disabled") + verifyNamespaceManagementSecretAndApplication(argoCD, nsCustom, false, []string{argoCD.Namespace, nsCustom.Name}) + }) + + It("should not create roles when ArgoCD CR has no managedBy entry", func() { + if fixture.EnvLocalRun() { + Skip("This test modifies the Subscription/operator deployment env vars, which requires the operator be running on the cluster.") + return + } + + By("Create ArgoCD with no namespaceManagement field") + argoCD := deployArgoCD(randomNS.Name, nil) + + By("enabling namespace management via env var") + fixture.SetEnvInOperatorSubscriptionOrDeployment("ALLOW_NAMESPACE_MANAGEMENT_IN_NAMESPACE_SCOPED_INSTANCES", "true") + + By("Verify Roles/RoleBindings are deleted from managed namespace") + checkRolesBindings(nsCustom.Name, false) + + By("Verify Application and Secret of managed namespace when nm is not present in ArgoCD") + verifyNamespaceManagementSecretAndApplication(argoCD, nsCustom, false, []string{argoCD.Namespace, nsCustom.Name}) + }) + + It("should enable namespace management when env var is true and disable it when set to false", func() { + if fixture.EnvLocalRun() { + Skip("This test modifies the Subscription/operator deployment env vars, which requires the operator be running on the cluster.") + return + } + + By("Create ArgoCD with namespaceManagement field set to true") + argoCD := deployArgoCD(randomNS.Name, []argov1beta1api.ManagedNamespaces{ + {Name: nsCustom.Name, AllowManagedBy: true}, + }) + + By("Enabling namespace management via env var") + fixture.SetEnvInOperatorSubscriptionOrDeployment("ALLOW_NAMESPACE_MANAGEMENT_IN_NAMESPACE_SCOPED_INSTANCES", "true") + + By("Create namespaceManagement CR with the namespace which needs to be managed") + nm := argov1beta1api.NamespaceManagement{ + ObjectMeta: metav1.ObjectMeta{Name: nmName, Namespace: nsCustom.Name}, + Spec: argov1beta1api.NamespaceManagementSpec{ManagedBy: randomNS.Name}, + } + Expect(k8sClient.Create(ctx, &nm)).To(Succeed()) + + By("Verify Roles/RoleBindings are created for managed namespace when env var is true") + checkRolesBindings(nsCustom.Name, true) + + By("Verify Application and Secret for managed namespace") + verifyNamespaceManagementSecretAndApplication(argoCD, nsCustom, true, []string{argoCD.Namespace, nsCustom.Name}) + + By("Disabling namespace management via env var") + fixture.SetEnvInOperatorSubscriptionOrDeployment("ALLOW_NAMESPACE_MANAGEMENT_IN_NAMESPACE_SCOPED_INSTANCES", "false") + + By("verifying ALLOW_NAMESPACE_MANAGEMENT_IN_NAMESPACE_SCOPED_INSTANCES is 'false'") + Eventually(func() bool { + val, err := fixture.GetEnvInOperatorSubscriptionOrDeployment("ALLOW_NAMESPACE_MANAGEMENT_IN_NAMESPACE_SCOPED_INSTANCES") + if err != nil { + GinkgoWriter.Println(err) + return false + } + if val == nil { + return false + } + return *val == "false" + }).Should(BeTrue(), "ALLOW_NAMESPACE_MANAGEMENT_IN_NAMESPACE_SCOPED_INSTANCES should be false") + + By("Verify Roles/RoleBindings are deleted for managed namespace when env var is false") + checkRolesBindings(nsCustom.Name, false) + + By("Verify Application should not be able to sync to managed namespace when env var is false") + verifyNamespaceManagementSecretAndApplication(argoCD, nsCustom, false, []string{argoCD.Namespace, nsCustom.Name}) }) }) }) From a5ab0dc00140f978925b6fd7947384bed424c9c2 Mon Sep 17 00:00:00 2001 From: Jonathan West Date: Tue, 2 Sep 2025 07:49:46 -0400 Subject: [PATCH 5/6] Add additional Consistently checks Signed-off-by: Jonathan West --- ...1-113_validate_namespacemanagement_test.go | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/test/openshift/e2e/ginkgo/sequential/1-113_validate_namespacemanagement_test.go b/test/openshift/e2e/ginkgo/sequential/1-113_validate_namespacemanagement_test.go index 1a86c5f3caf..1dd816b8c83 100644 --- a/test/openshift/e2e/ginkgo/sequential/1-113_validate_namespacemanagement_test.go +++ b/test/openshift/e2e/ginkgo/sequential/1-113_validate_namespacemanagement_test.go @@ -85,7 +85,8 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { if shouldExist { Eventually(role, "90s", "5s").Should(k8sFixture.ExistByName()) } else { - Eventually(role, "3m", "5s").ShouldNot(k8sFixture.ExistByName()) + Eventually(role, "3m", "5s").Should(k8sFixture.NotExistByName()) + Consistently(role).Should(k8sFixture.NotExistByName()) } } @@ -93,7 +94,8 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { if shouldExist { Eventually(rb, "90s", "5s").Should(k8sFixture.ExistByName()) } else { - Eventually(rb, "3m", "5s").ShouldNot(k8sFixture.ExistByName()) + Eventually(rb, "3m", "5s").Should(k8sFixture.NotExistByName()) + Consistently(rb).Should(k8sFixture.NotExistByName()) } } @@ -115,6 +117,12 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { strings.Join(expectedNamespaces, ","), ), ) + Consistently(defaultClusterConfigSecret).Should( + secretFixture.HaveStringDataKeyValue( + "namespaces", + strings.Join(expectedNamespaces, ","), + ), + ) } else { Eventually(defaultClusterConfigSecret, "90s", "5s").Should( secretFixture.HaveStringDataKeyValue( @@ -122,6 +130,12 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { argoCD.Namespace, ), ) + Consistently(defaultClusterConfigSecret).Should( + secretFixture.HaveStringDataKeyValue( + "namespaces", + argoCD.Namespace, + ), + ) } By("creating Argo CD Application targeting the other namespace") @@ -162,6 +176,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { } else { By("verifying that Argo CD is NOT able to deploy to that other namespace") Eventually(app, "4m", "5s").ShouldNot(appFixture.HaveSyncStatusCode(argocdv1alpha1.SyncStatusCodeSynced)) + Consistently(app, "1m", "5s").ShouldNot(appFixture.HaveSyncStatusCode(argocdv1alpha1.SyncStatusCodeSynced)) } } From b83ffdb66c67e100daa669b61e81a511bea0c778 Mon Sep 17 00:00:00 2001 From: Rizwana777 Date: Tue, 2 Sep 2025 22:52:35 +0530 Subject: [PATCH 6/6] Add a new test and address review comments Signed-off-by: Rizwana777 --- Makefile | 2 +- ...1-113_validate_namespacemanagement_test.go | 88 +++++++++++++++---- 2 files changed, 73 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index ac78713aca8..70fd28f68c7 100644 --- a/Makefile +++ b/Makefile @@ -161,7 +161,7 @@ e2e-tests-ginkgo: e2e-tests-sequential-ginkgo e2e-tests-parallel-ginkgo ## Runs .PHONY: e2e-tests-sequential-ginkgo e2e-tests-sequential-ginkgo: ginkgo ## Runs kuttl e2e sequential tests @echo "Running GitOps Operator sequential Ginkgo E2E tests..." - $(GINKGO_CLI) -v --trace --timeout 90m -r ./test/openshift/e2e/ginkgo/sequential + $(GINKGO_CLI) -v --trace --timeout 120m -r ./test/openshift/e2e/ginkgo/sequential .PHONY: e2e-tests-parallel-ginkgo ## Runs kuttl e2e parallel tests, (Defaults to 5 runs at a time) e2e-tests-parallel-ginkgo: ginkgo diff --git a/test/openshift/e2e/ginkgo/sequential/1-113_validate_namespacemanagement_test.go b/test/openshift/e2e/ginkgo/sequential/1-113_validate_namespacemanagement_test.go index 1dd816b8c83..62b093576f3 100644 --- a/test/openshift/e2e/ginkgo/sequential/1-113_validate_namespacemanagement_test.go +++ b/test/openshift/e2e/ginkgo/sequential/1-113_validate_namespacemanagement_test.go @@ -208,7 +208,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { verifyNamespaceManagementSecretAndApplication(argoCD, nsCustom, true, []string{argoCD.Namespace, nsCustom.Name}) }) - It("should not create roles when namespaceManagement env var is not set", func() { + It("should not create Roles/RoleBindings when namespaceManagement env var is not set", func() { if fixture.EnvLocalRun() { Skip("This test modifies the Subscription/operator deployment env vars, which requires the operator be running on the cluster.") return @@ -219,9 +219,6 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { {Name: nsCustom.Name, AllowManagedBy: true}, }) - By("Enabling namespaceManagement via env var") - fixture.SetEnvInOperatorSubscriptionOrDeployment("ALLOW_NAMESPACE_MANAGEMENT_IN_NAMESPACE_SCOPED_INSTANCES", "false") - By("Create namespaceManagement CR with the namespace which needs to be managed") nm := argov1beta1api.NamespaceManagement{ ObjectMeta: metav1.ObjectMeta{Name: nmName, Namespace: nsCustom.Name}, @@ -236,7 +233,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { verifyNamespaceManagementSecretAndApplication(argoCD, nsCustom, false, []string{}) }) - It("should delete Roles/RoleBindings when namespace management is disabled from ArgoCD NamespaceManagement field", func() { + It("Should not create Roles/RoleBindings when namespaceManagement is disabled via the ArgoCD NamespaceManagement.AllowManagedBy field.", func() { if fixture.EnvLocalRun() { Skip("This test modifies the Subscription/operator deployment env vars, which requires the operator be running on the cluster.") return @@ -257,7 +254,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { } Expect(k8sClient.Create(ctx, &nsm)).To(Succeed()) - By("Verify Roles/RoleBindings are deleted from managed namespace") + By("Verify Roles/RoleBindings are not created for managed namespace") checkRolesBindings(nsCustom.Name, false) By("Verify Application and Secret of managed namespace") @@ -303,6 +300,21 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { By("Verify Application and Secret of managed namespace test-second-nms") verifyNamespaceManagementSecretAndApplication(argoCD, targetNs, true, []string{argoCD.Namespace, nsCustom.Name, targetNs.Name}) + + By("Create a namespace that does NOT match glob pattern") + unmanagedNs, cleanupFunc4 := fixture.CreateNamespaceWithCleanupFunc("unmanaged-ns") + defer cleanupFunc4() + + By("Create namespaceManagement CR in unmanaged namespace (no match expected)") + nsm2 := argov1beta1api.NamespaceManagement{ + ObjectMeta: metav1.ObjectMeta{Name: "nm-unmanaged", Namespace: unmanagedNs.Name}, + Spec: argov1beta1api.NamespaceManagementSpec{ManagedBy: randomNS.Name}, + } + Expect(k8sClient.Create(ctx, &nsm2)).To(Succeed()) + + By("Verify Roles/RoleBindings are NOT created for unmanaged namespace") + checkRolesBindings(unmanagedNs.Name, false) // should NOT match pattern + }) It("should clean up Roles/Rolebindings when NamespaceManagement is removed from ArgoCD", func() { @@ -326,25 +338,25 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { } Expect(k8sClient.Create(ctx, &nsm)).To(Succeed()) - By("Role/Rolebindings should be created for managed namespace if namespaceManagement CR is present") + By("Roles/Rolebindings should be created for managed namespace if namespaceManagement CR is present") checkRolesBindings(nsCustom.Name, true) - By("Remove NamespaceManagement to check cleanup of Roles/Rolebindings") + By("Remove NamespaceManagement from ArgoCD to check cleanup of Roles/Rolebindings") Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(argoCD), argoCD)).To(Succeed()) - argoCD.Spec.NamespaceManagement = nil - Expect(k8sClient.Update(ctx, argoCD)).To(Succeed()) + k8sFixture.Update(argoCD, func(obj client.Object) { + argoCDObj, ok := obj.(*argov1beta1api.ArgoCD) + Expect(ok).To(BeTrue()) + argoCDObj.Spec.NamespaceManagement = nil + }) By("Verify Roles/RoleBindings are deleted from managed namespace") - Eventually(func() bool { - checkRolesBindings(nsCustom.Name, false) - return true - }, "2m", "5s").Should(BeTrue()) + checkRolesBindings(nsCustom.Name, false) By("Verify Application and Secret of managed namespace when nm is disabled") verifyNamespaceManagementSecretAndApplication(argoCD, nsCustom, false, []string{argoCD.Namespace, nsCustom.Name}) }) - It("should not create roles when ArgoCD CR has no managedBy entry", func() { + It("should not create Roles/RoleBindings when ArgoCD CR has no namespaceManagement field", func() { if fixture.EnvLocalRun() { Skip("This test modifies the Subscription/operator deployment env vars, which requires the operator be running on the cluster.") return @@ -356,7 +368,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { By("enabling namespace management via env var") fixture.SetEnvInOperatorSubscriptionOrDeployment("ALLOW_NAMESPACE_MANAGEMENT_IN_NAMESPACE_SCOPED_INSTANCES", "true") - By("Verify Roles/RoleBindings are deleted from managed namespace") + By("Verify Roles/RoleBindings are not created from managed namespace") checkRolesBindings(nsCustom.Name, false) By("Verify Application and Secret of managed namespace when nm is not present in ArgoCD") @@ -412,5 +424,49 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() { By("Verify Application should not be able to sync to managed namespace when env var is false") verifyNamespaceManagementSecretAndApplication(argoCD, nsCustom, false, []string{argoCD.Namespace, nsCustom.Name}) }) + + It("should create Roles/RoleBindings when AllowManagedBy is true and remove them when false", func() { + if fixture.EnvLocalRun() { + Skip("This test modifies the Subscription/operator deployment env vars, which requires the operator be running on the cluster.") + return + } + + By("Enabling namespaceManagement via env var") + fixture.SetEnvInOperatorSubscriptionOrDeployment("ALLOW_NAMESPACE_MANAGEMENT_IN_NAMESPACE_SCOPED_INSTANCES", "true") + + By("Create ArgoCD with namespaceManagement field set and AllowManagedBy field is true") + argoCD := deployArgoCD(randomNS.Name, []argov1beta1api.ManagedNamespaces{ + {Name: nsCustom.Name, AllowManagedBy: true}, + }) + + By("Create namespaceManagement CR with the namespace to be managed") + nm := argov1beta1api.NamespaceManagement{ + ObjectMeta: metav1.ObjectMeta{Name: nmName, Namespace: nsCustom.Name}, + Spec: argov1beta1api.NamespaceManagementSpec{ManagedBy: randomNS.Name}, + } + Expect(k8sClient.Create(ctx, &nm)).To(Succeed()) + + By("Verify Roles/RoleBindings are created for managed namespace") + checkRolesBindings(nsCustom.Name, true) + + By("Verify Application and Secret of managed namespace") + verifyNamespaceManagementSecretAndApplication(argoCD, nsCustom, true, []string{argoCD.Namespace, nsCustom.Name}) + + By("Update ArgoCD to set AllowManagedBy to false") + Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(argoCD), argoCD)).To(Succeed()) + k8sFixture.Update(argoCD, func(obj client.Object) { + argoCDObj, ok := obj.(*argov1beta1api.ArgoCD) + Expect(ok).To(BeTrue()) + argoCDObj.Spec.NamespaceManagement = []argov1beta1api.ManagedNamespaces{ + {Name: nsCustom.Name, AllowManagedBy: false}, + } + }) + + By("Verify Roles/RoleBindings are NOT created for managed namespace") + checkRolesBindings(nsCustom.Name, false) + + By("Verify Application and Secret of managed namespace when AllowManagedBy field is false") + verifyNamespaceManagementSecretAndApplication(argoCD, nsCustom, false, []string{argoCD.Namespace, nsCustom.Name}) + }) }) })