Skip to content

Commit bddea7b

Browse files
authored
feat(cli/vscodessh): add support for --wait and scripts that block login (#10473)
1 parent c6c71de commit bddea7b

File tree

1 file changed

+41
-23
lines changed

1 file changed

+41
-23
lines changed

cli/vscodessh.go

+41-23
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"cdr.dev/slog/sloggers/sloghuman"
2222

2323
"github.com/coder/coder/v2/cli/clibase"
24+
"github.com/coder/coder/v2/cli/cliui"
2425
"github.com/coder/coder/v2/cli/cliutil"
2526
"github.com/coder/coder/v2/codersdk"
2627
)
@@ -38,6 +39,7 @@ func (r *RootCmd) vscodeSSH() *clibase.Cmd {
3839
logDir string
3940
networkInfoDir string
4041
networkInfoInterval time.Duration
42+
waitEnum string
4143
)
4244
cmd := &clibase.Cmd{
4345
// A SSH config entry is added by the VS Code extension that
@@ -99,35 +101,45 @@ func (r *RootCmd) vscodeSSH() *clibase.Cmd {
99101
}
100102
owner := parts[1]
101103
name := parts[2]
104+
if len(parts) > 3 {
105+
name += "." + parts[3]
106+
}
107+
108+
// Set autostart to false because it's assumed the VS Code extension
109+
// will call this command after the workspace is started.
110+
autostart := false
102111

103-
workspace, err := client.WorkspaceByOwnerAndName(ctx, owner, name, codersdk.WorkspaceOptions{})
112+
_, workspaceAgent, err := getWorkspaceAndAgent(ctx, inv, client, autostart, owner, name)
104113
if err != nil {
105-
return xerrors.Errorf("find workspace: %w", err)
114+
return xerrors.Errorf("find workspace and agent: %w", err)
106115
}
107116

108-
var agent codersdk.WorkspaceAgent
109-
var found bool
110-
for _, resource := range workspace.LatestBuild.Resources {
111-
if len(resource.Agents) == 0 {
112-
continue
113-
}
114-
for _, resourceAgent := range resource.Agents {
115-
// If an agent name isn't included we default to
116-
// the first agent!
117-
if len(parts) != 4 {
118-
agent = resourceAgent
119-
found = true
117+
// Select the startup script behavior based on template configuration or flags.
118+
var wait bool
119+
switch waitEnum {
120+
case "yes":
121+
wait = true
122+
case "no":
123+
wait = false
124+
case "auto":
125+
for _, script := range workspaceAgent.Scripts {
126+
if script.StartBlocksLogin {
127+
wait = true
120128
break
121129
}
122-
if resourceAgent.Name != parts[3] {
123-
continue
124-
}
125-
agent = resourceAgent
126-
found = true
127-
break
128130
}
129-
if found {
130-
break
131+
default:
132+
return xerrors.Errorf("unknown wait value %q", waitEnum)
133+
}
134+
135+
err = cliui.Agent(ctx, inv.Stderr, workspaceAgent.ID, cliui.AgentOptions{
136+
Fetch: client.WorkspaceAgent,
137+
FetchLogs: client.WorkspaceAgentLogsAfter,
138+
Wait: wait,
139+
})
140+
if err != nil {
141+
if xerrors.Is(err, context.Canceled) {
142+
return cliui.Canceled
131143
}
132144
}
133145

@@ -152,7 +164,7 @@ func (r *RootCmd) vscodeSSH() *clibase.Cmd {
152164
if r.disableDirect {
153165
logger.Info(ctx, "direct connections disabled")
154166
}
155-
agentConn, err := client.DialWorkspaceAgent(ctx, agent.ID, &codersdk.DialWorkspaceAgentOptions{
167+
agentConn, err := client.DialWorkspaceAgent(ctx, workspaceAgent.ID, &codersdk.DialWorkspaceAgentOptions{
156168
Logger: logger,
157169
BlockEndpoints: r.disableDirect,
158170
})
@@ -249,6 +261,12 @@ func (r *RootCmd) vscodeSSH() *clibase.Cmd {
249261
Default: "5s",
250262
Value: clibase.DurationOf(&networkInfoInterval),
251263
},
264+
{
265+
Flag: "wait",
266+
Description: "Specifies whether or not to wait for the startup script to finish executing. Auto means that the agent startup script behavior configured in the workspace template is used.",
267+
Default: "auto",
268+
Value: clibase.EnumOf(&waitEnum, "yes", "no", "auto"),
269+
},
252270
}
253271
return cmd
254272
}

0 commit comments

Comments
 (0)