container_wait.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. package client
  2. import (
  3. "encoding/json"
  4. "net/url"
  5. "golang.org/x/net/context"
  6. "github.com/docker/docker/api/types/container"
  7. "github.com/docker/docker/api/types/versions"
  8. )
  9. // ContainerWait waits until the specified container is in a certain state
  10. // indicated by the given condition, either "not-running" (default),
  11. // "next-exit", or "removed".
  12. //
  13. // If this client's API version is beforer 1.30, condition is ignored and
  14. // ContainerWait will return immediately with the two channels, as the server
  15. // will wait as if the condition were "not-running".
  16. //
  17. // If this client's API version is at least 1.30, ContainerWait blocks until
  18. // the request has been acknowledged by the server (with a response header),
  19. // then returns two channels on which the caller can wait for the exit status
  20. // of the container or an error if there was a problem either beginning the
  21. // wait request or in getting the response. This allows the caller to
  22. // sychronize ContainerWait with other calls, such as specifying a
  23. // "next-exit" condition before issuing a ContainerStart request.
  24. func (cli *Client) ContainerWait(ctx context.Context, containerID string, condition container.WaitCondition) (<-chan container.ContainerWaitOKBody, <-chan error) {
  25. if versions.LessThan(cli.ClientVersion(), "1.30") {
  26. return cli.legacyContainerWait(ctx, containerID)
  27. }
  28. resultC := make(chan container.ContainerWaitOKBody)
  29. errC := make(chan error, 1)
  30. query := url.Values{}
  31. query.Set("condition", string(condition))
  32. resp, err := cli.post(ctx, "/containers/"+containerID+"/wait", query, nil, nil)
  33. if err != nil {
  34. defer ensureReaderClosed(resp)
  35. errC <- err
  36. return resultC, errC
  37. }
  38. go func() {
  39. defer ensureReaderClosed(resp)
  40. var res container.ContainerWaitOKBody
  41. if err := json.NewDecoder(resp.body).Decode(&res); err != nil {
  42. errC <- err
  43. return
  44. }
  45. resultC <- res
  46. }()
  47. return resultC, errC
  48. }
  49. // legacyContainerWait returns immediately and doesn't have an option to wait
  50. // until the container is removed.
  51. func (cli *Client) legacyContainerWait(ctx context.Context, containerID string) (<-chan container.ContainerWaitOKBody, <-chan error) {
  52. resultC := make(chan container.ContainerWaitOKBody)
  53. errC := make(chan error)
  54. go func() {
  55. resp, err := cli.post(ctx, "/containers/"+containerID+"/wait", nil, nil, nil)
  56. if err != nil {
  57. errC <- err
  58. return
  59. }
  60. defer ensureReaderClosed(resp)
  61. var res container.ContainerWaitOKBody
  62. if err := json.NewDecoder(resp.body).Decode(&res); err != nil {
  63. errC <- err
  64. return
  65. }
  66. resultC <- res
  67. }()
  68. return resultC, errC
  69. }