Skip to content

acc: converge ssh/connect-serverless-gpu tunnel test onto a local web…#5920

Merged
radakam merged 8 commits into
mainfrom
acc-ssh-serverless-gpu-tunnel
Jul 15, 2026
Merged

acc: converge ssh/connect-serverless-gpu tunnel test onto a local web…#5920
radakam merged 8 commits into
mainfrom
acc-ssh-serverless-gpu-tunnel

Conversation

@radakam

@radakam radakam commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Changes

Follow-up to #5878, converging the SSH tunnel's two test styles into one acceptance test. Two enabling changes: derive the driver-proxy websocket scheme from the host (httpws, else wss) instead of hardcoding wss so the client can dial the plaintext local test server, and add a testserver /ssh websocket route (via a new connection-hijacking Router.HandleRaw) that upgrades the driver-proxy request to a real sshd -i and bridges binary frames to its stdio, standing in for the tunnel server a real cluster runs — no Databricks compute required.

The /ssh handler reads the client public key the CLI uploaded via secrets/put (the ws dial carries the bearer token, so the token-scoped workspace is the one that stored it), writes an ephemeral host key + authorized_keys + a minimal sshd_config, and pumps websocket frames to and from sshd's stdin/stdout. /metadata now returns the current OS user so ssh -l <user> matches the account sshd runs as.

acceptance/ssh/connect-serverless-gpu now runs a single local ssh connect ... -- "echo 'Connection successful'" that both submits the serverless-GPU bootstrap job and completes a genuine SSH handshake, public-key auth, and remote command exec over the ws:// tunnel, asserting both the job payload and the command output. This makes TestClientServerRealSSHD redundant, so it's removed; the cat-echo transport tests in client_server_test.go remain.

Note the converged test exercises the real handshake on the client side only: the /ssh route is a testserver stand-in, not the production proxy.NewProxyServer/runServerProxy, so the server proxy's transport stays covered by the cat-echo tests rather than by a real handshake. This is a deliberate trade-off (runServerProxy is protocol-agnostic), not an accidental coverage drop.

