states.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. package swarm
  2. import (
  3. "context"
  4. "github.com/docker/docker/api/types"
  5. "github.com/docker/docker/api/types/filters"
  6. swarmtypes "github.com/docker/docker/api/types/swarm"
  7. "github.com/docker/docker/client"
  8. "gotest.tools/poll"
  9. )
  10. // NoTasksForService verifies that there are no more tasks for the given service
  11. func NoTasksForService(ctx context.Context, client client.ServiceAPIClient, serviceID string) func(log poll.LogT) poll.Result {
  12. return func(log poll.LogT) poll.Result {
  13. tasks, err := client.TaskList(ctx, types.TaskListOptions{
  14. Filters: filters.NewArgs(
  15. filters.Arg("service", serviceID),
  16. ),
  17. })
  18. if err == nil {
  19. if len(tasks) == 0 {
  20. return poll.Success()
  21. }
  22. if len(tasks) > 0 {
  23. return poll.Continue("task count for service %s at %d waiting for 0", serviceID, len(tasks))
  24. }
  25. return poll.Continue("waiting for tasks for service %s to be deleted", serviceID)
  26. }
  27. // TODO we should not use an error as indication that the tasks are gone. There may be other reasons for an error to occur.
  28. return poll.Success()
  29. }
  30. }
  31. // NoTasks verifies that all tasks are gone
  32. func NoTasks(ctx context.Context, client client.ServiceAPIClient) func(log poll.LogT) poll.Result {
  33. return func(log poll.LogT) poll.Result {
  34. tasks, err := client.TaskList(ctx, types.TaskListOptions{})
  35. switch {
  36. case err != nil:
  37. return poll.Error(err)
  38. case len(tasks) == 0:
  39. return poll.Success()
  40. default:
  41. return poll.Continue("waiting for all tasks to be removed: task count at %d", len(tasks))
  42. }
  43. }
  44. }
  45. // RunningTasksCount verifies there are `instances` tasks running for `serviceID`
  46. func RunningTasksCount(client client.ServiceAPIClient, serviceID string, instances uint64) func(log poll.LogT) poll.Result {
  47. return func(log poll.LogT) poll.Result {
  48. filter := filters.NewArgs()
  49. filter.Add("service", serviceID)
  50. tasks, err := client.TaskList(context.Background(), types.TaskListOptions{
  51. Filters: filter,
  52. })
  53. var running int
  54. var taskError string
  55. for _, task := range tasks {
  56. switch task.Status.State {
  57. case swarmtypes.TaskStateRunning:
  58. running++
  59. case swarmtypes.TaskStateFailed:
  60. if task.Status.Err != "" {
  61. taskError = task.Status.Err
  62. }
  63. }
  64. }
  65. switch {
  66. case err != nil:
  67. return poll.Error(err)
  68. case running > int(instances):
  69. return poll.Continue("waiting for tasks to terminate")
  70. case running < int(instances) && taskError != "":
  71. return poll.Continue("waiting for tasks to enter run state. task failed with error: %s", taskError)
  72. case running == int(instances):
  73. return poll.Success()
  74. default:
  75. return poll.Continue("running task count at %d waiting for %d (total tasks: %d)", running, instances, len(tasks))
  76. }
  77. }
  78. }