service_test.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  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/client"
  9. "github.com/docker/docker/integration/internal/network"
  10. "github.com/docker/docker/integration/internal/swarm"
  11. "github.com/docker/docker/testutil"
  12. "github.com/docker/docker/testutil/daemon"
  13. "gotest.tools/v3/assert"
  14. "gotest.tools/v3/icmd"
  15. "gotest.tools/v3/poll"
  16. "gotest.tools/v3/skip"
  17. )
  18. // delInterface removes given network interface
  19. func delInterface(ctx context.Context, t *testing.T, ifName string) {
  20. t.Helper()
  21. testutil.RunCommand(ctx, "ip", "link", "delete", ifName).Assert(t, icmd.Success)
  22. testutil.RunCommand(ctx, "iptables", "-t", "nat", "--flush").Assert(t, icmd.Success)
  23. testutil.RunCommand(ctx, "iptables", "--flush").Assert(t, icmd.Success)
  24. }
  25. func TestDaemonRestartWithLiveRestore(t *testing.T) {
  26. skip.If(t, testEnv.DaemonInfo.OSType == "windows")
  27. skip.If(t, testEnv.IsRemoteDaemon)
  28. skip.If(t, testEnv.IsRootless, "rootless mode has different view of network")
  29. ctx := testutil.StartSpan(baseContext, t)
  30. d := daemon.New(t)
  31. defer d.Stop(t)
  32. d.Start(t)
  33. c := d.NewClientT(t)
  34. defer c.Close()
  35. // Verify bridge network's subnet
  36. out, err := c.NetworkInspect(ctx, "bridge", types.NetworkInspectOptions{})
  37. assert.NilError(t, err)
  38. subnet := out.IPAM.Config[0].Subnet
  39. d.Restart(t,
  40. "--live-restore=true",
  41. "--default-address-pool", "base=175.30.0.0/16,size=16",
  42. "--default-address-pool", "base=175.33.0.0/16,size=24",
  43. )
  44. out1, err := c.NetworkInspect(ctx, "bridge", types.NetworkInspectOptions{})
  45. assert.NilError(t, err)
  46. // Make sure docker0 doesn't get override with new IP in live restore case
  47. assert.Equal(t, out1.IPAM.Config[0].Subnet, subnet)
  48. }
  49. func TestDaemonDefaultNetworkPools(t *testing.T) {
  50. skip.If(t, testEnv.DaemonInfo.OSType == "windows")
  51. // Remove docker0 bridge and the start daemon defining the predefined address pools
  52. skip.If(t, testEnv.IsRemoteDaemon)
  53. skip.If(t, testEnv.IsRootless, "rootless mode has different view of network")
  54. ctx := testutil.StartSpan(baseContext, t)
  55. defaultNetworkBridge := "docker0"
  56. delInterface(ctx, t, defaultNetworkBridge)
  57. d := daemon.New(t)
  58. defer d.Stop(t)
  59. d.Start(t,
  60. "--default-address-pool", "base=175.30.0.0/16,size=16",
  61. "--default-address-pool", "base=175.33.0.0/16,size=24",
  62. )
  63. c := d.NewClientT(t)
  64. defer c.Close()
  65. // Verify bridge network's subnet
  66. out, err := c.NetworkInspect(ctx, "bridge", types.NetworkInspectOptions{})
  67. assert.NilError(t, err)
  68. assert.Equal(t, out.IPAM.Config[0].Subnet, "175.30.0.0/16")
  69. // Create a bridge network and verify its subnet is the second default pool
  70. name := "elango" + t.Name()
  71. network.CreateNoError(ctx, t, c, name,
  72. network.WithDriver("bridge"),
  73. )
  74. out, err = c.NetworkInspect(ctx, name, types.NetworkInspectOptions{})
  75. assert.NilError(t, err)
  76. assert.Equal(t, out.IPAM.Config[0].Subnet, "175.33.0.0/24")
  77. // Create a bridge network and verify its subnet is the third default pool
  78. name = "saanvi" + t.Name()
  79. network.CreateNoError(ctx, t, c, name,
  80. network.WithDriver("bridge"),
  81. )
  82. out, err = c.NetworkInspect(ctx, name, types.NetworkInspectOptions{})
  83. assert.NilError(t, err)
  84. assert.Equal(t, out.IPAM.Config[0].Subnet, "175.33.1.0/24")
  85. delInterface(ctx, t, defaultNetworkBridge)
  86. }
  87. func TestDaemonRestartWithExistingNetwork(t *testing.T) {
  88. skip.If(t, testEnv.DaemonInfo.OSType == "windows")
  89. skip.If(t, testEnv.IsRemoteDaemon)
  90. skip.If(t, testEnv.IsRootless, "rootless mode has different view of network")
  91. ctx := testutil.StartSpan(baseContext, t)
  92. defaultNetworkBridge := "docker0"
  93. d := daemon.New(t)
  94. d.Start(t)
  95. defer d.Stop(t)
  96. c := d.NewClientT(t)
  97. defer c.Close()
  98. // Create a bridge network
  99. name := "elango" + t.Name()
  100. network.CreateNoError(ctx, t, c, name,
  101. network.WithDriver("bridge"),
  102. )
  103. // Verify bridge network's subnet
  104. out, err := c.NetworkInspect(ctx, name, types.NetworkInspectOptions{})
  105. assert.NilError(t, err)
  106. networkip := out.IPAM.Config[0].Subnet
  107. // Restart daemon with default address pool option
  108. d.Restart(t,
  109. "--default-address-pool", "base=175.30.0.0/16,size=16",
  110. "--default-address-pool", "base=175.33.0.0/16,size=24")
  111. out1, err := c.NetworkInspect(ctx, name, types.NetworkInspectOptions{})
  112. assert.NilError(t, err)
  113. assert.Equal(t, out1.IPAM.Config[0].Subnet, networkip)
  114. delInterface(ctx, t, defaultNetworkBridge)
  115. }
  116. func TestDaemonRestartWithExistingNetworkWithDefaultPoolRange(t *testing.T) {
  117. skip.If(t, testEnv.DaemonInfo.OSType == "windows")
  118. skip.If(t, testEnv.IsRemoteDaemon)
  119. skip.If(t, testEnv.IsRootless, "rootless mode has different view of network")
  120. ctx := testutil.StartSpan(baseContext, t)
  121. defaultNetworkBridge := "docker0"
  122. d := daemon.New(t)
  123. d.Start(t)
  124. defer d.Stop(t)
  125. c := d.NewClientT(t)
  126. defer c.Close()
  127. // Create a bridge network
  128. name := "elango" + t.Name()
  129. network.CreateNoError(ctx, t, c, name,
  130. network.WithDriver("bridge"),
  131. )
  132. // Verify bridge network's subnet
  133. out, err := c.NetworkInspect(ctx, name, types.NetworkInspectOptions{})
  134. assert.NilError(t, err)
  135. networkip := out.IPAM.Config[0].Subnet
  136. // Create a bridge network
  137. name = "sthira" + t.Name()
  138. network.CreateNoError(ctx, t, c, name,
  139. network.WithDriver("bridge"),
  140. )
  141. out, err = c.NetworkInspect(ctx, name, types.NetworkInspectOptions{})
  142. assert.NilError(t, err)
  143. networkip2 := out.IPAM.Config[0].Subnet
  144. // Restart daemon with default address pool option
  145. d.Restart(t,
  146. "--default-address-pool", "base=175.18.0.0/16,size=16",
  147. "--default-address-pool", "base=175.19.0.0/16,size=24",
  148. )
  149. // Create a bridge network
  150. name = "saanvi" + t.Name()
  151. network.CreateNoError(ctx, t, c, name,
  152. network.WithDriver("bridge"),
  153. )
  154. out1, err := c.NetworkInspect(ctx, name, types.NetworkInspectOptions{})
  155. assert.NilError(t, err)
  156. assert.Check(t, out1.IPAM.Config[0].Subnet != networkip)
  157. assert.Check(t, out1.IPAM.Config[0].Subnet != networkip2)
  158. delInterface(ctx, t, defaultNetworkBridge)
  159. }
  160. func TestDaemonWithBipAndDefaultNetworkPool(t *testing.T) {
  161. skip.If(t, testEnv.DaemonInfo.OSType == "windows")
  162. skip.If(t, testEnv.IsRemoteDaemon)
  163. skip.If(t, testEnv.IsRootless, "rootless mode has different view of network")
  164. ctx := testutil.StartSpan(baseContext, t)
  165. defaultNetworkBridge := "docker0"
  166. d := daemon.New(t)
  167. defer d.Stop(t)
  168. d.Start(t,
  169. "--bip=172.60.0.1/16",
  170. "--default-address-pool", "base=175.30.0.0/16,size=16",
  171. "--default-address-pool", "base=175.33.0.0/16,size=24",
  172. )
  173. c := d.NewClientT(t)
  174. defer c.Close()
  175. // Verify bridge network's subnet
  176. out, err := c.NetworkInspect(ctx, "bridge", types.NetworkInspectOptions{})
  177. assert.NilError(t, err)
  178. // Make sure BIP IP doesn't get override with new default address pool .
  179. assert.Equal(t, out.IPAM.Config[0].Subnet, "172.60.0.0/16")
  180. delInterface(ctx, t, defaultNetworkBridge)
  181. }
  182. func TestServiceWithPredefinedNetwork(t *testing.T) {
  183. skip.If(t, testEnv.DaemonInfo.OSType == "windows")
  184. skip.If(t, testEnv.IsRootless, "rootless mode doesn't support Swarm-mode")
  185. ctx := setupTest(t)
  186. d := swarm.NewSwarm(ctx, t, testEnv)
  187. defer d.Stop(t)
  188. c := d.NewClientT(t)
  189. defer c.Close()
  190. hostName := "host"
  191. var instances uint64 = 1
  192. serviceName := "TestService" + t.Name()
  193. serviceID := swarm.CreateService(ctx, t, d,
  194. swarm.ServiceWithReplicas(instances),
  195. swarm.ServiceWithName(serviceName),
  196. swarm.ServiceWithNetwork(hostName),
  197. )
  198. poll.WaitOn(t, swarm.RunningTasksCount(ctx, c, serviceID, instances), swarm.ServicePoll)
  199. _, _, err := c.ServiceInspectWithRaw(ctx, serviceID, types.ServiceInspectOptions{})
  200. assert.NilError(t, err)
  201. err = c.ServiceRemove(ctx, serviceID)
  202. assert.NilError(t, err)
  203. }
  204. const ingressNet = "ingress"
  205. func TestServiceRemoveKeepsIngressNetwork(t *testing.T) {
  206. t.Skip("FLAKY_TEST")
  207. skip.If(t, testEnv.IsRootless, "rootless mode doesn't support Swarm-mode")
  208. skip.If(t, testEnv.DaemonInfo.OSType == "windows")
  209. ctx := setupTest(t)
  210. d := swarm.NewSwarm(ctx, t, testEnv)
  211. defer d.Stop(t)
  212. c := d.NewClientT(t)
  213. defer c.Close()
  214. poll.WaitOn(t, swarmIngressReady(ctx, c), swarm.NetworkPoll)
  215. var instances uint64 = 1
  216. serviceID := swarm.CreateService(ctx, t, d,
  217. swarm.ServiceWithReplicas(instances),
  218. swarm.ServiceWithName(t.Name()+"-service"),
  219. swarm.ServiceWithEndpoint(&swarmtypes.EndpointSpec{
  220. Ports: []swarmtypes.PortConfig{
  221. {
  222. Protocol: swarmtypes.PortConfigProtocolTCP,
  223. TargetPort: 80,
  224. PublishMode: swarmtypes.PortConfigPublishModeIngress,
  225. },
  226. },
  227. }),
  228. )
  229. poll.WaitOn(t, swarm.RunningTasksCount(ctx, c, serviceID, instances), swarm.ServicePoll)
  230. _, _, err := c.ServiceInspectWithRaw(ctx, serviceID, types.ServiceInspectOptions{})
  231. assert.NilError(t, err)
  232. err = c.ServiceRemove(ctx, serviceID)
  233. assert.NilError(t, err)
  234. poll.WaitOn(t, noServices(ctx, c), swarm.ServicePoll)
  235. poll.WaitOn(t, swarm.NoTasks(ctx, c), swarm.ServicePoll)
  236. // Ensure that "ingress" is not removed or corrupted
  237. time.Sleep(10 * time.Second)
  238. netInfo, err := c.NetworkInspect(ctx, ingressNet, types.NetworkInspectOptions{
  239. Verbose: true,
  240. Scope: "swarm",
  241. })
  242. assert.NilError(t, err, "Ingress network was removed after removing service!")
  243. assert.Assert(t, len(netInfo.Containers) != 0, "No load balancing endpoints in ingress network")
  244. assert.Assert(t, len(netInfo.Peers) != 0, "No peers (including self) in ingress network")
  245. _, ok := netInfo.Containers["ingress-sbox"]
  246. assert.Assert(t, ok, "ingress-sbox not present in ingress network")
  247. }
  248. //nolint:unused // for some reason, the "unused" linter marks this function as "unused"
  249. func swarmIngressReady(ctx context.Context, client client.NetworkAPIClient) func(log poll.LogT) poll.Result {
  250. return func(log poll.LogT) poll.Result {
  251. netInfo, err := client.NetworkInspect(ctx, 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.DaemonInfo.OSType == "windows")
  285. skip.If(t, testEnv.IsRootless, "rootless mode doesn't support Swarm-mode")
  286. ctx := setupTest(t)
  287. var datapathPort uint32 = 7777
  288. d := swarm.NewSwarm(ctx, t, testEnv, daemon.WithSwarmDataPathPort(datapathPort))
  289. c := d.NewClientT(t)
  290. // Create a overlay network
  291. name := "saanvisthira" + t.Name()
  292. overlayID := network.CreateNoError(ctx, t, c, name,
  293. network.WithDriver("overlay"))
  294. var instances uint64 = 1
  295. serviceID := swarm.CreateService(ctx, t, d,
  296. swarm.ServiceWithReplicas(instances),
  297. swarm.ServiceWithName(name),
  298. swarm.ServiceWithNetwork(name),
  299. )
  300. poll.WaitOn(t, swarm.RunningTasksCount(ctx, c, serviceID, instances), swarm.ServicePoll)
  301. info := d.Info(t)
  302. assert.Equal(t, info.Swarm.Cluster.DataPathPort, datapathPort)
  303. err := c.ServiceRemove(ctx, serviceID)
  304. assert.NilError(t, err)
  305. poll.WaitOn(t, noServices(ctx, c), swarm.ServicePoll)
  306. poll.WaitOn(t, swarm.NoTasks(ctx, c), swarm.ServicePoll)
  307. err = c.NetworkRemove(ctx, overlayID)
  308. assert.NilError(t, err)
  309. c.Close()
  310. err = d.SwarmLeave(ctx, t, true)
  311. assert.NilError(t, err)
  312. d.Stop(t)
  313. // Clean up , set it back to original one to make sure other tests don't fail
  314. // call without datapath port option.
  315. d = swarm.NewSwarm(ctx, t, testEnv)
  316. defer d.Stop(t)
  317. nc := d.NewClientT(t)
  318. defer nc.Close()
  319. // Create a overlay network
  320. name = "not-saanvisthira" + t.Name()
  321. overlayID = network.CreateNoError(ctx, t, nc, name,
  322. network.WithDriver("overlay"))
  323. serviceID = swarm.CreateService(ctx, t, d,
  324. swarm.ServiceWithReplicas(instances),
  325. swarm.ServiceWithName(name),
  326. swarm.ServiceWithNetwork(name),
  327. )
  328. poll.WaitOn(t, swarm.RunningTasksCount(ctx, nc, serviceID, instances), swarm.ServicePoll)
  329. info = d.Info(t)
  330. var defaultDataPathPort uint32 = 4789
  331. assert.Equal(t, info.Swarm.Cluster.DataPathPort, defaultDataPathPort)
  332. err = nc.ServiceRemove(ctx, serviceID)
  333. assert.NilError(t, err)
  334. poll.WaitOn(t, noServices(ctx, nc), swarm.ServicePoll)
  335. poll.WaitOn(t, swarm.NoTasks(ctx, nc), swarm.ServicePoll)
  336. err = nc.NetworkRemove(ctx, overlayID)
  337. assert.NilError(t, err)
  338. err = d.SwarmLeave(ctx, t, true)
  339. assert.NilError(t, err)
  340. }
  341. func TestServiceWithDefaultAddressPoolInit(t *testing.T) {
  342. skip.If(t, testEnv.DaemonInfo.OSType == "windows")
  343. skip.If(t, testEnv.IsRootless, "rootless mode doesn't support Swarm-mode")
  344. ctx := setupTest(t)
  345. d := swarm.NewSwarm(ctx, t, testEnv,
  346. daemon.WithSwarmDefaultAddrPool([]string{"20.20.0.0/16"}),
  347. daemon.WithSwarmDefaultAddrPoolSubnetSize(24))
  348. defer d.Stop(t)
  349. cli := d.NewClientT(t)
  350. defer cli.Close()
  351. // Create a overlay network
  352. name := "sthira" + t.Name()
  353. overlayID := network.CreateNoError(ctx, t, cli, name,
  354. network.WithDriver("overlay"),
  355. )
  356. var instances uint64 = 1
  357. serviceName := "TestService" + t.Name()
  358. serviceID := swarm.CreateService(ctx, t, d,
  359. swarm.ServiceWithReplicas(instances),
  360. swarm.ServiceWithName(serviceName),
  361. swarm.ServiceWithNetwork(name),
  362. )
  363. poll.WaitOn(t, swarm.RunningTasksCount(ctx, cli, serviceID, instances), swarm.ServicePoll)
  364. _, _, err := cli.ServiceInspectWithRaw(ctx, serviceID, types.ServiceInspectOptions{})
  365. assert.NilError(t, err)
  366. out, err := cli.NetworkInspect(ctx, overlayID, types.NetworkInspectOptions{Verbose: true})
  367. assert.NilError(t, err)
  368. t.Logf("%s: NetworkInspect: %+v", t.Name(), out)
  369. assert.Assert(t, len(out.IPAM.Config) > 0)
  370. // As of docker/swarmkit#2890, the ingress network uses the default address
  371. // pool (whereas before, the subnet for the ingress network was hard-coded.
  372. // This means that the ingress network gets the subnet 20.20.0.0/24, and
  373. // the network we just created gets subnet 20.20.1.0/24.
  374. assert.Equal(t, out.IPAM.Config[0].Subnet, "20.20.1.0/24")
  375. // Also inspect ingress network and make sure its in the same subnet
  376. out, err = cli.NetworkInspect(ctx, "ingress", types.NetworkInspectOptions{Verbose: true})
  377. assert.NilError(t, err)
  378. assert.Assert(t, len(out.IPAM.Config) > 0)
  379. assert.Equal(t, out.IPAM.Config[0].Subnet, "20.20.0.0/24")
  380. err = cli.ServiceRemove(ctx, serviceID)
  381. poll.WaitOn(t, noServices(ctx, cli), swarm.ServicePoll)
  382. poll.WaitOn(t, swarm.NoTasks(ctx, cli), swarm.ServicePoll)
  383. assert.NilError(t, err)
  384. err = cli.NetworkRemove(ctx, overlayID)
  385. assert.NilError(t, err)
  386. err = d.SwarmLeave(ctx, t, true)
  387. assert.NilError(t, err)
  388. }