Merge pull request #2068 from dgageot/cleanup-for-more-tests

Make commands code easier to test
This commit is contained in:
Nathan LeClaire 2015-10-29 12:30:15 -07:00
commit fe94b4c44f
24 changed files with 224 additions and 178 deletions

View File

@ -12,20 +12,27 @@ import (
"github.com/docker/machine/libmachine/state"
)
func cmdActive(c *cli.Context) {
var (
errTooManyArguments = errors.New("Error: Too many arguments given")
)
func cmdActive(c *cli.Context) error {
if len(c.Args()) > 0 {
fatal("Error: Too many arguments given.")
return errTooManyArguments
}
store := getStore(c)
host, err := getActiveHost(store)
if err != nil {
fatalf("Error getting active host: %s", err)
return fmt.Errorf("Error getting active host: %s", err)
}
if host != nil {
fmt.Println(host.Name)
}
return nil
}
func getActiveHost(store persist.Store) (*host.Host, error) {

View File

@ -19,8 +19,8 @@ import (
var (
ErrUnknownShell = errors.New("Error: Unknown shell")
ErrNoMachineSpecified = errors.New("Error: Expected to get one or more machine names as arguments.")
ErrExpectedOneMachine = errors.New("Error: Expected one machine name as an argument.")
ErrNoMachineSpecified = errors.New("Error: Expected to get one or more machine names as arguments")
ErrExpectedOneMachine = errors.New("Error: Expected one machine name as an argument")
)
func newPluginDriver(driverName string, rawContent []byte) (*rpcdriver.RpcClientDriver, error) {
@ -32,29 +32,25 @@ func newPluginDriver(driverName string, rawContent []byte) (*rpcdriver.RpcClient
return d, nil
}
func fatal(args ...interface{}) {
log.Fatal(args...)
func fatalOnError(command func(context *cli.Context) error) func(context *cli.Context) {
return func(context *cli.Context) {
if err := command(context); err != nil {
log.Fatal(err)
}
}
}
func fatalf(fmtString string, args ...interface{}) {
log.Fatalf(fmtString, args...)
}
func confirmInput(msg string) bool {
func confirmInput(msg string) (bool, error) {
fmt.Printf("%s (y/n): ", msg)
var resp string
_, err := fmt.Scanln(&resp)
if err != nil {
fatal(err)
return false, err
}
if strings.Index(strings.ToLower(resp), "y") == 0 {
return true
}
return false
confirmed := strings.Index(strings.ToLower(resp), "y") == 0
return confirmed, nil
}
func getStore(c *cli.Context) persist.Store {
@ -112,17 +108,16 @@ func saveHost(store persist.Store, h *host.Host) error {
return nil
}
func getFirstArgHost(c *cli.Context) *host.Host {
func getFirstArgHost(c *cli.Context) (*host.Host, error) {
store := getStore(c)
hostName := c.Args().First()
exists, err := store.Exists(hostName)
if err != nil {
fatalf("Error checking if host %q exists: %s", hostName, err)
return nil, fmt.Errorf("Error checking if host %q exists: %s", hostName, err)
}
if !exists {
fatalf("Host %q does not exist", hostName)
return nil, fmt.Errorf("Host %q does not exist", hostName)
}
h, err := loadHost(store, hostName)
@ -131,9 +126,10 @@ func getFirstArgHost(c *cli.Context) *host.Host {
// the host reliably we're definitely not going to be able to
// do anything else interesting, but also this premature exit
// feels wrong to me. Let's revisit it later.
fatalf("Error trying to get host %q: %s", hostName, err)
return nil, fmt.Errorf("Error trying to get host %q: %s", hostName, err)
}
return h
return h, nil
}
func getHostsFromContext(c *cli.Context) ([]*host.Host, error) {
@ -155,13 +151,13 @@ var Commands = []cli.Command{
{
Name: "active",
Usage: "Print which machine is active",
Action: cmdActive,
Action: fatalOnError(cmdActive),
},
{
Name: "config",
Usage: "Print the connection config for machine",
Description: "Argument is a machine name.",
Action: cmdConfig,
Action: fatalOnError(cmdConfig),
Flags: []cli.Flag{
cli.BoolFlag{
Name: "swarm",
@ -173,14 +169,14 @@ var Commands = []cli.Command{
Flags: sharedCreateFlags,
Name: "create",
Usage: "Create a machine.\n\nSpecify a driver with --driver to include the create flags for that driver in the help text.",
Action: cmdCreateOuter,
Action: fatalOnError(cmdCreateOuter),
SkipFlagParsing: true,
},
{
Name: "env",
Usage: "Display the commands to set up the environment for the Docker client",
Description: "Argument is a machine name.",
Action: cmdEnv,
Action: fatalOnError(cmdEnv),
Flags: []cli.Flag{
cli.BoolFlag{
Name: "swarm",
@ -204,7 +200,7 @@ var Commands = []cli.Command{
Name: "inspect",
Usage: "Inspect information about a machine",
Description: "Argument is a machine name.",
Action: cmdInspect,
Action: fatalOnError(cmdInspect),
Flags: []cli.Flag{
cli.StringFlag{
Name: "format, f",
@ -217,13 +213,13 @@ var Commands = []cli.Command{
Name: "ip",
Usage: "Get the IP address of a machine",
Description: "Argument(s) are one or more machine names.",
Action: cmdIp,
Action: fatalOnError(cmdIp),
},
{
Name: "kill",
Usage: "Kill a machine",
Description: "Argument(s) are one or more machine names.",
Action: cmdKill,
Action: fatalOnError(cmdKill),
},
{
Flags: []cli.Flag{
@ -239,13 +235,13 @@ var Commands = []cli.Command{
},
Name: "ls",
Usage: "List machines",
Action: cmdLs,
Action: fatalOnError(cmdLs),
},
{
Name: "regenerate-certs",
Usage: "Regenerate TLS Certificates for a machine",
Description: "Argument(s) are one or more machine names.",
Action: cmdRegenerateCerts,
Action: fatalOnError(cmdRegenerateCerts),
Flags: []cli.Flag{
cli.BoolFlag{
Name: "force, f",
@ -257,7 +253,7 @@ var Commands = []cli.Command{
Name: "restart",
Usage: "Restart a machine",
Description: "Argument(s) are one or more machine names.",
Action: cmdRestart,
Action: fatalOnError(cmdRestart),
},
{
Flags: []cli.Flag{
@ -269,20 +265,20 @@ var Commands = []cli.Command{
Name: "rm",
Usage: "Remove a machine",
Description: "Argument(s) are one or more machine names.",
Action: cmdRm,
Action: fatalOnError(cmdRm),
},
{
Name: "ssh",
Usage: "Log into or run a command on a machine with SSH.",
Description: "Arguments are [machine-name] [command]",
Action: cmdSsh,
Action: fatalOnError(cmdSsh),
SkipFlagParsing: true,
},
{
Name: "scp",
Usage: "Copy files between machines",
Description: "Arguments are [machine:][path] [machine:][path].",
Action: cmdScp,
Action: fatalOnError(cmdScp),
Flags: []cli.Flag{
cli.BoolFlag{
Name: "recursive, r",
@ -294,31 +290,31 @@ var Commands = []cli.Command{
Name: "start",
Usage: "Start a machine",
Description: "Argument(s) are one or more machine names.",
Action: cmdStart,
Action: fatalOnError(cmdStart),
},
{
Name: "status",
Usage: "Get the status of a machine",
Description: "Argument is a machine name.",
Action: cmdStatus,
Action: fatalOnError(cmdStatus),
},
{
Name: "stop",
Usage: "Stop a machine",
Description: "Argument(s) are one or more machine names.",
Action: cmdStop,
Action: fatalOnError(cmdStop),
},
{
Name: "upgrade",
Usage: "Upgrade a machine to the latest version of Docker",
Description: "Argument(s) are one or more machine names.",
Action: cmdUpgrade,
Action: fatalOnError(cmdUpgrade),
},
{
Name: "url",
Usage: "Get the URL of a machine",
Description: "Argument is a machine name.",
Action: cmdUrl,
Action: fatalOnError(cmdUrl),
},
}

View File

@ -14,26 +14,31 @@ import (
"github.com/docker/machine/libmachine/state"
)
func cmdConfig(c *cli.Context) {
func cmdConfig(c *cli.Context) error {
// Ensure that log messages always go to stderr when this command is
// being run (it is intended to be run in a subshell)
log.SetOutWriter(os.Stderr)
if len(c.Args()) != 1 {
fatal(ErrExpectedOneMachine)
return ErrExpectedOneMachine
}
h := getFirstArgHost(c)
dockerHost, authOptions, err := runConnectionBoilerplate(h, c)
host, err := getFirstArgHost(c)
if err != nil {
fatalf("Error running connection boilerplate: %s", err)
return err
}
dockerHost, authOptions, err := runConnectionBoilerplate(host, c)
if err != nil {
return fmt.Errorf("Error running connection boilerplate: %s", err)
}
log.Debug(dockerHost)
fmt.Printf("--tlsverify --tlscacert=%q --tlscert=%q --tlskey=%q -H=%s",
authOptions.CaCertPath, authOptions.ClientCertPath, authOptions.ClientKeyPath, dockerHost)
return nil
}
func runConnectionBoilerplate(h *host.Host, c *cli.Context) (string, *auth.AuthOptions, error) {
@ -44,7 +49,7 @@ func runConnectionBoilerplate(h *host.Host, c *cli.Context) (string, *auth.AuthO
return "", &auth.AuthOptions{}, fmt.Errorf("Error trying to get host state: %s", err)
}
if hostState != state.Running {
return "", &auth.AuthOptions{}, fmt.Errorf("%s is not running. Please start it in order to use the connection settings.", h.Name)
return "", &auth.AuthOptions{}, fmt.Errorf("%s is not running. Please start it in order to use the connection settings", h.Name)
}
dockerHost, err := h.Driver.GetURL()
@ -101,7 +106,7 @@ func parseSwarm(hostUrl string, h *host.Host) (string, error) {
swarmOptions := h.HostOptions.SwarmOptions
if !swarmOptions.Master {
return "", fmt.Errorf("Error: %s is not a swarm master. The --swarm flag is intended for use with swarm masters.", h.Name)
return "", fmt.Errorf("Error: %s is not a swarm master. The --swarm flag is intended for use with swarm masters", h.Name)
}
u, err := url.Parse(swarmOptions.Host)

View File

@ -10,6 +10,8 @@ import (
"sort"
"strings"
"errors"
"github.com/docker/machine/cli"
"github.com/docker/machine/commands/mcndirs"
"github.com/docker/machine/libmachine"
@ -25,6 +27,10 @@ import (
"github.com/docker/machine/libmachine/swarm"
)
var (
errNoMachineName = errors.New("Error: No machine name specified")
)
var (
sharedCreateFlags = []cli.Flag{
cli.StringFlag{
@ -111,9 +117,9 @@ var (
}
)
func cmdCreateInner(c *cli.Context) {
func cmdCreateInner(c *cli.Context) error {
if len(c.Args()) > 1 {
fatalf("Invalid command line. Found extra arguments %v", c.Args()[1:])
return fmt.Errorf("Invalid command line. Found extra arguments %v", c.Args()[1:])
}
name := c.Args().First()
@ -130,16 +136,16 @@ func cmdCreateInner(c *cli.Context) {
if name == "" {
cli.ShowCommandHelp(c, "create")
fatal("Error: No machine name specified.")
return errNoMachineName
}
validName := host.ValidateHostName(name)
if !validName {
fatal("Error creating machine: ", mcnerror.ErrInvalidHostname)
return fmt.Errorf("Error creating machine: %s", mcnerror.ErrInvalidHostname)
}
if err := validateSwarmDiscovery(c.String("swarm-discovery")); err != nil {
fatalf("Error parsing swarm discovery: %s", err)
return fmt.Errorf("Error parsing swarm discovery: %s", err)
}
// TODO: Fix hacky JSON solution
@ -148,17 +154,17 @@ func cmdCreateInner(c *cli.Context) {
StorePath: c.GlobalString("storage-path"),
})
if err != nil {
fatalf("Error attempting to marshal bare driver data: %s", err)
return fmt.Errorf("Error attempting to marshal bare driver data: %s", err)
}
driver, err := newPluginDriver(driverName, bareDriverData)
if err != nil {
fatalf("Error loading driver %q: %s", driverName, err)
return fmt.Errorf("Error loading driver %q: %s", driverName, err)
}
h, err := store.NewHost(driver)
if err != nil {
fatalf("Error getting new host: %s", err)
return fmt.Errorf("Error getting new host: %s", err)
}
h.HostOptions = &host.HostOptions{
@ -196,12 +202,12 @@ func cmdCreateInner(c *cli.Context) {
exists, err := store.Exists(h.Name)
if err != nil {
fatalf("Error checking if host exists: %s", err)
return fmt.Errorf("Error checking if host exists: %s", err)
}
if exists {
fatal(mcnerror.ErrHostAlreadyExists{
return mcnerror.ErrHostAlreadyExists{
Name: h.Name,
})
}
}
// driverOpts is the actual data we send over the wire to set the
@ -211,18 +217,20 @@ func cmdCreateInner(c *cli.Context) {
driverOpts := getDriverOpts(c, mcnFlags)
if err := h.Driver.SetConfigFromFlags(driverOpts); err != nil {
fatalf("Error setting machine configuration from flags provided: %s", err)
return fmt.Errorf("Error setting machine configuration from flags provided: %s", err)
}
if err := libmachine.Create(store, h); err != nil {
fatalf("Error creating machine: %s", err)
return fmt.Errorf("Error creating machine: %s", err)
}
if err := saveHost(store, h); err != nil {
fatalf("Error attempting to save store: %s", err)
return fmt.Errorf("Error attempting to save store: %s", err)
}
log.Infof("To see how to connect Docker to this machine, run: %s", fmt.Sprintf("%s env %s", os.Args[0], name))
return nil
}
// The following function is needed because the CLI acrobatics that we're doing
@ -261,13 +269,13 @@ func flagHackLookup(flagName string) string {
return ""
}
func cmdCreateOuter(c *cli.Context) {
func cmdCreateOuter(c *cli.Context) error {
driverName := flagHackLookup("--driver")
// We didn't recognize the driver name.
if driverName == "" {
cli.ShowCommandHelp(c, "create")
return
return nil // ?
}
name := c.Args().First()
@ -277,12 +285,12 @@ func cmdCreateOuter(c *cli.Context) {
MachineName: name,
})
if err != nil {
fatalf("Error attempting to marshal bare driver data: %s", err)
return fmt.Errorf("Error attempting to marshal bare driver data: %s", err)
}
driver, err := newPluginDriver(driverName, bareDriverData)
if err != nil {
fatalf("Error loading driver %q: %s", driverName, err)
return fmt.Errorf("Error loading driver %q: %s", driverName, err)
}
// TODO: So much flag manipulation and voodoo here, it seems to be
@ -296,8 +304,9 @@ func cmdCreateOuter(c *cli.Context) {
// on the requested driver.
cliFlags, err := convertMcnFlagsToCliFlags(mcnFlags)
if err != nil {
fatalf("Error trying to convert provided driver flags to cli flags: %s", err)
return fmt.Errorf("Error trying to convert provided driver flags to cli flags: %s", err)
}
for i := range c.App.Commands {
cmd := &c.App.Commands[i]
if cmd.HasName("create") {
@ -306,12 +315,10 @@ func cmdCreateOuter(c *cli.Context) {
}
if err := driver.Close(); err != nil {
fatal(err)
return err
}
if err := c.App.Run(os.Args); err != nil {
fatal(err)
}
return c.App.Run(os.Args)
}
func getDriverOpts(c *cli.Context, mcnflags []mcnflag.Flag) drivers.DriverOptions {
@ -401,7 +408,7 @@ func convertMcnFlagsToCliFlags(mcnFlags []mcnflag.Flag) ([]cli.Flag, error) {
func addDriverFlagsToCommand(cliFlags []cli.Flag, cmd *cli.Command) *cli.Command {
cmd.Flags = append(sharedCreateFlags, cliFlags...)
cmd.SkipFlagParsing = false
cmd.Action = cmdCreateInner
cmd.Action = fatalOnError(cmdCreateInner)
sort.Sort(ByFlagName(cmd.Flags))
return cmd

View File

@ -18,7 +18,7 @@ const (
)
var (
improperEnvArgsError = errors.New("Error: Expected either one machine name, or -u flag to unset the variables in the arguments.")
errImproperEnvArgs = errors.New("Error: Expected either one machine name, or -u flag to unset the variables in the arguments")
)
type ShellConfig struct {
@ -34,27 +34,30 @@ type ShellConfig struct {
NoProxyValue string
}
func cmdEnv(c *cli.Context) {
func cmdEnv(c *cli.Context) error {
// Ensure that log messages always go to stderr when this command is
// being run (it is intended to be run in a subshell)
log.SetOutWriter(os.Stderr)
if len(c.Args()) != 1 && !c.Bool("unset") {
fatal(improperEnvArgsError)
return errImproperEnvArgs
}
h := getFirstArgHost(c)
dockerHost, _, err := runConnectionBoilerplate(h, c)
host, err := getFirstArgHost(c)
if err != nil {
fatalf("Error running connection boilerplate: %s", err)
return err
}
dockerHost, _, err := runConnectionBoilerplate(host, c)
if err != nil {
return fmt.Errorf("Error running connection boilerplate: %s", err)
}
userShell := c.String("shell")
if userShell == "" {
shell, err := detectShell()
if err != nil {
fatal(err)
return err
}
userShell = shell
}
@ -64,17 +67,17 @@ func cmdEnv(c *cli.Context) {
usageHint := generateUsageHint(userShell, os.Args)
shellCfg := &ShellConfig{
DockerCertPath: filepath.Join(mcndirs.GetMachineDir(), h.Name),
DockerCertPath: filepath.Join(mcndirs.GetMachineDir(), host.Name),
DockerHost: dockerHost,
DockerTLSVerify: "1",
UsageHint: usageHint,
MachineName: h.Name,
MachineName: host.Name,
}
if c.Bool("no-proxy") {
ip, err := h.Driver.GetIP()
ip, err := host.Driver.GetIP()
if err != nil {
fatalf("Error getting host IP: %s", err)
return fmt.Errorf("Error getting host IP: %s", err)
}
// first check for an existing lower case no_proxy var
@ -128,13 +131,10 @@ func cmdEnv(c *cli.Context) {
tmpl, err := t.Parse(envTmpl)
if err != nil {
fatal(err)
return err
}
if err := tmpl.Execute(os.Stdout, shellCfg); err != nil {
fatal(err)
}
return
return tmpl.Execute(os.Stdout, shellCfg)
}
switch userShell {
@ -158,12 +158,10 @@ func cmdEnv(c *cli.Context) {
tmpl, err := t.Parse(envTmpl)
if err != nil {
fatal(err)
return err
}
if err := tmpl.Execute(os.Stdout, shellCfg); err != nil {
fatal(err)
}
return tmpl.Execute(os.Stdout, shellCfg)
}
func generateUsageHint(userShell string, args []string) string {

View File

@ -20,10 +20,15 @@ var funcMap = template.FuncMap{
},
}
func cmdInspect(c *cli.Context) {
func cmdInspect(c *cli.Context) error {
if len(c.Args()) == 0 {
cli.ShowCommandHelp(c, "inspect")
fatal("You must specify a machine name")
return ErrExpectedOneMachine
}
host, err := getFirstArgHost(c)
if err != nil {
return err
}
tmplString := c.String("format")
@ -31,28 +36,32 @@ func cmdInspect(c *cli.Context) {
var tmpl *template.Template
var err error
if tmpl, err = template.New("").Funcs(funcMap).Parse(tmplString); err != nil {
fatalf("Template parsing error: %v\n", err)
return fmt.Errorf("Template parsing error: %v\n", err)
}
jsonHost, err := json.Marshal(getFirstArgHost(c))
jsonHost, err := json.Marshal(host)
if err != nil {
fatal(err)
return err
}
obj := make(map[string]interface{})
if err := json.Unmarshal(jsonHost, &obj); err != nil {
fatal(err)
return err
}
if err := tmpl.Execute(os.Stdout, obj); err != nil {
fatal(err)
return err
}
os.Stdout.Write([]byte{'\n'})
} else {
prettyJSON, err := json.MarshalIndent(getFirstArgHost(c), "", " ")
prettyJSON, err := json.MarshalIndent(host, "", " ")
if err != nil {
fatal(err)
return err
}
fmt.Println(string(prettyJSON))
}
return nil
}

View File

@ -2,8 +2,6 @@ package commands
import "github.com/docker/machine/cli"
func cmdIp(c *cli.Context) {
if err := runActionWithContext("ip", c); err != nil {
fatal(err)
}
func cmdIp(c *cli.Context) error {
return runActionWithContext("ip", c)
}

View File

@ -2,8 +2,6 @@ package commands
import "github.com/docker/machine/cli"
func cmdKill(c *cli.Context) {
if err := runActionWithContext("kill", c); err != nil {
fatal(err)
}
func cmdKill(c *cli.Context) error {
return runActionWithContext("kill", c)
}

View File

@ -40,17 +40,17 @@ type HostListItem struct {
SwarmOptions *swarm.SwarmOptions
}
func cmdLs(c *cli.Context) {
func cmdLs(c *cli.Context) error {
quiet := c.Bool("quiet")
filters, err := parseFilters(c.StringSlice("filter"))
if err != nil {
fatal(err)
return err
}
store := getStore(c)
hostList, err := listHosts(store)
if err != nil {
fatal(err)
return err
}
hostList = filterHosts(hostList, filters)
@ -60,7 +60,7 @@ func cmdLs(c *cli.Context) {
for _, host := range hostList {
fmt.Println(host.Name)
}
return
return nil
}
swarmMasters := make(map[string]string)
@ -103,6 +103,8 @@ func cmdLs(c *cli.Context) {
}
w.Flush()
return nil
}
func parseFilters(filters []string) (FilterOptions, error) {
@ -218,7 +220,8 @@ func matchesName(host *host.Host, names []string) bool {
for _, n := range names {
r, err := regexp.Compile(n)
if err != nil {
fatal(err)
// TODO: remove that call to Fatal
log.Fatal(err)
}
if r.MatchString(host.Driver.GetMachineName()) {
return true

View File

@ -5,12 +5,19 @@ import (
"github.com/docker/machine/libmachine/log"
)
func cmdRegenerateCerts(c *cli.Context) {
force := c.Bool("force")
if force || confirmInput("Regenerate TLS machine certs? Warning: this is irreversible.") {
func cmdRegenerateCerts(c *cli.Context) error {
if !c.Bool("force") {
ok, err := confirmInput("Regenerate TLS machine certs? Warning: this is irreversible.")
if err != nil {
return err
}
if !ok {
return nil
}
}
log.Infof("Regenerating TLS certificates")
if err := runActionWithContext("configureAuth", c); err != nil {
fatal(err)
}
}
return runActionWithContext("configureAuth", c)
}

View File

@ -6,9 +6,12 @@ import (
"github.com/docker/machine/cli"
)
func cmdRestart(c *cli.Context) {
func cmdRestart(c *cli.Context) error {
if err := runActionWithContext("restart", c); err != nil {
fatal(err)
return err
}
log.Info("Restarted machines may have new IP addresses. You may need to re-run the `docker-machine env` command.")
return nil
}

View File

@ -1,14 +1,17 @@
package commands
import (
"errors"
"fmt"
"github.com/docker/machine/cli"
"github.com/docker/machine/libmachine/log"
)
func cmdRm(c *cli.Context) {
func cmdRm(c *cli.Context) error {
if len(c.Args()) == 0 {
cli.ShowCommandHelp(c, "rm")
fatal("You must specify a machine name")
return errors.New("You must specify a machine name")
}
force := c.Bool("force")
@ -17,8 +20,9 @@ func cmdRm(c *cli.Context) {
for _, hostName := range c.Args() {
h, err := loadHost(store, hostName)
if err != nil {
fatalf("Error removing host %q: %s", hostName, err)
return fmt.Errorf("Error removing host %q: %s", hostName, err)
}
if err := h.Driver.Remove(); err != nil {
if !force {
log.Errorf("Provider error removing machine %q: %s", hostName, err)
@ -32,4 +36,6 @@ func cmdRm(c *cli.Context) {
log.Infof("Successfully removed %s", hostName)
}
}
return nil
}

View File

@ -14,7 +14,8 @@ import (
)
var (
ErrMalformedInput = fmt.Errorf("The input was malformed")
errMalformedInput = errors.New("The input was malformed")
errWrongNumberArguments = errors.New("Improper number of arguments")
)
var (
@ -64,7 +65,7 @@ func getInfoForScpArg(hostAndPath string, store persist.Store) (*host.Host, stri
return host, path, args, nil
}
return nil, "", nil, ErrMalformedInput
return nil, "", nil, errMalformedInput
}
func generateLocationArg(host *host.Host, path string) (string, error) {
@ -120,19 +121,17 @@ func runCmdWithStdIo(cmd exec.Cmd) error {
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
fatal(err)
}
return nil
return cmd.Run()
}
func cmdScp(c *cli.Context) {
func cmdScp(c *cli.Context) error {
hostLoader = &ScpHostLoader{}
args := c.Args()
if len(args) != 2 {
cli.ShowCommandHelp(c, "scp")
fatal("Improper number of arguments.")
return errWrongNumberArguments
}
// TODO: Check that "-3" flag is available in user's version of scp.
@ -147,12 +146,11 @@ func cmdScp(c *cli.Context) {
dest := args[1]
store := getStore(c)
cmd, err := getScpCmd(src, dest, sshArgs, store)
cmd, err := getScpCmd(src, dest, sshArgs, store)
if err != nil {
fatal(err)
}
if err := runCmdWithStdIo(*cmd); err != nil {
fatal(err)
return err
}
return runCmdWithStdIo(*cmd)
}

View File

@ -196,7 +196,7 @@ func TestGetInfoForScpArg(t *testing.T) {
}
host, path, opts, err = getInfoForScpArg("foo:bar:widget", store)
if err != ErrMalformedInput {
if err != errMalformedInput {
t.Fatalf("Didn't get back an error when we were expecting it for malformed args")
}
}

View File

@ -1,39 +1,37 @@
package commands
import (
"fmt"
"github.com/docker/machine/cli"
"github.com/docker/machine/libmachine/state"
)
func cmdSsh(c *cli.Context) {
args := c.Args()
name := args.First()
func cmdSsh(c *cli.Context) error {
name := c.Args().First()
if name == "" {
fatal("Error: Please specify a machine name.")
return ErrExpectedOneMachine
}
store := getStore(c)
host, err := loadHost(store, name)
if err != nil {
fatal(err)
return err
}
currentState, err := host.Driver.GetState()
if err != nil {
fatal(err)
return err
}
if currentState != state.Running {
fatalf("Error: Cannot run SSH command: Host %q is not running", host.Name)
return fmt.Errorf("Error: Cannot run SSH command: Host %q is not running", host.Name)
}
client, err := host.CreateSSHClient()
if err != nil {
fatal(err)
return err
}
if err := client.Shell(c.Args().Tail()...); err != nil {
fatal(err)
}
return client.Shell(c.Args().Tail()...)
}

View File

@ -6,9 +6,12 @@ import (
"github.com/docker/machine/cli"
)
func cmdStart(c *cli.Context) {
func cmdStart(c *cli.Context) error {
if err := runActionWithContext("start", c); err != nil {
fatal(err)
return err
}
log.Info("Started machines may have new IP addresses. You may need to re-run the `docker-machine env` command.")
return nil
}

View File

@ -5,16 +5,22 @@ import (
"github.com/docker/machine/libmachine/log"
)
func cmdStatus(c *cli.Context) {
func cmdStatus(c *cli.Context) error {
if len(c.Args()) != 1 {
fatal(ErrExpectedOneMachine)
return ErrExpectedOneMachine
}
host, err := getFirstArgHost(c)
if err != nil {
return err
}
host := getFirstArgHost(c)
currentState, err := host.Driver.GetState()
if err != nil {
log.Errorf("error getting state for host %s: %s", host.Name, err)
}
log.Info(currentState)
return nil
}

View File

@ -2,8 +2,6 @@ package commands
import "github.com/docker/machine/cli"
func cmdStop(c *cli.Context) {
if err := runActionWithContext("stop", c); err != nil {
fatal(err)
}
func cmdStop(c *cli.Context) error {
return runActionWithContext("stop", c)
}

View File

@ -2,8 +2,6 @@ package commands
import "github.com/docker/machine/cli"
func cmdUpgrade(c *cli.Context) {
if err := runActionWithContext("upgrade", c); err != nil {
fatal(err)
}
func cmdUpgrade(c *cli.Context) error {
return runActionWithContext("upgrade", c)
}

View File

@ -6,14 +6,22 @@ import (
"github.com/docker/machine/cli"
)
func cmdUrl(c *cli.Context) {
func cmdUrl(c *cli.Context) error {
if len(c.Args()) != 1 {
fatal(ErrExpectedOneMachine)
return ErrExpectedOneMachine
}
url, err := getFirstArgHost(c).GetURL()
host, err := getFirstArgHost(c)
if err != nil {
fatal(err)
return err
}
url, err := host.GetURL()
if err != nil {
return err
}
fmt.Println(url)
return nil
}

View File

@ -8,11 +8,11 @@ load ${BASE_TEST_DIR}/helpers.bash
[[ ${lines[0]} == "Driver \"bogus\" not found. Do you have the plugin binary accessible in your PATH?" ]]
}
@test "none: create with no name fails 'machine create -d none \" \"'" {
@test "none: create with no name fails 'machine create -d none'" {
run machine create -d none
last=$((${#lines[@]} - 1))
[ "$status" -eq 1 ]
[[ ${lines[$last]} == "Error: No machine name specified." ]]
[[ ${lines[$last]} == "Error: No machine name specified" ]]
}
@test "none: create with invalid name fails 'machine create -d none --url none ∞'" {

View File

@ -5,5 +5,5 @@ load ${BASE_TEST_DIR}/helpers.bash
@test "inspect: show error in case of no args" {
run machine inspect
[ "$status" -eq 1 ]
[[ ${output} == *"must specify a machine name"* ]]
[[ ${output} == *"Expected one machine name as an argument"* ]]
}

View File

@ -5,5 +5,5 @@ load ${BASE_TEST_DIR}/helpers.bash
@test "status: show error in case of no args" {
run machine status
[ "$status" -eq 1 ]
[[ ${output} == *"Expected one machine name as an argument."* ]]
[[ ${output} == *"Expected one machine name as an argument"* ]]
}

View File

@ -5,5 +5,5 @@ load ${BASE_TEST_DIR}/helpers.bash
@test "url: show error in case of no args" {
run machine url
[ "$status" -eq 1 ]
[[ ${output} == *"Expected one machine name as an argument."* ]]
[[ ${output} == *"Expected one machine name as an argument"* ]]
}