Skip to content

feat(e2e): make e2e:kubernetes work transparently on OpenShift #2956

Description

@jgarciao

User Story

As a contributor running the Kubernetes e2e test suite on an OpenShift cluster,
I want mise run e2e:kubernetes to detect OpenShift automatically and handle
Security Context Constraints (SCC) setup and teardown,
so that I can validate OpenShell on OpenShift without a separate task or manual SCC commands.

Problem Statement

Running mise run e2e:kubernetes on OpenShift requires manual preparation:
the contributor must pre-create the namespace, grant the privileged SCC to
the openshell-sandbox service account, and override the Helm chart's
hardcoded runAsUser: 1000 and fsGroup: 1000 (which OpenShift's
restricted-v2 SCC rejects because it requires UIDs from the
namespace-assigned range). None of this is automated by the harness. A
separate e2e:openshift task exists but only verifies the gateway pod
starts — it does not run the Rust e2e test suite.

Impact / Why This Matters

Without this feature, contributors who need to validate OpenShell on OpenShift must:

  1. Manually create the openshell namespace before running the task.
  2. Manually grant the privileged SCC to the openshell-sandbox service account.
  3. Manually pass Helm value overrides to remove runAsUser/fsGroup.
  4. Manually clean up SCC bindings after the run.

These steps are error-prone, undocumented in the test harness, and easy to
forget — especially the cleanup. The separate e2e:openshift task creates
the impression that OpenShift is covered, but it only checks pod readiness
and provides no functional test coverage. Contributors can run the full Rust
e2e suite on OpenShift today via e2e:kubernetes with manual setup, but the
harness should handle this transparently.

Proposed Design

Running mise run e2e:kubernetes (or any variant like e2e:kubernetes:db)
should work identically on vanilla Kubernetes and OpenShift clusters:

  1. Auto-detection: The harness script detects OpenShift by checking for the
    route.openshift.io API group. No extra flags or environment variables are
    needed.

  2. SCC handling: When OpenShift is detected, the harness:

    • Applies an SCC-compatible Helm values overlay that removes hardcoded
      runAsUser/fsGroup, letting OpenShift assign UIDs from the namespace range.
    • Grants the privileged SCC to the openshell-sandbox service account.
    • For DB scenarios, grants the anyuid SCC to the PostgreSQL fixture service account.
  3. Cleanup: SCC bindings are removed in the cleanup function, ensuring they
    are cleaned up even if tests fail or are interrupted.

  4. Remove e2e:openshift: The separate task and script are removed since
    e2e:kubernetes now covers OpenShift.

  5. No changes on vanilla Kubernetes: When OpenShift is not detected, behavior
    is identical to today.

Acceptance Criteria

  • mise run e2e:kubernetes auto-detects OpenShift and prints "OpenShift detected" when running on an OpenShift cluster
  • mise run e2e:kubernetes does not falsely detect OpenShift on vanilla Kubernetes clusters (Kind, k3d, etc.)
  • The Helm chart deploys without runAsUser/fsGroup on OpenShift (SCC overlay applied automatically)
  • The privileged SCC is granted to openshell-sandbox before Helm install and removed during cleanup
  • The anyuid SCC is granted to the PostgreSQL fixture service account in DB scenarios and removed during cleanup
  • The e2e:openshift task and e2e-openshift.sh script are removed
  • TESTING.md documents the Kubernetes e2e tasks, OpenShift auto-detection, and relevant environment variables
  • All oc commands use --context "${KUBE_CONTEXT}" to target the correct cluster

Alternatives Considered

  1. Keep e2e:openshift as a separate task: This is the status quo. It
    requires maintaining two scripts with diverging logic. The separate script
    only checks pod readiness and provides no actual test coverage. Rejected
    because it creates a false sense of OpenShift coverage.

  2. Require explicit --openshift flag or environment variable: This would
    work but adds friction and is easy to forget. Auto-detection via the
    route.openshift.io API group is reliable and requires no user action.
    The API group check uses --no-headers output piped to grep -q . to
    avoid false positives from successful-but-empty kubectl api-resources
    responses.

  3. Separate Helm values file passed manually: Contributors could pass
    OPENSHELL_E2E_KUBE_EXTRA_VALUES pointing to an SCC overlay. This works
    but pushes OpenShift knowledge onto each contributor and doesn't handle
    SCC grant/cleanup. Rejected in favor of full automation.

Agent Investigation

The implementation was developed and tested on both Kind and OpenShift clusters.
Key findings:

  • PR history: e2e-openshift.sh was created in PR feat(helm): add optional PostgreSQL backing store #1579 as a shortcut
    during PostgreSQL backing store work. The author deferred OpenShift integration
    into the main harness. PRs refactor(helm): require external postgres for ha #1844, fix(e2e): make postgres fixture compatible with OpenShift #2002, and chore(ci): disable telemetry in internal test runs #2648 iterated on the OpenShift
    e2e path without merging it into the main harness. No CI workflow references
    e2e:openshift.

  • Helm template fix needed: The podSecurityContext block in
    _gateway-workload.tpl renders invalid YAML when values are null. Wrapping
    with {{- with }} makes it conditional.

  • OpenShift detection pitfall: kubectl api-resources --api-group=route.openshift.io
    returns exit code 0 even on vanilla Kubernetes (empty result set). Detection
    must check for actual output, not just exit code.

  • oc context targeting: oc adm policy commands default to oc's own
    current context, which may differ from KUBE_CONTEXT. All oc commands must
    use --context "${KUBE_CONTEXT}".

  • Test results: Both Kind and OpenShift test runs were completed. On Kind,
    all tests pass or fail with pre-existing issues (host.openshell.internal
    unreachable, Docker is Podman shim). On OpenShift, the same pre-existing
    failures occur. Tests that don't depend on sandbox SSH readiness (smoke,
    bypass_detection, community_image, landlock, no_proxy, etc.) pass normally.

Related issues:


I have an implementation ready here and can open a PR once this is accepted.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions