diff --git a/commands.go b/commands.go index 0d89704038..cc931a3028 100644 --- a/commands.go +++ b/commands.go @@ -135,6 +135,29 @@ var Commands = []cli.Command{ ), Value: "none", }, + cli.BoolFlag{ + Name: "swarm", + Usage: "Configure Machine with Swarm", + }, + cli.BoolFlag{ + Name: "swarm-master", + Usage: "Configure Machine to be a Swarm master", + }, + cli.StringFlag{ + Name: "swarm-discovery", + Usage: "Discovery service to use with Swarm", + Value: "", + }, + cli.StringFlag{ + Name: "swarm-host", + Usage: "ip/socket to listen on for Swarm master", + Value: "tcp://0.0.0.0:3376", + }, + cli.StringFlag{ + Name: "swarm-addr", + Usage: "addr to advertise for Swarm (default: detect and use the machine IP)", + Value: "", + }, ), Name: "create", Usage: "Create a machine", diff --git a/host.go b/host.go index 61537aed0a..fdcc4d2cb0 100644 --- a/host.go +++ b/host.go @@ -24,6 +24,10 @@ var ( ErrInvalidHostname = errors.New("Invalid hostname specified") ) +const ( + swarmDockerImage = "ehazlett/swarm:latest" +) + type Host struct { Name string `json:"-"` DriverName string @@ -100,6 +104,70 @@ func GenerateClientCertificate(caCertPath, privateKeyPath string) error { return nil } +func (h *Host) ConfigureSwarm(discovery string, master bool, host string, addr string) error { + d := h.Driver + + if d.DriverName() == "none" { + return nil + } + + if addr == "" { + ip, err := d.GetIP() + if err != nil { + return err + } + // TODO: remove hardcoded port + addr = fmt.Sprintf("%s:2376", ip) + } + + var ( + role string + args string + ) + + if master { + role = "manage" + // TODO: remove hardcoded paths + args = fmt.Sprintf("--tlsverify --tlscacert=/etc/docker/ca.pem --tlscert=/etc/docker/server.pem --tlskey=/etc/docker/server-key.pem -H %s", + host) + } else { + role = "join" + args = fmt.Sprintf("--addr %s", addr) + } + + args = fmt.Sprintf("%s %s", args, discovery) + + u, err := url.Parse(host) + if err != nil { + return err + } + + parts := strings.Split(u.Host, ":") + port := parts[1] + + cmd, err := d.GetSSHCommand(fmt.Sprintf("sudo docker pull %s", swarmDockerImage)) + if err != nil { + return err + } + if err := cmd.Run(); err != nil { + return err + } + + cmd, err = d.GetSSHCommand(fmt.Sprintf("sudo docker run -d -p %s:%s --restart=always --name swarm-agent -v /etc/docker:/etc/docker %s %s %s", + port, port, swarmDockerImage, role, args)) + if err != nil { + return err + } + if err := cmd.Run(); err != nil { + return err + } + // TODO: + // - configure swarm to start / autostart + // - configure node to join cluster + // - configure node to run with IP of machine and URL to Docker + return nil +} + func (h *Host) ConfigureAuth() error { d := h.Driver diff --git a/store.go b/store.go index 235ea4a247..51445e2274 100644 --- a/store.go +++ b/store.go @@ -68,6 +68,18 @@ func (s *Store) Create(name string, driverName string, flags drivers.DriverOptio return host, err } + if flags.Bool("swarm") { + log.Info("Configuring Swarm") + + discovery := flags.String("swarm-discovery") + master := flags.Bool("swarm-master") + swarmHost := flags.String("swarm-host") + addr := flags.String("swarm-addr") + if err := host.ConfigureSwarm(discovery, master, swarmHost, addr); err != nil { + log.Errorf("Error configuring Swarm: %s", err) + } + } + return host, nil }