create_test.go 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. package service
  2. import (
  3. "runtime"
  4. "testing"
  5. "time"
  6. "github.com/docker/docker/api/types"
  7. "github.com/docker/docker/api/types/filters"
  8. "github.com/docker/docker/api/types/swarm"
  9. "github.com/docker/docker/client"
  10. "github.com/docker/docker/integration-cli/request"
  11. "github.com/gotestyourself/gotestyourself/poll"
  12. "github.com/stretchr/testify/assert"
  13. "github.com/stretchr/testify/require"
  14. "golang.org/x/net/context"
  15. )
  16. func TestCreateServiceMultipleTimes(t *testing.T) {
  17. defer setupTest(t)()
  18. d := newSwarm(t)
  19. defer d.Stop(t)
  20. client, err := request.NewClientForHost(d.Sock())
  21. require.NoError(t, err)
  22. overlayName := "overlay1"
  23. networkCreate := types.NetworkCreate{
  24. CheckDuplicate: true,
  25. Driver: "overlay",
  26. }
  27. netResp, err := client.NetworkCreate(context.Background(), overlayName, networkCreate)
  28. require.NoError(t, err)
  29. overlayID := netResp.ID
  30. var instances uint64 = 4
  31. serviceSpec := swarmServiceSpec("TestService", instances)
  32. serviceSpec.TaskTemplate.Networks = append(serviceSpec.TaskTemplate.Networks, swarm.NetworkAttachmentConfig{Target: overlayName})
  33. serviceResp, err := client.ServiceCreate(context.Background(), serviceSpec, types.ServiceCreateOptions{
  34. QueryRegistry: false,
  35. })
  36. require.NoError(t, err)
  37. pollSettings := func(config *poll.Settings) {
  38. // It takes about ~25s to finish the multi services creation in this case per the pratical observation on arm64/arm platform
  39. if runtime.GOARCH == "arm64" || runtime.GOARCH == "arm" {
  40. config.Timeout = 30 * time.Second
  41. config.Delay = 100 * time.Millisecond
  42. }
  43. }
  44. serviceID := serviceResp.ID
  45. poll.WaitOn(t, serviceRunningTasksCount(client, serviceID, instances), pollSettings)
  46. _, _, err = client.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{})
  47. require.NoError(t, err)
  48. err = client.ServiceRemove(context.Background(), serviceID)
  49. require.NoError(t, err)
  50. poll.WaitOn(t, serviceIsRemoved(client, serviceID), pollSettings)
  51. poll.WaitOn(t, noTasks(client), pollSettings)
  52. serviceResp, err = client.ServiceCreate(context.Background(), serviceSpec, types.ServiceCreateOptions{
  53. QueryRegistry: false,
  54. })
  55. require.NoError(t, err)
  56. serviceID2 := serviceResp.ID
  57. poll.WaitOn(t, serviceRunningTasksCount(client, serviceID2, instances), pollSettings)
  58. err = client.ServiceRemove(context.Background(), serviceID2)
  59. require.NoError(t, err)
  60. poll.WaitOn(t, serviceIsRemoved(client, serviceID2), pollSettings)
  61. poll.WaitOn(t, noTasks(client), pollSettings)
  62. err = client.NetworkRemove(context.Background(), overlayID)
  63. require.NoError(t, err)
  64. poll.WaitOn(t, networkIsRemoved(client, overlayID), poll.WithTimeout(1*time.Minute), poll.WithDelay(10*time.Second))
  65. }
  66. func TestCreateWithDuplicateNetworkNames(t *testing.T) {
  67. defer setupTest(t)()
  68. d := newSwarm(t)
  69. defer d.Stop(t)
  70. client, err := request.NewClientForHost(d.Sock())
  71. require.NoError(t, err)
  72. name := "foo"
  73. networkCreate := types.NetworkCreate{
  74. CheckDuplicate: false,
  75. Driver: "bridge",
  76. }
  77. n1, err := client.NetworkCreate(context.Background(), name, networkCreate)
  78. require.NoError(t, err)
  79. n2, err := client.NetworkCreate(context.Background(), name, networkCreate)
  80. require.NoError(t, err)
  81. // Dupliates with name but with different driver
  82. networkCreate.Driver = "overlay"
  83. n3, err := client.NetworkCreate(context.Background(), name, networkCreate)
  84. require.NoError(t, err)
  85. // Create Service with the same name
  86. var instances uint64 = 1
  87. serviceSpec := swarmServiceSpec("top", instances)
  88. serviceSpec.TaskTemplate.Networks = append(serviceSpec.TaskTemplate.Networks, swarm.NetworkAttachmentConfig{Target: name})
  89. service, err := client.ServiceCreate(context.Background(), serviceSpec, types.ServiceCreateOptions{})
  90. require.NoError(t, err)
  91. poll.WaitOn(t, serviceRunningTasksCount(client, service.ID, instances))
  92. resp, _, err := client.ServiceInspectWithRaw(context.Background(), service.ID, types.ServiceInspectOptions{})
  93. require.NoError(t, err)
  94. assert.Equal(t, n3.ID, resp.Spec.TaskTemplate.Networks[0].Target)
  95. // Remove Service
  96. err = client.ServiceRemove(context.Background(), service.ID)
  97. require.NoError(t, err)
  98. // Make sure task has been destroyed.
  99. poll.WaitOn(t, serviceIsRemoved(client, service.ID))
  100. // Remove networks
  101. err = client.NetworkRemove(context.Background(), n3.ID)
  102. require.NoError(t, err)
  103. err = client.NetworkRemove(context.Background(), n2.ID)
  104. require.NoError(t, err)
  105. err = client.NetworkRemove(context.Background(), n1.ID)
  106. require.NoError(t, err)
  107. // Make sure networks have been destroyed.
  108. poll.WaitOn(t, networkIsRemoved(client, n3.ID), poll.WithTimeout(1*time.Minute), poll.WithDelay(10*time.Second))
  109. poll.WaitOn(t, networkIsRemoved(client, n2.ID), poll.WithTimeout(1*time.Minute), poll.WithDelay(10*time.Second))
  110. poll.WaitOn(t, networkIsRemoved(client, n1.ID), poll.WithTimeout(1*time.Minute), poll.WithDelay(10*time.Second))
  111. }
  112. func swarmServiceSpec(name string, replicas uint64) swarm.ServiceSpec {
  113. return swarm.ServiceSpec{
  114. Annotations: swarm.Annotations{
  115. Name: name,
  116. },
  117. TaskTemplate: swarm.TaskSpec{
  118. ContainerSpec: &swarm.ContainerSpec{
  119. Image: "busybox:latest",
  120. Command: []string{"/bin/top"},
  121. },
  122. },
  123. Mode: swarm.ServiceMode{
  124. Replicated: &swarm.ReplicatedService{
  125. Replicas: &replicas,
  126. },
  127. },
  128. }
  129. }
  130. func serviceRunningTasksCount(client client.ServiceAPIClient, serviceID string, instances uint64) func(log poll.LogT) poll.Result {
  131. return func(log poll.LogT) poll.Result {
  132. filter := filters.NewArgs()
  133. filter.Add("service", serviceID)
  134. tasks, err := client.TaskList(context.Background(), types.TaskListOptions{
  135. Filters: filter,
  136. })
  137. switch {
  138. case err != nil:
  139. return poll.Error(err)
  140. case len(tasks) == int(instances):
  141. for _, task := range tasks {
  142. if task.Status.State != swarm.TaskStateRunning {
  143. return poll.Continue("waiting for tasks to enter run state")
  144. }
  145. }
  146. return poll.Success()
  147. default:
  148. return poll.Continue("task count at %d waiting for %d", len(tasks), instances)
  149. }
  150. }
  151. }
  152. func noTasks(client client.ServiceAPIClient) func(log poll.LogT) poll.Result {
  153. return func(log poll.LogT) poll.Result {
  154. filter := filters.NewArgs()
  155. tasks, err := client.TaskList(context.Background(), types.TaskListOptions{
  156. Filters: filter,
  157. })
  158. switch {
  159. case err != nil:
  160. return poll.Error(err)
  161. case len(tasks) == 0:
  162. return poll.Success()
  163. default:
  164. return poll.Continue("task count at %d waiting for 0", len(tasks))
  165. }
  166. }
  167. }
  168. func serviceIsRemoved(client client.ServiceAPIClient, serviceID string) func(log poll.LogT) poll.Result {
  169. return func(log poll.LogT) poll.Result {
  170. filter := filters.NewArgs()
  171. filter.Add("service", serviceID)
  172. _, err := client.TaskList(context.Background(), types.TaskListOptions{
  173. Filters: filter,
  174. })
  175. if err == nil {
  176. return poll.Continue("waiting for service %s to be deleted", serviceID)
  177. }
  178. return poll.Success()
  179. }
  180. }
  181. func networkIsRemoved(client client.NetworkAPIClient, networkID string) func(log poll.LogT) poll.Result {
  182. return func(log poll.LogT) poll.Result {
  183. _, err := client.NetworkInspect(context.Background(), networkID, types.NetworkInspectOptions{})
  184. if err == nil {
  185. return poll.Continue("waiting for network %s to be removed", networkID)
  186. }
  187. return poll.Success()
  188. }
  189. }