inspect_test.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. package service
  2. import (
  3. "fmt"
  4. "testing"
  5. "time"
  6. "github.com/docker/docker/api/types"
  7. "github.com/docker/docker/api/types/container"
  8. "github.com/docker/docker/api/types/filters"
  9. "github.com/docker/docker/api/types/swarm"
  10. "github.com/docker/docker/client"
  11. "github.com/docker/docker/integration-cli/daemon"
  12. "github.com/docker/docker/integration-cli/request"
  13. "github.com/gotestyourself/gotestyourself/poll"
  14. "github.com/gotestyourself/gotestyourself/skip"
  15. "github.com/stretchr/testify/assert"
  16. "github.com/stretchr/testify/require"
  17. "golang.org/x/net/context"
  18. )
  19. func TestInspect(t *testing.T) {
  20. skip.IfCondition(t, !testEnv.IsLocalDaemon())
  21. defer setupTest(t)()
  22. d := newSwarm(t)
  23. defer d.Stop(t)
  24. client, err := request.NewClientForHost(d.Sock())
  25. require.NoError(t, err)
  26. var before = time.Now()
  27. var instances uint64 = 2
  28. serviceSpec := fullSwarmServiceSpec("test-service-inspect", instances)
  29. ctx := context.Background()
  30. resp, err := client.ServiceCreate(ctx, serviceSpec, types.ServiceCreateOptions{
  31. QueryRegistry: false,
  32. })
  33. require.NoError(t, err)
  34. id := resp.ID
  35. poll.WaitOn(t, serviceContainerCount(client, id, instances))
  36. service, _, err := client.ServiceInspectWithRaw(ctx, id, types.ServiceInspectOptions{})
  37. require.NoError(t, err)
  38. assert.Equal(t, serviceSpec, service.Spec)
  39. assert.Equal(t, uint64(11), service.Meta.Version.Index)
  40. assert.Equal(t, id, service.ID)
  41. assert.WithinDuration(t, before, service.CreatedAt, 30*time.Second)
  42. assert.WithinDuration(t, before, service.UpdatedAt, 30*time.Second)
  43. }
  44. func fullSwarmServiceSpec(name string, replicas uint64) swarm.ServiceSpec {
  45. restartDelay := 100 * time.Millisecond
  46. maxAttempts := uint64(4)
  47. return swarm.ServiceSpec{
  48. Annotations: swarm.Annotations{
  49. Name: name,
  50. Labels: map[string]string{
  51. "service-label": "service-label-value",
  52. },
  53. },
  54. TaskTemplate: swarm.TaskSpec{
  55. ContainerSpec: &swarm.ContainerSpec{
  56. Image: "busybox:latest",
  57. Labels: map[string]string{"container-label": "container-value"},
  58. Command: []string{"/bin/top"},
  59. Args: []string{"-u", "root"},
  60. Hostname: "hostname",
  61. Env: []string{"envvar=envvalue"},
  62. Dir: "/work",
  63. User: "root",
  64. StopSignal: "SIGINT",
  65. StopGracePeriod: &restartDelay,
  66. Hosts: []string{"8.8.8.8 google"},
  67. DNSConfig: &swarm.DNSConfig{
  68. Nameservers: []string{"8.8.8.8"},
  69. Search: []string{"somedomain"},
  70. },
  71. Isolation: container.IsolationDefault,
  72. },
  73. RestartPolicy: &swarm.RestartPolicy{
  74. Delay: &restartDelay,
  75. Condition: swarm.RestartPolicyConditionOnFailure,
  76. MaxAttempts: &maxAttempts,
  77. },
  78. Runtime: swarm.RuntimeContainer,
  79. },
  80. Mode: swarm.ServiceMode{
  81. Replicated: &swarm.ReplicatedService{
  82. Replicas: &replicas,
  83. },
  84. },
  85. UpdateConfig: &swarm.UpdateConfig{
  86. Parallelism: 2,
  87. Delay: 200 * time.Second,
  88. FailureAction: swarm.UpdateFailureActionContinue,
  89. Monitor: 2 * time.Second,
  90. MaxFailureRatio: 0.2,
  91. Order: swarm.UpdateOrderStopFirst,
  92. },
  93. RollbackConfig: &swarm.UpdateConfig{
  94. Parallelism: 3,
  95. Delay: 300 * time.Second,
  96. FailureAction: swarm.UpdateFailureActionPause,
  97. Monitor: 3 * time.Second,
  98. MaxFailureRatio: 0.3,
  99. Order: swarm.UpdateOrderStartFirst,
  100. },
  101. }
  102. }
  103. const defaultSwarmPort = 2477
  104. func newSwarm(t *testing.T) *daemon.Swarm {
  105. d := &daemon.Swarm{
  106. Daemon: daemon.New(t, "", dockerdBinary, daemon.Config{
  107. Experimental: testEnv.DaemonInfo.ExperimentalBuild,
  108. }),
  109. // TODO: better method of finding an unused port
  110. Port: defaultSwarmPort,
  111. }
  112. // TODO: move to a NewSwarm constructor
  113. d.ListenAddr = fmt.Sprintf("0.0.0.0:%d", d.Port)
  114. // avoid networking conflicts
  115. args := []string{"--iptables=false", "--swarm-default-advertise-addr=lo"}
  116. d.StartWithBusybox(t, args...)
  117. require.NoError(t, d.Init(swarm.InitRequest{}))
  118. return d
  119. }
  120. func serviceContainerCount(client client.ServiceAPIClient, id string, count uint64) func(log poll.LogT) poll.Result {
  121. return func(log poll.LogT) poll.Result {
  122. filter := filters.NewArgs()
  123. filter.Add("service", id)
  124. tasks, err := client.TaskList(context.Background(), types.TaskListOptions{
  125. Filters: filter,
  126. })
  127. switch {
  128. case err != nil:
  129. return poll.Error(err)
  130. case len(tasks) == int(count):
  131. return poll.Success()
  132. default:
  133. return poll.Continue("task count at %d waiting for %d", len(tasks), count)
  134. }
  135. }
  136. }