Merge pull request #1951 from nathanleclaire/windows_ssh

Fix Windows SSH issues
This commit is contained in:
Nathan LeClaire 2015-10-13 17:53:18 -07:00
commit 7f18deb79f
5 changed files with 71 additions and 43 deletions

View File

@ -1,9 +1,6 @@
package commands package commands
import ( import (
"fmt"
"strings"
"github.com/docker/machine/libmachine/log" "github.com/docker/machine/libmachine/log"
"github.com/docker/machine/libmachine/state" "github.com/docker/machine/libmachine/state"
@ -33,18 +30,12 @@ func cmdSsh(c *cli.Context) {
log.Fatalf("Error: Cannot run SSH command: Host %q is not running", host.Name) log.Fatalf("Error: Cannot run SSH command: Host %q is not running", host.Name)
} }
if len(c.Args()) == 1 { client, err := host.CreateSSHClient()
err := host.CreateSSHShell() if err != nil {
if err != nil { log.Fatal(err)
log.Fatal(err)
}
} else {
output, err := host.RunSSHCommand(strings.Join(c.Args().Tail(), " "))
if err != nil {
log.Fatal(err)
}
fmt.Print(output)
} }
if err := client.Shell(c.Args().Tail()...); err != nil {
log.Fatal(err)
}
} }

View File

@ -74,15 +74,6 @@ func (h *Host) CreateSSHClient() (ssh.Client, error) {
return ssh.NewClient(h.Driver.GetSSHUsername(), addr, port, auth) return ssh.NewClient(h.Driver.GetSSHUsername(), addr, port, auth)
} }
func (h *Host) CreateSSHShell() error {
client, err := h.CreateSSHClient()
if err != nil {
return err
}
return client.Shell()
}
func (h *Host) runActionForState(action func() error, desiredState state.State) error { func (h *Host) runActionForState(action func() error, desiredState state.State) error {
if drivers.MachineInState(h.Driver, desiredState)() { if drivers.MachineInState(h.Driver, desiredState)() {
return fmt.Errorf("Machine %q is already %s.", h.Name, strings.ToLower(desiredState.String())) return fmt.Errorf("Machine %q is already %s.", h.Name, strings.ToLower(desiredState.String()))

View File

@ -16,7 +16,7 @@ import (
type Client interface { type Client interface {
Output(command string) (string, error) Output(command string) (string, error)
Shell() error Shell(args ...string) error
} }
type ExternalClient struct { type ExternalClient struct {
@ -195,7 +195,7 @@ func (client NativeClient) OutputWithPty(command string) (string, error) {
return string(output), err return string(output), err
} }
func (client NativeClient) Shell() error { func (client NativeClient) Shell(args ...string) error {
var ( var (
termWidth, termHeight int termWidth, termHeight int
) )
@ -243,12 +243,15 @@ func (client NativeClient) Shell() error {
return err return err
} }
if err := session.Shell(); err != nil { if len(args) == 0 {
return err if err := session.Shell(); err != nil {
return err
}
session.Wait()
} else {
session.Run(strings.Join(args, " "))
} }
session.Wait()
return nil return nil
} }
@ -272,23 +275,21 @@ func NewExternalClient(sshBinaryPath, user, host string, port int, auth *Auth) (
return client, nil return client, nil
} }
func getSSHCmd(binaryPath string, args ...string) *exec.Cmd {
return exec.Command(binaryPath, args...)
}
func (client ExternalClient) Output(command string) (string, error) { func (client ExternalClient) Output(command string) (string, error) {
// TODO: Ugh, gross hack. Replace with all instances using variadic args := append(client.BaseArgs, command)
// syntax cmd := getSSHCmd(client.BinaryPath, args...)
args := append(client.BaseArgs, strings.Split(command, " ")...)
cmd := exec.Command(client.BinaryPath, args...)
log.Debug(cmd)
// Allow piping of local things to remote commands.
cmd.Stdin = os.Stdin
output, err := cmd.CombinedOutput() output, err := cmd.CombinedOutput()
return string(output), err return string(output), err
} }
func (client ExternalClient) Shell() error { func (client ExternalClient) Shell(args ...string) error {
cmd := exec.Command(client.BinaryPath, client.BaseArgs...) args = append(client.BaseArgs, args...)
cmd := getSSHCmd(client.BinaryPath, args...)
log.Debug(cmd) log.Debug(cmd)
cmd.Stdin = os.Stdin cmd.Stdin = os.Stdin

View File

@ -0,0 +1,45 @@
package ssh
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestGetSSHCmdArgs(t *testing.T) {
cases := []struct {
binaryPath string
args []string
expectedArgs []string
}{
{
binaryPath: "/usr/local/bin/ssh",
args: []string{
"docker@localhost",
"apt-get install -y htop",
},
expectedArgs: []string{
"/usr/local/bin/ssh",
"docker@localhost",
"apt-get install -y htop",
},
},
{
binaryPath: "C:\\Program Files\\Git\\bin\\ssh.exe",
args: []string{
"docker@localhost",
"sudo /usr/bin/sethostname foobar && echo 'foobar' | sudo tee /var/lib/boot2docker/etc/hostname",
},
expectedArgs: []string{
"C:\\Program Files\\Git\\bin\\ssh.exe",
"docker@localhost",
"sudo /usr/bin/sethostname foobar && echo 'foobar' | sudo tee /var/lib/boot2docker/etc/hostname",
},
},
}
for _, c := range cases {
cmd := getSSHCmd(c.binaryPath, c.args...)
assert.Equal(t, cmd.Args, c.expectedArgs)
}
}

View File

@ -26,7 +26,7 @@ load ${BASE_TEST_DIR}/helpers.bash
@test "$DRIVER: test command did what it purported to -- native ssh" { @test "$DRIVER: test command did what it purported to -- native ssh" {
run machine --native-ssh ssh $NAME echo foo run machine --native-ssh ssh $NAME echo foo
[[ "$output" == "foo" ]] [[ "$output" =~ "foo" ]]
} }
@test "$DRIVER: ensure that ssh extra arguments work" { @test "$DRIVER: ensure that ssh extra arguments work" {