github.com/containers/podman/v4@v4.9.4/test/e2e/network_create_test.go (about) 1 package integration 2 3 import ( 4 "encoding/json" 5 "net" 6 7 "github.com/containers/common/libnetwork/types" 8 . "github.com/containers/podman/v4/test/utils" 9 "github.com/containers/storage/pkg/stringid" 10 . "github.com/onsi/ginkgo/v2" 11 . "github.com/onsi/gomega" 12 . "github.com/onsi/gomega/gexec" 13 ) 14 15 func removeNetworkDevice(name string) { 16 session := SystemExec("ip", []string{"link", "delete", name}) 17 session.WaitWithDefaultTimeout() 18 } 19 20 var _ = Describe("Podman network create", func() { 21 22 It("podman network create with name and subnet", func() { 23 netName := "subnet-" + stringid.GenerateRandomID() 24 nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.12.0/24", "--ip-range", "10.11.12.0/26", netName}) 25 nc.WaitWithDefaultTimeout() 26 defer podmanTest.removeNetwork(netName) 27 Expect(nc).Should(ExitCleanly()) 28 29 // Inspect the network configuration 30 inspect := podmanTest.Podman([]string{"network", "inspect", netName}) 31 inspect.WaitWithDefaultTimeout() 32 Expect(inspect).Should(ExitCleanly()) 33 34 // JSON the network configuration into something usable 35 var results []types.Network 36 err := json.Unmarshal([]byte(inspect.OutputToString()), &results) 37 Expect(err).ToNot(HaveOccurred()) 38 Expect(results).To(HaveLen(1)) 39 result := results[0] 40 Expect(result).To(HaveField("Name", netName)) 41 Expect(result.Subnets).To(HaveLen(1)) 42 Expect(result.Subnets[0].Subnet.String()).To(Equal("10.11.12.0/24")) 43 Expect(result.Subnets[0].Gateway.String()).To(Equal("10.11.12.1")) 44 Expect(result.Subnets[0].LeaseRange).ToNot(BeNil()) 45 Expect(result.Subnets[0].LeaseRange.StartIP.String()).To(Equal("10.11.12.1")) 46 Expect(result.Subnets[0].LeaseRange.EndIP.String()).To(Equal("10.11.12.63")) 47 48 // Once a container executes a new network, the nic will be created. We should clean those up 49 // best we can 50 defer removeNetworkDevice(result.NetworkInterface) 51 52 try := podmanTest.Podman([]string{"run", "--rm", "--network", netName, ALPINE, "sh", "-c", "ip addr show eth0 | awk ' /inet / {print $2}'"}) 53 try.WaitWithDefaultTimeout() 54 Expect(try).To(ExitCleanly()) 55 56 _, subnet, err := net.ParseCIDR("10.11.12.0/24") 57 Expect(err).ToNot(HaveOccurred()) 58 // Note this is an IPv4 test only! 59 containerIP, _, err := net.ParseCIDR(try.OutputToString()) 60 Expect(err).ToNot(HaveOccurred()) 61 // Ensure that the IP the container got is within the subnet the user asked for 62 Expect(subnet.Contains(containerIP)).To(BeTrue(), "subnet contains containerIP") 63 }) 64 65 It("podman network create with name and subnet and static route", func() { 66 SkipIfCNI(podmanTest) 67 netName := "subnet-" + stringid.GenerateRandomID() 68 nc := podmanTest.Podman([]string{ 69 "network", 70 "create", 71 "--subnet", 72 "10.19.12.0/24", 73 "--route", 74 "10.21.0.0/24,10.19.12.250", 75 netName, 76 }) 77 nc.WaitWithDefaultTimeout() 78 defer podmanTest.removeNetwork(netName) 79 Expect(nc).Should(ExitCleanly()) 80 81 // Inspect the network configuration 82 inspect := podmanTest.Podman([]string{"network", "inspect", netName}) 83 inspect.WaitWithDefaultTimeout() 84 Expect(inspect).Should(ExitCleanly()) 85 86 // JSON the network configuration into something usable 87 var results []types.Network 88 err := json.Unmarshal([]byte(inspect.OutputToString()), &results) 89 Expect(err).ToNot(HaveOccurred()) 90 Expect(results).To(HaveLen(1)) 91 result := results[0] 92 Expect(result).To(HaveField("Name", netName)) 93 Expect(result.Subnets).To(HaveLen(1)) 94 Expect(result.Subnets[0].Subnet.String()).To(Equal("10.19.12.0/24")) 95 Expect(result.Subnets[0].Gateway.String()).To(Equal("10.19.12.1")) 96 Expect(result.Routes[0].Destination.String()).To(Equal("10.21.0.0/24")) 97 Expect(result.Routes[0].Gateway.String()).To(Equal("10.19.12.250")) 98 Expect(result.Routes[0].Metric).To(BeNil()) 99 100 // Once a container executes a new network, the nic will be created. We should clean those up 101 // best we can 102 defer removeNetworkDevice(result.NetworkInterface) 103 104 }) 105 106 It("podman network create with name and subnet and static route and metric", func() { 107 SkipIfCNI(podmanTest) 108 netName := "subnet-" + stringid.GenerateRandomID() 109 nc := podmanTest.Podman([]string{ 110 "network", 111 "create", 112 "--subnet", 113 "10.19.13.0/24", 114 "--route", 115 "10.21.1.0/24,10.19.13.250,120", 116 netName, 117 }) 118 nc.WaitWithDefaultTimeout() 119 defer podmanTest.removeNetwork(netName) 120 Expect(nc).Should(ExitCleanly()) 121 122 // Inspect the network configuration 123 inspect := podmanTest.Podman([]string{"network", "inspect", netName}) 124 inspect.WaitWithDefaultTimeout() 125 Expect(inspect).Should(ExitCleanly()) 126 127 // JSON the network configuration into something usable 128 var results []types.Network 129 err := json.Unmarshal([]byte(inspect.OutputToString()), &results) 130 Expect(err).ToNot(HaveOccurred()) 131 Expect(results).To(HaveLen(1)) 132 result := results[0] 133 Expect(result).To(HaveField("Name", netName)) 134 Expect(result.Subnets).To(HaveLen(1)) 135 Expect(result.Subnets[0].Subnet.String()).To(Equal("10.19.13.0/24")) 136 Expect(result.Subnets[0].Gateway.String()).To(Equal("10.19.13.1")) 137 Expect(result.Routes[0].Destination.String()).To(Equal("10.21.1.0/24")) 138 Expect(result.Routes[0].Gateway.String()).To(Equal("10.19.13.250")) 139 Expect(*result.Routes[0].Metric).To(Equal(uint32(120))) 140 141 // Once a container executes a new network, the nic will be created. We should clean those up 142 // best we can 143 defer removeNetworkDevice(result.NetworkInterface) 144 145 }) 146 147 It("podman network create with name and subnet and two static routes", func() { 148 SkipIfCNI(podmanTest) 149 netName := "subnet-" + stringid.GenerateRandomID() 150 nc := podmanTest.Podman([]string{ 151 "network", 152 "create", 153 "--subnet", 154 "10.19.14.0/24", 155 "--route", 156 "10.21.2.0/24,10.19.14.250", 157 "--route", 158 "10.21.3.0/24,10.19.14.251,120", 159 netName, 160 }) 161 nc.WaitWithDefaultTimeout() 162 defer podmanTest.removeNetwork(netName) 163 Expect(nc).Should(ExitCleanly()) 164 165 // Inspect the network configuration 166 inspect := podmanTest.Podman([]string{"network", "inspect", netName}) 167 inspect.WaitWithDefaultTimeout() 168 Expect(inspect).Should(ExitCleanly()) 169 170 // JSON the network configuration into something usable 171 var results []types.Network 172 err := json.Unmarshal([]byte(inspect.OutputToString()), &results) 173 Expect(err).ToNot(HaveOccurred()) 174 Expect(results).To(HaveLen(1)) 175 result := results[0] 176 Expect(result).To(HaveField("Name", netName)) 177 Expect(result.Subnets).To(HaveLen(1)) 178 Expect(result.Subnets[0].Subnet.String()).To(Equal("10.19.14.0/24")) 179 Expect(result.Subnets[0].Gateway.String()).To(Equal("10.19.14.1")) 180 Expect(result.Routes).To(HaveLen(2)) 181 Expect(result.Routes[0].Destination.String()).To(Equal("10.21.2.0/24")) 182 Expect(result.Routes[0].Gateway.String()).To(Equal("10.19.14.250")) 183 Expect(result.Routes[0].Metric).To(BeNil()) 184 Expect(result.Routes[1].Destination.String()).To(Equal("10.21.3.0/24")) 185 Expect(result.Routes[1].Gateway.String()).To(Equal("10.19.14.251")) 186 Expect(*result.Routes[1].Metric).To(Equal(uint32(120))) 187 188 // Once a container executes a new network, the nic will be created. We should clean those up 189 // best we can 190 defer removeNetworkDevice(result.NetworkInterface) 191 192 }) 193 194 It("podman network create with name and subnet and static route (ipv6)", func() { 195 SkipIfCNI(podmanTest) 196 netName := "subnet-" + stringid.GenerateRandomID() 197 nc := podmanTest.Podman([]string{ 198 "network", 199 "create", 200 "--subnet", 201 "fd:ab04::/64", 202 "--route", 203 "fd:1::/64,fd::1,120", 204 netName, 205 }) 206 nc.WaitWithDefaultTimeout() 207 defer podmanTest.removeNetwork(netName) 208 Expect(nc).Should(ExitCleanly()) 209 210 // Inspect the network configuration 211 inspect := podmanTest.Podman([]string{"network", "inspect", netName}) 212 inspect.WaitWithDefaultTimeout() 213 Expect(inspect).Should(ExitCleanly()) 214 215 // JSON the network configuration into something usable 216 var results []types.Network 217 err := json.Unmarshal([]byte(inspect.OutputToString()), &results) 218 Expect(err).ToNot(HaveOccurred()) 219 Expect(results).To(HaveLen(1)) 220 result := results[0] 221 Expect(result).To(HaveField("Name", netName)) 222 Expect(result.Subnets).To(HaveLen(1)) 223 Expect(result.Subnets[0].Subnet.String()).To(Equal("fd:ab04::/64")) 224 Expect(result.Subnets[0].Gateway.String()).To(Equal("fd:ab04::1")) 225 Expect(result.Routes[0].Destination.String()).To(Equal("fd:1::/64")) 226 Expect(result.Routes[0].Gateway.String()).To(Equal("fd::1")) 227 Expect(*result.Routes[0].Metric).To(Equal(uint32(120))) 228 229 // Once a container executes a new network, the nic will be created. We should clean those up 230 // best we can 231 defer removeNetworkDevice(result.NetworkInterface) 232 233 }) 234 235 It("podman network create with name and subnet with --opt no_default_route=1", func() { 236 SkipIfCNI(podmanTest) 237 netName := "subnet-" + stringid.GenerateRandomID() 238 nc := podmanTest.Podman([]string{ 239 "network", 240 "create", 241 "--subnet", 242 "10.19.15.0/24", 243 "--opt", 244 "no_default_route=1", 245 netName, 246 }) 247 nc.WaitWithDefaultTimeout() 248 defer podmanTest.removeNetwork(netName) 249 Expect(nc).Should(ExitCleanly()) 250 251 // Inspect the network configuration 252 inspect := podmanTest.Podman([]string{"network", "inspect", netName}) 253 inspect.WaitWithDefaultTimeout() 254 Expect(inspect).Should(ExitCleanly()) 255 256 // JSON the network configuration into something usable 257 var results []types.Network 258 err := json.Unmarshal([]byte(inspect.OutputToString()), &results) 259 Expect(err).ToNot(HaveOccurred()) 260 Expect(results).To(HaveLen(1)) 261 result := results[0] 262 Expect(result).To(HaveField("Name", netName)) 263 Expect(result.Subnets).To(HaveLen(1)) 264 Expect(result.Subnets[0].Subnet.String()).To(Equal("10.19.15.0/24")) 265 Expect(result.Subnets[0].Gateway.String()).To(Equal("10.19.15.1")) 266 Expect(result.Options[types.NoDefaultRoute]).To(Equal("true")) 267 268 // Once a container executes a new network, the nic will be created. We should clean those up 269 // best we can 270 defer removeNetworkDevice(result.NetworkInterface) 271 272 }) 273 274 It("podman network create with name and IPv6 subnet", func() { 275 netName := "ipv6-" + stringid.GenerateRandomID() 276 nc := podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:1:2:3:4::/64", netName}) 277 nc.WaitWithDefaultTimeout() 278 defer podmanTest.removeNetwork(netName) 279 Expect(nc).Should(ExitCleanly()) 280 281 // Inspect the network configuration 282 inspect := podmanTest.Podman([]string{"network", "inspect", netName}) 283 inspect.WaitWithDefaultTimeout() 284 Expect(inspect).Should(ExitCleanly()) 285 286 // JSON the network configuration into something usable 287 var results []types.Network 288 err := json.Unmarshal([]byte(inspect.OutputToString()), &results) 289 Expect(err).ToNot(HaveOccurred()) 290 Expect(results).To(HaveLen(1)) 291 result := results[0] 292 Expect(result).To(HaveField("Name", netName)) 293 Expect(result.Subnets).To(HaveLen(1)) 294 Expect(result.Subnets[0].Gateway.String()).To(Equal("fd00:1:2:3::1")) 295 Expect(result.Subnets[0].Subnet.String()).To(Equal("fd00:1:2:3::/64")) 296 297 // Once a container executes a new network, the nic will be created. We should clean those up 298 // best we can 299 defer removeNetworkDevice(result.NetworkInterface) 300 301 try := podmanTest.Podman([]string{"run", "--rm", "--network", netName, ALPINE, "sh", "-c", "ip addr show eth0 | grep global | awk ' /inet6 / {print $2}'"}) 302 try.WaitWithDefaultTimeout() 303 Expect(try).To(ExitCleanly()) 304 305 _, subnet, err := net.ParseCIDR("fd00:1:2:3:4::/64") 306 Expect(err).ToNot(HaveOccurred()) 307 containerIP, _, err := net.ParseCIDR(try.OutputToString()) 308 Expect(err).ToNot(HaveOccurred()) 309 // Ensure that the IP the container got is within the subnet the user asked for 310 Expect(subnet.Contains(containerIP)).To(BeTrue(), "subnet contains containerIP") 311 }) 312 313 It("podman network create with name and IPv6 flag (dual-stack)", func() { 314 netName := "dual-" + stringid.GenerateRandomID() 315 nc := podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:4:3:2::/64", "--ipv6", netName}) 316 nc.WaitWithDefaultTimeout() 317 defer podmanTest.removeNetwork(netName) 318 Expect(nc).Should(ExitCleanly()) 319 320 // Inspect the network configuration 321 inspect := podmanTest.Podman([]string{"network", "inspect", netName}) 322 inspect.WaitWithDefaultTimeout() 323 Expect(inspect).Should(ExitCleanly()) 324 325 // JSON the network configuration into something usable 326 var results []types.Network 327 err := json.Unmarshal([]byte(inspect.OutputToString()), &results) 328 Expect(err).ToNot(HaveOccurred()) 329 Expect(results).To(HaveLen(1)) 330 result := results[0] 331 Expect(result).To(HaveField("Name", netName)) 332 Expect(result.Subnets).To(HaveLen(2)) 333 Expect(result.Subnets[0].Subnet.IP).ToNot(BeNil()) 334 Expect(result.Subnets[1].Subnet.IP).ToNot(BeNil()) 335 336 _, subnet11, err := net.ParseCIDR(result.Subnets[0].Subnet.String()) 337 Expect(err).ToNot(HaveOccurred()) 338 _, subnet12, err := net.ParseCIDR(result.Subnets[1].Subnet.String()) 339 Expect(err).ToNot(HaveOccurred()) 340 341 // Once a container executes a new network, the nic will be created. We should clean those up 342 // best we can 343 defer removeNetworkDevice(result.NetworkInterface) 344 345 // create a second network to check the auto assigned ipv4 subnet does not overlap 346 // https://github.com/containers/podman/issues/11032 347 netName2 := "dual-" + stringid.GenerateRandomID() 348 nc = podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:10:3:2::/64", "--ipv6", netName2}) 349 nc.WaitWithDefaultTimeout() 350 defer podmanTest.removeNetwork(netName2) 351 Expect(nc).Should(ExitCleanly()) 352 353 // Inspect the network configuration 354 inspect = podmanTest.Podman([]string{"network", "inspect", netName2}) 355 inspect.WaitWithDefaultTimeout() 356 Expect(inspect).Should(ExitCleanly()) 357 358 // JSON the network configuration into something usable 359 err = json.Unmarshal([]byte(inspect.OutputToString()), &results) 360 Expect(err).ToNot(HaveOccurred()) 361 Expect(results).To(HaveLen(1)) 362 result = results[0] 363 Expect(result).To(HaveField("Name", netName2)) 364 Expect(result.Subnets).To(HaveLen(2)) 365 Expect(result.Subnets[0].Subnet.IP).ToNot(BeNil()) 366 Expect(result.Subnets[1].Subnet.IP).ToNot(BeNil()) 367 368 _, subnet21, err := net.ParseCIDR(result.Subnets[0].Subnet.String()) 369 Expect(err).ToNot(HaveOccurred()) 370 _, subnet22, err := net.ParseCIDR(result.Subnets[1].Subnet.String()) 371 Expect(err).ToNot(HaveOccurred()) 372 373 // check that the subnets do not overlap 374 Expect(subnet11.Contains(subnet21.IP)).To(BeFalse()) 375 Expect(subnet12.Contains(subnet22.IP)).To(BeFalse()) 376 377 try := podmanTest.Podman([]string{"run", "--rm", "--network", netName, ALPINE, "sh", "-c", "ip addr show eth0 | grep global | awk ' /inet6 / {print $2}'"}) 378 try.WaitWithDefaultTimeout() 379 380 _, subnet, err := net.ParseCIDR("fd00:4:3:2:1::/64") 381 Expect(err).ToNot(HaveOccurred()) 382 containerIP, _, err := net.ParseCIDR(try.OutputToString()) 383 Expect(err).ToNot(HaveOccurred()) 384 // Ensure that the IP the container got is within the subnet the user asked for 385 Expect(subnet.Contains(containerIP)).To(BeTrue(), "subnet contains containerIP") 386 // verify the container has an IPv4 address too (the IPv4 subnet is autogenerated) 387 try = podmanTest.Podman([]string{"run", "--rm", "--network", netName, ALPINE, "sh", "-c", "ip addr show eth0 | awk ' /inet / {print $2}'"}) 388 try.WaitWithDefaultTimeout() 389 containerIP, _, err = net.ParseCIDR(try.OutputToString()) 390 Expect(err).ToNot(HaveOccurred()) 391 Expect(containerIP.To4()).To(Not(BeNil())) 392 }) 393 394 It("podman network create with invalid subnet", func() { 395 nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.12.0/17000", stringid.GenerateRandomID()}) 396 nc.WaitWithDefaultTimeout() 397 Expect(nc).To(ExitWithError()) 398 }) 399 400 It("podman network create with ipv4 subnet and ipv6 flag", func() { 401 name := stringid.GenerateRandomID() 402 nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.14.0/24", "--ipv6", name}) 403 nc.WaitWithDefaultTimeout() 404 Expect(nc).To(ExitCleanly()) 405 defer podmanTest.removeNetwork(name) 406 407 nc = podmanTest.Podman([]string{"network", "inspect", name}) 408 nc.WaitWithDefaultTimeout() 409 Expect(nc).To(ExitCleanly()) 410 Expect(nc.OutputToString()).To(ContainSubstring(`::/64`)) 411 Expect(nc.OutputToString()).To(ContainSubstring(`10.11.14.0/24`)) 412 }) 413 414 It("podman network create with empty subnet and ipv6 flag", func() { 415 name := stringid.GenerateRandomID() 416 nc := podmanTest.Podman([]string{"network", "create", "--ipv6", name}) 417 nc.WaitWithDefaultTimeout() 418 Expect(nc).To(ExitCleanly()) 419 defer podmanTest.removeNetwork(name) 420 421 nc = podmanTest.Podman([]string{"network", "inspect", name}) 422 nc.WaitWithDefaultTimeout() 423 Expect(nc).To(ExitCleanly()) 424 Expect(nc.OutputToString()).To(ContainSubstring(`::/64`)) 425 Expect(nc.OutputToString()).To(ContainSubstring(`.0/24`)) 426 }) 427 428 It("podman network create with invalid IP", func() { 429 nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.0/17000", stringid.GenerateRandomID()}) 430 nc.WaitWithDefaultTimeout() 431 Expect(nc).To(ExitWithError()) 432 }) 433 434 It("podman network create with invalid gateway for subnet", func() { 435 nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.12.0/24", "--gateway", "192.168.1.1", stringid.GenerateRandomID()}) 436 nc.WaitWithDefaultTimeout() 437 Expect(nc).To(ExitWithError()) 438 }) 439 440 It("podman network create two networks with same name should fail", func() { 441 netName := "same-" + stringid.GenerateRandomID() 442 nc := podmanTest.Podman([]string{"network", "create", netName}) 443 nc.WaitWithDefaultTimeout() 444 defer podmanTest.removeNetwork(netName) 445 Expect(nc).Should(ExitCleanly()) 446 447 ncFail := podmanTest.Podman([]string{"network", "create", netName}) 448 ncFail.WaitWithDefaultTimeout() 449 Expect(ncFail).To(ExitWithError()) 450 }) 451 452 It("podman network create two networks with same subnet should fail", func() { 453 netName1 := "sub1-" + stringid.GenerateRandomID() 454 nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.13.0/24", netName1}) 455 nc.WaitWithDefaultTimeout() 456 defer podmanTest.removeNetwork(netName1) 457 Expect(nc).Should(ExitCleanly()) 458 459 netName2 := "sub2-" + stringid.GenerateRandomID() 460 ncFail := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.13.0/24", netName2}) 461 ncFail.WaitWithDefaultTimeout() 462 defer podmanTest.removeNetwork(netName2) 463 Expect(ncFail).To(ExitWithError()) 464 }) 465 466 It("podman network create two IPv6 networks with same subnet should fail", func() { 467 netName1 := "subipv61-" + stringid.GenerateRandomID() 468 nc := podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:4:4:4:4::/64", "--ipv6", netName1}) 469 nc.WaitWithDefaultTimeout() 470 defer podmanTest.removeNetwork(netName1) 471 Expect(nc).Should(ExitCleanly()) 472 473 netName2 := "subipv62-" + stringid.GenerateRandomID() 474 ncFail := podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:4:4:4:4::/64", "--ipv6", netName2}) 475 ncFail.WaitWithDefaultTimeout() 476 defer podmanTest.removeNetwork(netName2) 477 Expect(ncFail).To(ExitWithError()) 478 }) 479 480 It("podman network create with invalid network name", func() { 481 nc := podmanTest.Podman([]string{"network", "create", "foo "}) 482 nc.WaitWithDefaultTimeout() 483 Expect(nc).To(ExitWithError()) 484 }) 485 486 It("podman network create with mtu option", func() { 487 net := "mtu-test" + stringid.GenerateRandomID() 488 nc := podmanTest.Podman([]string{"network", "create", "--opt", "mtu=9000", net}) 489 nc.WaitWithDefaultTimeout() 490 defer podmanTest.removeNetwork(net) 491 Expect(nc).Should(ExitCleanly()) 492 493 nc = podmanTest.Podman([]string{"network", "inspect", net}) 494 nc.WaitWithDefaultTimeout() 495 Expect(nc).Should(ExitCleanly()) 496 Expect(nc.OutputToString()).To(ContainSubstring(`"mtu": "9000"`)) 497 }) 498 499 It("podman network create with vlan option", func() { 500 net := "vlan-test" + stringid.GenerateRandomID() 501 nc := podmanTest.Podman([]string{"network", "create", "--opt", "vlan=9", net}) 502 nc.WaitWithDefaultTimeout() 503 defer podmanTest.removeNetwork(net) 504 Expect(nc).Should(ExitCleanly()) 505 506 nc = podmanTest.Podman([]string{"network", "inspect", net}) 507 nc.WaitWithDefaultTimeout() 508 Expect(nc).Should(ExitCleanly()) 509 Expect(nc.OutputToString()).To(ContainSubstring(`"vlan": "9"`)) 510 }) 511 512 It("podman network create with invalid option", func() { 513 net := "invalid-test" + stringid.GenerateRandomID() 514 nc := podmanTest.Podman([]string{"network", "create", "--opt", "foo=bar", net}) 515 nc.WaitWithDefaultTimeout() 516 defer podmanTest.removeNetwork(net) 517 Expect(nc).To(ExitWithError()) 518 }) 519 520 It("podman CNI network create with internal should not have dnsname", func() { 521 SkipIfNetavark(podmanTest) 522 net := "internal-test" + stringid.GenerateRandomID() 523 nc := podmanTest.Podman([]string{"network", "create", "--internal", net}) 524 nc.WaitWithDefaultTimeout() 525 defer podmanTest.removeNetwork(net) 526 // Cannot ExitCleanly(): "dnsname and internal networks are incompatible" 527 Expect(nc).Should(Exit(0)) 528 // Not performing this check on remote tests because it is a logrus error which does 529 // not come back via stderr on the remote client. 530 if !IsRemote() { 531 Expect(nc.ErrorToString()).To(ContainSubstring("dnsname and internal networks are incompatible")) 532 } 533 nc = podmanTest.Podman([]string{"network", "inspect", net}) 534 nc.WaitWithDefaultTimeout() 535 Expect(nc).Should(ExitCleanly()) 536 Expect(nc.OutputToString()).ToNot(ContainSubstring("dnsname")) 537 }) 538 539 It("podman Netavark network create with internal should have dnsname", func() { 540 SkipIfCNI(podmanTest) 541 net := "internal-test" + stringid.GenerateRandomID() 542 nc := podmanTest.Podman([]string{"network", "create", "--internal", net}) 543 nc.WaitWithDefaultTimeout() 544 defer podmanTest.removeNetwork(net) 545 Expect(nc).Should(ExitCleanly()) 546 // Not performing this check on remote tests because it is a logrus error which does 547 // not come back via stderr on the remote client. 548 if !IsRemote() { 549 Expect(nc.ErrorToString()).To(BeEmpty()) 550 } 551 nc = podmanTest.Podman([]string{"network", "inspect", net}) 552 nc.WaitWithDefaultTimeout() 553 Expect(nc).Should(ExitCleanly()) 554 Expect(nc.OutputToString()).To(ContainSubstring(`"dns_enabled": true`)) 555 }) 556 557 It("podman network create with invalid name", func() { 558 for _, name := range []string{"none", "host", "bridge", "private", "slirp4netns", "container", "ns", "default"} { 559 nc := podmanTest.Podman([]string{"network", "create", name}) 560 nc.WaitWithDefaultTimeout() 561 Expect(nc).To(Exit(125)) 562 Expect(nc.ErrorToString()).To(ContainSubstring("cannot create network with name %q because it conflicts with a valid network mode", name)) 563 } 564 }) 565 566 It("podman network create with multiple subnets", func() { 567 name := "subnets-" + stringid.GenerateRandomID() 568 subnet1 := "10.10.0.0/24" 569 subnet2 := "10.10.1.0/24" 570 nc := podmanTest.Podman([]string{"network", "create", "--subnet", subnet1, "--subnet", subnet2, name}) 571 nc.WaitWithDefaultTimeout() 572 defer podmanTest.removeNetwork(name) 573 Expect(nc).To(ExitCleanly()) 574 Expect(nc.OutputToString()).To(Equal(name)) 575 576 inspect := podmanTest.Podman([]string{"network", "inspect", name}) 577 inspect.WaitWithDefaultTimeout() 578 Expect(inspect).To(ExitCleanly()) 579 Expect(inspect.OutputToString()).To(ContainSubstring(`"subnet": "` + subnet1)) 580 Expect(inspect.OutputToString()).To(ContainSubstring(`"subnet": "` + subnet2)) 581 Expect(inspect.OutputToString()).To(ContainSubstring(`"ipv6_enabled": false`)) 582 }) 583 584 It("podman network create with multiple subnets dual stack", func() { 585 name := "subnets-" + stringid.GenerateRandomID() 586 subnet1 := "10.10.2.0/24" 587 subnet2 := "fd52:2a5a:747e:3acd::/64" 588 nc := podmanTest.Podman([]string{"network", "create", "--subnet", subnet1, "--subnet", subnet2, name}) 589 nc.WaitWithDefaultTimeout() 590 defer podmanTest.removeNetwork(name) 591 Expect(nc).To(ExitCleanly()) 592 Expect(nc.OutputToString()).To(Equal(name)) 593 594 inspect := podmanTest.Podman([]string{"network", "inspect", name}) 595 inspect.WaitWithDefaultTimeout() 596 Expect(inspect).To(ExitCleanly()) 597 Expect(inspect.OutputToString()).To(ContainSubstring(`"subnet": "` + subnet1)) 598 Expect(inspect.OutputToString()).To(ContainSubstring(`"subnet": "` + subnet2)) 599 Expect(inspect.OutputToString()).To(ContainSubstring(`"ipv6_enabled": true`)) 600 }) 601 602 It("podman network create with multiple subnets dual stack with gateway and range", func() { 603 name := "subnets-" + stringid.GenerateRandomID() 604 subnet1 := "10.10.3.0/24" 605 gw1 := "10.10.3.10" 606 range1 := "10.10.3.0/26" 607 subnet2 := "fd52:2a5a:747e:3ace::/64" 608 gw2 := "fd52:2a5a:747e:3ace::10" 609 nc := podmanTest.Podman([]string{"network", "create", "--subnet", subnet1, "--gateway", gw1, "--ip-range", range1, "--subnet", subnet2, "--gateway", gw2, name}) 610 nc.WaitWithDefaultTimeout() 611 defer podmanTest.removeNetwork(name) 612 Expect(nc).To(ExitCleanly()) 613 Expect(nc.OutputToString()).To(Equal(name)) 614 615 inspect := podmanTest.Podman([]string{"network", "inspect", name}) 616 inspect.WaitWithDefaultTimeout() 617 Expect(inspect).To(ExitCleanly()) 618 Expect(inspect.OutputToString()).To(ContainSubstring(`"subnet": "` + subnet1)) 619 Expect(inspect.OutputToString()).To(ContainSubstring(`"gateway": "` + gw1)) 620 Expect(inspect.OutputToString()).To(ContainSubstring(`"start_ip": "10.10.3.1",`)) 621 Expect(inspect.OutputToString()).To(ContainSubstring(`"end_ip": "10.10.3.63"`)) 622 Expect(inspect.OutputToString()).To(ContainSubstring(`"subnet": "` + subnet2)) 623 Expect(inspect.OutputToString()).To(ContainSubstring(`"gateway": "` + gw2)) 624 Expect(inspect.OutputToString()).To(ContainSubstring(`"ipv6_enabled": true`)) 625 }) 626 627 It("podman network create invalid options with multiple subnets", func() { 628 name := "subnets-" + stringid.GenerateRandomID() 629 subnet1 := "10.10.3.0/24" 630 gw1 := "10.10.3.10" 631 gw2 := "fd52:2a5a:747e:3acf::10" 632 nc := podmanTest.Podman([]string{"network", "create", "--subnet", subnet1, "--gateway", gw1, "--gateway", gw2, name}) 633 nc.WaitWithDefaultTimeout() 634 Expect(nc).To(Exit(125)) 635 Expect(nc.ErrorToString()).To(Equal("Error: cannot set more gateways than subnets")) 636 637 range1 := "10.10.3.0/26" 638 range2 := "10.10.3.0/28" 639 nc = podmanTest.Podman([]string{"network", "create", "--subnet", subnet1, "--ip-range", range1, "--ip-range", range2, name}) 640 nc.WaitWithDefaultTimeout() 641 Expect(nc).To(Exit(125)) 642 Expect(nc.ErrorToString()).To(Equal("Error: cannot set more ranges than subnets")) 643 }) 644 645 It("podman network create same name - fail", func() { 646 name := "same-name-" + stringid.GenerateRandomID() 647 networkCreateCommand := []string{"network", "create", name} 648 nc := podmanTest.Podman(networkCreateCommand) 649 nc.WaitWithDefaultTimeout() 650 defer podmanTest.removeNetwork(name) 651 Expect(nc).To(ExitCleanly()) 652 Expect(nc.OutputToString()).To(Equal(name)) 653 654 nc = podmanTest.Podman(networkCreateCommand) 655 nc.WaitWithDefaultTimeout() 656 Expect(nc).To(Exit(125)) 657 }) 658 659 It("podman network create same name - succeed with ignore", func() { 660 name := "same-name-" + stringid.GenerateRandomID() 661 networkCreateCommand := []string{"network", "create", "--ignore", name} 662 nc := podmanTest.Podman(networkCreateCommand) 663 nc.WaitWithDefaultTimeout() 664 defer podmanTest.removeNetwork(name) 665 Expect(nc).To(ExitCleanly()) 666 Expect(nc.OutputToString()).To(Equal(name)) 667 668 nc = podmanTest.Podman(networkCreateCommand) 669 nc.WaitWithDefaultTimeout() 670 Expect(nc).To(ExitCleanly()) 671 Expect(nc.OutputToString()).To(Equal(name)) 672 }) 673 674 It("podman network create --interface-name", func() { 675 netName := "bridge-" + stringid.GenerateRandomID() 676 bridgeName := "mybridge" + stringid.GenerateRandomID()[:4] 677 nc := podmanTest.Podman([]string{"network", "create", "--interface-name", bridgeName, netName}) 678 nc.WaitWithDefaultTimeout() 679 defer podmanTest.removeNetwork(netName) 680 Expect(nc).To(ExitCleanly()) 681 Expect(nc.OutputToString()).To(Equal(netName)) 682 683 session := podmanTest.Podman([]string{"network", "inspect", "--format", "{{.NetworkInterface}}", netName}) 684 session.WaitWithDefaultTimeout() 685 Expect(session).To(ExitCleanly()) 686 Expect(session.OutputToString()).To(Equal(bridgeName)) 687 688 session = podmanTest.Podman([]string{"run", "-d", "--network", netName, ALPINE, "top"}) 689 session.WaitWithDefaultTimeout() 690 Expect(session).To(ExitCleanly()) 691 692 // can only check this as root 693 if !isRootless() { 694 // make sure cni/netavark created bridge with expected name 695 bridge, err := net.InterfaceByName(bridgeName) 696 Expect(err).ToNot(HaveOccurred()) 697 Expect(bridge.Name).To(Equal(bridgeName)) 698 } 699 }) 700 701 It("podman network create --ip-range sip-eip", func() { 702 netName := "subnet-" + stringid.GenerateRandomID() 703 nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.16.0/24", "--ip-range", "10.11.16.11-10.11.16.12", netName}) 704 nc.WaitWithDefaultTimeout() 705 defer podmanTest.removeNetwork(netName) 706 Expect(nc).Should(ExitCleanly()) 707 708 // Inspect the network configuration 709 inspect := podmanTest.Podman([]string{"network", "inspect", netName}) 710 inspect.WaitWithDefaultTimeout() 711 Expect(inspect).Should(ExitCleanly()) 712 713 // JSON the network configuration into something usable 714 var results []types.Network 715 err := json.Unmarshal([]byte(inspect.OutputToString()), &results) 716 Expect(err).ToNot(HaveOccurred()) 717 Expect(results).To(HaveLen(1)) 718 result := results[0] 719 Expect(result).To(HaveField("Name", netName)) 720 Expect(result.Subnets).To(HaveLen(1)) 721 Expect(result.Subnets[0].Subnet.String()).To(Equal("10.11.16.0/24")) 722 Expect(result.Subnets[0].Gateway.String()).To(Equal("10.11.16.1")) 723 Expect(result.Subnets[0].LeaseRange).ToNot(BeNil()) 724 Expect(result.Subnets[0].LeaseRange.StartIP.String()).To(Equal("10.11.16.11")) 725 Expect(result.Subnets[0].LeaseRange.EndIP.String()).To(Equal("10.11.16.12")) 726 727 try := podmanTest.Podman([]string{"run", "--rm", "--network", netName, ALPINE, "sh", "-c", "ip addr show eth0 | awk ' /inet / {print $2}'"}) 728 try.WaitWithDefaultTimeout() 729 Expect(try).To(ExitCleanly()) 730 731 containerIP, _, err := net.ParseCIDR(try.OutputToString()) 732 Expect(err).ToNot(HaveOccurred()) 733 // Note as of today (June 2023) we always get the first ip from netavark and cni but let's not depend on that. 734 // All we care about is the ip is from the range which allows for both. 735 Expect(containerIP.String()).To(Or(Equal("10.11.16.11"), Equal("10.11.16.12")), "ip address must be in --ip-range") 736 }) 737 })