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