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