Keep backwards compatibility in kill api.
Return an error when the container is stopped only in api versions equal or greater than 1.20 (docker 1.8). Signed-off-by: David Calavera <david.calavera@gmail.com>
This commit is contained in:
parent
c473ae14fd
commit
621e3d8587
4 changed files with 34 additions and 12 deletions
|
@ -298,7 +298,13 @@ func (s *Server) postContainersKill(version version.Version, w http.ResponseWrit
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.daemon.ContainerKill(name, sig); err != nil {
|
if err := s.daemon.ContainerKill(name, sig); err != nil {
|
||||||
return err
|
_, isStopped := err.(daemon.ErrContainerNotRunning)
|
||||||
|
// Return error that's not caused because the container is stopped.
|
||||||
|
// Return error if the container is not running and the api is >= 1.20
|
||||||
|
// to keep backwards compatibility.
|
||||||
|
if version.GreaterThanOrEqualTo("1.20") || !isStopped {
|
||||||
|
return fmt.Errorf("Cannot kill container %s: %v", name, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
w.WriteHeader(http.StatusNoContent)
|
w.WriteHeader(http.StatusNoContent)
|
||||||
|
|
|
@ -41,6 +41,14 @@ var (
|
||||||
ErrContainerRootfsReadonly = errors.New("container rootfs is marked read-only")
|
ErrContainerRootfsReadonly = errors.New("container rootfs is marked read-only")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ErrContainerNotRunning struct {
|
||||||
|
id string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e ErrContainerNotRunning) Error() string {
|
||||||
|
return fmt.Sprintf("Container %s is not running", e.id)
|
||||||
|
}
|
||||||
|
|
||||||
type StreamConfig struct {
|
type StreamConfig struct {
|
||||||
stdout *broadcastwriter.BroadcastWriter
|
stdout *broadcastwriter.BroadcastWriter
|
||||||
stderr *broadcastwriter.BroadcastWriter
|
stderr *broadcastwriter.BroadcastWriter
|
||||||
|
@ -361,7 +369,7 @@ func (container *Container) KillSig(sig int) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !container.Running {
|
if !container.Running {
|
||||||
return fmt.Errorf("Container %s is not running", container.ID)
|
return ErrContainerNotRunning{container.ID}
|
||||||
}
|
}
|
||||||
|
|
||||||
// signal to the monitor that it should not restart the container
|
// signal to the monitor that it should not restart the container
|
||||||
|
@ -398,7 +406,7 @@ func (container *Container) Pause() error {
|
||||||
|
|
||||||
// We cannot Pause the container which is not running
|
// We cannot Pause the container which is not running
|
||||||
if !container.Running {
|
if !container.Running {
|
||||||
return fmt.Errorf("Container %s is not running, cannot pause a non-running container", container.ID)
|
return ErrContainerNotRunning{container.ID}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We cannot Pause the container which is already paused
|
// We cannot Pause the container which is already paused
|
||||||
|
@ -420,7 +428,7 @@ func (container *Container) Unpause() error {
|
||||||
|
|
||||||
// We cannot unpause the container which is not running
|
// We cannot unpause the container which is not running
|
||||||
if !container.Running {
|
if !container.Running {
|
||||||
return fmt.Errorf("Container %s is not running, cannot unpause a non-running container", container.ID)
|
return ErrContainerNotRunning{container.ID}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We cannot unpause the container which is not paused
|
// We cannot unpause the container which is not paused
|
||||||
|
@ -438,7 +446,7 @@ func (container *Container) Unpause() error {
|
||||||
|
|
||||||
func (container *Container) Kill() error {
|
func (container *Container) Kill() error {
|
||||||
if !container.IsRunning() {
|
if !container.IsRunning() {
|
||||||
return fmt.Errorf("Container %s is not running", container.ID)
|
return ErrContainerNotRunning{container.ID}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. Send SIGKILL
|
// 1. Send SIGKILL
|
||||||
|
@ -520,7 +528,7 @@ func (container *Container) Restart(seconds int) error {
|
||||||
|
|
||||||
func (container *Container) Resize(h, w int) error {
|
func (container *Container) Resize(h, w int) error {
|
||||||
if !container.IsRunning() {
|
if !container.IsRunning() {
|
||||||
return fmt.Errorf("Cannot resize container %s, container is not running", container.ID)
|
return ErrContainerNotRunning{container.ID}
|
||||||
}
|
}
|
||||||
if err := container.command.ProcessConfig.Terminal.Resize(h, w); err != nil {
|
if err := container.command.ProcessConfig.Terminal.Resize(h, w); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
package daemon
|
package daemon
|
||||||
|
|
||||||
import (
|
import "syscall"
|
||||||
"fmt"
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ContainerKill send signal to the container
|
// ContainerKill send signal to the container
|
||||||
// If no signal is given (sig 0), then Kill with SIGKILL and wait
|
// If no signal is given (sig 0), then Kill with SIGKILL and wait
|
||||||
|
@ -18,12 +15,12 @@ func (daemon *Daemon) ContainerKill(name string, sig uint64) error {
|
||||||
// If no signal is passed, or SIGKILL, perform regular Kill (SIGKILL + wait())
|
// If no signal is passed, or SIGKILL, perform regular Kill (SIGKILL + wait())
|
||||||
if sig == 0 || syscall.Signal(sig) == syscall.SIGKILL {
|
if sig == 0 || syscall.Signal(sig) == syscall.SIGKILL {
|
||||||
if err := container.Kill(); err != nil {
|
if err := container.Kill(); err != nil {
|
||||||
return fmt.Errorf("Cannot kill container %s: %s", name, err)
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, just send the requested signal
|
// Otherwise, just send the requested signal
|
||||||
if err := container.KillSig(int(sig)); err != nil {
|
if err := container.KillSig(int(sig)); err != nil {
|
||||||
return fmt.Errorf("Cannot kill container %s: %s", name, err)
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/go-check/check"
|
"github.com/go-check/check"
|
||||||
|
@ -87,3 +89,12 @@ func (s *DockerSuite) TestKillWithInvalidSignal(c *check.C) {
|
||||||
c.Fatal("Container should be in running state after an invalid signal")
|
c.Fatal("Container should be in running state after an invalid signal")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *DockerSuite) TestKillofStoppedContainerAPIPre120(c *check.C) {
|
||||||
|
dockerCmd(c, "run", "--name", "docker-kill-test-api", "-d", "busybox", "top")
|
||||||
|
dockerCmd(c, "stop", "docker-kill-test-api")
|
||||||
|
|
||||||
|
status, _, err := sockRequest("POST", fmt.Sprintf("/v1.19/containers/%s/kill", "docker-kill-test-api"), nil)
|
||||||
|
c.Assert(err, check.IsNil)
|
||||||
|
c.Assert(status, check.Equals, http.StatusNoContent)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue