mirror of
https://github.com/clearlinux/docker.git
synced 2026-10-03 23:38:24 +00:00
Merge pull request #7344 from shykes/cleanup-server-attach
Move container-related jobs out of deprecated server/ package
This commit is contained in:
@@ -1,11 +1,122 @@
|
||||
package daemon
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/engine"
|
||||
"github.com/docker/docker/utils"
|
||||
)
|
||||
|
||||
func (daemon *Daemon) ContainerAttach(job *engine.Job) engine.Status {
|
||||
if len(job.Args) != 1 {
|
||||
return job.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 := daemon.Get(name)
|
||||
if container == nil {
|
||||
return job.Errorf("No such container: %s", name)
|
||||
}
|
||||
|
||||
//logs
|
||||
if logs {
|
||||
cLog, err := container.ReadLog("json")
|
||||
if err != nil && os.IsNotExist(err) {
|
||||
// Legacy logs
|
||||
utils.Debugf("Old logs format")
|
||||
if stdout {
|
||||
cLog, err := container.ReadLog("stdout")
|
||||
if err != nil {
|
||||
utils.Errorf("Error reading logs (stdout): %s", err)
|
||||
} else if _, err := io.Copy(job.Stdout, cLog); err != nil {
|
||||
utils.Errorf("Error streaming logs (stdout): %s", err)
|
||||
}
|
||||
}
|
||||
if stderr {
|
||||
cLog, err := container.ReadLog("stderr")
|
||||
if err != nil {
|
||||
utils.Errorf("Error reading logs (stderr): %s", err)
|
||||
} else if _, err := io.Copy(job.Stderr, cLog); err != nil {
|
||||
utils.Errorf("Error streaming logs (stderr): %s", err)
|
||||
}
|
||||
}
|
||||
} else if err != nil {
|
||||
utils.Errorf("Error reading logs (json): %s", err)
|
||||
} else {
|
||||
dec := json.NewDecoder(cLog)
|
||||
for {
|
||||
l := &utils.JSONLog{}
|
||||
|
||||
if err := dec.Decode(l); err == io.EOF {
|
||||
break
|
||||
} else if err != nil {
|
||||
utils.Errorf("Error streaming logs: %s", err)
|
||||
break
|
||||
}
|
||||
if l.Stream == "stdout" && stdout {
|
||||
fmt.Fprintf(job.Stdout, "%s", l.Log)
|
||||
}
|
||||
if l.Stream == "stderr" && stderr {
|
||||
fmt.Fprintf(job.Stderr, "%s", l.Log)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//stream
|
||||
if stream {
|
||||
var (
|
||||
cStdin io.ReadCloser
|
||||
cStdout, cStderr io.Writer
|
||||
cStdinCloser io.Closer
|
||||
)
|
||||
|
||||
if stdin {
|
||||
r, w := io.Pipe()
|
||||
go func() {
|
||||
defer w.Close()
|
||||
defer utils.Debugf("Closing buffered stdin pipe")
|
||||
io.Copy(w, job.Stdin)
|
||||
}()
|
||||
cStdin = r
|
||||
cStdinCloser = job.Stdin
|
||||
}
|
||||
if stdout {
|
||||
cStdout = job.Stdout
|
||||
}
|
||||
if stderr {
|
||||
cStderr = job.Stderr
|
||||
}
|
||||
|
||||
<-daemon.Attach(container, cStdin, cStdinCloser, cStdout, cStderr)
|
||||
|
||||
// If we are in stdinonce mode, wait for the process to end
|
||||
// otherwise, simply return
|
||||
if container.Config.StdinOnce && !container.Config.Tty {
|
||||
container.State.WaitStop(-1 * time.Second)
|
||||
}
|
||||
}
|
||||
return engine.StatusOK
|
||||
}
|
||||
|
||||
// FIXME: this should be private, and every outside subsystem
|
||||
// should go through the "container_attach" job. But that would require
|
||||
// that job to be properly documented, as well as the relationship betweem
|
||||
// Attach and ContainerAttach.
|
||||
//
|
||||
// This method is in use by builder/builder.go.
|
||||
func (daemon *Daemon) Attach(container *Container, stdin io.ReadCloser, stdinCloser io.Closer, stdout io.Writer, stderr io.Writer) chan error {
|
||||
var (
|
||||
cStdout, cStderr io.ReadCloser
|
||||
|
||||
+13
-1
@@ -105,7 +105,19 @@ type Daemon struct {
|
||||
|
||||
// Install installs daemon capabilities to eng.
|
||||
func (daemon *Daemon) Install(eng *engine.Engine) error {
|
||||
return eng.Register("container_inspect", daemon.ContainerInspect)
|
||||
if err := eng.Register("container_inspect", daemon.ContainerInspect); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := eng.Register("attach", daemon.ContainerAttach); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := eng.Register("pause", daemon.ContainerPause); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := eng.Register("unpause", daemon.ContainerUnpause); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// List returns an array of all containers registered in the daemon.
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package daemon
|
||||
|
||||
import (
|
||||
"github.com/docker/docker/engine"
|
||||
)
|
||||
|
||||
func (daemon *Daemon) ContainerPause(job *engine.Job) engine.Status {
|
||||
if len(job.Args) != 1 {
|
||||
return job.Errorf("Usage: %s CONTAINER", job.Name)
|
||||
}
|
||||
name := job.Args[0]
|
||||
container := daemon.Get(name)
|
||||
if container == nil {
|
||||
return job.Errorf("No such container: %s", name)
|
||||
}
|
||||
if err := container.Pause(); err != nil {
|
||||
return job.Errorf("Cannot pause container %s: %s", name, err)
|
||||
}
|
||||
job.Eng.Job("log", "pause", container.ID, daemon.Repositories().ImageName(container.Image)).Run()
|
||||
return engine.StatusOK
|
||||
}
|
||||
|
||||
func (daemon *Daemon) ContainerUnpause(job *engine.Job) engine.Status {
|
||||
if n := len(job.Args); n < 1 || n > 2 {
|
||||
return job.Errorf("Usage: %s CONTAINER", job.Name)
|
||||
}
|
||||
name := job.Args[0]
|
||||
container := daemon.Get(name)
|
||||
if container == nil {
|
||||
return job.Errorf("No such container: %s", name)
|
||||
}
|
||||
if err := container.Unpause(); err != nil {
|
||||
return job.Errorf("Cannot unpause container %s: %s", name, err)
|
||||
}
|
||||
job.Eng.Job("log", "unpause", container.ID, daemon.Repositories().ImageName(container.Image)).Run()
|
||||
return engine.StatusOK
|
||||
}
|
||||
Reference in New Issue
Block a user