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  })