plugin_test.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. package service
  2. import (
  3. "context"
  4. "io"
  5. "io/ioutil"
  6. "os"
  7. "path"
  8. "testing"
  9. "github.com/docker/docker/api/types"
  10. swarmtypes "github.com/docker/docker/api/types/swarm"
  11. "github.com/docker/docker/api/types/swarm/runtime"
  12. "github.com/docker/docker/integration/internal/swarm"
  13. "github.com/docker/docker/internal/test/daemon"
  14. "github.com/docker/docker/internal/test/fixtures/plugin"
  15. "github.com/docker/docker/internal/test/registry"
  16. "gotest.tools/assert"
  17. "gotest.tools/poll"
  18. "gotest.tools/skip"
  19. )
  20. func TestServicePlugin(t *testing.T) {
  21. skip.If(t, testEnv.IsRemoteDaemon, "cannot run daemon when remote daemon")
  22. skip.If(t, testEnv.DaemonInfo.OSType == "windows")
  23. skip.If(t, os.Getenv("DOCKER_ENGINE_GOARCH") != "amd64")
  24. defer setupTest(t)()
  25. reg := registry.NewV2(t)
  26. defer reg.Close()
  27. repo := path.Join(registry.DefaultURL, "swarm", "test:v1")
  28. repo2 := path.Join(registry.DefaultURL, "swarm", "test:v2")
  29. name := "test"
  30. d := daemon.New(t)
  31. d.StartWithBusybox(t)
  32. apiclient := d.NewClientT(t)
  33. err := plugin.Create(context.Background(), apiclient, repo)
  34. assert.NilError(t, err)
  35. r, err := apiclient.PluginPush(context.Background(), repo, "")
  36. assert.NilError(t, err)
  37. _, err = io.Copy(ioutil.Discard, r)
  38. assert.NilError(t, err)
  39. err = apiclient.PluginRemove(context.Background(), repo, types.PluginRemoveOptions{})
  40. assert.NilError(t, err)
  41. err = plugin.Create(context.Background(), apiclient, repo2)
  42. assert.NilError(t, err)
  43. r, err = apiclient.PluginPush(context.Background(), repo2, "")
  44. assert.NilError(t, err)
  45. _, err = io.Copy(ioutil.Discard, r)
  46. assert.NilError(t, err)
  47. err = apiclient.PluginRemove(context.Background(), repo2, types.PluginRemoveOptions{})
  48. assert.NilError(t, err)
  49. d.Stop(t)
  50. d1 := swarm.NewSwarm(t, testEnv, daemon.WithExperimental)
  51. defer d1.Stop(t)
  52. d2 := daemon.New(t, daemon.WithExperimental, daemon.WithSwarmPort(daemon.DefaultSwarmPort+1))
  53. d2.StartAndSwarmJoin(t, d1, true)
  54. defer d2.Stop(t)
  55. d3 := daemon.New(t, daemon.WithExperimental, daemon.WithSwarmPort(daemon.DefaultSwarmPort+2))
  56. d3.StartAndSwarmJoin(t, d1, false)
  57. defer d3.Stop(t)
  58. id := d1.CreateService(t, makePlugin(repo, name, nil))
  59. poll.WaitOn(t, d1.PluginIsRunning(t, name), swarm.ServicePoll)
  60. poll.WaitOn(t, d2.PluginIsRunning(t, name), swarm.ServicePoll)
  61. poll.WaitOn(t, d3.PluginIsRunning(t, name), swarm.ServicePoll)
  62. service := d1.GetService(t, id)
  63. d1.UpdateService(t, service, makePlugin(repo2, name, nil))
  64. poll.WaitOn(t, d1.PluginReferenceIs(t, name, repo2), swarm.ServicePoll)
  65. poll.WaitOn(t, d2.PluginReferenceIs(t, name, repo2), swarm.ServicePoll)
  66. poll.WaitOn(t, d3.PluginReferenceIs(t, name, repo2), swarm.ServicePoll)
  67. poll.WaitOn(t, d1.PluginIsRunning(t, name), swarm.ServicePoll)
  68. poll.WaitOn(t, d2.PluginIsRunning(t, name), swarm.ServicePoll)
  69. poll.WaitOn(t, d3.PluginIsRunning(t, name), swarm.ServicePoll)
  70. d1.RemoveService(t, id)
  71. poll.WaitOn(t, d1.PluginIsNotPresent(t, name), swarm.ServicePoll)
  72. poll.WaitOn(t, d2.PluginIsNotPresent(t, name), swarm.ServicePoll)
  73. poll.WaitOn(t, d3.PluginIsNotPresent(t, name), swarm.ServicePoll)
  74. // constrain to managers only
  75. id = d1.CreateService(t, makePlugin(repo, name, []string{"node.role==manager"}))
  76. poll.WaitOn(t, d1.PluginIsRunning(t, name), swarm.ServicePoll)
  77. poll.WaitOn(t, d2.PluginIsRunning(t, name), swarm.ServicePoll)
  78. poll.WaitOn(t, d3.PluginIsNotPresent(t, name), swarm.ServicePoll)
  79. d1.RemoveService(t, id)
  80. poll.WaitOn(t, d1.PluginIsNotPresent(t, name), swarm.ServicePoll)
  81. poll.WaitOn(t, d2.PluginIsNotPresent(t, name), swarm.ServicePoll)
  82. poll.WaitOn(t, d3.PluginIsNotPresent(t, name), swarm.ServicePoll)
  83. // with no name
  84. id = d1.CreateService(t, makePlugin(repo, "", nil))
  85. poll.WaitOn(t, d1.PluginIsRunning(t, repo), swarm.ServicePoll)
  86. poll.WaitOn(t, d2.PluginIsRunning(t, repo), swarm.ServicePoll)
  87. poll.WaitOn(t, d3.PluginIsRunning(t, repo), swarm.ServicePoll)
  88. d1.RemoveService(t, id)
  89. poll.WaitOn(t, d1.PluginIsNotPresent(t, repo), swarm.ServicePoll)
  90. poll.WaitOn(t, d2.PluginIsNotPresent(t, repo), swarm.ServicePoll)
  91. poll.WaitOn(t, d3.PluginIsNotPresent(t, repo), swarm.ServicePoll)
  92. }
  93. func makePlugin(repo, name string, constraints []string) func(*swarmtypes.Service) {
  94. return func(s *swarmtypes.Service) {
  95. s.Spec.TaskTemplate.Runtime = swarmtypes.RuntimePlugin
  96. s.Spec.TaskTemplate.PluginSpec = &runtime.PluginSpec{
  97. Name: name,
  98. Remote: repo,
  99. }
  100. if constraints != nil {
  101. s.Spec.TaskTemplate.Placement = &swarmtypes.Placement{
  102. Constraints: constraints,
  103. }
  104. }
  105. }
  106. }