github.com/AbhinandanKurakure/podman/v3@v3.4.10/libpod/network/cni/run_test.go (about) 1 // +build linux 2 3 package cni_test 4 5 // The tests have to be run as root. 6 // For each test there will be two network namespaces created, 7 // netNSTest and netNSContainer. Each test must be run inside 8 // netNSTest to prevent leakage in the host netns, therefore 9 // it should use the following structure: 10 // It("test name", func() { 11 // runTest(func() { 12 // // add test logic here 13 // }) 14 // }) 15 16 import ( 17 "bytes" 18 "io/ioutil" 19 "net" 20 "os" 21 "path/filepath" 22 "strconv" 23 "sync" 24 "time" 25 26 "github.com/containernetworking/plugins/pkg/ns" 27 . "github.com/onsi/ginkgo" 28 . "github.com/onsi/gomega" 29 "github.com/sirupsen/logrus" 30 "github.com/vishvananda/netlink" 31 "golang.org/x/sys/unix" 32 33 "github.com/containers/podman/v3/libpod/network/types" 34 "github.com/containers/podman/v3/pkg/netns" 35 "github.com/containers/podman/v3/pkg/rootless" 36 "github.com/containers/storage/pkg/stringid" 37 ) 38 39 var _ = Describe("run CNI", func() { 40 var ( 41 libpodNet types.ContainerNetwork 42 cniConfDir string 43 logBuffer bytes.Buffer 44 netNSTest ns.NetNS 45 netNSContainer ns.NetNS 46 ) 47 const cniVarDir = "/var/lib/cni" 48 49 // runTest is a helper function to run a test. It ensures that each test 50 // is run in its own netns. It also creates a mountns to mount a tmpfs to /var/lib/cni. 51 runTest := func(run func()) { 52 netNSTest.Do(func(_ ns.NetNS) error { 53 defer GinkgoRecover() 54 err := os.MkdirAll(cniVarDir, 0755) 55 Expect(err).To(BeNil(), "Failed to create cniVarDir") 56 err = unix.Unshare(unix.CLONE_NEWNS) 57 Expect(err).To(BeNil(), "Failed to create new mountns") 58 err = unix.Mount("tmpfs", cniVarDir, "tmpfs", unix.MS_NOEXEC|unix.MS_NOSUID|unix.MS_NODEV, "") 59 Expect(err).To(BeNil(), "Failed to mount tmpfs for cniVarDir") 60 defer unix.Unmount(cniVarDir, 0) 61 62 // we have to setup the loopback adapter in this netns to use port forwarding 63 link, err := netlink.LinkByName("lo") 64 Expect(err).To(BeNil(), "Failed to get loopback adapter") 65 err = netlink.LinkSetUp(link) 66 Expect(err).To(BeNil(), "Failed to set loopback adapter up") 67 run() 68 return nil 69 }) 70 } 71 72 BeforeEach(func() { 73 // The tests need root privileges. 74 // Technically we could work around that by using user namespaces and 75 // the rootless cni code but this is to much work to get it right for a unit test. 76 if rootless.IsRootless() { 77 Skip("this test needs to be run as root") 78 } 79 80 var err error 81 cniConfDir, err = ioutil.TempDir("", "podman_cni_test") 82 if err != nil { 83 Fail("Failed to create tmpdir") 84 } 85 logBuffer = bytes.Buffer{} 86 logrus.SetOutput(&logBuffer) 87 88 netNSTest, err = netns.NewNS() 89 if err != nil { 90 Fail("Failed to create netns") 91 } 92 93 netNSContainer, err = netns.NewNS() 94 if err != nil { 95 Fail("Failed to create netns") 96 } 97 }) 98 99 JustBeforeEach(func() { 100 var err error 101 libpodNet, err = getNetworkInterface(cniConfDir, false) 102 if err != nil { 103 Fail("Failed to create NewCNINetworkInterface") 104 } 105 }) 106 107 AfterEach(func() { 108 os.RemoveAll(cniConfDir) 109 110 netns.UnmountNS(netNSTest) 111 netNSTest.Close() 112 113 netns.UnmountNS(netNSContainer) 114 netNSContainer.Close() 115 }) 116 117 Context("network setup test", func() { 118 119 It("run with default config", func() { 120 runTest(func() { 121 defNet := types.DefaultNetworkName 122 intName := "eth0" 123 setupOpts := types.SetupOptions{ 124 NetworkOptions: types.NetworkOptions{ 125 ContainerID: stringid.GenerateNonCryptoID(), 126 Networks: map[string]types.PerNetworkOptions{ 127 defNet: {InterfaceName: intName}, 128 }, 129 }, 130 } 131 res, err := libpodNet.Setup(netNSContainer.Path(), setupOpts) 132 Expect(err).To(BeNil()) 133 Expect(res).To(HaveLen(1)) 134 Expect(res).To(HaveKey(defNet)) 135 Expect(res[defNet].Interfaces).To(HaveKey(intName)) 136 Expect(res[defNet].Interfaces[intName].Networks).To(HaveLen(1)) 137 Expect(res[defNet].Interfaces[intName].Networks[0].Subnet.IP.String()).To(ContainSubstring("10.88.0.")) 138 Expect(res[defNet].Interfaces[intName].MacAddress).To(HaveLen(6)) 139 // default network has no dns 140 Expect(res[defNet].DNSServerIPs).To(BeEmpty()) 141 Expect(res[defNet].DNSSearchDomains).To(BeEmpty()) 142 143 err = libpodNet.Teardown(netNSContainer.Path(), types.TeardownOptions(setupOpts)) 144 Expect(err).To(BeNil()) 145 }) 146 }) 147 148 It("run with default config and static ip", func() { 149 runTest(func() { 150 defNet := types.DefaultNetworkName 151 intName := "eth0" 152 ip := net.ParseIP("10.88.5.5") 153 setupOpts := types.SetupOptions{ 154 NetworkOptions: types.NetworkOptions{ 155 ContainerID: stringid.GenerateNonCryptoID(), 156 Networks: map[string]types.PerNetworkOptions{ 157 defNet: { 158 InterfaceName: intName, 159 StaticIPs: []net.IP{ip}, 160 }, 161 }, 162 }, 163 } 164 res, err := libpodNet.Setup(netNSContainer.Path(), setupOpts) 165 Expect(err).To(BeNil()) 166 Expect(res).To(HaveLen(1)) 167 Expect(res).To(HaveKey(defNet)) 168 Expect(res[defNet].Interfaces).To(HaveKey(intName)) 169 Expect(res[defNet].Interfaces[intName].Networks).To(HaveLen(1)) 170 Expect(res[defNet].Interfaces[intName].Networks[0].Subnet.IP).To(Equal(ip)) 171 Expect(res[defNet].Interfaces[intName].MacAddress).To(HaveLen(6)) 172 // default network has no dns 173 Expect(res[defNet].DNSServerIPs).To(BeEmpty()) 174 Expect(res[defNet].DNSSearchDomains).To(BeEmpty()) 175 176 err = libpodNet.Teardown(netNSContainer.Path(), types.TeardownOptions(setupOpts)) 177 Expect(err).To(BeNil()) 178 }) 179 }) 180 181 for _, proto := range []string{"tcp", "udp"} { 182 // copy proto to extra var to keep correct references in the goroutines 183 protocol := proto 184 It("run with exposed ports protocol "+protocol, func() { 185 runTest(func() { 186 testdata := stringid.GenerateNonCryptoID() 187 defNet := types.DefaultNetworkName 188 intName := "eth0" 189 setupOpts := types.SetupOptions{ 190 NetworkOptions: types.NetworkOptions{ 191 ContainerID: stringid.GenerateNonCryptoID(), 192 PortMappings: []types.PortMapping{{ 193 Protocol: protocol, 194 HostIP: "127.0.0.1", 195 HostPort: 5000, 196 ContainerPort: 5000, 197 }}, 198 Networks: map[string]types.PerNetworkOptions{ 199 defNet: {InterfaceName: intName}, 200 }, 201 }, 202 } 203 res, err := libpodNet.Setup(netNSContainer.Path(), setupOpts) 204 Expect(err).To(BeNil()) 205 Expect(res).To(HaveLen(1)) 206 Expect(res).To(HaveKey(defNet)) 207 Expect(res[defNet].Interfaces).To(HaveKey(intName)) 208 Expect(res[defNet].Interfaces[intName].Networks).To(HaveLen(1)) 209 Expect(res[defNet].Interfaces[intName].Networks[0].Subnet.IP.String()).To(ContainSubstring("10.88.0.")) 210 Expect(res[defNet].Interfaces[intName].MacAddress).To(HaveLen(6)) 211 // default network has no dns 212 Expect(res[defNet].DNSServerIPs).To(BeEmpty()) 213 Expect(res[defNet].DNSSearchDomains).To(BeEmpty()) 214 var wg sync.WaitGroup 215 wg.Add(1) 216 // start a listener in the container ns 217 err = netNSContainer.Do(func(_ ns.NetNS) error { 218 defer GinkgoRecover() 219 runNetListener(&wg, protocol, "0.0.0.0", 5000, testdata) 220 return nil 221 }) 222 Expect(err).To(BeNil()) 223 224 conn, err := net.Dial(protocol, "127.0.0.1:5000") 225 Expect(err).To(BeNil()) 226 _, err = conn.Write([]byte(testdata)) 227 Expect(err).To(BeNil()) 228 conn.Close() 229 230 // wait for the listener to finish 231 wg.Wait() 232 233 err = libpodNet.Teardown(netNSContainer.Path(), types.TeardownOptions(setupOpts)) 234 Expect(err).To(BeNil()) 235 }) 236 }) 237 238 It("run with range ports protocol "+protocol, func() { 239 runTest(func() { 240 defNet := types.DefaultNetworkName 241 intName := "eth0" 242 setupOpts := types.SetupOptions{ 243 NetworkOptions: types.NetworkOptions{ 244 ContainerID: stringid.GenerateNonCryptoID(), 245 PortMappings: []types.PortMapping{{ 246 Protocol: protocol, 247 HostIP: "127.0.0.1", 248 HostPort: 5001, 249 ContainerPort: 5000, 250 Range: 3, 251 }}, 252 Networks: map[string]types.PerNetworkOptions{ 253 defNet: {InterfaceName: intName}, 254 }, 255 }, 256 } 257 res, err := libpodNet.Setup(netNSContainer.Path(), setupOpts) 258 Expect(err).To(BeNil()) 259 Expect(res).To(HaveLen(1)) 260 Expect(res).To(HaveKey(defNet)) 261 Expect(res[defNet].Interfaces).To(HaveKey(intName)) 262 Expect(res[defNet].Interfaces[intName].Networks).To(HaveLen(1)) 263 containerIP := res[defNet].Interfaces[intName].Networks[0].Subnet.IP.String() 264 Expect(containerIP).To(ContainSubstring("10.88.0.")) 265 Expect(res[defNet].Interfaces[intName].MacAddress).To(HaveLen(6)) 266 // default network has no dns 267 Expect(res[defNet].DNSServerIPs).To(BeEmpty()) 268 Expect(res[defNet].DNSSearchDomains).To(BeEmpty()) 269 270 // loop over all ports 271 for p := 5001; p < 5004; p++ { 272 port := p 273 var wg sync.WaitGroup 274 wg.Add(1) 275 testdata := stringid.GenerateNonCryptoID() 276 // start a listener in the container ns 277 err = netNSContainer.Do(func(_ ns.NetNS) error { 278 defer GinkgoRecover() 279 runNetListener(&wg, protocol, containerIP, port-1, testdata) 280 return nil 281 }) 282 Expect(err).To(BeNil()) 283 284 conn, err := net.Dial(protocol, net.JoinHostPort("127.0.0.1", strconv.Itoa(port))) 285 Expect(err).To(BeNil()) 286 _, err = conn.Write([]byte(testdata)) 287 Expect(err).To(BeNil()) 288 conn.Close() 289 290 // wait for the listener to finish 291 wg.Wait() 292 } 293 294 err = libpodNet.Teardown(netNSContainer.Path(), types.TeardownOptions(setupOpts)) 295 Expect(err).To(BeNil()) 296 }) 297 }) 298 } 299 300 It("run with comma separated port protocol", func() { 301 runTest(func() { 302 defNet := types.DefaultNetworkName 303 intName := "eth0" 304 setupOpts := types.SetupOptions{ 305 NetworkOptions: types.NetworkOptions{ 306 ContainerID: stringid.GenerateNonCryptoID(), 307 PortMappings: []types.PortMapping{{ 308 Protocol: "tcp,udp", 309 HostIP: "127.0.0.1", 310 HostPort: 5000, 311 ContainerPort: 5000, 312 }}, 313 Networks: map[string]types.PerNetworkOptions{ 314 defNet: {InterfaceName: intName}, 315 }, 316 }, 317 } 318 res, err := libpodNet.Setup(netNSContainer.Path(), setupOpts) 319 Expect(err).To(BeNil()) 320 Expect(res).To(HaveLen(1)) 321 Expect(res).To(HaveKey(defNet)) 322 Expect(res[defNet].Interfaces).To(HaveKey(intName)) 323 Expect(res[defNet].Interfaces[intName].Networks).To(HaveLen(1)) 324 Expect(res[defNet].Interfaces[intName].Networks[0].Subnet.IP.String()).To(ContainSubstring("10.88.0.")) 325 Expect(res[defNet].Interfaces[intName].MacAddress).To(HaveLen(6)) 326 327 for _, proto := range []string{"tcp", "udp"} { 328 // copy proto to extra var to keep correct references in the goroutines 329 protocol := proto 330 331 testdata := stringid.GenerateNonCryptoID() 332 var wg sync.WaitGroup 333 wg.Add(1) 334 // start tcp listener in the container ns 335 err = netNSContainer.Do(func(_ ns.NetNS) error { 336 defer GinkgoRecover() 337 runNetListener(&wg, protocol, "0.0.0.0", 5000, testdata) 338 return nil 339 }) 340 Expect(err).To(BeNil()) 341 342 conn, err := net.Dial(protocol, "127.0.0.1:5000") 343 Expect(err).To(BeNil()) 344 _, err = conn.Write([]byte(testdata)) 345 Expect(err).To(BeNil()) 346 conn.Close() 347 348 // wait for the listener to finish 349 wg.Wait() 350 } 351 352 err = libpodNet.Teardown(netNSContainer.Path(), types.TeardownOptions(setupOpts)) 353 Expect(err).To(BeNil()) 354 }) 355 }) 356 357 It("call setup twice", func() { 358 runTest(func() { 359 network := types.Network{} 360 network1, err := libpodNet.NetworkCreate(network) 361 Expect(err).To(BeNil()) 362 363 intName1 := "eth0" 364 netName1 := network1.Name 365 366 containerID := stringid.GenerateNonCryptoID() 367 368 setupOpts := types.SetupOptions{ 369 NetworkOptions: types.NetworkOptions{ 370 ContainerID: containerID, 371 Networks: map[string]types.PerNetworkOptions{ 372 netName1: { 373 InterfaceName: intName1, 374 }, 375 }, 376 }, 377 } 378 379 res, err := libpodNet.Setup(netNSContainer.Path(), setupOpts) 380 Expect(err).To(BeNil()) 381 Expect(res).To(HaveLen(1)) 382 383 Expect(res).To(HaveKey(netName1)) 384 Expect(res[netName1].Interfaces).To(HaveKey(intName1)) 385 Expect(res[netName1].Interfaces[intName1].Networks).To(HaveLen(1)) 386 ipInt1 := res[netName1].Interfaces[intName1].Networks[0].Subnet.IP 387 Expect(ipInt1).ToNot(BeEmpty()) 388 macInt1 := res[netName1].Interfaces[intName1].MacAddress 389 Expect(macInt1).To(HaveLen(6)) 390 391 // check in the container namespace if the settings are applied 392 err = netNSContainer.Do(func(_ ns.NetNS) error { 393 defer GinkgoRecover() 394 i, err := net.InterfaceByName(intName1) 395 Expect(err).To(BeNil()) 396 Expect(i.Name).To(Equal(intName1)) 397 Expect(i.HardwareAddr).To(Equal(macInt1)) 398 addrs, err := i.Addrs() 399 Expect(err).To(BeNil()) 400 subnet := &net.IPNet{ 401 IP: ipInt1, 402 Mask: net.CIDRMask(24, 32), 403 } 404 Expect(addrs).To(ContainElements(subnet)) 405 406 // check loopback adapter 407 i, err = net.InterfaceByName("lo") 408 Expect(err).To(BeNil()) 409 Expect(i.Name).To(Equal("lo")) 410 Expect(i.Flags & net.FlagLoopback).To(Equal(net.FlagLoopback)) 411 Expect(i.Flags&net.FlagUp).To(Equal(net.FlagUp), "Loopback adapter should be up") 412 return nil 413 }) 414 Expect(err).To(BeNil()) 415 416 network = types.Network{} 417 network2, err := libpodNet.NetworkCreate(network) 418 Expect(err).To(BeNil()) 419 420 intName2 := "eth1" 421 netName2 := network2.Name 422 423 setupOpts.Networks = map[string]types.PerNetworkOptions{ 424 netName2: { 425 InterfaceName: intName2, 426 }, 427 } 428 429 res, err = libpodNet.Setup(netNSContainer.Path(), setupOpts) 430 Expect(err).To(BeNil()) 431 Expect(res).To(HaveLen(1)) 432 433 Expect(res).To(HaveKey(netName2)) 434 Expect(res[netName2].Interfaces).To(HaveKey(intName2)) 435 Expect(res[netName2].Interfaces[intName2].Networks).To(HaveLen(1)) 436 ipInt2 := res[netName2].Interfaces[intName2].Networks[0].Subnet.IP 437 Expect(ipInt2).ToNot(BeEmpty()) 438 macInt2 := res[netName2].Interfaces[intName2].MacAddress 439 Expect(macInt2).To(HaveLen(6)) 440 441 // check in the container namespace if the settings are applied 442 err = netNSContainer.Do(func(_ ns.NetNS) error { 443 defer GinkgoRecover() 444 i, err := net.InterfaceByName(intName1) 445 Expect(err).To(BeNil()) 446 Expect(i.Name).To(Equal(intName1)) 447 Expect(i.HardwareAddr).To(Equal(macInt1)) 448 addrs, err := i.Addrs() 449 Expect(err).To(BeNil()) 450 subnet := &net.IPNet{ 451 IP: ipInt1, 452 Mask: net.CIDRMask(24, 32), 453 } 454 Expect(addrs).To(ContainElements(subnet)) 455 456 i, err = net.InterfaceByName(intName2) 457 Expect(err).To(BeNil()) 458 Expect(i.Name).To(Equal(intName2)) 459 Expect(i.HardwareAddr).To(Equal(macInt2)) 460 addrs, err = i.Addrs() 461 Expect(err).To(BeNil()) 462 subnet = &net.IPNet{ 463 IP: ipInt2, 464 Mask: net.CIDRMask(24, 32), 465 } 466 Expect(addrs).To(ContainElements(subnet)) 467 468 // check loopback adapter 469 i, err = net.InterfaceByName("lo") 470 Expect(err).To(BeNil()) 471 Expect(i.Name).To(Equal("lo")) 472 Expect(i.Flags & net.FlagLoopback).To(Equal(net.FlagLoopback)) 473 Expect(i.Flags&net.FlagUp).To(Equal(net.FlagUp), "Loopback adapter should be up") 474 return nil 475 }) 476 Expect(err).To(BeNil()) 477 478 teatdownOpts := types.TeardownOptions{ 479 NetworkOptions: types.NetworkOptions{ 480 ContainerID: containerID, 481 Networks: map[string]types.PerNetworkOptions{ 482 netName1: { 483 InterfaceName: intName1, 484 }, 485 netName2: { 486 InterfaceName: intName2, 487 }, 488 }, 489 }, 490 } 491 492 err = libpodNet.Teardown(netNSContainer.Path(), teatdownOpts) 493 Expect(err).To(BeNil()) 494 logString := logBuffer.String() 495 Expect(logString).To(BeEmpty()) 496 497 // check in the container namespace that the interface is removed 498 err = netNSContainer.Do(func(_ ns.NetNS) error { 499 defer GinkgoRecover() 500 _, err := net.InterfaceByName(intName1) 501 Expect(err).To(HaveOccurred()) 502 _, err = net.InterfaceByName(intName2) 503 Expect(err).To(HaveOccurred()) 504 505 // check that only the loopback adapter is left 506 ints, err := net.Interfaces() 507 Expect(err).To(BeNil()) 508 Expect(ints).To(HaveLen(1)) 509 Expect(ints[0].Name).To(Equal("lo")) 510 Expect(ints[0].Flags & net.FlagLoopback).To(Equal(net.FlagLoopback)) 511 Expect(ints[0].Flags&net.FlagUp).To(Equal(net.FlagUp), "Loopback adapter should be up") 512 513 return nil 514 }) 515 Expect(err).To(BeNil()) 516 517 err = libpodNet.NetworkRemove(netName1) 518 Expect(err).To(BeNil()) 519 err = libpodNet.NetworkRemove(netName2) 520 Expect(err).To(BeNil()) 521 522 // check that the interfaces are removed in the host ns 523 _, err = net.InterfaceByName(network1.NetworkInterface) 524 Expect(err).To(HaveOccurred()) 525 _, err = net.InterfaceByName(network2.NetworkInterface) 526 Expect(err).To(HaveOccurred()) 527 }) 528 }) 529 530 It("setup two networks with one setup call", func() { 531 runTest(func() { 532 subnet1, _ := types.ParseCIDR("192.168.0.0/24") 533 subnet2, _ := types.ParseCIDR("192.168.1.0/24") 534 network := types.Network{ 535 Subnets: []types.Subnet{ 536 {Subnet: subnet1}, 537 }, 538 } 539 network1, err := libpodNet.NetworkCreate(network) 540 Expect(err).To(BeNil()) 541 542 network = types.Network{ 543 Subnets: []types.Subnet{ 544 {Subnet: subnet2}, 545 }, 546 } 547 network2, err := libpodNet.NetworkCreate(network) 548 Expect(err).To(BeNil()) 549 550 intName1 := "eth0" 551 intName2 := "eth1" 552 netName1 := network1.Name 553 netName2 := network2.Name 554 555 setupOpts := types.SetupOptions{ 556 NetworkOptions: types.NetworkOptions{ 557 ContainerID: stringid.GenerateNonCryptoID(), 558 Networks: map[string]types.PerNetworkOptions{ 559 netName1: { 560 InterfaceName: intName1, 561 }, 562 netName2: { 563 InterfaceName: intName2, 564 }, 565 }, 566 }, 567 } 568 569 res, err := libpodNet.Setup(netNSContainer.Path(), setupOpts) 570 Expect(err).To(BeNil()) 571 Expect(res).To(HaveLen(2)) 572 573 Expect(res).To(HaveKey(netName1)) 574 Expect(res[netName1].Interfaces).To(HaveKey(intName1)) 575 Expect(res[netName1].Interfaces[intName1].Networks).To(HaveLen(1)) 576 ipInt1 := res[netName1].Interfaces[intName1].Networks[0].Subnet.IP 577 Expect(ipInt1.String()).To(ContainSubstring("192.168.0.")) 578 macInt1 := res[netName1].Interfaces[intName1].MacAddress 579 Expect(macInt1).To(HaveLen(6)) 580 581 Expect(res).To(HaveKey(netName2)) 582 Expect(res[netName2].Interfaces).To(HaveKey(intName2)) 583 Expect(res[netName2].Interfaces[intName2].Networks).To(HaveLen(1)) 584 ipInt2 := res[netName2].Interfaces[intName2].Networks[0].Subnet.IP 585 Expect(ipInt2.String()).To(ContainSubstring("192.168.1.")) 586 macInt2 := res[netName2].Interfaces[intName2].MacAddress 587 Expect(macInt2).To(HaveLen(6)) 588 589 // default network has no dns 590 Expect(res[netName1].DNSServerIPs).To(BeEmpty()) 591 Expect(res[netName1].DNSSearchDomains).To(BeEmpty()) 592 593 // check in the container namespace if the settings are applied 594 err = netNSContainer.Do(func(_ ns.NetNS) error { 595 defer GinkgoRecover() 596 i, err := net.InterfaceByName(intName1) 597 Expect(err).To(BeNil()) 598 Expect(i.Name).To(Equal(intName1)) 599 Expect(i.HardwareAddr).To(Equal(macInt1)) 600 addrs, err := i.Addrs() 601 Expect(err).To(BeNil()) 602 subnet := &net.IPNet{ 603 IP: ipInt1, 604 Mask: net.CIDRMask(24, 32), 605 } 606 Expect(addrs).To(ContainElements(subnet)) 607 608 i, err = net.InterfaceByName(intName2) 609 Expect(err).To(BeNil()) 610 Expect(i.Name).To(Equal(intName2)) 611 Expect(i.HardwareAddr).To(Equal(macInt2)) 612 addrs, err = i.Addrs() 613 Expect(err).To(BeNil()) 614 subnet = &net.IPNet{ 615 IP: ipInt2, 616 Mask: net.CIDRMask(24, 32), 617 } 618 Expect(addrs).To(ContainElements(subnet)) 619 620 // check loopback adapter 621 i, err = net.InterfaceByName("lo") 622 Expect(err).To(BeNil()) 623 Expect(i.Name).To(Equal("lo")) 624 Expect(i.Flags & net.FlagLoopback).To(Equal(net.FlagLoopback)) 625 Expect(i.Flags&net.FlagUp).To(Equal(net.FlagUp), "Loopback adapter should be up") 626 return nil 627 }) 628 Expect(err).To(BeNil()) 629 630 err = libpodNet.Teardown(netNSContainer.Path(), types.TeardownOptions(setupOpts)) 631 Expect(err).To(BeNil()) 632 logString := logBuffer.String() 633 Expect(logString).To(BeEmpty()) 634 635 // check in the container namespace that the interface is removed 636 err = netNSContainer.Do(func(_ ns.NetNS) error { 637 defer GinkgoRecover() 638 _, err := net.InterfaceByName(intName1) 639 Expect(err).To(HaveOccurred()) 640 _, err = net.InterfaceByName(intName2) 641 Expect(err).To(HaveOccurred()) 642 643 // check that only the loopback adapter is left 644 ints, err := net.Interfaces() 645 Expect(err).To(BeNil()) 646 Expect(ints).To(HaveLen(1)) 647 Expect(ints[0].Name).To(Equal("lo")) 648 Expect(ints[0].Flags & net.FlagLoopback).To(Equal(net.FlagLoopback)) 649 Expect(ints[0].Flags&net.FlagUp).To(Equal(net.FlagUp), "Loopback adapter should be up") 650 651 return nil 652 }) 653 Expect(err).To(BeNil()) 654 }) 655 656 }) 657 658 It("dual stack network with static ips", func() { 659 // Version checks for cni plugins are not possible, the plugins do not output 660 // version information and using the package manager does not work across distros. 661 // Fedora has the right version so we use this for now. 662 SkipIfNotFedora("requires cni plugins 1.0.0 or newer for multiple static ips") 663 runTest(func() { 664 subnet1, _ := types.ParseCIDR("192.168.0.0/24") 665 subnet2, _ := types.ParseCIDR("fd41:0a75:2ca0:48a9::/64") 666 network := types.Network{ 667 Subnets: []types.Subnet{ 668 {Subnet: subnet1}, {Subnet: subnet2}, 669 }, 670 } 671 network1, err := libpodNet.NetworkCreate(network) 672 Expect(err).To(BeNil()) 673 674 mac, _ := net.ParseMAC("40:15:2f:d8:42:36") 675 interfaceName := "eth0" 676 677 ip1 := net.ParseIP("192.168.0.5") 678 ip2 := net.ParseIP("fd41:0a75:2ca0:48a9::5") 679 680 netName := network1.Name 681 setupOpts := types.SetupOptions{ 682 NetworkOptions: types.NetworkOptions{ 683 ContainerName: "mycon", 684 ContainerID: stringid.GenerateNonCryptoID(), 685 Networks: map[string]types.PerNetworkOptions{ 686 netName: { 687 InterfaceName: interfaceName, 688 StaticIPs: []net.IP{ip1, ip2}, 689 StaticMAC: mac, 690 }, 691 }, 692 }, 693 } 694 695 res, err := libpodNet.Setup(netNSContainer.Path(), setupOpts) 696 Expect(err).To(BeNil()) 697 Expect(res).To(HaveLen(1)) 698 Expect(res).To(HaveKey(netName)) 699 Expect(res[netName].Interfaces).To(HaveKey(interfaceName)) 700 Expect(res[netName].Interfaces[interfaceName].Networks).To(HaveLen(2)) 701 Expect(res[netName].Interfaces[interfaceName].Networks[0].Subnet.IP.String()).To(Equal(ip1.String())) 702 Expect(res[netName].Interfaces[interfaceName].Networks[0].Subnet.Mask).To(Equal(subnet1.Mask)) 703 Expect(res[netName].Interfaces[interfaceName].Networks[0].Gateway).To(Equal(net.ParseIP("192.168.0.1"))) 704 Expect(res[netName].Interfaces[interfaceName].Networks[1].Subnet.IP.String()).To(Equal(ip2.String())) 705 Expect(res[netName].Interfaces[interfaceName].Networks[1].Subnet.Mask).To(Equal(subnet2.Mask)) 706 Expect(res[netName].Interfaces[interfaceName].Networks[1].Gateway).To(Equal(net.ParseIP("fd41:0a75:2ca0:48a9::1"))) 707 Expect(res[netName].Interfaces[interfaceName].MacAddress).To(Equal(mac)) 708 // default network has no dns 709 Expect(res[netName].DNSServerIPs).To(BeEmpty()) 710 Expect(res[netName].DNSSearchDomains).To(BeEmpty()) 711 712 // check in the container namespace if the settings are applied 713 err = netNSContainer.Do(func(_ ns.NetNS) error { 714 defer GinkgoRecover() 715 i, err := net.InterfaceByName(interfaceName) 716 Expect(err).To(BeNil()) 717 Expect(i.Name).To(Equal(interfaceName)) 718 Expect(i.HardwareAddr).To(Equal(mac)) 719 addrs, err := i.Addrs() 720 Expect(err).To(BeNil()) 721 subnet1 := &net.IPNet{ 722 IP: ip1, 723 Mask: net.CIDRMask(24, 32), 724 } 725 subnet2 := &net.IPNet{ 726 IP: ip2, 727 Mask: net.CIDRMask(64, 128), 728 } 729 Expect(addrs).To(ContainElements(subnet1, subnet2)) 730 731 // check loopback adapter 732 i, err = net.InterfaceByName("lo") 733 Expect(err).To(BeNil()) 734 Expect(i.Name).To(Equal("lo")) 735 Expect(i.Flags & net.FlagLoopback).To(Equal(net.FlagLoopback)) 736 Expect(i.Flags&net.FlagUp).To(Equal(net.FlagUp), "Loopback adapter should be up") 737 return nil 738 }) 739 Expect(err).To(BeNil()) 740 741 err = libpodNet.Teardown(netNSContainer.Path(), types.TeardownOptions(setupOpts)) 742 Expect(err).To(BeNil()) 743 logString := logBuffer.String() 744 Expect(logString).To(BeEmpty()) 745 746 // check in the container namespace that the interface is removed 747 err = netNSContainer.Do(func(_ ns.NetNS) error { 748 defer GinkgoRecover() 749 _, err := net.InterfaceByName(interfaceName) 750 Expect(err).To(HaveOccurred()) 751 752 // check that only the loopback adapter is left 753 ints, err := net.Interfaces() 754 Expect(err).To(BeNil()) 755 Expect(ints).To(HaveLen(1)) 756 Expect(ints[0].Name).To(Equal("lo")) 757 Expect(ints[0].Flags & net.FlagLoopback).To(Equal(net.FlagLoopback)) 758 Expect(ints[0].Flags&net.FlagUp).To(Equal(net.FlagUp), "Loopback adapter should be up") 759 760 return nil 761 }) 762 Expect(err).To(BeNil()) 763 }) 764 }) 765 766 It("CNI_ARGS from environment variable", func() { 767 runTest(func() { 768 subnet1, _ := types.ParseCIDR("172.16.1.0/24") 769 ip := "172.16.1.5" 770 network := types.Network{ 771 Subnets: []types.Subnet{ 772 {Subnet: subnet1}, 773 }, 774 } 775 network1, err := libpodNet.NetworkCreate(network) 776 Expect(err).To(BeNil()) 777 netName := network1.Name 778 intName := "eth0" 779 setupOpts := types.SetupOptions{ 780 NetworkOptions: types.NetworkOptions{ 781 ContainerID: stringid.GenerateNonCryptoID(), 782 Networks: map[string]types.PerNetworkOptions{ 783 netName: { 784 InterfaceName: intName, 785 }, 786 }, 787 }, 788 } 789 790 os.Setenv("CNI_ARGS", "IP="+ip) 791 defer os.Unsetenv("CNI_ARGS") 792 793 res, err := libpodNet.Setup(netNSContainer.Path(), setupOpts) 794 Expect(err).To(BeNil()) 795 Expect(res).To(HaveLen(1)) 796 Expect(res).To(HaveKey(netName)) 797 Expect(res[netName].Interfaces).To(HaveKey(intName)) 798 Expect(res[netName].Interfaces[intName].Networks).To(HaveLen(1)) 799 Expect(res[netName].Interfaces[intName].Networks[0].Subnet.IP.String()).To(Equal(ip)) 800 Expect(res[netName].Interfaces[intName].Networks[0].Subnet.Mask).To(Equal(net.CIDRMask(24, 32))) 801 802 // check in the container namespace if the settings are applied 803 err = netNSContainer.Do(func(_ ns.NetNS) error { 804 defer GinkgoRecover() 805 i, err := net.InterfaceByName(intName) 806 Expect(err).To(BeNil()) 807 Expect(i.Name).To(Equal(intName)) 808 addrs, err := i.Addrs() 809 Expect(err).To(BeNil()) 810 subnet := &net.IPNet{ 811 IP: net.ParseIP(ip), 812 Mask: net.CIDRMask(24, 32), 813 } 814 Expect(addrs).To(ContainElements(subnet)) 815 816 // check loopback adapter 817 i, err = net.InterfaceByName("lo") 818 Expect(err).To(BeNil()) 819 Expect(i.Name).To(Equal("lo")) 820 Expect(i.Flags & net.FlagLoopback).To(Equal(net.FlagLoopback)) 821 Expect(i.Flags&net.FlagUp).To(Equal(net.FlagUp), "Loopback adapter should be up") 822 return nil 823 }) 824 Expect(err).To(BeNil()) 825 }) 826 }) 827 }) 828 829 Context("network setup test with networks from disk", func() { 830 831 BeforeEach(func() { 832 dir := "testfiles/valid" 833 files, err := ioutil.ReadDir(dir) 834 if err != nil { 835 Fail("Failed to read test directory") 836 } 837 for _, file := range files { 838 filename := file.Name() 839 data, err := ioutil.ReadFile(filepath.Join(dir, filename)) 840 if err != nil { 841 Fail("Failed to copy test files") 842 } 843 err = ioutil.WriteFile(filepath.Join(cniConfDir, filename), data, 0700) 844 if err != nil { 845 Fail("Failed to copy test files") 846 } 847 } 848 }) 849 850 It("dualstack setup with static ip and dns", func() { 851 SkipIfNoDnsname() 852 // Version checks for cni plugins are not possible, the plugins do not output 853 // version information and using the package manager does not work across distros. 854 // Fedora has the right version so we use this for now. 855 SkipIfNotFedora("requires cni plugins 1.0.0 or newer for multiple static ips") 856 runTest(func() { 857 interfaceName := "eth0" 858 859 ip1 := net.ParseIP("fd10:88:a::11") 860 ip2 := net.ParseIP("10.89.19.15") 861 862 containerName := "myname" 863 aliases := []string{"aliasname"} 864 865 netName := "dualstack" 866 setupOpts := types.SetupOptions{ 867 NetworkOptions: types.NetworkOptions{ 868 ContainerID: stringid.GenerateNonCryptoID(), 869 ContainerName: containerName, 870 Networks: map[string]types.PerNetworkOptions{ 871 netName: { 872 InterfaceName: interfaceName, 873 StaticIPs: []net.IP{ip1, ip2}, 874 Aliases: aliases, 875 }, 876 }, 877 }, 878 } 879 880 network, err := libpodNet.NetworkInspect(netName) 881 Expect(err).To(BeNil()) 882 Expect(network.Name).To(Equal(netName)) 883 Expect(network.DNSEnabled).To(BeTrue()) 884 Expect(network.Subnets).To(HaveLen(2)) 885 gw1 := network.Subnets[0].Gateway 886 Expect(gw1).To(HaveLen(16)) 887 mask1 := network.Subnets[0].Subnet.Mask 888 Expect(mask1).To(HaveLen(16)) 889 gw2 := network.Subnets[1].Gateway 890 Expect(gw2).To(HaveLen(4)) 891 mask2 := network.Subnets[1].Subnet.Mask 892 Expect(mask2).To(HaveLen(4)) 893 894 // because this net has dns we should always teardown otherwise we leak a dnsmasq process 895 defer libpodNet.Teardown(netNSContainer.Path(), types.TeardownOptions(setupOpts)) 896 res, err := libpodNet.Setup(netNSContainer.Path(), setupOpts) 897 Expect(err).To(BeNil()) 898 Expect(res).To(HaveLen(1)) 899 Expect(res).To(HaveKey(netName)) 900 Expect(res[netName].Interfaces).To(HaveKey(interfaceName)) 901 Expect(res[netName].Interfaces[interfaceName].Networks).To(HaveLen(2)) 902 Expect(res[netName].Interfaces[interfaceName].Networks[0].Subnet.IP.String()).To(Equal(ip1.String())) 903 Expect(res[netName].Interfaces[interfaceName].Networks[0].Subnet.Mask).To(Equal(mask1)) 904 Expect(res[netName].Interfaces[interfaceName].Networks[1].Subnet.IP.String()).To(Equal(ip2.String())) 905 Expect(res[netName].Interfaces[interfaceName].Networks[1].Subnet.Mask).To(Equal(mask2)) 906 // dualstack network dns 907 Expect(res[netName].DNSServerIPs).To(HaveLen(2)) 908 Expect(res[netName].DNSSearchDomains).To(HaveLen(1)) 909 Expect(res[netName].DNSSearchDomains).To(ConsistOf("dns.podman")) 910 911 // check in the container namespace if the settings are applied 912 err = netNSContainer.Do(func(_ ns.NetNS) error { 913 defer GinkgoRecover() 914 i, err := net.InterfaceByName(interfaceName) 915 Expect(err).To(BeNil()) 916 Expect(i.Name).To(Equal(interfaceName)) 917 addrs, err := i.Addrs() 918 Expect(err).To(BeNil()) 919 subnet1 := &net.IPNet{ 920 IP: ip1, 921 Mask: net.CIDRMask(64, 128), 922 } 923 subnet2 := &net.IPNet{ 924 IP: ip2, 925 Mask: net.CIDRMask(24, 32), 926 } 927 Expect(addrs).To(ContainElements(subnet1, subnet2)) 928 929 // check loopback adapter 930 i, err = net.InterfaceByName("lo") 931 Expect(err).To(BeNil()) 932 Expect(i.Name).To(Equal("lo")) 933 Expect(i.Flags & net.FlagLoopback).To(Equal(net.FlagLoopback)) 934 Expect(i.Flags&net.FlagUp).To(Equal(net.FlagUp), "Loopback adapter should be up") 935 936 return nil 937 }) 938 Expect(err).To(BeNil()) 939 940 err = libpodNet.Teardown(netNSContainer.Path(), types.TeardownOptions(setupOpts)) 941 Expect(err).To(BeNil()) 942 logString := logBuffer.String() 943 Expect(logString).To(BeEmpty()) 944 945 // check in the container namespace that the interface is removed 946 err = netNSContainer.Do(func(_ ns.NetNS) error { 947 defer GinkgoRecover() 948 _, err := net.InterfaceByName(interfaceName) 949 Expect(err).To(HaveOccurred()) 950 951 // check that only the loopback adapter is left 952 ints, err := net.Interfaces() 953 Expect(err).To(BeNil()) 954 Expect(ints).To(HaveLen(1)) 955 Expect(ints[0].Name).To(Equal("lo")) 956 Expect(ints[0].Flags & net.FlagLoopback).To(Equal(net.FlagLoopback)) 957 Expect(ints[0].Flags&net.FlagUp).To(Equal(net.FlagUp), "Loopback adapter should be up") 958 959 return nil 960 }) 961 Expect(err).To(BeNil()) 962 }) 963 }) 964 965 }) 966 967 Context("invalid network setup test", func() { 968 969 It("static ip not in subnet", func() { 970 runTest(func() { 971 defNet := types.DefaultNetworkName 972 intName := "eth0" 973 ip := "1.1.1.1" 974 setupOpts := types.SetupOptions{ 975 NetworkOptions: types.NetworkOptions{ 976 ContainerID: stringid.GenerateNonCryptoID(), 977 Networks: map[string]types.PerNetworkOptions{ 978 defNet: { 979 InterfaceName: intName, 980 StaticIPs: []net.IP{net.ParseIP(ip)}, 981 }, 982 }, 983 }, 984 } 985 _, err := libpodNet.Setup(netNSContainer.Path(), setupOpts) 986 Expect(err).To(HaveOccurred()) 987 Expect(err.Error()).To(ContainSubstring("requested static ip %s not in any subnet on network %s", ip, defNet)) 988 }) 989 }) 990 991 It("setup without namespace path", func() { 992 runTest(func() { 993 defNet := types.DefaultNetworkName 994 intName := "eth0" 995 setupOpts := types.SetupOptions{ 996 NetworkOptions: types.NetworkOptions{ 997 ContainerID: stringid.GenerateNonCryptoID(), 998 Networks: map[string]types.PerNetworkOptions{ 999 defNet: { 1000 InterfaceName: intName, 1001 }, 1002 }, 1003 }, 1004 } 1005 _, err := libpodNet.Setup("", setupOpts) 1006 Expect(err).To(HaveOccurred()) 1007 Expect(err.Error()).To(ContainSubstring("namespacePath is empty")) 1008 }) 1009 }) 1010 1011 It("setup with invalid namespace path", func() { 1012 runTest(func() { 1013 defNet := types.DefaultNetworkName 1014 intName := "eth0" 1015 setupOpts := types.SetupOptions{ 1016 NetworkOptions: types.NetworkOptions{ 1017 ContainerID: stringid.GenerateNonCryptoID(), 1018 Networks: map[string]types.PerNetworkOptions{ 1019 defNet: { 1020 InterfaceName: intName, 1021 }, 1022 }, 1023 }, 1024 } 1025 _, err := libpodNet.Setup("some path", setupOpts) 1026 Expect(err).To(HaveOccurred()) 1027 Expect(err.Error()).To(ContainSubstring(`"some path": no such file or directory`)) 1028 }) 1029 }) 1030 1031 It("setup without container ID", func() { 1032 runTest(func() { 1033 defNet := types.DefaultNetworkName 1034 intName := "eth0" 1035 setupOpts := types.SetupOptions{ 1036 NetworkOptions: types.NetworkOptions{ 1037 ContainerID: "", 1038 Networks: map[string]types.PerNetworkOptions{ 1039 defNet: { 1040 InterfaceName: intName, 1041 }, 1042 }, 1043 }, 1044 } 1045 _, err := libpodNet.Setup(netNSContainer.Path(), setupOpts) 1046 Expect(err).To(HaveOccurred()) 1047 Expect(err.Error()).To(ContainSubstring("ContainerID is empty")) 1048 }) 1049 }) 1050 1051 It("setup with aliases but dns disabled", func() { 1052 runTest(func() { 1053 defNet := types.DefaultNetworkName 1054 intName := "eth0" 1055 setupOpts := types.SetupOptions{ 1056 NetworkOptions: types.NetworkOptions{ 1057 ContainerID: stringid.GenerateNonCryptoID(), 1058 Networks: map[string]types.PerNetworkOptions{ 1059 defNet: { 1060 InterfaceName: intName, 1061 Aliases: []string{"somealias"}, 1062 }, 1063 }, 1064 }, 1065 } 1066 _, err := libpodNet.Setup(netNSContainer.Path(), setupOpts) 1067 Expect(err).To(HaveOccurred()) 1068 Expect(err.Error()).To(ContainSubstring("cannot set aliases on a network without dns enabled")) 1069 }) 1070 }) 1071 1072 It("setup without networks", func() { 1073 runTest(func() { 1074 setupOpts := types.SetupOptions{ 1075 NetworkOptions: types.NetworkOptions{ 1076 ContainerID: stringid.GenerateNonCryptoID(), 1077 }, 1078 } 1079 _, err := libpodNet.Setup(netNSContainer.Path(), setupOpts) 1080 Expect(err).To(HaveOccurred()) 1081 Expect(err.Error()).To(ContainSubstring("must specify at least one network")) 1082 }) 1083 }) 1084 1085 It("setup without interface name", func() { 1086 runTest(func() { 1087 defNet := types.DefaultNetworkName 1088 setupOpts := types.SetupOptions{ 1089 NetworkOptions: types.NetworkOptions{ 1090 ContainerID: stringid.GenerateNonCryptoID(), 1091 Networks: map[string]types.PerNetworkOptions{ 1092 defNet: { 1093 InterfaceName: "", 1094 }, 1095 }, 1096 }, 1097 } 1098 _, err := libpodNet.Setup(netNSContainer.Path(), setupOpts) 1099 Expect(err).To(HaveOccurred()) 1100 Expect(err.Error()).To(ContainSubstring("interface name on network %s is empty", defNet)) 1101 }) 1102 }) 1103 1104 It("setup does teardown on failure", func() { 1105 runTest(func() { 1106 subnet1, _ := types.ParseCIDR("192.168.0.0/24") 1107 network := types.Network{ 1108 Subnets: []types.Subnet{ 1109 {Subnet: subnet1}, 1110 }, 1111 } 1112 network1, err := libpodNet.NetworkCreate(network) 1113 Expect(err).To(BeNil()) 1114 1115 subnet2, _ := types.ParseCIDR("192.168.1.0/31") 1116 network = types.Network{ 1117 Subnets: []types.Subnet{ 1118 {Subnet: subnet2}, 1119 }, 1120 } 1121 network2, err := libpodNet.NetworkCreate(network) 1122 Expect(err).To(BeNil()) 1123 1124 intName1 := "eth0" 1125 intName2 := "eth1" 1126 netName1 := network1.Name 1127 netName2 := network2.Name 1128 1129 setupOpts := types.SetupOptions{ 1130 NetworkOptions: types.NetworkOptions{ 1131 ContainerID: stringid.GenerateNonCryptoID(), 1132 Networks: map[string]types.PerNetworkOptions{ 1133 netName1: { 1134 InterfaceName: intName1, 1135 }, 1136 netName2: { 1137 InterfaceName: intName2, 1138 }, 1139 }, 1140 }, 1141 } 1142 _, err = libpodNet.Setup(netNSContainer.Path(), setupOpts) 1143 Expect(err).To(HaveOccurred()) 1144 Expect(err.Error()).To(ContainSubstring("Network 192.168.1.0/31 too small to allocate from")) 1145 // Note: we call teardown on the failing net and log the error, it should be the same. 1146 logString := logBuffer.String() 1147 Expect(logString).To(ContainSubstring("Network 192.168.1.0/31 too small to allocate from")) 1148 1149 // check in the container namespace that no interface is there 1150 err = netNSContainer.Do(func(_ ns.NetNS) error { 1151 defer GinkgoRecover() 1152 _, err := net.InterfaceByName(intName1) 1153 Expect(err).To(HaveOccurred()) 1154 1155 // Note: We can check if intName2 is removed because 1156 // the cni plugin fails before it removes the interface 1157 1158 // check loopback adapter 1159 i, err := net.InterfaceByName("lo") 1160 Expect(err).To(BeNil()) 1161 Expect(i.Name).To(Equal("lo")) 1162 Expect(i.Flags & net.FlagLoopback).To(Equal(net.FlagLoopback)) 1163 Expect(i.Flags&net.FlagUp).To(Equal(net.FlagUp), "Loopback adapter should be up") 1164 return nil 1165 }) 1166 Expect(err).To(BeNil()) 1167 }) 1168 }) 1169 1170 It("setup with exposed invalid port protocol", func() { 1171 runTest(func() { 1172 defNet := types.DefaultNetworkName 1173 intName := "eth0" 1174 setupOpts := types.SetupOptions{ 1175 NetworkOptions: types.NetworkOptions{ 1176 ContainerID: stringid.GenerateNonCryptoID(), 1177 PortMappings: []types.PortMapping{{ 1178 Protocol: "someproto", 1179 HostIP: "127.0.0.1", 1180 HostPort: 5000, 1181 ContainerPort: 5000, 1182 }}, 1183 Networks: map[string]types.PerNetworkOptions{ 1184 defNet: {InterfaceName: intName}, 1185 }, 1186 }, 1187 } 1188 _, err := libpodNet.Setup(netNSContainer.Path(), setupOpts) 1189 Expect(err).To(HaveOccurred()) 1190 Expect(err.Error()).To(ContainSubstring("unknown port protocol someproto")) 1191 }) 1192 }) 1193 1194 It("setup with exposed empty port protocol", func() { 1195 runTest(func() { 1196 defNet := types.DefaultNetworkName 1197 intName := "eth0" 1198 setupOpts := types.SetupOptions{ 1199 NetworkOptions: types.NetworkOptions{ 1200 ContainerID: stringid.GenerateNonCryptoID(), 1201 PortMappings: []types.PortMapping{{ 1202 Protocol: "", 1203 HostIP: "127.0.0.1", 1204 HostPort: 5000, 1205 ContainerPort: 5000, 1206 }}, 1207 Networks: map[string]types.PerNetworkOptions{ 1208 defNet: {InterfaceName: intName}, 1209 }, 1210 }, 1211 } 1212 _, err := libpodNet.Setup(netNSContainer.Path(), setupOpts) 1213 Expect(err).To(HaveOccurred()) 1214 Expect(err.Error()).To(ContainSubstring("port protocol should not be empty")) 1215 }) 1216 }) 1217 1218 It("setup with unknown network", func() { 1219 runTest(func() { 1220 defNet := "somenet" 1221 intName := "eth0" 1222 setupOpts := types.SetupOptions{ 1223 NetworkOptions: types.NetworkOptions{ 1224 ContainerID: stringid.GenerateNonCryptoID(), 1225 Networks: map[string]types.PerNetworkOptions{ 1226 defNet: {InterfaceName: intName}, 1227 }, 1228 }, 1229 } 1230 _, err := libpodNet.Setup(netNSContainer.Path(), setupOpts) 1231 Expect(err).To(HaveOccurred()) 1232 Expect(err.Error()).To(ContainSubstring("network somenet: network not found")) 1233 }) 1234 }) 1235 1236 It("teardown with unknown network", func() { 1237 runTest(func() { 1238 interfaceName := "eth0" 1239 netName := "somenet" 1240 teardownOpts := types.TeardownOptions{ 1241 NetworkOptions: types.NetworkOptions{ 1242 ContainerID: stringid.GenerateNonCryptoID(), 1243 Networks: map[string]types.PerNetworkOptions{ 1244 netName: { 1245 InterfaceName: interfaceName, 1246 }, 1247 }, 1248 }, 1249 } 1250 1251 err := libpodNet.Teardown(netNSContainer.Path(), teardownOpts) 1252 Expect(err).To(HaveOccurred()) 1253 Expect(err.Error()).To(ContainSubstring("network somenet: network not found")) 1254 logString := logBuffer.String() 1255 Expect(logString).To(ContainSubstring("failed to load cached network config")) 1256 }) 1257 }) 1258 1259 It("teardown on not connected network", func() { 1260 runTest(func() { 1261 network := types.Network{} 1262 network1, err := libpodNet.NetworkCreate(network) 1263 Expect(err).To(BeNil()) 1264 1265 interfaceName := "eth0" 1266 netName := network1.Name 1267 teardownOpts := types.TeardownOptions{ 1268 NetworkOptions: types.NetworkOptions{ 1269 ContainerID: stringid.GenerateNonCryptoID(), 1270 Networks: map[string]types.PerNetworkOptions{ 1271 netName: { 1272 InterfaceName: interfaceName, 1273 }, 1274 }, 1275 }, 1276 } 1277 1278 // Most CNI plugins do not error on teardown when there is nothing to do. 1279 err = libpodNet.Teardown(netNSContainer.Path(), teardownOpts) 1280 Expect(err).To(BeNil()) 1281 logString := logBuffer.String() 1282 Expect(logString).To(ContainSubstring("failed to load cached network config")) 1283 }) 1284 }) 1285 }) 1286 }) 1287 1288 func runNetListener(wg *sync.WaitGroup, protocol, ip string, port int, expectedData string) { 1289 switch protocol { 1290 case "tcp": 1291 ln, err := net.Listen(protocol, net.JoinHostPort(ip, strconv.Itoa(port))) 1292 Expect(err).To(BeNil()) 1293 // make sure to read in a separate goroutine to not block 1294 go func() { 1295 defer GinkgoRecover() 1296 defer wg.Done() 1297 conn, err := ln.Accept() 1298 Expect(err).To(BeNil()) 1299 conn.SetDeadline(time.Now().Add(1 * time.Second)) 1300 data, err := ioutil.ReadAll(conn) 1301 Expect(err).To(BeNil()) 1302 Expect(string(data)).To(Equal(expectedData)) 1303 conn.Close() 1304 ln.Close() 1305 }() 1306 case "udp": 1307 conn, err := net.ListenUDP("udp", &net.UDPAddr{ 1308 IP: net.ParseIP(ip), 1309 Port: port, 1310 }) 1311 Expect(err).To(BeNil()) 1312 conn.SetDeadline(time.Now().Add(1 * time.Second)) 1313 go func() { 1314 defer GinkgoRecover() 1315 defer wg.Done() 1316 data := make([]byte, len(expectedData)) 1317 i, err := conn.Read(data) 1318 Expect(err).To(BeNil()) 1319 Expect(i).To(Equal(len(expectedData))) 1320 Expect(string(data)).To(Equal(expectedData)) 1321 conn.Close() 1322 }() 1323 default: 1324 Fail("unsupported protocol") 1325 } 1326 }