Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -376,10 +376,11 @@ jobs:
go install sigs.k8s.io/kind@v0.32.0
kind version

- name: Install openshell CLI
run: |
curl -LsSf https://raw.githubusercontent.com/NVIDIA/OpenShell/v0.0.110/install.sh | OPENSHELL_VERSION=v0.0.110 sh
openshell --version
# The openshell CLI is not pre-installed here. The e2e test installs it
# using the same gateway-matched command the console recommends, derived
# from the reconciled gateway_version API field
# (tests/e2e/e2e-openshell.sh, step 5). This keeps CI exercising the exact
# command shipped to users instead of a separately pinned version.

- name: Create Kind cluster with OIDC
env:
Expand Down
93 changes: 89 additions & 4 deletions tests/e2e/e2e-openshell.sh
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,22 @@ SANDBOX_NAME=""
E2E_GW_PF_PID="${E2E_GW_PF_PID:-}"
E2E_HS_NAMESPACE="${E2E_HS_NAMESPACE:-hypershell-system}"

if ! command -v "${OPENSHELL_BIN}" >/dev/null 2>&1; then
red "ERROR: openshell CLI not found (OPENSHELL_BIN=${OPENSHELL_BIN})"
red "Install: curl -LsSf https://raw.githubusercontent.com/NVIDIA/OpenShell/main/install.sh | sh"
exit 1
# The openshell CLI is installed later (step 5) using the same gateway-matched
# command the console recommends, derived from the reconciled gateway_version
# API field. It therefore cannot be present at start-up in a clean CI run, so we
# only record whether a binary is already available. Setting
# E2E_OPENSHELL_INSTALL=never opts out of installing and requires a pre-existing
# CLI (fail fast here in that mode).
if command -v "${OPENSHELL_BIN}" >/dev/null 2>&1; then
OPENSHELL_PREINSTALLED=1
else
OPENSHELL_PREINSTALLED=0
if [[ "${E2E_OPENSHELL_INSTALL}" == "never" ]]; then
red "ERROR: openshell CLI not found (OPENSHELL_BIN=${OPENSHELL_BIN}) and E2E_OPENSHELL_INSTALL=never"
red "Install it manually, or set E2E_OPENSHELL_INSTALL=auto to install the"
red "gateway-matched version via the console-recommended command."
exit 1
fi
fi

# --- Cleanup trap ---
Expand Down Expand Up @@ -836,6 +848,79 @@ echo ""
bold "5. Route Discovery + CLI Registration"
echo ""

# Install the openshell CLI exactly as the console recommends: read the
# reconciled gateway_version from the API, derive the installer version with the
# same rule as buildOpenShellInstallCommand, and run the upstream install.sh.
# This proves the recommended command keeps working end-to-end, including for
# downstream gateway images whose reported version carries a "-rh…" suffix.
install_openshell_cli_from_api() {
if [[ "${E2E_OPENSHELL_INSTALL}" == "never" ]]; then
dim " E2E_OPENSHELL_INSTALL=never; using pre-installed openshell CLI."
return 0
fi
if [[ "${E2E_OPENSHELL_INSTALL}" != "always" && "${OPENSHELL_PREINSTALLED}" == "1" ]]; then
dim " Using pre-installed openshell CLI (E2E_OPENSHELL_INSTALL=${E2E_OPENSHELL_INSTALL})."
return 0
fi

# The control plane reconciles gateway_version from the gateway's health
# endpoint after the pod is Running; poll for a bounded period.
local raw_version="" deadline
deadline=$(($(date +%s) + E2E_GATEWAY_VERSION_TIMEOUT))
dim " Waiting for reconciled gateway_version (timeout: ${E2E_GATEWAY_VERSION_TIMEOUT}s)..."
while [[ $(date +%s) -lt $deadline ]]; do
# Provisioning can outlast the access token; api_curl reads it each call.
acquire_oidc_token 2>/dev/null || true
raw_version=$(api_curl "${API_HOST}/api/hypershell/v1/gateways/${GW_ID}" 2>/dev/null | \
python3 -c "import json,sys; print(json.load(sys.stdin).get('gateway_version') or '')" 2>/dev/null || true)
[[ -n "$raw_version" ]] && break
sleep 5
done
if [[ -z "$raw_version" ]]; then
fail_test "API never reported gateway_version for ${GW_ID} within ${E2E_GATEWAY_VERSION_TIMEOUT}s"
exit 1
fi
pass "Reconciled gateway_version: ${raw_version}"

local installer_version
if ! installer_version=$(openshell_installer_version "$raw_version"); then
fail_test "Could not derive an installer version from gateway_version='${raw_version}'"
exit 1
fi
dim " Derived installer version: ${installer_version} (from '${raw_version}')"

# The exact command the console shows the user (installScriptUrl + OPENSHELL_VERSION).
show_cmd "curl -LsSf ${OPENSHELL_INSTALL_SCRIPT_URL} | OPENSHELL_VERSION=${installer_version} sh"
if ! curl -LsSf "${OPENSHELL_INSTALL_SCRIPT_URL}" | OPENSHELL_VERSION="${installer_version}" sh; then
fail_test "openshell install.sh failed for OPENSHELL_VERSION=${installer_version} (recommended command broken)"
exit 1
fi

# install.sh may place the binary in a directory not yet on PATH.
if ! command -v "${OPENSHELL_BIN}" >/dev/null 2>&1; then
export PATH="${HOME}/.local/bin:${HOME}/.openshell/bin:${PATH}"
hash -r 2>/dev/null || true
fi
if ! command -v "${OPENSHELL_BIN}" >/dev/null 2>&1; then
fail_test "openshell CLI not on PATH after install (OPENSHELL_BIN=${OPENSHELL_BIN})"
exit 1
fi

local reported
reported=$("${OPENSHELL_BIN}" --version 2>&1 || true)
dim " openshell --version: ${reported}"
# install.sh pins OPENSHELL_VERSION exactly, so the CLI must report it. This is
# the guardrail: a mismatched or nonexistent version fails the test here rather
# than silently installing the wrong CLI.
if [[ "$reported" != *"${installer_version#v}"* ]]; then
fail_test "Installed openshell version '${reported}' does not match requested ${installer_version}"
exit 1
fi
pass "openshell CLI installed via console-recommended command (${installer_version})"
}

