list_test.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. package service // import "github.com/docker/docker/integration/service"
  2. import (
  3. "context"
  4. "fmt"
  5. "testing"
  6. "github.com/docker/docker/api/types"
  7. "github.com/docker/docker/api/types/filters"
  8. swarmtypes "github.com/docker/docker/api/types/swarm"
  9. "github.com/docker/docker/api/types/versions"
  10. "github.com/docker/docker/integration/internal/swarm"
  11. "gotest.tools/v3/assert"
  12. is "gotest.tools/v3/assert/cmp"
  13. "gotest.tools/v3/poll"
  14. "gotest.tools/v3/skip"
  15. )
  16. // TestServiceListWithStatuses tests that performing a ServiceList operation
  17. // correctly uses the Status parameter, and that the resulting response
  18. // contains correct service statuses.
  19. //
  20. // NOTE(dperny): because it's a pain to elicit the behavior of an unconverged
  21. // service reliably, I'm not testing that an unconverged service returns X
  22. // running and Y desired tasks. Instead, I'm just going to trust that I can
  23. // successfully assign a value to another value without screwing it up. The
  24. // logic for computing service statuses is in swarmkit anyway, not in the
  25. // engine, and is well-tested there, so this test just needs to make sure that
  26. // statuses get correctly associated with the right services.
  27. func TestServiceListWithStatuses(t *testing.T) {
  28. skip.If(t, testEnv.IsRemoteDaemon)
  29. skip.If(t, testEnv.DaemonInfo.OSType == "windows")
  30. // statuses were added in API version 1.41
  31. skip.If(t, versions.LessThan(testEnv.DaemonInfo.ServerVersion, "1.41"))
  32. defer setupTest(t)()
  33. d := swarm.NewSwarm(t, testEnv)
  34. defer d.Stop(t)
  35. client := d.NewClientT(t)
  36. defer client.Close()
  37. ctx := context.Background()
  38. serviceCount := 3
  39. // create some services.
  40. for i := 0; i < serviceCount; i++ {
  41. spec := fullSwarmServiceSpec(fmt.Sprintf("test-list-%d", i), uint64(i+1))
  42. // for whatever reason, the args "-u root", when included, cause these
  43. // tasks to fail and exit. instead, we'll just pass no args, which
  44. // works.
  45. spec.TaskTemplate.ContainerSpec.Args = []string{}
  46. resp, err := client.ServiceCreate(ctx, spec, types.ServiceCreateOptions{
  47. QueryRegistry: false,
  48. })
  49. assert.NilError(t, err)
  50. id := resp.ID
  51. // we need to wait specifically for the tasks to be running, which the
  52. // serviceContainerCount function does not do. instead, we'll use a
  53. // bespoke closure right here.
  54. poll.WaitOn(t, func(log poll.LogT) poll.Result {
  55. tasks, err := client.TaskList(context.Background(), types.TaskListOptions{
  56. Filters: filters.NewArgs(filters.Arg("service", id)),
  57. })
  58. running := 0
  59. for _, task := range tasks {
  60. if task.Status.State == swarmtypes.TaskStateRunning {
  61. running++
  62. }
  63. }
  64. switch {
  65. case err != nil:
  66. return poll.Error(err)
  67. case running == i+1:
  68. return poll.Success()
  69. default:
  70. return poll.Continue(
  71. "running task count %d (%d total), waiting for %d",
  72. running, len(tasks), i+1,
  73. )
  74. }
  75. })
  76. }
  77. // now, let's do the list operation with no status arg set.
  78. resp, err := client.ServiceList(ctx, types.ServiceListOptions{})
  79. assert.NilError(t, err)
  80. assert.Check(t, is.Len(resp, serviceCount))
  81. for _, service := range resp {
  82. assert.Check(t, is.Nil(service.ServiceStatus))
  83. }
  84. // now try again, but with Status: true. This time, we should have statuses
  85. resp, err = client.ServiceList(ctx, types.ServiceListOptions{Status: true})
  86. assert.NilError(t, err)
  87. assert.Check(t, is.Len(resp, serviceCount))
  88. for _, service := range resp {
  89. replicas := *service.Spec.Mode.Replicated.Replicas
  90. assert.Assert(t, service.ServiceStatus != nil)
  91. // Use assert.Check to not fail out of the test if this fails
  92. assert.Check(t, is.Equal(service.ServiceStatus.DesiredTasks, replicas))
  93. assert.Check(t, is.Equal(service.ServiceStatus.RunningTasks, replicas))
  94. }
  95. }