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