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