Add pod kill

With tests, man page, and completions.

Signed-off-by: haircommander <pehunt@redhat.com>

Closes: #1125
Approved by: rhatdan
This commit is contained in:
haircommander
2018-07-20 14:06:26 -04:00
committed by Atomic Bot
parent 8ce0e0b246
commit 73e3945282
7 changed files with 346 additions and 0 deletions

View File

@ -18,6 +18,7 @@ var (
UseShortOptionHandling: true,
Subcommands: []cli.Command{
podCreateCommand,
podKillCommand,
podPsCommand,
podRestartCommand,
podRmCommand,

114
cmd/podman/pod_kill.go Normal file
View File

@ -0,0 +1,114 @@
package main
import (
"fmt"
"syscall"
"github.com/docker/docker/pkg/signal"
"github.com/pkg/errors"
"github.com/projectatomic/libpod/cmd/podman/libpodruntime"
"github.com/projectatomic/libpod/libpod"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
)
var (
podKillFlags = []cli.Flag{
cli.BoolFlag{
Name: "all, a",
Usage: "Kill all containers in all pods",
},
cli.StringFlag{
Name: "signal, s",
Usage: "Signal to send to the containers in the pod",
Value: "KILL",
},
LatestFlag,
}
podKillDescription = "The main process of each container inside the specified pod will be sent SIGKILL, or any signal specified with option --signal."
podKillCommand = cli.Command{
Name: "kill",
Usage: "Send the specified signal or SIGKILL to containers in pod",
Description: podKillDescription,
Flags: podKillFlags,
Action: podKillCmd,
ArgsUsage: "[POD_NAME_OR_ID]",
UseShortOptionHandling: true,
}
)
// podKillCmd kills one or more pods with a signal
func podKillCmd(c *cli.Context) error {
if err := checkMutuallyExclusiveFlags(c); err != nil {
return err
}
runtime, err := libpodruntime.GetRuntime(c)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
defer runtime.Shutdown(false)
args := c.Args()
var killSignal uint = uint(syscall.SIGTERM)
var lastError error
var pods []*libpod.Pod
if c.String("signal") != "" {
// Check if the signalString provided by the user is valid
// Invalid signals will return err
sysSignal, err := signal.ParseSignal(c.String("signal"))
if err != nil {
return err
}
killSignal = uint(sysSignal)
}
if c.Bool("all") {
pods, err = runtime.Pods()
if err != nil {
return errors.Wrapf(err, "unable to get pods")
}
}
if c.Bool("latest") {
pod, err := runtime.GetLatestPod()
if err != nil {
return errors.Wrapf(err, "unable to get latest pod")
}
pods = append(pods, pod)
}
for _, i := range args {
pod, err := runtime.LookupPod(i)
if err != nil {
logrus.Errorf("%q", lastError)
if lastError != nil {
logrus.Errorf("%q", lastError)
}
lastError = errors.Wrapf(err, "unable to find pods %s", i)
continue
}
pods = append(pods, pod)
}
for _, pod := range pods {
ctr_errs, err := pod.Kill(killSignal)
if ctr_errs != nil {
for ctr, err := range ctr_errs {
if lastError != nil {
logrus.Errorf("%q", lastError)
}
lastError = errors.Wrapf(err, "unable to kill container %q in pod %q", ctr, pod.ID())
}
continue
}
if err != nil {
if lastError != nil {
logrus.Errorf("%q", lastError)
}
lastError = errors.Wrapf(err, "unable to kill pod %q", pod.ID())
continue
}
fmt.Println(pod.ID())
}
return lastError
}

View File

@ -31,6 +31,7 @@
| [podman-pause(1)](/docs/podman-pause.1.md) | Pause one or more running containers |[![...](/docs/play.png)](https://asciinema.org/a/141292)|
| [podman-pod(1)](/docs/podman-pod.1.md) | Simple management tool for groups of containers, called pods ||
| [podman-pod-create(1)](/docs/podman-pod-create.1.md) | Create a new pod ||
| [podman-pod-kill(1)](podman-pod-kill.1.md) | Kill the main process of each container in pod. ||
| [podman-pod-ps(1)](/docs/podman-pod-ps.1.md) | List the pods on the system ||
| [podman-pod-restart](/docs/podman-pod-restart.1.md) | Restart one or more pods ||
| [podman-pod-rm(1)](/docs/podman-pod-rm.1.md) | Remove one or more pods ||

View File

@ -2086,6 +2086,29 @@ _podman_pod_create() {
_complete_ "$options_with_args" "$boolean_options"
}
_podman_pod_kill() {
local options_with_args="
"
local boolean_options="
--all
-a
--signal
-s
--latest
-l
"
_complete_ "$options_with_args" "$boolean_options"
case "$cur" in
-*)
COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
;;
*)
__podman_complete_pod_names
;;
esac
}
__podman_pod_ps() {
local options_with_args="
-f
@ -2215,6 +2238,7 @@ _podman_pod() {
"
subcommands="
create
kill
ps
restart
rm

43
docs/podman-pod-kill.1.md Normal file
View File

@ -0,0 +1,43 @@
% podman-pod-kill "1"
## NAME
podman\-pod\-kill - Kills all containers in one or more pods with a signal
## SYNOPSIS
**podman pod kill** [*options*] *pod* ...
## DESCRIPTION
The main process of each container inside the pods specified will be sent SIGKILL, or any signal specified with option --signal.
## OPTIONS
**--all, -a**
Sends signal to all containers associated with a pod.
**--latest, -l**
Instead of providing the pod name or ID, use the last created pod. If you use methods other than Podman
to run pods such as CRI-O, the last started pod could be from either of those methods.
**--signal, s**
Signal to send to the containers in the pod. For more information on Linux signals, refer to *man signal(7)*.
## EXAMPLE
podman pod kill mywebserver
podman pod kill 860a4b23
podman pod kill --signal TERM 860a4b23
podman pod kill --latest
podman pod kill --all
## SEE ALSO
podman-pod(1), podman-pod-stop(1)
## HISTORY
July 2018, Originally compiled by Peter Hunt <pehunt@redhat.com>

View File

@ -14,6 +14,7 @@ podman pod is a set of subcommands that manage pods, or groups of containers.
| Subcommand | Description |
| ------------------------------------------------- | ------------------------------------------------------------------------------ |
| [podman-pod-create(1)](podman-pod-create.1.md) | Create a new pod. |
| [podman-pod-kill(1)](podman-pod-kill.1.md) | Kill the main process of each container in pod. |
| [podman-pod-ps(1)](podman-pod-ps.1.md) | Prints out information about pods. |
| [podman-pod-rm(1)](podman-pod-rm.1.md) | Remove one or more pods. |
| [podman-pod-start(1)](podman-pod-start.1.md) | Start one or more pods. |

162
test/e2e/pod_kill_test.go Normal file
View File

@ -0,0 +1,162 @@
package integration
import (
"os"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("Podman pod kill", func() {
var (
tempdir string
err error
podmanTest PodmanTest
)
BeforeEach(func() {
tempdir, err = CreateTempDirInTempDir()
if err != nil {
os.Exit(1)
}
podmanTest = PodmanCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
AfterEach(func() {
podmanTest.CleanupPod()
})
It("podman pod kill bogus", func() {
session := podmanTest.Podman([]string{"pod", "kill", "foobar"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Not(Equal(0)))
})
It("podman pod kill a pod by id", func() {
session := podmanTest.Podman([]string{"pod", "create"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
podid := session.OutputToString()
session = podmanTest.RunTopContainerInPod("", podid)
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
session = podmanTest.RunTopContainerInPod("", podid)
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
result := podmanTest.Podman([]string{"pod", "kill", podid})
result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To(Equal(0))
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
})
It("podman pod kill a pod by id with TERM", func() {
session := podmanTest.Podman([]string{"pod", "create"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
podid := session.OutputToString()
session = podmanTest.RunTopContainerInPod("", podid)
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
result := podmanTest.Podman([]string{"pod", "kill", "-s", "9", podid})
result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To(Equal(0))
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
})
It("podman pod kill a pod by name", func() {
session := podmanTest.Podman([]string{"pod", "create", "--name", "test1"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
podid := session.OutputToString()
session = podmanTest.RunTopContainerInPod("", podid)
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
result := podmanTest.Podman([]string{"pod", "kill", "test1"})
result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To(Equal(0))
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
})
It("podman pod kill a pod by id with a bogus signal", func() {
session := podmanTest.Podman([]string{"pod", "create", "--name", "test1"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
podid := session.OutputToString()
session = podmanTest.RunTopContainerInPod("", podid)
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
result := podmanTest.Podman([]string{"pod", "kill", "-s", "bogus", "test1"})
result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To(Equal(125))
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
})
It("podman pod kill latest pod", func() {
session := podmanTest.Podman([]string{"pod", "create", "--name", "test1"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
podid := session.OutputToString()
session = podmanTest.RunTopContainerInPod("", podid)
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
session = podmanTest.Podman([]string{"pod", "create", "--name", "test2"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
podid2 := session.OutputToString()
session = podmanTest.RunTopContainerInPod("", podid2)
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
session = podmanTest.RunTopContainerInPod("", podid2)
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
result := podmanTest.Podman([]string{"pod", "kill", "-l"})
result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To(Equal(0))
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
})
It("podman pod kill all", func() {
session := podmanTest.Podman([]string{"pod", "create", "--name", "test1"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
podid := session.OutputToString()
session = podmanTest.RunTopContainerInPod("", podid)
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
session = podmanTest.RunTopContainerInPod("", podid)
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
session = podmanTest.Podman([]string{"pod", "create", "--name", "test2"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
podid2 := session.OutputToString()
session = podmanTest.RunTopContainerInPod("", podid2)
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
result := podmanTest.Podman([]string{"pod", "kill", "-a"})
result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To(Equal(0))
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
})
})