func makeSSHTunnel(user string, signer ssh.Signer, host string) (*SSHTunnel, error) { config := ssh.ClientConfig{ User: user, Auth: []ssh.AuthMethod{ssh.PublicKeys(signer)}, } return &SSHTunnel{ Config: &config, Host: host, SSHPort: "22", }, nil }
// Internal implementation of runSSHCommand, for testing func runSSHCommand(dialer sshDialer, cmd, user, host string, signer ssh.Signer) (string, string, int, error) { if user == "" { user = os.Getenv("USER") } // Setup the config, dial the server, and open a session. config := &ssh.ClientConfig{ User: user, Auth: []ssh.AuthMethod{ssh.PublicKeys(signer)}, } client, err := dialer.Dial("tcp", host, config) if err != nil { return "", "", 0, fmt.Errorf("error getting SSH client to %s@%s: '%v'", user, host, err) } session, err := client.NewSession() if err != nil { return "", "", 0, fmt.Errorf("error creating session to %s@%s: '%v'", user, host, err) } defer session.Close() // Run the command. code := 0 var bout, berr bytes.Buffer session.Stdout, session.Stderr = &bout, &berr if err = session.Run(cmd); err != nil { // Check whether the command failed to run or didn't complete. if exiterr, ok := err.(*ssh.ExitError); ok { // If we got an ExitError and the exit code is nonzero, we'll // consider the SSH itself successful (just that the command run // errored on the host). if code = exiterr.ExitStatus(); code != 0 { err = nil } } else { // Some other kind of error happened (e.g. an IOError); consider the // SSH unsuccessful. err = fmt.Errorf("failed running `%s` on %s@%s: '%v'", cmd, user, host, err) } } return bout.String(), berr.String(), code, err }