The handshake needs a real OpenSSH server: the test self-skips via SKIP_TEST when sshd is absent (the general test job doesn't provision it; task test-exp-ssh installs openssh-server on Linux). It's pinned to Linux (darwin/windows disabled), where running sshd -i as a non-root user with a throwaway config is reliable — matching the removed Go test's rationale.

Tests

  • acceptance/ssh/connect-serverless-gpu (bootstrap job payload + real SSH handshake and remote exec over the ws:// tunnel)
  • TestBuildProxyWebsocketURL (ws/wss scheme selection)

…socket route

Follow-up to #5878. That PR covered the SSH tunnel in two styles: an acceptance
test asserting the submitted bootstrap job, and a Go test (TestClientServerRealSSHD)
driving the tunnel transport. This folds the tunnel coverage into the acceptance
test so a single local run exercises both layers.

Two enabling changes:

- Product fix (experimental/ssh/internal/client/websockets.go): derive the
  websocket scheme from the workspace host (http -> ws, else wss) instead of
  hardcoding wss, so the client can dial the plaintext local test server. Adds a
  unit test for the URL builder.
- Test server (libs/testserver): add a raw, connection-hijacking handler
  registration (Router.HandleRaw) plus a driver-proxy /ssh websocket route that
  echoes binary frames, standing in for the SSH tunnel server a real cluster runs.
  In-process, so it also works on Windows.

acceptance/ssh/connect-serverless-gpu now runs a single `ssh connect --proxy`
locally: it submits the same serverless-GPU bootstrap job and pipes stdin/stdout
over the tunnel, asserting both the job payload and the echoed bytes. Proxy mode
skips the ssh subprocess, so it doesn't hang looping a handshake against the echo.
@radakam radakam temporarily deployed to test-trigger-is July 14, 2026 08:36 — with GitHub Actions Inactive
@radakam radakam temporarily deployed to test-trigger-is July 14, 2026 08:36 — with GitHub Actions Inactive
@radakam radakam temporarily deployed to test-trigger-is July 14, 2026 08:39 — with GitHub Actions Inactive
@radakam radakam temporarily deployed to test-trigger-is July 14, 2026 08:39 — with GitHub Actions Inactive
@eng-dev-ecosystem-bot

eng-dev-ecosystem-bot commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

Integration test report

Commit: 04c8e74

Run: 29324416011

Env 🟨​KNOWN 🔄​flaky 💚​RECOVERED 🙈​SKIP ✅​pass 🙈​skip Time
💚​ aws linux 4 4 230 1087 5:59
💚​ aws windows 4 4 232 1085 7:34
🔄​ aws-ucws linux 3 3 4 314 1004 10:18
💚​ aws-ucws windows 4 4 318 1002 7:46
🟨​ azure linux 3 1 4 230 1086 10:41
🟨​ azure windows 1 2 1 4 232 1084 11:41
🔄​ azure-ucws linux 2 4 4 316 1001 9:33
💚​ azure-ucws windows 4 4 320 999 7:59
💚​ gcp linux 4 4 229 1088 6:16
💚​ gcp windows 4 4 231 1086 7:49
12 interesting tests: 5 flaky, 4 SKIP, 3 KNOWN
Test Name aws linux aws windows aws-ucws linux aws-ucws windows azure linux azure windows azure-ucws linux azure-ucws windows gcp linux gcp windows
🔄​ TestAccept 💚​R 💚​R 🔄​f 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
🙈​ TestAccept/bundle/invariant/no_drift 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/vector_search_endpoints/drift/recreated_same_name 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/vector_search_indexes/recreate/embedding_dimension 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🔄​ TestAccept/ssh/connect-serverless-cpu 🙈​s 🙈​s 🔄​f ✅​p 🙈​s 🙈​s ✅​p ✅​p 🙈​s 🙈​s
🔄​ TestAccept/ssh/connect-serverless-cpu/DATABRICKS_BUNDLE_ENGINE=direct 🔄​f ✅​p ✅​p ✅​p
🙈​ TestAccept/ssh/connection 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🔄​ TestFsCpFileToDir ✅​p ✅​p ✅​p ✅​p ✅​p ✅​p 🔄​f ✅​p ✅​p ✅​p
🔄​ TestFsCpFileToDir/dbfs_to_local ✅​p ✅​p ✅​p ✅​p ✅​p ✅​p 🔄​f ✅​p ✅​p ✅​p
🟨​ TestFetchRepositoryInfoAPI_FromRepo 💚​R 💚​R 💚​R 💚​R 🟨​K 🔄​f 💚​R 💚​R 💚​R 💚​R
🟨​ TestFetchRepositoryInfoAPI_FromRepo/root 💚​R 💚​R 💚​R 💚​R 🟨​K 🔄​f 💚​R 💚​R 💚​R 💚​R
🟨​ TestFetchRepositoryInfoAPI_FromRepo/subdir 💚​R 💚​R 💚​R 💚​R 🟨​K 🟨​K 💚​R 💚​R 💚​R 💚​R
Top 12 slowest tests (at least 2 minutes):
duration env testname
6:16 azure windows TestAccept
6:13 gcp windows TestAccept
6:10 aws windows TestAccept
6:10 aws-ucws windows TestAccept
5:59 azure-ucws windows TestAccept
3:29 aws windows TestSecretsPutSecretStringValue
2:55 azure linux TestAccept
2:54 gcp linux TestAccept
2:51 aws linux TestAccept
2:45 azure-ucws linux TestAccept
2:19 azure linux TestAccept/bundle/deploy/mlops-stacks/DATABRICKS_BUNDLE_ENGINE=terraform
2:03 azure-ucws windows TestFilerWorkspaceFilesExtensionsReadDir

@radakam radakam marked this pull request as ready for review July 14, 2026 09:09
…s locally

Deepens the convergence started earlier on this branch. Instead of echoing
frames, the test server now upgrades the driver-proxy /ssh websocket to a real
`sshd -i` and bridges binary frames to its stdio, so a single local
`ssh connect ... -- "echo ..."` completes a genuine SSH handshake, public-key
auth, and remote command exec with no Databricks compute.

- libs/testserver: replace the echo handler with (*Server).sshTunnelHandler,
  which reads the CLI's uploaded client-public-key secret (the ws dial carries
  the bearer token, so the token-scoped workspace is the one that stored it),
  writes an ephemeral host key + authorized_keys + a minimal sshd_config, spawns
  sshd, and pumps ws frames <-> sshd stdin/stdout. /metadata now returns the
  current OS user so `ssh -l <user>` matches the account sshd runs as.
- acceptance/ssh/connect-serverless-gpu: run the full handshake locally, still
  assert the bootstrap job payload, and self-skip via SKIP_TEST when sshd is
  absent (the general test job doesn't provision it; task test-exp-ssh does).
  Gated to linux, matching the removed Go test's rationale.
- Delete TestClientServerRealSSHD: the acceptance test now covers the real
  handshake end to end, so the Go stand-in is redundant. The cat-echo transport
  tests remain.
@radakam radakam temporarily deployed to test-trigger-is July 14, 2026 09:39 — with GitHub Actions Inactive
@radakam radakam temporarily deployed to test-trigger-is July 14, 2026 09:39 — with GitHub Actions Inactive
CI caught two issues in the previous commit:

- lint: use sync.OnceFunc and wg.Go instead of sync.Once/wg.Add+Done in the
  test server's ssh handler.
- GOOS keys absent from the map default to enabled, so `linux = true` alone did
  not disable macOS/Windows. They ran the handshake: macOS found its system sshd
  and hung, Windows found sshd.exe and failed fast. Disable darwin and windows
  explicitly to keep the test Linux-only.
@radakam radakam temporarily deployed to test-trigger-is July 14, 2026 09:59 — with GitHub Actions Inactive
@radakam radakam temporarily deployed to test-trigger-is July 14, 2026 09:59 — with GitHub Actions Inactive
@radakam radakam temporarily deployed to test-trigger-is July 14, 2026 10:10 — with GitHub Actions Inactive
@radakam radakam temporarily deployed to test-trigger-is July 14, 2026 10:10 — with GitHub Actions Inactive
@radakam radakam requested a review from anton-107 July 14, 2026 11:12

@anton-107 anton-107 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approve — nicely done. The convergence works: the CLI subprocess drives the real client proxy (RunClientProxy) while the testserver upgrades /ssh to a real sshd -i, so one local run genuinely exercises handshake + pubkey auth + remote exec with no compute. Confirmed it actually runs (not skipped): TestAccept/ssh/connect-serverless-gpu passes in ~0.5s on the Linux test-exp-ssh job. The buildProxyWebsocketURL http→ws / else→wss refactor is correct for all real inputs (Config.Host is always scheme-normalized by the SDK before use).

One non-blocking note on test strategy: the deleted TestClientServerRealSSHD was the only test that carried a real SSH handshake through the production server proxy (proxy.NewProxyServer/runServerProxy). The new libs/testserver/ssh.go handler is a hand-rolled ws↔sshd pump that never calls NewProxyServer, so that specific coverage is lost. It is narrow — runServerProxy is protocol-agnostic and the surviving cat-echo tests still drive it end-to-end for frame pumping / interleaving / handover — what is uniquely gone is the real-handshake banner emission and natural-sshd-exit teardown ordering. Low regression-escape risk, so not a blocker, but worth a sentence in the description that this is a client-side-only real-handshake test. If cheap, having sshTunnelHandler delegate to proxy.NewProxyServer would reclaim the coverage and drop the duplicated pump/findSSHD logic.

Minor, optional: a one-line t.Logf on the early-return failure paths in sshTunnelHandler (missing secret / pipe / Start error) would make a future breakage self-explanatory instead of surfacing only as an empty-stdout golden diff.

The testserver /ssh handler returned silently on every setup failure
(missing secret, pipe/Start errors, etc.), so a broken sshd setup only
surfaced as an empty-stdout golden diff. Log each early-return reason so
a future breakage is self-explanatory.
@radakam radakam temporarily deployed to test-trigger-is July 15, 2026 06:50 — with GitHub Actions Inactive
@radakam radakam temporarily deployed to test-trigger-is July 15, 2026 06:50 — with GitHub Actions Inactive
@radakam radakam temporarily deployed to test-trigger-is July 15, 2026 07:12 — with GitHub Actions Inactive
@radakam radakam temporarily deployed to test-trigger-is July 15, 2026 07:12 — with GitHub Actions Inactive
The testserver /ssh route now drives a real sshd, so ssh/connection's
local run completes a genuine handshake and remote exec instead of
producing nothing. Mirror connect-serverless-gpu: skip when sshd is
absent, gate to Linux (macOS hangs on system sshd, Windows differs), and
record "Connection successful" as the golden stdout.
@radakam radakam temporarily deployed to test-trigger-is July 15, 2026 08:53 — with GitHub Actions Inactive
@radakam radakam temporarily deployed to test-trigger-is July 15, 2026 08:53 — with GitHub Actions Inactive
@radakam radakam enabled auto-merge July 15, 2026 08:55
@radakam radakam disabled auto-merge July 15, 2026 10:56
@radakam radakam merged commit 1b5e966 into main Jul 15, 2026
25 of 26 checks passed
@radakam radakam deleted the acc-ssh-serverless-gpu-tunnel branch July 15, 2026 10:57
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.

3 participants