update_test.go 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. package service // import "github.com/docker/docker/integration/service"
  2. import (
  3. "context"
  4. "testing"
  5. "github.com/docker/docker/api/types"
  6. swarmtypes "github.com/docker/docker/api/types/swarm"
  7. "github.com/docker/docker/client"
  8. "github.com/docker/docker/integration/internal/network"
  9. "github.com/docker/docker/integration/internal/swarm"
  10. "gotest.tools/assert"
  11. is "gotest.tools/assert/cmp"
  12. "gotest.tools/poll"
  13. "gotest.tools/skip"
  14. )
  15. func TestServiceUpdateLabel(t *testing.T) {
  16. skip.If(t, testEnv.DaemonInfo.OSType != "linux")
  17. defer setupTest(t)()
  18. d := swarm.NewSwarm(t, testEnv)
  19. defer d.Stop(t)
  20. cli := d.NewClientT(t)
  21. defer cli.Close()
  22. ctx := context.Background()
  23. serviceName := "TestService_" + t.Name()
  24. serviceID := swarm.CreateService(t, d, swarm.ServiceWithName(serviceName))
  25. service := getService(t, cli, serviceID)
  26. assert.Check(t, is.DeepEqual(service.Spec.Labels, map[string]string{}))
  27. // add label to empty set
  28. service.Spec.Labels["foo"] = "bar"
  29. _, err := cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{})
  30. assert.NilError(t, err)
  31. poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll)
  32. service = getService(t, cli, serviceID)
  33. assert.Check(t, is.DeepEqual(service.Spec.Labels, map[string]string{"foo": "bar"}))
  34. // add label to non-empty set
  35. service.Spec.Labels["foo2"] = "bar"
  36. _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{})
  37. assert.NilError(t, err)
  38. poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll)
  39. service = getService(t, cli, serviceID)
  40. assert.Check(t, is.DeepEqual(service.Spec.Labels, map[string]string{"foo": "bar", "foo2": "bar"}))
  41. delete(service.Spec.Labels, "foo2")
  42. _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{})
  43. assert.NilError(t, err)
  44. poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll)
  45. service = getService(t, cli, serviceID)
  46. assert.Check(t, is.DeepEqual(service.Spec.Labels, map[string]string{"foo": "bar"}))
  47. delete(service.Spec.Labels, "foo")
  48. _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{})
  49. assert.NilError(t, err)
  50. poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll)
  51. service = getService(t, cli, serviceID)
  52. assert.Check(t, is.DeepEqual(service.Spec.Labels, map[string]string{}))
  53. // now make sure we can add again
  54. service.Spec.Labels["foo"] = "bar"
  55. _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{})
  56. assert.NilError(t, err)
  57. poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll)
  58. service = getService(t, cli, serviceID)
  59. assert.Check(t, is.DeepEqual(service.Spec.Labels, map[string]string{"foo": "bar"}))
  60. err = cli.ServiceRemove(context.Background(), serviceID)
  61. assert.NilError(t, err)
  62. }
  63. func TestServiceUpdateSecrets(t *testing.T) {
  64. skip.If(t, testEnv.DaemonInfo.OSType != "linux")
  65. defer setupTest(t)()
  66. d := swarm.NewSwarm(t, testEnv)
  67. defer d.Stop(t)
  68. cli := d.NewClientT(t)
  69. defer cli.Close()
  70. ctx := context.Background()
  71. secretName := "TestSecret_" + t.Name()
  72. secretTarget := "targetName"
  73. resp, err := cli.SecretCreate(ctx, swarmtypes.SecretSpec{
  74. Annotations: swarmtypes.Annotations{
  75. Name: secretName,
  76. },
  77. Data: []byte("TESTINGDATA"),
  78. })
  79. assert.NilError(t, err)
  80. assert.Check(t, resp.ID != "")
  81. serviceName := "TestService_" + t.Name()
  82. serviceID := swarm.CreateService(t, d, swarm.ServiceWithName(serviceName))
  83. service := getService(t, cli, serviceID)
  84. // add secret
  85. service.Spec.TaskTemplate.ContainerSpec.Secrets = append(service.Spec.TaskTemplate.ContainerSpec.Secrets,
  86. &swarmtypes.SecretReference{
  87. File: &swarmtypes.SecretReferenceFileTarget{
  88. Name: secretTarget,
  89. UID: "0",
  90. GID: "0",
  91. Mode: 0600,
  92. },
  93. SecretID: resp.ID,
  94. SecretName: secretName,
  95. },
  96. )
  97. _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{})
  98. assert.NilError(t, err)
  99. poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll)
  100. service = getService(t, cli, serviceID)
  101. secrets := service.Spec.TaskTemplate.ContainerSpec.Secrets
  102. assert.Assert(t, is.Equal(1, len(secrets)))
  103. secret := *secrets[0]
  104. assert.Check(t, is.Equal(secretName, secret.SecretName))
  105. assert.Check(t, nil != secret.File)
  106. assert.Check(t, is.Equal(secretTarget, secret.File.Name))
  107. // remove
  108. service.Spec.TaskTemplate.ContainerSpec.Secrets = []*swarmtypes.SecretReference{}
  109. _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{})
  110. assert.NilError(t, err)
  111. poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll)
  112. service = getService(t, cli, serviceID)
  113. assert.Check(t, is.Equal(0, len(service.Spec.TaskTemplate.ContainerSpec.Secrets)))
  114. err = cli.ServiceRemove(context.Background(), serviceID)
  115. assert.NilError(t, err)
  116. }
  117. func TestServiceUpdateConfigs(t *testing.T) {
  118. skip.If(t, testEnv.DaemonInfo.OSType != "linux")
  119. defer setupTest(t)()
  120. d := swarm.NewSwarm(t, testEnv)
  121. defer d.Stop(t)
  122. cli := d.NewClientT(t)
  123. defer cli.Close()
  124. ctx := context.Background()
  125. configName := "TestConfig_" + t.Name()
  126. configTarget := "targetName"
  127. resp, err := cli.ConfigCreate(ctx, swarmtypes.ConfigSpec{
  128. Annotations: swarmtypes.Annotations{
  129. Name: configName,
  130. },
  131. Data: []byte("TESTINGDATA"),
  132. })
  133. assert.NilError(t, err)
  134. assert.Check(t, resp.ID != "")
  135. serviceName := "TestService_" + t.Name()
  136. serviceID := swarm.CreateService(t, d, swarm.ServiceWithName(serviceName))
  137. service := getService(t, cli, serviceID)
  138. // add config
  139. service.Spec.TaskTemplate.ContainerSpec.Configs = append(service.Spec.TaskTemplate.ContainerSpec.Configs,
  140. &swarmtypes.ConfigReference{
  141. File: &swarmtypes.ConfigReferenceFileTarget{
  142. Name: configTarget,
  143. UID: "0",
  144. GID: "0",
  145. Mode: 0600,
  146. },
  147. ConfigID: resp.ID,
  148. ConfigName: configName,
  149. },
  150. )
  151. _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{})
  152. assert.NilError(t, err)
  153. poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll)
  154. service = getService(t, cli, serviceID)
  155. configs := service.Spec.TaskTemplate.ContainerSpec.Configs
  156. assert.Assert(t, is.Equal(1, len(configs)))
  157. config := *configs[0]
  158. assert.Check(t, is.Equal(configName, config.ConfigName))
  159. assert.Check(t, nil != config.File)
  160. assert.Check(t, is.Equal(configTarget, config.File.Name))
  161. // remove
  162. service.Spec.TaskTemplate.ContainerSpec.Configs = []*swarmtypes.ConfigReference{}
  163. _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{})
  164. assert.NilError(t, err)
  165. poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll)
  166. service = getService(t, cli, serviceID)
  167. assert.Check(t, is.Equal(0, len(service.Spec.TaskTemplate.ContainerSpec.Configs)))
  168. err = cli.ServiceRemove(context.Background(), serviceID)
  169. assert.NilError(t, err)
  170. }
  171. func TestServiceUpdateNetwork(t *testing.T) {
  172. skip.If(t, testEnv.DaemonInfo.OSType != "linux")
  173. defer setupTest(t)()
  174. d := swarm.NewSwarm(t, testEnv)
  175. defer d.Stop(t)
  176. cli := d.NewClientT(t)
  177. defer cli.Close()
  178. ctx := context.Background()
  179. // Create a overlay network
  180. testNet := "testNet" + t.Name()
  181. overlayID := network.CreateNoError(t, ctx, cli, testNet,
  182. network.WithDriver("overlay"))
  183. var instances uint64 = 1
  184. // Create service with the overlay network
  185. serviceName := "TestServiceUpdateNetworkRM_" + t.Name()
  186. serviceID := swarm.CreateService(t, d,
  187. swarm.ServiceWithReplicas(instances),
  188. swarm.ServiceWithName(serviceName),
  189. swarm.ServiceWithNetwork(testNet))
  190. poll.WaitOn(t, swarm.RunningTasksCount(cli, serviceID, instances), swarm.ServicePoll)
  191. service := getService(t, cli, serviceID)
  192. netInfo, err := cli.NetworkInspect(ctx, testNet, types.NetworkInspectOptions{
  193. Verbose: true,
  194. Scope: "swarm",
  195. })
  196. assert.NilError(t, err)
  197. assert.Assert(t, len(netInfo.Containers) == 2, "Expected 2 endpoints, one for container and one for LB Sandbox")
  198. //Remove network from service
  199. service.Spec.TaskTemplate.Networks = []swarmtypes.NetworkAttachmentConfig{}
  200. _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{})
  201. assert.NilError(t, err)
  202. poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll)
  203. netInfo, err = cli.NetworkInspect(ctx, testNet, types.NetworkInspectOptions{
  204. Verbose: true,
  205. Scope: "swarm",
  206. })
  207. assert.NilError(t, err)
  208. assert.Assert(t, len(netInfo.Containers) == 0, "Load balancing endpoint still exists in network")
  209. err = cli.NetworkRemove(ctx, overlayID)
  210. assert.NilError(t, err)
  211. err = cli.ServiceRemove(ctx, serviceID)
  212. assert.NilError(t, err)
  213. }
  214. func getService(t *testing.T, cli client.ServiceAPIClient, serviceID string) swarmtypes.Service {
  215. t.Helper()
  216. service, _, err := cli.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{})
  217. assert.NilError(t, err)
  218. return service
  219. }
  220. func serviceIsUpdated(client client.ServiceAPIClient, serviceID string) func(log poll.LogT) poll.Result {
  221. return func(log poll.LogT) poll.Result {
  222. service, _, err := client.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{})
  223. switch {
  224. case err != nil:
  225. return poll.Error(err)
  226. case service.UpdateStatus != nil && service.UpdateStatus.State == swarmtypes.UpdateStateCompleted:
  227. return poll.Success()
  228. default:
  229. if service.UpdateStatus != nil {
  230. return poll.Continue("waiting for service %s to be updated, state: %s, message: %s", serviceID, service.UpdateStatus.State, service.UpdateStatus.Message)
  231. }
  232. return poll.Continue("waiting for service %s to be updated", serviceID)
  233. }
  234. }
  235. }