Skip to content

Commit 24b95e1

Browse files
authored
feat: add --disable-direct flag to CLI (coder#8131)
1 parent bc739bd commit 24b95e1

File tree

11 files changed

+90
-16
lines changed

11 files changed

+90
-16
lines changed

cli/ping.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,13 @@ func (r *RootCmd) ping() *clibase.Cmd {
4949
logger = slog.Make(sloghuman.Sink(inv.Stdout)).Leveled(slog.LevelDebug)
5050
}
5151

52-
conn, err := client.DialWorkspaceAgent(ctx, workspaceAgent.ID, &codersdk.DialWorkspaceAgentOptions{Logger: logger})
52+
if r.disableDirect {
53+
_, _ = fmt.Fprintln(inv.Stderr, "Direct connections disabled.")
54+
}
55+
conn, err := client.DialWorkspaceAgent(ctx, workspaceAgent.ID, &codersdk.DialWorkspaceAgentOptions{
56+
Logger: logger,
57+
BlockEndpoints: r.disableDirect,
58+
})
5359
if err != nil {
5460
return err
5561
}

cli/portforward.go

+15-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ import (
1515
"github.com/pion/udp"
1616
"golang.org/x/xerrors"
1717

18+
"cdr.dev/slog"
19+
"cdr.dev/slog/sloggers/sloghuman"
20+
1821
"github.com/coder/coder/agent/agentssh"
1922
"github.com/coder/coder/cli/clibase"
2023
"github.com/coder/coder/cli/cliui"
@@ -98,7 +101,18 @@ func (r *RootCmd) portForward() *clibase.Cmd {
98101
return xerrors.Errorf("await agent: %w", err)
99102
}
100103

101-
conn, err := client.DialWorkspaceAgent(ctx, workspaceAgent.ID, nil)
104+
var logger slog.Logger
105+
if r.verbose {
106+
logger = slog.Make(sloghuman.Sink(inv.Stdout)).Leveled(slog.LevelDebug)
107+
}
108+
109+
if r.disableDirect {
110+
_, _ = fmt.Fprintln(inv.Stderr, "Direct connections disabled.")
111+
}
112+
conn, err := client.DialWorkspaceAgent(ctx, workspaceAgent.ID, &codersdk.DialWorkspaceAgentOptions{
113+
Logger: logger,
114+
BlockEndpoints: r.disableDirect,
115+
})
102116
if err != nil {
103117
return err
104118
}

cli/root.go

+20-10
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ const (
6060
varNoFeatureWarning = "no-feature-warning"
6161
varForceTty = "force-tty"
6262
varVerbose = "verbose"
63+
varDisableDirect = "disable-direct-connections"
6364
notLoggedInMessage = "You are not logged in. Try logging in using 'coder login <url>'."
6465

6566
envNoVersionCheck = "CODER_NO_VERSION_WARNING"
@@ -367,6 +368,13 @@ func (r *RootCmd) Command(subcommands []*clibase.Cmd) (*clibase.Cmd, error) {
367368
Value: clibase.BoolOf(&r.verbose),
368369
Group: globalGroup,
369370
},
371+
{
372+
Flag: varDisableDirect,
373+
Env: "CODER_DISABLE_DIRECT_CONNECTIONS",
374+
Description: "Disable direct (P2P) connections to workspaces.",
375+
Value: clibase.BoolOf(&r.disableDirect),
376+
Group: globalGroup,
377+
},
370378
{
371379
Flag: "debug-http",
372380
Description: "Debug codersdk HTTP requests.",
@@ -413,16 +421,17 @@ func isTest() bool {
413421

414422
// RootCmd contains parameters and helpers useful to all commands.
415423
type RootCmd struct {
416-
clientURL *url.URL
417-
token string
418-
globalConfig string
419-
header []string
420-
agentToken string
421-
agentURL *url.URL
422-
forceTTY bool
423-
noOpen bool
424-
verbose bool
425-
debugHTTP bool
424+
clientURL *url.URL
425+
token string
426+
globalConfig string
427+
header []string
428+
agentToken string
429+
agentURL *url.URL
430+
forceTTY bool
431+
noOpen bool
432+
verbose bool
433+
disableDirect bool
434+
debugHTTP bool
426435

427436
noVersionCheck bool
428437
noFeatureWarning bool
@@ -524,6 +533,7 @@ func (r *RootCmd) InitClient(client *codersdk.Client) clibase.MiddlewareFunc {
524533
client.PlainLogger = os.Stderr
525534
client.LogBodies = true
526535
}
536+
client.DisableDirectConnections = r.disableDirect
527537

528538
// We send these requests in parallel to minimize latency.
529539
var (

cli/speedtest.go

+5
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,18 @@ func (r *RootCmd) speedtest() *clibase.Cmd {
5050
if err != nil && !xerrors.Is(err, cliui.AgentStartError) {
5151
return xerrors.Errorf("await agent: %w", err)
5252
}
53+
5354
logger, ok := LoggerFromContext(ctx)
5455
if !ok {
5556
logger = slog.Make(sloghuman.Sink(inv.Stderr))
5657
}
5758
if r.verbose {
5859
logger = logger.Leveled(slog.LevelDebug)
5960
}
61+
62+
if r.disableDirect {
63+
_, _ = fmt.Fprintln(inv.Stderr, "Direct connections disabled.")
64+
}
6065
conn, err := client.DialWorkspaceAgent(ctx, workspaceAgent.ID, &codersdk.DialWorkspaceAgentOptions{
6166
Logger: logger,
6267
})

cli/ssh.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -195,8 +195,12 @@ func (r *RootCmd) ssh() *clibase.Cmd {
195195
// We don't print the error because cliui.Agent does that for us.
196196
}
197197

198+
if r.disableDirect {
199+
_, _ = fmt.Fprintln(inv.Stderr, "Direct connections disabled.")
200+
}
198201
conn, err := client.DialWorkspaceAgent(ctx, workspaceAgent.ID, &codersdk.DialWorkspaceAgentOptions{
199-
Logger: logger,
202+
Logger: logger,
203+
BlockEndpoints: r.disableDirect,
200204
})
201205
if err != nil {
202206
return xerrors.Errorf("dial agent: %w", err)

cli/testdata/coder_--help.golden

+3
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ variables or flags.
5151
--debug-options bool
5252
Print all options, how they're set, then exit.
5353

54+
--disable-direct-connections bool, $CODER_DISABLE_DIRECT_CONNECTIONS
55+
Disable direct (P2P) connections to workspaces.
56+
5457
--global-config string, $CODER_CONFIG_DIR (default: ~/.config/coderv2)
5558
Path to the global `coder` config directory.
5659

cli/vscodessh.go

+15-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ import (
1717
"tailscale.com/tailcfg"
1818
"tailscale.com/types/netlogtype"
1919

20+
"cdr.dev/slog"
21+
"cdr.dev/slog/sloggers/sloghuman"
22+
2023
"github.com/coder/coder/cli/clibase"
2124
"github.com/coder/coder/codersdk"
2225
)
@@ -126,7 +129,18 @@ func (r *RootCmd) vscodeSSH() *clibase.Cmd {
126129
}
127130
}
128131

129-
agentConn, err := client.DialWorkspaceAgent(ctx, agent.ID, &codersdk.DialWorkspaceAgentOptions{})
132+
var logger slog.Logger
133+
if r.verbose {
134+
logger = slog.Make(sloghuman.Sink(inv.Stdout)).Leveled(slog.LevelDebug)
135+
}
136+
137+
if r.disableDirect {
138+
_, _ = fmt.Fprintln(inv.Stderr, "Direct connections disabled.")
139+
}
140+
agentConn, err := client.DialWorkspaceAgent(ctx, agent.ID, &codersdk.DialWorkspaceAgentOptions{
141+
Logger: logger,
142+
BlockEndpoints: r.disableDirect,
143+
})
130144
if err != nil {
131145
return xerrors.Errorf("dial workspace agent: %w", err)
132146
}

codersdk/client.go

+5
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,11 @@ type Client struct {
117117
// Trace can be enabled to propagate tracing spans to the Coder API.
118118
// This is useful for tracking a request end-to-end.
119119
Trace bool
120+
121+
// DisableDirectConnections forces any connections to workspaces to go
122+
// through DERP, regardless of the BlockEndpoints setting on each
123+
// connection.
124+
DisableDirectConnections bool
120125
}
121126

122127
// SessionToken returns the currently set token for the client.

codersdk/workspaceagents.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,8 @@ func (c *Client) WorkspaceAgentConnectionInfo(ctx context.Context) (*WorkspaceAg
193193
// @typescript-ignore DialWorkspaceAgentOptions
194194
type DialWorkspaceAgentOptions struct {
195195
Logger slog.Logger
196-
// BlockEndpoints forced a direct connection through DERP.
196+
// BlockEndpoints forced a direct connection through DERP. The Client may
197+
// have DisableDirect set which will override this value.
197198
BlockEndpoints bool
198199
}
199200

@@ -228,7 +229,7 @@ func (c *Client) DialWorkspaceAgent(ctx context.Context, agentID uuid.UUID, opti
228229
DERPMap: connInfo.DERPMap,
229230
DERPHeader: &header,
230231
Logger: options.Logger,
231-
BlockEndpoints: options.BlockEndpoints,
232+
BlockEndpoints: c.DisableDirectConnections || options.BlockEndpoints,
232233
})
233234
if err != nil {
234235
return nil, xerrors.Errorf("create tailnet: %w", err)

docs/cli.md

+9
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,15 @@ Coder — A tool for provisioning self-hosted development environments with Terr
6868

6969
Print all options, how they're set, then exit.
7070

71+
### --disable-direct-connections
72+
73+
| | |
74+
| ----------- | ---------------------------------------------- |
75+
| Type | <code>bool</code> |
76+
| Environment | <code>$CODER_DISABLE_DIRECT_CONNECTIONS</code> |
77+
78+
Disable direct (P2P) connections to workspaces.
79+
7180
### --global-config
7281

7382
| | |

enterprise/cli/testdata/coder_--help.golden

+3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ variables or flags.
2323
--debug-options bool
2424
Print all options, how they're set, then exit.
2525

26+
--disable-direct-connections bool, $CODER_DISABLE_DIRECT_CONNECTIONS
27+
Disable direct (P2P) connections to workspaces.
28+
2629
--global-config string, $CODER_CONFIG_DIR (default: ~/.config/coderv2)
2730
Path to the global `coder` config directory.
2831

0 commit comments

Comments
 (0)