create_test.go 12 KB

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