mirror of
https://github.com/aljazceru/kata-containers.git
synced 2025-12-27 19:14:21 +01:00
The same way a caller of "kata-runtime kill 12345" expects the container 12345 to be killed, the same call to a container representing a sandbox should actually kill the sandbox, meaning it would be stopped after the container has been killed. This way, the caller knows the VM is stopped after kill returns. This is an issue raised by Openshift and Kubernetes tests. They call into delete way after the call to kill has been submitted, and in the meantime they kill all processes related to the container, meaning they do kill the VM before we could do it ourselves. In this case, the delete responsible of stopping the VM comes too late and it returns an error when trying to destroy the sandbox while trying to communicate with the agent since the VM is not here anymore. This commit addresses this issue by letting "kill" call into StopSandbox() if the command relates to a sandbox instead of a simple container. Fixes #246 Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
339 lines
9.3 KiB
Go
339 lines
9.3 KiB
Go
// Copyright (c) 2017 Intel Corporation
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
|
|
package main
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"syscall"
|
|
"testing"
|
|
|
|
vc "github.com/kata-containers/runtime/virtcontainers"
|
|
vcAnnotations "github.com/kata-containers/runtime/virtcontainers/pkg/annotations"
|
|
"github.com/kata-containers/runtime/virtcontainers/pkg/vcmock"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
var (
|
|
testKillContainerFuncReturnNil = func(sandboxID, containerID string, signal syscall.Signal, all bool) error {
|
|
return nil
|
|
}
|
|
|
|
testStopContainerFuncReturnNil = func(sandboxID, containerID string) (vc.VCContainer, error) {
|
|
return &vcmock.Container{}, nil
|
|
}
|
|
|
|
testStopSandboxFuncReturnNil = func(sandboxID string) (vc.VCSandbox, error) {
|
|
return &vcmock.Sandbox{}, nil
|
|
}
|
|
)
|
|
|
|
func TestProcessSignal(t *testing.T) {
|
|
tests := []struct {
|
|
signal string
|
|
valid bool
|
|
signum syscall.Signal
|
|
}{
|
|
{"SIGDCKBY", false, 0}, //invalid signal
|
|
{"DCKBY", false, 0}, //invalid signal
|
|
{"99999", false, 0}, //invalid signal
|
|
{"SIGTERM", true, syscall.SIGTERM},
|
|
{"TERM", true, syscall.SIGTERM},
|
|
{"15", true, syscall.SIGTERM},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
signum, err := processSignal(test.signal)
|
|
if signum != test.signum {
|
|
t.Fatalf("signal received: %d expected signal: %d\n", signum, test.signum)
|
|
}
|
|
if test.valid && err != nil {
|
|
t.Fatalf("signal %s is a valid but a error was received: %s\n", test.signal, err)
|
|
}
|
|
if !test.valid && err == nil {
|
|
t.Fatalf("signal %s is not a valid signal and no error was reported\n", test.signal)
|
|
}
|
|
}
|
|
}
|
|
|
|
func testKillCLIFunctionTerminationSignalSuccessful(t *testing.T, sig string) {
|
|
assert := assert.New(t)
|
|
|
|
state := vc.State{
|
|
State: vc.StateRunning,
|
|
}
|
|
|
|
annotations := map[string]string{
|
|
vcAnnotations.ContainerTypeKey: string(vc.PodContainer),
|
|
}
|
|
|
|
testingImpl.KillContainerFunc = testKillContainerFuncReturnNil
|
|
testingImpl.StopContainerFunc = testStopContainerFuncReturnNil
|
|
testingImpl.ListSandboxFunc = func() ([]vc.SandboxStatus, error) {
|
|
return newSingleContainerSandboxStatusList(testSandboxID, testContainerID, state, state, annotations), nil
|
|
}
|
|
defer func() {
|
|
testingImpl.KillContainerFunc = nil
|
|
testingImpl.StopContainerFunc = nil
|
|
testingImpl.ListSandboxFunc = nil
|
|
}()
|
|
|
|
set := flag.NewFlagSet("", 0)
|
|
set.Parse([]string{testContainerID, sig})
|
|
|
|
execCLICommandFunc(assert, killCLICommand, set, false)
|
|
|
|
annotations = map[string]string{
|
|
vcAnnotations.ContainerTypeKey: string(vc.PodSandbox),
|
|
}
|
|
|
|
testingImpl.StopContainerFunc = nil
|
|
testingImpl.StopSandboxFunc = testStopSandboxFuncReturnNil
|
|
testingImpl.ListSandboxFunc = func() ([]vc.SandboxStatus, error) {
|
|
return newSingleContainerSandboxStatusList(testSandboxID, testContainerID, state, state, annotations), nil
|
|
}
|
|
defer func() {
|
|
testingImpl.StopSandboxFunc = nil
|
|
}()
|
|
|
|
execCLICommandFunc(assert, killCLICommand, set, false)
|
|
}
|
|
|
|
func TestKillCLIFunctionSigkillSuccessful(t *testing.T) {
|
|
testKillCLIFunctionTerminationSignalSuccessful(t, "SIGKILL")
|
|
}
|
|
|
|
func TestKillCLIFunctionSigtermSuccessful(t *testing.T) {
|
|
testKillCLIFunctionTerminationSignalSuccessful(t, "SIGTERM")
|
|
}
|
|
|
|
func TestKillCLIFunctionNotTerminationSignalSuccessful(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
state := vc.State{
|
|
State: vc.StateRunning,
|
|
}
|
|
|
|
testingImpl.KillContainerFunc = testKillContainerFuncReturnNil
|
|
testingImpl.ListSandboxFunc = func() ([]vc.SandboxStatus, error) {
|
|
return newSingleContainerSandboxStatusList(testSandboxID, testContainerID, state, state, map[string]string{}), nil
|
|
}
|
|
defer func() {
|
|
testingImpl.KillContainerFunc = nil
|
|
testingImpl.ListSandboxFunc = nil
|
|
}()
|
|
|
|
set := flag.NewFlagSet("", 0)
|
|
set.Parse([]string{testContainerID, "SIGUSR1"})
|
|
|
|
execCLICommandFunc(assert, killCLICommand, set, false)
|
|
}
|
|
|
|
func TestKillCLIFunctionNoSignalSuccessful(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
state := vc.State{
|
|
State: vc.StateRunning,
|
|
}
|
|
|
|
annotations := map[string]string{
|
|
vcAnnotations.ContainerTypeKey: string(vc.PodContainer),
|
|
}
|
|
|
|
testingImpl.KillContainerFunc = testKillContainerFuncReturnNil
|
|
testingImpl.StopContainerFunc = testStopContainerFuncReturnNil
|
|
testingImpl.ListSandboxFunc = func() ([]vc.SandboxStatus, error) {
|
|
return newSingleContainerSandboxStatusList(testSandboxID, testContainerID, state, state, annotations), nil
|
|
}
|
|
defer func() {
|
|
testingImpl.KillContainerFunc = nil
|
|
testingImpl.StopContainerFunc = nil
|
|
testingImpl.ListSandboxFunc = nil
|
|
}()
|
|
|
|
set := flag.NewFlagSet("", 0)
|
|
set.Parse([]string{testContainerID})
|
|
|
|
execCLICommandFunc(assert, killCLICommand, set, false)
|
|
|
|
annotations = map[string]string{
|
|
vcAnnotations.ContainerTypeKey: string(vc.PodSandbox),
|
|
}
|
|
|
|
testingImpl.StopContainerFunc = nil
|
|
testingImpl.StopSandboxFunc = testStopSandboxFuncReturnNil
|
|
testingImpl.ListSandboxFunc = func() ([]vc.SandboxStatus, error) {
|
|
return newSingleContainerSandboxStatusList(testSandboxID, testContainerID, state, state, annotations), nil
|
|
}
|
|
defer func() {
|
|
testingImpl.StopSandboxFunc = nil
|
|
}()
|
|
|
|
execCLICommandFunc(assert, killCLICommand, set, false)
|
|
}
|
|
|
|
func TestKillCLIFunctionEnableAllSuccessful(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
state := vc.State{
|
|
State: vc.StateRunning,
|
|
}
|
|
|
|
annotations := map[string]string{
|
|
vcAnnotations.ContainerTypeKey: string(vc.PodContainer),
|
|
}
|
|
|
|
testingImpl.KillContainerFunc = func(sandboxID, containerID string, signal syscall.Signal, all bool) error {
|
|
if !all {
|
|
return fmt.Errorf("Expecting -all flag = true, Got false")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
testingImpl.StopContainerFunc = testStopContainerFuncReturnNil
|
|
testingImpl.ListSandboxFunc = func() ([]vc.SandboxStatus, error) {
|
|
return newSingleContainerSandboxStatusList(testSandboxID, testContainerID, state, state, annotations), nil
|
|
}
|
|
defer func() {
|
|
testingImpl.KillContainerFunc = nil
|
|
testingImpl.StopContainerFunc = nil
|
|
testingImpl.ListSandboxFunc = nil
|
|
}()
|
|
|
|
set := flag.NewFlagSet("", 0)
|
|
set.Bool("all", true, "")
|
|
set.Parse([]string{testContainerID})
|
|
|
|
execCLICommandFunc(assert, killCLICommand, set, false)
|
|
|
|
annotations = map[string]string{
|
|
vcAnnotations.ContainerTypeKey: string(vc.PodSandbox),
|
|
}
|
|
|
|
testingImpl.StopContainerFunc = nil
|
|
testingImpl.StopSandboxFunc = testStopSandboxFuncReturnNil
|
|
testingImpl.ListSandboxFunc = func() ([]vc.SandboxStatus, error) {
|
|
return newSingleContainerSandboxStatusList(testSandboxID, testContainerID, state, state, annotations), nil
|
|
}
|
|
defer func() {
|
|
testingImpl.StopSandboxFunc = nil
|
|
}()
|
|
|
|
execCLICommandFunc(assert, killCLICommand, set, false)
|
|
}
|
|
|
|
func TestKillCLIFunctionNoContainerIDFailure(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
set := flag.NewFlagSet("", 0)
|
|
|
|
execCLICommandFunc(assert, killCLICommand, set, true)
|
|
}
|
|
|
|
func TestKillCLIFunctionContainerNotExistFailure(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
testingImpl.KillContainerFunc = testKillContainerFuncReturnNil
|
|
testingImpl.ListSandboxFunc = func() ([]vc.SandboxStatus, error) {
|
|
return []vc.SandboxStatus{}, nil
|
|
}
|
|
defer func() {
|
|
testingImpl.KillContainerFunc = nil
|
|
testingImpl.ListSandboxFunc = nil
|
|
}()
|
|
|
|
set := flag.NewFlagSet("", 0)
|
|
set.Parse([]string{testContainerID})
|
|
|
|
execCLICommandFunc(assert, killCLICommand, set, true)
|
|
}
|
|
|
|
func TestKillCLIFunctionInvalidSignalFailure(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
state := vc.State{
|
|
State: vc.StateRunning,
|
|
}
|
|
|
|
testingImpl.KillContainerFunc = testKillContainerFuncReturnNil
|
|
testingImpl.ListSandboxFunc = func() ([]vc.SandboxStatus, error) {
|
|
return newSingleContainerSandboxStatusList(testSandboxID, testContainerID, state, state, map[string]string{}), nil
|
|
}
|
|
defer func() {
|
|
testingImpl.KillContainerFunc = nil
|
|
testingImpl.ListSandboxFunc = nil
|
|
}()
|
|
|
|
set := flag.NewFlagSet("", 0)
|
|
set.Parse([]string{testContainerID, "SIGINVALID"})
|
|
|
|
execCLICommandFunc(assert, killCLICommand, set, true)
|
|
}
|
|
|
|
func TestKillCLIFunctionInvalidStatePausedFailure(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
state := vc.State{
|
|
State: vc.StatePaused,
|
|
}
|
|
|
|
testingImpl.KillContainerFunc = testKillContainerFuncReturnNil
|
|
testingImpl.ListSandboxFunc = func() ([]vc.SandboxStatus, error) {
|
|
return newSingleContainerSandboxStatusList(testSandboxID, testContainerID, state, state, map[string]string{}), nil
|
|
}
|
|
defer func() {
|
|
testingImpl.KillContainerFunc = nil
|
|
testingImpl.ListSandboxFunc = nil
|
|
}()
|
|
|
|
set := flag.NewFlagSet("", 0)
|
|
set.Parse([]string{testContainerID})
|
|
|
|
execCLICommandFunc(assert, killCLICommand, set, true)
|
|
}
|
|
|
|
func TestKillCLIFunctionInvalidStateStoppedFailure(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
state := vc.State{
|
|
State: vc.StateStopped,
|
|
}
|
|
|
|
testingImpl.KillContainerFunc = testKillContainerFuncReturnNil
|
|
testingImpl.ListSandboxFunc = func() ([]vc.SandboxStatus, error) {
|
|
return newSingleContainerSandboxStatusList(testSandboxID, testContainerID, state, state, map[string]string{}), nil
|
|
}
|
|
defer func() {
|
|
testingImpl.KillContainerFunc = nil
|
|
testingImpl.ListSandboxFunc = nil
|
|
}()
|
|
|
|
set := flag.NewFlagSet("", 0)
|
|
set.Parse([]string{testContainerID})
|
|
|
|
execCLICommandFunc(assert, killCLICommand, set, true)
|
|
}
|
|
|
|
func TestKillCLIFunctionKillContainerFailure(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
state := vc.State{
|
|
State: vc.StateRunning,
|
|
}
|
|
|
|
testingImpl.ListSandboxFunc = func() ([]vc.SandboxStatus, error) {
|
|
return newSingleContainerSandboxStatusList(testSandboxID, testContainerID, state, state, map[string]string{}), nil
|
|
}
|
|
defer func() {
|
|
testingImpl.ListSandboxFunc = nil
|
|
}()
|
|
|
|
set := flag.NewFlagSet("", 0)
|
|
set.Parse([]string{testContainerID})
|
|
|
|
execCLICommandFunc(assert, killCLICommand, set, true)
|
|
}
|