Skip to content

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

Open
jgarciao wants to merge 2 commits into
NVIDIA:mainfrom
jgarciao:merge-e2e-kubernetes-openshift
Open

feat(e2e): make e2e:kubernetes work transparently on OpenShift#3183
jgarciao wants to merge 2 commits into
NVIDIA:mainfrom
jgarciao:merge-e2e-kubernetes-openshift

Conversation

@jgarciao

@jgarciao jgarciao commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Makes mise run e2e:kubernetes run transparently on OpenShift. When the target cluster exposes the route.openshift.io API group, the harness auto-detects OpenShift and adapts the deployment and transport: it applies SCC-compatible Helm overrides, grants the required SCCs, and drives the gateway through a passthrough Route secured with mandatory mTLS instead of kubectl port-forward (which stalls the SSH-relay sandbox connect path). The previous standalone, weaker e2e:openshift task is removed. Vanilla-Kubernetes behavior is unchanged — every OpenShift branch is gated on OPENSHIFT_DETECTED.

Related Issue

Closes #2956
Closes #3033

Changes

  • Auto-detect OpenShift in e2e/with-kube-gateway.sh via the route.openshift.io API group; all OpenShift-specific behavior is gated on OPENSHIFT_DETECTED so the vanilla-Kubernetes path is untouched.
  • On OpenShift, reach the gateway over a passthrough OpenShift Route with mandatory mTLS instead of kubectl port-forward, which stalls the round-trip-heavy SSH-relay sandbox connect suites.
  • Add a security gate that asserts a certless caller is rejected at the TLS handshake before registering the gateway (fails the run on acceptance or on an unconfirmable rejection).
  • Grant privileged SCC to openshell-sandbox and anyuid to the PostgreSQL fixture; track grants with flags recorded before the operation so cleanup() revokes them even on failure or interrupt. Extracted client mTLS material is removed on cleanup.
  • New Helm CI overlays: ci/values-openshift-scc.yaml (drops hardcoded runAsUser/fsGroup so restricted-v2 injects the namespace UID/GID range) and ci/values-openshift-e2e.yaml (Route/mTLS transport, Always pull policy, raised HAProxy Route timeouts for long-lived transfers).
  • Guard pod securityContext in _gateway-workload.tpl with {{- with .Values.podSecurityContext }} so the SCC overlay can null it out.
  • Remove the standalone e2e:openshift task and e2e/rust/e2e-openshift.sh (gateway-readiness-only), folding its coverage into the unified path.
  • Refactor duplicated port-forward blocks into start_grpc_portforward / start_health_portforward / scenario_record_failure helpers.
  • Document the OpenShift flow, task variants, env vars, and image-tag pinning guidance in TESTING.md; add OpenShift SCC/Route troubleshooting to the debug-openshell-cluster skill.

Testing

  • mise run pre-commit passes
  • Unit tests added/updated
  • E2E tests added/updated (if applicable)
  • Verified mise run e2e:kubernetes against a live OpenShift cluster: SCC grants applied and revoked, passthrough Route serves mTLS, certless request rejected at the TLS handshake, and the SSH-relay sandbox connect suites pass over the Route.
  • Vanilla-Kubernetes path unchanged (all OpenShift branches gated on OPENSHIFT_DETECTED).

Checklist

  • Follows Conventional Commits
  • Commits are signed off (DCO)
  • Architecture docs updated (if applicable)

Running `mise run e2e:kubernetes` on OpenShift required manual namespace
creation, SCC grants, Helm value overrides, and cleanup. A separate
`e2e:openshift` task existed but only checked pod readiness without
running the Rust e2e test suite, and even with the suite wired up the
SSH-relay `sandbox connect` path stalled to the ready timeout because
`kubectl port-forward` cannot carry round-trip-heavy SSH over the
internet.

The harness now auto-detects OpenShift via the `route.openshift.io` API
group and, on OpenShift, both configures the cluster and switches the
gateway transport automatically:

- Drives the gateway through a passthrough OpenShift Route secured with
  mandatory mTLS instead of port-forward, so the connect suites
  (live_policy_update, port_forward, sync, connect-based
  sandbox_lifecycle, settings_management) actually pass. Computes the
  Route host from the cluster ingress domain, extracts client mTLS
  material from the openshell-client-tls secret, waits for the Route to
  serve mTLS, asserts a certless caller is rejected at the TLS
  handshake, and registers an mTLS CLI gateway pointing at the Route.
- 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 openshell-sandbox before Helm install
  and removes it during cleanup.
- Grants the anyuid SCC to the PostgreSQL fixture service account in
  DB scenarios and removes it during cleanup.
- All oc commands use --context to target the correct cluster.

The OpenShift e2e overlay (ci/values-openshift-e2e.yaml) turns TLS back
on, enables the Route, promotes the cert-verified caller to a dev
principal, and forces `image.pullPolicy`/`supervisor.image.pullPolicy`
to Always so runs against the `latest` upstream image use it instead of
a stale copy cached on the cluster nodes. Every OpenShift branch is
gated on OPENSHIFT_DETECTED, so the vanilla-Kubernetes port-forward path
is unchanged.

The Helm template for podSecurityContext is wrapped with {{- with }} so
null values omit the block instead of rendering invalid YAML.

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

TESTING.md is updated with Kubernetes e2e documentation including
OpenShift auto-detection, dropping the e2e-host-gateway feature on
remote clusters, pinning IMAGE_TAG when the CLI and image versions
differ, task variants, and environment variables.

The debug-openshell-cluster skill gains an OpenShift platform row and
two SCC failure patterns (gateway rejected over hardcoded runAsUser,
sandbox missing the privileged SCC) covering the SCC handling and
podSecurityContext behavior this change introduces.

Signed-off-by: Jorge Garcia Oncins <jgarciao@redhat.com>
Track the anyuid SCC grant for the PostgreSQL fixture with a dedicated
OPENSHIFT_POSTGRES_SCC_GRANTED flag set before the fixture apply, so a
failed apply no longer leaks the binding; cleanup now revokes it whenever
the grant succeeded, independent of deploy state.

Validate the Route server cert in the certless security gate (curl
--cacert instead of -k) and classify curl's exit code so only a TLS
client-auth rejection (35/56) counts as the expected certless rejection;
an unrelated DNS/timeout/TLS failure now fails loudly instead of masking
a potential mTLS hole.

Raise the OpenShift Route timeout in the e2e overlay. The default HAProxy
Route timeout is 30s, which severed long-lived transfers (large sandbox
upload/download, SSH-relay `sandbox connect`) mid-stream and failed the
sync e2e tests. Set both haproxy.router.openshift.io/timeout and
timeout-tunnel to 300s: a passthrough Route proxies in TCP mode, so
timeout-tunnel governs the established tunnel while timeout covers the
pre-tunnel phase.

Document the OpenShift transport exception, oc prerequisites and SCC
grants, and make the skopeo tag-check example copy-safe in TESTING.md.

Signed-off-by: Jorge Garcia Oncins <jgarciao@redhat.com>
@copy-pr-bot

copy-pr-bot Bot commented Sep 4, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(helm): omit podSecurityContext block when value is null feat(e2e): make e2e:kubernetes work transparently on OpenShift

1 participant