From b7a9ea8977882381bff2a4ea38ff9563e3675493 Mon Sep 17 00:00:00 2001 From: midays Date: Wed, 24 Jun 2026 11:18:39 +0300 Subject: [PATCH 1/3] Enhance e2e test framework with RunAs configuration - Added `RunAs` field to the configuration to allow tests to run with cluster-admin credentials. - Updated `SetupActiveNamespaceAdmin` and `SetupActiveKubectlRunners` functions to utilize the new `RunAs` configuration for managing namespace access. - Refactored multiple test cases to replace direct calls to `SetupNamespaceAdminUsersForScenario` with `SetupActiveKubectlRunners`, streamlining the process for both admin and non-admin contexts. - Removed redundant context checks in tests, simplifying the setup process. This change improves flexibility in test execution and aligns with the new configuration structure. Signed-off-by: midays --- e2e-tests/config/config.go | 1 + e2e-tests/framework/rbac.go | 41 +++++++++++++++++++ e2e-tests/framework/scenario.go | 19 ++++++--- e2e-tests/tests/tier0/e2e_suite_test.go | 1 + .../tier0/mta_804_empty_pvc_migration_test.go | 8 +--- e2e-tests/tests/tier0/mta_805_sets_test.go | 8 +--- .../tier0/mta_806_pvc_data_integrity_test.go | 8 +--- .../tier0/mta_807_data_validation_test.go | 8 +--- .../tests/tier0/mta_809_initcontainer_test.go | 8 +--- .../tests/tier0/mta_810_configmap_test.go | 8 +--- .../tier0/mta_811_mongodb_non_admin_test.go | 8 +--- .../tier0/mta_812_role_migration_test.go | 8 +--- .../tests/tier0/mta_813_cronJob_PVC_test.go | 8 +--- ...ta_827_custom_transformation_stage_test.go | 10 +---- ...ta_828_instructions_file_migration_test.go | 8 +--- ...idate_compatible_resources_offline_test.go | 8 +--- .../mta_833_compatible_resources_live_test.go | 8 +--- ..._844_validate_mixed_resources_live_test.go | 8 +--- ...5_validate_mixed_resources_offline_test.go | 8 +--- ...ate_single_incompatible_route_live_test.go | 3 -- e2e-tests/tests/tier1/e2e_suite_test.go | 1 + ...validate_alternative_gv_suggestion_test.go | 8 +--- ..._instructions_file_force_reconcile_test.go | 8 +--- ..._alternative_gv_suggestion_offline_test.go | 8 +--- ...alidate_core_group_omitted_offline_test.go | 8 +--- .../mta_850_validate_duplicate_gvk_test.go | 3 -- 26 files changed, 78 insertions(+), 145 deletions(-) diff --git a/e2e-tests/config/config.go b/e2e-tests/config/config.go index 54c29651..a2bd79c9 100644 --- a/e2e-tests/config/config.go +++ b/e2e-tests/config/config.go @@ -9,4 +9,5 @@ var ( SourceNonAdminContext string TargetNonAdminContext string InsecureSkipTLSVerify bool + RunAs string ) \ No newline at end of file diff --git a/e2e-tests/framework/rbac.go b/e2e-tests/framework/rbac.go index 6d7774b0..d6873130 100644 --- a/e2e-tests/framework/rbac.go +++ b/e2e-tests/framework/rbac.go @@ -5,6 +5,7 @@ import ( "log" "strings" + "github.com/konveyor/crane/e2e-tests/config" "github.com/konveyor/crane/e2e-tests/utils" ) @@ -108,6 +109,46 @@ func SetupNamespaceAdminUser(adminKubectl KubectlRunner, nonAdminContext, namesp return userKubectl, cleanup, nil } +// SetupActiveNamespaceAdmin sets up namespace-scoped access on a single cluster. +// When config.RunAs == "admin", it creates the namespace with the admin runner and returns +// a no-op cleanup. Otherwise it delegates to SetupNamespaceAdminUser. +func SetupActiveNamespaceAdmin(adminKubectl KubectlRunner, nonAdminContext, namespace string) (KubectlRunner, func(), error) { + if config.RunAs == "admin" { + if err := adminKubectl.CreateNamespace(namespace); err != nil { + return KubectlRunner{}, nil, fmt.Errorf("failed to create namespace %q: %w", namespace, err) + } + return adminKubectl, func() {}, nil + } + return SetupNamespaceAdminUser(adminKubectl, nonAdminContext, namespace) +} + +// SetupActiveKubectlRunners returns kubectl runners appropriate for the current RunAs mode. +// When config.RunAs == "admin", it creates the namespace with admin credentials and returns +// admin runners directly (bypassing RBAC setup). Otherwise it delegates to +// SetupNamespaceAdminUsersForScenario to grant namespace-scoped permissions to the non-admin user. +func SetupActiveKubectlRunners(scenario MigrationScenario, namespace string) (KubectlRunner, KubectlRunner, func(), error) { + if config.RunAs == "admin" { + if srcUser, err := ResolveUsernameForContext(scenario.KubectlSrc.Context); err != nil { + log.Printf("[run-as=admin] source context=%q: could not resolve username: %v", scenario.KubectlSrc.Context, err) + } else { + log.Printf("[run-as=admin] source context=%q running as user=%q", scenario.KubectlSrc.Context, srcUser) + } + if tgtUser, err := ResolveUsernameForContext(scenario.KubectlTgt.Context); err != nil { + log.Printf("[run-as=admin] target context=%q: could not resolve username: %v", scenario.KubectlTgt.Context, err) + } else { + log.Printf("[run-as=admin] target context=%q running as user=%q", scenario.KubectlTgt.Context, tgtUser) + } + if err := scenario.KubectlSrc.CreateNamespace(namespace); err != nil { + return KubectlRunner{}, KubectlRunner{}, nil, fmt.Errorf("failed to create namespace %q on source: %w", namespace, err) + } + if err := scenario.KubectlTgt.CreateNamespace(namespace); err != nil { + return KubectlRunner{}, KubectlRunner{}, nil, fmt.Errorf("failed to create namespace %q on target: %w", namespace, err) + } + return scenario.KubectlSrc, scenario.KubectlTgt, func() {}, nil + } + return SetupNamespaceAdminUsersForScenario(scenario, namespace) +} + // SetupNamespaceAdminUsersForScenario grants namespace-scoped admin permissions // on both source and target clusters for the configured non-admin contexts. // It returns kubectl runners bound to the non-admin contexts and a combined diff --git a/e2e-tests/framework/scenario.go b/e2e-tests/framework/scenario.go index a3172c97..bc2e4fbf 100644 --- a/e2e-tests/framework/scenario.go +++ b/e2e-tests/framework/scenario.go @@ -26,7 +26,16 @@ type MigrationScenario struct { } // NewMigrationScenario builds shared runners and app objects for a migration test. +// When config.RunAs == "admin", the NonAdmin fields are populated with admin contexts +// so all test code using those fields automatically runs with cluster-admin credentials. func NewMigrationScenario(appName, namespace, k8sDeployBin, craneBin, srcCtx, tgtCtx string) MigrationScenario { + srcNonAdminCtx := config.SourceNonAdminContext + tgtNonAdminCtx := config.TargetNonAdminContext + if config.RunAs == "admin" { + srcNonAdminCtx = srcCtx + tgtNonAdminCtx = tgtCtx + } + return MigrationScenario{ AppName: appName, Namespace: namespace, @@ -48,27 +57,27 @@ func NewMigrationScenario(appName, namespace, k8sDeployBin, craneBin, srcCtx, tg Name: appName, Namespace: namespace, Bin: k8sDeployBin, - Context: config.SourceNonAdminContext, + Context: srcNonAdminCtx, InsecureSkipTLS: config.InsecureSkipTLSVerify, }, TgtAppNonAdmin: K8sDeployApp{ Name: appName, Namespace: namespace, Bin: k8sDeployBin, - Context: config.TargetNonAdminContext, + Context: tgtNonAdminCtx, InsecureSkipTLS: config.InsecureSkipTLSVerify, }, KubectlSrc: KubectlRunner{Bin: "kubectl", Context: srcCtx}, KubectlTgt: KubectlRunner{Bin: "kubectl", Context: tgtCtx}, - KubectlSrcNonAdmin: KubectlRunner{Bin: "kubectl", Context: config.SourceNonAdminContext}, - KubectlTgtNonAdmin: KubectlRunner{Bin: "kubectl", Context: config.TargetNonAdminContext}, + KubectlSrcNonAdmin: KubectlRunner{Bin: "kubectl", Context: srcNonAdminCtx}, + KubectlTgtNonAdmin: KubectlRunner{Bin: "kubectl", Context: tgtNonAdminCtx}, Crane: CraneRunner{ Bin: craneBin, SourceContext: srcCtx, }, CraneNonAdmin: CraneRunner{ Bin: craneBin, - SourceContext: config.SourceNonAdminContext, + SourceContext: srcNonAdminCtx, }, } } diff --git a/e2e-tests/tests/tier0/e2e_suite_test.go b/e2e-tests/tests/tier0/e2e_suite_test.go index 183c32f7..17b644af 100644 --- a/e2e-tests/tests/tier0/e2e_suite_test.go +++ b/e2e-tests/tests/tier0/e2e_suite_test.go @@ -21,6 +21,7 @@ func init() { flag.StringVar(&config.SourceNonAdminContext, "source-nonadmin-context", "", "Source cluster non-admin context for RBAC scenarios") flag.StringVar(&config.TargetNonAdminContext, "target-nonadmin-context", "", "Target cluster non-admin context for RBAC scenarios") flag.BoolVar(&config.InsecureSkipTLSVerify, "insecure-skip-tls-verify", false, "Skip TLS certificate verification for k8sdeploy connections (use for OCP clusters with self-signed certs)") + flag.StringVar(&config.RunAs, "run-as", "", "Override user context: set to 'admin' to run all tests with cluster-admin credentials") } // TestE2E configures Ginkgo and executes the e2e test suite. diff --git a/e2e-tests/tests/tier0/mta_804_empty_pvc_migration_test.go b/e2e-tests/tests/tier0/mta_804_empty_pvc_migration_test.go index 0b0ac746..f21cd506 100644 --- a/e2e-tests/tests/tier0/mta_804_empty_pvc_migration_test.go +++ b/e2e-tests/tests/tier0/mta_804_empty_pvc_migration_test.go @@ -23,12 +23,6 @@ var _ = Describe("Empty PVC migration", func() { config.SourceContext, config.TargetContext, ) - if scenario.KubectlSrcNonAdmin.Context == "" { - Skip("source-nonadmin-context is required for non-admin test") - } - if scenario.KubectlTgtNonAdmin.Context == "" { - Skip("target-nonadmin-context is required for non-admin test") - } srcApp := scenario.SrcAppNonAdmin tgtApp := scenario.TgtAppNonAdmin @@ -42,7 +36,7 @@ var _ = Describe("Empty PVC migration", func() { } By("Grant ns admin permissions to nonadmin user on source and target") - kubectlSrcNonAdmin, kubectlTgtNonAdmin, cleanup, err := SetupNamespaceAdminUsersForScenario(scenario, namespace) + kubectlSrcNonAdmin, kubectlTgtNonAdmin, cleanup, err := SetupActiveKubectlRunners(scenario, namespace) Expect(err).NotTo(HaveOccurred()) DeferCleanup(cleanup) diff --git a/e2e-tests/tests/tier0/mta_805_sets_test.go b/e2e-tests/tests/tier0/mta_805_sets_test.go index 2efff928..5c1241c9 100644 --- a/e2e-tests/tests/tier0/mta_805_sets_test.go +++ b/e2e-tests/tests/tier0/mta_805_sets_test.go @@ -25,12 +25,6 @@ var _ = Describe("Sets resources migration", func() { config.SourceContext, config.TargetContext, ) - if scenario.KubectlSrcNonAdmin.Context == "" { - Skip("source-nonadmin-context is required for non-admin stateless migration test") - } - if scenario.KubectlTgtNonAdmin.Context == "" { - Skip("target-nonadmin-context is required for non-admin stateless migration test") - } srcApp := scenario.SrcAppNonAdmin tgtApp := scenario.TgtAppNonAdmin runner := scenario.CraneNonAdmin @@ -53,7 +47,7 @@ var _ = Describe("Sets resources migration", func() { tgtApp.ExtraVars = srcApp.ExtraVars By("Grant ns admin permissions to nonadmin user on source and target") - kubectlSrcNonAdmin, kubectlTgtNonAdmin, cleanup, err := SetupNamespaceAdminUsersForScenario(scenario, namespace) + kubectlSrcNonAdmin, kubectlTgtNonAdmin, cleanup, err := SetupActiveKubectlRunners(scenario, namespace) Expect(err).NotTo(HaveOccurred()) DeferCleanup(func() { By("Delete test namespace on source and target (best effort)") diff --git a/e2e-tests/tests/tier0/mta_806_pvc_data_integrity_test.go b/e2e-tests/tests/tier0/mta_806_pvc_data_integrity_test.go index 6126803e..e08704d1 100644 --- a/e2e-tests/tests/tier0/mta_806_pvc_data_integrity_test.go +++ b/e2e-tests/tests/tier0/mta_806_pvc_data_integrity_test.go @@ -25,12 +25,6 @@ var _ = Describe("PVC data integrity migration", func() { config.SourceContext, config.TargetContext, ) - if scenario.KubectlSrcNonAdmin.Context == "" { - Skip("source-nonadmin-context is required for non-admin test") - } - if scenario.KubectlTgtNonAdmin.Context == "" { - Skip("target-nonadmin-context is required for non-admin test") - } srcApp := scenario.SrcAppNonAdmin tgtApp := scenario.TgtAppNonAdmin @@ -48,7 +42,7 @@ var _ = Describe("PVC data integrity migration", func() { } By("Grant ns admin permissions to nonadmin user on source and target") - kubectlSrcNonAdmin, kubectlTgtNonAdmin, cleanup, err := SetupNamespaceAdminUsersForScenario(scenario, namespace) + kubectlSrcNonAdmin, kubectlTgtNonAdmin, cleanup, err := SetupActiveKubectlRunners(scenario, namespace) Expect(err).NotTo(HaveOccurred()) DeferCleanup(cleanup) diff --git a/e2e-tests/tests/tier0/mta_807_data_validation_test.go b/e2e-tests/tests/tier0/mta_807_data_validation_test.go index 049db867..304db632 100644 --- a/e2e-tests/tests/tier0/mta_807_data_validation_test.go +++ b/e2e-tests/tests/tier0/mta_807_data_validation_test.go @@ -129,12 +129,6 @@ var _ = Describe("Data validation with indirect migration of MySQL DB", func() { config.SourceContext, config.TargetContext, ) - if scenario.KubectlSrcNonAdmin.Context == "" { - Skip("source-nonadmin-context is required for non-admin stateful migration test") - } - if scenario.KubectlTgtNonAdmin.Context == "" { - Skip("target-nonadmin-context is required for non-admin stateful migration test") - } srcApp := scenario.SrcAppNonAdmin tgtApp := scenario.TgtAppNonAdmin runner := scenario.CraneNonAdmin @@ -150,7 +144,7 @@ var _ = Describe("Data validation with indirect migration of MySQL DB", func() { } By("Grant namespace admin permissions to nonadmin user on source and target") - kubectlSrcNonAdmin, kubectlTgtNonAdmin, cleanup, err := SetupNamespaceAdminUsersForScenario(scenario, namespace) + kubectlSrcNonAdmin, kubectlTgtNonAdmin, cleanup, err := SetupActiveKubectlRunners(scenario, namespace) Expect(err).NotTo(HaveOccurred()) DeferCleanup(func() { diff --git a/e2e-tests/tests/tier0/mta_809_initcontainer_test.go b/e2e-tests/tests/tier0/mta_809_initcontainer_test.go index 2d3ed31c..17c9b730 100644 --- a/e2e-tests/tests/tier0/mta_809_initcontainer_test.go +++ b/e2e-tests/tests/tier0/mta_809_initcontainer_test.go @@ -23,12 +23,6 @@ var _ = Describe("InitContainer Migration", func() { config.SourceContext, config.TargetContext, ) - if scenario.KubectlSrcNonAdmin.Context == "" { - Skip("source-nonadmin-context is required for non-admin stateless migration test") - } - if scenario.KubectlTgtNonAdmin.Context == "" { - Skip("target-nonadmin-context is required for non-admin stateless migration test") - } srcApp := scenario.SrcAppNonAdmin tgtApp := scenario.TgtAppNonAdmin runner := scenario.CraneNonAdmin @@ -43,7 +37,7 @@ var _ = Describe("InitContainer Migration", func() { } By("Grant ns admin permissions to nonadmin user on source and target") - kubectlSrcNonAdmin, kubectlTgtNonAdmin, cleanup, err := SetupNamespaceAdminUsersForScenario(scenario, namespace) + kubectlSrcNonAdmin, kubectlTgtNonAdmin, cleanup, err := SetupActiveKubectlRunners(scenario, namespace) Expect(err).NotTo(HaveOccurred()) DeferCleanup(func() { By("Delete test namespace on source and target (wait for completion)") diff --git a/e2e-tests/tests/tier0/mta_810_configmap_test.go b/e2e-tests/tests/tier0/mta_810_configmap_test.go index 1d476667..477fdfd0 100644 --- a/e2e-tests/tests/tier0/mta_810_configmap_test.go +++ b/e2e-tests/tests/tier0/mta_810_configmap_test.go @@ -25,12 +25,6 @@ var _ = Describe("ConfigMap Migration", func() { config.TargetContext, ) - if scenario.KubectlSrcNonAdmin.Context == "" { - Skip("source-nonadmin-context is required for non-admin stateless migration test") - } - if scenario.KubectlTgtNonAdmin.Context == "" { - Skip("target-nonadmin-context is required for non-admin stateless migration test") - } srcApp := scenario.SrcAppNonAdmin tgtApp := scenario.TgtAppNonAdmin runner := scenario.CraneNonAdmin @@ -43,7 +37,7 @@ var _ = Describe("ConfigMap Migration", func() { } By("Grant ns admin permissions to nonadmin user on source and target") - kubectlSrcNonAdmin, kubectlTgtNonAdmin, cleanup, err := SetupNamespaceAdminUsersForScenario(scenario, namespace) + kubectlSrcNonAdmin, kubectlTgtNonAdmin, cleanup, err := SetupActiveKubectlRunners(scenario, namespace) Expect(err).NotTo(HaveOccurred()) DeferCleanup(func() { By("Delete test namespace on source and target (wait for completion)") diff --git a/e2e-tests/tests/tier0/mta_811_mongodb_non_admin_test.go b/e2e-tests/tests/tier0/mta_811_mongodb_non_admin_test.go index 05491fd2..e44e48ab 100644 --- a/e2e-tests/tests/tier0/mta_811_mongodb_non_admin_test.go +++ b/e2e-tests/tests/tier0/mta_811_mongodb_non_admin_test.go @@ -108,12 +108,6 @@ var _ = Describe("MongoDB Migration", func() { config.TargetContext, ) - if scenario.KubectlSrcNonAdmin.Context == "" { - Skip("source-nonadmin-context is required for non-admin stateful migration test") - } - if scenario.KubectlTgtNonAdmin.Context == "" { - Skip("target-nonadmin-context is required for non-admin stateful migration test") - } srcApp := scenario.SrcAppNonAdmin tgtApp := scenario.TgtAppNonAdmin runner := scenario.CraneNonAdmin @@ -126,7 +120,7 @@ var _ = Describe("MongoDB Migration", func() { } By("Grant namespace admin permissions to nonadmin user on source and target") - kubectlSrcNonAdmin, kubectlTgtNonAdmin, cleanup, err := SetupNamespaceAdminUsersForScenario(scenario, namespace) + kubectlSrcNonAdmin, kubectlTgtNonAdmin, cleanup, err := SetupActiveKubectlRunners(scenario, namespace) Expect(err).NotTo(HaveOccurred()) DeferCleanup(func() { diff --git a/e2e-tests/tests/tier0/mta_812_role_migration_test.go b/e2e-tests/tests/tier0/mta_812_role_migration_test.go index 9284f8e2..574c29cc 100644 --- a/e2e-tests/tests/tier0/mta_812_role_migration_test.go +++ b/e2e-tests/tests/tier0/mta_812_role_migration_test.go @@ -24,12 +24,6 @@ var _ = Describe("Role and RoleBinding migration", func() { config.TargetContext, ) - if scenario.KubectlSrcNonAdmin.Context == "" { - Skip("source-nonadmin-context is required for non-admin role migration test") - } - if scenario.KubectlTgtNonAdmin.Context == "" { - Skip("target-nonadmin-context is required for non-admin role migration test") - } srcApp := scenario.SrcAppNonAdmin tgtApp := scenario.TgtAppNonAdmin @@ -43,7 +37,7 @@ var _ = Describe("Role and RoleBinding migration", func() { } By("Grant ns admin permissions to nonadmin user on source and target") - kubectlSrcNonAdmin, kubectlTgtNonAdmin, cleanup, err := SetupNamespaceAdminUsersForScenario(scenario, namespace) + kubectlSrcNonAdmin, kubectlTgtNonAdmin, cleanup, err := SetupActiveKubectlRunners(scenario, namespace) Expect(err).NotTo(HaveOccurred()) DeferCleanup(func() { By("Delete test namespace on source and target (wait for completion)") diff --git a/e2e-tests/tests/tier0/mta_813_cronJob_PVC_test.go b/e2e-tests/tests/tier0/mta_813_cronJob_PVC_test.go index c41a9c84..500215e3 100644 --- a/e2e-tests/tests/tier0/mta_813_cronJob_PVC_test.go +++ b/e2e-tests/tests/tier0/mta_813_cronJob_PVC_test.go @@ -26,12 +26,6 @@ var _ = Describe("CronJob with attached PVC migration as non-admin user", func() config.TargetContext, ) - if scenario.KubectlSrcNonAdmin.Context == "" { - Skip("source-nonadmin-context is required for this test") - } - if scenario.KubectlTgtNonAdmin.Context == "" { - Skip("target-nonadmin-context is required for this test") - } srcApp := scenario.SrcAppNonAdmin tgtApp := scenario.TgtAppNonAdmin @@ -51,7 +45,7 @@ var _ = Describe("CronJob with attached PVC migration as non-admin user", func() } By("Grant namespace-admin permissions to non-admin user on source and target") - kubectlSrcNonAdmin, _, cleanup, err := SetupNamespaceAdminUsersForScenario(scenario, namespace) + kubectlSrcNonAdmin, _, cleanup, err := SetupActiveKubectlRunners(scenario, namespace) Expect(err).NotTo(HaveOccurred()) DeferCleanup(func() { By("Delete test namespace on source and target (wait for completion)") diff --git a/e2e-tests/tests/tier0/mta_827_custom_transformation_stage_test.go b/e2e-tests/tests/tier0/mta_827_custom_transformation_stage_test.go index a8958ecd..af2149f5 100644 --- a/e2e-tests/tests/tier0/mta_827_custom_transformation_stage_test.go +++ b/e2e-tests/tests/tier0/mta_827_custom_transformation_stage_test.go @@ -28,12 +28,6 @@ var _ = Describe("Custom transformation stage", func() { config.SourceContext, config.TargetContext, ) - if scenario.KubectlSrcNonAdmin.Context == "" { - Skip("source-nonadmin-context is required for non-admin custom transformation stage test") - } - if scenario.KubectlTgtNonAdmin.Context == "" { - Skip("target-nonadmin-context is required for non-admin custom transformation stage test") - } srcApp := scenario.SrcAppNonAdmin tgtApp := scenario.TgtAppNonAdmin @@ -48,10 +42,10 @@ var _ = Describe("Custom transformation stage", func() { } By("Grant namespace admin permissions to nonadmin user on source and target") - kubectlSrcNonAdmin, kubectlTgtNonAdmin, scenarioCleanup, err := SetupNamespaceAdminUsersForScenario(scenario, namespace) + kubectlSrcNonAdmin, kubectlTgtNonAdmin, scenarioCleanup, err := SetupActiveKubectlRunners(scenario, namespace) Expect(err).NotTo(HaveOccurred()) By("Grant namespace admin permissions to nonadmin user on migrated target namespace") - _, migratedNamespaceCleanup, err := SetupNamespaceAdminUser( + _, migratedNamespaceCleanup, err := SetupActiveNamespaceAdmin( scenario.KubectlTgt, scenario.KubectlTgtNonAdmin.Context, targetNamespace, diff --git a/e2e-tests/tests/tier0/mta_828_instructions_file_migration_test.go b/e2e-tests/tests/tier0/mta_828_instructions_file_migration_test.go index 0e187f59..37c502bf 100644 --- a/e2e-tests/tests/tier0/mta_828_instructions_file_migration_test.go +++ b/e2e-tests/tests/tier0/mta_828_instructions_file_migration_test.go @@ -28,12 +28,6 @@ var _ = Describe("Instructions-file migration", func() { config.TargetContext, ) - if scenario.KubectlSrcNonAdmin.Context == "" { - Skip("source-nonadmin-context is required for non-admin instructions file migration test") - } - if scenario.KubectlTgtNonAdmin.Context == "" { - Skip("target-nonadmin-context is required for non-admin instructions file migration test") - } srcApp := scenario.SrcAppNonAdmin tgtApp := scenario.TgtAppNonAdmin @@ -44,7 +38,7 @@ var _ = Describe("Instructions-file migration", func() { tgtApp.ExtraVars = srcApp.ExtraVars By("Grant ns admin permissions to nonadmin user on source and target") - kubectlSrcNonAdmin, _, cleanup, err := SetupNamespaceAdminUsersForScenario(scenario, namespace) + kubectlSrcNonAdmin, _, cleanup, err := SetupActiveKubectlRunners(scenario, namespace) Expect(err).NotTo(HaveOccurred()) DeferCleanup(func() { By("Delete test namespace on source and target (wait for completion)") diff --git a/e2e-tests/tests/tier0/mta_831_validate_compatible_resources_offline_test.go b/e2e-tests/tests/tier0/mta_831_validate_compatible_resources_offline_test.go index 91b9ed35..68641bae 100644 --- a/e2e-tests/tests/tier0/mta_831_validate_compatible_resources_offline_test.go +++ b/e2e-tests/tests/tier0/mta_831_validate_compatible_resources_offline_test.go @@ -28,12 +28,6 @@ var _ = Describe("Crane validate: all compatible standard resources in offline m config.TargetContext, ) - if scenario.SrcAppNonAdmin.Context == "" { - Skip("source-nonadmin-context is required for non-admin offline validation test") - } - if scenario.TgtAppNonAdmin.Context == "" { - Skip("target-nonadmin-context is required for non-admin offline validation test") - } srcApp := scenario.SrcAppNonAdmin tgtApp := scenario.TgtAppNonAdmin runner := scenario.CraneNonAdmin @@ -43,7 +37,7 @@ var _ = Describe("Crane validate: all compatible standard resources in offline m tgtApp.ExtraVars = srcApp.ExtraVars By("Grant ns admin permissions to nonadmin user on source and target") - kubectlSrcNonAdmin, _, cleanup, err := SetupNamespaceAdminUsersForScenario(scenario, namespace) + kubectlSrcNonAdmin, _, cleanup, err := SetupActiveKubectlRunners(scenario, namespace) Expect(err).NotTo(HaveOccurred()) DeferCleanup(func() { By("Delete test namespace on source and target (wait for completion)") diff --git a/e2e-tests/tests/tier0/mta_833_compatible_resources_live_test.go b/e2e-tests/tests/tier0/mta_833_compatible_resources_live_test.go index 848cb395..764fb37b 100644 --- a/e2e-tests/tests/tier0/mta_833_compatible_resources_live_test.go +++ b/e2e-tests/tests/tier0/mta_833_compatible_resources_live_test.go @@ -25,12 +25,6 @@ var _ = Describe("Crane validate: all compatible standard resources in live mode config.SourceContext, config.TargetContext, ) - if scenario.SrcAppNonAdmin.Context == "" { - Skip("source-nonadmin-context is required for non-admin offline validation test") - } - if scenario.TgtAppNonAdmin.Context == "" { - Skip("target-nonadmin-context is required for non-admin offline validation test") - } srcApp := scenario.SrcAppNonAdmin tgtApp := scenario.TgtAppNonAdmin runner := scenario.CraneNonAdmin @@ -40,7 +34,7 @@ var _ = Describe("Crane validate: all compatible standard resources in live mode tgtApp.ExtraVars = srcApp.ExtraVars By("Grant ns admin permissions to nonadmin user on source and target") - kubectlSrcNonAdmin, _, cleanup, err := SetupNamespaceAdminUsersForScenario(scenario, namespace) + kubectlSrcNonAdmin, _, cleanup, err := SetupActiveKubectlRunners(scenario, namespace) Expect(err).NotTo(HaveOccurred()) DeferCleanup(func() { By("Delete test namespace on source and target (wait for completion)") diff --git a/e2e-tests/tests/tier0/mta_844_validate_mixed_resources_live_test.go b/e2e-tests/tests/tier0/mta_844_validate_mixed_resources_live_test.go index 278f9a5c..8a1c27df 100644 --- a/e2e-tests/tests/tier0/mta_844_validate_mixed_resources_live_test.go +++ b/e2e-tests/tests/tier0/mta_844_validate_mixed_resources_live_test.go @@ -28,12 +28,6 @@ var _ = Describe("Crane validate: mixed compatible and incompatible resources in config.TargetContext, ) - if scenario.SrcAppNonAdmin.Context == "" { - Skip("source-nonadmin-context is required for non-admin validation test") - } - if scenario.TgtAppNonAdmin.Context == "" { - Skip("target-nonadmin-context is required for non-admin validation test") - } srcApp := scenario.SrcAppNonAdmin tgtApp := scenario.TgtAppNonAdmin runner := scenario.CraneNonAdmin @@ -43,7 +37,7 @@ var _ = Describe("Crane validate: mixed compatible and incompatible resources in tgtApp.ExtraVars = srcApp.ExtraVars By("Grant ns admin permissions to nonadmin user on source and target") - kubectlSrcNonAdmin, _, cleanup, err := SetupNamespaceAdminUsersForScenario(scenario, namespace) + kubectlSrcNonAdmin, _, cleanup, err := SetupActiveKubectlRunners(scenario, namespace) Expect(err).NotTo(HaveOccurred()) DeferCleanup(func() { By("Delete test namespace on source and target (wait for completion)") diff --git a/e2e-tests/tests/tier0/mta_845_validate_mixed_resources_offline_test.go b/e2e-tests/tests/tier0/mta_845_validate_mixed_resources_offline_test.go index 5f40c041..230847ff 100644 --- a/e2e-tests/tests/tier0/mta_845_validate_mixed_resources_offline_test.go +++ b/e2e-tests/tests/tier0/mta_845_validate_mixed_resources_offline_test.go @@ -30,12 +30,6 @@ var _ = Describe("Crane validate: mixed compatible and incompatible resources in config.TargetContext, ) - if scenario.SrcAppNonAdmin.Context == "" { - Skip("source-nonadmin-context is required for non-admin validation test") - } - if scenario.TgtAppNonAdmin.Context == "" { - Skip("target-nonadmin-context is required for non-admin validation test") - } srcApp := scenario.SrcAppNonAdmin tgtApp := scenario.TgtAppNonAdmin runner := scenario.CraneNonAdmin @@ -45,7 +39,7 @@ var _ = Describe("Crane validate: mixed compatible and incompatible resources in tgtApp.ExtraVars = srcApp.ExtraVars By("Grant ns admin permissions to nonadmin user on source and target") - kubectlSrcNonAdmin, _, cleanup, err := SetupNamespaceAdminUsersForScenario(scenario, namespace) + kubectlSrcNonAdmin, _, cleanup, err := SetupActiveKubectlRunners(scenario, namespace) Expect(err).NotTo(HaveOccurred()) DeferCleanup(func() { By("Delete test namespace on source and target (wait for completion)") diff --git a/e2e-tests/tests/tier0/mta_846_validate_single_incompatible_route_live_test.go b/e2e-tests/tests/tier0/mta_846_validate_single_incompatible_route_live_test.go index 24a84399..2989f822 100644 --- a/e2e-tests/tests/tier0/mta_846_validate_single_incompatible_route_live_test.go +++ b/e2e-tests/tests/tier0/mta_846_validate_single_incompatible_route_live_test.go @@ -28,9 +28,6 @@ var _ = Describe("Validate single incompatible Route [Live Mode]", func() { Skip("Route is supported on OpenShift targets; this minikube-only incompatibility check is not applicable") } - if scenario.KubectlTgtNonAdmin.Context == "" { - Skip("target-nonadmin-context is required") - } runner := scenario.CraneNonAdmin paths, err := NewScenarioPaths("crane-validate-single-route-live-*") diff --git a/e2e-tests/tests/tier1/e2e_suite_test.go b/e2e-tests/tests/tier1/e2e_suite_test.go index 5390c6c4..9c2e56bb 100644 --- a/e2e-tests/tests/tier1/e2e_suite_test.go +++ b/e2e-tests/tests/tier1/e2e_suite_test.go @@ -21,6 +21,7 @@ func init() { flag.StringVar(&config.SourceNonAdminContext, "source-nonadmin-context", "", "Source cluster non-admin context for RBAC scenarios") flag.StringVar(&config.TargetNonAdminContext, "target-nonadmin-context", "", "Target cluster non-admin context for RBAC scenarios") flag.BoolVar(&config.InsecureSkipTLSVerify, "insecure-skip-tls-verify", false, "Skip TLS certificate verification for k8sdeploy connections (use for OCP clusters with self-signed certs)") + flag.StringVar(&config.RunAs, "run-as", "", "Override user context: set to 'admin' to run all tests with cluster-admin credentials") } // TestE2E configures Ginkgo and executes the e2e test suite. diff --git a/e2e-tests/tests/tier1/mta_829_validate_alternative_gv_suggestion_test.go b/e2e-tests/tests/tier1/mta_829_validate_alternative_gv_suggestion_test.go index 9b7a2d03..3618f747 100644 --- a/e2e-tests/tests/tier1/mta_829_validate_alternative_gv_suggestion_test.go +++ b/e2e-tests/tests/tier1/mta_829_validate_alternative_gv_suggestion_test.go @@ -26,12 +26,6 @@ var _ = Describe("Validate alternative GV suggestion [Live Mode]", func() { config.TargetContext, ) - if scenario.SrcAppNonAdmin.Context == "" { - Skip("source-nonadmin-context is required for non-admin stateless migration test") - } - if scenario.TgtAppNonAdmin.Context == "" { - Skip("target-nonadmin-context is required for non-admin stateless migration test") - } srcApp := scenario.SrcAppNonAdmin tgtApp := scenario.TgtAppNonAdmin runner := scenario.CraneNonAdmin @@ -40,7 +34,7 @@ var _ = Describe("Validate alternative GV suggestion [Live Mode]", func() { } tgtApp.ExtraVars = srcApp.ExtraVars By("Grant ns admin permissions to nonadmin user on source and target") - kubectlSrcNonAdmin, _, cleanup, err := SetupNamespaceAdminUsersForScenario(scenario, namespace) + kubectlSrcNonAdmin, _, cleanup, err := SetupActiveKubectlRunners(scenario, namespace) Expect(err).NotTo(HaveOccurred()) DeferCleanup(func() { By("Delete test namespace on source and target (wait for completion)") diff --git a/e2e-tests/tests/tier1/mta_830_instructions_file_force_reconcile_test.go b/e2e-tests/tests/tier1/mta_830_instructions_file_force_reconcile_test.go index 36197e16..8b07fd7b 100644 --- a/e2e-tests/tests/tier1/mta_830_instructions_file_force_reconcile_test.go +++ b/e2e-tests/tests/tier1/mta_830_instructions_file_force_reconcile_test.go @@ -27,12 +27,6 @@ var _ = Describe("Instructions-file force reconcile migration", func() { config.TargetContext, ) - if scenario.KubectlSrcNonAdmin.Context == "" { - Skip("source-nonadmin-context is required for non-admin instructions file migration test") - } - if scenario.KubectlTgtNonAdmin.Context == "" { - Skip("target-nonadmin-context is required for non-admin instructions file migration test") - } srcApp := scenario.SrcAppNonAdmin tgtApp := scenario.TgtAppNonAdmin @@ -43,7 +37,7 @@ var _ = Describe("Instructions-file force reconcile migration", func() { tgtApp.ExtraVars = srcApp.ExtraVars By("Grant ns admin permissions to nonadmin user on source and target") - kubectlSrcNonAdmin, kubectlTgtNonAdmin, cleanup, err := SetupNamespaceAdminUsersForScenario(scenario, namespace) + kubectlSrcNonAdmin, kubectlTgtNonAdmin, cleanup, err := SetupActiveKubectlRunners(scenario, namespace) Expect(err).NotTo(HaveOccurred()) DeferCleanup(func() { By("Delete test namespace on source and target (wait for completion)") diff --git a/e2e-tests/tests/tier1/mta_832_validate_alternative_gv_suggestion_offline_test.go b/e2e-tests/tests/tier1/mta_832_validate_alternative_gv_suggestion_offline_test.go index edb9883c..6d591852 100644 --- a/e2e-tests/tests/tier1/mta_832_validate_alternative_gv_suggestion_offline_test.go +++ b/e2e-tests/tests/tier1/mta_832_validate_alternative_gv_suggestion_offline_test.go @@ -29,12 +29,6 @@ var _ = Describe("Validate alternative GV suggestion [Offline Mode]", func() { config.TargetContext, ) - if scenario.SrcAppNonAdmin.Context == "" { - Skip("source-nonadmin-context is required for non-admin stateless migration test") - } - if scenario.TgtAppNonAdmin.Context == "" { - Skip("target-nonadmin-context is required for non-admin stateless migration test") - } srcApp := scenario.SrcAppNonAdmin tgtApp := scenario.TgtAppNonAdmin runner := scenario.CraneNonAdmin @@ -43,7 +37,7 @@ var _ = Describe("Validate alternative GV suggestion [Offline Mode]", func() { } tgtApp.ExtraVars = srcApp.ExtraVars By("Grant ns admin permissions to nonadmin user on source and target") - kubectlSrcNonAdmin, _, cleanup, err := SetupNamespaceAdminUsersForScenario(scenario, namespace) + kubectlSrcNonAdmin, _, cleanup, err := SetupActiveKubectlRunners(scenario, namespace) Expect(err).NotTo(HaveOccurred()) DeferCleanup(func() { By("Delete test namespace on source and target (wait for completion)") diff --git a/e2e-tests/tests/tier1/mta_836_validate_core_group_omitted_offline_test.go b/e2e-tests/tests/tier1/mta_836_validate_core_group_omitted_offline_test.go index 2217ff90..5e688b4e 100644 --- a/e2e-tests/tests/tier1/mta_836_validate_core_group_omitted_offline_test.go +++ b/e2e-tests/tests/tier1/mta_836_validate_core_group_omitted_offline_test.go @@ -28,12 +28,6 @@ var _ = Describe("Validate core group omission [Offline Mode]", func() { config.TargetContext, ) - if scenario.SrcAppNonAdmin.Context == "" { - Skip("source-nonadmin-context is required for non-admin offline validation test") - } - if scenario.TgtAppNonAdmin.Context == "" { - Skip("target-nonadmin-context is required for non-admin offline validation test") - } srcApp := scenario.SrcAppNonAdmin tgtApp := scenario.TgtAppNonAdmin @@ -45,7 +39,7 @@ var _ = Describe("Validate core group omission [Offline Mode]", func() { tgtApp.ExtraVars = srcApp.ExtraVars By("Grant ns admin permissions to nonadmin user on source and target") - kubectlSrcNonAdmin, _, cleanup, err := SetupNamespaceAdminUsersForScenario(scenario, namespace) + kubectlSrcNonAdmin, _, cleanup, err := SetupActiveKubectlRunners(scenario, namespace) Expect(err).NotTo(HaveOccurred()) DeferCleanup(func() { By("Delete test namespace on source and target (wait for completion)") diff --git a/e2e-tests/tests/tier1/mta_850_validate_duplicate_gvk_test.go b/e2e-tests/tests/tier1/mta_850_validate_duplicate_gvk_test.go index 3dbedee4..fbce850a 100644 --- a/e2e-tests/tests/tier1/mta_850_validate_duplicate_gvk_test.go +++ b/e2e-tests/tests/tier1/mta_850_validate_duplicate_gvk_test.go @@ -63,9 +63,6 @@ var _ = Describe("Crane validate with duplicate GVK resources in live mode", fun config.TargetContext, ) - if scenario.KubectlTgtNonAdmin.Context == "" { - Skip("target-nonadmin-context is required for live validation test") - } runner := scenario.CraneNonAdmin runner.WorkDir = tempDir From b53d66df15c9b5e1635f5be9749ac52b6f58ee1d Mon Sep 17 00:00:00 2001 From: midays Date: Tue, 30 Jun 2026 13:54:35 +0300 Subject: [PATCH 2/3] Add test compliance workflow for e2e tests - Introduced a new GitHub Actions workflow to enforce compliance checks on non-admin e2e test files. - The workflow verifies that tests do not use deprecated functions and ensures proper context handling. - Outputs results indicating compliance status for all relevant test files. This addition enhances the testing framework by ensuring adherence to best practices in test configurations. Signed-off-by: midays --- .github/workflows/test-compliance.yml | 58 +++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 .github/workflows/test-compliance.yml diff --git a/.github/workflows/test-compliance.yml b/.github/workflows/test-compliance.yml new file mode 100644 index 00000000..80a42955 --- /dev/null +++ b/.github/workflows/test-compliance.yml @@ -0,0 +1,58 @@ +name: Test Compliance + +on: + pull_request: + paths: + - 'e2e-tests/tests/**' + +permissions: + contents: read + +jobs: + run-as-admin-compliance: + name: run-as-admin compliance + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Check for non-compliant test patterns + run: | + set +e + FAILED=0 + + # Check all test files in the repo + CHANGED=$(find e2e-tests/tests -name '*_test.go') + + echo "Checking files:" + echo "$CHANGED" + echo "" + + for FILE in $CHANGED; do + [ -f "$FILE" ] || continue + + # Skip admin tests — only non-admin tests call SetupActiveKubectlRunners + if ! grep -q "SetupActiveKubectlRunners\|SetupNamespaceAdminUsersForScenario" "$FILE"; then + echo "SKIP $FILE: admin test, skipping compliance check" + continue + fi + + echo "CHECK $FILE: non-admin test, checking compliance..." + + # 1. Must not call SetupNamespaceAdminUsersForScenario — use SetupActiveKubectlRunners instead + if grep -n "SetupNamespaceAdminUsersForScenario" "$FILE"; then + echo "FAIL $FILE: use SetupActiveKubectlRunners instead of SetupNamespaceAdminUsersForScenario" + FAILED=1 + fi + + # 2. Must not guard on empty non-admin context (Skip guards prevent RUN_AS_ADMIN override from working) + if grep -n 'NonAdmin\.Context == ""' "$FILE"; then + echo "FAIL $FILE: remove empty-context Skip guards — they block the RUN_AS_ADMIN override in Jenkins" + FAILED=1 + fi + done + + if [ "$FAILED" -eq 0 ]; then + echo "PASS: all test files are compliant." + fi + + exit $FAILED From b6eca9ea2af1533b904989695b369e42d1709252 Mon Sep 17 00:00:00 2001 From: midays Date: Tue, 30 Jun 2026 13:58:09 +0300 Subject: [PATCH 3/3] Refactor compliance check for non-admin e2e tests - Updated the compliance workflow to collect and report violations for non-admin test files more effectively. - Replaced deprecated function calls with `SetupActiveKubectlRunners` in relevant test cases. - Removed empty context checks to streamline compliance checks and improve clarity in test configurations. This change enhances the compliance verification process and aligns with best practices for non-admin test setups. Signed-off-by: midays --- .github/workflows/test-compliance.yml | 48 ++++++++++--------- .../tests/tier0/mta_853_split_apply_test.go | 8 +--- 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/.github/workflows/test-compliance.yml b/.github/workflows/test-compliance.yml index 80a42955..920446f9 100644 --- a/.github/workflows/test-compliance.yml +++ b/.github/workflows/test-compliance.yml @@ -18,41 +18,45 @@ jobs: - name: Check for non-compliant test patterns run: | set +e - FAILED=0 + VIOLATIONS=() - # Check all test files in the repo - CHANGED=$(find e2e-tests/tests -name '*_test.go') - - echo "Checking files:" - echo "$CHANGED" - echo "" - - for FILE in $CHANGED; do + for FILE in $(find e2e-tests/tests -name '*_test.go'); do [ -f "$FILE" ] || continue # Skip admin tests — only non-admin tests call SetupActiveKubectlRunners if ! grep -q "SetupActiveKubectlRunners\|SetupNamespaceAdminUsersForScenario" "$FILE"; then - echo "SKIP $FILE: admin test, skipping compliance check" continue fi - echo "CHECK $FILE: non-admin test, checking compliance..." + ISSUES="" + + if grep -q "SetupNamespaceAdminUsersForScenario" "$FILE"; then + ISSUES="${ISSUES}\n - use SetupActiveKubectlRunners instead of SetupNamespaceAdminUsersForScenario" + fi - # 1. Must not call SetupNamespaceAdminUsersForScenario — use SetupActiveKubectlRunners instead - if grep -n "SetupNamespaceAdminUsersForScenario" "$FILE"; then - echo "FAIL $FILE: use SetupActiveKubectlRunners instead of SetupNamespaceAdminUsersForScenario" - FAILED=1 + if grep -q 'NonAdmin\.Context == ""' "$FILE"; then + ISSUES="${ISSUES}\n - remove empty-context Skip guards (they block RUN_AS_ADMIN override)" fi - # 2. Must not guard on empty non-admin context (Skip guards prevent RUN_AS_ADMIN override from working) - if grep -n 'NonAdmin\.Context == ""' "$FILE"; then - echo "FAIL $FILE: remove empty-context Skip guards — they block the RUN_AS_ADMIN override in Jenkins" - FAILED=1 + if [ -n "$ISSUES" ]; then + VIOLATIONS+=("$FILE:$ISSUES") fi done - if [ "$FAILED" -eq 0 ]; then - echo "PASS: all test files are compliant." + echo "" + if [ ${#VIOLATIONS[@]} -eq 0 ]; then + echo "PASS: all non-admin test files are compliant." + exit 0 fi - exit $FAILED + echo "FAIL: the following non-admin test files are not compliant with RUN_AS_ADMIN:" + echo "" + for V in "${VIOLATIONS[@]}"; do + FILE="${V%%:*}" + ISSUES="${V#*:}" + echo " $FILE" + echo -e "$ISSUES" + echo "" + done + + exit 1 diff --git a/e2e-tests/tests/tier0/mta_853_split_apply_test.go b/e2e-tests/tests/tier0/mta_853_split_apply_test.go index 7d676489..7403af53 100644 --- a/e2e-tests/tests/tier0/mta_853_split_apply_test.go +++ b/e2e-tests/tests/tier0/mta_853_split_apply_test.go @@ -27,12 +27,6 @@ var _ = Describe("Namespace-admin cluster-level migration", func() { clusterRoleBindingName := "crane-e2e-pod-reader-binding" clusterRoleName := "crane-e2e-pod-reader" deniedResources := []string{"clusterroles.yaml", "clusterrolebindings.yaml"} - if scenario.KubectlSrcNonAdmin.Context == "" { - Skip("source-nonadmin-context is required for non-admin role migration test") - } - if scenario.KubectlTgtNonAdmin.Context == "" { - Skip("target-nonadmin-context is required for non-admin role migration test") - } srcAppNonAdmin := scenario.SrcAppNonAdmin tgtAppNonAdmin := scenario.TgtAppNonAdmin @@ -58,7 +52,7 @@ var _ = Describe("Namespace-admin cluster-level migration", func() { cr := ClusterRole{Name: clusterRoleName, Verb: "get,list,watch", Resource: "pods"} By("Granting namespace-admin permissions to non-admin user on source and target") - kubectlSrcNonAdmin, kubectlTgtNonAdmin, rbacCleanup, err := SetupNamespaceAdminUsersForScenario(scenario, namespace) + kubectlSrcNonAdmin, kubectlTgtNonAdmin, rbacCleanup, err := SetupActiveKubectlRunners(scenario, namespace) Expect(err).NotTo(HaveOccurred()) DeferCleanup(rbacCleanup)