From 7d5ea4401dbfa9f95097cde6adcd0b25041e66fb Mon Sep 17 00:00:00 2001 From: Lantao Liu Date: Tue, 20 Jun 2017 21:11:04 +0000 Subject: [PATCH] Send stop signal specified in image config. Signed-off-by: Lantao Liu --- pkg/server/container_stop.go | 23 ++++++++++++++++++----- pkg/server/container_stop_test.go | 30 ++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/pkg/server/container_stop.go b/pkg/server/container_stop.go index 95abc7968..377b3c938 100644 --- a/pkg/server/container_stop.go +++ b/pkg/server/container_stop.go @@ -20,12 +20,11 @@ import ( "fmt" "time" + "github.com/containerd/containerd/api/services/execution" + "github.com/docker/docker/pkg/signal" "github.com/golang/glog" "golang.org/x/net/context" "golang.org/x/sys/unix" - - "github.com/containerd/containerd/api/services/execution" - runtime "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1" "github.com/kubernetes-incubator/cri-containerd/pkg/metadata" @@ -76,10 +75,24 @@ func (c *criContainerdService) stopContainer(ctx context.Context, meta *metadata } if timeout > 0 { - // TODO(random-liu): [P1] Get stop signal from image config. stopSignal := unix.SIGTERM + imageMeta, err := c.imageMetadataStore.Get(meta.ImageRef) + if err != nil { + // NOTE(random-liu): It's possible that the container is stopped, + // deleted and image is garbage collected before this point. However, + // the chance is really slim, even it happens, it's still fine to return + // an error here. + return fmt.Errorf("failed to get image metadata %q: %v", meta.ImageRef, err) + } + if imageMeta.Config.StopSignal != "" { + stopSignal, err = signal.ParseSignal(imageMeta.Config.StopSignal) + if err != nil { + return fmt.Errorf("failed to parse stop signal %q: %v", + imageMeta.Config.StopSignal, err) + } + } glog.V(2).Infof("Stop container %q with signal %v", id, stopSignal) - _, err := c.taskService.Kill(ctx, &execution.KillRequest{ + _, err = c.taskService.Kill(ctx, &execution.KillRequest{ ContainerID: id, Signal: uint32(stopSignal), PidOrAll: &execution.KillRequest_All{All: true}, diff --git a/pkg/server/container_stop_test.go b/pkg/server/container_stop_test.go index 8bfe30a10..d7352d29f 100644 --- a/pkg/server/container_stop_test.go +++ b/pkg/server/container_stop_test.go @@ -23,6 +23,7 @@ import ( "github.com/containerd/containerd/api/services/execution" "github.com/containerd/containerd/api/types/task" + imagespec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/stretchr/testify/assert" "golang.org/x/net/context" "golang.org/x/sys/unix" @@ -96,9 +97,14 @@ func TestStopContainer(t *testing.T) { testMetadata := metadata.ContainerMetadata{ ID: testID, Pid: testPid, + ImageRef: "test-image-id", CreatedAt: time.Now().UnixNano(), StartedAt: time.Now().UnixNano(), } + testImageMetadata := metadata.ImageMetadata{ + ID: "test-image-id", + Config: &imagespec.ImageConfig{}, + } testContainer := task.Task{ ID: testID, Pid: testPid, @@ -107,6 +113,7 @@ func TestStopContainer(t *testing.T) { for desc, test := range map[string]struct { metadata *metadata.ContainerMetadata containerdContainer *task.Task + stopSignal string stopErr error noTimeout bool expectErr bool @@ -222,6 +229,27 @@ func TestStopContainer(t *testing.T) { }, }, }, + "should use stop signal specified in image config if not empty": { + metadata: &testMetadata, + containerdContainer: &testContainer, + stopSignal: "SIGHUP", + expectErr: false, + // deleted by the event monitor. + expectCalls: []servertesting.CalledDetail{ + { + Name: "kill", + Argument: &execution.KillRequest{ + ContainerID: testID, + Signal: uint32(unix.SIGHUP), + PidOrAll: &execution.KillRequest_All{All: true}, + }, + }, + { + Name: "delete", + Argument: &execution.DeleteRequest{ContainerID: testID}, + }, + }, + }, "should directly kill container if timeout is 0": { metadata: &testMetadata, containerdContainer: &testContainer, @@ -259,6 +287,8 @@ func TestStopContainer(t *testing.T) { if test.containerdContainer != nil { fake.SetFakeTasks([]task.Task{*test.containerdContainer}) } + testImageMetadata.Config.StopSignal = test.stopSignal + assert.NoError(t, c.imageMetadataStore.Create(testImageMetadata)) if test.stopErr != nil { fake.InjectError("kill", test.stopErr) }