wait: add --ignore option

In the recent past, I met the frequent need to wait for a container to
exist that, at the same time, may get removed (e.g., system tests in [1]).

Add an `--ignore` option to podman-wait which will ignore errors when a
specified container is missing and mark its exit code as -1.  Also
remove ID fields from the WaitReport.  It is actually not used by
callers and removing it makes the code simpler and faster.

Once merged, we can go over the tests and simplify them.

[1] github.com/containers/podman/pull/16852

Signed-off-by: Valentin Rothberg <vrothberg@redhat.com>
This commit is contained in:
Valentin Rothberg
2022-12-15 14:24:33 +01:00
parent 18f1a8046b
commit f4d0496b54
6 changed files with 50 additions and 16 deletions

View File

@ -53,6 +53,8 @@ func waitFlags(cmd *cobra.Command) {
flags.StringVarP(&waitInterval, intervalFlagName, "i", "250ms", "Time Interval to wait before polling for completion")
_ = cmd.RegisterFlagCompletionFunc(intervalFlagName, completion.AutocompleteNone)
flags.BoolVarP(&waitOptions.Ignore, "ignore", "", false, "Ignore if a container does not exist")
conditionFlagName := "condition"
flags.StringSliceVar(&waitConditions, conditionFlagName, []string{}, "Condition to wait on")
_ = cmd.RegisterFlagCompletionFunc(conditionFlagName, common.AutocompleteWaitCondition)

View File

@ -23,6 +23,10 @@ Condition to wait on (default "stopped")
Print usage statement
#### **--ignore**
Ignore errors when a specified container is missing and mark its return code as -1.
#### **--interval**, **-i**=*duration*
Time interval to wait before polling for completion. A duration string is a sequence of decimal numbers, each with optional fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m". Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". Time unit defaults to "ms".
@ -46,6 +50,9 @@ $ podman wait 860a4b23
$ podman wait mywebserver myftpserver
0
125
$ podman wait --ignore does-not-exist
-1
```
## SEE ALSO

View File

@ -52,11 +52,11 @@ type ContainerRunlabelReport struct{}
type WaitOptions struct {
Condition []define.ContainerStatus
Interval time.Duration
Ignore bool
Latest bool
}
type WaitReport struct {
Id string //nolint:revive,stylecheck
Error error
ExitCode int32
}

View File

@ -139,13 +139,29 @@ func (ic *ContainerEngine) ContainerExists(ctx context.Context, nameOrID string,
}
func (ic *ContainerEngine) ContainerWait(ctx context.Context, namesOrIds []string, options entities.WaitOptions) ([]entities.WaitReport, error) {
ctrs, err := getContainersByContext(false, options.Latest, false, namesOrIds, ic.Libpod)
if err != nil {
return nil, err
responses := make([]entities.WaitReport, 0, len(namesOrIds))
if options.Latest {
ctr, err := ic.Libpod.GetLatestContainer()
if err != nil {
if options.Ignore && errors.Is(err, define.ErrNoSuchCtr) {
responses = append(responses, entities.WaitReport{ExitCode: -1})
return responses, nil
}
return nil, err
}
namesOrIds = append(namesOrIds, ctr.ID())
}
responses := make([]entities.WaitReport, 0, len(ctrs))
for _, c := range ctrs {
response := entities.WaitReport{Id: c.ID()}
for _, n := range namesOrIds {
c, err := ic.Libpod.LookupContainer(n)
if err != nil {
if options.Ignore && errors.Is(err, define.ErrNoSuchCtr) {
responses = append(responses, entities.WaitReport{ExitCode: -1})
continue
}
return nil, err
}
response := entities.WaitReport{}
if options.Condition == nil {
options.Condition = []define.ContainerStatus{define.ContainerStateStopped, define.ContainerStateExited}
}

View File

@ -38,17 +38,17 @@ func (ic *ContainerEngine) ContainerExists(ctx context.Context, nameOrID string,
}
func (ic *ContainerEngine) ContainerWait(ctx context.Context, namesOrIds []string, opts entities.WaitOptions) ([]entities.WaitReport, error) {
cons, err := getContainersByContext(ic.ClientCtx, false, false, namesOrIds)
if err != nil {
return nil, err
}
responses := make([]entities.WaitReport, 0, len(cons))
responses := make([]entities.WaitReport, 0, len(namesOrIds))
options := new(containers.WaitOptions).WithCondition(opts.Condition).WithInterval(opts.Interval.String())
for _, c := range cons {
response := entities.WaitReport{Id: c.ID}
exitCode, err := containers.Wait(ic.ClientCtx, c.ID, options)
for _, n := range namesOrIds {
response := entities.WaitReport{}
exitCode, err := containers.Wait(ic.ClientCtx, n, options)
if err != nil {
response.Error = err
if opts.Ignore && errorhandling.Contains(err, define.ErrNoSuchCtr) {
response.ExitCode = -1
} else {
response.Error = err
}
} else {
response.ExitCode = exitCode
}

View File

@ -20,6 +20,15 @@ load helpers
run_podman rm $rand
is "$output" "$rand" "display raw input"
run_podman 125 inspect $rand
run_podman 125 wait $rand
run_podman wait --ignore $rand
is "$output" "-1" "wait --ignore will mark missing containers with -1"
if !is_remote; then
# remote does not support the --latest flag
run_podman wait --ignore --latest
is "$output" "-1" "wait --ignore will mark missing containers with -1"
fi
}
@test "podman rm - running container, w/o and w/ force" {