github.com/AbhinandanKurakure/podman/v3@v3.4.10/test/e2e/network_create_test.go (about) 1 package integration 2 3 import ( 4 "encoding/json" 5 "io/ioutil" 6 "net" 7 "os" 8 "strings" 9 10 cniversion "github.com/containernetworking/cni/pkg/version" 11 "github.com/containers/podman/v3/libpod/network" 12 . "github.com/containers/podman/v3/test/utils" 13 "github.com/containers/storage/pkg/stringid" 14 . "github.com/onsi/ginkgo" 15 . "github.com/onsi/gomega" 16 . "github.com/onsi/gomega/gexec" 17 "github.com/pkg/errors" 18 ) 19 20 var ErrPluginNotFound = errors.New("plugin not found") 21 22 func findPluginByName(plugins interface{}, pluginType string) (interface{}, error) { 23 for _, p := range plugins.([]interface{}) { 24 r := p.(map[string]interface{}) 25 if pluginType == r["type"] { 26 return p, nil 27 } 28 } 29 return nil, errors.Wrap(ErrPluginNotFound, pluginType) 30 } 31 32 func genericPluginsToBridge(plugins interface{}, pluginType string) (network.HostLocalBridge, error) { 33 var bridge network.HostLocalBridge 34 generic, err := findPluginByName(plugins, pluginType) 35 if err != nil { 36 return bridge, err 37 } 38 b, err := json.Marshal(generic) 39 if err != nil { 40 return bridge, err 41 } 42 err = json.Unmarshal(b, &bridge) 43 return bridge, err 44 } 45 46 func genericPluginsToPortMap(plugins interface{}, pluginType string) (network.PortMapConfig, error) { 47 var portMap network.PortMapConfig 48 generic, err := findPluginByName(plugins, "portmap") 49 if err != nil { 50 return portMap, err 51 } 52 b, err := json.Marshal(generic) 53 if err != nil { 54 return portMap, err 55 } 56 err = json.Unmarshal(b, &portMap) 57 return portMap, err 58 } 59 60 func removeNetworkDevice(name string) { 61 session := SystemExec("ip", []string{"link", "delete", name}) 62 session.WaitWithDefaultTimeout() 63 } 64 65 var _ = Describe("Podman network create", func() { 66 var ( 67 tempdir string 68 err error 69 podmanTest *PodmanTestIntegration 70 ) 71 72 BeforeEach(func() { 73 tempdir, err = CreateTempDirInTempDir() 74 if err != nil { 75 os.Exit(1) 76 } 77 podmanTest = PodmanTestCreate(tempdir) 78 podmanTest.Setup() 79 podmanTest.SeedImages() 80 }) 81 82 AfterEach(func() { 83 podmanTest.Cleanup() 84 f := CurrentGinkgoTestDescription() 85 processTestResult(f) 86 }) 87 88 It("podman network create with no input", func() { 89 var result network.NcList 90 91 nc := podmanTest.Podman([]string{"network", "create"}) 92 nc.WaitWithDefaultTimeout() 93 Expect(nc).Should(Exit(0)) 94 95 fileContent, err := ioutil.ReadFile(nc.OutputToString()) 96 Expect(err).To(BeNil()) 97 err = json.Unmarshal(fileContent, &result) 98 Expect(err).To(BeNil()) 99 defer podmanTest.removeCNINetwork(result["name"].(string)) 100 Expect(result["cniVersion"]).To(Equal(cniversion.Current())) 101 Expect(strings.HasPrefix(result["name"].(string), "cni-podman")).To(BeTrue()) 102 103 bridgePlugin, err := genericPluginsToBridge(result["plugins"], "bridge") 104 Expect(err).To(BeNil()) 105 portMapPlugin, err := genericPluginsToPortMap(result["plugins"], "portmap") 106 Expect(err).To(BeNil()) 107 108 Expect(bridgePlugin.IPAM.Routes[0].Dest).To(Equal("0.0.0.0/0")) 109 Expect(bridgePlugin.IsGW).To(BeTrue()) 110 Expect(bridgePlugin.IPMasq).To(BeTrue()) 111 Expect(bridgePlugin.IPAM.Ranges[0][0].Gateway).ToNot(BeEmpty()) 112 Expect(portMapPlugin.Capabilities["portMappings"]).To(BeTrue()) 113 114 }) 115 116 It("podman network create with name", func() { 117 var ( 118 results []network.NcList 119 ) 120 121 netName := "inspectnet-" + stringid.GenerateNonCryptoID() 122 nc := podmanTest.Podman([]string{"network", "create", netName}) 123 nc.WaitWithDefaultTimeout() 124 defer podmanTest.removeCNINetwork(netName) 125 Expect(nc).Should(Exit(0)) 126 127 inspect := podmanTest.Podman([]string{"network", "inspect", netName}) 128 inspect.WaitWithDefaultTimeout() 129 130 err := json.Unmarshal([]byte(inspect.OutputToString()), &results) 131 Expect(err).To(BeNil()) 132 result := results[0] 133 Expect(result["name"]).To(Equal(netName)) 134 135 }) 136 137 It("podman network create with name and subnet", func() { 138 var ( 139 results []network.NcList 140 ) 141 netName := "subnet-" + stringid.GenerateNonCryptoID() 142 nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.12.0/24", netName}) 143 nc.WaitWithDefaultTimeout() 144 defer podmanTest.removeCNINetwork(netName) 145 Expect(nc).Should(Exit(0)) 146 147 // Inspect the network configuration 148 inspect := podmanTest.Podman([]string{"network", "inspect", netName}) 149 inspect.WaitWithDefaultTimeout() 150 151 // JSON the network configuration into something usable 152 err := json.Unmarshal([]byte(inspect.OutputToString()), &results) 153 Expect(err).To(BeNil()) 154 result := results[0] 155 Expect(result["name"]).To(Equal(netName)) 156 157 // JSON the bridge info 158 bridgePlugin, err := genericPluginsToBridge(result["plugins"], "bridge") 159 Expect(err).To(BeNil()) 160 // check that gateway is added to config 161 Expect(bridgePlugin.IPAM.Ranges[0][0].Gateway).To(Equal("10.11.12.1")) 162 163 // Once a container executes a new network, the nic will be created. We should clean those up 164 // best we can 165 defer removeNetworkDevice(bridgePlugin.BrName) 166 167 try := podmanTest.Podman([]string{"run", "-it", "--rm", "--network", netName, ALPINE, "sh", "-c", "ip addr show eth0 | awk ' /inet / {print $2}'"}) 168 try.WaitWithDefaultTimeout() 169 170 _, subnet, err := net.ParseCIDR("10.11.12.0/24") 171 Expect(err).To(BeNil()) 172 // Note this is an IPv4 test only! 173 containerIP, _, err := net.ParseCIDR(try.OutputToString()) 174 Expect(err).To(BeNil()) 175 // Ensure that the IP the container got is within the subnet the user asked for 176 Expect(subnet.Contains(containerIP)).To(BeTrue()) 177 }) 178 179 It("podman network create with name and IPv6 subnet", func() { 180 SkipIfRootless("FIXME It needs the ip6tables modules loaded") 181 var ( 182 results []network.NcList 183 ) 184 netName := "ipv6-" + stringid.GenerateNonCryptoID() 185 nc := podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:1:2:3:4::/64", netName}) 186 nc.WaitWithDefaultTimeout() 187 defer podmanTest.removeCNINetwork(netName) 188 Expect(nc).Should(Exit(0)) 189 190 // Inspect the network configuration 191 inspect := podmanTest.Podman([]string{"network", "inspect", netName}) 192 inspect.WaitWithDefaultTimeout() 193 194 // JSON the network configuration into something usable 195 err := json.Unmarshal([]byte(inspect.OutputToString()), &results) 196 Expect(err).To(BeNil()) 197 result := results[0] 198 Expect(result["name"]).To(Equal(netName)) 199 200 // JSON the bridge info 201 bridgePlugin, err := genericPluginsToBridge(result["plugins"], "bridge") 202 Expect(err).To(BeNil()) 203 Expect(bridgePlugin.IPAM.Routes[0].Dest).To(Equal("::/0")) 204 205 // Once a container executes a new network, the nic will be created. We should clean those up 206 // best we can 207 defer removeNetworkDevice(bridgePlugin.BrName) 208 209 try := podmanTest.Podman([]string{"run", "-it", "--rm", "--network", netName, ALPINE, "sh", "-c", "ip addr show eth0 | grep global | awk ' /inet6 / {print $2}'"}) 210 try.WaitWithDefaultTimeout() 211 212 _, subnet, err := net.ParseCIDR("fd00:1:2:3:4::/64") 213 Expect(err).To(BeNil()) 214 containerIP, _, err := net.ParseCIDR(try.OutputToString()) 215 Expect(err).To(BeNil()) 216 // Ensure that the IP the container got is within the subnet the user asked for 217 Expect(subnet.Contains(containerIP)).To(BeTrue()) 218 }) 219 220 It("podman network create with name and IPv6 flag (dual-stack)", func() { 221 SkipIfRootless("FIXME It needs the ip6tables modules loaded") 222 var ( 223 results []network.NcList 224 ) 225 netName := "dual-" + stringid.GenerateNonCryptoID() 226 nc := podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:4:3:2:1::/64", "--ipv6", netName}) 227 nc.WaitWithDefaultTimeout() 228 defer podmanTest.removeCNINetwork(netName) 229 Expect(nc).Should(Exit(0)) 230 231 // Inspect the network configuration 232 inspect := podmanTest.Podman([]string{"network", "inspect", netName}) 233 inspect.WaitWithDefaultTimeout() 234 235 // JSON the network configuration into something usable 236 err := json.Unmarshal([]byte(inspect.OutputToString()), &results) 237 Expect(err).To(BeNil()) 238 result := results[0] 239 Expect(result["name"]).To(Equal(netName)) 240 241 // JSON the bridge info 242 bridgePlugin, err := genericPluginsToBridge(result["plugins"], "bridge") 243 Expect(err).To(BeNil()) 244 Expect(bridgePlugin.IPAM.Routes[0].Dest).To(Equal("::/0")) 245 Expect(bridgePlugin.IPAM.Routes[1].Dest).To(Equal("0.0.0.0/0")) 246 247 Expect(bridgePlugin.IPAM.Ranges).To(HaveLen(2)) 248 Expect(bridgePlugin.IPAM.Ranges[0]).To(HaveLen(1)) 249 Expect(bridgePlugin.IPAM.Ranges[0][0].Subnet).ToNot(BeEmpty()) 250 Expect(bridgePlugin.IPAM.Ranges[1]).To(HaveLen(1)) 251 Expect(bridgePlugin.IPAM.Ranges[1][0].Subnet).ToNot(BeEmpty()) 252 253 _, subnet11, err := net.ParseCIDR(bridgePlugin.IPAM.Ranges[0][0].Subnet) 254 Expect(err).To(BeNil()) 255 _, subnet12, err := net.ParseCIDR(bridgePlugin.IPAM.Ranges[1][0].Subnet) 256 Expect(err).To(BeNil()) 257 258 // Once a container executes a new network, the nic will be created. We should clean those up 259 // best we can 260 defer removeNetworkDevice(bridgePlugin.BrName) 261 262 // create a second network to check the auto assigned ipv4 subnet does not overlap 263 // https://github.com/containers/podman/issues/11032 264 netName2 := "dual-" + stringid.GenerateNonCryptoID() 265 nc = podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:6:3:2:1::/64", "--ipv6", netName2}) 266 nc.WaitWithDefaultTimeout() 267 defer podmanTest.removeCNINetwork(netName2) 268 Expect(nc).Should(Exit(0)) 269 270 // Inspect the network configuration 271 inspect = podmanTest.Podman([]string{"network", "inspect", netName2}) 272 inspect.WaitWithDefaultTimeout() 273 274 // JSON the network configuration into something usable 275 err = json.Unmarshal([]byte(inspect.OutputToString()), &results) 276 Expect(err).To(BeNil()) 277 result = results[0] 278 Expect(result["name"]).To(Equal(netName2)) 279 280 // JSON the bridge info 281 bridgePlugin, err = genericPluginsToBridge(result["plugins"], "bridge") 282 Expect(err).To(BeNil()) 283 Expect(bridgePlugin.IPAM.Routes[0].Dest).To(Equal("::/0")) 284 Expect(bridgePlugin.IPAM.Routes[1].Dest).To(Equal("0.0.0.0/0")) 285 Expect(bridgePlugin.IPAM.Ranges).To(HaveLen(2)) 286 Expect(bridgePlugin.IPAM.Ranges[0]).To(HaveLen(1)) 287 Expect(bridgePlugin.IPAM.Ranges[0][0].Subnet).ToNot(BeEmpty()) 288 Expect(bridgePlugin.IPAM.Ranges[1]).To(HaveLen(1)) 289 Expect(bridgePlugin.IPAM.Ranges[1][0].Subnet).ToNot(BeEmpty()) 290 291 _, subnet21, err := net.ParseCIDR(bridgePlugin.IPAM.Ranges[0][0].Subnet) 292 Expect(err).To(BeNil()) 293 _, subnet22, err := net.ParseCIDR(bridgePlugin.IPAM.Ranges[1][0].Subnet) 294 Expect(err).To(BeNil()) 295 296 // check that the subnets do not overlap 297 Expect(subnet11.Contains(subnet21.IP)).To(BeFalse()) 298 Expect(subnet12.Contains(subnet22.IP)).To(BeFalse()) 299 300 try := podmanTest.Podman([]string{"run", "-it", "--rm", "--network", netName, ALPINE, "sh", "-c", "ip addr show eth0 | grep global | awk ' /inet6 / {print $2}'"}) 301 try.WaitWithDefaultTimeout() 302 303 _, subnet, err := net.ParseCIDR("fd00:4:3:2:1::/64") 304 Expect(err).To(BeNil()) 305 containerIP, _, err := net.ParseCIDR(try.OutputToString()) 306 Expect(err).To(BeNil()) 307 // Ensure that the IP the container got is within the subnet the user asked for 308 Expect(subnet.Contains(containerIP)).To(BeTrue()) 309 // verify the container has an IPv4 address too (the IPv4 subnet is autogenerated) 310 try = podmanTest.Podman([]string{"run", "-it", "--rm", "--network", netName, ALPINE, "sh", "-c", "ip addr show eth0 | awk ' /inet / {print $2}'"}) 311 try.WaitWithDefaultTimeout() 312 containerIP, _, err = net.ParseCIDR(try.OutputToString()) 313 Expect(err).To(BeNil()) 314 Expect(containerIP.To4()).To(Not(BeNil())) 315 }) 316 317 It("podman network create with invalid subnet", func() { 318 nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.12.0/17000", stringid.GenerateNonCryptoID()}) 319 nc.WaitWithDefaultTimeout() 320 Expect(nc).To(ExitWithError()) 321 }) 322 323 It("podman network create with ipv4 subnet and ipv6 flag", func() { 324 nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.12.0/24", "--ipv6", stringid.GenerateNonCryptoID()}) 325 nc.WaitWithDefaultTimeout() 326 Expect(nc).To(ExitWithError()) 327 }) 328 329 It("podman network create with empty subnet and ipv6 flag", func() { 330 nc := podmanTest.Podman([]string{"network", "create", "--ipv6", stringid.GenerateNonCryptoID()}) 331 nc.WaitWithDefaultTimeout() 332 Expect(nc).To(ExitWithError()) 333 }) 334 335 It("podman network create with invalid IP", func() { 336 nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.0/17000", stringid.GenerateNonCryptoID()}) 337 nc.WaitWithDefaultTimeout() 338 Expect(nc).To(ExitWithError()) 339 }) 340 341 It("podman network create with invalid gateway for subnet", func() { 342 nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.12.0/24", "--gateway", "192.168.1.1", stringid.GenerateNonCryptoID()}) 343 nc.WaitWithDefaultTimeout() 344 Expect(nc).To(ExitWithError()) 345 }) 346 347 It("podman network create two networks with same name should fail", func() { 348 netName := "same-" + stringid.GenerateNonCryptoID() 349 nc := podmanTest.Podman([]string{"network", "create", netName}) 350 nc.WaitWithDefaultTimeout() 351 defer podmanTest.removeCNINetwork(netName) 352 Expect(nc).Should(Exit(0)) 353 354 ncFail := podmanTest.Podman([]string{"network", "create", netName}) 355 ncFail.WaitWithDefaultTimeout() 356 Expect(ncFail).To(ExitWithError()) 357 }) 358 359 It("podman network create two networks with same subnet should fail", func() { 360 netName1 := "sub1-" + stringid.GenerateNonCryptoID() 361 nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.13.0/24", netName1}) 362 nc.WaitWithDefaultTimeout() 363 defer podmanTest.removeCNINetwork(netName1) 364 Expect(nc).Should(Exit(0)) 365 366 netName2 := "sub2-" + stringid.GenerateNonCryptoID() 367 ncFail := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.13.0/24", netName2}) 368 ncFail.WaitWithDefaultTimeout() 369 defer podmanTest.removeCNINetwork(netName2) 370 Expect(ncFail).To(ExitWithError()) 371 }) 372 373 It("podman network create two IPv6 networks with same subnet should fail", func() { 374 SkipIfRootless("FIXME It needs the ip6tables modules loaded") 375 netName1 := "subipv61-" + stringid.GenerateNonCryptoID() 376 nc := podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:4:4:4:4::/64", "--ipv6", netName1}) 377 nc.WaitWithDefaultTimeout() 378 defer podmanTest.removeCNINetwork(netName1) 379 Expect(nc).Should(Exit(0)) 380 381 netName2 := "subipv62-" + stringid.GenerateNonCryptoID() 382 ncFail := podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:4:4:4:4::/64", "--ipv6", netName2}) 383 ncFail.WaitWithDefaultTimeout() 384 defer podmanTest.removeCNINetwork(netName2) 385 Expect(ncFail).To(ExitWithError()) 386 }) 387 388 It("podman network create with invalid network name", func() { 389 nc := podmanTest.Podman([]string{"network", "create", "foo "}) 390 nc.WaitWithDefaultTimeout() 391 Expect(nc).To(ExitWithError()) 392 }) 393 394 It("podman network create with mtu option", func() { 395 net := "mtu-test" + stringid.GenerateNonCryptoID() 396 nc := podmanTest.Podman([]string{"network", "create", "--opt", "mtu=9000", net}) 397 nc.WaitWithDefaultTimeout() 398 defer podmanTest.removeCNINetwork(net) 399 Expect(nc).Should(Exit(0)) 400 401 nc = podmanTest.Podman([]string{"network", "inspect", net}) 402 nc.WaitWithDefaultTimeout() 403 Expect(nc).Should(Exit(0)) 404 Expect(nc.OutputToString()).To(ContainSubstring(`"mtu": 9000,`)) 405 }) 406 407 It("podman network create with vlan option", func() { 408 net := "vlan-test" + stringid.GenerateNonCryptoID() 409 nc := podmanTest.Podman([]string{"network", "create", "--opt", "vlan=9", net}) 410 nc.WaitWithDefaultTimeout() 411 defer podmanTest.removeCNINetwork(net) 412 Expect(nc).Should(Exit(0)) 413 414 nc = podmanTest.Podman([]string{"network", "inspect", net}) 415 nc.WaitWithDefaultTimeout() 416 Expect(nc).Should(Exit(0)) 417 Expect(nc.OutputToString()).To(ContainSubstring(`"vlan": 9`)) 418 }) 419 420 It("podman network create with invalid option", func() { 421 net := "invalid-test" + stringid.GenerateNonCryptoID() 422 nc := podmanTest.Podman([]string{"network", "create", "--opt", "foo=bar", net}) 423 nc.WaitWithDefaultTimeout() 424 defer podmanTest.removeCNINetwork(net) 425 Expect(nc).To(ExitWithError()) 426 }) 427 428 It("podman network create with internal should not have dnsname", func() { 429 net := "internal-test" + stringid.GenerateNonCryptoID() 430 nc := podmanTest.Podman([]string{"network", "create", "--internal", net}) 431 nc.WaitWithDefaultTimeout() 432 defer podmanTest.removeCNINetwork(net) 433 Expect(nc).Should(Exit(0)) 434 // Not performing this check on remote tests because it is a logrus error which does 435 // not come back via stderr on the remote client. 436 if !IsRemote() { 437 Expect(nc.ErrorToString()).To(ContainSubstring("dnsname and --internal networks are incompatible")) 438 } 439 nc = podmanTest.Podman([]string{"network", "inspect", net}) 440 nc.WaitWithDefaultTimeout() 441 Expect(nc).Should(Exit(0)) 442 Expect(nc.OutputToString()).ToNot(ContainSubstring("dnsname")) 443 }) 444 445 })