github.com/containers/podman/v2@v2.2.2-0.20210501105131-c1e07d070c4c/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/v2/libpod/network"
    12  	. "github.com/containers/podman/v2/test/utils"
    13  	. "github.com/onsi/ginkgo"
    14  	. "github.com/onsi/gomega"
    15  	"github.com/pkg/errors"
    16  )
    17  
    18  var ErrPluginNotFound = errors.New("plugin not found")
    19  
    20  func findPluginByName(plugins interface{}, pluginType string) (interface{}, error) {
    21  	for _, p := range plugins.([]interface{}) {
    22  		r := p.(map[string]interface{})
    23  		if pluginType == r["type"] {
    24  			return p, nil
    25  		}
    26  	}
    27  	return nil, errors.Wrap(ErrPluginNotFound, pluginType)
    28  }
    29  
    30  func genericPluginsToBridge(plugins interface{}, pluginType string) (network.HostLocalBridge, error) {
    31  	var bridge network.HostLocalBridge
    32  	generic, err := findPluginByName(plugins, pluginType)
    33  	if err != nil {
    34  		return bridge, err
    35  	}
    36  	b, err := json.Marshal(generic)
    37  	if err != nil {
    38  		return bridge, err
    39  	}
    40  	err = json.Unmarshal(b, &bridge)
    41  	return bridge, err
    42  }
    43  
    44  func genericPluginsToPortMap(plugins interface{}, pluginType string) (network.PortMapConfig, error) {
    45  	var portMap network.PortMapConfig
    46  	generic, err := findPluginByName(plugins, "portmap")
    47  	if err != nil {
    48  		return portMap, err
    49  	}
    50  	b, err := json.Marshal(generic)
    51  	if err != nil {
    52  		return portMap, err
    53  	}
    54  	err = json.Unmarshal(b, &portMap)
    55  	return portMap, err
    56  }
    57  
    58  func (p *PodmanTestIntegration) removeCNINetwork(name string) {
    59  	session := p.Podman([]string{"network", "rm", "-f", name})
    60  	session.WaitWithDefaultTimeout()
    61  	Expect(session.ExitCode()).To(BeNumerically("<=", 1))
    62  }
    63  
    64  func removeNetworkDevice(name string) {
    65  	session := SystemExec("ip", []string{"link", "delete", name})
    66  	session.WaitWithDefaultTimeout()
    67  }
    68  
    69  var _ = Describe("Podman network create", func() {
    70  	var (
    71  		tempdir    string
    72  		err        error
    73  		podmanTest *PodmanTestIntegration
    74  	)
    75  
    76  	BeforeEach(func() {
    77  		SkipIfRootless("rootless CNI is tech preview in RHEL 8.3.1")
    78  		tempdir, err = CreateTempDirInTempDir()
    79  		if err != nil {
    80  			os.Exit(1)
    81  		}
    82  		podmanTest = PodmanTestCreate(tempdir)
    83  		podmanTest.Setup()
    84  		podmanTest.SeedImages()
    85  	})
    86  
    87  	AfterEach(func() {
    88  		podmanTest.Cleanup()
    89  		f := CurrentGinkgoTestDescription()
    90  		processTestResult(f)
    91  	})
    92  
    93  	It("podman network create with no input", func() {
    94  		var result network.NcList
    95  
    96  		nc := podmanTest.Podman([]string{"network", "create"})
    97  		nc.WaitWithDefaultTimeout()
    98  		Expect(nc.ExitCode()).To(BeZero())
    99  
   100  		fileContent, err := ioutil.ReadFile(nc.OutputToString())
   101  		Expect(err).To(BeNil())
   102  		err = json.Unmarshal(fileContent, &result)
   103  		Expect(err).To(BeNil())
   104  		defer podmanTest.removeCNINetwork(result["name"].(string))
   105  		Expect(result["cniVersion"]).To(Equal(cniversion.Current()))
   106  		Expect(strings.HasPrefix(result["name"].(string), "cni-podman")).To(BeTrue())
   107  
   108  		bridgePlugin, err := genericPluginsToBridge(result["plugins"], "bridge")
   109  		Expect(err).To(BeNil())
   110  		portMapPlugin, err := genericPluginsToPortMap(result["plugins"], "portmap")
   111  		Expect(err).To(BeNil())
   112  
   113  		Expect(bridgePlugin.IPAM.Routes[0].Dest).To(Equal("0.0.0.0/0"))
   114  		Expect(bridgePlugin.IsGW).To(BeTrue())
   115  		Expect(bridgePlugin.IPMasq).To(BeTrue())
   116  		Expect(portMapPlugin.Capabilities["portMappings"]).To(BeTrue())
   117  
   118  	})
   119  
   120  	It("podman network create with name", func() {
   121  		var (
   122  			results []network.NcList
   123  		)
   124  
   125  		nc := podmanTest.Podman([]string{"network", "create", "newname"})
   126  		nc.WaitWithDefaultTimeout()
   127  		Expect(nc.ExitCode()).To(BeZero())
   128  		defer podmanTest.removeCNINetwork("newname")
   129  
   130  		inspect := podmanTest.Podman([]string{"network", "inspect", "newname"})
   131  		inspect.WaitWithDefaultTimeout()
   132  
   133  		err := json.Unmarshal([]byte(inspect.OutputToString()), &results)
   134  		Expect(err).To(BeNil())
   135  		result := results[0]
   136  		Expect(result["name"]).To(Equal("newname"))
   137  
   138  	})
   139  
   140  	It("podman network create with name and subnet", func() {
   141  		var (
   142  			results []network.NcList
   143  		)
   144  		nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.12.0/24", "newnetwork"})
   145  		nc.WaitWithDefaultTimeout()
   146  		Expect(nc.ExitCode()).To(BeZero())
   147  
   148  		defer podmanTest.removeCNINetwork("newnetwork")
   149  
   150  		// Inspect the network configuration
   151  		inspect := podmanTest.Podman([]string{"network", "inspect", "newnetwork"})
   152  		inspect.WaitWithDefaultTimeout()
   153  
   154  		// JSON the network configuration into something usable
   155  		err := json.Unmarshal([]byte(inspect.OutputToString()), &results)
   156  		Expect(err).To(BeNil())
   157  		result := results[0]
   158  		Expect(result["name"]).To(Equal("newnetwork"))
   159  
   160  		// JSON the bridge info
   161  		bridgePlugin, err := genericPluginsToBridge(result["plugins"], "bridge")
   162  		Expect(err).To(BeNil())
   163  
   164  		// Once a container executes a new network, the nic will be created. We should clean those up
   165  		// best we can
   166  		defer removeNetworkDevice(bridgePlugin.BrName)
   167  
   168  		try := podmanTest.Podman([]string{"run", "-it", "--rm", "--network", "newnetwork", ALPINE, "sh", "-c", "ip addr show eth0 |  awk ' /inet / {print $2}'"})
   169  		try.WaitWithDefaultTimeout()
   170  
   171  		_, subnet, err := net.ParseCIDR("10.11.12.0/24")
   172  		Expect(err).To(BeNil())
   173  		// Note this is an IPv4 test only!
   174  		containerIP, _, err := net.ParseCIDR(try.OutputToString())
   175  		Expect(err).To(BeNil())
   176  		// Ensure that the IP the container got is within the subnet the user asked for
   177  		Expect(subnet.Contains(containerIP)).To(BeTrue())
   178  	})
   179  
   180  	It("podman network create with name and IPv6 subnet", func() {
   181  		SkipIfRootless("FIXME It needs the ip6tables modules loaded")
   182  		var (
   183  			results []network.NcList
   184  		)
   185  		nc := podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:1:2:3:4::/64", "newIPv6network"})
   186  		nc.WaitWithDefaultTimeout()
   187  		Expect(nc.ExitCode()).To(BeZero())
   188  
   189  		defer podmanTest.removeCNINetwork("newIPv6network")
   190  
   191  		// Inspect the network configuration
   192  		inspect := podmanTest.Podman([]string{"network", "inspect", "newIPv6network"})
   193  		inspect.WaitWithDefaultTimeout()
   194  
   195  		// JSON the network configuration into something usable
   196  		err := json.Unmarshal([]byte(inspect.OutputToString()), &results)
   197  		Expect(err).To(BeNil())
   198  		result := results[0]
   199  		Expect(result["name"]).To(Equal("newIPv6network"))
   200  
   201  		// JSON the bridge info
   202  		bridgePlugin, err := genericPluginsToBridge(result["plugins"], "bridge")
   203  		Expect(err).To(BeNil())
   204  		Expect(bridgePlugin.IPAM.Routes[0].Dest).To(Equal("::/0"))
   205  
   206  		// Once a container executes a new network, the nic will be created. We should clean those up
   207  		// best we can
   208  		defer removeNetworkDevice(bridgePlugin.BrName)
   209  
   210  		try := podmanTest.Podman([]string{"run", "-it", "--rm", "--network", "newIPv6network", ALPINE, "sh", "-c", "ip addr show eth0 |  grep global | awk ' /inet6 / {print $2}'"})
   211  		try.WaitWithDefaultTimeout()
   212  
   213  		_, subnet, err := net.ParseCIDR("fd00:1:2:3:4::/64")
   214  		Expect(err).To(BeNil())
   215  		containerIP, _, err := net.ParseCIDR(try.OutputToString())
   216  		Expect(err).To(BeNil())
   217  		// Ensure that the IP the container got is within the subnet the user asked for
   218  		Expect(subnet.Contains(containerIP)).To(BeTrue())
   219  	})
   220  
   221  	It("podman network create with name and IPv6 flag (dual-stack)", func() {
   222  		SkipIfRootless("FIXME It needs the ip6tables modules loaded")
   223  		var (
   224  			results []network.NcList
   225  		)
   226  		nc := podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:4:3:2:1::/64", "--ipv6", "newDualStacknetwork"})
   227  		nc.WaitWithDefaultTimeout()
   228  		Expect(nc.ExitCode()).To(BeZero())
   229  
   230  		defer podmanTest.removeCNINetwork("newDualStacknetwork")
   231  
   232  		// Inspect the network configuration
   233  		inspect := podmanTest.Podman([]string{"network", "inspect", "newDualStacknetwork"})
   234  		inspect.WaitWithDefaultTimeout()
   235  
   236  		// JSON the network configuration into something usable
   237  		err := json.Unmarshal([]byte(inspect.OutputToString()), &results)
   238  		Expect(err).To(BeNil())
   239  		result := results[0]
   240  		Expect(result["name"]).To(Equal("newDualStacknetwork"))
   241  
   242  		// JSON the bridge info
   243  		bridgePlugin, err := genericPluginsToBridge(result["plugins"], "bridge")
   244  		Expect(err).To(BeNil())
   245  		Expect(bridgePlugin.IPAM.Routes[0].Dest).To(Equal("::/0"))
   246  		Expect(bridgePlugin.IPAM.Routes[1].Dest).To(Equal("0.0.0.0/0"))
   247  
   248  		// Once a container executes a new network, the nic will be created. We should clean those up
   249  		// best we can
   250  		defer removeNetworkDevice(bridgePlugin.BrName)
   251  
   252  		try := podmanTest.Podman([]string{"run", "-it", "--rm", "--network", "newDualStacknetwork", ALPINE, "sh", "-c", "ip addr show eth0 |  grep global | awk ' /inet6 / {print $2}'"})
   253  		try.WaitWithDefaultTimeout()
   254  
   255  		_, subnet, err := net.ParseCIDR("fd00:4:3:2:1::/64")
   256  		Expect(err).To(BeNil())
   257  		containerIP, _, err := net.ParseCIDR(try.OutputToString())
   258  		Expect(err).To(BeNil())
   259  		// Ensure that the IP the container got is within the subnet the user asked for
   260  		Expect(subnet.Contains(containerIP)).To(BeTrue())
   261  		// verify the container has an IPv4 address too (the IPv4 subnet is autogenerated)
   262  		try = podmanTest.Podman([]string{"run", "-it", "--rm", "--network", "newDualStacknetwork", ALPINE, "sh", "-c", "ip addr show eth0 |  awk ' /inet / {print $2}'"})
   263  		try.WaitWithDefaultTimeout()
   264  		containerIP, _, err = net.ParseCIDR(try.OutputToString())
   265  		Expect(err).To(BeNil())
   266  		Expect(containerIP.To4()).To(Not(BeNil()))
   267  	})
   268  
   269  	It("podman network create with invalid subnet", func() {
   270  		nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.12.0/17000", "fail"})
   271  		nc.WaitWithDefaultTimeout()
   272  		Expect(nc).To(ExitWithError())
   273  	})
   274  
   275  	It("podman network create with ipv4 subnet and ipv6 flag", func() {
   276  		nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.12.0/24", "--ipv6", "fail"})
   277  		nc.WaitWithDefaultTimeout()
   278  		Expect(nc).To(ExitWithError())
   279  	})
   280  
   281  	It("podman network create with empty subnet and ipv6 flag", func() {
   282  		nc := podmanTest.Podman([]string{"network", "create", "--ipv6", "fail"})
   283  		nc.WaitWithDefaultTimeout()
   284  		Expect(nc).To(ExitWithError())
   285  	})
   286  
   287  	It("podman network create with invalid IP", func() {
   288  		nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.0/17000", "fail"})
   289  		nc.WaitWithDefaultTimeout()
   290  		Expect(nc).To(ExitWithError())
   291  	})
   292  
   293  	It("podman network create with invalid gateway for subnet", func() {
   294  		nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.12.0/24", "--gateway", "192.168.1.1", "fail"})
   295  		nc.WaitWithDefaultTimeout()
   296  		Expect(nc).To(ExitWithError())
   297  	})
   298  
   299  	It("podman network create two networks with same name should fail", func() {
   300  		nc := podmanTest.Podman([]string{"network", "create", "samename"})
   301  		nc.WaitWithDefaultTimeout()
   302  		Expect(nc.ExitCode()).To(BeZero())
   303  		defer podmanTest.removeCNINetwork("samename")
   304  
   305  		ncFail := podmanTest.Podman([]string{"network", "create", "samename"})
   306  		ncFail.WaitWithDefaultTimeout()
   307  		Expect(ncFail).To(ExitWithError())
   308  	})
   309  
   310  	It("podman network create two networks with same subnet should fail", func() {
   311  		nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.13.0/24", "subnet1"})
   312  		nc.WaitWithDefaultTimeout()
   313  		Expect(nc.ExitCode()).To(BeZero())
   314  		defer podmanTest.removeCNINetwork("subnet1")
   315  
   316  		ncFail := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.13.0/24", "subnet2"})
   317  		ncFail.WaitWithDefaultTimeout()
   318  		Expect(ncFail).To(ExitWithError())
   319  	})
   320  
   321  	It("podman network create two IPv6 networks with same subnet should fail", func() {
   322  		SkipIfRootless("FIXME It needs the ip6tables modules loaded")
   323  		nc := podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:4:4:4:4::/64", "--ipv6", "subnet1v6"})
   324  		nc.WaitWithDefaultTimeout()
   325  		Expect(nc.ExitCode()).To(BeZero())
   326  		defer podmanTest.removeCNINetwork("subnet1v6")
   327  
   328  		ncFail := podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:4:4:4:4::/64", "--ipv6", "subnet2v6"})
   329  		ncFail.WaitWithDefaultTimeout()
   330  		Expect(ncFail).To(ExitWithError())
   331  	})
   332  
   333  	It("podman network create with invalid network name", func() {
   334  		nc := podmanTest.Podman([]string{"network", "create", "foo "})
   335  		nc.WaitWithDefaultTimeout()
   336  		Expect(nc).To(ExitWithError())
   337  	})
   338  
   339  })