Skip to content

Commit da4953f

Browse files
committed
Add ssh connect command
1 parent ead9e8c commit da4953f

File tree

14 files changed

+1267
-3
lines changed

14 files changed

+1267
-3
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,6 @@ tools/yamlfmt.exe
3636

3737
# Cache for tools/gh_report.py
3838
.gh-logs
39+
40+
# Release artifacts
41+
dist/

Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,11 @@ build-vm: tidy
8888
snapshot:
8989
go build -o .databricks/databricks
9090

91+
# Produce release binaries and archives in the dist folder without uploading them anywhere.
92+
# Useful for "databricks ssh" development, as it needs to upload linux releases to the /Workspace.
93+
snapshot-release:
94+
goreleaser release --clean --skip docker --snapshot
95+
9196
schema:
9297
go run ./bundle/internal/schema ./bundle/internal/schema ./bundle/schema/jsonschema.json
9398

cmd/ssh/connect.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package ssh
2+
3+
import (
4+
"time"
5+
6+
"github.com/databricks/cli/cmd/root"
7+
"github.com/databricks/cli/libs/cmdctx"
8+
"github.com/databricks/cli/libs/ssh"
9+
"github.com/spf13/cobra"
10+
)
11+
12+
func newConnectCommand() *cobra.Command {
13+
cmd := &cobra.Command{
14+
Use: "connect",
15+
Short: "Connect to Databricks compute via SSH",
16+
Long: `Connect to Databricks compute via SSH.
17+
18+
This command establishes an SSH connection to Databricks compute, setting up
19+
the SSH server and handling the connection proxy.
20+
21+
` + disclaimer,
22+
}
23+
24+
var clusterID string
25+
var proxyMode bool
26+
var serverMetadata string
27+
var shutdownDelay time.Duration
28+
var maxClients int
29+
var handoverTimeout time.Duration
30+
var releasesDir string
31+
32+
cmd.Flags().StringVar(&clusterID, "cluster", "", "Databricks cluster ID (required)")
33+
cmd.MarkFlagRequired("cluster")
34+
cmd.Flags().DurationVar(&shutdownDelay, "shutdown-delay", 10*time.Minute, "Delay before shutting down the server after the last client disconnects")
35+
cmd.Flags().IntVar(&maxClients, "max-clients", 10, "Maximum number of SSH clients")
36+
37+
cmd.Flags().BoolVar(&proxyMode, "proxy", false, "ProxyCommand mode")
38+
cmd.Flags().MarkHidden("proxy")
39+
cmd.Flags().StringVar(&serverMetadata, "metadata", "", "Metadata of the running SSH server (format: <user_name>,<port>)")
40+
cmd.Flags().MarkHidden("metadata")
41+
cmd.Flags().DurationVar(&handoverTimeout, "handover-timeout", 30*time.Minute, "How often the CLI should reconnect to the server with new auth")
42+
cmd.Flags().MarkHidden("handover-timeout")
43+
44+
cmd.Flags().StringVar(&releasesDir, "releases-dir", "", "Directory for local SSH tunnel development releases")
45+
cmd.Flags().MarkHidden("releases-dir")
46+
47+
cmd.PreRunE = root.MustWorkspaceClient
48+
cmd.RunE = func(cmd *cobra.Command, args []string) error {
49+
ctx := cmd.Context()
50+
client := cmdctx.WorkspaceClient(ctx)
51+
opts := ssh.ClientOptions{
52+
ClusterID: clusterID,
53+
ProxyMode: proxyMode,
54+
ServerMetadata: serverMetadata,
55+
ShutdownDelay: shutdownDelay,
56+
MaxClients: maxClients,
57+
HandoverTimeout: handoverTimeout,
58+
ReleasesDir: releasesDir,
59+
AdditionalArgs: args,
60+
ClientPublicKeyName: "client-public-key",
61+
}
62+
return ssh.RunClient(ctx, client, opts)
63+
}
64+
65+
return cmd
66+
}

cmd/ssh/ssh.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ Common workflows:
2828
}
2929

3030
cmd.AddCommand(newSetupCommand())
31+
cmd.AddCommand(newConnectCommand())
3132

3233
return cmd
3334
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ require (
2828
github.com/spf13/cobra v1.9.1 // Apache 2.0
2929
github.com/spf13/pflag v1.0.7 // BSD-3-Clause
3030
github.com/stretchr/testify v1.11.0 // MIT
31+
golang.org/x/crypto v0.41.0 // BSD-3-Clause
3132
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b
3233
golang.org/x/mod v0.27.0
3334
golang.org/x/oauth2 v0.30.0
@@ -75,7 +76,6 @@ require (
7576
go.opentelemetry.io/otel v1.36.0 // indirect
7677
go.opentelemetry.io/otel/metric v1.36.0 // indirect
7778
go.opentelemetry.io/otel/trace v1.36.0 // indirect
78-
golang.org/x/crypto v0.40.0 // indirect
7979
golang.org/x/net v0.42.0 // indirect
8080
golang.org/x/time v0.12.0 // indirect
8181
golang.org/x/tools v0.35.0 // indirect

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,8 @@ go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFw
173173
go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4=
174174
go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w=
175175
go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA=
176-
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
177-
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
176+
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
177+
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
178178
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o=
179179
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8=
180180
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=

0 commit comments

Comments
 (0)