mirror of https://github.com/containers/podman.git
fix: improved "containers/{name}/wait" endpoint
Using event API to detect changes to container instead of polling. Polling was unreliable, sometime change of a state might have been missed. Signed-off-by: Matej Vasek <mvasek@redhat.com>
This commit is contained in:
parent
0ce6a65b39
commit
66e38ca55d
|
@ -7,6 +7,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/containers/podman/v3/libpod/events"
|
||||||
"github.com/containers/podman/v3/pkg/domain/entities"
|
"github.com/containers/podman/v3/pkg/domain/entities"
|
||||||
"github.com/containers/podman/v3/pkg/domain/infra/abi"
|
"github.com/containers/podman/v3/pkg/domain/infra/abi"
|
||||||
|
|
||||||
|
@ -175,7 +176,7 @@ func waitDockerCondition(ctx context.Context, containerName string, interval tim
|
||||||
var code int32
|
var code int32
|
||||||
switch dockerCondition {
|
switch dockerCondition {
|
||||||
case "next-exit":
|
case "next-exit":
|
||||||
code, err = waitNextExit(containerWait)
|
code, err = waitNextExit(ctx, containerName)
|
||||||
case "removed":
|
case "removed":
|
||||||
code, err = waitRemoved(containerWait)
|
code, err = waitRemoved(containerWait)
|
||||||
case "not-running", "":
|
case "not-running", "":
|
||||||
|
@ -202,12 +203,32 @@ func waitRemoved(ctrWait containerWaitFn) (int32, error) {
|
||||||
return code, err
|
return code, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func waitNextExit(ctrWait containerWaitFn) (int32, error) {
|
func waitNextExit(ctx context.Context, containerName string) (int32, error) {
|
||||||
_, err := ctrWait(define.ContainerStateRunning)
|
runtime := ctx.Value("runtime").(*libpod.Runtime)
|
||||||
if err != nil {
|
containerEngine := &abi.ContainerEngine{Libpod: runtime}
|
||||||
return -1, err
|
eventChannel := make(chan *events.Event)
|
||||||
|
errChannel := make(chan error)
|
||||||
|
opts := entities.EventsOptions{
|
||||||
|
EventChan: eventChannel,
|
||||||
|
Filter: []string{"event=died", fmt.Sprintf("container=%s", containerName)},
|
||||||
|
Stream: true,
|
||||||
}
|
}
|
||||||
return ctrWait(notRunningStates...)
|
|
||||||
|
// ctx is used to cancel event watching goroutine
|
||||||
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
defer cancel()
|
||||||
|
go func() {
|
||||||
|
errChannel <- containerEngine.Events(ctx, opts)
|
||||||
|
}()
|
||||||
|
|
||||||
|
evt, ok := <-eventChannel
|
||||||
|
if ok {
|
||||||
|
return int32(evt.ContainerExitCode), nil
|
||||||
|
}
|
||||||
|
// if ok == false then containerEngine.Events() has exited
|
||||||
|
// it may happen if request was canceled (e.g. client closed connection prematurely) or
|
||||||
|
// the server is in process of shutting down
|
||||||
|
return -1, <-errChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
func waitNotRunning(ctrWait containerWaitFn) (int32, error) {
|
func waitNotRunning(ctrWait containerWaitFn) (int32, error) {
|
||||||
|
|
|
@ -15,7 +15,7 @@ CTR="WaitTestingCtr"
|
||||||
|
|
||||||
t POST "containers/nonExistent/wait?condition=next-exit" 404
|
t POST "containers/nonExistent/wait?condition=next-exit" 404
|
||||||
|
|
||||||
podman create --name "${CTR}" --entrypoint '["sleep", "0.5"]' "${IMAGE}"
|
podman create --name "${CTR}" --entrypoint '["true"]' "${IMAGE}"
|
||||||
|
|
||||||
t POST "containers/${CTR}/wait?condition=non-existent-cond" 400
|
t POST "containers/${CTR}/wait?condition=non-existent-cond" 400
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue