create_test.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. package service // import "github.com/docker/docker/integration/service"
  2. import (
  3. "context"
  4. "fmt"
  5. "io/ioutil"
  6. "testing"
  7. "time"
  8. "github.com/docker/docker/api/types"
  9. "github.com/docker/docker/api/types/filters"
  10. swarmtypes "github.com/docker/docker/api/types/swarm"
  11. "github.com/docker/docker/client"
  12. "github.com/docker/docker/integration/internal/network"
  13. "github.com/docker/docker/integration/internal/swarm"
  14. "github.com/docker/docker/internal/test/daemon"
  15. "gotest.tools/assert"
  16. is "gotest.tools/assert/cmp"
  17. "gotest.tools/poll"
  18. "gotest.tools/skip"
  19. )
  20. func TestServiceCreateInit(t *testing.T) {
  21. defer setupTest(t)()
  22. t.Run("daemonInitDisabled", testServiceCreateInit(false))
  23. t.Run("daemonInitEnabled", testServiceCreateInit(true))
  24. }
  25. func testServiceCreateInit(daemonEnabled bool) func(t *testing.T) {
  26. return func(t *testing.T) {
  27. var ops = []func(*daemon.Daemon){}
  28. if daemonEnabled {
  29. ops = append(ops, daemon.WithInit)
  30. }
  31. d := swarm.NewSwarm(t, testEnv, ops...)
  32. defer d.Stop(t)
  33. client := d.NewClientT(t)
  34. defer client.Close()
  35. booleanTrue := true
  36. booleanFalse := false
  37. serviceID := swarm.CreateService(t, d)
  38. poll.WaitOn(t, serviceRunningTasksCount(client, serviceID, 1), swarm.ServicePoll)
  39. i := inspectServiceContainer(t, client, serviceID)
  40. // HostConfig.Init == nil means that it delegates to daemon configuration
  41. assert.Check(t, i.HostConfig.Init == nil)
  42. serviceID = swarm.CreateService(t, d, swarm.ServiceWithInit(&booleanTrue))
  43. poll.WaitOn(t, serviceRunningTasksCount(client, serviceID, 1), swarm.ServicePoll)
  44. i = inspectServiceContainer(t, client, serviceID)
  45. assert.Check(t, is.Equal(true, *i.HostConfig.Init))
  46. serviceID = swarm.CreateService(t, d, swarm.ServiceWithInit(&booleanFalse))
  47. poll.WaitOn(t, serviceRunningTasksCount(client, serviceID, 1), swarm.ServicePoll)
  48. i = inspectServiceContainer(t, client, serviceID)
  49. assert.Check(t, is.Equal(false, *i.HostConfig.Init))
  50. }
  51. }
  52. func inspectServiceContainer(t *testing.T, client client.APIClient, serviceID string) types.ContainerJSON {
  53. t.Helper()
  54. filter := filters.NewArgs()
  55. filter.Add("label", fmt.Sprintf("com.docker.swarm.service.id=%s", serviceID))
  56. containers, err := client.ContainerList(context.Background(), types.ContainerListOptions{Filters: filter})
  57. assert.NilError(t, err)
  58. assert.Check(t, is.Len(containers, 1))
  59. i, err := client.ContainerInspect(context.Background(), containers[0].ID)
  60. assert.NilError(t, err)
  61. return i
  62. }
  63. func TestCreateServiceMultipleTimes(t *testing.T) {
  64. skip.If(t, testEnv.DaemonInfo.OSType == "windows")
  65. defer setupTest(t)()
  66. d := swarm.NewSwarm(t, testEnv)
  67. defer d.Stop(t)
  68. client := d.NewClientT(t)
  69. defer client.Close()
  70. overlayName := "overlay1_" + t.Name()
  71. overlayID := network.CreateNoError(t, context.Background(), client, overlayName,
  72. network.WithCheckDuplicate(),
  73. network.WithDriver("overlay"),
  74. )
  75. var instances uint64 = 4
  76. serviceName := "TestService_" + t.Name()
  77. serviceSpec := []swarm.ServiceSpecOpt{
  78. swarm.ServiceWithReplicas(instances),
  79. swarm.ServiceWithName(serviceName),
  80. swarm.ServiceWithNetwork(overlayName),
  81. }
  82. serviceID := swarm.CreateService(t, d, serviceSpec...)
  83. poll.WaitOn(t, serviceRunningTasksCount(client, serviceID, instances), swarm.ServicePoll)
  84. _, _, err := client.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{})
  85. assert.NilError(t, err)
  86. err = client.ServiceRemove(context.Background(), serviceID)
  87. assert.NilError(t, err)
  88. poll.WaitOn(t, serviceIsRemoved(client, serviceID), swarm.ServicePoll)
  89. poll.WaitOn(t, noTasks(client), swarm.ServicePoll)
  90. serviceID2 := swarm.CreateService(t, d, serviceSpec...)
  91. poll.WaitOn(t, serviceRunningTasksCount(client, serviceID2, instances), swarm.ServicePoll)
  92. err = client.ServiceRemove(context.Background(), serviceID2)
  93. assert.NilError(t, err)
  94. poll.WaitOn(t, serviceIsRemoved(client, serviceID2), swarm.ServicePoll)
  95. poll.WaitOn(t, noTasks(client), swarm.ServicePoll)
  96. err = client.NetworkRemove(context.Background(), overlayID)
  97. assert.NilError(t, err)
  98. poll.WaitOn(t, networkIsRemoved(client, overlayID), poll.WithTimeout(1*time.Minute), poll.WithDelay(10*time.Second))
  99. }
  100. func TestCreateWithDuplicateNetworkNames(t *testing.T) {
  101. skip.If(t, testEnv.DaemonInfo.OSType == "windows")
  102. defer setupTest(t)()
  103. d := swarm.NewSwarm(t, testEnv)
  104. defer d.Stop(t)
  105. client := d.NewClientT(t)
  106. defer client.Close()
  107. name := "foo_" + t.Name()
  108. n1 := network.CreateNoError(t, context.Background(), client, name,
  109. network.WithDriver("bridge"),
  110. )
  111. n2 := network.CreateNoError(t, context.Background(), client, name,
  112. network.WithDriver("bridge"),
  113. )
  114. // Duplicates with name but with different driver
  115. n3 := network.CreateNoError(t, context.Background(), client, name,
  116. network.WithDriver("overlay"),
  117. )
  118. // Create Service with the same name
  119. var instances uint64 = 1
  120. serviceName := "top_" + t.Name()
  121. serviceID := swarm.CreateService(t, d,
  122. swarm.ServiceWithReplicas(instances),
  123. swarm.ServiceWithName(serviceName),
  124. swarm.ServiceWithNetwork(name),
  125. )
  126. poll.WaitOn(t, serviceRunningTasksCount(client, serviceID, instances), swarm.ServicePoll)
  127. resp, _, err := client.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{})
  128. assert.NilError(t, err)
  129. assert.Check(t, is.Equal(n3, resp.Spec.TaskTemplate.Networks[0].Target))
  130. // Remove Service
  131. err = client.ServiceRemove(context.Background(), serviceID)
  132. assert.NilError(t, err)
  133. // Make sure task has been destroyed.
  134. poll.WaitOn(t, serviceIsRemoved(client, serviceID), swarm.ServicePoll)
  135. // Remove networks
  136. err = client.NetworkRemove(context.Background(), n3)
  137. assert.NilError(t, err)
  138. err = client.NetworkRemove(context.Background(), n2)
  139. assert.NilError(t, err)
  140. err = client.NetworkRemove(context.Background(), n1)
  141. assert.NilError(t, err)
  142. // Make sure networks have been destroyed.
  143. poll.WaitOn(t, networkIsRemoved(client, n3), poll.WithTimeout(1*time.Minute), poll.WithDelay(10*time.Second))
  144. poll.WaitOn(t, networkIsRemoved(client, n2), poll.WithTimeout(1*time.Minute), poll.WithDelay(10*time.Second))
  145. poll.WaitOn(t, networkIsRemoved(client, n1), poll.WithTimeout(1*time.Minute), poll.WithDelay(10*time.Second))
  146. }
  147. func TestCreateServiceSecretFileMode(t *testing.T) {
  148. skip.If(t, testEnv.DaemonInfo.OSType == "windows")
  149. defer setupTest(t)()
  150. d := swarm.NewSwarm(t, testEnv)
  151. defer d.Stop(t)
  152. client := d.NewClientT(t)
  153. defer client.Close()
  154. ctx := context.Background()
  155. secretName := "TestSecret_" + t.Name()
  156. secretResp, err := client.SecretCreate(ctx, swarmtypes.SecretSpec{
  157. Annotations: swarmtypes.Annotations{
  158. Name: secretName,
  159. },
  160. Data: []byte("TESTSECRET"),
  161. })
  162. assert.NilError(t, err)
  163. var instances uint64 = 1
  164. serviceName := "TestService_" + t.Name()
  165. serviceID := swarm.CreateService(t, d,
  166. swarm.ServiceWithReplicas(instances),
  167. swarm.ServiceWithName(serviceName),
  168. swarm.ServiceWithCommand([]string{"/bin/sh", "-c", "ls -l /etc/secret || /bin/top"}),
  169. swarm.ServiceWithSecret(&swarmtypes.SecretReference{
  170. File: &swarmtypes.SecretReferenceFileTarget{
  171. Name: "/etc/secret",
  172. UID: "0",
  173. GID: "0",
  174. Mode: 0777,
  175. },
  176. SecretID: secretResp.ID,
  177. SecretName: secretName,
  178. }),
  179. )
  180. poll.WaitOn(t, serviceRunningTasksCount(client, serviceID, instances), swarm.ServicePoll)
  181. filter := filters.NewArgs()
  182. filter.Add("service", serviceID)
  183. tasks, err := client.TaskList(ctx, types.TaskListOptions{
  184. Filters: filter,
  185. })
  186. assert.NilError(t, err)
  187. assert.Check(t, is.Equal(len(tasks), 1))
  188. body, err := client.ContainerLogs(ctx, tasks[0].Status.ContainerStatus.ContainerID, types.ContainerLogsOptions{
  189. ShowStdout: true,
  190. })
  191. assert.NilError(t, err)
  192. defer body.Close()
  193. content, err := ioutil.ReadAll(body)
  194. assert.NilError(t, err)
  195. assert.Check(t, is.Contains(string(content), "-rwxrwxrwx"))
  196. err = client.ServiceRemove(ctx, serviceID)
  197. assert.NilError(t, err)
  198. poll.WaitOn(t, serviceIsRemoved(client, serviceID), swarm.ServicePoll)
  199. poll.WaitOn(t, noTasks(client), swarm.ServicePoll)
  200. err = client.SecretRemove(ctx, secretName)
  201. assert.NilError(t, err)
  202. }
  203. func TestCreateServiceConfigFileMode(t *testing.T) {
  204. skip.If(t, testEnv.DaemonInfo.OSType == "windows")
  205. defer setupTest(t)()
  206. d := swarm.NewSwarm(t, testEnv)
  207. defer d.Stop(t)
  208. client := d.NewClientT(t)
  209. defer client.Close()
  210. ctx := context.Background()
  211. configName := "TestConfig_" + t.Name()
  212. configResp, err := client.ConfigCreate(ctx, swarmtypes.ConfigSpec{
  213. Annotations: swarmtypes.Annotations{
  214. Name: configName,
  215. },
  216. Data: []byte("TESTCONFIG"),
  217. })
  218. assert.NilError(t, err)
  219. var instances uint64 = 1
  220. serviceName := "TestService_" + t.Name()
  221. serviceID := swarm.CreateService(t, d,
  222. swarm.ServiceWithName(serviceName),
  223. swarm.ServiceWithCommand([]string{"/bin/sh", "-c", "ls -l /etc/config || /bin/top"}),
  224. swarm.ServiceWithReplicas(instances),
  225. swarm.ServiceWithConfig(&swarmtypes.ConfigReference{
  226. File: &swarmtypes.ConfigReferenceFileTarget{
  227. Name: "/etc/config",
  228. UID: "0",
  229. GID: "0",
  230. Mode: 0777,
  231. },
  232. ConfigID: configResp.ID,
  233. ConfigName: configName,
  234. }),
  235. )
  236. poll.WaitOn(t, serviceRunningTasksCount(client, serviceID, instances))
  237. filter := filters.NewArgs()
  238. filter.Add("service", serviceID)
  239. tasks, err := client.TaskList(ctx, types.TaskListOptions{
  240. Filters: filter,
  241. })
  242. assert.NilError(t, err)
  243. assert.Check(t, is.Equal(len(tasks), 1))
  244. body, err := client.ContainerLogs(ctx, tasks[0].Status.ContainerStatus.ContainerID, types.ContainerLogsOptions{
  245. ShowStdout: true,
  246. })
  247. assert.NilError(t, err)
  248. defer body.Close()
  249. content, err := ioutil.ReadAll(body)
  250. assert.NilError(t, err)
  251. assert.Check(t, is.Contains(string(content), "-rwxrwxrwx"))
  252. err = client.ServiceRemove(ctx, serviceID)
  253. assert.NilError(t, err)
  254. poll.WaitOn(t, serviceIsRemoved(client, serviceID))
  255. poll.WaitOn(t, noTasks(client))
  256. err = client.ConfigRemove(ctx, configName)
  257. assert.NilError(t, err)
  258. }
  259. func serviceRunningTasksCount(client client.ServiceAPIClient, serviceID string, instances uint64) func(log poll.LogT) poll.Result {
  260. return func(log poll.LogT) poll.Result {
  261. filter := filters.NewArgs()
  262. filter.Add("service", serviceID)
  263. tasks, err := client.TaskList(context.Background(), types.TaskListOptions{
  264. Filters: filter,
  265. })
  266. switch {
  267. case err != nil:
  268. return poll.Error(err)
  269. case len(tasks) == int(instances):
  270. for _, task := range tasks {
  271. if task.Status.State != swarmtypes.TaskStateRunning {
  272. return poll.Continue("waiting for tasks to enter run state")
  273. }
  274. }
  275. return poll.Success()
  276. default:
  277. return poll.Continue("task count at %d waiting for %d", len(tasks), instances)
  278. }
  279. }
  280. }
  281. func noTasks(client client.ServiceAPIClient) func(log poll.LogT) poll.Result {
  282. return func(log poll.LogT) poll.Result {
  283. filter := filters.NewArgs()
  284. tasks, err := client.TaskList(context.Background(), types.TaskListOptions{
  285. Filters: filter,
  286. })
  287. switch {
  288. case err != nil:
  289. return poll.Error(err)
  290. case len(tasks) == 0:
  291. return poll.Success()
  292. default:
  293. return poll.Continue("task count at %d waiting for 0", len(tasks))
  294. }
  295. }
  296. }
  297. func serviceIsRemoved(client client.ServiceAPIClient, serviceID string) func(log poll.LogT) poll.Result {
  298. return func(log poll.LogT) poll.Result {
  299. filter := filters.NewArgs()
  300. filter.Add("service", serviceID)
  301. _, err := client.TaskList(context.Background(), types.TaskListOptions{
  302. Filters: filter,
  303. })
  304. if err == nil {
  305. return poll.Continue("waiting for service %s to be deleted", serviceID)
  306. }
  307. return poll.Success()
  308. }
  309. }
  310. func networkIsRemoved(client client.NetworkAPIClient, networkID string) func(log poll.LogT) poll.Result {
  311. return func(log poll.LogT) poll.Result {
  312. _, err := client.NetworkInspect(context.Background(), networkID, types.NetworkInspectOptions{})
  313. if err == nil {
  314. return poll.Continue("waiting for network %s to be removed", networkID)
  315. }
  316. return poll.Success()
  317. }
  318. }