Skip to content

feat(cli/configssh): add support for wait yes/no/auto #7893

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 8, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
Prev Previous commit
Next Next commit
Replace --wait/--no-wait with --wait=yes|no|auto
  • Loading branch information
mafredri committed Jun 7, 2023
commit 38ea959bde6f5caf14740efec2dbd302340389c3
54 changes: 19 additions & 35 deletions cli/configssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,7 @@ const (
// sshConfigOptions represents options that can be stored and read
// from the coder config in ~/.ssh/coder.
type sshConfigOptions struct {
wait bool
noWait bool
waitEnum string
userHostPrefix string
sshOptions []string
}
Expand Down Expand Up @@ -106,15 +105,12 @@ func (o sshConfigOptions) equal(other sshConfigOptions) bool {
if !slices.Equal(opt1, opt2) {
return false
}
return o.wait == other.wait && o.noWait == other.noWait && o.userHostPrefix == other.userHostPrefix
return o.waitEnum == other.waitEnum && o.userHostPrefix == other.userHostPrefix
}

func (o sshConfigOptions) asList() (list []string) {
if o.wait {
list = append(list, "wait")
}
if o.noWait {
list = append(list, "no-wait")
if o.waitEnum != "auto" {
list = append(list, fmt.Sprintf("wait: %s", o.waitEnum))
}
if o.userHostPrefix != "" {
list = append(list, fmt.Sprintf("ssh-host-prefix: %s", o.userHostPrefix))
Expand Down Expand Up @@ -222,11 +218,8 @@ func (r *RootCmd) configSSH() *clibase.Cmd {
r.InitClient(client),
),
Handler: func(inv *clibase.Invocation) error {
if sshConfigOpts.wait && sshConfigOpts.noWait {
return xerrors.Errorf("cannot specify both --wait and --no-wait")
}
if skipProxyCommand && (sshConfigOpts.wait || sshConfigOpts.noWait) {
return xerrors.Errorf("cannot specify --skip-proxy-command with --wait or --no-wait")
if sshConfigOpts.waitEnum != "auto" && skipProxyCommand {
return xerrors.Errorf("cannot specify both --skip-proxy-command and --wait")
}

recvWorkspaceConfigs := sshPrepareWorkspaceConfigs(inv.Context(), client)
Expand Down Expand Up @@ -386,10 +379,8 @@ func (r *RootCmd) configSSH() *clibase.Cmd {

if !skipProxyCommand {
flags := ""
if sshConfigOpts.wait {
flags += " --wait"
} else if sshConfigOpts.noWait {
flags += " --no-wait"
if sshConfigOpts.waitEnum != "auto" {
flags += " --wait=" + sshConfigOpts.waitEnum
}
defaultOptions = append(defaultOptions, fmt.Sprintf(
"ProxyCommand %s --global-config %s ssh --stdio%s %s",
Expand Down Expand Up @@ -536,21 +527,16 @@ func (r *RootCmd) configSSH() *clibase.Cmd {
},
{
Flag: "ssh-host-prefix",
Env: "",
Env: "CODER_CONFIGSSH_SSH_HOST_PREFIX",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Description: "Override the default host prefix.",
Value: clibase.StringOf(&sshConfigOpts.userHostPrefix),
},
{
Flag: "wait",
Env: "CODER_CONFIGSSH_WAIT", // Not to be mixed with CODER_SSH_WAIT.
Description: "Set the option to wait for the the startup script to finish executing. This is the default if the template has configured the agent startup script behavior as blocking. Can not be used together with --no-wait.",
Value: clibase.BoolOf(&sshConfigOpts.wait),
},
{
Flag: "no-wait",
Env: "CODER_CONFIGSSH_NO_WAIT", // Not to be mixed with CODER_SSH_NO_WAIT.
Description: "Set the option to enter workspace immediately after the agent has connected. This is the default if the template has configured the agent startup script behavior as non-blocking. Can not be used together with --wait.",
Value: clibase.BoolOf(&sshConfigOpts.noWait),
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.",
Default: "auto",
Value: clibase.EnumOf(&sshConfigOpts.waitEnum, "yes", "no", "auto"),
},
cliui.SkipPromptOption(),
}
Expand All @@ -569,11 +555,8 @@ func sshConfigWriteSectionHeader(w io.Writer, addNewline bool, o sshConfigOption
_, _ = fmt.Fprint(w, sshConfigDocsHeader)

var ow strings.Builder
if o.wait {
_, _ = fmt.Fprintf(&ow, "# :%s\n", "wait")
}
if o.noWait {
_, _ = fmt.Fprintf(&ow, "# :%s\n", "no-wait")
if o.waitEnum != "auto" {
_, _ = fmt.Fprintf(&ow, "# :%s=%s\n", "wait", o.waitEnum)
}
if o.userHostPrefix != "" {
_, _ = fmt.Fprintf(&ow, "# :%s=%s\n", "ssh-host-prefix", o.userHostPrefix)
Expand All @@ -594,6 +577,9 @@ func sshConfigWriteSectionEnd(w io.Writer) {
}

func sshConfigParseLastOptions(r io.Reader) (o sshConfigOptions) {
// Default values.
o.waitEnum = "auto"

s := bufio.NewScanner(r)
for s.Scan() {
line := s.Text()
Expand All @@ -602,10 +588,8 @@ func sshConfigParseLastOptions(r io.Reader) (o sshConfigOptions) {
parts := strings.SplitN(line, "=", 2)
switch parts[0] {
case "wait":
o.wait = true
case "no-wait":
o.noWait = true
case "user-host-prefix":
o.waitEnum = parts[1]
case "ssh-host-prefix":
o.userHostPrefix = parts[1]
case "ssh-option":
o.sshOptions = append(o.sshOptions, parts[1])
Expand Down
8 changes: 4 additions & 4 deletions cli/configssh_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ func TestConfigSSH_FileWriteAndOptionsFlow(t *testing.T) {
ssh: strings.Join([]string{
headerStart,
"# Last config-ssh options:",
"# :wait",
"# :wait=yes",
"# :ssh-host-prefix=coder-test.",
"#",
headerEnd,
Expand All @@ -496,7 +496,7 @@ func TestConfigSSH_FileWriteAndOptionsFlow(t *testing.T) {
},
args: []string{
"--yes",
"--wait",
"--wait=yes",
"--ssh-host-prefix", "coder-test.",
},
},
Expand All @@ -506,7 +506,7 @@ func TestConfigSSH_FileWriteAndOptionsFlow(t *testing.T) {
ssh: strings.Join([]string{
headerStart,
"# Last config-ssh options:",
"# :no-wait",
"# :wait=no",
"# :ssh-option=ForwardAgent=yes",
"#",
headerEnd,
Expand All @@ -517,7 +517,7 @@ func TestConfigSSH_FileWriteAndOptionsFlow(t *testing.T) {
ssh: strings.Join([]string{
headerStart,
"# Last config-ssh options:",
"# :no-wait",
"# :wait=no",
"# :ssh-option=ForwardAgent=yes",
"#",
headerEnd,
Expand Down
16 changes: 5 additions & 11 deletions cli/testdata/coder_config-ssh_--help.golden
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,10 @@ Add an SSH Host entry for your workspaces "ssh coder.workspace"
-n, --dry-run bool, $CODER_SSH_DRY_RUN
Perform a trial run with no changes made, showing a diff at the end.

--no-wait bool, $CODER_CONFIGSSH_NO_WAIT
Set the option to enter workspace immediately after the agent has
connected. This is the default if the template has configured the
agent startup script behavior as non-blocking. Can not be used
together with --wait.

--ssh-config-file string, $CODER_SSH_CONFIG_FILE (default: ~/.ssh/config)
Specifies the path to an SSH config.

--ssh-host-prefix string
--ssh-host-prefix string, $CODER_CONFIGSSH_SSH_HOST_PREFIX
Override the default host prefix.

-o, --ssh-option string-array, $CODER_SSH_CONFIG_OPTS
Expand All @@ -34,10 +28,10 @@ Add an SSH Host entry for your workspaces "ssh coder.workspace"
Specifies whether or not to keep options from previous run of
config-ssh.

--wait bool, $CODER_CONFIGSSH_WAIT
Set the option to wait for the the startup script to finish executing.
This is the default if the template has configured the agent startup
script behavior as blocking. Can not be used together with --no-wait.
--wait yes|no|auto, $CODER_CONFIGSSH_WAIT (default: auto)
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.

-y, --yes bool
Bypass prompts.
Expand Down
23 changes: 8 additions & 15 deletions docs/cli/config-ssh.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,6 @@ coder config-ssh [flags]

Perform a trial run with no changes made, showing a diff at the end.

### --no-wait

| | |
| ----------- | ------------------------------------- |
| Type | <code>bool</code> |
| Environment | <code>$CODER_CONFIGSSH_NO_WAIT</code> |

Set the option to enter workspace immediately after the agent has connected. This is the default if the template has configured the agent startup script behavior as non-blocking. Can not be used together with --wait.

### --ssh-config-file

| | |
Expand All @@ -55,9 +46,10 @@ Specifies the path to an SSH config.

### --ssh-host-prefix

| | |
| ---- | ------------------- |
| Type | <code>string</code> |
| | |
| ----------- | --------------------------------------------- |
| Type | <code>string</code> |
| Environment | <code>$CODER_CONFIGSSH_SSH_HOST_PREFIX</code> |

Override the default host prefix.

Expand All @@ -82,11 +74,12 @@ Specifies whether or not to keep options from previous run of config-ssh.
### --wait

| | |
| ----------- | ---------------------------------- |
| Type | <code>bool</code> |
| ----------- | ---------------------------------- | --- | ------------ |
| Type | <code>enum[yes | no | auto]</code> |
| Environment | <code>$CODER_CONFIGSSH_WAIT</code> |
| Default | <code>auto</code> |

Set the option to wait for the the startup script to finish executing. This is the default if the template has configured the agent startup script behavior as blocking. Can not be used together with --no-wait.
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.

### -y, --yes

Expand Down