Skip to content

Commit c2acc35

Browse files
authored
feat: add custom coder bin path for ProxyCommand (coder#8425)
* feat: add custom coder bin path for ProxyCommand * force cli path to be absolute (on non-windows)
1 parent 47d5806 commit c2acc35

File tree

4 files changed

+73
-13
lines changed

4 files changed

+73
-13
lines changed

cli/configssh.go

+28-3
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ func (r *RootCmd) configSSH() *clibase.Cmd {
198198
dryRun bool
199199
skipProxyCommand bool
200200
forceUnixSeparators bool
201+
coderCliPath string
201202
)
202203
client := new(codersdk.Client)
203204
cmd := &clibase.Cmd{
@@ -233,10 +234,16 @@ func (r *RootCmd) configSSH() *clibase.Cmd {
233234
// that it's possible to capture the diff.
234235
out = inv.Stderr
235236
}
236-
coderBinary, err := currentBinPath(out)
237-
if err != nil {
238-
return err
237+
238+
var err error
239+
coderBinary := coderCliPath
240+
if coderBinary == "" {
241+
coderBinary, err = currentBinPath(out)
242+
if err != nil {
243+
return err
244+
}
239245
}
246+
240247
escapedCoderBinary, err := sshConfigExecEscape(coderBinary, forceUnixSeparators)
241248
if err != nil {
242249
return xerrors.Errorf("escape coder binary for ssh failed: %w", err)
@@ -501,6 +508,24 @@ func (r *RootCmd) configSSH() *clibase.Cmd {
501508
Description: "Specifies the path to an SSH config.",
502509
Value: clibase.StringOf(&sshConfigFile),
503510
},
511+
{
512+
Flag: "coder-binary-path",
513+
Env: "CODER_SSH_CONFIG_BINARY_PATH",
514+
Default: "",
515+
Description: "Optionally specify the absolute path to the coder binary used in ProxyCommand. " +
516+
"By default, the binary invoking this command ('config ssh') is used.",
517+
Value: clibase.Validate(clibase.StringOf(&coderCliPath), func(value *clibase.String) error {
518+
if runtime.GOOS == goosWindows {
519+
// For some reason filepath.IsAbs() does not work on windows.
520+
return nil
521+
}
522+
absolute := filepath.IsAbs(value.String())
523+
if !absolute {
524+
return xerrors.Errorf("coder cli path must be an absolute path")
525+
}
526+
return nil
527+
}),
528+
},
504529
{
505530
Flag: "ssh-option",
506531
FlagShorthand: "o",

cli/configssh_test.go

+31-10
Original file line numberDiff line numberDiff line change
@@ -216,18 +216,20 @@ func TestConfigSSH_FileWriteAndOptionsFlow(t *testing.T) {
216216
ssh string
217217
}
218218
type wantConfig struct {
219-
ssh string
219+
ssh string
220+
regexMatch string
220221
}
221222
type match struct {
222223
match, write string
223224
}
224225
tests := []struct {
225-
name string
226-
args []string
227-
matches []match
228-
writeConfig writeConfig
229-
wantConfig wantConfig
230-
wantErr bool
226+
name string
227+
args []string
228+
matches []match
229+
writeConfig writeConfig
230+
wantConfig wantConfig
231+
wantErr bool
232+
echoResponse *echo.Responses
231233
}{
232234
{
233235
name: "Config file is created",
@@ -579,6 +581,20 @@ func TestConfigSSH_FileWriteAndOptionsFlow(t *testing.T) {
579581
},
580582
wantErr: true,
581583
},
584+
{
585+
name: "Custom CLI Path",
586+
args: []string{
587+
"-y", "--coder-binary-path", "/foo/bar/coder",
588+
},
589+
wantErr: false,
590+
echoResponse: &echo.Responses{
591+
Parse: echo.ParseComplete,
592+
ProvisionApply: echo.ProvisionApplyWithAgent(""),
593+
},
594+
wantConfig: wantConfig{
595+
regexMatch: "ProxyCommand /foo/bar/coder",
596+
},
597+
},
582598
}
583599
for _, tt := range tests {
584600
tt := tt
@@ -588,7 +604,7 @@ func TestConfigSSH_FileWriteAndOptionsFlow(t *testing.T) {
588604
var (
589605
client = coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
590606
user = coderdtest.CreateFirstUser(t, client)
591-
version = coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
607+
version = coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, tt.echoResponse)
592608
_ = coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
593609
project = coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
594610
workspace = coderdtest.CreateWorkspace(t, client, user.OrganizationID, project.ID)
@@ -627,9 +643,14 @@ func TestConfigSSH_FileWriteAndOptionsFlow(t *testing.T) {
627643

628644
<-done
629645

630-
if tt.wantConfig.ssh != "" {
646+
if tt.wantConfig.ssh != "" || tt.wantConfig.regexMatch != "" {
631647
got := sshConfigFileRead(t, sshConfigName)
632-
assert.Equal(t, tt.wantConfig.ssh, got)
648+
if tt.wantConfig.ssh != "" {
649+
assert.Equal(t, tt.wantConfig.ssh, got)
650+
}
651+
if tt.wantConfig.regexMatch != "" {
652+
assert.Regexp(t, tt.wantConfig.regexMatch, got, "regex match")
653+
}
633654
}
634655
})
635656
}

cli/testdata/coder_config-ssh_--help.golden

+5
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ Add an SSH Host entry for your workspaces "ssh coder.workspace"
1212
 $ coder config-ssh --dry-run 
1313

1414
Options
15+
--coder-binary-path string, $CODER_SSH_CONFIG_BINARY_PATH
16+
Optionally specify the absolute path to the coder binary used in
17+
ProxyCommand. By default, the binary invoking this command ('config
18+
ssh') is used.
19+
1520
-n, --dry-run bool, $CODER_SSH_DRY_RUN
1621
Perform a trial run with no changes made, showing a diff at the end.
1722

docs/cli/config-ssh.md

+9
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,15 @@ coder config-ssh [flags]
2525

2626
## Options
2727

28+
### --coder-binary-path
29+
30+
| | |
31+
| ----------- | ------------------------------------------ |
32+
| Type | <code>string</code> |
33+
| Environment | <code>$CODER_SSH_CONFIG_BINARY_PATH</code> |
34+
35+
Optionally specify the absolute path to the coder binary used in ProxyCommand. By default, the binary invoking this command ('config ssh') is used.
36+
2837
### -n, --dry-run
2938

3039
| | |

0 commit comments

Comments
 (0)