Merge pull request #12120 from LK4D4/split_attach

Remove engine usage from attach
This commit is contained in:
Tibor Vass 2015-04-07 18:13:35 -04:00
commit dccda72a41
5 changed files with 44 additions and 91 deletions

View File

@ -904,16 +904,12 @@ func postContainersAttach(eng *engine.Engine, version version.Version, w http.Re
return fmt.Errorf("Missing parameter")
}
var (
job = eng.Job("container_inspect", vars["name"])
c, err = job.Stdout.AddEnv()
)
d := getDaemon(eng)
cont, err := d.Get(vars["name"])
if err != nil {
return err
}
if err = job.Run(); err != nil {
return err
}
inStream, outStream, err := hijackServer(w)
if err != nil {
@ -929,25 +925,17 @@ func postContainersAttach(eng *engine.Engine, version version.Version, w http.Re
fmt.Fprintf(outStream, "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.docker.raw-stream\r\n\r\n")
}
if c.GetSubEnv("Config") != nil && !c.GetSubEnv("Config").GetBool("Tty") && version.GreaterThanOrEqualTo("1.6") {
if !cont.Config.Tty && version.GreaterThanOrEqualTo("1.6") {
errStream = stdcopy.NewStdWriter(outStream, stdcopy.Stderr)
outStream = stdcopy.NewStdWriter(outStream, stdcopy.Stdout)
} else {
errStream = outStream
}
logs := r.Form.Get("logs") != ""
stream := r.Form.Get("stream") != ""
job = eng.Job("attach", vars["name"])
job.Setenv("logs", r.Form.Get("logs"))
job.Setenv("stream", r.Form.Get("stream"))
job.Setenv("stdin", r.Form.Get("stdin"))
job.Setenv("stdout", r.Form.Get("stdout"))
job.Setenv("stderr", r.Form.Get("stderr"))
job.Stdin.Add(inStream)
job.Stdout.Add(outStream)
job.Stderr.Set(errStream)
if err := job.Run(); err != nil {
if err := cont.AttachWithLogs(inStream, outStream, errStream, logs, stream); err != nil {
fmt.Fprintf(outStream, "Error attaching: %s\n", err)
}
return nil
}
@ -959,23 +947,19 @@ func wsContainersAttach(eng *engine.Engine, version version.Version, w http.Resp
if vars == nil {
return fmt.Errorf("Missing parameter")
}
d := getDaemon(eng)
if err := eng.Job("container_inspect", vars["name"]).Run(); err != nil {
cont, err := d.Get(vars["name"])
if err != nil {
return err
}
h := websocket.Handler(func(ws *websocket.Conn) {
defer ws.Close()
job := eng.Job("attach", vars["name"])
job.Setenv("logs", r.Form.Get("logs"))
job.Setenv("stream", r.Form.Get("stream"))
job.Setenv("stdin", r.Form.Get("stdin"))
job.Setenv("stdout", r.Form.Get("stdout"))
job.Setenv("stderr", r.Form.Get("stderr"))
job.Stdin.Add(ws)
job.Stdout.Add(ws)
job.Stderr.Set(ws)
if err := job.Run(); err != nil {
logs := r.Form.Get("logs") != ""
stream := r.Form.Get("stream") != ""
if err := cont.AttachWithLogs(ws, ws, ws, logs, stream); err != nil {
logrus.Errorf("Error attaching websocket: %s", err)
}
})

View File

@ -573,7 +573,7 @@ func (b *Builder) create() (*daemon.Container, error) {
func (b *Builder) run(c *daemon.Container) error {
var errCh chan error
if b.Verbose {
errCh = b.Daemon.Attach(&c.StreamConfig, c.Config.OpenStdin, c.Config.StdinOnce, c.Config.Tty, nil, b.OutStream, b.ErrStream)
errCh = c.Attach(nil, b.OutStream, b.ErrStream)
}
//start the container

View File

@ -2,57 +2,36 @@ package daemon
import (
"encoding/json"
"fmt"
"io"
"os"
"sync"
"time"
"github.com/Sirupsen/logrus"
"github.com/docker/docker/engine"
"github.com/docker/docker/pkg/jsonlog"
"github.com/docker/docker/pkg/promise"
"github.com/docker/docker/utils"
)
func (daemon *Daemon) ContainerAttach(job *engine.Job) error {
if len(job.Args) != 1 {
return fmt.Errorf("Usage: %s CONTAINER\n", job.Name)
}
var (
name = job.Args[0]
logs = job.GetenvBool("logs")
stream = job.GetenvBool("stream")
stdin = job.GetenvBool("stdin")
stdout = job.GetenvBool("stdout")
stderr = job.GetenvBool("stderr")
)
container, err := daemon.Get(name)
if err != nil {
return err
}
//logs
func (c *Container) AttachWithLogs(stdin io.ReadCloser, stdout, stderr io.Writer, logs, stream bool) error {
if logs {
cLog, err := container.ReadLog("json")
cLog, err := c.ReadLog("json")
if err != nil && os.IsNotExist(err) {
// Legacy logs
logrus.Debugf("Old logs format")
if stdout {
cLog, err := container.ReadLog("stdout")
if stdout != nil {
cLog, err := c.ReadLog("stdout")
if err != nil {
logrus.Errorf("Error reading logs (stdout): %s", err)
} else if _, err := io.Copy(job.Stdout, cLog); err != nil {
} else if _, err := io.Copy(stdout, cLog); err != nil {
logrus.Errorf("Error streaming logs (stdout): %s", err)
}
}
if stderr {
cLog, err := container.ReadLog("stderr")
if stderr != nil {
cLog, err := c.ReadLog("stderr")
if err != nil {
logrus.Errorf("Error reading logs (stderr): %s", err)
} else if _, err := io.Copy(job.Stderr, cLog); err != nil {
} else if _, err := io.Copy(stderr, cLog); err != nil {
logrus.Errorf("Error streaming logs (stderr): %s", err)
}
}
@ -69,11 +48,11 @@ func (daemon *Daemon) ContainerAttach(job *engine.Job) error {
logrus.Errorf("Error streaming logs: %s", err)
break
}
if l.Stream == "stdout" && stdout {
io.WriteString(job.Stdout, l.Log)
if l.Stream == "stdout" && stdout != nil {
io.WriteString(stdout, l.Log)
}
if l.Stream == "stderr" && stderr {
io.WriteString(job.Stderr, l.Log)
if l.Stream == "stderr" && stderr != nil {
io.WriteString(stderr, l.Log)
}
}
}
@ -81,38 +60,29 @@ func (daemon *Daemon) ContainerAttach(job *engine.Job) error {
//stream
if stream {
var (
cStdin io.ReadCloser
cStdout, cStderr io.Writer
)
if stdin {
r, w := io.Pipe()
go func() {
defer w.Close()
defer logrus.Debugf("Closing buffered stdin pipe")
io.Copy(w, job.Stdin)
}()
cStdin = r
}
if stdout {
cStdout = job.Stdout
}
if stderr {
cStderr = job.Stderr
}
<-daemon.Attach(&container.StreamConfig, container.Config.OpenStdin, container.Config.StdinOnce, container.Config.Tty, cStdin, cStdout, cStderr)
var stdinPipe io.ReadCloser
r, w := io.Pipe()
go func() {
defer w.Close()
defer logrus.Debugf("Closing buffered stdin pipe")
io.Copy(w, stdin)
}()
stdinPipe = r
<-c.Attach(stdinPipe, stdout, stderr)
// If we are in stdinonce mode, wait for the process to end
// otherwise, simply return
if container.Config.StdinOnce && !container.Config.Tty {
container.WaitStop(-1 * time.Second)
if c.Config.StdinOnce && !c.Config.Tty {
c.WaitStop(-1 * time.Second)
}
}
return nil
}
func (daemon *Daemon) Attach(streamConfig *StreamConfig, openStdin, stdinOnce, tty bool, stdin io.ReadCloser, stdout io.Writer, stderr io.Writer) chan error {
func (c *Container) Attach(stdin io.ReadCloser, stdout io.Writer, stderr io.Writer) chan error {
return attach(&c.StreamConfig, c.Config.OpenStdin, c.Config.StdinOnce, c.Config.Tty, stdin, stdout, stderr)
}
func attach(streamConfig *StreamConfig, openStdin, stdinOnce, tty bool, stdin io.ReadCloser, stdout io.Writer, stderr io.Writer) chan error {
var (
cStdout, cStderr io.ReadCloser
cStdin io.WriteCloser

View File

@ -115,7 +115,6 @@ type Daemon struct {
func (daemon *Daemon) Install(eng *engine.Engine) error {
// FIXME: remove ImageDelete's dependency on Daemon, then move to graph/
for name, method := range map[string]engine.Handler{
"attach": daemon.ContainerAttach,
"commit": daemon.ContainerCommit,
"container_changes": daemon.ContainerChanges,
"container_copy": daemon.ContainerCopy,

View File

@ -218,7 +218,7 @@ func (d *Daemon) ContainerExecStart(job *engine.Job) error {
execConfig.StreamConfig.stdinPipe = ioutils.NopWriteCloser(ioutil.Discard) // Silently drop stdin
}
attachErr := d.Attach(&execConfig.StreamConfig, execConfig.OpenStdin, true, execConfig.ProcessConfig.Tty, cStdin, cStdout, cStderr)
attachErr := attach(&execConfig.StreamConfig, execConfig.OpenStdin, true, execConfig.ProcessConfig.Tty, cStdin, cStdout, cStderr)
execErr := make(chan error)