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