Send stop signal specified in image config.
Signed-off-by: Lantao Liu <lantaol@google.com>
This commit is contained in:
		@@ -20,12 +20,11 @@ import (
 | 
				
			|||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/containerd/containerd/api/services/execution"
 | 
				
			||||||
 | 
						"github.com/docker/docker/pkg/signal"
 | 
				
			||||||
	"github.com/golang/glog"
 | 
						"github.com/golang/glog"
 | 
				
			||||||
	"golang.org/x/net/context"
 | 
						"golang.org/x/net/context"
 | 
				
			||||||
	"golang.org/x/sys/unix"
 | 
						"golang.org/x/sys/unix"
 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/containerd/containerd/api/services/execution"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	runtime "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1"
 | 
						runtime "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/kubernetes-incubator/cri-containerd/pkg/metadata"
 | 
						"github.com/kubernetes-incubator/cri-containerd/pkg/metadata"
 | 
				
			||||||
@@ -76,10 +75,24 @@ func (c *criContainerdService) stopContainer(ctx context.Context, meta *metadata
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if timeout > 0 {
 | 
						if timeout > 0 {
 | 
				
			||||||
		// TODO(random-liu): [P1] Get stop signal from image config.
 | 
					 | 
				
			||||||
		stopSignal := unix.SIGTERM
 | 
							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)
 | 
							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,
 | 
								ContainerID: id,
 | 
				
			||||||
			Signal:      uint32(stopSignal),
 | 
								Signal:      uint32(stopSignal),
 | 
				
			||||||
			PidOrAll:    &execution.KillRequest_All{All: true},
 | 
								PidOrAll:    &execution.KillRequest_All{All: true},
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,6 +23,7 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	"github.com/containerd/containerd/api/services/execution"
 | 
						"github.com/containerd/containerd/api/services/execution"
 | 
				
			||||||
	"github.com/containerd/containerd/api/types/task"
 | 
						"github.com/containerd/containerd/api/types/task"
 | 
				
			||||||
 | 
						imagespec "github.com/opencontainers/image-spec/specs-go/v1"
 | 
				
			||||||
	"github.com/stretchr/testify/assert"
 | 
						"github.com/stretchr/testify/assert"
 | 
				
			||||||
	"golang.org/x/net/context"
 | 
						"golang.org/x/net/context"
 | 
				
			||||||
	"golang.org/x/sys/unix"
 | 
						"golang.org/x/sys/unix"
 | 
				
			||||||
@@ -96,9 +97,14 @@ func TestStopContainer(t *testing.T) {
 | 
				
			|||||||
	testMetadata := metadata.ContainerMetadata{
 | 
						testMetadata := metadata.ContainerMetadata{
 | 
				
			||||||
		ID:        testID,
 | 
							ID:        testID,
 | 
				
			||||||
		Pid:       testPid,
 | 
							Pid:       testPid,
 | 
				
			||||||
 | 
							ImageRef:  "test-image-id",
 | 
				
			||||||
		CreatedAt: time.Now().UnixNano(),
 | 
							CreatedAt: time.Now().UnixNano(),
 | 
				
			||||||
		StartedAt: time.Now().UnixNano(),
 | 
							StartedAt: time.Now().UnixNano(),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						testImageMetadata := metadata.ImageMetadata{
 | 
				
			||||||
 | 
							ID:     "test-image-id",
 | 
				
			||||||
 | 
							Config: &imagespec.ImageConfig{},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	testContainer := task.Task{
 | 
						testContainer := task.Task{
 | 
				
			||||||
		ID:     testID,
 | 
							ID:     testID,
 | 
				
			||||||
		Pid:    testPid,
 | 
							Pid:    testPid,
 | 
				
			||||||
@@ -107,6 +113,7 @@ func TestStopContainer(t *testing.T) {
 | 
				
			|||||||
	for desc, test := range map[string]struct {
 | 
						for desc, test := range map[string]struct {
 | 
				
			||||||
		metadata            *metadata.ContainerMetadata
 | 
							metadata            *metadata.ContainerMetadata
 | 
				
			||||||
		containerdContainer *task.Task
 | 
							containerdContainer *task.Task
 | 
				
			||||||
 | 
							stopSignal          string
 | 
				
			||||||
		stopErr             error
 | 
							stopErr             error
 | 
				
			||||||
		noTimeout           bool
 | 
							noTimeout           bool
 | 
				
			||||||
		expectErr           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": {
 | 
							"should directly kill container if timeout is 0": {
 | 
				
			||||||
			metadata:            &testMetadata,
 | 
								metadata:            &testMetadata,
 | 
				
			||||||
			containerdContainer: &testContainer,
 | 
								containerdContainer: &testContainer,
 | 
				
			||||||
@@ -259,6 +287,8 @@ func TestStopContainer(t *testing.T) {
 | 
				
			|||||||
		if test.containerdContainer != nil {
 | 
							if test.containerdContainer != nil {
 | 
				
			||||||
			fake.SetFakeTasks([]task.Task{*test.containerdContainer})
 | 
								fake.SetFakeTasks([]task.Task{*test.containerdContainer})
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							testImageMetadata.Config.StopSignal = test.stopSignal
 | 
				
			||||||
 | 
							assert.NoError(t, c.imageMetadataStore.Create(testImageMetadata))
 | 
				
			||||||
		if test.stopErr != nil {
 | 
							if test.stopErr != nil {
 | 
				
			||||||
			fake.InjectError("kill", test.stopErr)
 | 
								fake.InjectError("kill", test.stopErr)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user