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 EncodeStream(sender libswarm.Sender, reader io.Reader, tag string) { chunk := make([]byte, 4096) for { n, err := reader.Read(chunk) if n > 0 { sender.Send(&libswarm.Message{Verb: libswarm.Log, Args: []string{tag, string(chunk[0:n])}}) } if err != nil { message := fmt.Sprintf("Error reading from stream: %v", err) sender.Send(&libswarm.Message{Verb: libswarm.Error, Args: []string{message}}) break } } }
func (c *container) attach(name string, ret libswarm.Sender) error { if _, err := ret.Send(&libswarm.Message{Verb: libswarm.Ack}); err != nil { return err } path := fmt.Sprintf("/containers/%s/attach?stdout=1&stderr=1&stream=1", c.id) stdoutR, stdoutW := io.Pipe() stderrR, stderrW := io.Pipe() go utils.EncodeStream(ret, stdoutR, "stdout") go utils.EncodeStream(ret, stderrR, "stderr") c.backend.client.hijack("POST", path, nil, stdoutW, stderrW) return nil }
func (b *dockerClientBackend) attach(name string, ret libswarm.Sender) error { if name == "" { ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: b.Server}) <-make(chan struct{}) } else { path := fmt.Sprintf("/containers/%s/json", name) resp, err := b.client.call("GET", path, "") if err != nil { return err } respBody, err := ioutil.ReadAll(resp.Body) if err != nil { return err } if resp.StatusCode != 200 { return fmt.Errorf("%s", respBody) } c := b.newContainer(name) ret.Send(&libswarm.Message{Verb: libswarm.Ack, Ret: c}) } return nil }