Merge pull request #100 from aanand/port-to-libchan-pt2

This commit is contained in:
Solomon Hykes 2014-07-01 19:00:26 -07:00
commit 379c579493
25 changed files with 358 additions and 346 deletions

View File

@ -1,7 +1,7 @@
package backends package backends
import ( import (
"github.com/docker/libswarm/beam" "github.com/docker/libswarm"
"github.com/flynn/go-shlex" "github.com/flynn/go-shlex"
"fmt" "fmt"
@ -9,11 +9,11 @@ import (
"sync" "sync"
) )
func Aggregate() beam.Sender { func Aggregate() libswarm.Sender {
backend := beam.NewServer() backend := libswarm.NewServer()
backend.OnSpawn(func(cmd ...string) (beam.Sender, error) { backend.OnSpawn(func(cmd ...string) (libswarm.Sender, error) {
allBackends := New() allBackends := New()
instance := beam.NewServer() instance := libswarm.NewServer()
a, err := newAggregator(allBackends, instance, cmd) a, err := newAggregator(allBackends, instance, cmd)
if err != nil { if err != nil {
@ -30,11 +30,11 @@ func Aggregate() beam.Sender {
} }
type aggregator struct { type aggregator struct {
backends []*beam.Object backends []*libswarm.Client
server *beam.Server server *libswarm.Server
} }
func newAggregator(allBackends *beam.Object, server *beam.Server, args []string) (*aggregator, error) { func newAggregator(allBackends *libswarm.Client, server *libswarm.Server, args []string) (*aggregator, error) {
a := &aggregator{server: server} a := &aggregator{server: server}
for _, argString := range args { for _, argString := range args {
@ -60,13 +60,13 @@ func newAggregator(allBackends *beam.Object, server *beam.Server, args []string)
return a, nil return a, nil
} }
func (a *aggregator) attach(name string, ret beam.Sender) error { func (a *aggregator) attach(name string, ret libswarm.Sender) error {
if name != "" { if name != "" {
// TODO: implement this? // TODO: implement this?
return fmt.Errorf("attaching to a child is not implemented") return fmt.Errorf("attaching to a child is not implemented")
} }
if _, err := ret.Send(&beam.Message{Verb: beam.Ack, Ret: a.server}); err != nil { if _, err := ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: a.server}); err != nil {
return err return err
} }
@ -80,7 +80,7 @@ func (a *aggregator) attach(name string, ret beam.Sender) error {
copies.Add(1) copies.Add(1)
go func() { go func() {
log.Printf("copying output from %#v\n", b) log.Printf("copying output from %#v\n", b)
beam.Copy(ret, r) libswarm.Copy(ret, r)
log.Printf("finished output from %#v\n", b) log.Printf("finished output from %#v\n", b)
copies.Done() copies.Done()
}() }()

View File

@ -1,8 +1,9 @@
package backends package backends
import ( import (
"github.com/docker/libswarm/beam" "github.com/docker/libswarm"
"github.com/docker/libswarm/debug" "github.com/docker/libswarm/debug"
"github.com/docker/libswarm/utils"
) )
// New returns a new engine, with all backends // New returns a new engine, with all backends
@ -11,8 +12,8 @@ import (
// engine, named after the desired backend. // engine, named after the desired backend.
// //
// Example: `New().Job("debug").Run()` // Example: `New().Job("debug").Run()`
func New() *beam.Object { func New() *libswarm.Client {
backends := beam.NewTree() backends := utils.NewTree()
backends.Bind("simulator", Simulator()) backends.Bind("simulator", Simulator())
backends.Bind("debug", debug.Debug()) backends.Bind("debug", debug.Debug())
backends.Bind("fakeclient", FakeClient()) backends.Bind("fakeclient", FakeClient())
@ -24,5 +25,5 @@ func New() *beam.Object {
backends.Bind("shipyard", Shipyard()) backends.Bind("shipyard", Shipyard())
backends.Bind("ec2", Ec2()) backends.Bind("ec2", Ec2())
backends.Bind("tutum", Tutum()) backends.Bind("tutum", Tutum())
return beam.Obj(backends) return libswarm.AsClient(backends)
} }

View File

@ -4,9 +4,10 @@ import (
"crypto/tls" "crypto/tls"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/docker/libswarm/beam" "github.com/docker/libswarm"
"github.com/docker/libswarm/utils"
"github.com/dotcloud/docker/engine" "github.com/dotcloud/docker/engine"
"github.com/dotcloud/docker/utils" dockerutils "github.com/dotcloud/docker/utils"
"io" "io"
"io/ioutil" "io/ioutil"
"net" "net"
@ -22,16 +23,16 @@ type DockerClientConfig struct {
TLSClientConfig *tls.Config TLSClientConfig *tls.Config
} }
func DockerClient() beam.Sender { func DockerClient() libswarm.Sender {
return DockerClientWithConfig(&DockerClientConfig{ return DockerClientWithConfig(&DockerClientConfig{
Scheme: "http", Scheme: "http",
URLHost: "dummy.host", URLHost: "dummy.host",
}) })
} }
func DockerClientWithConfig(config *DockerClientConfig) beam.Sender { func DockerClientWithConfig(config *DockerClientConfig) libswarm.Sender {
backend := beam.NewServer() backend := libswarm.NewServer()
backend.OnSpawn(func(cmd ...string) (beam.Sender, error) { backend.OnSpawn(func(cmd ...string) (libswarm.Sender, error) {
if len(cmd) != 1 { if len(cmd) != 1 {
return nil, fmt.Errorf("dockerclient: spawn takes exactly 1 argument, got %d", len(cmd)) return nil, fmt.Errorf("dockerclient: spawn takes exactly 1 argument, got %d", len(cmd))
} }
@ -42,7 +43,7 @@ func DockerClientWithConfig(config *DockerClientConfig) beam.Sender {
client.setURL(cmd[0]) client.setURL(cmd[0])
b := &dockerClientBackend{ b := &dockerClientBackend{
client: client, client: client,
Server: beam.NewServer(), Server: libswarm.NewServer(),
} }
b.Server.OnAttach(b.attach) b.Server.OnAttach(b.attach)
b.Server.OnStart(b.start) b.Server.OnStart(b.start)
@ -55,12 +56,12 @@ func DockerClientWithConfig(config *DockerClientConfig) beam.Sender {
type dockerClientBackend struct { type dockerClientBackend struct {
client *client client *client
*beam.Server *libswarm.Server
} }
func (b *dockerClientBackend) attach(name string, ret beam.Sender) error { func (b *dockerClientBackend) attach(name string, ret libswarm.Sender) error {
if name == "" { if name == "" {
ret.Send(&beam.Message{Verb: beam.Ack, Ret: b.Server}) ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: b.Server})
<-make(chan struct{}) <-make(chan struct{})
} else { } else {
path := fmt.Sprintf("/containers/%s/json", name) path := fmt.Sprintf("/containers/%s/json", name)
@ -76,7 +77,7 @@ func (b *dockerClientBackend) attach(name string, ret beam.Sender) error {
return fmt.Errorf("%s", respBody) return fmt.Errorf("%s", respBody)
} }
c := b.newContainer(name) c := b.newContainer(name)
ret.Send(&beam.Message{Verb: beam.Ack, Ret: c}) ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: c})
} }
return nil return nil
} }
@ -106,7 +107,7 @@ func (b *dockerClientBackend) ls() ([]string, error) {
return names, nil return names, nil
} }
func (b *dockerClientBackend) spawn(cmd ...string) (beam.Sender, error) { func (b *dockerClientBackend) spawn(cmd ...string) (libswarm.Sender, error) {
if len(cmd) != 1 { if len(cmd) != 1 {
return nil, fmt.Errorf("dockerclient: spawn takes exactly 1 argument, got %d", len(cmd)) return nil, fmt.Errorf("dockerclient: spawn takes exactly 1 argument, got %d", len(cmd))
} }
@ -128,9 +129,9 @@ func (b *dockerClientBackend) spawn(cmd ...string) (beam.Sender, error) {
return b.newContainer(respJson.Id), nil return b.newContainer(respJson.Id), nil
} }
func (b *dockerClientBackend) newContainer(id string) beam.Sender { func (b *dockerClientBackend) newContainer(id string) libswarm.Sender {
c := &container{backend: b, id: id} c := &container{backend: b, id: id}
instance := beam.NewServer() instance := libswarm.NewServer()
instance.OnAttach(c.attach) instance.OnAttach(c.attach)
instance.OnStart(c.start) instance.OnStart(c.start)
instance.OnStop(c.stop) instance.OnStop(c.stop)
@ -143,8 +144,8 @@ type container struct {
id string id string
} }
func (c *container) attach(name string, ret beam.Sender) error { func (c *container) attach(name string, ret libswarm.Sender) error {
if _, err := ret.Send(&beam.Message{Verb: beam.Ack}); err != nil { if _, err := ret.Send(&libswarm.Message{Verb: libswarm.Ack}); err != nil {
return err return err
} }
@ -152,8 +153,8 @@ func (c *container) attach(name string, ret beam.Sender) error {
stdoutR, stdoutW := io.Pipe() stdoutR, stdoutW := io.Pipe()
stderrR, stderrW := io.Pipe() stderrR, stderrW := io.Pipe()
go beam.EncodeStream(ret, stdoutR, "stdout") go utils.EncodeStream(ret, stdoutR, "stdout")
go beam.EncodeStream(ret, stderrR, "stderr") go utils.EncodeStream(ret, stderrR, "stderr")
c.backend.client.hijack("POST", path, nil, stdoutW, stderrW) c.backend.client.hijack("POST", path, nil, stdoutW, stderrW)
return nil return nil
@ -270,40 +271,40 @@ func (c *client) hijack(method, path string, in io.ReadCloser, stdout, stderr io
rwc, br := clientconn.Hijack() rwc, br := clientconn.Hijack()
defer rwc.Close() defer rwc.Close()
receiveStdout := utils.Go(func() (err error) { receiveStdout := dockerutils.Go(func() (err error) {
defer func() { defer func() {
if in != nil { if in != nil {
in.Close() in.Close()
} }
}() }()
_, err = utils.StdCopy(stdout, stderr, br) _, err = dockerutils.StdCopy(stdout, stderr, br)
utils.Debugf("[hijack] End of stdout") dockerutils.Debugf("[hijack] End of stdout")
return err return err
}) })
sendStdin := utils.Go(func() error { sendStdin := dockerutils.Go(func() error {
if in != nil { if in != nil {
io.Copy(rwc, in) io.Copy(rwc, in)
utils.Debugf("[hijack] End of stdin") dockerutils.Debugf("[hijack] End of stdin")
} }
if tcpc, ok := rwc.(*net.TCPConn); ok { if tcpc, ok := rwc.(*net.TCPConn); ok {
if err := tcpc.CloseWrite(); err != nil { if err := tcpc.CloseWrite(); err != nil {
utils.Debugf("Couldn't send EOF: %s", err) dockerutils.Debugf("Couldn't send EOF: %s", err)
} }
} else if unixc, ok := rwc.(*net.UnixConn); ok { } else if unixc, ok := rwc.(*net.UnixConn); ok {
if err := unixc.CloseWrite(); err != nil { if err := unixc.CloseWrite(); err != nil {
utils.Debugf("Couldn't send EOF: %s", err) dockerutils.Debugf("Couldn't send EOF: %s", err)
} }
} }
// Discard errors due to pipe interruption // Discard errors due to pipe interruption
return nil return nil
}) })
if err := <-receiveStdout; err != nil { if err := <-receiveStdout; err != nil {
utils.Debugf("Error receiveStdout: %s", err) dockerutils.Debugf("Error receiveStdout: %s", err)
return err return err
} }
if err := <-sendStdin; err != nil { if err := <-sendStdin; err != nil {
utils.Debugf("Error sendStdin: %s", err) dockerutils.Debugf("Error sendStdin: %s", err)
return err return err
} }
return nil return nil

View File

@ -1,7 +1,7 @@
package backends package backends
import ( import (
"github.com/docker/libswarm/beam" "github.com/docker/libswarm"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
@ -240,21 +240,21 @@ func (s *stubServer) AllSummaries() []string {
return summaries return summaries
} }
func instance(t *testing.T, server *stubServer) *beam.Object { func instance(t *testing.T, server *stubServer) *libswarm.Client {
url := "tcp://localhost:4243" url := "tcp://localhost:4243"
if server != nil { if server != nil {
url = strings.Replace(server.URL, "http://", "tcp://", 1) url = strings.Replace(server.URL, "http://", "tcp://", 1)
} }
backend := DockerClient() backend := DockerClient()
instance, err := beam.Obj(backend).Spawn(url) instance, err := libswarm.AsClient(backend).Spawn(url)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
return instance return instance
} }
func child(t *testing.T, server *stubServer, i *beam.Object, name string) *beam.Object { func child(t *testing.T, server *stubServer, i *libswarm.Client, name string) *libswarm.Client {
_, child, err := i.Attach(name) _, child, err := i.Attach(name)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)

View File

@ -3,11 +3,12 @@ package backends
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/docker/libswarm/beam" "github.com/docker/libswarm"
"github.com/docker/libswarm/utils"
"github.com/dotcloud/docker/api" "github.com/dotcloud/docker/api"
"github.com/dotcloud/docker/pkg/version" "github.com/dotcloud/docker/pkg/version"
dockerContainerConfig "github.com/dotcloud/docker/runconfig" dockerContainerConfig "github.com/dotcloud/docker/runconfig"
"github.com/dotcloud/docker/utils" dockerutils "github.com/dotcloud/docker/utils"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"io" "io"
"io/ioutil" "io/ioutil"
@ -20,10 +21,10 @@ import (
"time" "time"
) )
func DockerServer() beam.Sender { func DockerServer() libswarm.Sender {
backend := beam.NewServer() backend := libswarm.NewServer()
backend.OnVerb(beam.Spawn, beam.Handler(func(ctx *beam.Message) error { backend.OnVerb(libswarm.Spawn, libswarm.Handler(func(ctx *libswarm.Message) error {
instance := beam.Task(func(in beam.Receiver, out beam.Sender) { instance := utils.Task(func(in libswarm.Receiver, out libswarm.Sender) {
url := "tcp://localhost:4243" url := "tcp://localhost:4243"
if len(ctx.Args) > 0 { if len(ctx.Args) > 0 {
url = ctx.Args[0] url = ctx.Args[0]
@ -33,15 +34,15 @@ func DockerServer() beam.Sender {
fmt.Printf("listenAndServe: %v", err) fmt.Printf("listenAndServe: %v", err)
} }
}) })
_, err := ctx.Ret.Send(&beam.Message{Verb: beam.Ack, Ret: instance}) _, err := ctx.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: instance})
return err return err
})) }))
return backend return backend
} }
type HttpApiFunc func(out beam.Sender, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error type HttpApiFunc func(out libswarm.Sender, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error
func listenAndServe(urlStr string, out beam.Sender) error { func listenAndServe(urlStr string, out libswarm.Sender) error {
fmt.Println("Starting Docker server...") fmt.Println("Starting Docker server...")
r, err := createRouter(out) r, err := createRouter(out)
if err != nil { if err != nil {
@ -69,7 +70,7 @@ func listenAndServe(urlStr string, out beam.Sender) error {
return httpSrv.Serve(l) return httpSrv.Serve(l)
} }
func ping(out beam.Sender, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { func ping(out libswarm.Sender, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
_, err := w.Write([]byte{'O', 'K'}) _, err := w.Write([]byte{'O', 'K'})
return err return err
} }
@ -107,14 +108,14 @@ type containerJson struct {
VolumesRW map[string]bool VolumesRW map[string]bool
} }
func getContainerJson(out beam.Sender, containerID string) (containerJson, error) { func getContainerJson(out libswarm.Sender, containerID string) (containerJson, error) {
o := beam.Obj(out) o := libswarm.AsClient(out)
_, containerOut, err := o.Attach(containerID) _, containerOut, err := o.Attach(containerID)
if err != nil { if err != nil {
return containerJson{}, err return containerJson{}, err
} }
container := beam.Obj(containerOut) container := libswarm.AsClient(containerOut)
responseJson, err := container.Get() responseJson, err := container.Get()
if err != nil { if err != nil {
return containerJson{}, err return containerJson{}, err
@ -128,7 +129,7 @@ func getContainerJson(out beam.Sender, containerID string) (containerJson, error
return response, nil return response, nil
} }
func getContainerInfo(out beam.Sender, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { func getContainerInfo(out libswarm.Sender, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
container, err := getContainerJson(out, vars["name"]) container, err := getContainerJson(out, vars["name"])
if err != nil { if err != nil {
return err return err
@ -136,12 +137,12 @@ func getContainerInfo(out beam.Sender, version version.Version, w http.ResponseW
return writeJSON(w, http.StatusOK, container) return writeJSON(w, http.StatusOK, container)
} }
func getContainersJSON(out beam.Sender, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { func getContainersJSON(out libswarm.Sender, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if err := r.ParseForm(); err != nil { if err := r.ParseForm(); err != nil {
return err return err
} }
o := beam.Obj(out) o := libswarm.AsClient(out)
names, err := o.Ls() names, err := o.Ls()
if err != nil { if err != nil {
return err return err
@ -214,7 +215,7 @@ func getContainersJSON(out beam.Sender, version version.Version, w http.Response
return writeJSON(w, http.StatusOK, responses) return writeJSON(w, http.StatusOK, responses)
} }
func postContainersCreate(out beam.Sender, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { func postContainersCreate(out libswarm.Sender, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if err := r.ParseForm(); err != nil { if err := r.ParseForm(); err != nil {
return nil return nil
} }
@ -224,7 +225,7 @@ func postContainersCreate(out beam.Sender, version version.Version, w http.Respo
return err return err
} }
container, err := beam.Obj(out).Spawn(string(body)) container, err := libswarm.AsClient(out).Spawn(string(body))
if err != nil { if err != nil {
return err return err
} }
@ -241,7 +242,7 @@ func postContainersCreate(out beam.Sender, version version.Version, w http.Respo
return writeJSON(w, http.StatusCreated, response) return writeJSON(w, http.StatusCreated, response)
} }
func postContainersStart(out beam.Sender, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { func postContainersStart(out libswarm.Sender, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if vars == nil { if vars == nil {
return fmt.Errorf("Missing parameter") return fmt.Errorf("Missing parameter")
} }
@ -249,8 +250,8 @@ func postContainersStart(out beam.Sender, version version.Version, w http.Respon
// TODO: r.Body // TODO: r.Body
name := vars["name"] name := vars["name"]
_, containerOut, err := beam.Obj(out).Attach(name) _, containerOut, err := libswarm.AsClient(out).Attach(name)
container := beam.Obj(containerOut) container := libswarm.AsClient(containerOut)
if err != nil { if err != nil {
return err return err
} }
@ -262,14 +263,14 @@ func postContainersStart(out beam.Sender, version version.Version, w http.Respon
return nil return nil
} }
func postContainersStop(out beam.Sender, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { func postContainersStop(out libswarm.Sender, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if vars == nil { if vars == nil {
return fmt.Errorf("Missing parameter") return fmt.Errorf("Missing parameter")
} }
name := vars["name"] name := vars["name"]
_, containerOut, err := beam.Obj(out).Attach(name) _, containerOut, err := libswarm.AsClient(out).Attach(name)
container := beam.Obj(containerOut) container := libswarm.AsClient(containerOut)
if err != nil { if err != nil {
return err return err
} }
@ -291,7 +292,7 @@ func hijackServer(w http.ResponseWriter) (io.ReadCloser, io.Writer, error) {
return conn, conn, nil return conn, conn, nil
} }
func postContainersAttach(out beam.Sender, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { func postContainersAttach(out libswarm.Sender, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if err := r.ParseForm(); err != nil { if err := r.ParseForm(); err != nil {
return err return err
} }
@ -321,20 +322,20 @@ func postContainersAttach(out beam.Sender, version version.Version, w http.Respo
fmt.Fprintf(outStream, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n") fmt.Fprintf(outStream, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n")
// TODO: if a TTY, then no multiplexing is done // TODO: if a TTY, then no multiplexing is done
errStream := utils.NewStdWriter(outStream, utils.Stderr) errStream := dockerutils.NewStdWriter(outStream, dockerutils.Stderr)
outStream = utils.NewStdWriter(outStream, utils.Stdout) outStream = dockerutils.NewStdWriter(outStream, dockerutils.Stdout)
_, containerOut, err := beam.Obj(out).Attach(vars["name"]) _, containerOut, err := libswarm.AsClient(out).Attach(vars["name"])
if err != nil { if err != nil {
return err return err
} }
container := beam.Obj(containerOut) container := libswarm.AsClient(containerOut)
containerR, _, err := container.Attach("") containerR, _, err := container.Attach("")
var tasks sync.WaitGroup var tasks sync.WaitGroup
go func() { go func() {
defer tasks.Done() defer tasks.Done()
err := beam.DecodeStream(outStream, containerR, "stdout") err := utils.DecodeStream(outStream, containerR, "stdout")
if err != nil { if err != nil {
fmt.Printf("decodestream: %v\n", err) fmt.Printf("decodestream: %v\n", err)
} }
@ -342,7 +343,7 @@ func postContainersAttach(out beam.Sender, version version.Version, w http.Respo
tasks.Add(1) tasks.Add(1)
go func() { go func() {
defer tasks.Done() defer tasks.Done()
err := beam.DecodeStream(errStream, containerR, "stderr") err := utils.DecodeStream(errStream, containerR, "stderr")
if err != nil { if err != nil {
fmt.Printf("decodestream: %v\n", err) fmt.Printf("decodestream: %v\n", err)
} }
@ -353,7 +354,7 @@ func postContainersAttach(out beam.Sender, version version.Version, w http.Respo
return nil return nil
} }
func postContainersWait(out beam.Sender, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { func postContainersWait(out libswarm.Sender, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if vars == nil { if vars == nil {
return fmt.Errorf("Missing parameter") return fmt.Errorf("Missing parameter")
} }
@ -365,7 +366,7 @@ func postContainersWait(out beam.Sender, version version.Version, w http.Respons
}) })
} }
func createRouter(out beam.Sender) (*mux.Router, error) { func createRouter(out libswarm.Sender) (*mux.Router, error) {
r := mux.NewRouter() r := mux.NewRouter()
m := map[string]map[string]HttpApiFunc{ m := map[string]map[string]HttpApiFunc{
"GET": { "GET": {
@ -405,7 +406,7 @@ func createRouter(out beam.Sender) (*mux.Router, error) {
return r, nil return r, nil
} }
func makeHttpHandler(out beam.Sender, localMethod string, localRoute string, handlerFunc HttpApiFunc, dockerVersion version.Version) http.HandlerFunc { func makeHttpHandler(out libswarm.Sender, localMethod string, localRoute string, handlerFunc HttpApiFunc, dockerVersion version.Version) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
// log the request // log the request
fmt.Printf("Calling %s %s\n", localMethod, localRoute) fmt.Printf("Calling %s %s\n", localMethod, localRoute)

View File

@ -3,7 +3,7 @@ package backends
import ( import (
"errors" "errors"
"fmt" "fmt"
"github.com/docker/libswarm/beam" "github.com/docker/libswarm"
"net" "net"
"net/http" "net/http"
"os" "os"
@ -36,22 +36,22 @@ type ec2Config struct {
type ec2Client struct { type ec2Client struct {
config *ec2Config config *ec2Config
ec2Conn *ec2.EC2 ec2Conn *ec2.EC2
Server *beam.Server Server *libswarm.Server
instance *ec2.Instance instance *ec2.Instance
sshTunnel *os.Process sshTunnel *os.Process
dockerInstance *beam.Object dockerInstance *libswarm.Client
} }
func (c *ec2Client) get(ctx *beam.Message) error { func (c *ec2Client) get(ctx *libswarm.Message) error {
output, err := c.dockerInstance.Get() output, err := c.dockerInstance.Get()
if err != nil { if err != nil {
return err return err
} }
ctx.Ret.Send(&beam.Message{Verb: beam.Set, Args: []string{output}}) ctx.Ret.Send(&libswarm.Message{Verb: libswarm.Set, Args: []string{output}})
return nil return nil
} }
func (c *ec2Client) start(ctx *beam.Message) error { func (c *ec2Client) start(ctx *libswarm.Message) error {
if instance, err := c.findInstance(); err != nil { if instance, err := c.findInstance(); err != nil {
return err return err
} else if instance != nil { } else if instance != nil {
@ -73,44 +73,44 @@ func (c *ec2Client) start(ctx *beam.Message) error {
c.waitForDockerDaemon() c.waitForDockerDaemon()
fmt.Printf("ec2 service up and running: region: %s zone: %s\n", fmt.Printf("ec2 service up and running: region: %s zone: %s\n",
c.config.region.Name, c.config.zone) c.config.region.Name, c.config.zone)
ctx.Ret.Send(&beam.Message{Verb: beam.Ack, Ret: c.Server}) ctx.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: c.Server})
return nil return nil
} }
func (c *ec2Client) spawn(ctx *beam.Message) error { func (c *ec2Client) spawn(ctx *libswarm.Message) error {
out, err := c.dockerInstance.Spawn(ctx.Args...) out, err := c.dockerInstance.Spawn(ctx.Args...)
if err != nil { if err != nil {
return err return err
} }
ctx.Ret.Send(&beam.Message{Verb: beam.Ack, Ret: out}) ctx.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: out})
return nil return nil
} }
func (c *ec2Client) ls(ctx *beam.Message) error { func (c *ec2Client) ls(ctx *libswarm.Message) error {
output, err := c.dockerInstance.Ls() output, err := c.dockerInstance.Ls()
if err != nil { if err != nil {
return err return err
} }
ctx.Ret.Send(&beam.Message{Verb: beam.Set, Args: output}) ctx.Ret.Send(&libswarm.Message{Verb: libswarm.Set, Args: output})
return nil return nil
} }
func (c *ec2Client) stop(ctx *beam.Message) error { func (c *ec2Client) stop(ctx *libswarm.Message) error {
c.dockerInstance.Stop() c.dockerInstance.Stop()
return nil return nil
} }
func (c *ec2Client) attach(ctx *beam.Message) error { func (c *ec2Client) attach(ctx *libswarm.Message) error {
if ctx.Args[0] == "" { if ctx.Args[0] == "" {
ctx.Ret.Send(&beam.Message{Verb: beam.Ack, Ret: c.Server}) ctx.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: c.Server})
<-make(chan struct{}) <-make(chan struct{})
} else { } else {
_, out, err := c.dockerInstance.Attach(ctx.Args[0]) _, out, err := c.dockerInstance.Attach(ctx.Args[0])
if err != nil { if err != nil {
return err return err
} }
ctx.Ret.Send(&beam.Message{Verb: beam.Ack, Ret: out}) ctx.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: out})
} }
return nil return nil
@ -281,7 +281,7 @@ func (c *ec2Client) initDockerClientInstance(instance *ec2.Instance) error {
URLHost: "localhost", URLHost: "localhost",
}) })
dockerBackend := beam.Obj(dockerClient) dockerBackend := libswarm.AsClient(dockerClient)
url := fmt.Sprintf("tcp://localhost:%s", c.config.sshLocalPort) url := fmt.Sprintf("tcp://localhost:%s", c.config.sshLocalPort)
dockerInstance, err := dockerBackend.Spawn(url) dockerInstance, err := dockerBackend.Spawn(url)
c.dockerInstance = dockerInstance c.dockerInstance = dockerInstance
@ -341,9 +341,9 @@ func signalHandler(client *ec2Client) {
}() }()
} }
func Ec2() beam.Sender { func Ec2() libswarm.Sender {
backend := beam.NewServer() backend := libswarm.NewServer()
backend.OnVerb(beam.Spawn, beam.Handler(func(ctx *beam.Message) error { backend.OnVerb(libswarm.Spawn, libswarm.Handler(func(ctx *libswarm.Message) error {
var config, err = newConfig(ctx.Args) var config, err = newConfig(ctx.Args)
if err != nil { if err != nil {
@ -355,16 +355,16 @@ func Ec2() beam.Sender {
return err return err
} }
client := &ec2Client{config, ec2Conn, beam.NewServer(), nil, nil, nil} client := &ec2Client{config, ec2Conn, libswarm.NewServer(), nil, nil, nil}
client.Server.OnVerb(beam.Spawn, beam.Handler(client.spawn)) client.Server.OnVerb(libswarm.Spawn, libswarm.Handler(client.spawn))
client.Server.OnVerb(beam.Start, beam.Handler(client.start)) client.Server.OnVerb(libswarm.Start, libswarm.Handler(client.start))
client.Server.OnVerb(beam.Stop, beam.Handler(client.stop)) client.Server.OnVerb(libswarm.Stop, libswarm.Handler(client.stop))
client.Server.OnVerb(beam.Attach, beam.Handler(client.attach)) client.Server.OnVerb(libswarm.Attach, libswarm.Handler(client.attach))
client.Server.OnVerb(beam.Ls, beam.Handler(client.ls)) client.Server.OnVerb(libswarm.Ls, libswarm.Handler(client.ls))
client.Server.OnVerb(beam.Get, beam.Handler(client.get)) client.Server.OnVerb(libswarm.Get, libswarm.Handler(client.get))
signalHandler(client) signalHandler(client)
_, err = ctx.Ret.Send(&beam.Message{Verb: beam.Ack, Ret: client.Server}) _, err = ctx.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: client.Server})
return err return err
})) }))

View File

@ -9,12 +9,12 @@ import (
"strings" "strings"
"sync" "sync"
"github.com/docker/libswarm/beam" "github.com/docker/libswarm"
) )
func Exec() beam.Sender { func Exec() libswarm.Sender {
e := beam.NewServer() e := libswarm.NewServer()
e.OnVerb(beam.Spawn, beam.Handler(func(msg *beam.Message) error { e.OnVerb(libswarm.Spawn, libswarm.Handler(func(msg *libswarm.Message) error {
if len(msg.Args) < 1 { if len(msg.Args) < 1 {
return fmt.Errorf("usage: SPAWN exec|... <config>") return fmt.Errorf("usage: SPAWN exec|... <config>")
} }
@ -31,9 +31,9 @@ func Exec() beam.Sender {
} }
cmd := &command{ cmd := &command{
Cmd: exec.Command(config.Path, config.Args...), Cmd: exec.Command(config.Path, config.Args...),
Server: beam.NewServer(), Server: libswarm.NewServer(),
} }
cmd.OnVerb(beam.Attach, beam.Handler(func(msg *beam.Message) error { cmd.OnVerb(libswarm.Attach, libswarm.Handler(func(msg *libswarm.Message) error {
stdout, err := cmd.StdoutPipe() stdout, err := cmd.StdoutPipe()
if err != nil { if err != nil {
return err return err
@ -42,11 +42,11 @@ func Exec() beam.Sender {
if err != nil { if err != nil {
return err return err
} }
inR, inW := beam.Pipe() inR, inW := libswarm.Pipe()
if _, err := msg.Ret.Send(&beam.Message{Verb: beam.Ack, Ret: inW}); err != nil { if _, err := msg.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: inW}); err != nil {
return err return err
} }
out := beam.Obj(msg.Ret) out := libswarm.AsClient(msg.Ret)
go func() { go func() {
defer stdin.Close() defer stdin.Close()
for { for {
@ -54,7 +54,7 @@ func Exec() beam.Sender {
if err != nil { if err != nil {
return return
} }
if msg.Verb == beam.Log && len(msg.Args) > 0 { if msg.Verb == libswarm.Log && len(msg.Args) > 0 {
fmt.Fprintf(stdin, "%s\n", strings.TrimRight(msg.Args[0], "\r\n")) fmt.Fprintf(stdin, "%s\n", strings.TrimRight(msg.Args[0], "\r\n"))
} }
} }
@ -76,7 +76,7 @@ func Exec() beam.Sender {
cmd.tasks.Wait() cmd.tasks.Wait()
return nil return nil
})) }))
cmd.OnVerb(beam.Start, beam.Handler(func(msg *beam.Message) error { cmd.OnVerb(libswarm.Start, libswarm.Handler(func(msg *libswarm.Message) error {
cmd.tasks.Add(1) cmd.tasks.Add(1)
if err := cmd.Cmd.Start(); err != nil { if err := cmd.Cmd.Start(); err != nil {
return err return err
@ -84,13 +84,13 @@ func Exec() beam.Sender {
go func() { go func() {
defer cmd.tasks.Done() defer cmd.tasks.Done()
if err := cmd.Cmd.Wait(); err != nil { if err := cmd.Cmd.Wait(); err != nil {
beam.Obj(msg.Ret).Log("%s exited status=%v", cmd.Cmd.Path, err) libswarm.AsClient(msg.Ret).Log("%s exited status=%v", cmd.Cmd.Path, err)
} }
}() }()
msg.Ret.Send(&beam.Message{Verb: beam.Ack}) msg.Ret.Send(&libswarm.Message{Verb: libswarm.Ack})
return nil return nil
})) }))
if _, err := msg.Ret.Send(&beam.Message{Verb: beam.Ack, Ret: cmd}); err != nil { if _, err := msg.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: cmd}); err != nil {
return err return err
} }
return nil return nil
@ -100,6 +100,6 @@ func Exec() beam.Sender {
type command struct { type command struct {
*exec.Cmd *exec.Cmd
*beam.Server *libswarm.Server
tasks sync.WaitGroup tasks sync.WaitGroup
} }

View File

@ -4,17 +4,18 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/docker/libswarm/beam" "github.com/docker/libswarm"
"github.com/docker/libswarm/utils"
) )
func FakeClient() beam.Sender { func FakeClient() libswarm.Sender {
backend := beam.NewServer() backend := libswarm.NewServer()
backend.OnVerb(beam.Spawn, beam.Handler(func(ctx *beam.Message) error { backend.OnVerb(libswarm.Spawn, libswarm.Handler(func(ctx *libswarm.Message) error {
// Instantiate a new fakeclient instance // Instantiate a new fakeclient instance
instance := beam.Task(func(in beam.Receiver, out beam.Sender) { instance := utils.Task(func(in libswarm.Receiver, out libswarm.Sender) {
fmt.Printf("fake client!\n") fmt.Printf("fake client!\n")
defer fmt.Printf("end of fake client!\n") defer fmt.Printf("end of fake client!\n")
o := beam.Obj(out) o := libswarm.AsClient(out)
o.Log("fake client starting") o.Log("fake client starting")
defer o.Log("fake client terminating") defer o.Log("fake client terminating")
for { for {
@ -22,7 +23,7 @@ func FakeClient() beam.Sender {
o.Log("fake client heartbeat!") o.Log("fake client heartbeat!")
} }
}) })
_, err := ctx.Ret.Send(&beam.Message{Verb: beam.Ack, Ret: instance}) _, err := ctx.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: instance})
return err return err
})) }))
return backend return backend

View File

@ -1,7 +1,7 @@
package backends package backends
import ( import (
"github.com/docker/libswarm/beam" "github.com/docker/libswarm"
"github.com/orchardup/go-orchard/api" "github.com/orchardup/go-orchard/api"
"crypto/tls" "crypto/tls"
@ -11,9 +11,9 @@ import (
"os" "os"
) )
func Orchard() beam.Sender { func Orchard() libswarm.Sender {
backend := beam.NewServer() backend := libswarm.NewServer()
backend.OnSpawn(func(cmd ...string) (beam.Sender, error) { backend.OnSpawn(func(cmd ...string) (libswarm.Sender, error) {
if len(cmd) != 2 { if len(cmd) != 2 {
return nil, fmt.Errorf("orchard: spawn expects 2 arguments: API token and name of host") return nil, fmt.Errorf("orchard: spawn expects 2 arguments: API token and name of host")
} }
@ -40,7 +40,7 @@ func Orchard() beam.Sender {
URLHost: host.IPAddress, URLHost: host.IPAddress,
TLSClientConfig: tlsConfig, TLSClientConfig: tlsConfig,
}) })
forwardBackend := beam.Obj(backend) forwardBackend := libswarm.AsClient(backend)
forwardInstance, err := forwardBackend.Spawn(url) forwardInstance, err := forwardBackend.Spawn(url)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -3,7 +3,7 @@ package backends
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/docker/libswarm/beam" "github.com/docker/libswarm"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"net/url" "net/url"
@ -11,29 +11,29 @@ import (
"time" "time"
) )
func Shipyard() beam.Sender { func Shipyard() libswarm.Sender {
backend := beam.NewServer() backend := libswarm.NewServer()
backend.OnVerb(beam.Spawn, beam.Handler(func(ctx *beam.Message) error { backend.OnVerb(libswarm.Spawn, libswarm.Handler(func(ctx *libswarm.Message) error {
if len(ctx.Args) != 3 { if len(ctx.Args) != 3 {
return fmt.Errorf("Shipyard: Usage <shipyard URL> <user> <pass>") return fmt.Errorf("Shipyard: Usage <shipyard URL> <user> <pass>")
} }
c := &shipyard{url: ctx.Args[0], user: ctx.Args[1], pass: ctx.Args[2]} c := &shipyard{url: ctx.Args[0], user: ctx.Args[1], pass: ctx.Args[2]}
c.Server = beam.NewServer() c.Server = libswarm.NewServer()
c.Server.OnVerb(beam.Attach, beam.Handler(c.attach)) c.Server.OnVerb(libswarm.Attach, libswarm.Handler(c.attach))
c.Server.OnVerb(beam.Start, beam.Handler(c.start)) c.Server.OnVerb(libswarm.Start, libswarm.Handler(c.start))
c.Server.OnVerb(beam.Ls, beam.Handler(c.containers)) c.Server.OnVerb(libswarm.Ls, libswarm.Handler(c.containers))
c.OnVerb(beam.Get, beam.Handler(c.containerInspect)) c.OnVerb(libswarm.Get, libswarm.Handler(c.containerInspect))
_, err := ctx.Ret.Send(&beam.Message{Verb: beam.Ack, Ret: c.Server}) _, err := ctx.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: c.Server})
return err return err
})) }))
return backend return backend
} }
func (c *shipyard) attach(ctx *beam.Message) error { func (c *shipyard) attach(ctx *libswarm.Message) error {
if ctx.Args[0] == "" { if ctx.Args[0] == "" {
ctx.Ret.Send(&beam.Message{Verb: beam.Ack, Ret: c.Server}) ctx.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: c.Server})
for { for {
time.Sleep(1 * time.Second) time.Sleep(1 * time.Second)
} }
@ -41,17 +41,17 @@ func (c *shipyard) attach(ctx *beam.Message) error {
return nil return nil
} }
func (c *shipyard) start(ctx *beam.Message) error { func (c *shipyard) start(ctx *libswarm.Message) error {
ctx.Ret.Send(&beam.Message{Verb: beam.Ack}) ctx.Ret.Send(&libswarm.Message{Verb: libswarm.Ack})
return nil return nil
} }
type shipyard struct { type shipyard struct {
url, user, pass string url, user, pass string
*beam.Server *libswarm.Server
} }
func (c *shipyard) containers(ctx *beam.Message) error { func (c *shipyard) containers(ctx *libswarm.Message) error {
out, err := c.gateway("GET", "containers", "") out, err := c.gateway("GET", "containers", "")
if err != nil { if err != nil {
return err return err
@ -62,7 +62,7 @@ func (c *shipyard) containers(ctx *beam.Message) error {
for _, c := range data.Objects { for _, c := range data.Objects {
ids = append(ids, c.Id) ids = append(ids, c.Id)
} }
if _, err := ctx.Ret.Send(&beam.Message{Verb: beam.Set, Args: ids}); err != nil { if _, err := ctx.Ret.Send(&libswarm.Message{Verb: libswarm.Set, Args: ids}); err != nil {
return err return err
} }
return nil return nil
@ -76,7 +76,7 @@ type shipyardObject struct {
Id string `json:"container_id"` Id string `json:"container_id"`
} }
func (c *shipyard) containerInspect(ctx *beam.Message) error { func (c *shipyard) containerInspect(ctx *libswarm.Message) error {
if len(ctx.Args) != 1 { if len(ctx.Args) != 1 {
return fmt.Errorf("Expected 1 container id, got %s", len(ctx.Args)) return fmt.Errorf("Expected 1 container id, got %s", len(ctx.Args))
} }
@ -87,7 +87,7 @@ func (c *shipyard) containerInspect(ctx *beam.Message) error {
} }
var data shipyardObject var data shipyardObject
json.Unmarshal(out, &data) json.Unmarshal(out, &data)
if _, err := ctx.Ret.Send(&beam.Message{Verb: beam.Set, Args: []string{"foo", "bar"}}); err != nil { if _, err := ctx.Ret.Send(&libswarm.Message{Verb: libswarm.Set, Args: []string{"foo", "bar"}}); err != nil {
return err return err
} }
return nil return nil

View File

@ -1,24 +1,25 @@
package backends package backends
import ( import (
"github.com/docker/libswarm/beam" "github.com/docker/libswarm"
"github.com/docker/libswarm/utils"
) )
func Simulator() beam.Sender { func Simulator() libswarm.Sender {
s := beam.NewServer() s := libswarm.NewServer()
s.OnVerb(beam.Spawn, beam.Handler(func(ctx *beam.Message) error { s.OnVerb(libswarm.Spawn, libswarm.Handler(func(ctx *libswarm.Message) error {
containers := ctx.Args containers := ctx.Args
instance := beam.Task(func(in beam.Receiver, out beam.Sender) { instance := utils.Task(func(in libswarm.Receiver, out libswarm.Sender) {
beam.Obj(out).Log("[simulator] starting\n") libswarm.AsClient(out).Log("[simulator] starting\n")
s := beam.NewServer() s := libswarm.NewServer()
s.OnVerb(beam.Ls, beam.Handler(func(msg *beam.Message) error { s.OnVerb(libswarm.Ls, libswarm.Handler(func(msg *libswarm.Message) error {
beam.Obj(out).Log("[simulator] generating fake list of objects...\n") libswarm.AsClient(out).Log("[simulator] generating fake list of objects...\n")
beam.Obj(msg.Ret).Set(containers...) libswarm.AsClient(msg.Ret).Set(containers...)
return nil return nil
})) }))
beam.Copy(s, in) libswarm.Copy(s, in)
}) })
ctx.Ret.Send(&beam.Message{Verb: beam.Ack, Ret: instance}) ctx.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: instance})
return nil return nil
})) }))
return s return s

View File

@ -3,7 +3,7 @@ package backends
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/docker/libswarm/beam" "github.com/docker/libswarm"
"github.com/dotcloud/docker/engine" "github.com/dotcloud/docker/engine"
"github.com/tutumcloud/go-tutum" "github.com/tutumcloud/go-tutum"
"io/ioutil" "io/ioutil"
@ -18,9 +18,9 @@ var (
tutumConnectorVersion = "v1.11" tutumConnectorVersion = "v1.11"
) )
func Tutum() beam.Sender { func Tutum() libswarm.Sender {
backend := beam.NewServer() backend := libswarm.NewServer()
backend.OnVerb(beam.Spawn, beam.Handler(func(ctx *beam.Message) error { backend.OnVerb(libswarm.Spawn, libswarm.Handler(func(ctx *libswarm.Message) error {
if len(ctx.Args) == 2 { if len(ctx.Args) == 2 {
tutum.User = ctx.Args[0] tutum.User = ctx.Args[0]
tutum.ApiKey = ctx.Args[1] tutum.ApiKey = ctx.Args[1]
@ -34,13 +34,13 @@ func Tutum() beam.Sender {
} }
t := &tutumBackend{ t := &tutumBackend{
tutumDockerConnector: tutumDockerConnector, tutumDockerConnector: tutumDockerConnector,
Server: beam.NewServer(), Server: libswarm.NewServer(),
} }
t.Server.OnVerb(beam.Attach, beam.Handler(t.attach)) t.Server.OnVerb(libswarm.Attach, libswarm.Handler(t.attach))
t.Server.OnVerb(beam.Start, beam.Handler(t.ack)) t.Server.OnVerb(libswarm.Start, libswarm.Handler(t.ack))
t.Server.OnVerb(beam.Ls, beam.Handler(t.ls)) t.Server.OnVerb(libswarm.Ls, libswarm.Handler(t.ls))
t.Server.OnVerb(beam.Spawn, beam.Handler(t.spawn)) t.Server.OnVerb(libswarm.Spawn, libswarm.Handler(t.spawn))
_, err = ctx.Ret.Send(&beam.Message{Verb: beam.Ack, Ret: t.Server}) _, err = ctx.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: t.Server})
return err return err
})) }))
return backend return backend
@ -48,28 +48,28 @@ func Tutum() beam.Sender {
type tutumBackend struct { type tutumBackend struct {
tutumDockerConnector *tutumDockerConnector tutumDockerConnector *tutumDockerConnector
*beam.Server *libswarm.Server
} }
func (t *tutumBackend) attach(ctx *beam.Message) error { func (t *tutumBackend) attach(ctx *libswarm.Message) error {
if ctx.Args[0] == "" { if ctx.Args[0] == "" {
ctx.Ret.Send(&beam.Message{Verb: beam.Ack, Ret: t.Server}) ctx.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: t.Server})
for { for {
time.Sleep(1 * time.Second) time.Sleep(1 * time.Second)
} }
} else { } else {
c := t.newContainer(ctx.Args[0]) c := t.newContainer(ctx.Args[0])
ctx.Ret.Send(&beam.Message{Verb: beam.Ack, Ret: c}) ctx.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: c})
} }
return nil return nil
} }
func (t *tutumBackend) ack(ctx *beam.Message) error { func (t *tutumBackend) ack(ctx *libswarm.Message) error {
ctx.Ret.Send(&beam.Message{Verb: beam.Ack, Ret: t.Server}) ctx.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: t.Server})
return nil return nil
} }
func (t *tutumBackend) ls(ctx *beam.Message) error { func (t *tutumBackend) ls(ctx *libswarm.Message) error {
resp, err := t.tutumDockerConnector.call("GET", "/containers/json", "") resp, err := t.tutumDockerConnector.call("GET", "/containers/json", "")
if err != nil { if err != nil {
return fmt.Errorf("%s: get: %v", t.tutumDockerConnector.URL.String(), err) return fmt.Errorf("%s: get: %v", t.tutumDockerConnector.URL.String(), err)
@ -86,13 +86,13 @@ func (t *tutumBackend) ls(ctx *beam.Message) error {
for _, env := range c.Data { for _, env := range c.Data {
ids = append(ids, env.GetList("Id")[0]) ids = append(ids, env.GetList("Id")[0])
} }
if _, err := ctx.Ret.Send(&beam.Message{Verb: beam.Set, Args: ids}); err != nil { if _, err := ctx.Ret.Send(&libswarm.Message{Verb: libswarm.Set, Args: ids}); err != nil {
return fmt.Errorf("%s: send response: %v", t.tutumDockerConnector.URL.String(), err) return fmt.Errorf("%s: send response: %v", t.tutumDockerConnector.URL.String(), err)
} }
return nil return nil
} }
func (t *tutumBackend) spawn(ctx *beam.Message) error { func (t *tutumBackend) spawn(ctx *libswarm.Message) error {
if len(ctx.Args) != 1 { if len(ctx.Args) != 1 {
return fmt.Errorf("tutum: spawn takes exactly 1 argument, got %d", len(ctx.Args)) return fmt.Errorf("tutum: spawn takes exactly 1 argument, got %d", len(ctx.Args))
} }
@ -112,18 +112,18 @@ func (t *tutumBackend) spawn(ctx *beam.Message) error {
return err return err
} }
c := t.newContainer(respJson.Id) c := t.newContainer(respJson.Id)
if _, err = ctx.Ret.Send(&beam.Message{Verb: beam.Ack, Ret: c}); err != nil { if _, err = ctx.Ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: c}); err != nil {
return err return err
} }
return nil return nil
} }
func (t *tutumBackend) newContainer(id string) beam.Sender { func (t *tutumBackend) newContainer(id string) libswarm.Sender {
c := &tutumContainer{tutumBackend: t, id: id} c := &tutumContainer{tutumBackend: t, id: id}
instance := beam.NewServer() instance := libswarm.NewServer()
instance.OnVerb(beam.Get, beam.Handler(c.get)) instance.OnVerb(libswarm.Get, libswarm.Handler(c.get))
instance.OnVerb(beam.Start, beam.Handler(c.start)) instance.OnVerb(libswarm.Start, libswarm.Handler(c.start))
instance.OnVerb(beam.Stop, beam.Handler(c.stop)) instance.OnVerb(libswarm.Stop, libswarm.Handler(c.stop))
return instance return instance
} }
@ -132,7 +132,7 @@ type tutumContainer struct {
id string id string
} }
func (c *tutumContainer) get(ctx *beam.Message) error { func (c *tutumContainer) get(ctx *libswarm.Message) error {
path := fmt.Sprintf("/containers/%s/json", c.id) path := fmt.Sprintf("/containers/%s/json", c.id)
resp, err := c.tutumBackend.tutumDockerConnector.call("GET", path, "") resp, err := c.tutumBackend.tutumDockerConnector.call("GET", path, "")
if err != nil { if err != nil {
@ -146,13 +146,13 @@ func (c *tutumContainer) get(ctx *beam.Message) error {
if resp.StatusCode != 200 { if resp.StatusCode != 200 {
return fmt.Errorf("%s", respBody) return fmt.Errorf("%s", respBody)
} }
if _, err := ctx.Ret.Send(&beam.Message{Verb: beam.Set, Args: []string{string(respBody)}}); err != nil { if _, err := ctx.Ret.Send(&libswarm.Message{Verb: libswarm.Set, Args: []string{string(respBody)}}); err != nil {
return err return err
} }
return nil return nil
} }
func (c *tutumContainer) start(ctx *beam.Message) error { func (c *tutumContainer) start(ctx *libswarm.Message) error {
path := fmt.Sprintf("/containers/%s/start", c.id) path := fmt.Sprintf("/containers/%s/start", c.id)
resp, err := c.tutumBackend.tutumDockerConnector.call("POST", path, "") resp, err := c.tutumBackend.tutumDockerConnector.call("POST", path, "")
if err != nil { if err != nil {
@ -165,13 +165,13 @@ func (c *tutumContainer) start(ctx *beam.Message) error {
if resp.StatusCode != 204 { if resp.StatusCode != 204 {
return fmt.Errorf("expected status code 204, got %d:\n%s", resp.StatusCode, respBody) return fmt.Errorf("expected status code 204, got %d:\n%s", resp.StatusCode, respBody)
} }
if _, err := ctx.Ret.Send(&beam.Message{Verb: beam.Ack}); err != nil { if _, err := ctx.Ret.Send(&libswarm.Message{Verb: libswarm.Ack}); err != nil {
return err return err
} }
return nil return nil
} }
func (c *tutumContainer) stop(ctx *beam.Message) error { func (c *tutumContainer) stop(ctx *libswarm.Message) error {
path := fmt.Sprintf("/containers/%s/stop", c.id) path := fmt.Sprintf("/containers/%s/stop", c.id)
resp, err := c.tutumBackend.tutumDockerConnector.call("POST", path, "") resp, err := c.tutumBackend.tutumDockerConnector.call("POST", path, "")
if err != nil { if err != nil {
@ -184,7 +184,7 @@ func (c *tutumContainer) stop(ctx *beam.Message) error {
if resp.StatusCode != 204 { if resp.StatusCode != 204 {
return fmt.Errorf("expected status code 204, got %d:\n%s", resp.StatusCode, respBody) return fmt.Errorf("expected status code 204, got %d:\n%s", resp.StatusCode, respBody)
} }
if _, err := ctx.Ret.Send(&beam.Message{Verb: beam.Ack}); err != nil { if _, err := ctx.Ret.Send(&libswarm.Message{Verb: libswarm.Ack}); err != nil {
return err return err
} }
return nil return nil

View File

@ -1,36 +0,0 @@
package beam
import (
"fmt"
"sync"
)
func Task(f func(in Receiver, out Sender)) Sender {
var running bool
var l sync.RWMutex
inR, inW := Pipe()
outR, outW := Pipe()
obj := NewServer()
obj.OnVerb(Attach, Handler(func(msg *Message) error {
msg.Ret.Send(&Message{Verb: 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)
Copy(msg.Ret, outR)
return nil
}))
obj.OnVerb(Start, Handler(func(msg *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(&Message{Verb: Ack})
return nil
}))
return obj
}

View File

@ -1,44 +0,0 @@
package beam
import (
"sort"
)
type Tree struct {
*Server
children map[string]Sender
}
func NewTree() *Tree {
t := &Tree{
Server: NewServer(),
children: make(map[string]Sender),
}
t.OnVerb(Attach, Handler(func(msg *Message) error {
if len(msg.Args) == 0 || msg.Args[0] == "" {
msg.Ret.Send(&Message{Verb: Ack, Ret: t})
return nil
}
if child, exists := t.children[msg.Args[0]]; exists {
msg.Ret.Send(&Message{Verb: Ack, Ret: child})
return nil
}
Obj(msg.Ret).Error("not found")
return nil
}))
t.OnVerb(Ls, Handler(func(msg *Message) error {
names := make([]string, 0, len(t.children))
for name := range t.children {
names = append(names, name)
}
sort.Strings(names)
Obj(msg.Ret).Set(names...)
return nil
}))
return t
}
func (t *Tree) Bind(name string, dst Sender) *Tree {
t.children[name] = dst
return t
}

View File

@ -1,4 +1,4 @@
package beam package libswarm
import ( import (
"encoding/json" "encoding/json"
@ -8,23 +8,21 @@ import (
"strings" "strings"
) )
// FIXME: rename Object to Client type Client struct {
type Object struct {
Sender Sender
} }
func Obj(dst Sender) *Object { func AsClient(dst Sender) *Client {
return &Object{dst} return &Client{dst}
} }
func (o *Object) Log(msg string, args ...interface{}) error { func (c *Client) Log(msg string, args ...interface{}) error {
_, err := o.Send(&Message{Verb: Log, Args: []string{fmt.Sprintf(msg, args...)}}) _, err := c.Send(&Message{Verb: Log, Args: []string{fmt.Sprintf(msg, args...)}})
return err return err
} }
func (o *Object) Ls() ([]string, error) { func (c *Client) Ls() ([]string, error) {
ret, err := o.Send(&Message{Verb: Ls, Ret: RetPipe}) ret, err := c.Send(&Message{Verb: Ls, Ret: RetPipe})
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -44,8 +42,8 @@ func (o *Object) Ls() ([]string, error) {
return nil, fmt.Errorf("unexpected verb %v", msg.Verb) return nil, fmt.Errorf("unexpected verb %v", msg.Verb)
} }
func (o *Object) Spawn(cmd ...string) (out *Object, err error) { func (c *Client) Spawn(cmd ...string) (out *Client, err error) {
ret, err := o.Send(&Message{Verb: Spawn, Args: cmd, Ret: RetPipe}) ret, err := c.Send(&Message{Verb: Spawn, Args: cmd, Ret: RetPipe})
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -57,7 +55,7 @@ func (o *Object) Spawn(cmd ...string) (out *Object, err error) {
return nil, err return nil, err
} }
if msg.Verb == Ack { if msg.Verb == Ack {
return &Object{msg.Ret}, nil return &Client{msg.Ret}, nil
} }
msg.Ret.Close() msg.Ret.Close()
if msg.Verb == Error { if msg.Verb == Error {
@ -66,8 +64,8 @@ func (o *Object) Spawn(cmd ...string) (out *Object, err error) {
return nil, fmt.Errorf("unexpected verb %v", msg.Verb) return nil, fmt.Errorf("unexpected verb %v", msg.Verb)
} }
func (o *Object) Attach(name string) (in Receiver, out *Object, err error) { func (c *Client) Attach(name string) (in Receiver, out *Client, err error) {
ret, err := o.Send(&Message{Verb: Attach, Args: []string{name}, Ret: RetPipe}) ret, err := c.Send(&Message{Verb: Attach, Args: []string{name}, Ret: RetPipe})
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -79,7 +77,7 @@ func (o *Object) Attach(name string) (in Receiver, out *Object, err error) {
return nil, nil, err return nil, nil, err
} }
if msg.Verb == Ack { if msg.Verb == Ack {
return ret, &Object{msg.Ret}, nil return ret, &Client{msg.Ret}, nil
} }
msg.Ret.Close() msg.Ret.Close()
if msg.Verb == Error { if msg.Verb == Error {
@ -88,13 +86,13 @@ func (o *Object) Attach(name string) (in Receiver, out *Object, err error) {
return nil, nil, fmt.Errorf("unexpected verb %v", msg.Verb) return nil, nil, fmt.Errorf("unexpected verb %v", msg.Verb)
} }
func (o *Object) Error(msg string, args ...interface{}) error { func (c *Client) Error(msg string, args ...interface{}) error {
_, err := o.Send(&Message{Verb: Error, Args: []string{fmt.Sprintf(msg, args...)}}) _, err := c.Send(&Message{Verb: Error, Args: []string{fmt.Sprintf(msg, args...)}})
return err return err
} }
func (o *Object) Connect() (net.Conn, error) { func (c *Client) Connect() (net.Conn, error) {
ret, err := o.Send(&Message{Verb: Connect, Ret: RetPipe}) ret, err := c.Send(&Message{Verb: Connect, Ret: RetPipe})
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -121,21 +119,21 @@ func (o *Object) Connect() (net.Conn, error) {
return nil, fmt.Errorf("unexpected verb %v", msg.Verb) return nil, fmt.Errorf("unexpected verb %v", msg.Verb)
} }
func (o *Object) SetJson(val interface{}) error { func (c *Client) SetJson(val interface{}) error {
txt, err := json.Marshal(val) txt, err := json.Marshal(val)
if err != nil { if err != nil {
return err return err
} }
return o.Set(string(txt)) return c.Set(string(txt))
} }
func (o *Object) Set(vals ...string) error { func (c *Client) Set(vals ...string) error {
_, err := o.Send(&Message{Verb: Set, Args: vals}) _, err := c.Send(&Message{Verb: Set, Args: vals})
return err return err
} }
func (o *Object) Get() (string, error) { func (c *Client) Get() (string, error) {
ret, err := o.Send(&Message{Verb: Get, Ret: RetPipe}) ret, err := c.Send(&Message{Verb: Get, Ret: RetPipe})
if err != nil { if err != nil {
return "", err return "", err
} }
@ -158,8 +156,8 @@ func (o *Object) Get() (string, error) {
return "", fmt.Errorf("unexpected verb %v", msg.Verb) return "", fmt.Errorf("unexpected verb %v", msg.Verb)
} }
func (o *Object) Watch() (Receiver, error) { func (c *Client) Watch() (Receiver, error) {
ret, err := o.Send(&Message{Verb: Watch, Ret: RetPipe}) ret, err := c.Send(&Message{Verb: Watch, Ret: RetPipe})
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -173,8 +171,8 @@ func (o *Object) Watch() (Receiver, error) {
return nil, fmt.Errorf("unexpected verb %v", msg.Verb) return nil, fmt.Errorf("unexpected verb %v", msg.Verb)
} }
func (o *Object) Start() error { func (c *Client) Start() error {
ret, err := o.Send(&Message{Verb: Start, Ret: RetPipe}) ret, err := c.Send(&Message{Verb: Start, Ret: RetPipe})
msg, err := ret.Receive(0) msg, err := ret.Receive(0)
if err == io.EOF { if err == io.EOF {
return fmt.Errorf("unexpected EOF") return fmt.Errorf("unexpected EOF")
@ -188,8 +186,8 @@ func (o *Object) Start() error {
return fmt.Errorf("unexpected verb %v", msg.Verb) return fmt.Errorf("unexpected verb %v", msg.Verb)
} }
func (o *Object) Stop() error { func (c *Client) Stop() error {
ret, err := o.Send(&Message{Verb: Stop, Ret: RetPipe}) ret, err := c.Send(&Message{Verb: Stop, Ret: RetPipe})
msg, err := ret.Receive(0) msg, err := ret.Receive(0)
if err == io.EOF { if err == io.EOF {
return fmt.Errorf("unexpected EOF") return fmt.Errorf("unexpected EOF")

View File

@ -5,46 +5,47 @@ import (
"io" "io"
"log" "log"
"github.com/docker/libswarm/beam" "github.com/docker/libswarm"
"github.com/docker/libswarm/utils"
) )
// The Debug service is an example of intercepting messages between a receiver and a sender. // 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. // The service also exposes messages passing through it for debug purposes.
func Debug() beam.Sender { func Debug() libswarm.Sender {
dbgInstance := &debug{ dbgInstance := &debug{
service: beam.NewServer(), service: libswarm.NewServer(),
} }
sender := beam.NewServer() sender := libswarm.NewServer()
sender.OnVerb(beam.Spawn, beam.Handler(dbgInstance.spawn)) sender.OnVerb(libswarm.Spawn, libswarm.Handler(dbgInstance.spawn))
return sender return sender
} }
// Debug service type // Debug service type
type debug struct { type debug struct {
service *beam.Server service *libswarm.Server
out beam.Sender out libswarm.Sender
} }
// Spawn will return a new instance as the Ret channel of the message sent back // Spawn will return a new instance as the Ret channel of the message sent back
func (dbg *debug) spawn(msg *beam.Message) (err error) { func (dbg *debug) spawn(msg *libswarm.Message) (err error) {
// By sending back a task, beam will run the function with the in and out arguments // 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. // set to the services present before and after this one in the pipeline.
instance := beam.Task(func(in beam.Receiver, out beam.Sender) { instance := utils.Task(func(in libswarm.Receiver, out libswarm.Sender) {
// Setup our channels // Setup our channels
dbg.out = out dbg.out = out
// Set up the debug interceptor // Set up the debug interceptor
dbg.service.Catchall(beam.Handler(dbg.catchall)) dbg.service.Catchall(libswarm.Handler(dbg.catchall))
// Copy everything from the receiver to our service. By copying like this in the task // 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. // we can use the catchall handler instead of handling the message here.
beam.Copy(dbg.service, in) libswarm.Copy(dbg.service, in)
}) })
// Inform the system of our new instance // Inform the system of our new instance
msg.Ret.Send(&beam.Message{ msg.Ret.Send(&libswarm.Message{
Verb: beam.Ack, Verb: libswarm.Ack,
Ret: instance, Ret: instance,
}) })
@ -52,7 +53,7 @@ func (dbg *debug) spawn(msg *beam.Message) (err error) {
} }
// Catches all messages sent to the service // Catches all messages sent to the service
func (dbg *debug) catchall(msg *beam.Message) (err error) { func (dbg *debug) catchall(msg *libswarm.Message) (err error) {
log.Printf("[debug] ---> Outbound Message ---> { Verb: %s, Args: %v }\n", msg.Verb, msg.Args) log.Printf("[debug] ---> Outbound Message ---> { Verb: %s, Args: %v }\n", msg.Verb, msg.Args)
// If there's no output after us then we'll just reply with an error // If there's no output after us then we'll just reply with an error
@ -61,13 +62,13 @@ func (dbg *debug) catchall(msg *beam.Message) (err error) {
return fmt.Errorf("[debug] Verb: %s is not implemented.", msg.Verb) return fmt.Errorf("[debug] Verb: %s is not implemented.", msg.Verb)
} }
// We forward the message with a special Ret value of "beam.RetPipe" - this // We forward the message with a special Ret value of "libswarm.RetPipe" - this
// asks libchan to open a new pipe so that we can read replies from upstream // asks libchan to open a new pipe so that we can read replies from upstream
forwardedMsg := &beam.Message{ forwardedMsg := &libswarm.Message{
Verb: msg.Verb, Verb: msg.Verb,
Args: msg.Args, Args: msg.Args,
Att: msg.Att, Att: msg.Att,
Ret: beam.RetPipe, Ret: libswarm.RetPipe,
} }
// Send the forwarded message // Send the forwarded message
@ -78,7 +79,7 @@ func (dbg *debug) catchall(msg *beam.Message) (err error) {
} else { } else {
for { for {
// Relay all messages returned until the inbound channel is empty (EOF) // Relay all messages returned until the inbound channel is empty (EOF)
var reply *beam.Message var reply *libswarm.Message
if reply, err = inbound.Receive(0); err != nil { if reply, err = inbound.Receive(0); err != nil {
if err == io.EOF { if err == io.EOF {
// EOF is expected // EOF is expected

View File

@ -1,4 +1,4 @@
package beam package libswarm
import ( import (
"github.com/docker/libchan" "github.com/docker/libchan"

View File

@ -1,4 +1,4 @@
package beam package libswarm
import ( import (
"io/ioutil" "io/ioutil"

View File

@ -1,4 +1,4 @@
package beam package libswarm
import ( import (
"github.com/docker/libchan" "github.com/docker/libchan"

View File

@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"github.com/codegangsta/cli" "github.com/codegangsta/cli"
"github.com/docker/libswarm/backends" "github.com/docker/libswarm/backends"
"github.com/docker/libswarm/beam" "github.com/docker/libswarm"
_ "github.com/dotcloud/docker/api/server" _ "github.com/dotcloud/docker/api/server"
"github.com/flynn/go-shlex" "github.com/flynn/go-shlex"
"io" "io"
@ -24,7 +24,7 @@ func main() {
} }
func cmdDaemon(c *cli.Context) { func cmdDaemon(c *cli.Context) {
app := beam.NewServer() app := libswarm.NewServer()
app.OnLog(func(args ...string) error { app.OnLog(func(args ...string) error {
log.Printf("%s\n", strings.Join(args, " ")) log.Printf("%s\n", strings.Join(args, " "))
return nil return nil
@ -42,7 +42,7 @@ func cmdDaemon(c *cli.Context) {
fmt.Println(strings.Join(names, "\n")) fmt.Println(strings.Join(names, "\n"))
return return
} }
var previousInstanceR beam.Receiver var previousInstanceR libswarm.Receiver
// FIXME: refactor into a Pipeline // FIXME: refactor into a Pipeline
for idx, backendArg := range c.Args() { for idx, backendArg := range c.Args() {
bName, bArgs, err := parseCmd(backendArg) bName, bArgs, err := parseCmd(backendArg)
@ -61,9 +61,9 @@ func cmdDaemon(c *cli.Context) {
if err != nil { if err != nil {
Fatalf("attach: %v", err) Fatalf("attach: %v", err)
} }
go func(r beam.Receiver, w beam.Sender, idx int) { go func(r libswarm.Receiver, w libswarm.Sender, idx int) {
if r != nil { if r != nil {
beam.Copy(w, r) libswarm.Copy(w, r)
} }
w.Close() w.Close()
}(previousInstanceR, instanceW, idx) }(previousInstanceR, instanceW, idx)
@ -72,7 +72,7 @@ func cmdDaemon(c *cli.Context) {
} }
previousInstanceR = instanceR previousInstanceR = instanceR
} }
_, err := beam.Copy(app, previousInstanceR) _, err := libswarm.Copy(app, previousInstanceR)
if err != nil { if err != nil {
Fatalf("copy: %v", err) Fatalf("copy: %v", err)
} }

View File

@ -1,13 +1,15 @@
package beam package utils
import ( import (
"github.com/docker/libchan" "github.com/docker/libchan"
"github.com/docker/libswarm"
"io" "io"
) )
type NopSender struct{} type NopSender struct{}
func (s NopSender) Send(msg *Message) (Receiver, error) { func (s NopSender) Send(msg *libswarm.Message) (libswarm.Receiver, error) {
return NopReceiver{}, nil return NopReceiver{}, nil
} }
@ -21,7 +23,7 @@ func (s NopSender) Unwrap() libchan.Sender {
type NopReceiver struct{} type NopReceiver struct{}
func (r NopReceiver) Receive(mode int) (*Message, error) { func (r NopReceiver) Receive(mode int) (*libswarm.Message, error) {
return nil, io.EOF return nil, io.EOF
} }

View File

@ -1,28 +1,30 @@
package beam package utils
import ( import (
"github.com/docker/libswarm"
"fmt" "fmt"
"io" "io"
) )
func EncodeStream(sender Sender, reader io.Reader, tag string) { func EncodeStream(sender libswarm.Sender, reader io.Reader, tag string) {
chunk := make([]byte, 4096) chunk := make([]byte, 4096)
for { for {
n, err := reader.Read(chunk) n, err := reader.Read(chunk)
if n > 0 { if n > 0 {
sender.Send(&Message{Verb: Log, Args: []string{tag, string(chunk[0:n])}}) sender.Send(&libswarm.Message{Verb: libswarm.Log, Args: []string{tag, string(chunk[0:n])}})
} }
if err != nil { if err != nil {
message := fmt.Sprintf("Error reading from stream: %v", err) message := fmt.Sprintf("Error reading from stream: %v", err)
sender.Send(&Message{Verb: Error, Args: []string{message}}) sender.Send(&libswarm.Message{Verb: libswarm.Error, Args: []string{message}})
break break
} }
} }
} }
func DecodeStream(dst io.Writer, src Receiver, tag string) error { func DecodeStream(dst io.Writer, src libswarm.Receiver, tag string) error {
for { for {
msg, err := src.Receive(Ret) msg, err := src.Receive(libswarm.Ret)
if err == io.EOF { if err == io.EOF {
return nil return nil
} }

38
utils/task.go Normal file
View File

@ -0,0 +1,38 @@
package utils
import (
"github.com/docker/libswarm"
"fmt"
"sync"
)
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
}

46
utils/tree.go Normal file
View File

@ -0,0 +1,46 @@
package utils
import (
"github.com/docker/libswarm"
"sort"
)
type Tree struct {
*libswarm.Server
children map[string]libswarm.Sender
}
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 (t *Tree) Bind(name string, dst libswarm.Sender) *Tree {
t.children[name] = dst
return t
}

View File

@ -1,4 +1,4 @@
package beam package libswarm
import ( import (
"fmt" "fmt"