Add ability to set static routes
add routes using the --route flag. the no_default_route option in --opt prevents a default route from getting added automatically. Signed-off-by: Jan Hendrik Farr <github@jfarr.cc>
This commit is contained in:
parent
68183b07d6
commit
8bf168cc13
|
|
@ -4,6 +4,8 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/common/libnetwork/types"
|
||||
"github.com/containers/common/libnetwork/util"
|
||||
|
|
@ -77,6 +79,10 @@ func networkCreateFlags(cmd *cobra.Command) {
|
|||
flags.StringArrayVar(&networkCreateOptions.Subnets, subnetFlagName, nil, "subnets in CIDR format")
|
||||
_ = cmd.RegisterFlagCompletionFunc(subnetFlagName, completion.AutocompleteNone)
|
||||
|
||||
routeFlagName := "route"
|
||||
flags.StringArrayVar(&networkCreateOptions.Routes, routeFlagName, nil, "static routes")
|
||||
_ = cmd.RegisterFlagCompletionFunc(routeFlagName, completion.AutocompleteNone)
|
||||
|
||||
interfaceFlagName := "interface-name"
|
||||
flags.StringVar(&networkCreateOptions.InterfaceName, interfaceFlagName, "", "interface name which is used by the driver")
|
||||
_ = cmd.RegisterFlagCompletionFunc(interfaceFlagName, completion.AutocompleteNone)
|
||||
|
|
@ -176,6 +182,16 @@ func networkCreate(cmd *cobra.Command, args []string) error {
|
|||
return errors.New("cannot set gateway or range without subnet")
|
||||
}
|
||||
|
||||
for i := range networkCreateOptions.Routes {
|
||||
route, err := parseRoute(networkCreateOptions.Routes[i])
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
network.Routes = append(network.Routes, *route)
|
||||
}
|
||||
|
||||
extraCreateOptions := types.NetworkCreateOptions{
|
||||
IgnoreIfExists: networkCreateOptions.IgnoreIfExists,
|
||||
}
|
||||
|
|
@ -188,6 +204,46 @@ func networkCreate(cmd *cobra.Command, args []string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func parseRoute(routeStr string) (*types.Route, error) {
|
||||
s := strings.Split(routeStr, ",")
|
||||
var metric *uint32
|
||||
|
||||
if len(s) == 2 || len(s) == 3 {
|
||||
dstStr := s[0]
|
||||
gwStr := s[1]
|
||||
|
||||
destination, err := types.ParseCIDR(dstStr)
|
||||
gateway := net.ParseIP(gwStr)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid route destination %s", dstStr)
|
||||
}
|
||||
|
||||
if gateway == nil {
|
||||
return nil, fmt.Errorf("invalid route gateway %s", gwStr)
|
||||
}
|
||||
|
||||
if len(s) == 3 {
|
||||
mtr, err := strconv.ParseUint(s[2], 10, 32)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid route metric %s", s[2])
|
||||
}
|
||||
x := uint32(mtr)
|
||||
metric = &x
|
||||
}
|
||||
|
||||
r := types.Route{
|
||||
Destination: destination,
|
||||
Gateway: gateway,
|
||||
Metric: metric,
|
||||
}
|
||||
|
||||
return &r, nil
|
||||
}
|
||||
return nil, fmt.Errorf("invalid route: %s\nFormat: --route <destination in CIDR>,<gateway>,<metric (optional)>", routeStr)
|
||||
}
|
||||
|
||||
func parseRange(iprange string) (*types.LeaseRange, error) {
|
||||
_, subnet, err := net.ParseCIDR(iprange)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -95,10 +95,12 @@ Set metadata for a network (e.g., --label mykey=value).
|
|||
|
||||
Set driver specific options.
|
||||
|
||||
All drivers accept the `mtu` and `metric` options.
|
||||
All drivers accept the `mtu`, `metric`, `no_default_route` and options.
|
||||
|
||||
- `mtu`: Sets the Maximum Transmission Unit (MTU) and takes an integer value.
|
||||
- `metric` Sets the Route Metric for the default route created in every container joined to this network. Accepts a positive integer value. Can only be used with the Netavark network backend.
|
||||
- `no_default_route`: If set to 1, Podman will not automatically add a default route to subnets. Routes can still be added
|
||||
manually by creating a custom route using `--route`.
|
||||
|
||||
Additionally the `bridge` driver supports the following options:
|
||||
|
||||
|
|
@ -114,6 +116,10 @@ The `macvlan` and `ipvlan` driver support the following options:
|
|||
- Supported values for `macvlan` are `bridge`, `private`, `vepa`, `passthru`. Defaults to `bridge`.
|
||||
- Supported values for `ipvlan` are `l2`, `l3`, `l3s`. Defaults to `l2`.
|
||||
|
||||
#### **--route**=*route*
|
||||
|
||||
A static route in the format <destination in CIDR notation>,<gateway>,<route metric (optional)>. This route will be added to every container in this network. Only available with the netavark backend. It can be specified multiple times if more than one static route is desired.
|
||||
|
||||
#### **--subnet**=*subnet*
|
||||
|
||||
The subnet in CIDR notation. Can be specified multiple times to allocate more than one subnet for this network.
|
||||
|
|
@ -158,6 +164,17 @@ $ podman network create --subnet 192.168.55.0/24 --gateway 192.168.55.3 --subnet
|
|||
podman4
|
||||
```
|
||||
|
||||
Create a network with a static subnet and a static route.
|
||||
```
|
||||
$ podman network create --subnet 192.168.33.0/24 --route 10.1.0.0/24,192.168.33.10 newnet
|
||||
```
|
||||
|
||||
Create a network with a static subnet and a static route without a default
|
||||
route.
|
||||
```
|
||||
$ podman network create --subnet 192.168.33.0/24 --route 10.1.0.0/24,192.168.33.10 --opt no_default_route=1 newnet
|
||||
```
|
||||
|
||||
Create a Macvlan based network using the host interface eth0. Macvlan networks can only be used as root.
|
||||
```
|
||||
$ sudo podman network create -d macvlan -o parent=eth0 --subnet 192.5.0.0/16 newnet
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ Pretty-print networks to JSON or using a Go template.
|
|||
| .NetworkDNSServers | Array of DNS servers used in this network |
|
||||
| .NetworkInterface | Name of the network interface on the host |
|
||||
| .Options | Network options |
|
||||
| .Routes | List of static routes for this network |
|
||||
| .Subnets | List of subnets on this network |
|
||||
|
||||
## EXAMPLE
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ Valid placeholders for the Go template are listed below:
|
|||
| .NetworkDNSServers | Array of DNS servers used in this network |
|
||||
| .NetworkInterface | Name of the network interface on the host |
|
||||
| .Options | Network options |
|
||||
| .Routes | List of static routes for this network |
|
||||
| .Subnets | List of subnets on this network |
|
||||
|
||||
#### **--no-trunc**
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ type NetworkCreateOptions struct {
|
|||
NetworkDNSServers []string
|
||||
Ranges []string
|
||||
Subnets []string
|
||||
Routes []string
|
||||
IPv6 bool
|
||||
// Mapping of driver options and values.
|
||||
Options map[string]string
|
||||
|
|
|
|||
|
|
@ -62,6 +62,215 @@ var _ = Describe("Podman network create", func() {
|
|||
Expect(subnet.Contains(containerIP)).To(BeTrue(), "subnet contains containerIP")
|
||||
})
|
||||
|
||||
It("podman network create with name and subnet and static route", func() {
|
||||
SkipIfCNI(podmanTest)
|
||||
netName := "subnet-" + stringid.GenerateRandomID()
|
||||
nc := podmanTest.Podman([]string{
|
||||
"network",
|
||||
"create",
|
||||
"--subnet",
|
||||
"10.19.12.0/24",
|
||||
"--route",
|
||||
"10.21.0.0/24,10.19.12.250",
|
||||
netName,
|
||||
})
|
||||
nc.WaitWithDefaultTimeout()
|
||||
defer podmanTest.removeNetwork(netName)
|
||||
Expect(nc).Should(Exit(0))
|
||||
|
||||
// Inspect the network configuration
|
||||
inspect := podmanTest.Podman([]string{"network", "inspect", netName})
|
||||
inspect.WaitWithDefaultTimeout()
|
||||
Expect(inspect).Should(Exit(0))
|
||||
|
||||
// JSON the network configuration into something usable
|
||||
var results []types.Network
|
||||
err := json.Unmarshal([]byte(inspect.OutputToString()), &results)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(results).To(HaveLen(1))
|
||||
result := results[0]
|
||||
Expect(result).To(HaveField("Name", netName))
|
||||
Expect(result.Subnets).To(HaveLen(1))
|
||||
Expect(result.Subnets[0].Subnet.String()).To(Equal("10.19.12.0/24"))
|
||||
Expect(result.Subnets[0].Gateway.String()).To(Equal("10.19.12.1"))
|
||||
Expect(result.Routes[0].Destination.String()).To(Equal("10.21.0.0/24"))
|
||||
Expect(result.Routes[0].Gateway.String()).To(Equal("10.19.12.250"))
|
||||
Expect(result.Routes[0].Metric).To(BeNil())
|
||||
|
||||
// Once a container executes a new network, the nic will be created. We should clean those up
|
||||
// best we can
|
||||
defer removeNetworkDevice(result.NetworkInterface)
|
||||
|
||||
})
|
||||
|
||||
It("podman network create with name and subnet and static route and metric", func() {
|
||||
SkipIfCNI(podmanTest)
|
||||
netName := "subnet-" + stringid.GenerateRandomID()
|
||||
nc := podmanTest.Podman([]string{
|
||||
"network",
|
||||
"create",
|
||||
"--subnet",
|
||||
"10.19.13.0/24",
|
||||
"--route",
|
||||
"10.21.1.0/24,10.19.13.250,120",
|
||||
netName,
|
||||
})
|
||||
nc.WaitWithDefaultTimeout()
|
||||
defer podmanTest.removeNetwork(netName)
|
||||
Expect(nc).Should(Exit(0))
|
||||
|
||||
// Inspect the network configuration
|
||||
inspect := podmanTest.Podman([]string{"network", "inspect", netName})
|
||||
inspect.WaitWithDefaultTimeout()
|
||||
Expect(inspect).Should(Exit(0))
|
||||
|
||||
// JSON the network configuration into something usable
|
||||
var results []types.Network
|
||||
err := json.Unmarshal([]byte(inspect.OutputToString()), &results)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(results).To(HaveLen(1))
|
||||
result := results[0]
|
||||
Expect(result).To(HaveField("Name", netName))
|
||||
Expect(result.Subnets).To(HaveLen(1))
|
||||
Expect(result.Subnets[0].Subnet.String()).To(Equal("10.19.13.0/24"))
|
||||
Expect(result.Subnets[0].Gateway.String()).To(Equal("10.19.13.1"))
|
||||
Expect(result.Routes[0].Destination.String()).To(Equal("10.21.1.0/24"))
|
||||
Expect(result.Routes[0].Gateway.String()).To(Equal("10.19.13.250"))
|
||||
Expect(*result.Routes[0].Metric).To(Equal(uint32(120)))
|
||||
|
||||
// Once a container executes a new network, the nic will be created. We should clean those up
|
||||
// best we can
|
||||
defer removeNetworkDevice(result.NetworkInterface)
|
||||
|
||||
})
|
||||
|
||||
It("podman network create with name and subnet and two static routes", func() {
|
||||
SkipIfCNI(podmanTest)
|
||||
netName := "subnet-" + stringid.GenerateRandomID()
|
||||
nc := podmanTest.Podman([]string{
|
||||
"network",
|
||||
"create",
|
||||
"--subnet",
|
||||
"10.19.14.0/24",
|
||||
"--route",
|
||||
"10.21.2.0/24,10.19.14.250",
|
||||
"--route",
|
||||
"10.21.3.0/24,10.19.14.251,120",
|
||||
netName,
|
||||
})
|
||||
nc.WaitWithDefaultTimeout()
|
||||
defer podmanTest.removeNetwork(netName)
|
||||
Expect(nc).Should(Exit(0))
|
||||
|
||||
// Inspect the network configuration
|
||||
inspect := podmanTest.Podman([]string{"network", "inspect", netName})
|
||||
inspect.WaitWithDefaultTimeout()
|
||||
Expect(inspect).Should(Exit(0))
|
||||
|
||||
// JSON the network configuration into something usable
|
||||
var results []types.Network
|
||||
err := json.Unmarshal([]byte(inspect.OutputToString()), &results)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(results).To(HaveLen(1))
|
||||
result := results[0]
|
||||
Expect(result).To(HaveField("Name", netName))
|
||||
Expect(result.Subnets).To(HaveLen(1))
|
||||
Expect(result.Subnets[0].Subnet.String()).To(Equal("10.19.14.0/24"))
|
||||
Expect(result.Subnets[0].Gateway.String()).To(Equal("10.19.14.1"))
|
||||
Expect(result.Routes).To(HaveLen(2))
|
||||
Expect(result.Routes[0].Destination.String()).To(Equal("10.21.2.0/24"))
|
||||
Expect(result.Routes[0].Gateway.String()).To(Equal("10.19.14.250"))
|
||||
Expect(result.Routes[0].Metric).To(BeNil())
|
||||
Expect(result.Routes[1].Destination.String()).To(Equal("10.21.3.0/24"))
|
||||
Expect(result.Routes[1].Gateway.String()).To(Equal("10.19.14.251"))
|
||||
Expect(*result.Routes[1].Metric).To(Equal(uint32(120)))
|
||||
|
||||
// Once a container executes a new network, the nic will be created. We should clean those up
|
||||
// best we can
|
||||
defer removeNetworkDevice(result.NetworkInterface)
|
||||
|
||||
})
|
||||
|
||||
It("podman network create with name and subnet and static route (ipv6)", func() {
|
||||
SkipIfCNI(podmanTest)
|
||||
netName := "subnet-" + stringid.GenerateRandomID()
|
||||
nc := podmanTest.Podman([]string{
|
||||
"network",
|
||||
"create",
|
||||
"--subnet",
|
||||
"fd:ab04::/64",
|
||||
"--route",
|
||||
"fd:1::/64,fd::1,120",
|
||||
netName,
|
||||
})
|
||||
nc.WaitWithDefaultTimeout()
|
||||
defer podmanTest.removeNetwork(netName)
|
||||
Expect(nc).Should(Exit(0))
|
||||
|
||||
// Inspect the network configuration
|
||||
inspect := podmanTest.Podman([]string{"network", "inspect", netName})
|
||||
inspect.WaitWithDefaultTimeout()
|
||||
Expect(inspect).Should(Exit(0))
|
||||
|
||||
// JSON the network configuration into something usable
|
||||
var results []types.Network
|
||||
err := json.Unmarshal([]byte(inspect.OutputToString()), &results)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(results).To(HaveLen(1))
|
||||
result := results[0]
|
||||
Expect(result).To(HaveField("Name", netName))
|
||||
Expect(result.Subnets).To(HaveLen(1))
|
||||
Expect(result.Subnets[0].Subnet.String()).To(Equal("fd:ab04::/64"))
|
||||
Expect(result.Subnets[0].Gateway.String()).To(Equal("fd:ab04::1"))
|
||||
Expect(result.Routes[0].Destination.String()).To(Equal("fd:1::/64"))
|
||||
Expect(result.Routes[0].Gateway.String()).To(Equal("fd::1"))
|
||||
Expect(*result.Routes[0].Metric).To(Equal(uint32(120)))
|
||||
|
||||
// Once a container executes a new network, the nic will be created. We should clean those up
|
||||
// best we can
|
||||
defer removeNetworkDevice(result.NetworkInterface)
|
||||
|
||||
})
|
||||
|
||||
It("podman network create with name and subnet with --opt no_default_route=1", func() {
|
||||
SkipIfCNI(podmanTest)
|
||||
netName := "subnet-" + stringid.GenerateRandomID()
|
||||
nc := podmanTest.Podman([]string{
|
||||
"network",
|
||||
"create",
|
||||
"--subnet",
|
||||
"10.19.15.0/24",
|
||||
"--opt",
|
||||
"no_default_route=1",
|
||||
netName,
|
||||
})
|
||||
nc.WaitWithDefaultTimeout()
|
||||
defer podmanTest.removeNetwork(netName)
|
||||
Expect(nc).Should(Exit(0))
|
||||
|
||||
// Inspect the network configuration
|
||||
inspect := podmanTest.Podman([]string{"network", "inspect", netName})
|
||||
inspect.WaitWithDefaultTimeout()
|
||||
Expect(inspect).Should(Exit(0))
|
||||
|
||||
// JSON the network configuration into something usable
|
||||
var results []types.Network
|
||||
err := json.Unmarshal([]byte(inspect.OutputToString()), &results)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(results).To(HaveLen(1))
|
||||
result := results[0]
|
||||
Expect(result).To(HaveField("Name", netName))
|
||||
Expect(result.Subnets).To(HaveLen(1))
|
||||
Expect(result.Subnets[0].Subnet.String()).To(Equal("10.19.15.0/24"))
|
||||
Expect(result.Subnets[0].Gateway.String()).To(Equal("10.19.15.1"))
|
||||
Expect(result.Options[types.NoDefaultRoute]).To(Equal("true"))
|
||||
|
||||
// Once a container executes a new network, the nic will be created. We should clean those up
|
||||
// best we can
|
||||
defer removeNetworkDevice(result.NetworkInterface)
|
||||
|
||||
})
|
||||
|
||||
It("podman network create with name and IPv6 subnet", func() {
|
||||
netName := "ipv6-" + stringid.GenerateRandomID()
|
||||
nc := podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:1:2:3:4::/64", netName})
|
||||
|
|
|
|||
Loading…
Reference in New Issue