func Task(f func(in libswarm.Receiver, out libswarm.Sender)) libswarm.Sender { var running bool var l sync.RWMutex inR, inW := libswarm.Pipe() outR, outW := libswarm.Pipe() obj := libswarm.NewServer() obj.OnVerb(libswarm.Attach, libswarm.Handler(func(msg *libswarm.Message) error { msg.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: inW}) fmt.Printf("copying task output from %#v to %#v\n", outR, msg.Ret) defer fmt.Printf("(DONE) copying task output from %#v to %#v\n", outR, msg.Ret) libswarm.Copy(msg.Ret, outR) return nil })) obj.OnVerb(libswarm.Start, libswarm.Handler(func(msg *libswarm.Message) error { l.RLock() r := running l.RUnlock() if r { return fmt.Errorf("already running") } l.Lock() go f(inR, outW) running = true l.Unlock() msg.Ret.Send(&libswarm.Message{Verb: libswarm.Ack}) return nil })) return obj }
func NewTree() *Tree { t := &Tree{ Server: libswarm.NewServer(), children: make(map[string]libswarm.Sender), } t.OnVerb(libswarm.Attach, libswarm.Handler(func(msg *libswarm.Message) error { if len(msg.Args) == 0 || msg.Args[0] == "" { msg.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: t}) return nil } if child, exists := t.children[msg.Args[0]]; exists { msg.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: child}) return nil } libswarm.AsClient(msg.Ret).Error("not found") return nil })) t.OnVerb(libswarm.Ls, libswarm.Handler(func(msg *libswarm.Message) error { names := make([]string, 0, len(t.children)) for name := range t.children { names = append(names, name) } sort.Strings(names) libswarm.AsClient(msg.Ret).Set(names...) return nil })) return t }
func Tutum() libswarm.Sender { backend := libswarm.NewServer() backend.OnVerb(libswarm.Spawn, libswarm.Handler(func(ctx *libswarm.Message) error { if len(ctx.Args) == 2 { tutum.User = ctx.Args[0] tutum.ApiKey = ctx.Args[1] } if !tutum.IsAuthenticated() { return fmt.Errorf("You need to provide your Tutum credentials in ~/.tutum or environment variables TUTUM_USER and TUTUM_APIKEY") } tutumDockerConnector, err := newConnector(tutumConnectorHost, tutumConnectorVersion) if err != nil { return fmt.Errorf("%v", err) } t := &tutumBackend{ tutumDockerConnector: tutumDockerConnector, Server: libswarm.NewServer(), } t.Server.OnVerb(libswarm.Attach, libswarm.Handler(t.attach)) t.Server.OnVerb(libswarm.Start, libswarm.Handler(t.ack)) t.Server.OnVerb(libswarm.Ls, libswarm.Handler(t.ls)) t.Server.OnVerb(libswarm.Spawn, libswarm.Handler(t.spawn)) _, err = ctx.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: t.Server}) return err })) return backend }
func (t *tutumBackend) newContainer(id string) libswarm.Sender { c := &tutumContainer{tutumBackend: t, id: id} instance := libswarm.NewServer() instance.OnVerb(libswarm.Get, libswarm.Handler(c.get)) instance.OnVerb(libswarm.Start, libswarm.Handler(c.start)) instance.OnVerb(libswarm.Stop, libswarm.Handler(c.stop)) return instance }
func Ec2() libswarm.Sender { backend := libswarm.NewServer() backend.OnVerb(libswarm.Spawn, libswarm.Handler(func(ctx *libswarm.Message) error { var config, err = newConfig(ctx.Args) if err != nil { return err } ec2Conn, err := awsInit(config) if err != nil { return err } client := &ec2Client{config, ec2Conn, libswarm.NewServer(), nil, nil, nil} client.Server.OnVerb(libswarm.Spawn, libswarm.Handler(client.spawn)) client.Server.OnVerb(libswarm.Start, libswarm.Handler(client.start)) client.Server.OnVerb(libswarm.Stop, libswarm.Handler(client.stop)) client.Server.OnVerb(libswarm.Attach, libswarm.Handler(client.attach)) client.Server.OnVerb(libswarm.Ls, libswarm.Handler(client.ls)) client.Server.OnVerb(libswarm.Get, libswarm.Handler(client.get)) signalHandler(client) _, err = ctx.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: client.Server}) return err })) return backend }
// The Debug service is an example of intercepting messages between a receiver and a sender. // The service also exposes messages passing through it for debug purposes. func Debug() libswarm.Sender { dbgInstance := &debug{ service: libswarm.NewServer(), } sender := libswarm.NewServer() sender.OnVerb(libswarm.Spawn, libswarm.Handler(dbgInstance.spawn)) return sender }
func Simulator() libswarm.Sender { s := libswarm.NewServer() s.OnVerb(libswarm.Spawn, libswarm.Handler(func(ctx *libswarm.Message) error { containers := ctx.Args instance := utils.Task(func(in libswarm.Receiver, out libswarm.Sender) { libswarm.AsClient(out).Log("[simulator] starting\n") s := libswarm.NewServer() s.OnVerb(libswarm.Ls, libswarm.Handler(func(msg *libswarm.Message) error { libswarm.AsClient(out).Log("[simulator] generating fake list of objects...\n") libswarm.AsClient(msg.Ret).Set(containers...) return nil })) libswarm.Copy(s, in) }) ctx.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: instance}) return nil })) return s }
func Shipyard() libswarm.Sender { backend := libswarm.NewServer() backend.OnVerb(libswarm.Spawn, libswarm.Handler(func(ctx *libswarm.Message) error { if len(ctx.Args) != 3 { return fmt.Errorf("Shipyard: Usage <shipyard URL> <user> <pass>") } c := &shipyard{url: ctx.Args[0], user: ctx.Args[1], pass: ctx.Args[2]} c.Server = libswarm.NewServer() c.Server.OnVerb(libswarm.Attach, libswarm.Handler(c.attach)) c.Server.OnVerb(libswarm.Start, libswarm.Handler(c.start)) c.Server.OnVerb(libswarm.Ls, libswarm.Handler(c.containers)) c.OnVerb(libswarm.Get, libswarm.Handler(c.containerInspect)) _, err := ctx.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: c.Server}) return err })) return backend }
func DockerServer() libswarm.Sender { backend := libswarm.NewServer() backend.OnVerb(libswarm.Spawn, libswarm.Handler(func(ctx *libswarm.Message) error { instance := utils.Task(func(in libswarm.Receiver, out libswarm.Sender) { url := "tcp://localhost:4243" if len(ctx.Args) > 0 { url = ctx.Args[0] } err := listenAndServe(url, out) if err != nil { fmt.Printf("listenAndServe: %v", err) } }) _, err := ctx.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: instance}) return err })) return backend }
func FakeClient() libswarm.Sender { backend := libswarm.NewServer() backend.OnVerb(libswarm.Spawn, libswarm.Handler(func(ctx *libswarm.Message) error { // Instantiate a new fakeclient instance instance := utils.Task(func(in libswarm.Receiver, out libswarm.Sender) { fmt.Printf("fake client!\n") defer fmt.Printf("end of fake client!\n") o := libswarm.AsClient(out) o.Log("fake client starting") defer o.Log("fake client terminating") for { time.Sleep(1 * time.Second) o.Log("fake client heartbeat!") } }) _, err := ctx.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: instance}) return err })) return backend }
// Spawn will return a new instance as the Ret channel of the message sent back func (dbg *debug) spawn(msg *libswarm.Message) (err error) { // By sending back a task, libswarm will run the function with the in and out arguments // set to the services present before and after this one in the pipeline. instance := utils.Task(func(in libswarm.Receiver, out libswarm.Sender) { // Setup our channels dbg.out = out // Set up the debug interceptor dbg.service.Catchall(libswarm.Handler(dbg.catchall)) // Copy everything from the receiver to our service. By copying like this in the task // we can use the catchall handler instead of handling the message here. libswarm.Copy(dbg.service, in) }) // Inform the system of our new instance msg.Ret.Send(&libswarm.Message{ Verb: libswarm.Ack, Ret: instance, }) return }
func Exec() libswarm.Sender { e := libswarm.NewServer() e.OnVerb(libswarm.Spawn, libswarm.Handler(func(msg *libswarm.Message) error { if len(msg.Args) < 1 { return fmt.Errorf("usage: SPAWN exec|... <config>") } if msg.Args[0] != "exec" { return fmt.Errorf("invalid command: %s", msg.Args[0]) } var config struct { Path string Args []string } if err := json.Unmarshal([]byte(msg.Args[1]), &config); err != nil { config.Path = msg.Args[1] config.Args = msg.Args[2:] } cmd := &command{ Cmd: exec.Command(config.Path, config.Args...), Server: libswarm.NewServer(), } cmd.OnVerb(libswarm.Attach, libswarm.Handler(func(msg *libswarm.Message) error { stdout, err := cmd.StdoutPipe() if err != nil { return err } stdin, err := cmd.StdinPipe() if err != nil { return err } inR, inW := libswarm.Pipe() if _, err := msg.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: inW}); err != nil { return err } out := libswarm.AsClient(msg.Ret) go func() { defer stdin.Close() for { msg, err := inR.Receive(0) if err != nil { return } if msg.Verb == libswarm.Log && len(msg.Args) > 0 { fmt.Fprintf(stdin, "%s\n", strings.TrimRight(msg.Args[0], "\r\n")) } } }() cmd.tasks.Add(1) go func() { defer cmd.tasks.Done() scanner := bufio.NewScanner(stdout) for scanner.Scan() { if scanner.Err() != io.EOF && scanner.Err() != nil { return } if err := out.Log(scanner.Text()); err != nil { out.Error("%v", err) return } } }() cmd.tasks.Wait() return nil })) cmd.OnVerb(libswarm.Start, libswarm.Handler(func(msg *libswarm.Message) error { cmd.tasks.Add(1) if err := cmd.Cmd.Start(); err != nil { return err } go func() { defer cmd.tasks.Done() if err := cmd.Cmd.Wait(); err != nil { libswarm.AsClient(msg.Ret).Log("%s exited status=%v", cmd.Cmd.Path, err) } }() msg.Ret.Send(&libswarm.Message{Verb: libswarm.Ack}) return nil })) if _, err := msg.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: cmd}); err != nil { return err } return nil })) return e }