summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/kill.go73
-rw-r--r--pkg/adapter/containers.go24
-rw-r--r--pkg/adapter/containers_remote.go25
3 files changed, 80 insertions, 42 deletions
diff --git a/cmd/podman/kill.go b/cmd/podman/kill.go
index 76d2516b7..82a257e23 100644
--- a/cmd/podman/kill.go
+++ b/cmd/podman/kill.go
@@ -2,16 +2,15 @@ package main
import (
"fmt"
- "syscall"
+ "reflect"
+
+ "github.com/containers/libpod/pkg/adapter"
+ "github.com/opentracing/opentracing-go"
"github.com/containers/libpod/cmd/podman/cliconfig"
- "github.com/containers/libpod/cmd/podman/libpodruntime"
- "github.com/containers/libpod/cmd/podman/shared"
- "github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless"
"github.com/docker/docker/pkg/signal"
"github.com/pkg/errors"
- "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
@@ -51,54 +50,44 @@ func init() {
// killCmd kills one or more containers with a signal
func killCmd(c *cliconfig.KillValues) error {
- var (
- killFuncs []shared.ParallelWorkerInput
- killSignal uint = uint(syscall.SIGTERM)
- )
+ if c.Bool("trace") {
+ span, _ := opentracing.StartSpanFromContext(Ctx, "killCmd")
+ defer span.Finish()
+ }
+
+ // Check if the signalString provided by the user is valid
+ // Invalid signals will return err
+ killSignal, err := signal.ParseSignal(c.Signal)
+ if err != nil {
+ return err
+ }
rootless.SetSkipStorageSetup(true)
- runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
+ runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
defer runtime.Shutdown(false)
- if c.Signal != "" {
- // Check if the signalString provided by the user is valid
- // Invalid signals will return err
- sysSignal, err := signal.ParseSignal(c.Signal)
- if err != nil {
- return err
- }
- killSignal = uint(sysSignal)
- }
-
- containers, err := getAllOrLatestContainers(&c.PodmanCommand, runtime, libpod.ContainerStateRunning, "running")
+ ok, failures, err := runtime.KillContainers(getContext(), c, killSignal)
if err != nil {
- if len(containers) == 0 {
- return err
- }
- fmt.Println(err.Error())
+ return err
}
- for _, ctr := range containers {
- con := ctr
- f := func() error {
- return con.Kill(killSignal)
- }
-
- killFuncs = append(killFuncs, shared.ParallelWorkerInput{
- ContainerID: con.ID(),
- ParallelFunc: f,
- })
+ for _, id := range ok {
+ fmt.Println(id)
}
- maxWorkers := shared.Parallelize("kill")
- if c.GlobalIsSet("max-workers") {
- maxWorkers = c.GlobalFlags.MaxWorks
- }
- logrus.Debugf("Setting maximum workers to %d", maxWorkers)
+ if len(failures) > 0 {
+ keys := reflect.ValueOf(failures).MapKeys()
+ lastKey := keys[len(keys)-1].String()
+ lastErr := failures[lastKey]
+ delete(failures, lastKey)
- killErrors, errCount := shared.ParallelExecuteWorkerPool(maxWorkers, killFuncs)
- return printParallelOutput(killErrors, errCount)
+ for _, err := range failures {
+ outputError(err)
+ }
+ return lastErr
+ }
+ return nil
}
diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go
index b0c75cf49..4975bea9c 100644
--- a/pkg/adapter/containers.go
+++ b/pkg/adapter/containers.go
@@ -4,6 +4,7 @@ package adapter
import (
"context"
+ "syscall"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod"
@@ -70,3 +71,26 @@ func (r *LocalRuntime) StopContainers(ctx context.Context, cli *cliconfig.StopVa
}
return ok, failures, nil
}
+
+// KillContainers sends signal to container(s) based on CLI inputs.
+// Returns list of successful id(s), map of failed id(s) + error, or error not from container
+func (r *LocalRuntime) KillContainers(ctx context.Context, cli *cliconfig.KillValues, signal syscall.Signal) ([]string, map[string]error, error) {
+ var (
+ ok = []string{}
+ failures = map[string]error{}
+ )
+
+ ctrs, err := shortcuts.GetContainersByContext(cli.All, cli.Latest, cli.InputArgs, r.Runtime)
+ if err != nil {
+ return ok, failures, err
+ }
+
+ for _, c := range ctrs {
+ if err := c.Kill(uint(signal)); err == nil {
+ ok = append(ok, c.ID())
+ } else {
+ failures[c.ID()] = err
+ }
+ }
+ return ok, failures, nil
+}
diff --git a/pkg/adapter/containers_remote.go b/pkg/adapter/containers_remote.go
index df40c8efd..45926ccf9 100644
--- a/pkg/adapter/containers_remote.go
+++ b/pkg/adapter/containers_remote.go
@@ -6,6 +6,7 @@ import (
"context"
"encoding/json"
"errors"
+ "syscall"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/shared"
@@ -148,6 +149,30 @@ func (r *LocalRuntime) StopContainers(ctx context.Context, cli *cliconfig.StopVa
return ok, failures, nil
}
+// KillContainers sends signal to container(s) based on CLI inputs.
+// Returns list of successful id(s), map of failed id(s) + error, or error not from container
+func (r *LocalRuntime) KillContainers(ctx context.Context, cli *cliconfig.KillValues, signal syscall.Signal) ([]string, map[string]error, error) {
+ var (
+ ok = []string{}
+ failures = map[string]error{}
+ )
+
+ ids, err := iopodman.GetContainersByContext().Call(r.Conn, cli.All, cli.Latest, cli.InputArgs)
+ if err != nil {
+ return ok, failures, err
+ }
+
+ for _, id := range ids {
+ killed, err := iopodman.KillContainer().Call(r.Conn, id, int64(signal))
+ if err != nil {
+ failures[id] = err
+ } else {
+ ok = append(ok, killed)
+ }
+ }
+ return ok, failures, nil
+}
+
// BatchContainerOp is wrapper func to mimic shared's function with a similar name meant for libpod
func BatchContainerOp(ctr *Container, opts shared.PsOptions) (shared.BatchContainerStruct, error) {
// TODO If pod ps ever shows container's sizes, re-enable this code; otherwise it isn't needed