Skip to content

Commit c88e4df

Browse files
gcurtismikeland73
authored andcommitted
cloud: clean up mutagen sync ssh commands (#555)
Use the `openssh` package where possible when executing the SSH commands for setting the mutagen sync status. This provides better logging when commands fail. Also rename `openssh.Client` to `Cmd` to better reflect that we're calling an external process.
1 parent ad211d6 commit c88e4df

File tree

2 files changed

+53
-54
lines changed

2 files changed

+53
-54
lines changed

internal/cloud/cloud.go

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,15 @@ func Shell(w io.Writer, projectDir string, githubUsername string) error {
5555
// for github username.
5656
telemetryShellStartTime := time.Now()
5757

58-
sshClient := openssh.Client{
59-
Username: username,
60-
Addr: "gateway.devbox.sh",
58+
sshCmd := &openssh.Cmd{
59+
Username: username,
60+
DestinationAddr: "gateway.devbox.sh",
6161
}
6262
// When developing we can use this env variable to point
6363
// to a different gateway
6464
var err error
6565
if envGateway := os.Getenv("DEVBOX_GATEWAY"); envGateway != "" {
66-
sshClient.Addr = envGateway
66+
sshCmd.DestinationAddr = envGateway
6767
err = openssh.SetupInsecureDebug(envGateway)
6868
} else {
6969
err = openssh.SetupDevbox()
@@ -84,7 +84,7 @@ func Shell(w io.Writer, projectDir string, githubUsername string) error {
8484
color.New(color.FgGreen).Fprintln(w, "Detected existing virtual machine")
8585
} else {
8686
var region, vmUser string
87-
vmUser, vmHostname, region, err = getVirtualMachine(sshClient)
87+
vmUser, vmHostname, region, err = getVirtualMachine(sshCmd)
8888
if err != nil {
8989
return err
9090
}
@@ -191,8 +191,8 @@ func (vm vm) redact() *vm {
191191
return &vm
192192
}
193193

194-
func getVirtualMachine(client openssh.Client) (vmUser, vmHost, region string, err error) {
195-
sshOut, err := client.Exec("auth")
194+
func getVirtualMachine(sshCmd *openssh.Cmd) (vmUser, vmHost, region string, err error) {
195+
sshOut, err := sshCmd.ExecRemote("auth")
196196
if err != nil {
197197
return "", "", "", errors.Wrapf(err, "error requesting VM")
198198
}
@@ -280,19 +280,20 @@ func updateSyncStatus(mutagenSessionName, username, hostname, relProjectPathInVM
280280
status := "disconnected"
281281

282282
// Ensure the destination directory exists
283-
destServer := fmt.Sprintf("%s@%s", username, hostname)
284283
destDir := fmt.Sprintf("/home/%s/.config/devbox/starship/%s", username, hyphenatePath(filepath.Base(relProjectPathInVM)))
285-
remoteCmd := fmt.Sprintf("mkdir -p %s", destDir)
286-
cmd := exec.Command("ssh", destServer, remoteCmd)
287-
err := cmd.Run()
288-
debug.Log("mkdir starship mutagen_status command: %s with error: %s", cmd, err)
284+
mkdirCmd := openssh.Command(username, hostname)
285+
_, err := mkdirCmd.ExecRemote(fmt.Sprintf(`mkdir -p "%s"`, destDir))
286+
if err != nil {
287+
debug.Log("error setting initial starship mutagen status: %v", err)
288+
}
289289

290290
// Set an initial status
291291
displayableStatus := "initial sync"
292-
remoteCmd = fmt.Sprintf("echo %s > %s/mutagen_status.txt", displayableStatus, destDir)
293-
cmd = exec.Command("ssh", destServer, remoteCmd)
294-
err = cmd.Run()
295-
debug.Log("scp starship.toml with command: %s and error: %s", cmd, err)
292+
statusCmd := openssh.Command(username, hostname)
293+
_, err = statusCmd.ExecRemote(fmt.Sprintf(`echo "%s" > "%s/mutagen_status.txt"`, displayableStatus, destDir))
294+
if err != nil {
295+
debug.Log("error setting initial starship mutagen status: %v", err)
296+
}
296297
time.Sleep(5 * time.Second)
297298

298299
debug.Log("Starting check for file sync status")
@@ -309,10 +310,11 @@ func updateSyncStatus(mutagenSessionName, username, hostname, relProjectPathInVM
309310
displayableStatus = "\"watching for changes\""
310311
}
311312

312-
remoteCmd = fmt.Sprintf("echo %s > %s/mutagen_status.txt", displayableStatus, destDir)
313-
cmd = exec.Command("ssh", destServer, remoteCmd)
314-
err = cmd.Run()
315-
debug.Log("scp starship.toml with command: %s and error: %s", cmd, err)
313+
statusCmd := openssh.Command(username, hostname)
314+
_, err = statusCmd.ExecRemote(fmt.Sprintf(`echo "%s" > "%s/mutagen_status.txt"`, displayableStatus, destDir))
315+
if err != nil {
316+
debug.Log("error setting initial starship mutagen status: %v", err)
317+
}
316318
time.Sleep(5 * time.Second)
317319
}
318320
}
@@ -335,18 +337,18 @@ func getSyncStatus(mutagenSessionName string) (string, error) {
335337
func copyConfigFileToVM(hostname, username, projectDir, pathInVM string) error {
336338

337339
// Ensure the devbox-project's directory exists in the VM
338-
destServer := fmt.Sprintf("%s@%s", username, hostname)
339-
cmd := exec.Command("ssh", destServer, "--", "mkdir", "-p", pathInVM)
340-
err := cmd.Run()
341-
debug.Log("ssh mkdir command: %s with error: %s", cmd, err)
340+
mkdirCmd := openssh.Command(username, hostname)
341+
_, err := mkdirCmd.ExecRemote(fmt.Sprintf(`mkdir -p "%s"`, pathInVM))
342342
if err != nil {
343+
debug.Log("error copying config file to VM: %v", err)
343344
return errors.WithStack(err)
344345
}
345346

346347
// Copy the config file to the devbox-project directory in the VM
348+
destServer := fmt.Sprintf("%s@%s", username, hostname)
347349
configFilePath := filepath.Join(projectDir, "devbox.json")
348350
destPath := fmt.Sprintf("%s:%s", destServer, pathInVM)
349-
cmd = exec.Command("scp", configFilePath, destPath)
351+
cmd := exec.Command("scp", configFilePath, destPath)
350352
err = cmd.Run()
351353
debug.Log("scp devbox.json command: %s with error: %s", cmd, err)
352354
return errors.WithStack(err)
@@ -358,14 +360,14 @@ func shell(username, hostname, projectDir string, shellStartTime time.Time) erro
358360
return err
359361
}
360362

361-
client := &openssh.Client{
362-
Addr: hostname,
363-
PathInVM: absoluteProjectPathInVM(username, projectPath),
364-
ShellStartTime: telemetry.UnixTimestampFromTime(shellStartTime),
365-
Username: username,
363+
cmd := &openssh.Cmd{
364+
DestinationAddr: hostname,
365+
PathInVM: absoluteProjectPathInVM(username, projectPath),
366+
ShellStartTime: telemetry.UnixTimestampFromTime(shellStartTime),
367+
Username: username,
366368
}
367369
sessionErrors := newSSHSessionErrors()
368-
return cloudShellErrorHandler(client.Shell(sessionErrors), sessionErrors)
370+
return cloudShellErrorHandler(cmd.Shell(sessionErrors), sessionErrors)
369371
}
370372

371373
// relativeProjectPathInVM refers to the project path relative to the user's

internal/cloud/openssh/client.go renamed to internal/cloud/openssh/cmd.go

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,23 @@ import (
1717
"go.jetpack.io/devbox/internal/debug"
1818
)
1919

20-
type Client struct {
21-
Addr string
20+
type Cmd struct {
21+
// DestinationAddr is a "hostname[:port]" that specifies the remote host
22+
// and port to connect to.
23+
DestinationAddr string
24+
25+
// Username is the remote login name.
26+
Username string
27+
2228
PathInVM string
2329
ShellStartTime string // unix timestamp
24-
Username string
2530
}
2631

27-
func (c *Client) Shell(w io.Writer) error {
32+
func Command(user, dest string) *Cmd {
33+
return &Cmd{DestinationAddr: dest, Username: user}
34+
}
2835

36+
func (c *Cmd) Shell(w io.Writer) error {
2937
cmd := c.cmd("-t")
3038
remoteCmd := fmt.Sprintf(
3139
`bash -l -c "start_devbox_shell.sh \"%s\" %s"`,
@@ -39,9 +47,9 @@ func (c *Client) Shell(w io.Writer) error {
3947
return logCmdRun(cmd)
4048
}
4149

42-
func (c *Client) Exec(remoteCmd string) ([]byte, error) {
43-
sshCmd := c.cmd()
44-
sshCmd.Args = append(sshCmd.Args, remoteCmd)
50+
func (c *Cmd) ExecRemote(cmd string) ([]byte, error) {
51+
sshCmd := c.cmd("-T")
52+
sshCmd.Args = append(sshCmd.Args, cmd)
4553

4654
var stdout, stderr bytes.Buffer
4755
sshCmd.Stdout = &stdout
@@ -58,16 +66,14 @@ func (c *Client) Exec(remoteCmd string) ([]byte, error) {
5866
return stdout.Bytes(), nil
5967
}
6068

61-
func (c *Client) cmd(sshArgs ...string) *exec.Cmd {
62-
host, port := splitHostPort(c.Addr)
63-
cmd := exec.Command("ssh", sshArgs...)
64-
cmd.Args = append(cmd.Args, destination(c.Username, host))
65-
66-
// Add any necessary flags:
69+
func (c *Cmd) cmd(sshArgs ...string) *exec.Cmd {
70+
host, port := splitHostPort(c.DestinationAddr)
71+
cmd := exec.Command("ssh", "-l", c.Username)
6772
if port != 0 && port != 22 {
6873
cmd.Args = append(cmd.Args, "-p", strconv.Itoa(port))
6974
}
70-
75+
cmd.Args = append(cmd.Args, sshArgs...)
76+
cmd.Args = append(cmd.Args, host)
7177
return cmd
7278
}
7379

@@ -85,15 +91,6 @@ func splitHostPort(addr string) (host string, port int) {
8591
return host, port
8692
}
8793

88-
func destination(username, hostname string) string {
89-
result := hostname
90-
if username != "" {
91-
result = username + "@" + result
92-
}
93-
94-
return result
95-
}
96-
9794
func logCmdRun(cmd *exec.Cmd) error {
9895
// Use cmd.Start so we can log the pid. Don't bother writing errors to
9996
// the debug log since those will be printed anyway.

0 commit comments

Comments
 (0)