|
6 | 6 | "io/ioutil"
|
7 | 7 | "net/url"
|
8 | 8 | "os"
|
| 9 | + "os/exec" |
9 | 10 | "os/user"
|
10 | 11 | "path/filepath"
|
11 | 12 | "runtime"
|
@@ -114,8 +115,11 @@ func configSSH(configpath *string, remove *bool) func(cmd *cobra.Command, _ []st
|
114 | 115 | return xerrors.New("SSH is disabled or not available for any workspaces in your Coder deployment.")
|
115 | 116 | }
|
116 | 117 |
|
117 |
| - binPath, err := os.Executable() |
| 118 | + binPath, err := binPath() |
118 | 119 | if err != nil {
|
| 120 | + if runtime.GOOS == "windows" { |
| 121 | + return xerrors.Errorf("Failed to ensure `coder` is in $PATH, please move the `coder` binary to a location in $PATH (such as System32): %w", err) |
| 122 | + } |
119 | 123 | return xerrors.Errorf("Failed to get executable path: %w", err)
|
120 | 124 | }
|
121 | 125 |
|
@@ -147,6 +151,42 @@ func configSSH(configpath *string, remove *bool) func(cmd *cobra.Command, _ []st
|
147 | 151 | }
|
148 | 152 | }
|
149 | 153 |
|
| 154 | +// binPath returns the path to the coder binary suitable for use in ssh |
| 155 | +// ProxyCommand. |
| 156 | +func binPath() (string, error) { |
| 157 | + exePath, err := os.Executable() |
| 158 | + if err != nil { |
| 159 | + return "", xerrors.Errorf("get executable path: %w", err) |
| 160 | + } |
| 161 | + |
| 162 | + // On Windows, the coder-cli executable must be in $PATH for Msys2 and Git |
| 163 | + // Bash to function correctly. To prevent weird behavior when people switch |
| 164 | + // between the two, we require this for all users. |
| 165 | + if runtime.GOOS == "windows" { |
| 166 | + binName := filepath.Base(exePath) |
| 167 | + pathPath, err := exec.LookPath(exePath) |
| 168 | + if err != nil { |
| 169 | + return "", xerrors.Errorf("locate %q in $PATH: %w", binName, err) |
| 170 | + } |
| 171 | + |
| 172 | + // Warn the user if the current executable is not the same as the one in |
| 173 | + // $PATH. |
| 174 | + if filepath.Clean(pathPath) != filepath.Clean(exePath) { |
| 175 | + clog.LogWarn( |
| 176 | + "The current executable path does not match the executable path found in $PATH.", |
| 177 | + "This may lead to problems connecting to your workspace via SSH.", |
| 178 | + fmt.Sprintf("\t Current executable path: %q", exePath), |
| 179 | + fmt.Sprintf("\tExecutable path in $PATH: %q", pathPath), |
| 180 | + ) |
| 181 | + } |
| 182 | + |
| 183 | + return binName, nil |
| 184 | + } |
| 185 | + |
| 186 | + // On platforms other than Windows we can use the full path to the binary. |
| 187 | + return exePath, nil |
| 188 | +} |
| 189 | + |
150 | 190 | // removeOldConfig removes the old ssh configuration from the user's sshconfig.
|
151 | 191 | // Returns true if the config was modified.
|
152 | 192 | func removeOldConfig(config string) (string, bool) {
|
@@ -212,7 +252,7 @@ func makeSSHConfig(binPath, host, userName, workspaceName, privateKeyFilepath st
|
212 | 252 | host := fmt.Sprintf(
|
213 | 253 | `Host coder.%s
|
214 | 254 | HostName coder.%s
|
215 |
| - ProxyCommand %s tunnel %s 12213 stdio |
| 255 | + ProxyCommand "%s" tunnel %s 12213 stdio |
216 | 256 | StrictHostKeyChecking no
|
217 | 257 | ConnectTimeout=0
|
218 | 258 | IdentitiesOnly yes
|
|
0 commit comments