commit
a40aa7ad54
10 changed files with 322 additions and 0 deletions
|
@ -48,6 +48,7 @@ It is currently in active development in the Kubernetes community through the [d
|
|||
| [kpod-images(1)](/docs/kpod-images.1.md) | List images in local storage |[![...](/docs/play.png)](https://asciinema.org/a/133649)|
|
||||
| [kpod-info(1)](/docs/kpod-info.1.md) | Display system information ||
|
||||
| [kpod-inspect(1)](/docs/kpod-inspect.1.md) | Display the configuration of a container or image |[![...](/docs/play.png)](https://asciinema.org/a/133418)|
|
||||
| [kpod-kill(1)](/docs/kpod-kill.1.md) | Kill the main process in one or more running containers
|
||||
| [kpod-load(1)](/docs/kpod-load.1.md) | Load an image from docker archive or oci |[![...](/docs/play.png)](https://asciinema.org/a/kp8kOaexEhEa20P1KLZ3L5X4g)|
|
||||
| [kpod-logs(1)](/docs/kpod-logs.1.md) | Display the logs of a container ||
|
||||
| [kpod-mount(1)](/docs/kpod-mount.1.md) | Mount a working container's root filesystem ||
|
||||
|
|
71
cmd/kpod/kill.go
Normal file
71
cmd/kpod/kill.go
Normal file
|
@ -0,0 +1,71 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/docker/docker/pkg/signal"
|
||||
"github.com/kubernetes-incubator/cri-o/libkpod"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var (
|
||||
killFlags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "signal, s",
|
||||
Usage: "Signal to send to the container",
|
||||
Value: "KILL",
|
||||
},
|
||||
}
|
||||
killDescription = "The main process inside each container specified will be sent SIGKILL, or any signal specified with option --signal."
|
||||
killCommand = cli.Command{
|
||||
Name: "kill",
|
||||
Usage: "Kill one or more running containers with a specific signal",
|
||||
Description: killDescription,
|
||||
Flags: killFlags,
|
||||
Action: killCmd,
|
||||
ArgsUsage: "[CONTAINER_NAME_OR_ID]",
|
||||
}
|
||||
)
|
||||
|
||||
// killCmd kills one or more containers with a signal
|
||||
func killCmd(c *cli.Context) error {
|
||||
args := c.Args()
|
||||
if len(args) == 0 {
|
||||
return errors.Errorf("specify one or more containers to kill")
|
||||
}
|
||||
config, err := getConfig(c)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get config")
|
||||
}
|
||||
server, err := libkpod.New(config)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get container server")
|
||||
}
|
||||
killSignal := c.String("signal")
|
||||
// Check if the signalString provided by the user is valid
|
||||
// Invalid signals will return err
|
||||
sysSignal, err := signal.ParseSignal(killSignal)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer server.Shutdown()
|
||||
err = server.Update()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not update list of containers")
|
||||
}
|
||||
var lastError error
|
||||
for _, container := range c.Args() {
|
||||
id, err := server.ContainerKill(container, sysSignal)
|
||||
if err != nil {
|
||||
if lastError != nil {
|
||||
fmt.Fprintln(os.Stderr, lastError)
|
||||
}
|
||||
lastError = errors.Wrapf(err, "unable to kill %v", container)
|
||||
} else {
|
||||
fmt.Println(id)
|
||||
}
|
||||
}
|
||||
return lastError
|
||||
}
|
|
@ -37,6 +37,7 @@ func main() {
|
|||
imagesCommand,
|
||||
infoCommand,
|
||||
inspectCommand,
|
||||
killCommand,
|
||||
loadCommand,
|
||||
logsCommand,
|
||||
mountCommand,
|
||||
|
|
|
@ -137,6 +137,15 @@ _kpod_inspect() {
|
|||
;;
|
||||
esac
|
||||
}
|
||||
_kpod_kill() {
|
||||
local options_with_args="
|
||||
--signal -s
|
||||
"
|
||||
local boolean_options="
|
||||
--help
|
||||
-h"
|
||||
_complete_ "$options_with_args" "$boolean_options"
|
||||
}
|
||||
|
||||
_kpod_logs() {
|
||||
local options_with_args="
|
||||
|
@ -442,6 +451,7 @@ _kpod_kpod() {
|
|||
images
|
||||
info
|
||||
inspect
|
||||
kill
|
||||
load
|
||||
logs
|
||||
mount
|
||||
|
|
33
docs/kpod-kill.1.md
Normal file
33
docs/kpod-kill.1.md
Normal file
|
@ -0,0 +1,33 @@
|
|||
% kpod(1) kpod-kill- Kill one or more containers with a signal
|
||||
% Brent Baude
|
||||
# kpod-kill"1" "September 2017" "kpod"
|
||||
|
||||
## NAME
|
||||
kpod kill - Kills one or more containers with a signal
|
||||
|
||||
## SYNOPSIS
|
||||
**kpod kill [OPTIONS] CONTAINER [...]**
|
||||
|
||||
## DESCRIPTION
|
||||
The main process inside each container specified will be sent SIGKILL, or any signal specified with option --signal.
|
||||
|
||||
## OPTIONS
|
||||
|
||||
**--signal, s**
|
||||
|
||||
Signal to send to the container. For more information on Linux signals, refer to *man signal(7)*.
|
||||
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
kpod kill mywebserver
|
||||
|
||||
kpod kill 860a4b23
|
||||
|
||||
kpod kill --signal TERM 860a4b23
|
||||
|
||||
## SEE ALSO
|
||||
kpod(1), kpod-stop(1)
|
||||
|
||||
## HISTORY
|
||||
September 2017, Originally compiled by Brent Baude <bbaude@redhat.com>
|
|
@ -67,6 +67,9 @@ Displays system information
|
|||
### inspect
|
||||
Display a container or image's configuration
|
||||
|
||||
### kill
|
||||
Kill the main process in one or more containers
|
||||
|
||||
### load
|
||||
Load an image from docker archive
|
||||
|
||||
|
|
45
libkpod/kill.go
Normal file
45
libkpod/kill.go
Normal file
|
@ -0,0 +1,45 @@
|
|||
package libkpod
|
||||
|
||||
import (
|
||||
"github.com/docker/docker/pkg/signal"
|
||||
"github.com/kubernetes-incubator/cri-o/oci"
|
||||
"github.com/kubernetes-incubator/cri-o/utils"
|
||||
"github.com/pkg/errors"
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// Reverse lookup signal string from its map
|
||||
func findStringInSignalMap(killSignal syscall.Signal) (string, error) {
|
||||
for k, v := range signal.SignalMap {
|
||||
if v == killSignal {
|
||||
return k, nil
|
||||
}
|
||||
}
|
||||
return "", errors.Errorf("unable to convert signal to string")
|
||||
|
||||
}
|
||||
|
||||
// ContainerKill sends the user provided signal to the containers primary process.
|
||||
func (c *ContainerServer) ContainerKill(container string, killSignal syscall.Signal) (string, error) { // nolint
|
||||
ctr, err := c.LookupContainer(container)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "failed to find container %s", container)
|
||||
}
|
||||
c.runtime.UpdateStatus(ctr)
|
||||
cStatus := c.runtime.ContainerStatus(ctr)
|
||||
|
||||
// If the container is not running, error and move on.
|
||||
if cStatus.Status != oci.ContainerStateRunning {
|
||||
return "", errors.Errorf("cannot kill container %s: it is not running", container)
|
||||
}
|
||||
signalString, err := findStringInSignalMap(killSignal)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err := utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, c.runtime.Path(ctr), "kill", ctr.ID(), signalString); err != nil {
|
||||
return "", err
|
||||
}
|
||||
c.ContainerStateToDisk(ctr)
|
||||
return ctr.ID(), nil
|
||||
}
|
86
test/kpod_kill.bats
Normal file
86
test/kpod_kill.bats
Normal file
|
@ -0,0 +1,86 @@
|
|||
#!/usr/bin/env bats
|
||||
|
||||
load helpers
|
||||
|
||||
ROOT="$TESTDIR/crio"
|
||||
RUNROOT="$TESTDIR/crio-run"
|
||||
KPOD_OPTIONS="--root $ROOT --runroot $RUNROOT ${STORAGE_OPTS} --runtime $RUNTIME_BINARY"
|
||||
function teardown() {
|
||||
cleanup_test
|
||||
}
|
||||
|
||||
function start_sleep_container () {
|
||||
pod_id=$(crioctl pod run --config "$TESTDATA"/sandbox_config.json)
|
||||
ctr_id=$(crioctl ctr create --config "$TESTDATA"/container_config_sleep.json --pod "$pod_id")
|
||||
crioctl ctr start --id "$ctr_id"
|
||||
}
|
||||
|
||||
@test "kill a bogus container" {
|
||||
run ${KPOD_BINARY} ${KPOD_OPTIONS} kill foobar
|
||||
echo "$output"
|
||||
[ "$status" -ne 0 ]
|
||||
}
|
||||
|
||||
@test "kill a running container by id" {
|
||||
start_crio
|
||||
${KPOD_BINARY} ${KPOD_OPTIONS} pull docker.io/library/busybox:latest
|
||||
ctr_id=$( start_sleep_container )
|
||||
crioctl ctr status --id "$ctr_id"
|
||||
${KPOD_BINARY} ${KPOD_OPTIONS} ps -a
|
||||
${KPOD_BINARY} ${KPOD_OPTIONS} logs "$ctr_id"
|
||||
crioctl ctr status --id "$ctr_id"
|
||||
run ${KPOD_BINARY} ${KPOD_OPTIONS} kill "$ctr_id"
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
cleanup_ctrs
|
||||
cleanup_pods
|
||||
stop_crio
|
||||
}
|
||||
|
||||
@test "kill a running container by id with TERM" {
|
||||
start_crio
|
||||
${KPOD_BINARY} ${KPOD_OPTIONS} pull docker.io/library/busybox:latest
|
||||
ctr_id=$( start_sleep_container )
|
||||
crioctl ctr status --id "$ctr_id"
|
||||
${KPOD_BINARY} ${KPOD_OPTIONS} ps -a
|
||||
${KPOD_BINARY} ${KPOD_OPTIONS} logs "$ctr_id"
|
||||
crioctl ctr status --id "$ctr_id"
|
||||
run ${KPOD_BINARY} ${KPOD_OPTIONS} kill -s TERM "$ctr_id"
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
cleanup_ctrs
|
||||
cleanup_pods
|
||||
stop_crio
|
||||
}
|
||||
|
||||
@test "kill a running container by name" {
|
||||
start_crio
|
||||
${KPOD_BINARY} ${KPOD_OPTIONS} pull docker.io/library/busybox:latest
|
||||
ctr_id=$( start_sleep_container )
|
||||
crioctl ctr status --id "$ctr_id"
|
||||
${KPOD_BINARY} ${KPOD_OPTIONS} ps -a
|
||||
${KPOD_BINARY} ${KPOD_OPTIONS} logs "$ctr_id"
|
||||
crioctl ctr status --id "$ctr_id"
|
||||
${KPOD_BINARY} ${KPOD_OPTIONS} ps -a
|
||||
run ${KPOD_BINARY} ${KPOD_OPTIONS} kill "k8s_container999_podsandbox1_redhat.test.crio_redhat-test-crio_1"
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
cleanup_ctrs
|
||||
cleanup_pods
|
||||
stop_crio
|
||||
}
|
||||
|
||||
@test "kill a running container by id with a bogus signal" {
|
||||
start_crio
|
||||
${KPOD_BINARY} ${KPOD_OPTIONS} pull docker.io/library/busybox:latest
|
||||
ctr_id=$( start_sleep_container )
|
||||
crioctl ctr status --id "$ctr_id"
|
||||
${KPOD_BINARY} ${KPOD_OPTIONS} logs "$ctr_id"
|
||||
crioctl ctr status --id "$ctr_id"
|
||||
run ${KPOD_BINARY} ${KPOD_OPTIONS} kill -s foobar "$ctr_id"
|
||||
echo "$output"
|
||||
[ "$status" -ne 0 ]
|
||||
cleanup_ctrs
|
||||
cleanup_pods
|
||||
stop_crio
|
||||
}
|
71
test/testdata/container_config_sleep.json
vendored
Normal file
71
test/testdata/container_config_sleep.json
vendored
Normal file
|
@ -0,0 +1,71 @@
|
|||
{
|
||||
"metadata": {
|
||||
"name": "container999",
|
||||
"attempt": 1
|
||||
},
|
||||
"image": {
|
||||
"image": "docker.io/library/busybox:latest"
|
||||
},
|
||||
"command": [
|
||||
"sleep",
|
||||
"9999"
|
||||
],
|
||||
"args": [],
|
||||
"working_dir": "/",
|
||||
"envs": [
|
||||
{
|
||||
"key": "PATH",
|
||||
"value": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
},
|
||||
{
|
||||
"key": "TERM",
|
||||
"value": "xterm"
|
||||
},
|
||||
{
|
||||
"key": "TESTDIR",
|
||||
"value": "test/dir1"
|
||||
},
|
||||
{
|
||||
"key": "TESTFILE",
|
||||
"value": "test/file1"
|
||||
}
|
||||
],
|
||||
"labels": {
|
||||
"type": "small",
|
||||
"batch": "no"
|
||||
},
|
||||
"annotations": {
|
||||
"owner": "dragon",
|
||||
"daemon": "crio"
|
||||
},
|
||||
"privileged": true,
|
||||
"log_path": "",
|
||||
"stdin": false,
|
||||
"stdin_once": false,
|
||||
"tty": false,
|
||||
"linux": {
|
||||
"resources": {
|
||||
"cpu_period": 10000,
|
||||
"cpu_quota": 20000,
|
||||
"cpu_shares": 512,
|
||||
"oom_score_adj": 30
|
||||
},
|
||||
"security_context": {
|
||||
"readonly_rootfs": false,
|
||||
"selinux_options": {
|
||||
"user": "system_u",
|
||||
"role": "system_r",
|
||||
"type": "svirt_lxc_net_t",
|
||||
"level": "s0:c4,c5"
|
||||
},
|
||||
"capabilities": {
|
||||
"add_capabilities": [
|
||||
"setuid",
|
||||
"setgid"
|
||||
],
|
||||
"drop_capabilities": [
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -45,6 +45,7 @@ There are other equivalents for these tools
|
|||
| `docker export` | [`kpod export`](./docs/kpod-export.1.md) |
|
||||
| `docker history`| [`kpod history`](./docs/kpod-history.1.md)|
|
||||
| `docker images` | [`kpod images`](./docs/kpod-images.1.md) |
|
||||
| `docker kill` | [`kpod kill`](./docs/kpod-kill.1.md) |
|
||||
| `docker load` | [`kpod load`](./docs/kpod-load.1.md) |
|
||||
| `docker pause` | [`kpod pause`](./docs/kpod-pause.1.md) |
|
||||
| `docker ps` | [`kpod ps`](./docs/kpod-ps.1.md) |
|
||||
|
|
Loading…
Reference in a new issue