Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
d7899af
WIP: Add serverless GPU compute support to SSH tunnel
ilia-db Dec 19, 2025
140560e
Add liteswap header value for traffic routing (dev/test only).
ilia-db Dec 23, 2025
28c330e
Add liteswap option to the ProxyCommand.
ilia-db Dec 23, 2025
aa44ec9
Fix lint error
ilia-db Jan 9, 2026
9151da1
Add GPU accelerator support for serverless compute
ilia-db Jan 19, 2026
f488a38
Don't log metadata response to stdout
ilia-db Jan 19, 2026
3bf460d
Move metadata URL logging to debug level
ilia-db Jan 19, 2026
9961ebf
Simplify SSH tunnel job polling
ilia-db Jan 27, 2026
6a6f4f8
Make sure that connection name is not empty in serverless mode
ilia-db Feb 6, 2026
7040a1f
Extract serverless environment key to a constant
ilia-db Feb 6, 2026
a4d274e
Add IDE flag and support for IDE integration for vscode and cursor
ilia-db Jan 19, 2026
a0009d8
Mark hidden flags for serverless compute, remove manual Http call
ilia-db Feb 5, 2026
51b8b26
Separate IDE options into constants
ilia-db Feb 6, 2026
abb3157
Move unnecessary logging to debug level
ilia-db Feb 10, 2026
627868c
Remove dedicated cluster and serverless compute specific documentatio…
ilia-db Feb 12, 2026
a6a0cf9
New config logic
ilia-db Jan 23, 2026
f0b080c
Always recreate SSH config entry
ilia-db Jan 29, 2026
79f9ff5
Fix sshconfig logic and tests on Windows
ilia-db Feb 2, 2026
27dc6d4
Do not create secret scope if it already exists
ilia-db Feb 2, 2026
a671229
Better SSHD config escaping
ilia-db Feb 3, 2026
9ab10c3
Avoid duplication of host config generation code
ilia-db Feb 5, 2026
1595782
Escape backslashes in SetEnv values
ilia-db Feb 6, 2026
cbf2cdb
Initialize Spark Connect session in Jupyter init script
ilia-db Feb 5, 2026
d606086
Format jupyter-init.py
ilia-db Feb 5, 2026
4dc0faa
Use DatabricksSession for Spark Connect session initialization
ilia-db Feb 10, 2026
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
39 changes: 37 additions & 2 deletions experimental/ssh/cmd/connect.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package ssh

import (
"errors"
"time"

"github.com/databricks/cli/cmd/root"
Expand All @@ -22,21 +23,31 @@ the SSH server and handling the connection proxy.
}

var clusterID string
var connectionName string
var accelerator string
var proxyMode bool
var ide string
var serverMetadata string
var shutdownDelay time.Duration
var maxClients int
var handoverTimeout time.Duration
var releasesDir string
var autoStartCluster bool
var userKnownHostsFile string
var liteswap string

cmd.Flags().StringVar(&clusterID, "cluster", "", "Databricks cluster ID (required)")
cmd.MarkFlagRequired("cluster")
cmd.Flags().StringVar(&clusterID, "cluster", "", "Databricks cluster ID (for dedicated clusters)")
cmd.Flags().DurationVar(&shutdownDelay, "shutdown-delay", defaultShutdownDelay, "Delay before shutting down the server after the last client disconnects")
cmd.Flags().IntVar(&maxClients, "max-clients", defaultMaxClients, "Maximum number of SSH clients")
cmd.Flags().BoolVar(&autoStartCluster, "auto-start-cluster", true, "Automatically start the cluster if it is not running")

cmd.Flags().StringVar(&connectionName, "name", "", "Connection name (for serverless compute)")
cmd.Flags().MarkHidden("name")
cmd.Flags().StringVar(&accelerator, "accelerator", "", "GPU accelerator type (GPU_1xA10 or GPU_8xH100)")
cmd.Flags().MarkHidden("accelerator")
cmd.Flags().StringVar(&ide, "ide", "", "Open remote IDE window (vscode or cursor)")
cmd.Flags().MarkHidden("ide")

cmd.Flags().BoolVar(&proxyMode, "proxy", false, "ProxyCommand mode")
cmd.Flags().MarkHidden("proxy")
cmd.Flags().StringVar(&serverMetadata, "metadata", "", "Metadata of the running SSH server (format: <user_name>,<port>)")
Expand All @@ -50,6 +61,9 @@ the SSH server and handling the connection proxy.
cmd.Flags().StringVar(&userKnownHostsFile, "user-known-hosts-file", "", "Path to user known hosts file for SSH client")
cmd.Flags().MarkHidden("user-known-hosts-file")

cmd.Flags().StringVar(&liteswap, "liteswap", "", "Liteswap header value for traffic routing (dev/test only)")
cmd.Flags().MarkHidden("liteswap")

