diff --git a/cli/configssh.go b/cli/configssh.go
index f40fe484536b3..162c3c2a95855 100644
--- a/cli/configssh.go
+++ b/cli/configssh.go
@@ -198,6 +198,7 @@ func (r *RootCmd) configSSH() *clibase.Cmd {
dryRun bool
skipProxyCommand bool
forceUnixSeparators bool
+ coderCliPath string
)
client := new(codersdk.Client)
cmd := &clibase.Cmd{
@@ -233,10 +234,16 @@ func (r *RootCmd) configSSH() *clibase.Cmd {
// that it's possible to capture the diff.
out = inv.Stderr
}
- coderBinary, err := currentBinPath(out)
- if err != nil {
- return err
+
+ var err error
+ coderBinary := coderCliPath
+ if coderBinary == "" {
+ coderBinary, err = currentBinPath(out)
+ if err != nil {
+ return err
+ }
}
+
escapedCoderBinary, err := sshConfigExecEscape(coderBinary, forceUnixSeparators)
if err != nil {
return xerrors.Errorf("escape coder binary for ssh failed: %w", err)
@@ -501,6 +508,24 @@ func (r *RootCmd) configSSH() *clibase.Cmd {
Description: "Specifies the path to an SSH config.",
Value: clibase.StringOf(&sshConfigFile),
},
+ {
+ Flag: "coder-binary-path",
+ Env: "CODER_SSH_CONFIG_BINARY_PATH",
+ Default: "",
+ Description: "Optionally specify the absolute path to the coder binary used in ProxyCommand. " +
+ "By default, the binary invoking this command ('config ssh') is used.",
+ Value: clibase.Validate(clibase.StringOf(&coderCliPath), func(value *clibase.String) error {
+ if runtime.GOOS == goosWindows {
+ // For some reason filepath.IsAbs() does not work on windows.
+ return nil
+ }
+ absolute := filepath.IsAbs(value.String())
+ if !absolute {
+ return xerrors.Errorf("coder cli path must be an absolute path")
+ }
+ return nil
+ }),
+ },
{
Flag: "ssh-option",
FlagShorthand: "o",
diff --git a/cli/configssh_test.go b/cli/configssh_test.go
index f502304373f80..34da7dd03fcc0 100644
--- a/cli/configssh_test.go
+++ b/cli/configssh_test.go
@@ -216,18 +216,20 @@ func TestConfigSSH_FileWriteAndOptionsFlow(t *testing.T) {
ssh string
}
type wantConfig struct {
- ssh string
+ ssh string
+ regexMatch string
}
type match struct {
match, write string
}
tests := []struct {
- name string
- args []string
- matches []match
- writeConfig writeConfig
- wantConfig wantConfig
- wantErr bool
+ name string
+ args []string
+ matches []match
+ writeConfig writeConfig
+ wantConfig wantConfig
+ wantErr bool
+ echoResponse *echo.Responses
}{
{
name: "Config file is created",
@@ -579,6 +581,20 @@ func TestConfigSSH_FileWriteAndOptionsFlow(t *testing.T) {
},
wantErr: true,
},
+ {
+ name: "Custom CLI Path",
+ args: []string{
+ "-y", "--coder-binary-path", "/foo/bar/coder",
+ },
+ wantErr: false,
+ echoResponse: &echo.Responses{
+ Parse: echo.ParseComplete,
+ ProvisionApply: echo.ProvisionApplyWithAgent(""),
+ },
+ wantConfig: wantConfig{
+ regexMatch: "ProxyCommand /foo/bar/coder",
+ },
+ },
}
for _, tt := range tests {
tt := tt
@@ -588,7 +604,7 @@ func TestConfigSSH_FileWriteAndOptionsFlow(t *testing.T) {
var (
client = coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
user = coderdtest.CreateFirstUser(t, client)
- version = coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
+ version = coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, tt.echoResponse)
_ = coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
project = coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
workspace = coderdtest.CreateWorkspace(t, client, user.OrganizationID, project.ID)
@@ -627,9 +643,14 @@ func TestConfigSSH_FileWriteAndOptionsFlow(t *testing.T) {
<-done
- if tt.wantConfig.ssh != "" {
+ if tt.wantConfig.ssh != "" || tt.wantConfig.regexMatch != "" {
got := sshConfigFileRead(t, sshConfigName)
- assert.Equal(t, tt.wantConfig.ssh, got)
+ if tt.wantConfig.ssh != "" {
+ assert.Equal(t, tt.wantConfig.ssh, got)
+ }
+ if tt.wantConfig.regexMatch != "" {
+ assert.Regexp(t, tt.wantConfig.regexMatch, got, "regex match")
+ }
}
})
}
diff --git a/cli/testdata/coder_config-ssh_--help.golden b/cli/testdata/coder_config-ssh_--help.golden
index 857962b27141b..8aa547ccb467f 100644
--- a/cli/testdata/coder_config-ssh_--help.golden
+++ b/cli/testdata/coder_config-ssh_--help.golden
@@ -12,6 +12,11 @@ Add an SSH Host entry for your workspaces "ssh coder.workspace"
[40m [0m[91;40m$ coder config-ssh --dry-run[0m[40m [0m
[1mOptions[0m
+ --coder-binary-path string, $CODER_SSH_CONFIG_BINARY_PATH
+ Optionally specify the absolute path to the coder binary used in
+ ProxyCommand. By default, the binary invoking this command ('config
+ ssh') is used.
+
-n, --dry-run bool, $CODER_SSH_DRY_RUN
Perform a trial run with no changes made, showing a diff at the end.
diff --git a/docs/cli/config-ssh.md b/docs/cli/config-ssh.md
index 6178e207e1d30..9d5196c824827 100644
--- a/docs/cli/config-ssh.md
+++ b/docs/cli/config-ssh.md
@@ -25,6 +25,15 @@ coder config-ssh [flags]
## Options
+### --coder-binary-path
+
+| | |
+| ----------- | ------------------------------------------ |
+| Type | string
|
+| Environment | $CODER_SSH_CONFIG_BINARY_PATH
|
+
+Optionally specify the absolute path to the coder binary used in ProxyCommand. By default, the binary invoking this command ('config ssh') is used.
+
### -n, --dry-run
| | |