Enhancing `docker-machine ip` to support multiple host arguments

Fixes #999

Signed-off-by: Dave Henderson <Dave.Henderson@ca.ibm.com>
This commit is contained in:
Dave Henderson 2015-04-21 22:58:07 -04:00
parent 5fc9b78b38
commit a0f079a627
5 changed files with 75 additions and 13 deletions

View File

@ -234,7 +234,7 @@ var Commands = []cli.Command{
{ {
Name: "ip", Name: "ip",
Usage: "Get the IP address of a machine", Usage: "Get the IP address of a machine",
Description: "Argument is a machine name. Will use the active machine if none is provided.", Description: "Argument(s) are one or more machine names. Will use the active machine if none is provided.",
Action: cmdIp, Action: cmdIp,
}, },
{ {
@ -342,6 +342,7 @@ func machineCommand(actionName string, host *libmachine.Host, errorChan chan<- e
"restart": host.Restart, "restart": host.Restart,
"kill": host.Kill, "kill": host.Kill,
"upgrade": host.Upgrade, "upgrade": host.Upgrade,
"ip": host.PrintIP,
} }
log.Debugf("command=%s machine=%s", actionName, host.Name) log.Debugf("command=%s machine=%s", actionName, host.Name)

View File

@ -1,18 +1,13 @@
package commands package commands
import ( import (
"fmt"
log "github.com/Sirupsen/logrus" log "github.com/Sirupsen/logrus"
"github.com/codegangsta/cli" "github.com/codegangsta/cli"
) )
func cmdIp(c *cli.Context) { func cmdIp(c *cli.Context) {
ip, err := getHost(c).Driver.GetIP() if err := runActionWithContext("ip", c); err != nil {
if err != nil {
log.Fatal(err) log.Fatal(err)
} }
fmt.Println(ip)
} }

View File

@ -535,11 +535,16 @@ Show help text.
#### ip #### ip
Get the IP address of a machine. Get the IP address of one or more machines.
``` ```
$ docker-machine ip $ docker-machine ip
192.168.99.104 192.168.99.104
$ docker-machine ip dev
192.168.99.104
$ docker-machine ip dev dev2
192.168.99.104
192.168.99.105
``` ```
#### kill #### kill
@ -1051,5 +1056,3 @@ details, see [PR #553](https://github.com/docker/machine/issues/553).
* Improvements and isolation of provisioning functionality, so Machine can * Improvements and isolation of provisioning functionality, so Machine can
provision and configure the Docker Engine based on OS detection. For details, provision and configure the Docker Engine based on OS detection. For details,
see [PR #553](https://github.com/docker/machine/issues/553). see [PR #553](https://github.com/docker/machine/issues/553).

View File

@ -334,6 +334,15 @@ func (h *Host) SaveConfig() error {
return nil return nil
} }
func (h *Host) PrintIP() error {
if ip, err := h.Driver.GetIP(); err != nil {
return err
} else {
fmt.Println(ip)
}
return nil
}
func sshAvailableFunc(h *Host) func() bool { func sshAvailableFunc(h *Host) func() bool {
return func() bool { return func() bool {
log.Debug("Getting to WaitForSSH function...") log.Debug("Getting to WaitForSSH function...")

View File

@ -1,16 +1,21 @@
package libmachine package libmachine
import ( import (
"bytes"
"fmt" "fmt"
"io"
"io/ioutil" "io/ioutil"
"os" "os"
"strings"
"testing" "testing"
"github.com/docker/machine/drivers/fakedriver"
_ "github.com/docker/machine/drivers/none" _ "github.com/docker/machine/drivers/none"
"github.com/docker/machine/libmachine/auth" "github.com/docker/machine/libmachine/auth"
"github.com/docker/machine/libmachine/engine" "github.com/docker/machine/libmachine/engine"
"github.com/docker/machine/libmachine/swarm" "github.com/docker/machine/libmachine/swarm"
"github.com/stretchr/testify/assert"
) )
const ( const (
@ -22,8 +27,13 @@ const (
var ( var (
hostTestStorePath string hostTestStorePath string
stdout *os.File
) )
func init() {
stdout = os.Stdout
}
func getTestStore() (Store, error) { func getTestStore() (Store, error) {
tmpDir, err := ioutil.TempDir("", "machine-test-") tmpDir, err := ioutil.TempDir("", "machine-test-")
if err != nil { if err != nil {
@ -39,6 +49,7 @@ func getTestStore() (Store, error) {
} }
func cleanup() { func cleanup() {
os.Stdout = stdout
os.RemoveAll(hostTestStorePath) os.RemoveAll(hostTestStorePath)
} }
@ -124,7 +135,7 @@ func TestValidateHostnameValid(t *testing.T) {
for _, v := range hosts { for _, v := range hosts {
isValid := ValidateHostName(v) isValid := ValidateHostName(v)
if !isValid { if !isValid {
t.Fatal("Thought a valid hostname was invalid: %s", v) t.Fatalf("Thought a valid hostname was invalid: %s", v)
} }
} }
} }
@ -139,7 +150,7 @@ func TestValidateHostnameInvalid(t *testing.T) {
for _, v := range hosts { for _, v := range hosts {
isValid := ValidateHostName(v) isValid := ValidateHostName(v)
if isValid { if isValid {
t.Fatal("Thought an invalid hostname was valid: %s", v) t.Fatalf("Thought an invalid hostname was valid: %s", v)
} }
} }
} }
@ -172,3 +183,46 @@ func TestHostOptions(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
} }
func TestPrintIPEmptyGivenLocalEngine(t *testing.T) {
defer cleanup()
host, _ := getDefaultTestHost()
out, w := captureStdout()
assert.Nil(t, host.PrintIP())
w.Close()
assert.Equal(t, "", strings.TrimSpace(<-out))
}
func TestPrintIPPrintsGivenRemoteEngine(t *testing.T) {
defer cleanup()
host, _ := getDefaultTestHost()
host.Driver = &fakedriver.FakeDriver{}
out, w := captureStdout()
assert.Nil(t, host.PrintIP())
w.Close()
assert.Equal(t, "1.2.3.4", strings.TrimSpace(<-out))
}
func captureStdout() (chan string, *os.File) {
r, w, _ := os.Pipe()
// This is reversed in cleanup()
os.Stdout = w
out := make(chan string)
go func() {
var testOutput bytes.Buffer
io.Copy(&testOutput, r)
out <- testOutput.String()
}()
return out, w
}