cmd.PreRunE = func(cmd *cobra.Command, args []string) error {
// CLI in the proxy mode is executed by the ssh client and can't prompt for input
if proxyMode {
Expand All @@ -64,20 +78,41 @@ the SSH server and handling the connection proxy.
cmd.RunE = func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
wsClient := cmdctx.WorkspaceClient(ctx)

if !proxyMode && clusterID == "" && connectionName == "" {
return errors.New("please provide --cluster flag with the cluster ID, or --name flag with the connection name (for serverless compute)")
}

if accelerator != "" && connectionName == "" {
return errors.New("--accelerator flag can only be used with serverless compute (--name flag)")
}

// Remove when we add support for serverless CPU
if connectionName != "" && accelerator == "" {
return errors.New("--name flag requires --accelerator to be set (for now we only support serverless GPU compute)")
}

// TODO: validate connectionName if provided

opts := client.ClientOptions{
Profile: wsClient.Config.Profile,
ClusterID: clusterID,
ConnectionName: connectionName,
Accelerator: accelerator,
ProxyMode: proxyMode,
IDE: ide,
ServerMetadata: serverMetadata,
ShutdownDelay: shutdownDelay,
MaxClients: maxClients,
HandoverTimeout: handoverTimeout,
ReleasesDir: releasesDir,
ServerTimeout: max(serverTimeout, shutdownDelay),
TaskStartupTimeout: taskStartupTimeout,
AutoStartCluster: autoStartCluster,
ClientPublicKeyName: clientPublicKeyName,
ClientPrivateKeyName: clientPrivateKeyName,
UserKnownHostsFile: userKnownHostsFile,
Liteswap: liteswap,
AdditionalArgs: args,
}
return client.Run(ctx, wsClient, opts)
Expand Down
1 change: 1 addition & 0 deletions experimental/ssh/cmd/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const (
defaultHandoverTimeout = 30 * time.Minute

serverTimeout = 24 * time.Hour
taskStartupTimeout = 10 * time.Minute
serverPortRange = 100
serverConfigDir = ".ssh-tunnel"
serverPrivateKeyName = "server-private-key"
Expand Down
4 changes: 4 additions & 0 deletions experimental/ssh/cmd/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,15 @@ and proxies them to local SSH daemon processes.
var maxClients int
var shutdownDelay time.Duration
var clusterID string
var sessionID string
var version string
var secretScopeName string
var authorizedKeySecretName string

cmd.Flags().StringVar(&clusterID, "cluster", "", "Databricks cluster ID")
cmd.MarkFlagRequired("cluster")
cmd.Flags().StringVar(&sessionID, "session-id", "", "Session identifier (cluster ID or serverless connection name)")
cmd.MarkFlagRequired("session-id")
cmd.Flags().StringVar(&secretScopeName, "secret-scope-name", "", "Databricks secret scope name to store SSH keys")
cmd.MarkFlagRequired("secret-scope-name")
cmd.Flags().StringVar(&authorizedKeySecretName, "authorized-key-secret-name", "", "Name of the secret containing the client public key")
Expand All @@ -56,6 +59,7 @@ and proxies them to local SSH daemon processes.
wsc := cmdctx.WorkspaceClient(ctx)
opts := server.ServerOptions{
ClusterID: clusterID,
SessionID: sessionID,
MaxClients: maxClients,
ShutdownDelay: shutdownDelay,
Version: version,
Expand Down
21 changes: 17 additions & 4 deletions experimental/ssh/cmd/setup.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package ssh

import (
"fmt"
"time"

"github.com/databricks/cli/cmd/root"
"github.com/databricks/cli/experimental/ssh/internal/client"
"github.com/databricks/cli/experimental/ssh/internal/setup"
"github.com/databricks/cli/libs/cmdctx"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -43,16 +45,27 @@ an SSH host configuration to your SSH config file.

cmd.RunE = func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
client := cmdctx.WorkspaceClient(ctx)
opts := setup.SetupOptions{
wsClient := cmdctx.WorkspaceClient(ctx)
setupOpts := setup.SetupOptions{
HostName: hostName,
ClusterID: clusterID,
AutoStartCluster: autoStartCluster,
SSHConfigPath: sshConfigPath,
ShutdownDelay: shutdownDelay,
Profile: client.Config.Profile,
Profile: wsClient.Config.Profile,
}
return setup.Setup(ctx, client, opts)
clientOpts := client.ClientOptions{
ClusterID: setupOpts.ClusterID,
AutoStartCluster: setupOpts.AutoStartCluster,
ShutdownDelay: setupOpts.ShutdownDelay,
Profile: setupOpts.Profile,
}
proxyCommand, err := clientOpts.ToProxyCommand()
if err != nil {
return fmt.Errorf("failed to generate ProxyCommand: %w", err)
}
setupOpts.ProxyCommand = proxyCommand
return setup.Setup(ctx, wsClient, setupOpts)
}

return cmd
Expand Down
Loading
Loading