From 2227c8ad5ee2bd2f636651efd4ef70e56c082f85 Mon Sep 17 00:00:00 2001 From: Vincent Demeester Date: Wed, 31 Jan 2018 11:41:31 -0800 Subject: [PATCH] Move some kill integration cli to api tests Signed-off-by: Vincent Demeester --- integration-cli/docker_cli_kill_test.go | 113 --------------- integration/container/kill_test.go | 182 ++++++++++++++++++++++++ integration/util/request/client.go | 10 +- 3 files changed, 186 insertions(+), 119 deletions(-) create mode 100644 integration/container/kill_test.go diff --git a/integration-cli/docker_cli_kill_test.go b/integration-cli/docker_cli_kill_test.go index 0a5aac5f8c..e2e510fcaa 100644 --- a/integration-cli/docker_cli_kill_test.go +++ b/integration-cli/docker_cli_kill_test.go @@ -6,37 +6,9 @@ import ( "github.com/docker/docker/integration-cli/checker" "github.com/docker/docker/integration-cli/cli" - "github.com/docker/docker/integration-cli/request" "github.com/go-check/check" - "github.com/gotestyourself/gotestyourself/icmd" - "golang.org/x/net/context" ) -func (s *DockerSuite) TestKillContainer(c *check.C) { - out := runSleepingContainer(c, "-d") - cleanedContainerID := strings.TrimSpace(out) - cli.WaitRun(c, cleanedContainerID) - - cli.DockerCmd(c, "kill", cleanedContainerID) - cli.WaitExited(c, cleanedContainerID, 10*time.Second) - - out = cli.DockerCmd(c, "ps", "-q").Combined() - c.Assert(out, checker.Not(checker.Contains), cleanedContainerID, check.Commentf("killed container is still running")) - -} - -func (s *DockerSuite) TestKillOffStoppedContainer(c *check.C) { - out := runSleepingContainer(c, "-d") - cleanedContainerID := strings.TrimSpace(out) - - cli.DockerCmd(c, "stop", cleanedContainerID) - cli.WaitExited(c, cleanedContainerID, 10*time.Second) - - cli.Docker(cli.Args("kill", "-s", "30", cleanedContainerID)).Assert(c, icmd.Expected{ - ExitCode: 1, - }) -} - func (s *DockerSuite) TestKillDifferentUserContainer(c *check.C) { // TODO Windows: Windows does not yet support -u (Feb 2016). testRequires(c, DaemonIsLinux) @@ -51,88 +23,3 @@ func (s *DockerSuite) TestKillDifferentUserContainer(c *check.C) { c.Assert(out, checker.Not(checker.Contains), cleanedContainerID, check.Commentf("killed container is still running")) } - -// regression test about correct signal parsing see #13665 -func (s *DockerSuite) TestKillWithSignal(c *check.C) { - // Cannot port to Windows - does not support signals in the same way Linux does - testRequires(c, DaemonIsLinux) - out, _ := dockerCmd(c, "run", "-d", "busybox", "top") - cid := strings.TrimSpace(out) - c.Assert(waitRun(cid), check.IsNil) - - dockerCmd(c, "kill", "-s", "SIGWINCH", cid) - time.Sleep(250 * time.Millisecond) - - running := inspectField(c, cid, "State.Running") - - c.Assert(running, checker.Equals, "true", check.Commentf("Container should be in running state after SIGWINCH")) -} - -func (s *DockerSuite) TestKillWithStopSignalWithSameSignalShouldDisableRestartPolicy(c *check.C) { - // Cannot port to Windows - does not support signals int the same way as Linux does - testRequires(c, DaemonIsLinux) - out := cli.DockerCmd(c, "run", "-d", "--stop-signal=TERM", "--restart=always", "busybox", "top").Combined() - cid := strings.TrimSpace(out) - cli.WaitRun(c, cid) - - // Let docker send a TERM signal to the container - // It will kill the process and disable the restart policy - cli.DockerCmd(c, "kill", "-s", "TERM", cid) - cli.WaitExited(c, cid, 10*time.Second) - - out = cli.DockerCmd(c, "ps", "-q").Combined() - c.Assert(out, checker.Not(checker.Contains), cid, check.Commentf("killed container is still running")) -} - -func (s *DockerSuite) TestKillWithStopSignalWithDifferentSignalShouldKeepRestartPolicy(c *check.C) { - // Cannot port to Windows - does not support signals int the same way as Linux does - testRequires(c, DaemonIsLinux) - out := cli.DockerCmd(c, "run", "-d", "--stop-signal=CONT", "--restart=always", "busybox", "top").Combined() - cid := strings.TrimSpace(out) - cli.WaitRun(c, cid) - - // Let docker send a TERM signal to the container - // It will kill the process, but not disable the restart policy - cli.DockerCmd(c, "kill", "-s", "TERM", cid) - cli.WaitRestart(c, cid, 10*time.Second) - - // Restart policy should still be in place, so it should be still running - cli.WaitRun(c, cid) -} - -// FIXME(vdemeester) should be a unit test -func (s *DockerSuite) TestKillWithInvalidSignal(c *check.C) { - out := runSleepingContainer(c, "-d") - cid := strings.TrimSpace(out) - c.Assert(waitRun(cid), check.IsNil) - - out, _, err := dockerCmdWithError("kill", "-s", "0", cid) - c.Assert(err, check.NotNil) - c.Assert(out, checker.Contains, "Invalid signal: 0", check.Commentf("Kill with an invalid signal didn't error out correctly")) - - running := inspectField(c, cid, "State.Running") - c.Assert(running, checker.Equals, "true", check.Commentf("Container should be in running state after an invalid signal")) - - out = runSleepingContainer(c, "-d") - cid = strings.TrimSpace(out) - c.Assert(waitRun(cid), check.IsNil) - - out, _, err = dockerCmdWithError("kill", "-s", "SIG42", cid) - c.Assert(err, check.NotNil) - c.Assert(out, checker.Contains, "Invalid signal: SIG42", check.Commentf("Kill with an invalid signal error out correctly")) - - running = inspectField(c, cid, "State.Running") - c.Assert(running, checker.Equals, "true", check.Commentf("Container should be in running state after an invalid signal")) - -} - -func (s *DockerSuite) TestKillStoppedContainerAPIPre120(c *check.C) { - testRequires(c, DaemonIsLinux) // Windows only supports 1.25 or later - runSleepingContainer(c, "--name", "docker-kill-test-api", "-d") - dockerCmd(c, "stop", "docker-kill-test-api") - cli, err := request.NewEnvClientWithVersion("v1.19") - c.Assert(err, check.IsNil) - defer cli.Close() - err = cli.ContainerKill(context.Background(), "docker-kill-test-api", "SIGKILL") - c.Assert(err, check.IsNil) -} diff --git a/integration/container/kill_test.go b/integration/container/kill_test.go new file mode 100644 index 0000000000..238515566d --- /dev/null +++ b/integration/container/kill_test.go @@ -0,0 +1,182 @@ +package container + +import ( + "context" + "testing" + "time" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" + "github.com/docker/docker/api/types/network" + "github.com/docker/docker/api/types/strslice" + "github.com/docker/docker/client" + "github.com/docker/docker/integration/util/request" + "github.com/gotestyourself/gotestyourself/poll" + "github.com/gotestyourself/gotestyourself/skip" + "github.com/stretchr/testify/require" +) + +func TestKillContainerInvalidSignal(t *testing.T) { + defer setupTest(t)() + client := request.NewAPIClient(t) + t.Parallel() + ctx := context.Background() + c, err := client.ContainerCreate(ctx, + &container.Config{ + Image: "busybox", + Cmd: strslice.StrSlice([]string{"top"}), + }, + &container.HostConfig{}, + &network.NetworkingConfig{}, + "") + require.NoError(t, err) + err = client.ContainerStart(ctx, c.ID, types.ContainerStartOptions{}) + require.NoError(t, err) + + err = client.ContainerKill(ctx, c.ID, "0") + require.EqualError(t, err, "Error response from daemon: Invalid signal: 0") + poll.WaitOn(t, containerIsInState(ctx, client, c.ID, "running"), poll.WithDelay(100*time.Millisecond)) + + err = client.ContainerKill(ctx, c.ID, "SIG42") + require.EqualError(t, err, "Error response from daemon: Invalid signal: SIG42") + poll.WaitOn(t, containerIsInState(ctx, client, c.ID, "running"), poll.WithDelay(100*time.Millisecond)) +} + +func TestKillContainer(t *testing.T) { + defer setupTest(t)() + client := request.NewAPIClient(t) + + testCases := []struct { + doc string + signal string + status string + }{ + { + doc: "no signal", + signal: "", + status: "exited", + }, + { + doc: "non killing signal", + signal: "SIGWINCH", + status: "running", + }, + { + doc: "killing signal", + signal: "SIGTERM", + status: "exited", + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.doc, func(t *testing.T) { + t.Parallel() + ctx := context.Background() + c, err := client.ContainerCreate(ctx, + &container.Config{ + Image: "busybox", + Cmd: strslice.StrSlice([]string{"top"}), + }, + &container.HostConfig{}, + &network.NetworkingConfig{}, + "") + require.NoError(t, err) + err = client.ContainerStart(ctx, c.ID, types.ContainerStartOptions{}) + require.NoError(t, err) + err = client.ContainerKill(ctx, c.ID, tc.signal) + require.NoError(t, err) + + poll.WaitOn(t, containerIsInState(ctx, client, c.ID, tc.status), poll.WithDelay(100*time.Millisecond)) + }) + } +} + +func TestKillWithStopSignalAndRestartPolicies(t *testing.T) { + skip.If(t, testEnv.OSType != "linux", "Windows only supports 1.25 or later") + defer setupTest(t)() + client := request.NewAPIClient(t) + + testCases := []struct { + doc string + stopsignal string + status string + }{ + { + doc: "same-signal-disables-restart-policy", + stopsignal: "TERM", + status: "exited", + }, + { + doc: "different-signal-keep-restart-policy", + stopsignal: "CONT", + status: "running", + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.doc, func(t *testing.T) { + t.Parallel() + ctx := context.Background() + c, err := client.ContainerCreate(ctx, + &container.Config{ + Image: "busybox", + Cmd: strslice.StrSlice([]string{"top"}), + StopSignal: tc.stopsignal, + }, + &container.HostConfig{ + RestartPolicy: container.RestartPolicy{ + Name: "always", + }}, + &network.NetworkingConfig{}, + "") + require.NoError(t, err) + err = client.ContainerStart(ctx, c.ID, types.ContainerStartOptions{}) + require.NoError(t, err) + err = client.ContainerKill(ctx, c.ID, "TERM") + require.NoError(t, err) + + poll.WaitOn(t, containerIsInState(ctx, client, c.ID, tc.status), poll.WithDelay(100*time.Millisecond)) + }) + } +} + +func TestKillStoppedContainer(t *testing.T) { + skip.If(t, testEnv.OSType != "linux") // Windows only supports 1.25 or later + defer setupTest(t)() + t.Parallel() + ctx := context.Background() + client := request.NewAPIClient(t) + c, err := client.ContainerCreate(ctx, + &container.Config{ + Image: "busybox", + Cmd: strslice.StrSlice([]string{"top"}), + }, + &container.HostConfig{}, + &network.NetworkingConfig{}, + "") + require.NoError(t, err) + err = client.ContainerKill(ctx, c.ID, "SIGKILL") + require.Error(t, err) + require.Contains(t, err.Error(), "is not running") +} + +func TestKillStoppedContainerAPIPre120(t *testing.T) { + skip.If(t, testEnv.OSType != "linux") // Windows only supports 1.25 or later + defer setupTest(t)() + t.Parallel() + ctx := context.Background() + client := request.NewAPIClient(t, client.WithVersion("1.19")) + c, err := client.ContainerCreate(ctx, + &container.Config{ + Image: "busybox", + Cmd: strslice.StrSlice([]string{"top"}), + }, + &container.HostConfig{}, + &network.NetworkingConfig{}, + "") + require.NoError(t, err) + err = client.ContainerKill(ctx, c.ID, "SIGKILL") + require.NoError(t, err) +} diff --git a/integration/util/request/client.go b/integration/util/request/client.go index b4a15a8c99..5c1ec08607 100644 --- a/integration/util/request/client.go +++ b/integration/util/request/client.go @@ -6,7 +6,6 @@ import ( "testing" "time" - "github.com/docker/docker/api" "github.com/docker/docker/client" "github.com/docker/go-connections/sockets" "github.com/docker/go-connections/tlsconfig" @@ -14,8 +13,9 @@ import ( ) // NewAPIClient returns a docker API client configured from environment variables -func NewAPIClient(t *testing.T) client.APIClient { - clt, err := client.NewEnvClient() +func NewAPIClient(t *testing.T, ops ...func(*client.Client) error) client.APIClient { + ops = append([]func(*client.Client) error{client.FromEnv}, ops...) + clt, err := client.NewClientWithOpts(ops...) require.NoError(t, err) return clt } @@ -47,7 +47,5 @@ func NewTLSAPIClient(t *testing.T, host, cacertPath, certPath, keyPath string) ( Transport: tr, CheckRedirect: client.CheckRedirect, } - verStr := api.DefaultVersion - customHeaders := map[string]string{} - return client.NewClient(host, verStr, httpClient, customHeaders) + return client.NewClientWithOpts(client.WithHost(host), client.WithHTTPClient(httpClient)) }