From 4d13a80fa46ce57e3c889934536320525338b3a4 Mon Sep 17 00:00:00 2001 From: Jhon Honce Date: Mon, 18 Feb 2019 16:01:31 -0700 Subject: Support podman-remote stop container(s) * Clean up adapter code * Add GetContainersByContext to Varlink API * Add missing comments * Restore save command * Restore error type mapping when using varlink Signed-off-by: Jhon Honce --- cmd/podman/commands.go | 1 - cmd/podman/errors.go | 5 ++- cmd/podman/errors_remote.go | 43 +++++++++++++++++++++++ cmd/podman/main.go | 1 + cmd/podman/stop.go | 67 +++++++++++++----------------------- cmd/podman/varlink/io.podman.varlink | 5 +++ 6 files changed, 76 insertions(+), 46 deletions(-) create mode 100644 cmd/podman/errors_remote.go (limited to 'cmd') diff --git a/cmd/podman/commands.go b/cmd/podman/commands.go index 2f9a9cfe2..635b16e0d 100644 --- a/cmd/podman/commands.go +++ b/cmd/podman/commands.go @@ -32,7 +32,6 @@ func getMainCommands() []*cobra.Command { _searchCommand, _startCommand, _statsCommand, - _stopCommand, _topCommand, _umountCommand, _unpauseCommand, diff --git a/cmd/podman/errors.go b/cmd/podman/errors.go index 2572b8779..9731037f4 100644 --- a/cmd/podman/errors.go +++ b/cmd/podman/errors.go @@ -1,3 +1,5 @@ +// +build !remoteclient + package main import ( @@ -13,7 +15,8 @@ func outputError(err error) { if MainGlobalOpts.LogLevel == "debug" { logrus.Errorf(err.Error()) } else { - if ee, ok := err.(*exec.ExitError); ok { + ee, ok := err.(*exec.ExitError) + if ok { if status, ok := ee.Sys().(syscall.WaitStatus); ok { exitCode = status.ExitStatus() } diff --git a/cmd/podman/errors_remote.go b/cmd/podman/errors_remote.go new file mode 100644 index 000000000..ab255ea56 --- /dev/null +++ b/cmd/podman/errors_remote.go @@ -0,0 +1,43 @@ +// +build remoteclient + +package main + +import ( + "fmt" + "os" + "os/exec" + "syscall" + + "github.com/containers/libpod/cmd/podman/varlink" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" +) + +func outputError(err error) { + if MainGlobalOpts.LogLevel == "debug" { + logrus.Errorf(err.Error()) + } else { + if ee, ok := err.(*exec.ExitError); ok { + if status, ok := ee.Sys().(syscall.WaitStatus); ok { + exitCode = status.ExitStatus() + } + } + var ne error + switch e := err.(type) { + // For some reason golang wont let me list them with commas so listing them all. + case *iopodman.ImageNotFound: + ne = errors.New(e.Reason) + case *iopodman.ContainerNotFound: + ne = errors.New(e.Reason) + case *iopodman.PodNotFound: + ne = errors.New(e.Reason) + case *iopodman.VolumeNotFound: + ne = errors.New(e.Reason) + case *iopodman.ErrorOccurred: + ne = errors.New(e.Reason) + default: + ne = err + } + fmt.Fprintln(os.Stderr, "Error:", ne.Error()) + } +} diff --git a/cmd/podman/main.go b/cmd/podman/main.go index 98e2f23ca..b3faf05c0 100644 --- a/cmd/podman/main.go +++ b/cmd/podman/main.go @@ -49,6 +49,7 @@ var mainCommands = []*cobra.Command{ _pushCommand, &_rmiCommand, _saveCommand, + _stopCommand, _tagCommand, _versionCommand, imageCommand.Command, diff --git a/cmd/podman/stop.go b/cmd/podman/stop.go index ab9a2cf38..7bd160494 100644 --- a/cmd/podman/stop.go +++ b/cmd/podman/stop.go @@ -2,15 +2,14 @@ package main import ( "fmt" + "reflect" "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/adapter" "github.com/containers/libpod/pkg/rootless" - opentracing "github.com/opentracing/opentracing-go" + "github.com/opentracing/opentracing-go" "github.com/pkg/errors" - "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -52,63 +51,43 @@ func init() { markFlagHiddenForRemoteClient("latest", flags) } +// stopCmd stops a container or containers func stopCmd(c *cliconfig.StopValues) error { + if c.Flag("timeout").Changed && c.Flag("time").Changed { + return errors.New("the --timeout and --time flags are mutually exclusive") + } + if c.Bool("trace") { span, _ := opentracing.StartSpanFromContext(Ctx, "stopCmd") defer span.Finish() } 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) - containers, err := getAllOrLatestContainers(&c.PodmanCommand, runtime, libpod.ContainerStateRunning, "running") + ok, failures, err := runtime.StopContainers(getContext(), c) if err != nil { - if len(containers) == 0 { - return err - } - fmt.Println(err.Error()) + return err } - if c.Flag("timeout").Changed && c.Flag("time").Changed { - return errors.New("the --timeout and --time flags are mutually exclusive") + for _, id := range ok { + fmt.Println(id) } - var stopFuncs []shared.ParallelWorkerInput - for _, ctr := range containers { - con := ctr - var stopTimeout uint - if c.Flag("timeout").Changed || c.Flag("time").Changed { - stopTimeout = c.Timeout - } else { - stopTimeout = ctr.StopTimeout() - logrus.Debugf("Set timeout to container %s default (%d)", ctr.ID(), stopTimeout) - } - f := func() error { - if err := con.StopWithTimeout(stopTimeout); err != nil { - if errors.Cause(err) == libpod.ErrCtrStopped { - logrus.Debugf("Container %s already stopped", con.ID()) - return nil - } - return err - } - return nil - } - stopFuncs = append(stopFuncs, shared.ParallelWorkerInput{ - ContainerID: con.ID(), - ParallelFunc: f, - }) - } + if len(failures) > 0 { + keys := reflect.ValueOf(failures).MapKeys() + lastKey := keys[len(keys)-1].String() + lastErr := failures[lastKey] + delete(failures, lastKey) - maxWorkers := shared.Parallelize("stop") - if c.GlobalIsSet("max-workers") { - maxWorkers = c.GlobalFlags.MaxWorks + for _, err := range failures { + outputError(err) + } + return lastErr } - logrus.Debugf("Setting maximum workers to %d", maxWorkers) - - stopErrors, errCount := shared.ParallelExecuteWorkerPool(maxWorkers, stopFuncs) - return printParallelOutput(stopErrors, errCount) + return nil } diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink index 618af3481..73e6c15f9 100644 --- a/cmd/podman/varlink/io.podman.varlink +++ b/cmd/podman/varlink/io.podman.varlink @@ -459,6 +459,11 @@ method ListContainers() -> (containers: []Container) # [InspectContainer](#InspectContainer). method GetContainer(id: string) -> (container: Container) +# GetContainersByContext allows you to get a list of container ids depending on all, latest, or a list of +# container names. The definition of latest container means the latest by creation date. In a multi- +# user environment, results might differ from what you expect. +method GetContainersByContext(all: bool, latest: bool, args: []string) -> (containers: []string) + # CreateContainer creates a new container from an image. It uses a [Create](#Create) type for input. The minimum # input required for CreateContainer is an image name. If the image name is not found, an [ImageNotFound](#ImageNotFound) # error will be returned. Otherwise, the ID of the newly created container will be returned. -- cgit v1.2.3-54-g00ecf