summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatej Vasek <mvasek@redhat.com>2021-05-07 22:35:20 +0200
committerMatej Vasek <mvasek@redhat.com>2021-05-10 13:40:06 +0200
commit66e38ca55d9a0079eb7d317b5a70c2623fc90d20 (patch)
tree3ea45c42923ca1954d9e8e01297c75114a0f4d4c
parent0ce6a65b3961465593470c3457d75b0a846c8d98 (diff)
downloadpodman-66e38ca55d9a0079eb7d317b5a70c2623fc90d20.tar.gz
podman-66e38ca55d9a0079eb7d317b5a70c2623fc90d20.tar.bz2
podman-66e38ca55d9a0079eb7d317b5a70c2623fc90d20.zip
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>
-rw-r--r--pkg/api/handlers/utils/containers.go35
-rw-r--r--test/apiv2/26-containersWait.at2
2 files changed, 29 insertions, 8 deletions
diff --git a/pkg/api/handlers/utils/containers.go b/pkg/api/handlers/utils/containers.go
index c4c9cc2ea..6c708f74e 100644
--- a/pkg/api/handlers/utils/containers.go
+++ b/pkg/api/handlers/utils/containers.go
@@ -7,6 +7,7 @@ import (
"strconv"
"time"
+ "github.com/containers/podman/v3/libpod/events"
"github.com/containers/podman/v3/pkg/domain/entities"
"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
switch dockerCondition {
case "next-exit":
- code, err = waitNextExit(containerWait)
+ code, err = waitNextExit(ctx, containerName)
case "removed":
code, err = waitRemoved(containerWait)
case "not-running", "":
@@ -202,12 +203,32 @@ func waitRemoved(ctrWait containerWaitFn) (int32, error) {
return code, err
}
-func waitNextExit(ctrWait containerWaitFn) (int32, error) {
- _, err := ctrWait(define.ContainerStateRunning)
- if err != nil {
- return -1, err
- }
- return ctrWait(notRunningStates...)
+func waitNextExit(ctx context.Context, containerName string) (int32, error) {
+ runtime := ctx.Value("runtime").(*libpod.Runtime)
+ containerEngine := &abi.ContainerEngine{Libpod: runtime}
+ 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,
+ }
+
+ // 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) {
diff --git a/test/apiv2/26-containersWait.at b/test/apiv2/26-containersWait.at
index 6a628e55a..ec16c35df 100644
--- a/test/apiv2/26-containersWait.at
+++ b/test/apiv2/26-containersWait.at
@@ -15,7 +15,7 @@ CTR="WaitTestingCtr"
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