Repository: kubernetes-sigs/kueue

Issue:
Enable e2e testing  in a user opt-in namespace
<!-- Please only use this template for submitting clean up requests -->

**What would you like to be cleaned**:

Currently, Kueue’s e2e tests are hardcoded to run in the `kueue-system` namespace, limiting flexibility for users/downstream contributors, who may want to test in other namespaces. There should be a mechanism to allow e2e tests to run in any namespace by providing a configuration option to specify a namespace.

**Why is this needed**:

This change would enhance usability and adaptability of the e2e testing in the downstream forks.

Discussion:
@sohankunkerkar: /assign sohankunkerkar@mimowo: +1, you can also consider using the customconfigs suite for that, if the main one is problematic.@k8s-triage-robot: The Kubernetes project currently lacks enough contributors to adequately respond to all issues.

This bot triages un-triaged issues according to the following rules:
- After 90d of inactivity, `lifecycle/stale` is applied
- After 30d of inactivity since `lifecycle/stale` was applied, `lifecycle/rotten` is applied
- After 30d of inactivity since `lifecycle/rotten` was applied, the issue is closed

You can:
- Mark this issue as fresh with `/remove-lifecycle stale`
- Close this issue with `/close`
- Offer to help out with [Issue Triage][1]

Please send feedback to sig-contributor-experience at [kubernetes/community](https://github.com/kubernetes/community).

/lifecycle stale

[1]: https://www.kubernetes.dev/docs/guide/issue-triage/@sohankunkerkar: /remove-lifecycle stale

Solution patch:
diff --git a/hack/e2e-common.sh b/hack/e2e-common.sh
index 05c919056..3aa4de454 100644
--- a/hack/e2e-common.sh
+++ b/hack/e2e-common.sh
@@ -18,6 +18,7 @@ export KUSTOMIZE="$ROOT_DIR"/bin/kustomize
 export GINKGO="$ROOT_DIR"/bin/ginkgo
 export KIND="$ROOT_DIR"/bin/kind
 export YQ="$ROOT_DIR"/bin/yq
+export KUEUE_NAMESPACE="${KUEUE_NAMESPACE:-kueue-system}"
 
 export KIND_VERSION="${E2E_KIND_VERSION/"kindest/node:v"/}"
 
@@ -207,8 +208,10 @@ function deploy_with_certmanager() {
         $KUSTOMIZE edit add patch --path "validating_webhookcainjection_patch.yaml"
         $KUSTOMIZE edit add patch --path "cert_metrics_manager_patch.yaml" --kind Deployment
         
-        $KUSTOMIZE build "${ROOT_DIR}/test/e2e/config/certmanager" | \
-        kubectl apply --kubeconfig="$1" --server-side -f -
+        local build_output
+        build_output=$($KUSTOMIZE build "${ROOT_DIR}/test/e2e/config/certmanager")
+        build_output="${build_output//kueue-system/$KUEUE_NAMESPACE}"
+        echo "$build_output" | kubectl apply --kubeconfig="$1" --server-side -f -
     )
 
     printf "%s\n" "$crd_backup" > "$crd_kust"
@@ -224,7 +227,10 @@ function cluster_kueue_deploy {
         
         deploy_with_certmanager "$1"
     else
-        kubectl apply --kubeconfig="$1" --server-side -k "${ROOT_DIR}/test/e2e/config/default"
+        local build_output
+        build_output=$($KUSTOMIZE build "${ROOT_DIR}/test/e2e/config/default")
+        build_output="${build_output//kueue-system/$KUEUE_NAMESPACE}"
+        echo "$build_output" | kubectl apply --kubeconfig="$1" --server-side -f -
     fi
 }
 
diff --git a/hack/e2e-kueueviz-backend.sh b/hack/e2e-kueueviz-backend.sh
index 5d32ff77c..d0f0725fb 100755
--- a/hack/e2e-kueueviz-backend.sh
+++ b/hack/e2e-kueueviz-backend.sh
@@ -46,7 +46,7 @@ prepare_docker_images
 cluster_kind_load "${KIND_CLUSTER_NAME}"
 (cd config/components/manager && $KUSTOMIZE edit set image controller="$IMAGE_TAG")
 cluster_kueue_deploy ""
-kubectl wait deploy/kueue-controller-manager -nkueue-system --for=condition=available --timeout=5m
+kubectl wait deploy/kueue-controller-manager -n"$KUEUE_NAMESPACE" --for=condition=available --timeout=5m
 
 # Deploy KueueViz resources
 kubectl create -f "${ROOT_DIR}/cmd/kueueviz/examples/"
diff --git a/hack/e2e-kueueviz-local.sh b/hack/e2e-kueueviz-local.sh
index 68673d5f0..84ae5dda2 100755
--- a/hack/e2e-kueueviz-local.sh
+++ b/hack/e2e-kueueviz-local.sh
@@ -38,7 +38,7 @@ prepare_docker_images
 cluster_kind_load "${KIND_CLUSTER_NAME}"
 (cd config/components/manager && $KUSTOMIZE edit set image controller="$IMAGE_TAG")
 cluster_kueue_deploy ""
-kubectl wait deploy/kueue-controller-manager -nkueue-system --for=condition=available --timeout=5m
+kubectl wait deploy/kueue-controller-manager -n"$KUEUE_NAMESPACE" --for=condition=available --timeout=5m
 
 # Deploy kueueviz resources
 kubectl create -f "${ROOT_DIR}/cmd/kueueviz/examples/"



Test patch:
diff --git a/pkg/scheduler/scheduler_test.go b/pkg/scheduler/scheduler_test.go
index 24616ccb7..7d733ab47 100644
--- a/pkg/scheduler/scheduler_test.go
+++ b/pkg/scheduler/scheduler_test.go
@@ -3630,22 +3630,6 @@ func TestLastSchedulingContext(t *testing.T) {
 		utiltesting.MakeResourceFlavor("on-demand").Obj(),
 		utiltesting.MakeResourceFlavor("spot").Obj(),
 	}
-	clusterQueue := []kueue.ClusterQueue{
-		*utiltesting.MakeClusterQueue("eng-alpha").
-			QueueingStrategy(kueue.BestEffortFIFO).
-			Preemption(kueue.ClusterQueuePreemption{
-				WithinClusterQueue: kueue.PreemptionPolicyLowerPriority,
-			}).
-			FlavorFungibility(kueue.FlavorFungibility{
-				WhenCanPreempt: kueue.Preempt,
-			}).
-			ResourceGroup(
-				*utiltesting.MakeFlavorQuotas("on-demand").
-					Resource(corev1.ResourceCPU, "50", "50").Obj(),
-				*utiltesting.MakeFlavorQuotas("spot").
-					Resource(corev1.ResourceCPU, "100", "0").Obj(),
-			).Obj(),
-	}
 	clusterQueueCohort := []kueue.ClusterQueue{
 		*utiltesting.MakeClusterQueue("eng-cohort-alpha").
 			Cohort("cohort").
@@ -3738,12 +3722,6 @@ func TestLastSchedulingContext(t *testing.T) {
 			},
 		},
 	}
