docs/dockerclient/dockerclient.go

124 lines
2.7 KiB
Go

package main
import (
"fmt"
"github.com/codegangsta/cli"
"github.com/docker/libswarm/backends"
"github.com/docker/libswarm/beam"
"log"
"os"
"strings"
)
func main() {
app := cli.NewApp()
app.Name = "swarmd"
app.Usage = "Control a heterogenous distributed system with the Docker API"
app.Version = "0.0.1"
app.Flags = []cli.Flag{
cli.StringFlag{"backend", "debug", "load a backend"},
}
app.Action = cmdDaemon
app.Run(os.Args)
}
func cmdDaemon(c *cli.Context) {
app := beam.NewServer()
app.OnLog(beam.Handler(func(msg *beam.Message) error {
log.Printf("%s\n", strings.Join(msg.Args, " "))
return nil
}))
app.OnError(beam.Handler(func(msg *beam.Message) error {
Fatalf("Fatal: %v", strings.Join(msg.Args[:1], ""))
return nil
}))
backend := beam.Object{backends.Forward()}
dockerHost := os.Getenv("DOCKER_HOST")
if dockerHost == "" {
dockerHost = "unix:///var/run/docker.sock"
}
log.Printf("---> Spawning\n")
instance, err := backend.Spawn(dockerHost)
if err != nil {
Fatalf("spawn: %v\n", err)
}
log.Printf("---> Attaching\n")
instanceIn, instanceOut, err := instance.Attach("")
if err != nil {
Fatalf("attach: %v", err)
}
defer instanceOut.Close()
go beam.Copy(app, instanceIn)
log.Printf("---> Starting\n")
if err := instance.Start(); err != nil {
Fatalf("start: %v", err)
}
err = doCmd(instance, c.Args())
if err != nil {
Fatalf("%v", err)
}
}
func doCmd(instance *beam.Object, args []string) error {
if len(args) == 0 {
return fmt.Errorf("no command supplied")
}
log.Printf("---> %s\n", args[0])
if args[0] == "ps" {
if len(args) != 1 {
return fmt.Errorf("usage: ps")
}
names, err := instance.Ls()
if err != nil {
return err
}
fmt.Println(strings.Join(names, "\n"))
return nil
}
if args[0] == "run" {
if len(args) < 3 {
return fmt.Errorf("usage: run IMAGE COMMAND...")
}
container, err := instance.Spawn(args[1:]...)
if err != nil {
return fmt.Errorf("spawn: %v", err)
}
logs, _, err := container.Attach("")
if err != nil {
return fmt.Errorf("attach: %v", err)
}
if err = container.Start(); err != nil {
return fmt.Errorf("start: %v", err)
}
for {
msg, err := logs.Receive(beam.Ret)
if err != nil {
if err.Error() == "EOF" {
break
}
return fmt.Errorf("error reading from container: %v", err)
}
if msg.Verb != beam.Log {
return fmt.Errorf("unexpected message reading from container: %v", msg)
}
fmt.Print(msg.Args[0])
}
return nil
}
return fmt.Errorf("unrecognised command: %s", args[0])
}
func Fatalf(msg string, args ...interface{}) {
if !strings.HasSuffix(msg, "\n") {
msg = msg + "\n"
}
fmt.Fprintf(os.Stderr, msg, args...)
os.Exit(1)
}