service.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. package swarm
  2. import (
  3. "context"
  4. "runtime"
  5. "testing"
  6. "time"
  7. "github.com/docker/docker/api/types"
  8. "github.com/docker/docker/api/types/filters"
  9. swarmtypes "github.com/docker/docker/api/types/swarm"
  10. "github.com/docker/docker/internal/test/daemon"
  11. "github.com/docker/docker/internal/test/environment"
  12. "github.com/gotestyourself/gotestyourself/assert"
  13. "github.com/gotestyourself/gotestyourself/poll"
  14. "github.com/gotestyourself/gotestyourself/skip"
  15. )
  16. // ServicePoll tweaks the pollSettings for `service`
  17. func ServicePoll(config *poll.Settings) {
  18. // Override the default pollSettings for `service` resource here ...
  19. if runtime.GOARCH == "arm64" || runtime.GOARCH == "arm" {
  20. config.Timeout = 1 * time.Minute
  21. config.Delay = 100 * time.Millisecond
  22. }
  23. }
  24. // NetworkPoll tweaks the pollSettings for `network`
  25. func NetworkPoll(config *poll.Settings) {
  26. // Override the default pollSettings for `network` resource here ...
  27. config.Timeout = 30 * time.Second
  28. config.Delay = 100 * time.Millisecond
  29. if runtime.GOARCH == "arm64" || runtime.GOARCH == "arm" {
  30. config.Timeout = 50 * time.Second
  31. }
  32. }
  33. // ContainerPoll tweaks the pollSettings for `container`
  34. func ContainerPoll(config *poll.Settings) {
  35. // Override the default pollSettings for `container` resource here ...
  36. if runtime.GOARCH == "arm64" || runtime.GOARCH == "arm" {
  37. config.Timeout = 30 * time.Second
  38. config.Delay = 100 * time.Millisecond
  39. }
  40. }
  41. // NewSwarm creates a swarm daemon for testing
  42. func NewSwarm(t *testing.T, testEnv *environment.Execution, ops ...func(*daemon.Daemon)) *daemon.Daemon {
  43. skip.IfCondition(t, testEnv.IsRemoteDaemon())
  44. if testEnv.DaemonInfo.ExperimentalBuild {
  45. ops = append(ops, daemon.WithExperimental)
  46. }
  47. d := daemon.New(t, ops...)
  48. d.StartAndSwarmInit(t)
  49. return d
  50. }
  51. // ServiceSpecOpt is used with `CreateService` to pass in service spec modifiers
  52. type ServiceSpecOpt func(*swarmtypes.ServiceSpec)
  53. // CreateService creates a service on the passed in swarm daemon.
  54. func CreateService(t *testing.T, d *daemon.Daemon, opts ...ServiceSpecOpt) string {
  55. spec := defaultServiceSpec()
  56. for _, o := range opts {
  57. o(&spec)
  58. }
  59. client := d.NewClientT(t)
  60. defer client.Close()
  61. resp, err := client.ServiceCreate(context.Background(), spec, types.ServiceCreateOptions{})
  62. assert.NilError(t, err, "error creating service")
  63. return resp.ID
  64. }
  65. func defaultServiceSpec() swarmtypes.ServiceSpec {
  66. var spec swarmtypes.ServiceSpec
  67. ServiceWithImage("busybox:latest")(&spec)
  68. ServiceWithCommand([]string{"/bin/top"})(&spec)
  69. ServiceWithReplicas(1)(&spec)
  70. return spec
  71. }
  72. // ServiceWithImage sets the image to use for the service
  73. func ServiceWithImage(image string) func(*swarmtypes.ServiceSpec) {
  74. return func(spec *swarmtypes.ServiceSpec) {
  75. ensureContainerSpec(spec)
  76. spec.TaskTemplate.ContainerSpec.Image = image
  77. }
  78. }
  79. // ServiceWithCommand sets the command to use for the service
  80. func ServiceWithCommand(cmd []string) ServiceSpecOpt {
  81. return func(spec *swarmtypes.ServiceSpec) {
  82. ensureContainerSpec(spec)
  83. spec.TaskTemplate.ContainerSpec.Command = cmd
  84. }
  85. }
  86. // ServiceWithConfig adds the config reference to the service
  87. func ServiceWithConfig(configRef *swarmtypes.ConfigReference) ServiceSpecOpt {
  88. return func(spec *swarmtypes.ServiceSpec) {
  89. ensureContainerSpec(spec)
  90. spec.TaskTemplate.ContainerSpec.Configs = append(spec.TaskTemplate.ContainerSpec.Configs, configRef)
  91. }
  92. }
  93. // ServiceWithSecret adds the secret reference to the service
  94. func ServiceWithSecret(secretRef *swarmtypes.SecretReference) ServiceSpecOpt {
  95. return func(spec *swarmtypes.ServiceSpec) {
  96. ensureContainerSpec(spec)
  97. spec.TaskTemplate.ContainerSpec.Secrets = append(spec.TaskTemplate.ContainerSpec.Secrets, secretRef)
  98. }
  99. }
  100. // ServiceWithReplicas sets the replicas for the service
  101. func ServiceWithReplicas(n uint64) ServiceSpecOpt {
  102. return func(spec *swarmtypes.ServiceSpec) {
  103. spec.Mode = swarmtypes.ServiceMode{
  104. Replicated: &swarmtypes.ReplicatedService{
  105. Replicas: &n,
  106. },
  107. }
  108. }
  109. }
  110. // ServiceWithName sets the name of the service
  111. func ServiceWithName(name string) ServiceSpecOpt {
  112. return func(spec *swarmtypes.ServiceSpec) {
  113. spec.Annotations.Name = name
  114. }
  115. }
  116. // GetRunningTasks gets the list of running tasks for a service
  117. func GetRunningTasks(t *testing.T, d *daemon.Daemon, serviceID string) []swarmtypes.Task {
  118. client := d.NewClientT(t)
  119. defer client.Close()
  120. filterArgs := filters.NewArgs()
  121. filterArgs.Add("desired-state", "running")
  122. filterArgs.Add("service", serviceID)
  123. options := types.TaskListOptions{
  124. Filters: filterArgs,
  125. }
  126. tasks, err := client.TaskList(context.Background(), options)
  127. assert.NilError(t, err)
  128. return tasks
  129. }
  130. // ExecTask runs the passed in exec config on the given task
  131. func ExecTask(t *testing.T, d *daemon.Daemon, task swarmtypes.Task, config types.ExecConfig) types.HijackedResponse {
  132. client := d.NewClientT(t)
  133. defer client.Close()
  134. ctx := context.Background()
  135. resp, err := client.ContainerExecCreate(ctx, task.Status.ContainerStatus.ContainerID, config)
  136. assert.NilError(t, err, "error creating exec")
  137. startCheck := types.ExecStartCheck{}
  138. attach, err := client.ContainerExecAttach(ctx, resp.ID, startCheck)
  139. assert.NilError(t, err, "error attaching to exec")
  140. return attach
  141. }
  142. func ensureContainerSpec(spec *swarmtypes.ServiceSpec) {
  143. if spec.TaskTemplate.ContainerSpec == nil {
  144. spec.TaskTemplate.ContainerSpec = &swarmtypes.ContainerSpec{}
  145. }
  146. }