mirror of https://github.com/docker/docs.git
116 lines
2.2 KiB
Go
116 lines
2.2 KiB
Go
package backends
|
|
|
|
import (
|
|
"github.com/docker/libswarm"
|
|
"github.com/flynn/go-shlex"
|
|
|
|
"fmt"
|
|
"log"
|
|
"sync"
|
|
)
|
|
|
|
func Aggregate() libswarm.Sender {
|
|
backend := libswarm.NewServer()
|
|
backend.OnSpawn(func(cmd ...string) (libswarm.Sender, error) {
|
|
allBackends := New()
|
|
instance := libswarm.NewServer()
|
|
|
|
a, err := newAggregator(allBackends, instance, cmd)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
instance.OnAttach(a.attach)
|
|
instance.OnStart(a.start)
|
|
instance.OnLs(a.ls)
|
|
|
|
return instance, nil
|
|
})
|
|
return backend
|
|
}
|
|
|
|
type aggregator struct {
|
|
backends []*libswarm.Client
|
|
server *libswarm.Server
|
|
}
|
|
|
|
func newAggregator(allBackends *libswarm.Client, server *libswarm.Server, args []string) (*aggregator, error) {
|
|
a := &aggregator{server: server}
|
|
|
|
for _, argString := range args {
|
|
args, err := shlex.Split(argString)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(args) == 0 {
|
|
return nil, fmt.Errorf("empty backend string")
|
|
}
|
|
log.Printf("aggregator: spawning %s(%#v)\n", args[0], args[1:])
|
|
_, b, err := allBackends.Attach(args[0])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
i, err := b.Spawn(args[1:]...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
a.backends = append(a.backends, i)
|
|
}
|
|
|
|
return a, nil
|
|
}
|
|
|
|
func (a *aggregator) attach(name string, ret libswarm.Sender) error {
|
|
if name != "" {
|
|
// TODO: implement this?
|
|
return fmt.Errorf("attaching to a child is not implemented")
|
|
}
|
|
|
|
if _, err := ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: a.server}); err != nil {
|
|
return err
|
|
}
|
|
|
|
var copies sync.WaitGroup
|
|
|
|
for _, b := range a.backends {
|
|
r, _, err := b.Attach("")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
copies.Add(1)
|
|
go func() {
|
|
log.Printf("copying output from %#v\n", b)
|
|
libswarm.Copy(ret, r)
|
|
log.Printf("finished output from %#v\n", b)
|
|
copies.Done()
|
|
}()
|
|
}
|
|
|
|
copies.Wait()
|
|
return nil
|
|
}
|
|
|
|
func (a *aggregator) start() error {
|
|
for _, b := range a.backends {
|
|
err := b.Start()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (a *aggregator) ls() ([]string, error) {
|
|
var children []string
|
|
|
|
for _, b := range a.backends {
|
|
bChildren, err := b.Ls()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
children = append(children, bChildren...)
|
|
}
|
|
|
|
return children, nil
|
|
}
|