mirror of https://github.com/docker/docs.git
wip: commands across nodes
Signed-off-by: Evan Hazlett <ejhazlett@gmail.com>
This commit is contained in:
parent
18b58b4601
commit
9ca79892a6
104
commands.go
104
commands.go
|
@ -9,7 +9,9 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
"time"
|
||||||
|
|
||||||
log "github.com/Sirupsen/logrus"
|
log "github.com/Sirupsen/logrus"
|
||||||
"github.com/codegangsta/cli"
|
"github.com/codegangsta/cli"
|
||||||
|
@ -382,12 +384,6 @@ func cmdIp(c *cli.Context) {
|
||||||
fmt.Println(ip)
|
fmt.Println(ip)
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmdKill(c *cli.Context) {
|
|
||||||
if err := getHost(c).Driver.Kill(); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func cmdLs(c *cli.Context) {
|
func cmdLs(c *cli.Context) {
|
||||||
quiet := c.Bool("quiet")
|
quiet := c.Bool("quiet")
|
||||||
store := NewStore(c.GlobalString("storage-path"), c.GlobalString("tls-ca-cert"), c.GlobalString("tls-ca-key"))
|
store := NewStore(c.GlobalString("storage-path"), c.GlobalString("tls-ca-cert"), c.GlobalString("tls-ca-key"))
|
||||||
|
@ -456,12 +452,6 @@ func cmdLs(c *cli.Context) {
|
||||||
w.Flush()
|
w.Flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmdRestart(c *cli.Context) {
|
|
||||||
if err := getHost(c).Driver.Restart(); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func cmdRm(c *cli.Context) {
|
func cmdRm(c *cli.Context) {
|
||||||
if len(c.Args()) == 0 {
|
if len(c.Args()) == 0 {
|
||||||
cli.ShowCommandHelp(c, "rm")
|
cli.ShowCommandHelp(c, "rm")
|
||||||
|
@ -573,20 +563,79 @@ func cmdSsh(c *cli.Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// machineCommand maps the command name to the corresponding machine command
|
||||||
|
// it is intended to be used by runCommand using a waitgroup and error channel
|
||||||
|
// to enable running commands across multiple machines asynchronously
|
||||||
|
func machineCommand(name string, machine *Host, wg *sync.WaitGroup, errorChan chan<- error) {
|
||||||
|
commands := map[string]interface{}{
|
||||||
|
"start": machine.Start,
|
||||||
|
"stop": machine.Stop,
|
||||||
|
"restart": machine.Driver.Restart,
|
||||||
|
"kill": machine.Driver.Kill,
|
||||||
|
"upgrade": machine.Upgrade,
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debugf("command=%s machine=%s", name, machine.Name)
|
||||||
|
|
||||||
|
if err := commands[name].(func() error)(); err != nil {
|
||||||
|
errorChan <- err
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Done()
|
||||||
|
}
|
||||||
|
|
||||||
|
// runCommand will run the command across multiple machines
|
||||||
|
func runCommand(name string, c *cli.Context) error {
|
||||||
|
errorChan := make(chan error)
|
||||||
|
go func() {
|
||||||
|
err := <-errorChan
|
||||||
|
log.Errorf(err.Error())
|
||||||
|
}()
|
||||||
|
|
||||||
|
wg := &sync.WaitGroup{}
|
||||||
|
|
||||||
|
machines, err := getHosts(c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, machine := range machines {
|
||||||
|
wg.Add(1)
|
||||||
|
go machineCommand(name, machine, wg, errorChan)
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func cmdStart(c *cli.Context) {
|
func cmdStart(c *cli.Context) {
|
||||||
if err := getHost(c).Start(); err != nil {
|
if err := runCommand("start", c); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmdStop(c *cli.Context) {
|
func cmdStop(c *cli.Context) {
|
||||||
if err := getHost(c).Stop(); err != nil {
|
if err := runCommand("stop", c); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdRestart(c *cli.Context) {
|
||||||
|
if err := runCommand("restart", c); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdKill(c *cli.Context) {
|
||||||
|
if err := runCommand("kill", c); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmdUpgrade(c *cli.Context) {
|
func cmdUpgrade(c *cli.Context) {
|
||||||
if err := getHost(c).Upgrade(); err != nil {
|
if err := runCommand("upgrade", c); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -610,6 +659,31 @@ func cmdNotFound(c *cli.Context, command string) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getHosts(c *cli.Context) ([]*Host, error) {
|
||||||
|
machines := []*Host{}
|
||||||
|
for _, n := range c.Args() {
|
||||||
|
machine, err := loadMachine(n, c)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
machines = append(machines, machine)
|
||||||
|
}
|
||||||
|
|
||||||
|
return machines, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadMachine(name string, c *cli.Context) (*Host, error) {
|
||||||
|
store := NewStore(c.GlobalString("storage-path"), c.GlobalString("tls-ca-cert"), c.GlobalString("tls-ca-key"))
|
||||||
|
|
||||||
|
machine, err := store.Load(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return machine, nil
|
||||||
|
}
|
||||||
|
|
||||||
func getHost(c *cli.Context) *Host {
|
func getHost(c *cli.Context) *Host {
|
||||||
name := c.Args().First()
|
name := c.Args().First()
|
||||||
store := NewStore(c.GlobalString("storage-path"), c.GlobalString("tls-ca-cert"), c.GlobalString("tls-ca-key"))
|
store := NewStore(c.GlobalString("storage-path"), c.GlobalString("tls-ca-cert"), c.GlobalString("tls-ca-key"))
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/codegangsta/cli"
|
||||||
drivers "github.com/docker/machine/drivers"
|
drivers "github.com/docker/machine/drivers"
|
||||||
"github.com/docker/machine/state"
|
"github.com/docker/machine/state"
|
||||||
)
|
)
|
||||||
|
@ -81,6 +84,49 @@ func (d *FakeDriver) GetSSHCommand(args ...string) (*exec.Cmd, error) {
|
||||||
return &exec.Cmd{}, nil
|
return &exec.Cmd{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetHosts(t *testing.T) {
|
||||||
|
if err := clearHosts(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
flags := getDefaultTestDriverFlags()
|
||||||
|
|
||||||
|
store := NewStore(TestStoreDir, "", "")
|
||||||
|
|
||||||
|
hostA, hostAerr := store.Create("test-a", "none", flags)
|
||||||
|
if hostAerr != nil {
|
||||||
|
t.Fatal(hostAerr)
|
||||||
|
}
|
||||||
|
|
||||||
|
hostB, hostBerr := store.Create("test-b", "none", flags)
|
||||||
|
if hostBerr != nil {
|
||||||
|
t.Fatal(hostBerr)
|
||||||
|
}
|
||||||
|
|
||||||
|
set := flag.NewFlagSet("start", 0)
|
||||||
|
set.Parse([]string{"test-a", "test-b"})
|
||||||
|
|
||||||
|
c := cli.NewContext(nil, set, nil)
|
||||||
|
globalSet := flag.NewFlagSet("-d", 0)
|
||||||
|
globalSet.String("-d", "none", "driver")
|
||||||
|
globalSet.String("storage-path", TestStoreDir, "storage path")
|
||||||
|
globalSet.String("tls-ca-cert", "", "")
|
||||||
|
globalSet.String("tls-ca-key", "", "")
|
||||||
|
|
||||||
|
hosts, err := getHosts(c)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(hosts)
|
||||||
|
fmt.Println(hostA)
|
||||||
|
fmt.Println(hostB)
|
||||||
|
|
||||||
|
if err := clearHosts(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestGetHostState(t *testing.T) {
|
func TestGetHostState(t *testing.T) {
|
||||||
storePath, err := ioutil.TempDir("", ".docker")
|
storePath, err := ioutil.TempDir("", ".docker")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -9,6 +9,15 @@ import (
|
||||||
"github.com/docker/machine/utils"
|
"github.com/docker/machine/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
TestStoreDir = ".store-test"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
|
||||||
|
os.Setenv("MACHINE_STORAGE_PATH", TestStoreDir)
|
||||||
|
}
|
||||||
|
|
||||||
type DriverOptionsMock struct {
|
type DriverOptionsMock struct {
|
||||||
Data map[string]interface{}
|
Data map[string]interface{}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +35,7 @@ func (d DriverOptionsMock) Bool(key string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func clearHosts() error {
|
func clearHosts() error {
|
||||||
return os.RemoveAll(utils.GetMachineDir())
|
return os.RemoveAll(TestStoreDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDefaultTestDriverFlags() *DriverOptionsMock {
|
func getDefaultTestDriverFlags() *DriverOptionsMock {
|
||||||
|
|
Loading…
Reference in New Issue