From de1d611990a80cf4a38ec501469c08c1aeee2d60 Mon Sep 17 00:00:00 2001 From: Lei Jitang Date: Wed, 28 Oct 2015 21:00:09 -0400 Subject: [PATCH] Add show error when attach to a paused container Signed-off-by: Lei Jitang --- api/client/attach.go | 4 ++++ api/server/router/local/container.go | 4 ++++ daemon/daemon.go | 6 ++++++ errors/daemon.go | 8 ++++++++ integration-cli/docker_cli_attach_test.go | 10 ++++++++++ 5 files changed, 32 insertions(+) diff --git a/api/client/attach.go b/api/client/attach.go index 8d0569b07d..825543d4f5 100644 --- a/api/client/attach.go +++ b/api/client/attach.go @@ -41,6 +41,10 @@ func (cli *DockerCli) CmdAttach(args ...string) error { return fmt.Errorf("You cannot attach to a stopped container, start it first") } + if c.State.Paused { + return fmt.Errorf("You cannot attach to a paused container, unpause it first") + } + if err := cli.CheckTtyInput(!*noStdin, c.Config.Tty); err != nil { return err } diff --git a/api/server/router/local/container.go b/api/server/router/local/container.go index f43093378b..479c1853a6 100644 --- a/api/server/router/local/container.go +++ b/api/server/router/local/container.go @@ -396,6 +396,10 @@ func (s *router) postContainersAttach(ctx context.Context, w http.ResponseWriter return derr.ErrorCodeNoSuchContainer.WithArgs(containerName) } + if s.daemon.IsPaused(containerName) { + return derr.ErrorCodePausedContainer.WithArgs(containerName) + } + inStream, outStream, err := httputils.HijackConnection(w) if err != nil { return err diff --git a/daemon/daemon.go b/daemon/daemon.go index 83b15a302e..1b06a24832 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -163,6 +163,12 @@ func (daemon *Daemon) Exists(id string) bool { return c != nil } +// IsPaused returns a bool indicating if the specified container is paused. +func (daemon *Daemon) IsPaused(id string) bool { + c, _ := daemon.Get(id) + return c.State.isPaused() +} + func (daemon *Daemon) containerRoot(id string) string { return filepath.Join(daemon.repository, id) } diff --git a/errors/daemon.go b/errors/daemon.go index 4673ad306d..da33558cdf 100644 --- a/errors/daemon.go +++ b/errors/daemon.go @@ -46,6 +46,14 @@ var ( HTTPStatusCode: http.StatusInternalServerError, }) + // ErrorCodePausedContainer is generated when we attempt to attach a + // container but its paused. + ErrorCodePausedContainer = errcode.Register(errGroup, errcode.ErrorDescriptor{ + Value: "CONTAINERPAUSED", + Message: "Container %s is paused. Unpause the container before attach", + Description: "The specified container is paused, unpause the container before attach", + HTTPStatusCode: http.StatusConflict, + }) // ErrorCodeAlreadyPaused is generated when we attempt to pause a // container when its already paused. ErrorCodeAlreadyPaused = errcode.Register(errGroup, errcode.ErrorDescriptor{ diff --git a/integration-cli/docker_cli_attach_test.go b/integration-cli/docker_cli_attach_test.go index bd19278d2a..ea2c69beef 100644 --- a/integration-cli/docker_cli_attach_test.go +++ b/integration-cli/docker_cli_attach_test.go @@ -9,6 +9,7 @@ import ( "sync" "time" + "github.com/docker/docker/pkg/integration/checker" "github.com/go-check/check" ) @@ -150,3 +151,12 @@ func (s *DockerSuite) TestAttachDisconnect(c *check.C) { c.Assert(err, check.IsNil) c.Assert(running, check.Equals, "true") } + +func (s *DockerSuite) TestAttachPausedContainer(c *check.C) { + defer unpauseAllContainers() + dockerCmd(c, "run", "-d", "--name=test", "busybox", "top") + dockerCmd(c, "pause", "test") + out, _, err := dockerCmdWithError("attach", "test") + c.Assert(err, checker.NotNil, check.Commentf(out)) + c.Assert(out, checker.Contains, "You cannot attach to a paused container, unpause it first") +}