service_test.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. package network // import "github.com/docker/docker/integration/network"
  2. import (
  3. "context"
  4. "testing"
  5. "time"
  6. "github.com/docker/docker/api/types"
  7. swarmtypes "github.com/docker/docker/api/types/swarm"
  8. "github.com/docker/docker/api/types/versions"
  9. "github.com/docker/docker/client"
  10. "github.com/docker/docker/integration/internal/network"
  11. "github.com/docker/docker/integration/internal/swarm"
  12. "github.com/docker/docker/internal/test/daemon"
  13. "gotest.tools/assert"
  14. "gotest.tools/icmd"
  15. "gotest.tools/poll"
  16. "gotest.tools/skip"
  17. )
  18. // delInterface removes given network interface
  19. func delInterface(t *testing.T, ifName string) {
  20. icmd.RunCommand("ip", "link", "delete", ifName).Assert(t, icmd.Success)
  21. icmd.RunCommand("iptables", "-t", "nat", "--flush").Assert(t, icmd.Success)
  22. icmd.RunCommand("iptables", "--flush").Assert(t, icmd.Success)
  23. }
  24. func TestDaemonRestartWithLiveRestore(t *testing.T) {
  25. skip.If(t, testEnv.OSType == "windows")
  26. skip.If(t, testEnv.IsRemoteDaemon)
  27. skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.38"), "skip test from new feature")
  28. d := daemon.New(t)
  29. defer d.Stop(t)
  30. d.Start(t)
  31. d.Restart(t,
  32. "--live-restore=true",
  33. "--default-address-pool", "base=175.30.0.0/16,size=16",
  34. "--default-address-pool", "base=175.33.0.0/16,size=24",
  35. )
  36. // Verify bridge network's subnet
  37. c := d.NewClientT(t)
  38. defer c.Close()
  39. out, err := c.NetworkInspect(context.Background(), "bridge", types.NetworkInspectOptions{})
  40. assert.NilError(t, err)
  41. // Make sure docker0 doesn't get override with new IP in live restore case
  42. assert.Equal(t, out.IPAM.Config[0].Subnet, "172.18.0.0/16")
  43. }
  44. func TestDaemonDefaultNetworkPools(t *testing.T) {
  45. skip.If(t, testEnv.OSType == "windows")
  46. // Remove docker0 bridge and the start daemon defining the predefined address pools
  47. skip.If(t, testEnv.IsRemoteDaemon)
  48. skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.38"), "skip test from new feature")
  49. defaultNetworkBridge := "docker0"
  50. delInterface(t, defaultNetworkBridge)
  51. d := daemon.New(t)
  52. defer d.Stop(t)
  53. d.Start(t,
  54. "--default-address-pool", "base=175.30.0.0/16,size=16",
  55. "--default-address-pool", "base=175.33.0.0/16,size=24",
  56. )
  57. c := d.NewClientT(t)
  58. defer c.Close()
  59. // Verify bridge network's subnet
  60. out, err := c.NetworkInspect(context.Background(), "bridge", types.NetworkInspectOptions{})
  61. assert.NilError(t, err)
  62. assert.Equal(t, out.IPAM.Config[0].Subnet, "175.30.0.0/16")
  63. // Create a bridge network and verify its subnet is the second default pool
  64. name := "elango" + t.Name()
  65. network.CreateNoError(t, context.Background(), c, name,
  66. network.WithDriver("bridge"),
  67. )
  68. out, err = c.NetworkInspect(context.Background(), name, types.NetworkInspectOptions{})
  69. assert.NilError(t, err)
  70. assert.Equal(t, out.IPAM.Config[0].Subnet, "175.33.0.0/24")
  71. // Create a bridge network and verify its subnet is the third default pool
  72. name = "saanvi" + t.Name()
  73. network.CreateNoError(t, context.Background(), c, name,
  74. network.WithDriver("bridge"),
  75. )
  76. out, err = c.NetworkInspect(context.Background(), name, types.NetworkInspectOptions{})
  77. assert.NilError(t, err)
  78. assert.Equal(t, out.IPAM.Config[0].Subnet, "175.33.1.0/24")
  79. delInterface(t, defaultNetworkBridge)
  80. }
  81. func TestDaemonRestartWithExistingNetwork(t *testing.T) {
  82. skip.If(t, testEnv.OSType == "windows")
  83. skip.If(t, testEnv.IsRemoteDaemon)
  84. skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.38"), "skip test from new feature")
  85. defaultNetworkBridge := "docker0"
  86. d := daemon.New(t)
  87. d.Start(t)
  88. defer d.Stop(t)
  89. c := d.NewClientT(t)
  90. defer c.Close()
  91. // Create a bridge network
  92. name := "elango" + t.Name()
  93. network.CreateNoError(t, context.Background(), c, name,
  94. network.WithDriver("bridge"),
  95. )
  96. // Verify bridge network's subnet
  97. out, err := c.NetworkInspect(context.Background(), name, types.NetworkInspectOptions{})
  98. assert.NilError(t, err)
  99. networkip := out.IPAM.Config[0].Subnet
  100. // Restart daemon with default address pool option
  101. d.Restart(t,
  102. "--default-address-pool", "base=175.30.0.0/16,size=16",
  103. "--default-address-pool", "base=175.33.0.0/16,size=24")
  104. out1, err := c.NetworkInspect(context.Background(), name, types.NetworkInspectOptions{})
  105. assert.NilError(t, err)
  106. assert.Equal(t, out1.IPAM.Config[0].Subnet, networkip)
  107. delInterface(t, defaultNetworkBridge)
  108. }
  109. func TestDaemonRestartWithExistingNetworkWithDefaultPoolRange(t *testing.T) {
  110. skip.If(t, testEnv.OSType == "windows")
  111. skip.If(t, testEnv.IsRemoteDaemon)
  112. skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.38"), "skip test from new feature")
  113. defaultNetworkBridge := "docker0"
  114. d := daemon.New(t)
  115. d.Start(t)
  116. defer d.Stop(t)
  117. c := d.NewClientT(t)
  118. defer c.Close()
  119. // Create a bridge network
  120. name := "elango" + t.Name()
  121. network.CreateNoError(t, context.Background(), c, name,
  122. network.WithDriver("bridge"),
  123. )
  124. // Verify bridge network's subnet
  125. out, err := c.NetworkInspect(context.Background(), name, types.NetworkInspectOptions{})
  126. assert.NilError(t, err)
  127. networkip := out.IPAM.Config[0].Subnet
  128. // Create a bridge network
  129. name = "sthira" + t.Name()
  130. network.CreateNoError(t, context.Background(), c, name,
  131. network.WithDriver("bridge"),
  132. )
  133. out, err = c.NetworkInspect(context.Background(), name, types.NetworkInspectOptions{})
  134. assert.NilError(t, err)
  135. networkip2 := out.IPAM.Config[0].Subnet
  136. // Restart daemon with default address pool option
  137. d.Restart(t,
  138. "--default-address-pool", "base=175.18.0.0/16,size=16",
  139. "--default-address-pool", "base=175.19.0.0/16,size=24",
  140. )
  141. // Create a bridge network
  142. name = "saanvi" + t.Name()
  143. network.CreateNoError(t, context.Background(), c, name,
  144. network.WithDriver("bridge"),
  145. )
  146. out1, err := c.NetworkInspect(context.Background(), name, types.NetworkInspectOptions{})
  147. assert.NilError(t, err)
  148. assert.Check(t, out1.IPAM.Config[0].Subnet != networkip)
  149. assert.Check(t, out1.IPAM.Config[0].Subnet != networkip2)
  150. delInterface(t, defaultNetworkBridge)
  151. }
  152. func TestDaemonWithBipAndDefaultNetworkPool(t *testing.T) {
  153. skip.If(t, testEnv.OSType == "windows")
  154. skip.If(t, testEnv.IsRemoteDaemon)
  155. skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.38"), "skip test from new feature")
  156. defaultNetworkBridge := "docker0"
  157. d := daemon.New(t)
  158. defer d.Stop(t)
  159. d.Start(t,
  160. "--bip=172.60.0.1/16",
  161. "--default-address-pool", "base=175.30.0.0/16,size=16",
  162. "--default-address-pool", "base=175.33.0.0/16,size=24",
  163. )
  164. c := d.NewClientT(t)
  165. defer c.Close()
  166. // Verify bridge network's subnet
  167. out, err := c.NetworkInspect(context.Background(), "bridge", types.NetworkInspectOptions{})
  168. assert.NilError(t, err)
  169. // Make sure BIP IP doesn't get override with new default address pool .
  170. assert.Equal(t, out.IPAM.Config[0].Subnet, "172.60.0.1/16")
  171. delInterface(t, defaultNetworkBridge)
  172. }
  173. func TestServiceWithPredefinedNetwork(t *testing.T) {
  174. skip.If(t, testEnv.OSType == "windows")
  175. defer setupTest(t)()
  176. d := swarm.NewSwarm(t, testEnv)
  177. defer d.Stop(t)
  178. c := d.NewClientT(t)
  179. defer c.Close()
  180. hostName := "host"
  181. var instances uint64 = 1
  182. serviceName := "TestService" + t.Name()
  183. serviceID := swarm.CreateService(t, d,
  184. swarm.ServiceWithReplicas(instances),
  185. swarm.ServiceWithName(serviceName),
  186. swarm.ServiceWithNetwork(hostName),
  187. )
  188. poll.WaitOn(t, serviceRunningCount(c, serviceID, instances), swarm.ServicePoll)
  189. _, _, err := c.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{})
  190. assert.NilError(t, err)
  191. err = c.ServiceRemove(context.Background(), serviceID)
  192. assert.NilError(t, err)
  193. }
  194. const ingressNet = "ingress"
  195. func TestServiceRemoveKeepsIngressNetwork(t *testing.T) {
  196. skip.If(t, testEnv.OSType == "windows")
  197. defer setupTest(t)()
  198. d := swarm.NewSwarm(t, testEnv)
  199. defer d.Stop(t)
  200. c := d.NewClientT(t)
  201. defer c.Close()
  202. poll.WaitOn(t, swarmIngressReady(c), swarm.NetworkPoll)
  203. var instances uint64 = 1
  204. serviceID := swarm.CreateService(t, d,
  205. swarm.ServiceWithReplicas(instances),
  206. swarm.ServiceWithName(t.Name()+"-service"),
  207. swarm.ServiceWithEndpoint(&swarmtypes.EndpointSpec{
  208. Ports: []swarmtypes.PortConfig{
  209. {
  210. Protocol: swarmtypes.PortConfigProtocolTCP,
  211. TargetPort: 80,
  212. PublishMode: swarmtypes.PortConfigPublishModeIngress,
  213. },
  214. },
  215. }),
  216. )
  217. poll.WaitOn(t, serviceRunningCount(c, serviceID, instances), swarm.ServicePoll)
  218. ctx := context.Background()
  219. _, _, err := c.ServiceInspectWithRaw(ctx, serviceID, types.ServiceInspectOptions{})
  220. assert.NilError(t, err)
  221. err = c.ServiceRemove(ctx, serviceID)
  222. assert.NilError(t, err)
  223. poll.WaitOn(t, noServices(ctx, c), swarm.ServicePoll)
  224. poll.WaitOn(t, swarm.NoTasks(ctx, c), swarm.ServicePoll)
  225. // Ensure that "ingress" is not removed or corrupted
  226. time.Sleep(10 * time.Second)
  227. netInfo, err := c.NetworkInspect(ctx, ingressNet, types.NetworkInspectOptions{
  228. Verbose: true,
  229. Scope: "swarm",
  230. })
  231. assert.NilError(t, err, "Ingress network was removed after removing service!")
  232. assert.Assert(t, len(netInfo.Containers) != 0, "No load balancing endpoints in ingress network")
  233. assert.Assert(t, len(netInfo.Peers) != 0, "No peers (including self) in ingress network")
  234. _, ok := netInfo.Containers["ingress-sbox"]
  235. assert.Assert(t, ok, "ingress-sbox not present in ingress network")
  236. }
  237. func serviceRunningCount(client client.ServiceAPIClient, serviceID string, instances uint64) func(log poll.LogT) poll.Result {
  238. return func(log poll.LogT) poll.Result {
  239. services, err := client.ServiceList(context.Background(), types.ServiceListOptions{})
  240. if err != nil {
  241. return poll.Error(err)
  242. }
  243. if len(services) != int(instances) {
  244. return poll.Continue("Service count at %d waiting for %d", len(services), instances)
  245. }
  246. return poll.Success()
  247. }
  248. }
  249. func swarmIngressReady(client client.NetworkAPIClient) func(log poll.LogT) poll.Result {
  250. return func(log poll.LogT) poll.Result {
  251. netInfo, err := client.NetworkInspect(context.Background(), ingressNet, types.NetworkInspectOptions{
  252. Verbose: true,
  253. Scope: "swarm",
  254. })
  255. if err != nil {
  256. return poll.Error(err)
  257. }
  258. np := len(netInfo.Peers)
  259. nc := len(netInfo.Containers)
  260. if np == 0 || nc == 0 {
  261. return poll.Continue("ingress not ready: %d peers and %d containers", nc, np)
  262. }
  263. _, ok := netInfo.Containers["ingress-sbox"]
  264. if !ok {
  265. return poll.Continue("ingress not ready: does not contain the ingress-sbox")
  266. }
  267. return poll.Success()
  268. }
  269. }
  270. func noServices(ctx context.Context, client client.ServiceAPIClient) func(log poll.LogT) poll.Result {
  271. return func(log poll.LogT) poll.Result {
  272. services, err := client.ServiceList(ctx, types.ServiceListOptions{})
  273. switch {
  274. case err != nil:
  275. return poll.Error(err)
  276. case len(services) == 0:
  277. return poll.Success()
  278. default:
  279. return poll.Continue("waiting for all services to be removed: service count at %d", len(services))
  280. }
  281. }
  282. }
  283. func TestServiceWithDataPathPortInit(t *testing.T) {
  284. skip.If(t, testEnv.OSType == "windows")
  285. skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.40"), "DataPathPort was added in API v1.40")
  286. defer setupTest(t)()
  287. var ops = []func(*daemon.Daemon){}
  288. var datapathPort uint32 = 7777
  289. ops = append(ops, daemon.WithSwarmDataPathPort(datapathPort))
  290. d := swarm.NewSwarm(t, testEnv, ops...)
  291. c := d.NewClientT(t)
  292. defer c.Close()
  293. // Create a overlay network
  294. name := "saanvisthira" + t.Name()
  295. network.CreateNoError(t, context.Background(), c, name,
  296. network.WithDriver("overlay"))
  297. var instances uint64 = 1
  298. serviceID := swarm.CreateService(t, d,
  299. swarm.ServiceWithReplicas(instances),
  300. swarm.ServiceWithNetwork(name),
  301. )
  302. poll.WaitOn(t, serviceRunningCount(c, serviceID, instances), swarm.ServicePoll)
  303. info := d.Info(t)
  304. assert.Equal(t, info.Swarm.Cluster.DataPathPort, datapathPort)
  305. err := c.ServiceRemove(context.Background(), serviceID)
  306. assert.NilError(t, err)
  307. d.SwarmLeave(t, true)
  308. d.Stop(t)
  309. // Clean up , set it back to original one to make sure other tests don't fail
  310. // call without datapath port option.
  311. ops = []func(*daemon.Daemon){}
  312. d = swarm.NewSwarm(t, testEnv, ops...)
  313. c = d.NewClientT(t)
  314. // Create a overlay network
  315. name = "saanvisthira" + t.Name()
  316. network.CreateNoError(t, context.Background(), c, name,
  317. network.WithDriver("overlay"))
  318. serviceID = swarm.CreateService(t, d,
  319. swarm.ServiceWithReplicas(instances),
  320. swarm.ServiceWithNetwork(name),
  321. )
  322. poll.WaitOn(t, serviceRunningCount(c, serviceID, instances), swarm.ServicePoll)
  323. info = d.Info(t)
  324. var defaultDataPathPort uint32 = 4789
  325. assert.Equal(t, info.Swarm.Cluster.DataPathPort, defaultDataPathPort)
  326. err = c.ServiceRemove(context.Background(), serviceID)
  327. assert.NilError(t, err)
  328. d.SwarmLeave(t, true)
  329. defer d.Stop(t)
  330. }
  331. func TestServiceWithDefaultAddressPoolInit(t *testing.T) {
  332. skip.If(t, testEnv.OSType == "windows")
  333. defer setupTest(t)()
  334. var ops = []func(*daemon.Daemon){}
  335. ipAddr := []string{"20.20.0.0/16"}
  336. ops = append(ops, daemon.WithSwarmDefaultAddrPool(ipAddr))
  337. ops = append(ops, daemon.WithSwarmDefaultAddrPoolSubnetSize(24))
  338. d := swarm.NewSwarm(t, testEnv, ops...)
  339. cli := d.NewClientT(t)
  340. defer cli.Close()
  341. // Create a overlay network
  342. name := "saanvisthira" + t.Name()
  343. network.CreateNoError(t, context.Background(), cli, name,
  344. network.WithDriver("overlay"))
  345. var instances uint64 = 1
  346. serviceName := "TestService" + t.Name()
  347. serviceID := swarm.CreateService(t, d,
  348. swarm.ServiceWithReplicas(instances),
  349. swarm.ServiceWithName(serviceName),
  350. swarm.ServiceWithNetwork(name),
  351. )
  352. poll.WaitOn(t, serviceRunningCount(cli, serviceID, instances), swarm.ServicePoll)
  353. _, _, err := cli.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{})
  354. assert.NilError(t, err)
  355. out, err := cli.NetworkInspect(context.Background(), name, types.NetworkInspectOptions{})
  356. assert.NilError(t, err)
  357. t.Logf("%s: NetworkInspect: %+v", t.Name(), out)
  358. assert.Assert(t, len(out.IPAM.Config) > 0)
  359. assert.Equal(t, out.IPAM.Config[0].Subnet, "20.20.0.0/24")
  360. err = cli.ServiceRemove(context.Background(), serviceID)
  361. assert.NilError(t, err)
  362. d.SwarmLeave(t, true)
  363. d.Stop(t)
  364. // Clean up , set it back to original one to make sure other tests don't fail
  365. ipAddr = []string{"10.0.0.0/8"}
  366. ops = append(ops, daemon.WithSwarmDefaultAddrPool(ipAddr))
  367. ops = append(ops, daemon.WithSwarmDefaultAddrPoolSubnetSize(24))
  368. d = swarm.NewSwarm(t, testEnv, ops...)
  369. d.SwarmLeave(t, true)
  370. defer d.Stop(t)
  371. }