-	wl := utiltesting.MakeWorkload("low-1", "default").
-		Queue("main").
-		Request(corev1.ResourceCPU, "50").
-		ReserveQuota(utiltesting.MakeAdmission("eng-alpha").Assignment(corev1.ResourceCPU, "on-demand", "50").Obj()).
-		Admitted(true).
-		Obj()
 	cases := []struct {
 		name                           string
 		cqs                            []kueue.ClusterQueue
@@ -3756,9 +3734,29 @@ func TestLastSchedulingContext(t *testing.T) {
 	}{
 		{
 			name: "scheduling context not changed: use next flavor if can't preempt",
-			cqs:  clusterQueue,
+			cqs: []kueue.ClusterQueue{
+				*utiltesting.MakeClusterQueue("eng-alpha").
+					QueueingStrategy(kueue.BestEffortFIFO).
+					Preemption(kueue.ClusterQueuePreemption{
+						WithinClusterQueue: kueue.PreemptionPolicyLowerPriority,
+					}).
+					FlavorFungibility(kueue.FlavorFungibility{
+						WhenCanPreempt: kueue.Preempt,
+					}).
+					ResourceGroup(
+						*utiltesting.MakeFlavorQuotas("on-demand").
+							Resource(corev1.ResourceCPU, "50", "50").Obj(),
+						*utiltesting.MakeFlavorQuotas("spot").
+							Resource(corev1.ResourceCPU, "100", "0").Obj(),
+					).Obj(),
+			},
 			admittedWorkloads: []kueue.Workload{
-				*wl,
+				utiltesting.MakeWorkload("low-1", "default").
+					Queue("main").
+					Request(corev1.ResourceCPU, "50").
+					ReserveQuota(utiltesting.MakeAdmission("eng-alpha").Assignment(corev1.ResourceCPU, "on-demand", "50").Obj()).
+					Admitted(true).
+					Workload,
 			},
 			workloads: []kueue.Workload{
 				*utiltesting.MakeWorkload("new", "default").
@@ -3776,9 +3774,29 @@ func TestLastSchedulingContext(t *testing.T) {
 		},
 		{
 			name: "some workloads were deleted",
-			cqs:  clusterQueue,
+			cqs: []kueue.ClusterQueue{
+				*utiltesting.MakeClusterQueue("eng-alpha").
+					QueueingStrategy(kueue.BestEffortFIFO).
+					Preemption(kueue.ClusterQueuePreemption{
+						WithinClusterQueue: kueue.PreemptionPolicyLowerPriority,
+					}).
+					FlavorFungibility(kueue.FlavorFungibility{
+						WhenCanPreempt: kueue.Preempt,
+					}).
+					ResourceGroup(
+						*utiltesting.MakeFlavorQuotas("on-demand").
+							Resource(corev1.ResourceCPU, "50", "50").Obj(),
+						*utiltesting.MakeFlavorQuotas("spot").
+							Resource(corev1.ResourceCPU, "100", "0").Obj(),
+					).Obj(),
+			},
 			admittedWorkloads: []kueue.Workload{
-				*wl,
+				utiltesting.MakeWorkload("low-1", "default").
+					Queue("main").
+					Request(corev1.ResourceCPU, "50").
+					ReserveQuota(utiltesting.MakeAdmission("eng-alpha").Assignment(corev1.ResourceCPU, "on-demand", "50").Obj()).
+					Admitted(true).
+					Workload,
 			},
 			workloads: []kueue.Workload{
 				*utiltesting.MakeWorkload("preemptor", "default").
@@ -3787,7 +3805,12 @@ func TestLastSchedulingContext(t *testing.T) {
 					Obj(),
 			},
 			deleteWorkloads: []kueue.Workload{
-				*wl,
+				utiltesting.MakeWorkload("low-1", "default").
+					Queue("main").
+					Request(corev1.ResourceCPU, "50").
+					ReserveQuota(utiltesting.MakeAdmission("eng-alpha").Assignment(corev1.ResourceCPU, "on-demand", "50").Obj()).
+					Admitted(true).
+					Workload,
 			},
 			wantPreempted:                 sets.Set[workload.Reference]{},
 			wantAdmissionsOnFirstSchedule: map[workload.Reference]kueue.Admission{},
diff --git a/test/e2e/certmanager/metrics_test.go b/test/e2e/certmanager/metrics_test.go
index c1f530408..16ee92ff0 100644
--- a/test/e2e/certmanager/metrics_test.go
+++ b/test/e2e/certmanager/metrics_test.go
@@ -26,7 +26,6 @@ import (
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 
-	config "sigs.k8s.io/kueue/apis/config/v1beta1"
 	"sigs.k8s.io/kueue/apis/kueue/v1beta1"
 	utiltesting "sigs.k8s.io/kueue/pkg/util/testing"
 	testingjobspod "sigs.k8s.io/kueue/pkg/util/testingjobs/pod"
@@ -64,7 +63,7 @@ var _ = ginkgo.Describe("Metrics", ginkgo.Ordered, func() {
 				{
 					Kind:      "ServiceAccount",
 					Name:      serviceAccountName,
-					Namespace: config.DefaultNamespace,
+					Namespace: kueueNS,
 				},
 			},
 			RoleRef: rbacv1.RoleRef{
@@ -75,7 +74,7 @@ var _ = ginkgo.Describe("Metrics", ginkgo.Ordered, func() {
 		}
 		gomega.Expect(k8sClient.Create(ctx, metricsReaderClusterRoleBinding)).Should(gomega.Succeed())
 
-		curlPod = testingjobspod.MakePod("curl-metrics", config.DefaultNamespace).
+		curlPod = testingjobspod.MakePod("curl-metrics", kueueNS).
 			ServiceAccountName(serviceAccountName).
 			Image(util.E2eTestAgnHostImage, util.BehaviorWaitForDeletion).
 			TerminationGracePeriod(1).
@@ -106,7 +105,7 @@ var _ = ginkgo.Describe("Metrics", ginkgo.Ordered, func() {
 			gomega.Eventually(func(g gomega.Gomega) {
 				secret := &corev1.Secret{}
 				g.Expect(k8sClient.Get(ctx, client.ObjectKey{
-					Namespace: config.DefaultNamespace,
+					Namespace: kueueNS,
 					Name:      certSecretName,
 				}, secret)).To(gomega.Succeed())
 			}, util.Timeout, util.Interval).Should(gomega.Succeed())
@@ -186,14 +185,14 @@ var _ = ginkgo.Describe("Metrics", ginkgo.Ordered, func() {
 })
 
 func getKueueMetricsSecure(curlPodName, curlContainerName string) ([]byte, error) {
-	metricsOutput, _, err := util.KExecute(ctx, cfg, restClient, config.DefaultNamespace, curlPodName, curlContainerName,
+	metricsOutput, _, err := util.KExecute(ctx, cfg, restClient, kueueNS, curlPodName, curlContainerName,
 		[]string{
 			"/bin/sh", "-c",
 			fmt.Sprintf(
 				"curl -s --cacert %s/ca.crt -H \"Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)\" https://%s.%s.svc.cluster.local:8443/metrics",
 				certMountPath,
 				metricsServiceName,
-				config.DefaultNamespace,
+				kueueNS,
 			),
 		})
 
diff --git a/test/e2e/certmanager/suite_test.go b/test/e2e/certmanager/suite_test.go
index e2513ad4a..0ec66cef3 100644
--- a/test/e2e/certmanager/suite_test.go
+++ b/test/e2e/certmanager/suite_test.go
@@ -38,6 +38,7 @@ var (
 	defaultKueueCfg *v1beta1.Configuration
 	cfg             *rest.Config
 	restClient      *rest.RESTClient
+	kueueNS         = util.GetKueueNamespace()
 )
 
 func TestAPIs(t *testing.T) {
diff --git a/test/e2e/customconfigs/suite_test.go b/test/e2e/customconfigs/suite_test.go
index 3dc72c2c0..29deb4aab 100644
--- a/test/e2e/customconfigs/suite_test.go
+++ b/test/e2e/customconfigs/suite_test.go
@@ -38,6 +38,7 @@ var (
 	restClient      *rest.RESTClient
 	ctx             context.Context
 	defaultKueueCfg *v1beta1.Configuration
+	kueueNS         = util.GetKueueNamespace()
 )
 
 func TestAPIs(t *testing.T) {
diff --git a/test/e2e/customconfigs/waitforpodsready_test.go b/test/e2e/customconfigs/waitforpodsready_test.go
index fd3415a77..c673b862f 100644
--- a/test/e2e/customconfigs/waitforpodsready_test.go
+++ b/test/e2e/customconfigs/waitforpodsready_test.go
@@ -64,7 +64,7 @@ var _ = ginkgo.Describe("WaitForPodsReady with tiny Timeout and no RecoveryTimeo
 				{
 					Kind:      "ServiceAccount",
 					Name:      serviceAccountName,
-					Namespace: configapi.DefaultNamespace,
+					Namespace: kueueNS,
 				},
 			},
 			RoleRef: rbacv1.RoleRef{
diff --git a/test/e2e/multikueue/e2e_test.go b/test/e2e/multikueue/e2e_test.go
index 68abd0995..8fb88cd91 100644
--- a/test/e2e/multikueue/e2e_test.go
+++ b/test/e2e/multikueue/e2e_test.go
@@ -911,7 +911,7 @@ var _ = ginkgo.Describe("MultiKueue", func() {
 				gomega.Expect(err).NotTo(gomega.HaveOccurred(), "%s: %s", err, output)
 
 				podList := &corev1.PodList{}
-				podListOptions := client.InNamespace("kueue-system")
+				podListOptions := client.InNamespace(kueueNS)
 				gomega.Eventually(func(g gomega.Gomega) {
 					g.Expect(k8sWorker1Client.List(ctx, podList, podListOptions)).Should(gomega.Succeed())
 				}, util.LongTimeout, util.Interval).ShouldNot(gomega.Succeed())
diff --git a/test/e2e/multikueue/suite_test.go b/test/e2e/multikueue/suite_test.go
index 318969306..ff4d8c846 100644
--- a/test/e2e/multikueue/suite_test.go
+++ b/test/e2e/multikueue/suite_test.go
@@ -53,6 +53,7 @@ var (
 	managerClusterName string
 	worker1ClusterName string
 	worker2ClusterName string
+	kueueNS            = util.GetKueueNamespace()
 
 	k8sManagerClient client.Client
 	k8sWorker1Client client.Client
@@ -271,13 +272,13 @@ var _ = ginkgo.BeforeSuite(func() {
 
 	ctx = ginkgo.GinkgoT().Context()
 
-	worker1Kconfig, err := kubeconfigForMultiKueueSA(ctx, k8sWorker1Client, worker1Cfg, "kueue-system", "mksa", worker1ClusterName)
+	worker1Kconfig, err := kubeconfigForMultiKueueSA(ctx, k8sWorker1Client, worker1Cfg, kueueNS, "mksa", worker1ClusterName)
 	gomega.Expect(err).NotTo(gomega.HaveOccurred())
-	gomega.Expect(makeMultiKueueSecret(ctx, k8sManagerClient, "kueue-system", "multikueue1", worker1Kconfig)).To(gomega.Succeed())
+	gomega.Expect(makeMultiKueueSecret(ctx, k8sManagerClient, kueueNS, "multikueue1", worker1Kconfig)).To(gomega.Succeed())
 
-	worker2Kconfig, err := kubeconfigForMultiKueueSA(ctx, k8sWorker2Client, worker2Cfg, "kueue-system", "mksa", worker2ClusterName)
+	worker2Kconfig, err := kubeconfigForMultiKueueSA(ctx, k8sWorker2Client, worker2Cfg, kueueNS, "mksa", worker2ClusterName)
 	gomega.Expect(err).NotTo(gomega.HaveOccurred())
-	gomega.Expect(makeMultiKueueSecret(ctx, k8sManagerClient, "kueue-system", "multikueue2", worker2Kconfig)).To(gomega.Succeed())
+	gomega.Expect(makeMultiKueueSecret(ctx, k8sManagerClient, kueueNS, "multikueue2", worker2Kconfig)).To(gomega.Succeed())
 
 	waitForAvailableStart := time.Now()
 	util.WaitForKueueAvailability(ctx, k8sManagerClient)
@@ -314,9 +315,9 @@ var _ = ginkgo.BeforeSuite(func() {
 })
 
 var _ = ginkgo.AfterSuite(func() {
-	gomega.Expect(cleanKubeconfigForMultiKueueSA(ctx, k8sWorker1Client, "kueue-system", "mksa")).To(gomega.Succeed())
-	gomega.Expect(cleanKubeconfigForMultiKueueSA(ctx, k8sWorker2Client, "kueue-system", "mksa")).To(gomega.Succeed())
+	gomega.Expect(cleanKubeconfigForMultiKueueSA(ctx, k8sWorker1Client, kueueNS, "mksa")).To(gomega.Succeed())
+	gomega.Expect(cleanKubeconfigForMultiKueueSA(ctx, k8sWorker2Client, kueueNS, "mksa")).To(gomega.Succeed())
 
-	gomega.Expect(cleanMultiKueueSecret(ctx, k8sManagerClient, "kueue-system", "multikueue1")).To(gomega.Succeed())
-	gomega.Expect(cleanMultiKueueSecret(ctx, k8sManagerClient, "kueue-system", "multikueue2")).To(gomega.Succeed())
+	gomega.Expect(cleanMultiKueueSecret(ctx, k8sManagerClient, kueueNS, "multikueue1")).To(gomega.Succeed())
+	gomega.Expect(cleanMultiKueueSecret(ctx, k8sManagerClient, kueueNS, "multikueue2")).To(gomega.Succeed())
 })
diff --git a/test/e2e/singlecluster/metrics_test.go b/test/e2e/singlecluster/metrics_test.go
index e4e90f843..15e751b78 100644
--- a/test/e2e/singlecluster/metrics_test.go
+++ b/test/e2e/singlecluster/metrics_test.go
@@ -28,7 +28,6 @@ import (
 	"k8s.io/utils/ptr"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 
-	config "sigs.k8s.io/kueue/apis/config/v1beta1"
 	"sigs.k8s.io/kueue/apis/kueue/v1beta1"
 	"sigs.k8s.io/kueue/pkg/controller/jobs/job"
 	utiltesting "sigs.k8s.io/kueue/pkg/util/testing"
@@ -66,7 +65,7 @@ var _ = ginkgo.Describe("Metrics", func() {
 				{
 					Kind:      "ServiceAccount",
 					Name:      serviceAccountName,
-					Namespace: config.DefaultNamespace,
+					Namespace: kueueNS,
 				},
 			},
 			RoleRef: rbacv1.RoleRef{
@@ -77,7 +76,7 @@ var _ = ginkgo.Describe("Metrics", func() {
 		}
 		util.MustCreate(ctx, k8sClient, metricsReaderClusterRoleBinding)
 
-		curlPod = testingjobspod.MakePod("curl-metrics", config.DefaultNamespace).
+		curlPod = testingjobspod.MakePod("curl-metrics", kueueNS).
 			ServiceAccountName(serviceAccountName).
 			Image(util.E2eTestAgnHostImage, util.BehaviorWaitForDeletion).
 			TerminationGracePeriod(1).
diff --git a/test/e2e/singlecluster/suite_test.go b/test/e2e/singlecluster/suite_test.go
index c665cb01a..57554a24c 100644
--- a/test/e2e/singlecluster/suite_test.go
+++ b/test/e2e/singlecluster/suite_test.go
@@ -43,6 +43,7 @@ var (
 	ctx                          context.Context
 	visibilityClient             visibilityv1beta1.VisibilityV1beta1Interface
 	impersonatedVisibilityClient visibilityv1beta1.VisibilityV1beta1Interface
+	kueueNS                      = util.GetKueueNamespace()
 )
 
 func TestAPIs(t *testing.T) {
@@ -62,7 +63,7 @@ var _ = ginkgo.BeforeSuite(func() {
 	k8sClient, cfg = util.CreateClientUsingCluster("")
 	restClient = util.CreateRestClient(cfg)
 	visibilityClient = util.CreateVisibilityClient("")
-	impersonatedVisibilityClient = util.CreateVisibilityClient("system:serviceaccount:kueue-system:default")
+	impersonatedVisibilityClient = util.CreateVisibilityClient(fmt.Sprintf("system:serviceaccount:%s:default", kueueNS))
 	ctx = ginkgo.GinkgoT().Context()
 
 	waitForAvailableStart := time.Now()
diff --git a/test/e2e/singlecluster/visibility_test.go b/test/e2e/singlecluster/visibility_test.go
index 6fa701e27..e54e627c6 100644
--- a/test/e2e/singlecluster/visibility_test.go
+++ b/test/e2e/singlecluster/visibility_test.go
@@ -487,7 +487,7 @@ var _ = ginkgo.Describe("Kueue visibility server", func() {
 				ObjectMeta: metav1.ObjectMeta{Name: "read-pending-workloads"},
 				RoleRef:    rbacv1.RoleRef{APIGroup: rbacv1.GroupName, Kind: "ClusterRole", Name: "kueue-batch-admin-role"},
 				Subjects: []rbacv1.Subject{
-					{Name: "default", APIGroup: "", Namespace: "kueue-system", Kind: rbacv1.ServiceAccountKind},
+					{Name: "default", APIGroup: "", Namespace: kueueNS, Kind: rbacv1.ServiceAccountKind},
 				},
 			}
 			util.MustCreate(ctx, k8sClient, clusterRoleBinding)
@@ -523,7 +523,7 @@ var _ = ginkgo.Describe("Kueue visibility server", func() {
 				ObjectMeta: metav1.ObjectMeta{Name: "read-pending-workloads", Namespace: nsA.Name},
 				RoleRef:    rbacv1.RoleRef{APIGroup: rbacv1.GroupName, Kind: "ClusterRole", Name: "kueue-batch-user-role"},
 				Subjects: []rbacv1.Subject{
-					{Name: "default", APIGroup: "", Namespace: "kueue-system", Kind: rbacv1.ServiceAccountKind},
+					{Name: "default", APIGroup: "", Namespace: kueueNS, Kind: rbacv1.ServiceAccountKind},
 				},
 			}
 			util.MustCreate(ctx, k8sClient, roleBinding)
diff --git a/test/util/e2e.go b/test/util/e2e.go
index 81f687b06..4162fc990 100644
--- a/test/util/e2e.go
+++ b/test/util/e2e.go
@@ -62,6 +62,13 @@ const (
 	defaultMetricsServiceName = "kueue-controller-manager-metrics-service"
 )
 
+func GetKueueNamespace() string {
+	if ns := os.Getenv("KUEUE_NAMESPACE"); ns != "" {
+		return ns
+	}
+	return configapi.DefaultNamespace
+}
+
 func CreateClientUsingCluster(kContext string) (client.WithWatch, *rest.Config) {
 	cfg, err := config.GetConfigWithContext(kContext)
 	if err != nil {
@@ -215,7 +222,8 @@ func waitForOperatorAvailability(ctx context.Context, k8sClient client.Client, k
 }
 
 func WaitForKueueAvailability(ctx context.Context, k8sClient client.Client) {
-	kcmKey := types.NamespacedName{Namespace: "kueue-system", Name: "kueue-controller-manager"}
+	kueueNS := GetKueueNamespace()
+	kcmKey := types.NamespacedName{Namespace: kueueNS, Name: "kueue-controller-manager"}
 	waitForOperatorAvailability(ctx, k8sClient, kcmKey)
 }
 
@@ -254,7 +262,8 @@ func WaitForKubeRayOperatorAvailability(ctx context.Context, k8sClient client.Cl
 
 func GetKueueConfiguration(ctx context.Context, k8sClient client.Client) *configapi.Configuration {
 	var kueueCfg configapi.Configuration
-	kcmKey := types.NamespacedName{Namespace: "kueue-system", Name: "kueue-manager-config"}
+	kueueNS := GetKueueNamespace()
+	kcmKey := types.NamespacedName{Namespace: kueueNS, Name: "kueue-manager-config"}
 	configMap := &corev1.ConfigMap{}
 
 	gomega.Expect(k8sClient.Get(ctx, kcmKey, configMap)).To(gomega.Succeed())
@@ -264,7 +273,8 @@ func GetKueueConfiguration(ctx context.Context, k8sClient client.Client) *config
 
 func ApplyKueueConfiguration(ctx context.Context, k8sClient client.Client, kueueCfg *configapi.Configuration) {
 	configMap := &corev1.ConfigMap{}
-	kcmKey := types.NamespacedName{Namespace: "kueue-system", Name: "kueue-manager-config"}
+	kueueNS := GetKueueNamespace()
+	kcmKey := types.NamespacedName{Namespace: kueueNS, Name: "kueue-manager-config"}
 	config, err := yaml.Marshal(kueueCfg)
 
 	gomega.Expect(err).ToNot(gomega.HaveOccurred())
@@ -276,7 +286,8 @@ func ApplyKueueConfiguration(ctx context.Context, k8sClient client.Client, kueue
 }
 
 func RestartKueueController(ctx context.Context, k8sClient client.Client) {
-	kcmKey := types.NamespacedName{Namespace: "kueue-system", Name: "kueue-controller-manager"}
+	kueueNS := GetKueueNamespace()
+	kcmKey := types.NamespacedName{Namespace: kueueNS, Name: "kueue-controller-manager"}
 	rolloutOperatorDeployment(ctx, k8sClient, kcmKey)
 }
 
@@ -338,11 +349,12 @@ func CreateNamespaceFromObjectWithLog(ctx context.Context, k8sClient client.Clie
 }
 
 func GetKueueMetrics(ctx context.Context, cfg *rest.Config, restClient *rest.RESTClient, curlPodName, curlContainerName string) (string, error) {
-	metricsOutput, _, err := KExecute(ctx, cfg, restClient, configapi.DefaultNamespace, curlPodName, curlContainerName, []string{
+	kueueNS := GetKueueNamespace()
+	metricsOutput, _, err := KExecute(ctx, cfg, restClient, kueueNS, curlPodName, curlContainerName, []string{
 		"/bin/sh", "-c",
 		fmt.Sprintf(
 			"curl -s -k -H \"Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)\" https://%s.%s.svc.cluster.local:8443/metrics",
-			defaultMetricsServiceName, configapi.DefaultNamespace,
+			defaultMetricsServiceName, kueueNS,
 		),
 	})
 	return string(metricsOutput), err