diff --git a/acceptance/ssh/connection/out.stdout.txt b/acceptance/ssh/connection/out.stdout.txt index 41cae5e7d16..e69de29bb2d 100644 --- a/acceptance/ssh/connection/out.stdout.txt +++ b/acceptance/ssh/connection/out.stdout.txt @@ -1 +0,0 @@ -Connection successful diff --git a/acceptance/ssh/connection/out.test.toml b/acceptance/ssh/connection/out.test.toml index 06079f65341..9d444f6ae49 100644 --- a/acceptance/ssh/connection/out.test.toml +++ b/acceptance/ssh/connection/out.test.toml @@ -1,4 +1,4 @@ -Local = false +Local = true Cloud = false RequiresCluster = true EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["direct"] diff --git a/acceptance/ssh/connection/output.txt b/acceptance/ssh/connection/output.txt index e69de29bb2d..6c4551026b5 100644 --- a/acceptance/ssh/connection/output.txt +++ b/acceptance/ssh/connection/output.txt @@ -0,0 +1,29 @@ + +>>> print_requests.py //api/2.2/jobs/runs/submit +{ + "method": "POST", + "path": "/api/2.2/jobs/runs/submit", + "body": { + "run_name": "ssh-server-bootstrap-[TEST_DEFAULT_CLUSTER_ID]", + "tasks": [ + { + "existing_cluster_id": "[TEST_DEFAULT_CLUSTER_ID]", + "notebook_task": { + "base_parameters": { + "authorizedKeySecretName": "client-public-key", + "maxClients": "10", + "secretScopeName": "[USERNAME]-[TEST_DEFAULT_CLUSTER_ID]-ssh-tunnel-keys", + "serverless": "false", + "sessionId": "[TEST_DEFAULT_CLUSTER_ID]", + "shutdownDelay": "10m0s", + "version": "[CLI_VERSION]" + }, + "notebook_path": "/Workspace/Users/[USERNAME]/.databricks/ssh-tunnel/[CLI_VERSION]/[TEST_DEFAULT_CLUSTER_ID]/ssh-server-bootstrap" + }, + "task_key": "start_ssh_server", + "timeout_seconds": 86400 + } + ], + "timeout_seconds": 86400 + } +} diff --git a/acceptance/ssh/connection/script b/acceptance/ssh/connection/script index 39e8b39ef4b..3e206bfbb01 100644 --- a/acceptance/ssh/connection/script +++ b/acceptance/ssh/connection/script @@ -1,6 +1,22 @@ +if [ -z "${CLOUD_ENV:-}" ]; then + # Local runs have no release artifacts and never execute the uploaded + # binaries, so stand in empty archives (dev name omits the version). + mkdir -p releases + : >releases/databricks_cli_linux_amd64.zip + : >releases/databricks_cli_linux_arm64.zip + CLI_RELEASES_DIR="$PWD/releases" +fi + errcode $CLI ssh connect --cluster=$TEST_DEFAULT_CLUSTER_ID --releases-dir=$CLI_RELEASES_DIR --user-known-hosts-file=known_hosts -- "echo 'Connection successful'" >out.stdout.txt 2>LOG.stderr -if ! grep -q "Connection successful" out.stdout.txt; then - run_id=$(cat LOG.stderr | grep -o "Job submitted successfully with run ID: [0-9]*" | grep -o "[0-9]*$") - trace $CLI jobs get-run "$run_id" > LOG.job +if [ -n "${CLOUD_ENV:-}" ]; then + # On cloud the connection runs the remote command; dump the run on failure. + if ! grep -q "Connection successful" out.stdout.txt; then + run_id=$(cat LOG.stderr | grep -o "Job submitted successfully with run ID: [0-9]*" | grep -o "[0-9]*$") + trace $CLI jobs get-run "$run_id" > LOG.job + fi +else + # Locally the handshake can't complete (no compute); just assert the CLI + # submitted the right dedicated-cluster bootstrap job. + trace print_requests.py //api/2.2/jobs/runs/submit fi diff --git a/acceptance/ssh/connection/test.toml b/acceptance/ssh/connection/test.toml index 76965d3ae0e..e2a33c0a5b9 100644 --- a/acceptance/ssh/connection/test.toml +++ b/acceptance/ssh/connection/test.toml @@ -1,6 +1,17 @@ -Local = false +Local = true Cloud = false + +# On cloud this needs a real dedicated single-user cluster; locally the default +# test cluster stands in for it. RequiresCluster = true +# Assert the dedicated-cluster bootstrap job the CLI submits on a local run. +RecordRequests = true + +# Local runs stage stand-in release archives here; not part of the golden output. +Ignore = [ + "releases", +] + [EnvMatrix] DATABRICKS_BUNDLE_ENGINE = ["direct"] diff --git a/libs/testserver/fake_workspace.go b/libs/testserver/fake_workspace.go index 1c5d842f0f8..df9499c7e91 100644 --- a/libs/testserver/fake_workspace.go +++ b/libs/testserver/fake_workspace.go @@ -382,9 +382,15 @@ func NewFakeWorkspace(url, token string) *FakeWorkspace { ModelRegistryModels: map[string]ml.Model{}, ModelRegistryModelIDs: map[string]string{}, Clusters: map[string]compute.ClusterDetails{ + // A running dedicated single-user cluster: the shape `ssh connect --cluster` + // requires (ValidateClusterAccess rejects anything else), matching the cloud + // TEST_DEFAULT_CLUSTER_ID this stands in for. TestDefaultClusterId: { - ClusterId: TestDefaultClusterId, - ClusterName: "DEFAULT Test Cluster", + ClusterId: TestDefaultClusterId, + ClusterName: "DEFAULT Test Cluster", + State: compute.StateRunning, + DataSecurityMode: compute.DataSecurityModeSingleUser, + SingleUserName: TestUser.UserName, }, }, }