install_openshell_cli_from_api

GW_LOCAL_NAME="${GW_NAMESPACE}-openshell"

if wait_for_gateway_route "$GW_NAME" "$GW_NAMESPACE"; then
Expand Down
40 changes: 40 additions & 0 deletions tests/e2e/lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,35 @@ retry_until() {
return 1
}

# --- openshell CLI install command ---
#
# The console recommends a gateway-matched install command to users. This helper
# reproduces the version-derivation rule so the e2e test installs the CLI the
# exact same way, catching regressions where the recommended command would break
# (notably for downstream gateway images whose reported version carries a
# "-rh…" build suffix).
#
# CANONICAL SOURCE - keep this in lockstep with buildOpenShellInstallCommand in
# packages/gateway-management-ui/src/gateways/gateway-connections.ts
# The rule: trim, drop the first "-" and everything after it, then ensure a
# leading "v". Returns non-zero when no usable version can be derived (the UI
# returns undefined in the same cases).
openshell_installer_version() {
local raw="$1"
# trim leading/trailing whitespace (mirrors the TS .trim())
raw="${raw#"${raw%%[![:space:]]*}"}"
raw="${raw%"${raw##*[![:space:]]}"}"
[[ -z "$raw" ]] && return 1
# Strip the first "-" and all following text (v0.0.109-rh9a8f8 -> v0.0.109).
local base="${raw%%-*}"
[[ -z "$base" ]] && return 1
if [[ "$base" == v* ]]; then
printf '%s' "$base"
else
printf 'v%s' "$base"
fi
}

# --- Environment defaults ---

: "${E2E_NAMESPACE:=openshell-e2e}"
Expand All @@ -100,6 +129,17 @@ retry_until() {
: "${E2E_SKIP_CLEANUP:=0}"
: "${E2E_PAUSE:=1}"
: "${OPENSHELL_BIN:=openshell}"
# How the e2e test obtains the openshell CLI:
# auto - install the gateway-matched version via the console-recommended
# command if the CLI is not already present (default)
# always - always install the gateway-matched version, even if one is present
# never - require a pre-installed CLI; do not install
: "${E2E_OPENSHELL_INSTALL:=auto}"
# Upstream install script the console links to (installScriptUrl in the UI).
: "${OPENSHELL_INSTALL_SCRIPT_URL:=https://raw.githubusercontent.com/NVIDIA/OpenShell/main/install.sh}"
# Bounded wait for the control plane to reconcile gateway_version from the
# gateway's health endpoint before deriving the install command.
: "${E2E_GATEWAY_VERSION_TIMEOUT:=120}"
: "${E2E_KEYCLOAK_NAMESPACE:=keycloak}"
: "${E2E_OIDC_ISSUER:=https://keycloak.hypershell.localhost/realms/hypershell}"
: "${E2E_OIDC_CLIENT_ID:=hypershell-frontend}"
Expand Down
Loading