mirror of
https://github.com/containers/podman.git
synced 2025-07-17 17:43:23 +08:00
rework apiv2 wait endpoint|binding
added the ability to wait on a condition (stopped, running, paused...) for a container. if a condition is not provided, wait will default to the stopped condition which uses the original wait code paths. if the condition is stopped, the container exit code will be returned. also, correct a mux issue we discovered. Signed-off-by: Brent Baude <bbaude@redhat.com>
This commit is contained in:
@ -629,6 +629,26 @@ func (c *Container) WaitWithInterval(waitTimeout time.Duration) (int32, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Container) WaitForConditionWithInterval(waitTimeout time.Duration, condition define.ContainerStatus) (int32, error) {
|
||||||
|
if !c.valid {
|
||||||
|
return -1, define.ErrCtrRemoved
|
||||||
|
}
|
||||||
|
if condition == define.ContainerStateStopped || condition == define.ContainerStateExited {
|
||||||
|
return c.WaitWithInterval(waitTimeout)
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
state, err := c.State()
|
||||||
|
if err != nil {
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
if state == condition {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
time.Sleep(waitTimeout)
|
||||||
|
}
|
||||||
|
return -1, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Cleanup unmounts all mount points in container and cleans up container storage
|
// Cleanup unmounts all mount points in container and cleans up container storage
|
||||||
// It also cleans up the network stack
|
// It also cleans up the network stack
|
||||||
func (c *Container) Cleanup(ctx context.Context) error {
|
func (c *Container) Cleanup(ctx context.Context) error {
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
"github.com/containers/libpod/libpod"
|
"github.com/containers/libpod/libpod"
|
||||||
"github.com/containers/libpod/libpod/define"
|
"github.com/containers/libpod/libpod/define"
|
||||||
"github.com/containers/libpod/pkg/api/handlers/utils"
|
"github.com/containers/libpod/pkg/api/handlers/utils"
|
||||||
"github.com/gorilla/mux"
|
|
||||||
"github.com/gorilla/schema"
|
"github.com/gorilla/schema"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
@ -179,7 +178,7 @@ func RestartContainer(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
timeout := con.StopTimeout()
|
timeout := con.StopTimeout()
|
||||||
if _, found := mux.Vars(r)["t"]; found {
|
if _, found := r.URL.Query()["t"]; found {
|
||||||
timeout = uint(query.Timeout)
|
timeout = uint(query.Timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@ import (
|
|||||||
"github.com/containers/libpod/libpod"
|
"github.com/containers/libpod/libpod"
|
||||||
"github.com/containers/libpod/libpod/define"
|
"github.com/containers/libpod/libpod/define"
|
||||||
"github.com/containers/libpod/pkg/api/handlers/utils"
|
"github.com/containers/libpod/pkg/api/handlers/utils"
|
||||||
"github.com/gorilla/mux"
|
|
||||||
"github.com/gorilla/schema"
|
"github.com/gorilla/schema"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
@ -30,12 +29,10 @@ func AttachContainer(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
muxVars := mux.Vars(r)
|
|
||||||
|
|
||||||
// Detach keys: explicitly set to "" is very different from unset
|
// Detach keys: explicitly set to "" is very different from unset
|
||||||
// TODO: Our format for parsing these may be different from Docker.
|
// TODO: Our format for parsing these may be different from Docker.
|
||||||
var detachKeys *string
|
var detachKeys *string
|
||||||
if _, found := muxVars["detachKeys"]; found {
|
if _, found := r.URL.Query()["detachKeys"]; found {
|
||||||
detachKeys = &query.DetachKeys
|
detachKeys = &query.DetachKeys
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,15 +41,15 @@ func AttachContainer(w http.ResponseWriter, r *http.Request) {
|
|||||||
streams.Stderr = true
|
streams.Stderr = true
|
||||||
streams.Stdin = true
|
streams.Stdin = true
|
||||||
useStreams := false
|
useStreams := false
|
||||||
if _, found := muxVars["stdin"]; found {
|
if _, found := r.URL.Query()["stdin"]; found {
|
||||||
streams.Stdin = query.Stdin
|
streams.Stdin = query.Stdin
|
||||||
useStreams = true
|
useStreams = true
|
||||||
}
|
}
|
||||||
if _, found := muxVars["stdout"]; found {
|
if _, found := r.URL.Query()["stdout"]; found {
|
||||||
streams.Stdout = query.Stdout
|
streams.Stdout = query.Stdout
|
||||||
useStreams = true
|
useStreams = true
|
||||||
}
|
}
|
||||||
if _, found := muxVars["stderr"]; found {
|
if _, found := r.URL.Query()["stderr"]; found {
|
||||||
streams.Stderr = query.Stderr
|
streams.Stderr = query.Stderr
|
||||||
useStreams = true
|
useStreams = true
|
||||||
}
|
}
|
||||||
@ -72,7 +69,7 @@ func AttachContainer(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
// We only support stream=true or unset
|
// We only support stream=true or unset
|
||||||
if _, found := muxVars["stream"]; found && query.Stream {
|
if _, found := r.URL.Query()["stream"]; found && query.Stream {
|
||||||
utils.Error(w, "Unsupported parameter", http.StatusBadRequest, errors.Errorf("the stream parameter to attach is not presently supported"))
|
utils.Error(w, "Unsupported parameter", http.StatusBadRequest, errors.Errorf("the stream parameter to attach is not presently supported"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,6 @@ import (
|
|||||||
"github.com/containers/libpod/pkg/api/handlers"
|
"github.com/containers/libpod/pkg/api/handlers"
|
||||||
"github.com/containers/libpod/pkg/api/handlers/utils"
|
"github.com/containers/libpod/pkg/api/handlers/utils"
|
||||||
"github.com/containers/libpod/pkg/util"
|
"github.com/containers/libpod/pkg/util"
|
||||||
"github.com/gorilla/mux"
|
|
||||||
"github.com/gorilla/schema"
|
"github.com/gorilla/schema"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
@ -71,7 +70,7 @@ func ListContainers(w http.ResponseWriter, r *http.Request) {
|
|||||||
utils.InternalServerError(w, err)
|
utils.InternalServerError(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if _, found := mux.Vars(r)["limit"]; found {
|
if _, found := r.URL.Query()["limit"]; found {
|
||||||
last := query.Limit
|
last := query.Limit
|
||||||
if len(containers) > last {
|
if len(containers) > last {
|
||||||
containers = containers[len(containers)-last:]
|
containers = containers[len(containers)-last:]
|
||||||
@ -136,7 +135,7 @@ func WaitContainer(w http.ResponseWriter, r *http.Request) {
|
|||||||
// /{version}/containers/(name)/wait
|
// /{version}/containers/(name)/wait
|
||||||
exitCode, err := utils.WaitContainer(w, r)
|
exitCode, err := utils.WaitContainer(w, r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg = err.Error()
|
return
|
||||||
}
|
}
|
||||||
utils.WriteResponse(w, http.StatusOK, handlers.ContainerWaitOKBody{
|
utils.WriteResponse(w, http.StatusOK, handlers.ContainerWaitOKBody{
|
||||||
StatusCode: int(exitCode),
|
StatusCode: int(exitCode),
|
||||||
@ -191,7 +190,7 @@ func LogsFromContainer(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var since time.Time
|
var since time.Time
|
||||||
if _, found := mux.Vars(r)["since"]; found {
|
if _, found := r.URL.Query()["since"]; found {
|
||||||
since, err = util.ParseInputTime(query.Since)
|
since, err = util.ParseInputTime(query.Since)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.BadRequest(w, "since", query.Since, err)
|
utils.BadRequest(w, "since", query.Since, err)
|
||||||
@ -200,7 +199,7 @@ func LogsFromContainer(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var until time.Time
|
var until time.Time
|
||||||
if _, found := mux.Vars(r)["until"]; found {
|
if _, found := r.URL.Query()["until"]; found {
|
||||||
since, err = util.ParseInputTime(query.Until)
|
since, err = util.ParseInputTime(query.Until)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.BadRequest(w, "until", query.Until, err)
|
utils.BadRequest(w, "until", query.Until, err)
|
||||||
@ -233,7 +232,7 @@ func LogsFromContainer(w http.ResponseWriter, r *http.Request) {
|
|||||||
var builder strings.Builder
|
var builder strings.Builder
|
||||||
for ok := true; ok; ok = query.Follow {
|
for ok := true; ok; ok = query.Follow {
|
||||||
for line := range logChannel {
|
for line := range logChannel {
|
||||||
if _, found := mux.Vars(r)["until"]; found {
|
if _, found := r.URL.Query()["until"]; found {
|
||||||
if line.Time.After(until) {
|
if line.Time.After(until) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,6 @@ import (
|
|||||||
"github.com/containers/libpod/libpod"
|
"github.com/containers/libpod/libpod"
|
||||||
"github.com/containers/libpod/libpod/image"
|
"github.com/containers/libpod/libpod/image"
|
||||||
"github.com/containers/libpod/pkg/api/handlers/utils"
|
"github.com/containers/libpod/pkg/api/handlers/utils"
|
||||||
"github.com/gorilla/mux"
|
|
||||||
"github.com/gorilla/schema"
|
"github.com/gorilla/schema"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
@ -87,8 +86,7 @@ func RemoveImage(w http.ResponseWriter, r *http.Request) {
|
|||||||
utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String()))
|
utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
muxVars := mux.Vars(r)
|
if _, found := r.URL.Query()["noprune"]; found {
|
||||||
if _, found := muxVars["noprune"]; found {
|
|
||||||
if query.noPrune {
|
if query.noPrune {
|
||||||
utils.UnSupportedParameter("noprune")
|
utils.UnSupportedParameter("noprune")
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,6 @@ import (
|
|||||||
"github.com/containers/buildah/imagebuildah"
|
"github.com/containers/buildah/imagebuildah"
|
||||||
"github.com/containers/libpod/pkg/api/handlers/utils"
|
"github.com/containers/libpod/pkg/api/handlers/utils"
|
||||||
"github.com/containers/storage/pkg/archive"
|
"github.com/containers/storage/pkg/archive"
|
||||||
"github.com/gorilla/mux"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func BuildImage(w http.ResponseWriter, r *http.Request) {
|
func BuildImage(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -114,24 +113,24 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
|
|||||||
tag = tokens[1]
|
tag = tokens[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
if t, found := mux.Vars(r)["target"]; found {
|
if _, found := r.URL.Query()["target"]; found {
|
||||||
name = t
|
name = query.Target
|
||||||
}
|
}
|
||||||
|
|
||||||
var buildArgs = map[string]string{}
|
var buildArgs = map[string]string{}
|
||||||
if a, found := mux.Vars(r)["buildargs"]; found {
|
if _, found := r.URL.Query()["buildargs"]; found {
|
||||||
if err := json.Unmarshal([]byte(a), &buildArgs); err != nil {
|
if err := json.Unmarshal([]byte(query.BuildArgs), &buildArgs); err != nil {
|
||||||
utils.BadRequest(w, "buildargs", a, err)
|
utils.BadRequest(w, "buildargs", query.BuildArgs, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert label formats
|
// convert label formats
|
||||||
var labels = []string{}
|
var labels = []string{}
|
||||||
if l, found := mux.Vars(r)["labels"]; found {
|
if _, found := r.URL.Query()["labels"]; found {
|
||||||
var m = map[string]string{}
|
var m = map[string]string{}
|
||||||
if err := json.Unmarshal([]byte(l), &m); err != nil {
|
if err := json.Unmarshal([]byte(query.Labels), &m); err != nil {
|
||||||
utils.BadRequest(w, "labels", l, err)
|
utils.BadRequest(w, "labels", query.Labels, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,7 +140,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pullPolicy := buildah.PullIfMissing
|
pullPolicy := buildah.PullIfMissing
|
||||||
if _, found := mux.Vars(r)["pull"]; found {
|
if _, found := r.URL.Query()["pull"]; found {
|
||||||
if query.Pull {
|
if query.Pull {
|
||||||
pullPolicy = buildah.PullAlways
|
pullPolicy = buildah.PullAlways
|
||||||
}
|
}
|
||||||
|
@ -178,7 +178,6 @@ func KillContainer(w http.ResponseWriter, r *http.Request) {
|
|||||||
func WaitContainer(w http.ResponseWriter, r *http.Request) {
|
func WaitContainer(w http.ResponseWriter, r *http.Request) {
|
||||||
exitCode, err := utils.WaitContainer(w, r)
|
exitCode, err := utils.WaitContainer(w, r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.InternalServerError(w, err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
utils.WriteResponse(w, http.StatusOK, strconv.Itoa(int(exitCode)))
|
utils.WriteResponse(w, http.StatusOK, strconv.Itoa(int(exitCode)))
|
||||||
|
@ -13,7 +13,6 @@ import (
|
|||||||
"github.com/containers/libpod/pkg/api/handlers"
|
"github.com/containers/libpod/pkg/api/handlers"
|
||||||
"github.com/containers/libpod/pkg/api/handlers/utils"
|
"github.com/containers/libpod/pkg/api/handlers/utils"
|
||||||
"github.com/containers/libpod/pkg/util"
|
"github.com/containers/libpod/pkg/util"
|
||||||
"github.com/gorilla/mux"
|
|
||||||
"github.com/gorilla/schema"
|
"github.com/gorilla/schema"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
@ -353,7 +352,7 @@ func PodKill(w http.ResponseWriter, r *http.Request) {
|
|||||||
signal = "SIGKILL"
|
signal = "SIGKILL"
|
||||||
)
|
)
|
||||||
query := struct {
|
query := struct {
|
||||||
signal string `schema:"signal"`
|
Signal string `schema:"signal"`
|
||||||
}{
|
}{
|
||||||
// override any golang type defaults
|
// override any golang type defaults
|
||||||
}
|
}
|
||||||
@ -362,9 +361,8 @@ func PodKill(w http.ResponseWriter, r *http.Request) {
|
|||||||
errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String()))
|
errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
muxVars := mux.Vars(r)
|
if _, found := r.URL.Query()["signal"]; found {
|
||||||
if _, found := muxVars["signal"]; found {
|
signal = query.Signal
|
||||||
signal = query.signal
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sig, err := util.ParseSignal(signal)
|
sig, err := util.ParseSignal(signal)
|
||||||
|
@ -78,9 +78,12 @@ func RemoveContainer(w http.ResponseWriter, r *http.Request, force, vols bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func WaitContainer(w http.ResponseWriter, r *http.Request) (int32, error) {
|
func WaitContainer(w http.ResponseWriter, r *http.Request) (int32, error) {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
interval time.Duration
|
||||||
|
)
|
||||||
runtime := r.Context().Value("runtime").(*libpod.Runtime)
|
runtime := r.Context().Value("runtime").(*libpod.Runtime)
|
||||||
decoder := r.Context().Value("decoder").(*schema.Decoder)
|
decoder := r.Context().Value("decoder").(*schema.Decoder)
|
||||||
// /{version}/containers/(name)/restart
|
|
||||||
query := struct {
|
query := struct {
|
||||||
Interval string `schema:"interval"`
|
Interval string `schema:"interval"`
|
||||||
Condition string `schema:"condition"`
|
Condition string `schema:"condition"`
|
||||||
@ -91,25 +94,34 @@ func WaitContainer(w http.ResponseWriter, r *http.Request) (int32, error) {
|
|||||||
Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String()))
|
Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String()))
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
if _, found := r.URL.Query()["interval"]; found {
|
||||||
if len(query.Condition) > 0 {
|
interval, err = time.ParseDuration(query.Interval)
|
||||||
UnSupportedParameter("condition")
|
if err != nil {
|
||||||
|
InternalServerError(w, err)
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
interval, err = time.ParseDuration("250ms")
|
||||||
|
if err != nil {
|
||||||
|
InternalServerError(w, err)
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
condition := define.ContainerStateStopped
|
||||||
|
if _, found := r.URL.Query()["condition"]; found {
|
||||||
|
condition, err = define.StringToContainerStatus(query.Condition)
|
||||||
|
if err != nil {
|
||||||
|
InternalServerError(w, err)
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
name := GetName(r)
|
name := GetName(r)
|
||||||
con, err := runtime.LookupContainer(name)
|
con, err := runtime.LookupContainer(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ContainerNotFound(w, name, err)
|
ContainerNotFound(w, name, err)
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
if len(query.Interval) > 0 {
|
return con.WaitForConditionWithInterval(interval, condition)
|
||||||
d, err := time.ParseDuration(query.Interval)
|
|
||||||
if err != nil {
|
|
||||||
Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "Failed to parse %s for interval", query.Interval))
|
|
||||||
}
|
|
||||||
return con.WaitWithInterval(d)
|
|
||||||
}
|
|
||||||
return con.Wait()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateFilterFuncsFromMap is used to generate un-executed functions that can be used to filter
|
// GenerateFilterFuncsFromMap is used to generate un-executed functions that can be used to filter
|
||||||
|
@ -6,7 +6,6 @@ import (
|
|||||||
|
|
||||||
"github.com/containers/libpod/libpod"
|
"github.com/containers/libpod/libpod"
|
||||||
"github.com/containers/libpod/libpod/image"
|
"github.com/containers/libpod/libpod/image"
|
||||||
"github.com/gorilla/mux"
|
|
||||||
"github.com/gorilla/schema"
|
"github.com/gorilla/schema"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -28,7 +27,7 @@ func GetImages(w http.ResponseWriter, r *http.Request) ([]*image.Image, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var filters = []string{}
|
var filters = []string{}
|
||||||
if _, found := mux.Vars(r)["digests"]; found && query.Digests {
|
if _, found := r.URL.Query()["digests"]; found && query.Digests {
|
||||||
UnSupportedParameter("digests")
|
UnSupportedParameter("digests")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,8 +436,8 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error {
|
|||||||
// ---
|
// ---
|
||||||
// tags:
|
// tags:
|
||||||
// - containers (compat)
|
// - containers (compat)
|
||||||
// summary: Wait on a container to exit
|
// summary: Wait on a container
|
||||||
// description: Block until a container stops, then returns the exit code.
|
// description: Block until a container stops or given condition is met.
|
||||||
// parameters:
|
// parameters:
|
||||||
// - in: path
|
// - in: path
|
||||||
// name: name
|
// name: name
|
||||||
@ -447,7 +447,14 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error {
|
|||||||
// - in: query
|
// - in: query
|
||||||
// name: condition
|
// name: condition
|
||||||
// type: string
|
// type: string
|
||||||
// description: not supported
|
// description: |
|
||||||
|
// wait until container is to a given condition. default is stopped. valid conditions are:
|
||||||
|
// - configured
|
||||||
|
// - created
|
||||||
|
// - exited
|
||||||
|
// - paused
|
||||||
|
// - running
|
||||||
|
// - stopped
|
||||||
// produces:
|
// produces:
|
||||||
// - application/json
|
// - application/json
|
||||||
// responses:
|
// responses:
|
||||||
@ -1030,18 +1037,30 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error {
|
|||||||
// ---
|
// ---
|
||||||
// tags:
|
// tags:
|
||||||
// - containers
|
// - containers
|
||||||
// summary: Wait on a container to exit
|
// summary: Wait on a container
|
||||||
|
// description: Wait on a container to met a given condition
|
||||||
// parameters:
|
// parameters:
|
||||||
// - in: path
|
// - in: path
|
||||||
// name: name
|
// name: name
|
||||||
// type: string
|
// type: string
|
||||||
// required: true
|
// required: true
|
||||||
// description: the name or ID of the container
|
// description: the name or ID of the container
|
||||||
|
// - in: query
|
||||||
|
// name: condition
|
||||||
|
// type: string
|
||||||
|
// description: |
|
||||||
|
// wait until container is to a given condition. default is stopped. valid conditions are:
|
||||||
|
// - configured
|
||||||
|
// - created
|
||||||
|
// - exited
|
||||||
|
// - paused
|
||||||
|
// - running
|
||||||
|
// - stopped
|
||||||
// produces:
|
// produces:
|
||||||
// - application/json
|
// - application/json
|
||||||
// responses:
|
// responses:
|
||||||
// 204:
|
// 200:
|
||||||
// description: no error
|
// $ref: "#/responses/ContainerWaitResponse"
|
||||||
// 404:
|
// 404:
|
||||||
// $ref: "#/responses/NoSuchContainer"
|
// $ref: "#/responses/NoSuchContainer"
|
||||||
// 500:
|
// 500:
|
||||||
|
@ -210,15 +210,20 @@ func Unpause(ctx context.Context, nameOrID string) error {
|
|||||||
return response.Process(nil)
|
return response.Process(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait blocks until the given container exits and returns its exit code. The nameOrID can be a container name
|
// Wait blocks until the given container reaches a condition. If not provided, the condition will
|
||||||
// or a partial/full ID.
|
// default to stopped. If the condition is stopped, an exit code for the container will be provided. The
|
||||||
func Wait(ctx context.Context, nameOrID string) (int32, error) {
|
// nameOrID can be a container name or a partial/full ID.
|
||||||
|
func Wait(ctx context.Context, nameOrID string, condition *string) (int32, error) {
|
||||||
var exitCode int32
|
var exitCode int32
|
||||||
conn, err := bindings.GetClient(ctx)
|
conn, err := bindings.GetClient(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return exitCode, err
|
return exitCode, err
|
||||||
}
|
}
|
||||||
response, err := conn.DoRequest(nil, http.MethodPost, "containers/%s/wait", nil, nameOrID)
|
params := url.Values{}
|
||||||
|
if condition != nil {
|
||||||
|
params.Set("condition", *condition)
|
||||||
|
}
|
||||||
|
response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/wait", params, nameOrID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return exitCode, err
|
return exitCode, err
|
||||||
}
|
}
|
||||||
|
@ -250,4 +250,61 @@ var _ = Describe("Podman containers ", func() {
|
|||||||
Expect(data.State.Status).To(Equal("exited"))
|
Expect(data.State.Status).To(Equal("exited"))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("podman wait no condition", func() {
|
||||||
|
var (
|
||||||
|
name = "top"
|
||||||
|
exitCode int32 = -1
|
||||||
|
)
|
||||||
|
_, err := containers.Wait(connText, "foobar", nil)
|
||||||
|
Expect(err).ToNot(BeNil())
|
||||||
|
code, _ := bindings.CheckResponseCode(err)
|
||||||
|
Expect(code).To(BeNumerically("==", http.StatusNotFound))
|
||||||
|
|
||||||
|
errChan := make(chan error)
|
||||||
|
bt.RunTopContainer(&name, nil, nil)
|
||||||
|
go func() {
|
||||||
|
exitCode, err = containers.Wait(connText, name, nil)
|
||||||
|
errChan <- err
|
||||||
|
close(errChan)
|
||||||
|
}()
|
||||||
|
err = containers.Stop(connText, name, nil)
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
wait := <-errChan
|
||||||
|
Expect(wait).To(BeNil())
|
||||||
|
Expect(exitCode).To(BeNumerically("==", 143))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("podman wait to pause|unpause condition", func() {
|
||||||
|
var (
|
||||||
|
name = "top"
|
||||||
|
exitCode int32 = -1
|
||||||
|
pause = "paused"
|
||||||
|
unpause = "running"
|
||||||
|
)
|
||||||
|
errChan := make(chan error)
|
||||||
|
bt.RunTopContainer(&name, nil, nil)
|
||||||
|
go func() {
|
||||||
|
exitCode, err = containers.Wait(connText, name, &pause)
|
||||||
|
errChan <- err
|
||||||
|
close(errChan)
|
||||||
|
}()
|
||||||
|
err := containers.Pause(connText, name)
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
wait := <-errChan
|
||||||
|
Expect(wait).To(BeNil())
|
||||||
|
Expect(exitCode).To(BeNumerically("==", -1))
|
||||||
|
|
||||||
|
errChan = make(chan error)
|
||||||
|
go func() {
|
||||||
|
exitCode, err = containers.Wait(connText, name, &unpause)
|
||||||
|
errChan <- err
|
||||||
|
close(errChan)
|
||||||
|
}()
|
||||||
|
err = containers.Unpause(connText, name)
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
unPausewait := <-errChan
|
||||||
|
Expect(unPausewait).To(BeNil())
|
||||||
|
Expect(exitCode).To(BeNumerically("==", -1))
|
||||||
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user