summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJhon Honce <jhonce@redhat.com>2019-03-04 17:21:23 -0700
committerJhon Honce <jhonce@redhat.com>2019-03-06 10:32:01 -0700
commit8a6758d5fdaba9e6ec58eeb23ee5123762c18b72 (patch)
tree4273a61b912797dc6cb4d27fb6743c5367a1dfa8
parentc6c0b54c361df623378706ca5e41faac309ab7ac (diff)
downloadpodman-8a6758d5fdaba9e6ec58eeb23ee5123762c18b72.tar.gz
podman-8a6758d5fdaba9e6ec58eeb23ee5123762c18b72.tar.bz2
podman-8a6758d5fdaba9e6ec58eeb23ee5123762c18b72.zip
Implement podman-remote wait command and container subcommand
Signed-off-by: Jhon Honce <jhonce@redhat.com>
-rwxr-xr-xAPI.md10
-rw-r--r--cmd/podman/commands.go1
-rw-r--r--cmd/podman/main.go1
-rw-r--r--cmd/podman/varlink/io.podman.varlink8
-rw-r--r--cmd/podman/wait.go53
-rw-r--r--pkg/adapter/containers.go24
-rw-r--r--pkg/adapter/containers_remote.go26
-rw-r--r--pkg/varlinkapi/containers.go5
8 files changed, 85 insertions, 43 deletions
diff --git a/API.md b/API.md
index d255037c1..fc0361195 100755
--- a/API.md
+++ b/API.md
@@ -143,7 +143,7 @@ in the [API.md](https://github.com/containers/libpod/blob/master/API.md) file in
[func VolumesPrune() []string, []string](#VolumesPrune)
-[func WaitContainer(name: string) int](#WaitContainer)
+[func WaitContainer(name: string, interval: int) int](#WaitContainer)
[type BuildInfo](#BuildInfo)
@@ -1013,10 +1013,10 @@ VolumesPrune removes unused volumes on the host
### <a name="WaitContainer"></a>func WaitContainer
<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;">
-method WaitContainer(name: [string](https://godoc.org/builtin#string)) [int](https://godoc.org/builtin#int)</div>
-WaitContainer takes the name or ID of a container and waits until the container stops. Upon stopping, the return
-code of the container is returned. If the container container cannot be found by ID or name,
-a [ContainerNotFound](#ContainerNotFound) error is returned.
+method WaitContainer(name: [string](https://godoc.org/builtin#string), interval: [int](https://godoc.org/builtin#int)) [int](https://godoc.org/builtin#int)</div>
+WaitContainer takes the name or ID of a container and waits the given interval in milliseconds until the container
+stops. Upon stopping, the return code of the container is returned. If the container container cannot be found by ID
+or name, a [ContainerNotFound](#ContainerNotFound) error is returned.
## Types
### <a name="BuildInfo"></a>type BuildInfo
diff --git a/cmd/podman/commands.go b/cmd/podman/commands.go
index 150413970..c59db024b 100644
--- a/cmd/podman/commands.go
+++ b/cmd/podman/commands.go
@@ -35,7 +35,6 @@ func getMainCommands() []*cobra.Command {
_topCommand,
_umountCommand,
_unpauseCommand,
- _waitCommand,
}
if len(_varlinkCommand.Use) > 0 {
diff --git a/cmd/podman/main.go b/cmd/podman/main.go
index b3faf05c0..97ffa8930 100644
--- a/cmd/podman/main.go
+++ b/cmd/podman/main.go
@@ -52,6 +52,7 @@ var mainCommands = []*cobra.Command{
_stopCommand,
_tagCommand,
_versionCommand,
+ _waitCommand,
imageCommand.Command,
systemCommand.Command,
}
diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink
index 73e6c15f9..296b20ed1 100644
--- a/cmd/podman/varlink/io.podman.varlink
+++ b/cmd/podman/varlink/io.podman.varlink
@@ -617,10 +617,10 @@ method UnpauseContainer(name: string) -> (container: string)
# ~~~
method GetAttachSockets(name: string) -> (sockets: Sockets)
-# WaitContainer takes the name or ID of a container and waits until the container stops. Upon stopping, the return
-# code of the container is returned. If the container container cannot be found by ID or name,
-# a [ContainerNotFound](#ContainerNotFound) error is returned.
-method WaitContainer(name: string) -> (exitcode: int)
+# WaitContainer takes the name or ID of a container and waits the given interval in milliseconds until the container
+# stops. Upon stopping, the return code of the container is returned. If the container container cannot be found by ID
+# or name, a [ContainerNotFound](#ContainerNotFound) error is returned.
+method WaitContainer(name: string, interval: int) -> (exitcode: int)
# RemoveContainer requires the name or ID of container as well a boolean representing whether a running container can be stopped and removed, and a boolean
# indicating whether to remove builtin volumes. Upon successful removal of the
diff --git a/cmd/podman/wait.go b/cmd/podman/wait.go
index 9df2e3208..6c2a8c9ff 100644
--- a/cmd/podman/wait.go
+++ b/cmd/podman/wait.go
@@ -2,11 +2,11 @@ package main
import (
"fmt"
- "os"
+ "reflect"
"time"
"github.com/containers/libpod/cmd/podman/cliconfig"
- "github.com/containers/libpod/cmd/podman/libpodruntime"
+ "github.com/containers/libpod/pkg/adapter"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@@ -49,43 +49,36 @@ func waitCmd(c *cliconfig.WaitValues) error {
return errors.Errorf("you must provide at least one container name or id")
}
- runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
+ if c.Interval == 0 {
+ return errors.Errorf("interval must be greater then 0")
+ }
+ interval := time.Duration(c.Interval) * time.Millisecond
+
+ runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil {
- return errors.Wrapf(err, "error creating libpod runtime")
+ return errors.Wrapf(err, "error creating runtime")
}
defer runtime.Shutdown(false)
+ ok, failures, err := runtime.WaitOnContainers(getContext(), c, interval)
if err != nil {
- return errors.Wrapf(err, "could not get config")
+ return err
}
- var lastError error
- if c.Latest {
- latestCtr, err := runtime.GetLatestContainer()
- if err != nil {
- return errors.Wrapf(err, "unable to wait on latest container")
- }
- args = append(args, latestCtr.ID())
+ for _, id := range ok {
+ fmt.Println(id)
}
- for _, container := range args {
- ctr, err := runtime.LookupContainer(container)
- if err != nil {
- return errors.Wrapf(err, "unable to find container %s", container)
- }
- if c.Interval == 0 {
- return errors.Errorf("interval must be greater then 0")
- }
- returnCode, err := ctr.WaitWithInterval(time.Duration(c.Interval) * time.Millisecond)
- if err != nil {
- if lastError != nil {
- fmt.Fprintln(os.Stderr, lastError)
- }
- lastError = errors.Wrapf(err, "failed to wait for the container %v", container)
- } else {
- fmt.Println(returnCode)
+ if len(failures) > 0 {
+ keys := reflect.ValueOf(failures).MapKeys()
+ lastKey := keys[len(keys)-1].String()
+ lastErr := failures[lastKey]
+ delete(failures, lastKey)
+
+ for _, err := range failures {
+ outputError(err)
}
+ return lastErr
}
-
- return lastError
+ return nil
}
diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go
index fcce9bb86..756369196 100644
--- a/pkg/adapter/containers.go
+++ b/pkg/adapter/containers.go
@@ -4,7 +4,9 @@ package adapter
import (
"context"
+ "strconv"
"syscall"
+ "time"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod"
@@ -103,3 +105,25 @@ func (r *LocalRuntime) KillContainers(ctx context.Context, cli *cliconfig.KillVa
}
return ok, failures, nil
}
+
+// WaitOnContainers waits for all given container(s) to stop
+func (r *LocalRuntime) WaitOnContainers(ctx context.Context, cli *cliconfig.WaitValues, interval time.Duration) ([]string, map[string]error, error) {
+ var (
+ ok = []string{}
+ failures = map[string]error{}
+ )
+
+ ctrs, err := shortcuts.GetContainersByContext(false, cli.Latest, cli.InputArgs, r.Runtime)
+ if err != nil {
+ return ok, failures, err
+ }
+
+ for _, c := range ctrs {
+ if returnCode, err := c.WaitWithInterval(interval); err == nil {
+ ok = append(ok, strconv.Itoa(int(returnCode)))
+ } else {
+ failures[c.ID()] = err
+ }
+ }
+ return ok, failures, err
+}
diff --git a/pkg/adapter/containers_remote.go b/pkg/adapter/containers_remote.go
index 45926ccf9..5646d2297 100644
--- a/pkg/adapter/containers_remote.go
+++ b/pkg/adapter/containers_remote.go
@@ -6,7 +6,9 @@ import (
"context"
"encoding/json"
"errors"
+ "strconv"
"syscall"
+ "time"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/shared"
@@ -173,6 +175,30 @@ func (r *LocalRuntime) KillContainers(ctx context.Context, cli *cliconfig.KillVa
return ok, failures, nil
}
+// WaitOnContainers waits for all given container(s) to stop.
+// interval is currently ignored.
+func (r *LocalRuntime) WaitOnContainers(ctx context.Context, cli *cliconfig.WaitValues, interval time.Duration) ([]string, map[string]error, error) {
+ var (
+ ok = []string{}
+ failures = map[string]error{}
+ )
+
+ ids, err := iopodman.GetContainersByContext().Call(r.Conn, false, cli.Latest, cli.InputArgs)
+ if err != nil {
+ return ok, failures, err
+ }
+
+ for _, id := range ids {
+ stopped, err := iopodman.WaitContainer().Call(r.Conn, id, int64(interval))
+ if err != nil {
+ failures[id] = err
+ } else {
+ ok = append(ok, strconv.FormatInt(stopped, 10))
+ }
+ }
+ 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
diff --git a/pkg/varlinkapi/containers.go b/pkg/varlinkapi/containers.go
index 27b8d15d2..9934ca0cc 100644
--- a/pkg/varlinkapi/containers.go
+++ b/pkg/varlinkapi/containers.go
@@ -360,17 +360,16 @@ func (i *LibpodAPI) UnpauseContainer(call iopodman.VarlinkCall, name string) err
}
// WaitContainer ...
-func (i *LibpodAPI) WaitContainer(call iopodman.VarlinkCall, name string) error {
+func (i *LibpodAPI) WaitContainer(call iopodman.VarlinkCall, name string, interval int64) error {
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
return call.ReplyContainerNotFound(name, err.Error())
}
- exitCode, err := ctr.Wait()
+ exitCode, err := ctr.WaitWithInterval(time.Duration(interval))
if err != nil {
return call.ReplyErrorOccurred(err.Error())
}
return call.ReplyWaitContainer(int64(exitCode))
-
}
// RemoveContainer ...