Merge pull request #537 from dcbw/100
Port plugins to CNI 1.0.0 and increase old verison test coverage
This commit is contained in:
commit
d385120175
4
go.mod
4
go.mod
@ -7,7 +7,7 @@ require (
|
||||
github.com/Microsoft/hcsshim v0.8.6
|
||||
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae
|
||||
github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44
|
||||
github.com/containernetworking/cni v0.8.1
|
||||
github.com/containernetworking/cni v0.8.1-0.20201216164644-62e54113f44a
|
||||
github.com/coreos/go-iptables v0.5.0
|
||||
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7
|
||||
github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c
|
||||
@ -17,7 +17,7 @@ require (
|
||||
github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c
|
||||
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56
|
||||
github.com/mattn/go-shellwords v1.0.3
|
||||
github.com/onsi/ginkgo v1.12.1
|
||||
github.com/onsi/ginkgo v1.13.0
|
||||
github.com/onsi/gomega v1.10.3
|
||||
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8
|
||||
github.com/sirupsen/logrus v1.0.6 // indirect
|
||||
|
15
go.sum
15
go.sum
@ -6,8 +6,8 @@ github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae h1:AMzIhMUq
|
||||
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
|
||||
github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44 h1:y853v6rXx+zefEcjET3JuKAqvhj+FKflQijjeaSv2iA=
|
||||
github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
|
||||
github.com/containernetworking/cni v0.8.1 h1:7zpDnQ3T3s4ucOuJ/ZCLrYBxzkg0AELFfII3Epo9TmI=
|
||||
github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
|
||||
github.com/containernetworking/cni v0.8.1-0.20201216164644-62e54113f44a h1:EDko/CXJ2CYF5pFdlTO/qHwkD0IxpSQY+FcTll6A/F4=
|
||||
github.com/containernetworking/cni v0.8.1-0.20201216164644-62e54113f44a/go.mod h1:AKuhXbN5EzmD4yTNtfSsX3tPcmtrBI6QcRV0NiNt15Y=
|
||||
github.com/coreos/go-iptables v0.5.0 h1:mw6SAibtHKZcNzAsOxjoHIG0gy5YFHhypWSSNc6EjbQ=
|
||||
github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
|
||||
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7 h1:u9SHYsPQNyt5tgDm3YN7+9dYrpK96E5wFilTFWIDZOM=
|
||||
@ -24,6 +24,8 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c h1:RBUpb2b14UnmRHNd2uHz20ZHLDK+SW5Us/vWF5IHRaY=
|
||||
github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
@ -48,13 +50,17 @@ github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1 h1:mFwc4LvZ0xpSvDZ3E+k8Yte0hLOMxXUlP+yXtJqkYfQ=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.13.0 h1:M76yO2HkZASFjXL0HSoZJ1AYEmQxNJmY41Jx1zNUq1Y=
|
||||
github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.10.3 h1:gph6h/qe9GSUw1NhH1gp+qb+h8rXD8Cy60Z32Qw3ELA=
|
||||
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8 h1:2c1EFnZHIPCW8qKWgHMH/fX2PkSabFc5mrVzfUNdg5U=
|
||||
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
|
||||
github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
|
||||
github.com/sirupsen/logrus v1.0.6 h1:hcP1GmhGigz/O7h1WVUM5KklBp1JoNS9FggWKdj/j3s=
|
||||
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
@ -69,6 +75,7 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnk
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0 h1:wBouT66WTYFXdxfVdz9sVWARVd/2vfGcmI45D2gj45M=
|
||||
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@ -76,13 +83,17 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637 h1:O5hKNaGxIT4A8OTMnuh6UpmBdI3SAPxlZ3g0olDrJVM=
|
||||
golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
@ -23,7 +23,7 @@ import (
|
||||
"github.com/Microsoft/hcsshim/hcn"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/plugins/pkg/errors"
|
||||
)
|
||||
|
||||
@ -286,28 +286,20 @@ func ConstructResult(hnsNetwork *hcsshim.HNSNetwork, hnsEndpoint *hcsshim.HNSEnd
|
||||
return nil, errors.Annotatef(err, "failed to parse CIDR from %s", hnsNetwork.Subnets[0].AddressPrefix)
|
||||
}
|
||||
|
||||
var ipVersion string
|
||||
if ipv4 := hnsEndpoint.IPAddress.To4(); ipv4 != nil {
|
||||
ipVersion = "4"
|
||||
} else if ipv6 := hnsEndpoint.IPAddress.To16(); ipv6 != nil {
|
||||
ipVersion = "6"
|
||||
} else {
|
||||
return nil, fmt.Errorf("IPAddress of HNSEndpoint %s isn't a valid ipv4 or ipv6 Address", hnsEndpoint.Name)
|
||||
}
|
||||
|
||||
resultIPConfig := ¤t.IPConfig{
|
||||
Version: ipVersion,
|
||||
Address: net.IPNet{
|
||||
IP: hnsEndpoint.IPAddress,
|
||||
Mask: ipSubnet.Mask},
|
||||
Gateway: net.ParseIP(hnsEndpoint.GatewayAddress),
|
||||
}
|
||||
result := ¤t.Result{}
|
||||
result.Interfaces = []*current.Interface{resultInterface}
|
||||
result.IPs = []*current.IPConfig{resultIPConfig}
|
||||
result.DNS = types.DNS{
|
||||
result := ¤t.Result{
|
||||
CNIVersion: current.ImplementedSpecVersion,
|
||||
Interfaces: []*current.Interface{resultInterface},
|
||||
IPs: []*current.IPConfig{resultIPConfig},
|
||||
DNS: types.DNS{
|
||||
Search: strings.Split(hnsEndpoint.DNSSuffix, ","),
|
||||
Nameservers: strings.Split(hnsEndpoint.DNSServerList, ","),
|
||||
},
|
||||
}
|
||||
|
||||
return result, nil
|
||||
@ -341,29 +333,21 @@ func ConstructHcnResult(hcnNetwork *hcn.HostComputeNetwork, hcnEndpoint *hcn.Hos
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ipVersion string
|
||||
ipAddress := net.ParseIP(hcnEndpoint.IpConfigurations[0].IpAddress)
|
||||
if ipv4 := ipAddress.To4(); ipv4 != nil {
|
||||
ipVersion = "4"
|
||||
} else if ipv6 := ipAddress.To16(); ipv6 != nil {
|
||||
ipVersion = "6"
|
||||
} else {
|
||||
return nil, fmt.Errorf("[win-cni] The IPAddress of hnsEndpoint isn't a valid ipv4 or ipv6 Address.")
|
||||
}
|
||||
|
||||
resultIPConfig := ¤t.IPConfig{
|
||||
Version: ipVersion,
|
||||
Address: net.IPNet{
|
||||
IP: ipAddress,
|
||||
Mask: ipSubnet.Mask},
|
||||
Gateway: net.ParseIP(hcnEndpoint.Routes[0].NextHop),
|
||||
}
|
||||
result := ¤t.Result{}
|
||||
result.Interfaces = []*current.Interface{resultInterface}
|
||||
result.IPs = []*current.IPConfig{resultIPConfig}
|
||||
result.DNS = types.DNS{
|
||||
result := ¤t.Result{
|
||||
CNIVersion: current.ImplementedSpecVersion,
|
||||
Interfaces: []*current.Interface{resultInterface},
|
||||
IPs: []*current.IPConfig{resultIPConfig},
|
||||
DNS: types.DNS{
|
||||
Search: hcnEndpoint.Dns.Search,
|
||||
Nameservers: hcnEndpoint.Dns.ServerList,
|
||||
},
|
||||
}
|
||||
|
||||
return result, nil
|
||||
|
@ -18,7 +18,7 @@ import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
)
|
||||
|
||||
func EnableIP4Forward() error {
|
||||
@ -36,12 +36,13 @@ func EnableForward(ips []*current.IPConfig) error {
|
||||
v6 := false
|
||||
|
||||
for _, ip := range ips {
|
||||
if ip.Version == "4" && !v4 {
|
||||
isV4 := ip.Address.IP.To4() != nil
|
||||
if isV4 && !v4 {
|
||||
if err := EnableIP4Forward(); err != nil {
|
||||
return err
|
||||
}
|
||||
v4 = true
|
||||
} else if ip.Version == "6" && !v6 {
|
||||
} else if !isV4 && !v6 {
|
||||
if err := EnableIP6Forward(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ import (
|
||||
"net"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
@ -57,15 +57,10 @@ func ValidateExpectedInterfaceIPs(ifName string, resultIPs []*current.IPConfig)
|
||||
|
||||
findGwy := &netlink.Route{Dst: ourPrefix}
|
||||
routeFilter := netlink.RT_FILTER_DST
|
||||
var family int
|
||||
|
||||
switch {
|
||||
case ips.Version == "4":
|
||||
family := netlink.FAMILY_V6
|
||||
if ips.Address.IP.To4() != nil {
|
||||
family = netlink.FAMILY_V4
|
||||
case ips.Version == "6":
|
||||
family = netlink.FAMILY_V6
|
||||
default:
|
||||
return fmt.Errorf("Invalid IP Version %v for interface %v", ips.Version, ifName)
|
||||
}
|
||||
|
||||
gwy, err := netlink.RouteListFiltered(family, findGwy, routeFilter)
|
||||
|
@ -19,7 +19,7 @@ import (
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/plugins/pkg/ip"
|
||||
"github.com/containernetworking/plugins/pkg/utils/sysctl"
|
||||
|
||||
@ -61,7 +61,7 @@ func ConfigureIface(ifName string, res *current.Result) error {
|
||||
|
||||
// Make sure sysctl "disable_ipv6" is 0 if we are about to add
|
||||
// an IPv6 address to the interface
|
||||
if !has_enabled_ipv6 && ipc.Version == "6" {
|
||||
if !has_enabled_ipv6 && ipc.Address.IP.To4() == nil {
|
||||
// Enabled IPv6 for loopback "lo" and the interface
|
||||
// being configured
|
||||
for _, iface := range [2]string{"lo", ifName} {
|
||||
|
@ -19,7 +19,7 @@ import (
|
||||
"syscall"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/plugins/pkg/ns"
|
||||
"github.com/containernetworking/plugins/pkg/testutils"
|
||||
|
||||
@ -109,13 +109,11 @@ var _ = Describe("ConfigureIface", func() {
|
||||
},
|
||||
IPs: []*current.IPConfig{
|
||||
{
|
||||
Version: "4",
|
||||
Interface: current.Int(0),
|
||||
Address: *ipv4,
|
||||
Gateway: ipgw4,
|
||||
},
|
||||
{
|
||||
Version: "6",
|
||||
Interface: current.Int(0),
|
||||
Address: *ipv6,
|
||||
Gateway: ipgw6,
|
||||
@ -281,12 +279,10 @@ var _ = Describe("ConfigureIface", func() {
|
||||
},
|
||||
IPs: []*current.IPConfig{
|
||||
{
|
||||
Version: "4",
|
||||
Address: *ipv4,
|
||||
Gateway: ipgw4,
|
||||
},
|
||||
{
|
||||
Version: "6",
|
||||
Address: *ipv6,
|
||||
Gateway: ipgw6,
|
||||
},
|
||||
|
@ -17,13 +17,24 @@ package testutils
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// Ping shells out to the `ping` command. Returns nil if successful.
|
||||
func Ping(saddr, daddr string, isV6 bool, timeoutSec int) error {
|
||||
func Ping(saddr, daddr string, timeoutSec int) error {
|
||||
ip := net.ParseIP(saddr)
|
||||
if ip == nil {
|
||||
return fmt.Errorf("failed to parse IP %q", saddr)
|
||||
}
|
||||
|
||||
bin := "ping6"
|
||||
if ip.To4() != nil {
|
||||
bin = "ping"
|
||||
}
|
||||
|
||||
args := []string{
|
||||
"-c", "1",
|
||||
"-W", strconv.Itoa(timeoutSec),
|
||||
@ -31,11 +42,6 @@ func Ping(saddr, daddr string, isV6 bool, timeoutSec int) error {
|
||||
daddr,
|
||||
}
|
||||
|
||||
bin := "ping"
|
||||
if isV6 {
|
||||
bin = "ping6"
|
||||
}
|
||||
|
||||
cmd := exec.Command(bin, args...)
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stderr = &stderr
|
||||
|
54
pkg/testutils/testing.go
Normal file
54
pkg/testutils/testing.go
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright 2016 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package testutils
|
||||
|
||||
import (
|
||||
"github.com/containernetworking/cni/pkg/version"
|
||||
)
|
||||
|
||||
// AllSpecVersions contains all CNI spec version numbers
|
||||
var AllSpecVersions = [...]string{"0.1.0", "0.2.0", "0.3.0", "0.3.1", "0.4.0", "1.0.0"}
|
||||
|
||||
// SpecVersionHasIPVersion returns true if the given CNI specification version
|
||||
// includes the "version" field in the IP address elements
|
||||
func SpecVersionHasIPVersion(ver string) bool {
|
||||
for _, i := range []string{"0.3.0", "0.3.1", "0.4.0"} {
|
||||
if ver == i {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// SpecVersionHasCHECK returns true if the given CNI specification version
|
||||
// supports the CHECK command
|
||||
func SpecVersionHasCHECK(ver string) bool {
|
||||
ok, _ := version.GreaterThanOrEqualTo(ver, "0.4.0")
|
||||
return ok
|
||||
}
|
||||
|
||||
// SpecVersionHasChaining returns true if the given CNI specification version
|
||||
// supports plugin chaining
|
||||
func SpecVersionHasChaining(ver string) bool {
|
||||
ok, _ := version.GreaterThanOrEqualTo(ver, "0.3.0")
|
||||
return ok
|
||||
}
|
||||
|
||||
// SpecVersionHasMultipleIPs returns true if the given CNI specification version
|
||||
// supports more than one IP address of each family
|
||||
func SpecVersionHasMultipleIPs(ver string) bool {
|
||||
ok, _ := version.GreaterThanOrEqualTo(ver, "0.3.0")
|
||||
return ok
|
||||
}
|
@ -30,7 +30,7 @@ import (
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/coreos/go-systemd/activation"
|
||||
)
|
||||
|
||||
@ -43,13 +43,15 @@ type DHCP struct {
|
||||
leases map[string]*DHCPLease
|
||||
hostNetnsPrefix string
|
||||
clientTimeout time.Duration
|
||||
clientResendMax time.Duration
|
||||
broadcast bool
|
||||
}
|
||||
|
||||
func newDHCP(clientTimeout time.Duration) *DHCP {
|
||||
func newDHCP(clientTimeout, clientResendMax time.Duration) *DHCP {
|
||||
return &DHCP{
|
||||
leases: make(map[string]*DHCPLease),
|
||||
clientTimeout: clientTimeout,
|
||||
clientResendMax: clientResendMax,
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,7 +69,7 @@ func (d *DHCP) Allocate(args *skel.CmdArgs, result *current.Result) error {
|
||||
|
||||
clientID := generateClientID(args.ContainerID, conf.Name, args.IfName)
|
||||
hostNetns := d.hostNetnsPrefix + args.Netns
|
||||
l, err := AcquireLease(clientID, hostNetns, args.IfName, d.clientTimeout, d.broadcast)
|
||||
l, err := AcquireLease(clientID, hostNetns, args.IfName, d.clientTimeout, d.clientResendMax, d.broadcast)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -81,7 +83,6 @@ func (d *DHCP) Allocate(args *skel.CmdArgs, result *current.Result) error {
|
||||
d.setLease(clientID, l)
|
||||
|
||||
result.IPs = []*current.IPConfig{{
|
||||
Version: "4",
|
||||
Address: *ipn,
|
||||
Gateway: l.Gateway(),
|
||||
}}
|
||||
@ -162,7 +163,7 @@ func getListener(socketPath string) (net.Listener, error) {
|
||||
|
||||
func runDaemon(
|
||||
pidfilePath, hostPrefix, socketPath string,
|
||||
dhcpClientTimeout time.Duration, broadcast bool,
|
||||
dhcpClientTimeout time.Duration, resendMax time.Duration, broadcast bool,
|
||||
) error {
|
||||
// since other goroutines (on separate threads) will change namespaces,
|
||||
// ensure the RPC server does not get scheduled onto those
|
||||
@ -183,7 +184,7 @@ func runDaemon(
|
||||
return fmt.Errorf("Error getting listener: %v", err)
|
||||
}
|
||||
|
||||
dhcp := newDHCP(dhcpClientTimeout)
|
||||
dhcp := newDHCP(dhcpClientTimeout, resendMax)
|
||||
dhcp.hostNetnsPrefix = hostPrefix
|
||||
dhcp.broadcast = broadcast
|
||||
rpc.Register(dhcp)
|
||||
|
@ -23,7 +23,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/plugins/pkg/ns"
|
||||
"github.com/containernetworking/plugins/pkg/testutils"
|
||||
|
||||
|
@ -15,7 +15,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
@ -25,7 +27,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
"github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/plugins/pkg/ns"
|
||||
"github.com/containernetworking/plugins/pkg/testutils"
|
||||
|
||||
@ -208,6 +210,11 @@ var _ = Describe("DHCP Operations", func() {
|
||||
dhcpPluginPath, err := exec.LookPath("dhcp")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
clientCmd = exec.Command(dhcpPluginPath, "daemon", "-socketpath", socketPath)
|
||||
|
||||
// copy dhcp client's stdout/stderr to test stdout
|
||||
clientCmd.Stdout = os.Stdout
|
||||
clientCmd.Stderr = os.Stderr
|
||||
|
||||
err = clientCmd.Start()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(clientCmd.Process).NotTo(BeNil())
|
||||
@ -226,20 +233,28 @@ var _ = Describe("DHCP Operations", func() {
|
||||
clientCmd.Wait()
|
||||
|
||||
Expect(originalNS.Close()).To(Succeed())
|
||||
Expect(testutils.UnmountNS(originalNS)).To(Succeed())
|
||||
Expect(targetNS.Close()).To(Succeed())
|
||||
defer os.RemoveAll(tmpDir)
|
||||
Expect(testutils.UnmountNS(targetNS)).To(Succeed())
|
||||
|
||||
Expect(os.RemoveAll(tmpDir)).To(Succeed())
|
||||
})
|
||||
|
||||
It("configures and deconfigures a link with ADD/DEL", func() {
|
||||
for _, ver := range testutils.AllSpecVersions {
|
||||
// Redefine ver inside for scope so real value is picked up by each dynamically defined It()
|
||||
// See Gingkgo's "Patterns for dynamically generating tests" documentation.
|
||||
ver := ver
|
||||
|
||||
It(fmt.Sprintf("[%s] configures and deconfigures a link with ADD/DEL", ver), func() {
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "ipvlan",
|
||||
"ipam": {
|
||||
"type": "dhcp",
|
||||
"daemonSocketPath": "%s"
|
||||
}
|
||||
}`, socketPath)
|
||||
}`, ver, socketPath)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
@ -248,7 +263,7 @@ var _ = Describe("DHCP Operations", func() {
|
||||
StdinData: []byte(conf),
|
||||
}
|
||||
|
||||
var addResult *current.Result
|
||||
var addResult *types100.Result
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
@ -257,7 +272,7 @@ var _ = Describe("DHCP Operations", func() {
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
addResult, err = current.GetResult(r)
|
||||
addResult, err = types100.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(len(addResult.IPs)).To(Equal(1))
|
||||
Expect(addResult.IPs[0].Address.String()).To(Equal("192.168.1.5/24"))
|
||||
@ -273,16 +288,16 @@ var _ = Describe("DHCP Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("correctly handles multiple DELs for the same container", func() {
|
||||
It(fmt.Sprintf("[%s] correctly handles multiple DELs for the same container", ver), func() {
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "ipvlan",
|
||||
"ipam": {
|
||||
"type": "dhcp",
|
||||
"daemonSocketPath": "%s"
|
||||
}
|
||||
}`, socketPath)
|
||||
}`, ver, socketPath)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
@ -291,7 +306,7 @@ var _ = Describe("DHCP Operations", func() {
|
||||
StdinData: []byte(conf),
|
||||
}
|
||||
|
||||
var addResult *current.Result
|
||||
var addResult *types100.Result
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
@ -300,7 +315,7 @@ var _ = Describe("DHCP Operations", func() {
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
addResult, err = current.GetResult(r)
|
||||
addResult, err = types100.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(len(addResult.IPs)).To(Equal(1))
|
||||
Expect(addResult.IPs[0].Address.String()).To(Equal("192.168.1.5/24"))
|
||||
@ -338,6 +353,7 @@ var _ = Describe("DHCP Operations", func() {
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
const (
|
||||
@ -508,7 +524,19 @@ var _ = Describe("DHCP Lease Unavailable Operations", func() {
|
||||
// Start the DHCP client daemon
|
||||
dhcpPluginPath, err := exec.LookPath("dhcp")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
clientCmd = exec.Command(dhcpPluginPath, "daemon", "-socketpath", socketPath)
|
||||
// Use very short timeouts for lease-unavailable operations because
|
||||
// the same test is run many times, and the delays will exceed the
|
||||
// `go test` timeout with default delays. Since our DHCP server
|
||||
// and client daemon are local processes anyway, we can depend on
|
||||
// them to respond very quickly.
|
||||
clientCmd = exec.Command(dhcpPluginPath, "daemon", "-socketpath", socketPath, "-timeout", "2s", "-resendmax", "8s")
|
||||
|
||||
// copy dhcp client's stdout/stderr to test stdout
|
||||
var b bytes.Buffer
|
||||
mw := io.MultiWriter(os.Stdout, &b)
|
||||
clientCmd.Stdout = mw
|
||||
clientCmd.Stderr = mw
|
||||
|
||||
err = clientCmd.Start()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(clientCmd.Process).NotTo(BeNil())
|
||||
@ -527,13 +555,21 @@ var _ = Describe("DHCP Lease Unavailable Operations", func() {
|
||||
clientCmd.Wait()
|
||||
|
||||
Expect(originalNS.Close()).To(Succeed())
|
||||
Expect(testutils.UnmountNS(originalNS)).To(Succeed())
|
||||
Expect(targetNS.Close()).To(Succeed())
|
||||
defer os.RemoveAll(tmpDir)
|
||||
Expect(testutils.UnmountNS(targetNS)).To(Succeed())
|
||||
|
||||
Expect(os.RemoveAll(tmpDir)).To(Succeed())
|
||||
})
|
||||
|
||||
It("Configures multiple links with multiple ADD with second lease unavailable", func() {
|
||||
for _, ver := range testutils.AllSpecVersions {
|
||||
// Redefine ver inside for scope so real value is picked up by each dynamically defined It()
|
||||
// See Gingkgo's "Patterns for dynamically generating tests" documentation.
|
||||
ver := ver
|
||||
|
||||
It(fmt.Sprintf("[%s] configures multiple links with multiple ADD with second lease unavailable", ver), func() {
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "bridge",
|
||||
"bridge": "%s",
|
||||
@ -541,7 +577,7 @@ var _ = Describe("DHCP Lease Unavailable Operations", func() {
|
||||
"type": "dhcp",
|
||||
"daemonSocketPath": "%s"
|
||||
}
|
||||
}`, hostBridgeName, socketPath)
|
||||
}`, ver, hostBridgeName, socketPath)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
@ -550,7 +586,7 @@ var _ = Describe("DHCP Lease Unavailable Operations", func() {
|
||||
StdinData: []byte(conf),
|
||||
}
|
||||
|
||||
var addResult *current.Result
|
||||
var addResult *types100.Result
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
@ -559,7 +595,7 @@ var _ = Describe("DHCP Lease Unavailable Operations", func() {
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
addResult, err = current.GetResult(r)
|
||||
addResult, err = types100.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(len(addResult.IPs)).To(Equal(1))
|
||||
Expect(addResult.IPs[0].Address.String()).To(Equal("192.168.1.5/24"))
|
||||
@ -615,4 +651,5 @@ var _ = Describe("DHCP Lease Unavailable Operations", func() {
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
}
|
||||
})
|
||||
|
@ -57,6 +57,7 @@ type DHCPLease struct {
|
||||
rebindingTime time.Time
|
||||
expireTime time.Time
|
||||
timeout time.Duration
|
||||
resendMax time.Duration
|
||||
broadcast bool
|
||||
stopping uint32
|
||||
stop chan struct{}
|
||||
@ -68,13 +69,14 @@ type DHCPLease struct {
|
||||
// calling DHCPLease.Stop()
|
||||
func AcquireLease(
|
||||
clientID, netns, ifName string,
|
||||
timeout time.Duration, broadcast bool,
|
||||
timeout, resendMax time.Duration, broadcast bool,
|
||||
) (*DHCPLease, error) {
|
||||
errCh := make(chan error, 1)
|
||||
l := &DHCPLease{
|
||||
clientID: clientID,
|
||||
stop: make(chan struct{}),
|
||||
timeout: timeout,
|
||||
resendMax: resendMax,
|
||||
broadcast: broadcast,
|
||||
}
|
||||
|
||||
@ -139,7 +141,7 @@ func (l *DHCPLease) acquire() error {
|
||||
opts[dhcp4.OptionClientIdentifier] = []byte(l.clientID)
|
||||
opts[dhcp4.OptionParameterRequestList] = []byte{byte(dhcp4.OptionRouter), byte(dhcp4.OptionSubnetMask)}
|
||||
|
||||
pkt, err := backoffRetry(func() (*dhcp4.Packet, error) {
|
||||
pkt, err := backoffRetry(l.resendMax, func() (*dhcp4.Packet, error) {
|
||||
ok, ack, err := DhcpRequest(c, opts)
|
||||
switch {
|
||||
case err != nil:
|
||||
@ -258,7 +260,7 @@ func (l *DHCPLease) renew() error {
|
||||
opts := make(dhcp4.Options)
|
||||
opts[dhcp4.OptionClientIdentifier] = []byte(l.clientID)
|
||||
|
||||
pkt, err := backoffRetry(func() (*dhcp4.Packet, error) {
|
||||
pkt, err := backoffRetry(l.resendMax, func() (*dhcp4.Packet, error) {
|
||||
ok, ack, err := DhcpRenew(c, *l.ack, opts)
|
||||
switch {
|
||||
case err != nil:
|
||||
@ -340,7 +342,7 @@ func jitter(span time.Duration) time.Duration {
|
||||
return time.Duration(float64(span) * (2.0*rand.Float64() - 1.0))
|
||||
}
|
||||
|
||||
func backoffRetry(f func() (*dhcp4.Packet, error)) (*dhcp4.Packet, error) {
|
||||
func backoffRetry(resendMax time.Duration, f func() (*dhcp4.Packet, error)) (*dhcp4.Packet, error) {
|
||||
var baseDelay time.Duration = resendDelay0
|
||||
var sleepTime time.Duration
|
||||
|
||||
@ -358,7 +360,7 @@ func backoffRetry(f func() (*dhcp4.Packet, error)) (*dhcp4.Packet, error) {
|
||||
|
||||
time.Sleep(sleepTime)
|
||||
|
||||
if baseDelay < resendDelayMax {
|
||||
if baseDelay < resendMax {
|
||||
baseDelay *= 2
|
||||
} else {
|
||||
break
|
||||
|
@ -26,7 +26,7 @@ import (
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/cni/pkg/version"
|
||||
bv "github.com/containernetworking/plugins/pkg/utils/buildversion"
|
||||
)
|
||||
@ -40,19 +40,21 @@ func main() {
|
||||
var socketPath string
|
||||
var broadcast bool
|
||||
var timeout time.Duration
|
||||
var resendMax time.Duration
|
||||
daemonFlags := flag.NewFlagSet("daemon", flag.ExitOnError)
|
||||
daemonFlags.StringVar(&pidfilePath, "pidfile", "", "optional path to write daemon PID to")
|
||||
daemonFlags.StringVar(&hostPrefix, "hostprefix", "", "optional prefix to host root")
|
||||
daemonFlags.StringVar(&socketPath, "socketpath", "", "optional dhcp server socketpath")
|
||||
daemonFlags.BoolVar(&broadcast, "broadcast", false, "broadcast DHCP leases")
|
||||
daemonFlags.DurationVar(&timeout, "timeout", 10*time.Second, "optional dhcp client timeout duration")
|
||||
daemonFlags.DurationVar(&resendMax, "resendmax", resendDelayMax, "optional dhcp client resend max duration")
|
||||
daemonFlags.Parse(os.Args[2:])
|
||||
|
||||
if socketPath == "" {
|
||||
socketPath = defaultSocketPath
|
||||
}
|
||||
|
||||
if err := runDaemon(pidfilePath, hostPrefix, socketPath, timeout, broadcast); err != nil {
|
||||
if err := runDaemon(pidfilePath, hostPrefix, socketPath, timeout, resendMax, broadcast); err != nil {
|
||||
log.Printf(err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
@ -69,7 +71,7 @@ func cmdAdd(args *skel.CmdArgs) error {
|
||||
return err
|
||||
}
|
||||
|
||||
result := ¤t.Result{}
|
||||
result := ¤t.Result{CNIVersion: current.ImplementedSpecVersion}
|
||||
if err := rpcCall("DHCP.Allocate", args, result); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -96,7 +98,7 @@ func cmdCheck(args *skel.CmdArgs) error {
|
||||
return err
|
||||
}
|
||||
|
||||
result := ¤t.Result{}
|
||||
result := ¤t.Result{CNIVersion: current.ImplementedSpecVersion}
|
||||
if err := rpcCall("DHCP.Allocate", args, result); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ import (
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/plugins/pkg/ip"
|
||||
"github.com/containernetworking/plugins/plugins/ipam/host-local/backend"
|
||||
)
|
||||
@ -108,13 +108,8 @@ func (a *IPAllocator) Get(id string, ifname string, requestedIP net.IP) (*curren
|
||||
if reservedIP == nil {
|
||||
return nil, fmt.Errorf("no IP addresses available in range set: %s", a.rangeset.String())
|
||||
}
|
||||
version := "4"
|
||||
if reservedIP.IP.To4() == nil {
|
||||
version = "6"
|
||||
}
|
||||
|
||||
return ¤t.IPConfig{
|
||||
Version: version,
|
||||
Address: *reservedIP,
|
||||
Gateway: gw,
|
||||
}, nil
|
||||
|
@ -19,7 +19,7 @@ import (
|
||||
"net"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
fakestore "github.com/containernetworking/plugins/plugins/ipam/host-local/backend/testing"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
|
@ -20,7 +20,7 @@ import (
|
||||
"net"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/020"
|
||||
"github.com/containernetworking/cni/pkg/version"
|
||||
)
|
||||
|
||||
// The top-level network config - IPAM plugins are passed the full configuration
|
||||
@ -136,12 +136,10 @@ func LoadIPAMConfig(bytes []byte, envArgs string) (*IPAMConfig, string, error) {
|
||||
|
||||
// CNI spec 0.2.0 and below supported only one v4 and v6 address
|
||||
if numV4 > 1 || numV6 > 1 {
|
||||
for _, v := range types020.SupportedVersions {
|
||||
if n.CNIVersion == v {
|
||||
if ok, _ := version.GreaterThanOrEqualTo(n.CNIVersion, "0.3.0"); !ok {
|
||||
return nil, "", fmt.Errorf("CNI version %v does not support more than 1 address per family", n.CNIVersion)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for overlaps
|
||||
l := len(n.IPAM.Ranges)
|
||||
|
@ -24,8 +24,7 @@ import (
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/020"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
"github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/plugins/pkg/testutils"
|
||||
|
||||
"github.com/containernetworking/plugins/plugins/ipam/host-local/backend/disk"
|
||||
@ -36,19 +35,34 @@ import (
|
||||
const LineBreak = "\r\n"
|
||||
|
||||
var _ = Describe("host-local Operations", func() {
|
||||
It("allocates and releases addresses with ADD/DEL", func() {
|
||||
const ifname string = "eth0"
|
||||
const nspath string = "/some/where"
|
||||
var tmpDir string
|
||||
const (
|
||||
ifname string = "eth0"
|
||||
nspath string = "/some/where"
|
||||
)
|
||||
|
||||
tmpDir, err := getTmpDir()
|
||||
BeforeEach(func() {
|
||||
var err error
|
||||
tmpDir, err = ioutil.TempDir("", "host-local_test")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer os.RemoveAll(tmpDir)
|
||||
tmpDir = filepath.ToSlash(tmpDir)
|
||||
})
|
||||
|
||||
err = ioutil.WriteFile(filepath.Join(tmpDir, "resolv.conf"), []byte("nameserver 192.0.2.3"), 0644)
|
||||
AfterEach(func() {
|
||||
os.RemoveAll(tmpDir)
|
||||
})
|
||||
|
||||
for _, ver := range testutils.AllSpecVersions {
|
||||
// Redefine ver inside for scope so real value is picked up by each dynamically defined It()
|
||||
// See Gingkgo's "Patterns for dynamically generating tests" documentation.
|
||||
ver := ver
|
||||
|
||||
It(fmt.Sprintf("[%s] allocates and releases addresses with ADD/DEL", ver), func() {
|
||||
err := ioutil.WriteFile(filepath.Join(tmpDir, "resolv.conf"), []byte("nameserver 192.0.2.3"), 0644)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "ipvlan",
|
||||
"master": "foo0",
|
||||
@ -67,7 +81,7 @@ var _ = Describe("host-local Operations", func() {
|
||||
{"dst": "2001:db8:2::0/64", "gw": "2001:db8:3::1"}
|
||||
]
|
||||
}
|
||||
}`, tmpDir, tmpDir)
|
||||
}`, ver, tmpDir, tmpDir)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
@ -81,34 +95,43 @@ var _ = Describe("host-local Operations", func() {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
if testutils.SpecVersionHasIPVersion(ver) {
|
||||
Expect(strings.Index(string(raw), "\"version\":")).Should(BeNumerically(">", 0))
|
||||
}
|
||||
|
||||
result, err := current.GetResult(r)
|
||||
result, err := types100.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Gomega is cranky about slices with different caps
|
||||
Expect(*result.IPs[0]).To(Equal(
|
||||
current.IPConfig{
|
||||
Version: "4",
|
||||
types100.IPConfig{
|
||||
Address: mustCIDR("10.1.2.2/24"),
|
||||
Gateway: net.ParseIP("10.1.2.1"),
|
||||
}))
|
||||
|
||||
Expect(*result.IPs[1]).To(Equal(
|
||||
current.IPConfig{
|
||||
Version: "6",
|
||||
types100.IPConfig{
|
||||
Address: mustCIDR("2001:db8:1::2/64"),
|
||||
Gateway: net.ParseIP("2001:db8:1::1"),
|
||||
},
|
||||
))
|
||||
Expect(len(result.IPs)).To(Equal(2))
|
||||
|
||||
Expect(result.Routes).To(Equal([]*types.Route{
|
||||
for _, expectedRoute := range []*types.Route{
|
||||
{Dst: mustCIDR("0.0.0.0/0"), GW: nil},
|
||||
{Dst: mustCIDR("::/0"), GW: nil},
|
||||
{Dst: mustCIDR("192.168.0.0/16"), GW: net.ParseIP("1.1.1.1")},
|
||||
{Dst: mustCIDR("2001:db8:2::0/64"), GW: net.ParseIP("2001:db8:3::1")},
|
||||
}))
|
||||
} {
|
||||
found := false
|
||||
for _, foundRoute := range result.Routes {
|
||||
if foundRoute.String() == expectedRoute.String() {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
Expect(found).To(BeTrue())
|
||||
}
|
||||
|
||||
ipFilePath1 := filepath.Join(tmpDir, "mynet", "10.1.2.2")
|
||||
contents, err := ioutil.ReadFile(ipFilePath1)
|
||||
@ -141,20 +164,14 @@ var _ = Describe("host-local Operations", func() {
|
||||
Expect(err).To(HaveOccurred())
|
||||
})
|
||||
|
||||
It("allocates and releases addresses on specific interface with ADD/DEL", func() {
|
||||
const ifname0 string = "eth0"
|
||||
It(fmt.Sprintf("[%s] allocates and releases addresses on specific interface with ADD/DEL", ver), func() {
|
||||
const ifname1 string = "eth1"
|
||||
const nspath string = "/some/where"
|
||||
|
||||
tmpDir, err := getTmpDir()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
err = ioutil.WriteFile(filepath.Join(tmpDir, "resolv.conf"), []byte("nameserver 192.0.2.3"), 0644)
|
||||
err := ioutil.WriteFile(filepath.Join(tmpDir, "resolv.conf"), []byte("nameserver 192.0.2.3"), 0644)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
conf0 := fmt.Sprintf(`{
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet0",
|
||||
"type": "ipvlan",
|
||||
"master": "foo0",
|
||||
@ -166,10 +183,10 @@ var _ = Describe("host-local Operations", func() {
|
||||
[{ "subnet": "10.1.2.0/24" }]
|
||||
]
|
||||
}
|
||||
}`, tmpDir, tmpDir)
|
||||
}`, ver, tmpDir, tmpDir)
|
||||
|
||||
conf1 := fmt.Sprintf(`{
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet1",
|
||||
"type": "ipvlan",
|
||||
"master": "foo1",
|
||||
@ -181,12 +198,12 @@ var _ = Describe("host-local Operations", func() {
|
||||
[{ "subnet": "10.2.2.0/24" }]
|
||||
]
|
||||
}
|
||||
}`, tmpDir, tmpDir)
|
||||
}`, ver, tmpDir, tmpDir)
|
||||
|
||||
args0 := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: nspath,
|
||||
IfName: ifname0,
|
||||
IfName: ifname,
|
||||
StdinData: []byte(conf0),
|
||||
}
|
||||
|
||||
@ -195,9 +212,11 @@ var _ = Describe("host-local Operations", func() {
|
||||
return cmdAdd(args0)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
if testutils.SpecVersionHasIPVersion(ver) {
|
||||
Expect(strings.Index(string(raw), "\"version\":")).Should(BeNumerically(">", 0))
|
||||
}
|
||||
|
||||
_, err = current.GetResult(r0)
|
||||
_, err = types100.GetResult(r0)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
args1 := &skel.CmdArgs{
|
||||
@ -212,22 +231,24 @@ var _ = Describe("host-local Operations", func() {
|
||||
return cmdAdd(args1)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
if testutils.SpecVersionHasIPVersion(ver) {
|
||||
Expect(strings.Index(string(raw), "\"version\":")).Should(BeNumerically(">", 0))
|
||||
}
|
||||
|
||||
_, err = current.GetResult(r1)
|
||||
_, err = types100.GetResult(r1)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
ipFilePath0 := filepath.Join(tmpDir, "mynet0", "10.1.2.2")
|
||||
contents, err := ioutil.ReadFile(ipFilePath0)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(string(contents)).To(Equal(args0.ContainerID + LineBreak + ifname0))
|
||||
Expect(string(contents)).To(Equal(args0.ContainerID + LineBreak + ifname))
|
||||
|
||||
ipFilePath1 := filepath.Join(tmpDir, "mynet1", "10.2.2.2")
|
||||
contents, err = ioutil.ReadFile(ipFilePath1)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(string(contents)).To(Equal(args1.ContainerID + LineBreak + ifname1))
|
||||
|
||||
// Release the IP on ifname0
|
||||
// Release the IP on ifname
|
||||
err = testutils.CmdDelWithArgs(args0, func() error {
|
||||
return cmdDel(args0)
|
||||
})
|
||||
@ -250,16 +271,9 @@ var _ = Describe("host-local Operations", func() {
|
||||
Expect(err).To(HaveOccurred())
|
||||
})
|
||||
|
||||
It("repeat allocating addresses on specific interface for same container ID with ADD", func() {
|
||||
const ifname string = "eth0"
|
||||
const nspath string = "/some/where"
|
||||
|
||||
tmpDir, err := getTmpDir()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
It(fmt.Sprintf("[%s] repeat allocating addresses on specific interface for same container ID with ADD", ver), func() {
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet0",
|
||||
"type": "ipvlan",
|
||||
"master": "foo0",
|
||||
@ -270,7 +284,7 @@ var _ = Describe("host-local Operations", func() {
|
||||
[{ "subnet": "10.1.2.0/24" }]
|
||||
]
|
||||
}
|
||||
}`, tmpDir)
|
||||
}`, ver, tmpDir)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
@ -291,9 +305,11 @@ var _ = Describe("host-local Operations", func() {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
if testutils.SpecVersionHasIPVersion(ver) {
|
||||
Expect(strings.Index(string(raw), "\"version\":")).Should(BeNumerically(">", 0))
|
||||
}
|
||||
|
||||
result0, err := current.GetResult(r0)
|
||||
result0, err := types100.GetResult(r0)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(len(result0.IPs)).Should(Equal(1))
|
||||
Expect(result0.IPs[0].Address.String()).Should(Equal("10.1.2.2/24"))
|
||||
@ -309,9 +325,11 @@ var _ = Describe("host-local Operations", func() {
|
||||
return cmdAdd(args1)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
if testutils.SpecVersionHasIPVersion(ver) {
|
||||
Expect(strings.Index(string(raw), "\"version\":")).Should(BeNumerically(">", 0))
|
||||
}
|
||||
|
||||
result1, err := current.GetResult(r1)
|
||||
result1, err := types100.GetResult(r1)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(len(result1.IPs)).Should(Equal(1))
|
||||
Expect(result1.IPs[0].Address.String()).Should(Equal("10.1.2.3/24"))
|
||||
@ -338,19 +356,12 @@ var _ = Describe("host-local Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("Verify DEL works on backwards compatible allocate", func() {
|
||||
const nspath string = "/some/where"
|
||||
const ifname string = "eth0"
|
||||
|
||||
tmpDir, err := getTmpDir()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
err = ioutil.WriteFile(filepath.Join(tmpDir, "resolv.conf"), []byte("nameserver 192.0.2.3"), 0644)
|
||||
It(fmt.Sprintf("[%s] verify DEL works on backwards compatible allocate", ver), func() {
|
||||
err := ioutil.WriteFile(filepath.Join(tmpDir, "resolv.conf"), []byte("nameserver 192.0.2.3"), 0644)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "ipvlan",
|
||||
"master": "foo",
|
||||
@ -362,7 +373,7 @@ var _ = Describe("host-local Operations", func() {
|
||||
[{ "subnet": "10.1.2.0/24" }]
|
||||
]
|
||||
}
|
||||
}`, tmpDir, tmpDir)
|
||||
}`, ver, tmpDir, tmpDir)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
@ -376,9 +387,11 @@ var _ = Describe("host-local Operations", func() {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
if testutils.SpecVersionHasIPVersion(ver) {
|
||||
Expect(strings.Index(string(raw), "\"version\":")).Should(BeNumerically(">", 0))
|
||||
}
|
||||
|
||||
_, err = current.GetResult(r)
|
||||
_, err = types100.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
ipFilePath := filepath.Join(tmpDir, "mynet", "10.1.2.2")
|
||||
@ -396,16 +409,9 @@ var _ = Describe("host-local Operations", func() {
|
||||
Expect(err).To(HaveOccurred())
|
||||
})
|
||||
|
||||
It("doesn't error when passed an unknown ID on DEL", func() {
|
||||
const ifname string = "eth0"
|
||||
const nspath string = "/some/where"
|
||||
|
||||
tmpDir, err := getTmpDir()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
It(fmt.Sprintf("[%s] doesn't error when passed an unknown ID on DEL", ver), func() {
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.3.0",
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "ipvlan",
|
||||
"master": "foo0",
|
||||
@ -414,7 +420,7 @@ var _ = Describe("host-local Operations", func() {
|
||||
"subnet": "10.1.2.0/24",
|
||||
"dataDir": "%s"
|
||||
}
|
||||
}`, tmpDir)
|
||||
}`, ver, tmpDir)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
@ -424,91 +430,15 @@ var _ = Describe("host-local Operations", func() {
|
||||
}
|
||||
|
||||
// Release the IP
|
||||
err = testutils.CmdDelWithArgs(args, func() error {
|
||||
err := testutils.CmdDelWithArgs(args, func() error {
|
||||
return cmdDel(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("allocates and releases an address with ADD/DEL and 0.1.0 config", func() {
|
||||
const ifname string = "eth0"
|
||||
const nspath string = "/some/where"
|
||||
|
||||
tmpDir, err := getTmpDir()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
err = ioutil.WriteFile(filepath.Join(tmpDir, "resolv.conf"), []byte("nameserver 192.0.2.3"), 0644)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
It(fmt.Sprintf("[%s] ignores whitespace in disk files", ver), func() {
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.1.0",
|
||||
"name": "mynet",
|
||||
"type": "ipvlan",
|
||||
"master": "foo0",
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": "10.1.2.0/24",
|
||||
"dataDir": "%s",
|
||||
"resolvConf": "%s/resolv.conf"
|
||||
}
|
||||
}`, tmpDir, tmpDir)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: nspath,
|
||||
IfName: ifname,
|
||||
StdinData: []byte(conf),
|
||||
}
|
||||
|
||||
// Allocate the IP
|
||||
r, raw, err := testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(strings.Index(string(raw), "\"ip4\":")).Should(BeNumerically(">", 0))
|
||||
|
||||
result, err := types020.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
expectedAddress, err := types.ParseCIDR("10.1.2.2/24")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
expectedAddress.IP = expectedAddress.IP.To16()
|
||||
Expect(result.IP4.IP).To(Equal(*expectedAddress))
|
||||
Expect(result.IP4.Gateway).To(Equal(net.ParseIP("10.1.2.1")))
|
||||
|
||||
ipFilePath := filepath.Join(tmpDir, "mynet", "10.1.2.2")
|
||||
contents, err := ioutil.ReadFile(ipFilePath)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(string(contents)).To(Equal(args.ContainerID + LineBreak + ifname))
|
||||
|
||||
lastFilePath := filepath.Join(tmpDir, "mynet", "last_reserved_ip.0")
|
||||
contents, err = ioutil.ReadFile(lastFilePath)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(string(contents)).To(Equal("10.1.2.2"))
|
||||
|
||||
Expect(result.DNS).To(Equal(types.DNS{Nameservers: []string{"192.0.2.3"}}))
|
||||
|
||||
// Release the IP
|
||||
err = testutils.CmdDelWithArgs(args, func() error {
|
||||
return cmdDel(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
_, err = os.Stat(ipFilePath)
|
||||
Expect(err).To(HaveOccurred())
|
||||
})
|
||||
|
||||
It("ignores whitespace in disk files", func() {
|
||||
const ifname string = "eth0"
|
||||
const nspath string = "/some/where"
|
||||
|
||||
tmpDir, err := getTmpDir()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "ipvlan",
|
||||
"master": "foo0",
|
||||
@ -517,7 +447,7 @@ var _ = Describe("host-local Operations", func() {
|
||||
"subnet": "10.1.2.0/24",
|
||||
"dataDir": "%s"
|
||||
}
|
||||
}`, tmpDir)
|
||||
}`, ver, tmpDir)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: " dummy\n ",
|
||||
@ -532,7 +462,7 @@ var _ = Describe("host-local Operations", func() {
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
result, err := current.GetResult(r)
|
||||
result, err := types100.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
ipFilePath := filepath.Join(tmpDir, "mynet", result.IPs[0].Address.IP.String())
|
||||
@ -550,16 +480,9 @@ var _ = Describe("host-local Operations", func() {
|
||||
Expect(err).To(HaveOccurred())
|
||||
})
|
||||
|
||||
It("does not output an error message upon initial subnet creation", func() {
|
||||
const ifname string = "eth0"
|
||||
const nspath string = "/some/where"
|
||||
|
||||
tmpDir, err := getTmpDir()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
It(fmt.Sprintf("[%s] does not output an error message upon initial subnet creation", ver), func() {
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.2.0",
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "ipvlan",
|
||||
"master": "foo0",
|
||||
@ -568,7 +491,7 @@ var _ = Describe("host-local Operations", func() {
|
||||
"subnet": "10.1.2.0/24",
|
||||
"dataDir": "%s"
|
||||
}
|
||||
}`, tmpDir)
|
||||
}`, ver, tmpDir)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "testing",
|
||||
@ -585,16 +508,9 @@ var _ = Describe("host-local Operations", func() {
|
||||
Expect(strings.Index(string(out), "Error retriving last reserved ip")).To(Equal(-1))
|
||||
})
|
||||
|
||||
It("allocates a custom IP when requested by config args", func() {
|
||||
const ifname string = "eth0"
|
||||
const nspath string = "/some/where"
|
||||
|
||||
tmpDir, err := getTmpDir()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
It(fmt.Sprintf("[%s] allocates a custom IP when requested by config args", ver), func() {
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "ipvlan",
|
||||
"master": "foo0",
|
||||
@ -610,7 +526,7 @@ var _ = Describe("host-local Operations", func() {
|
||||
"ips": ["10.1.2.88"]
|
||||
}
|
||||
}
|
||||
}`, tmpDir)
|
||||
}`, ver, tmpDir)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
@ -624,25 +540,18 @@ var _ = Describe("host-local Operations", func() {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
result, err := current.GetResult(r)
|
||||
result, err := types100.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(result.IPs).To(HaveLen(1))
|
||||
Expect(result.IPs[0].Address.IP).To(Equal(net.ParseIP("10.1.2.88")))
|
||||
})
|
||||
|
||||
It("allocates custom IPs from multiple ranges", func() {
|
||||
const ifname string = "eth0"
|
||||
const nspath string = "/some/where"
|
||||
|
||||
tmpDir, err := getTmpDir()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
err = ioutil.WriteFile(filepath.Join(tmpDir, "resolv.conf"), []byte("nameserver 192.0.2.3"), 0644)
|
||||
It(fmt.Sprintf("[%s] allocates custom IPs from multiple ranges", ver), func() {
|
||||
err := ioutil.WriteFile(filepath.Join(tmpDir, "resolv.conf"), []byte("nameserver 192.0.2.3"), 0644)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "ipvlan",
|
||||
"master": "foo0",
|
||||
@ -659,7 +568,7 @@ var _ = Describe("host-local Operations", func() {
|
||||
"ips": ["10.1.2.88", "10.1.3.77"]
|
||||
}
|
||||
}
|
||||
}`, tmpDir)
|
||||
}`, ver, tmpDir)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
@ -672,27 +581,25 @@ var _ = Describe("host-local Operations", func() {
|
||||
r, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
if !testutils.SpecVersionHasMultipleIPs(ver) {
|
||||
errStr := fmt.Sprintf("CNI version %s does not support more than 1 address per family", ver)
|
||||
Expect(err).To(MatchError(errStr))
|
||||
} else {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
result, err := current.GetResult(r)
|
||||
result, err := types100.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(result.IPs).To(HaveLen(2))
|
||||
Expect(result.IPs[0].Address.IP).To(Equal(net.ParseIP("10.1.2.88")))
|
||||
Expect(result.IPs[1].Address.IP).To(Equal(net.ParseIP("10.1.3.77")))
|
||||
}
|
||||
})
|
||||
|
||||
It("allocates custom IPs from multiple protocols", func() {
|
||||
const ifname string = "eth0"
|
||||
const nspath string = "/some/where"
|
||||
|
||||
tmpDir, err := getTmpDir()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
err = ioutil.WriteFile(filepath.Join(tmpDir, "resolv.conf"), []byte("nameserver 192.0.2.3"), 0644)
|
||||
It(fmt.Sprintf("[%s] allocates custom IPs from multiple protocols", ver), func() {
|
||||
err := ioutil.WriteFile(filepath.Join(tmpDir, "resolv.conf"), []byte("nameserver 192.0.2.3"), 0644)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "ipvlan",
|
||||
"master": "foo0",
|
||||
@ -709,7 +616,7 @@ var _ = Describe("host-local Operations", func() {
|
||||
"ips": ["10.1.2.88", "2001:db8:1::999"]
|
||||
}
|
||||
}
|
||||
}`, tmpDir)
|
||||
}`, ver, tmpDir)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
@ -723,23 +630,16 @@ var _ = Describe("host-local Operations", func() {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
result, err := current.GetResult(r)
|
||||
result, err := types100.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(result.IPs).To(HaveLen(2))
|
||||
Expect(result.IPs[0].Address.IP).To(Equal(net.ParseIP("10.1.2.88")))
|
||||
Expect(result.IPs[1].Address.IP).To(Equal(net.ParseIP("2001:db8:1::999")))
|
||||
})
|
||||
|
||||
It("fails if a requested custom IP is not used", func() {
|
||||
const ifname string = "eth0"
|
||||
const nspath string = "/some/where"
|
||||
|
||||
tmpDir, err := getTmpDir()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
It(fmt.Sprintf("[%s] fails if a requested custom IP is not used", ver), func() {
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "ipvlan",
|
||||
"master": "foo0",
|
||||
@ -756,7 +656,7 @@ var _ = Describe("host-local Operations", func() {
|
||||
"ips": ["10.1.2.88", "10.1.2.77"]
|
||||
}
|
||||
}
|
||||
}`, tmpDir)
|
||||
}`, ver, tmpDir)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
@ -766,23 +666,20 @@ var _ = Describe("host-local Operations", func() {
|
||||
}
|
||||
|
||||
// Allocate the IP
|
||||
_, _, err = testutils.CmdAddWithArgs(args, func() error {
|
||||
_, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
if !testutils.SpecVersionHasMultipleIPs(ver) {
|
||||
errStr := fmt.Sprintf("CNI version %s does not support more than 1 address per family", ver)
|
||||
Expect(err).To(MatchError(errStr))
|
||||
} else {
|
||||
Expect(err).To(HaveOccurred())
|
||||
// Need to match prefix, because ordering is not guaranteed
|
||||
Expect(err.Error()).To(HavePrefix("failed to allocate all requested IPs: 10.1.2."))
|
||||
})
|
||||
})
|
||||
|
||||
func getTmpDir() (string, error) {
|
||||
tmpDir, err := ioutil.TempDir("", "host_local_artifacts")
|
||||
if err == nil {
|
||||
tmpDir = filepath.ToSlash(tmpDir)
|
||||
}
|
||||
|
||||
return tmpDir, err
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
func mustCIDR(s string) net.IPNet {
|
||||
ip, n, err := net.ParseCIDR(s)
|
||||
|
@ -25,7 +25,7 @@ import (
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/cni/pkg/version"
|
||||
)
|
||||
|
||||
@ -62,7 +62,7 @@ func cmdAdd(args *skel.CmdArgs) error {
|
||||
return err
|
||||
}
|
||||
|
||||
result := ¤t.Result{}
|
||||
result := ¤t.Result{CNIVersion: current.ImplementedSpecVersion}
|
||||
|
||||
if ipamConf.ResolvConf != "" {
|
||||
dns, err := parseResolvConf(ipamConf.ResolvConf)
|
||||
|
@ -22,8 +22,7 @@ import (
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
types020 "github.com/containernetworking/cni/pkg/types/020"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/cni/pkg/version"
|
||||
bv "github.com/containernetworking/plugins/pkg/utils/buildversion"
|
||||
)
|
||||
@ -225,22 +224,18 @@ func LoadIPAMConfig(bytes []byte, envArgs string) (*IPAMConfig, string, error) {
|
||||
}
|
||||
|
||||
if n.IPAM.Addresses[i].Address.IP.To4() != nil {
|
||||
n.IPAM.Addresses[i].Version = "4"
|
||||
numV4++
|
||||
} else {
|
||||
n.IPAM.Addresses[i].Version = "6"
|
||||
numV6++
|
||||
}
|
||||
}
|
||||
|
||||
// CNI spec 0.2.0 and below supported only one v4 and v6 address
|
||||
if numV4 > 1 || numV6 > 1 {
|
||||
for _, v := range types020.SupportedVersions {
|
||||
if n.CNIVersion == v {
|
||||
if ok, _ := version.GreaterThanOrEqualTo(n.CNIVersion, "0.3.0"); !ok {
|
||||
return nil, "", fmt.Errorf("CNI version %v does not support more than 1 address per family", n.CNIVersion)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy net name into IPAM so not to drag Net struct around
|
||||
n.IPAM.Name = n.Name
|
||||
@ -254,14 +249,16 @@ func cmdAdd(args *skel.CmdArgs) error {
|
||||
return err
|
||||
}
|
||||
|
||||
result := ¤t.Result{}
|
||||
result.DNS = ipamConf.DNS
|
||||
result.Routes = ipamConf.Routes
|
||||
result := ¤t.Result{
|
||||
CNIVersion: current.ImplementedSpecVersion,
|
||||
DNS: ipamConf.DNS,
|
||||
Routes: ipamConf.Routes,
|
||||
}
|
||||
for _, v := range ipamConf.Addresses {
|
||||
result.IPs = append(result.IPs, ¤t.IPConfig{
|
||||
Version: v.Version,
|
||||
Address: v.Address,
|
||||
Gateway: v.Gateway})
|
||||
Gateway: v.Gateway,
|
||||
})
|
||||
}
|
||||
|
||||
return types.PrintResult(result, confVersion)
|
||||
|
@ -15,12 +15,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
"github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/plugins/pkg/testutils"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
@ -28,12 +29,17 @@ import (
|
||||
)
|
||||
|
||||
var _ = Describe("static Operations", func() {
|
||||
It("allocates and releases addresses with ADD/DEL", func() {
|
||||
for _, ver := range testutils.AllSpecVersions {
|
||||
// Redefine ver inside for scope so real value is picked up by each dynamically defined It()
|
||||
// See Gingkgo's "Patterns for dynamically generating tests" documentation.
|
||||
ver := ver
|
||||
|
||||
It(fmt.Sprintf("[%s] allocates and releases addresses with ADD/DEL", ver), func() {
|
||||
const ifname string = "eth0"
|
||||
const nspath string = "/some/where"
|
||||
|
||||
conf := `{
|
||||
"cniVersion": "0.3.1",
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "ipvlan",
|
||||
"master": "foo0",
|
||||
@ -57,7 +63,7 @@ var _ = Describe("static Operations", func() {
|
||||
"search": [ "example.com" ]
|
||||
}
|
||||
}
|
||||
}`
|
||||
}`, ver)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
@ -71,22 +77,22 @@ var _ = Describe("static Operations", func() {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
if testutils.SpecVersionHasIPVersion(ver) {
|
||||
Expect(strings.Index(string(raw), "\"version\":")).Should(BeNumerically(">", 0))
|
||||
}
|
||||
|
||||
result, err := current.GetResult(r)
|
||||
result, err := types100.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Gomega is cranky about slices with different caps
|
||||
Expect(*result.IPs[0]).To(Equal(
|
||||
current.IPConfig{
|
||||
Version: "4",
|
||||
types100.IPConfig{
|
||||
Address: mustCIDR("10.10.0.1/24"),
|
||||
Gateway: net.ParseIP("10.10.0.254"),
|
||||
}))
|
||||
|
||||
Expect(*result.IPs[1]).To(Equal(
|
||||
current.IPConfig{
|
||||
Version: "6",
|
||||
types100.IPConfig{
|
||||
Address: mustCIDR("3ffe:ffff:0:01ff::1/64"),
|
||||
Gateway: net.ParseIP("3ffe:ffff:0::1"),
|
||||
},
|
||||
@ -106,12 +112,12 @@ var _ = Describe("static Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("doesn't error when passed an unknown ID on DEL", func() {
|
||||
It(fmt.Sprintf("[%s] doesn't error when passed an unknown ID on DEL", ver), func() {
|
||||
const ifname string = "eth0"
|
||||
const nspath string = "/some/where"
|
||||
|
||||
conf := `{
|
||||
"cniVersion": "0.3.0",
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "ipvlan",
|
||||
"master": "foo0",
|
||||
@ -133,7 +139,9 @@ var _ = Describe("static Operations", func() {
|
||||
"nameservers" : ["8.8.8.8"],
|
||||
"domain": "example.com",
|
||||
"search": [ "example.com" ]
|
||||
}}}`
|
||||
}
|
||||
}
|
||||
}`, ver)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
@ -149,12 +157,12 @@ var _ = Describe("static Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("allocates and releases addresses with ADD/DEL, with ENV variables", func() {
|
||||
It(fmt.Sprintf("[%s] allocates and releases addresses with ADD/DEL, with ENV variables", ver), func() {
|
||||
const ifname string = "eth0"
|
||||
const nspath string = "/some/where"
|
||||
|
||||
conf := `{
|
||||
"cniVersion": "0.3.1",
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "ipvlan",
|
||||
"master": "foo0",
|
||||
@ -169,7 +177,7 @@ var _ = Describe("static Operations", func() {
|
||||
"search": [ "example.com" ]
|
||||
}
|
||||
}
|
||||
}`
|
||||
}`, ver)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
@ -184,15 +192,16 @@ var _ = Describe("static Operations", func() {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
if testutils.SpecVersionHasIPVersion(ver) {
|
||||
Expect(strings.Index(string(raw), "\"version\":")).Should(BeNumerically(">", 0))
|
||||
}
|
||||
|
||||
result, err := current.GetResult(r)
|
||||
result, err := types100.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Gomega is cranky about slices with different caps
|
||||
Expect(*result.IPs[0]).To(Equal(
|
||||
current.IPConfig{
|
||||
Version: "4",
|
||||
types100.IPConfig{
|
||||
Address: mustCIDR("10.10.0.1/24"),
|
||||
Gateway: net.ParseIP("10.10.0.254"),
|
||||
}))
|
||||
@ -211,19 +220,19 @@ var _ = Describe("static Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("allocates and releases multiple addresses with ADD/DEL, with ENV variables", func() {
|
||||
It(fmt.Sprintf("[%s] allocates and releases multiple addresses with ADD/DEL, with ENV variables", ver), func() {
|
||||
const ifname string = "eth0"
|
||||
const nspath string = "/some/where"
|
||||
|
||||
conf := `{
|
||||
"cniVersion": "0.3.1",
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "ipvlan",
|
||||
"master": "foo0",
|
||||
"ipam": {
|
||||
"type": "static"
|
||||
}
|
||||
}`
|
||||
}`, ver)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
@ -237,22 +246,28 @@ var _ = Describe("static Operations", func() {
|
||||
r, raw, err := testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(strings.Index(string(raw), "\"version\":")).Should(BeNumerically(">", 0))
|
||||
if !testutils.SpecVersionHasMultipleIPs(ver) {
|
||||
errStr := fmt.Sprintf("CNI version %s does not support more than 1 address per family", ver)
|
||||
Expect(err).To(MatchError(errStr))
|
||||
return
|
||||
}
|
||||
|
||||
result, err := current.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
if testutils.SpecVersionHasIPVersion(ver) {
|
||||
Expect(strings.Index(string(raw), "\"version\":")).Should(BeNumerically(">", 0))
|
||||
}
|
||||
|
||||
result, err := types100.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Gomega is cranky about slices with different caps
|
||||
Expect(*result.IPs[0]).To(Equal(
|
||||
current.IPConfig{
|
||||
Version: "4",
|
||||
types100.IPConfig{
|
||||
Address: mustCIDR("10.10.0.1/24"),
|
||||
Gateway: net.ParseIP("10.10.0.254"),
|
||||
}))
|
||||
Expect(*result.IPs[1]).To(Equal(
|
||||
current.IPConfig{
|
||||
Version: "4",
|
||||
types100.IPConfig{
|
||||
Address: mustCIDR("11.11.0.1/24"),
|
||||
Gateway: nil,
|
||||
}))
|
||||
@ -266,12 +281,12 @@ var _ = Describe("static Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("allocates and releases multiple addresses with ADD/DEL, from RuntimeConfig", func() {
|
||||
It(fmt.Sprintf("[%s] allocates and releases multiple addresses with ADD/DEL, from RuntimeConfig", ver), func() {
|
||||
const ifname string = "eth0"
|
||||
const nspath string = "/some/where"
|
||||
|
||||
conf := `{
|
||||
"cniVersion": "0.3.1",
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "ipvlan",
|
||||
"master": "foo0",
|
||||
@ -291,7 +306,7 @@ var _ = Describe("static Operations", func() {
|
||||
"RuntimeConfig": {
|
||||
"ips" : ["10.10.0.1/24", "3ffe:ffff:0:01ff::1/64"]
|
||||
}
|
||||
}`
|
||||
}`, ver)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
@ -305,20 +320,20 @@ var _ = Describe("static Operations", func() {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
if testutils.SpecVersionHasIPVersion(ver) {
|
||||
Expect(strings.Index(string(raw), "\"version\":")).Should(BeNumerically(">", 0))
|
||||
}
|
||||
|
||||
result, err := current.GetResult(r)
|
||||
result, err := types100.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Gomega is cranky about slices with different caps
|
||||
Expect(*result.IPs[0]).To(Equal(
|
||||
current.IPConfig{
|
||||
Version: "4",
|
||||
types100.IPConfig{
|
||||
Address: mustCIDR("10.10.0.1/24"),
|
||||
}))
|
||||
Expect(*result.IPs[1]).To(Equal(
|
||||
current.IPConfig{
|
||||
Version: "6",
|
||||
types100.IPConfig{
|
||||
Address: mustCIDR("3ffe:ffff:0:01ff::1/64"),
|
||||
},
|
||||
))
|
||||
@ -335,12 +350,12 @@ var _ = Describe("static Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("allocates and releases multiple addresses with ADD/DEL, from args", func() {
|
||||
It(fmt.Sprintf("[%s] allocates and releases multiple addresses with ADD/DEL, from args", ver), func() {
|
||||
const ifname string = "eth0"
|
||||
const nspath string = "/some/where"
|
||||
|
||||
conf := `{
|
||||
"cniVersion": "0.3.1",
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "ipvlan",
|
||||
"master": "foo0",
|
||||
@ -361,7 +376,7 @@ var _ = Describe("static Operations", func() {
|
||||
"ips" : ["10.10.0.1/24", "3ffe:ffff:0:01ff::1/64"]
|
||||
}
|
||||
}
|
||||
}`
|
||||
}`, ver)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
@ -375,20 +390,20 @@ var _ = Describe("static Operations", func() {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
if testutils.SpecVersionHasIPVersion(ver) {
|
||||
Expect(strings.Index(string(raw), "\"version\":")).Should(BeNumerically(">", 0))
|
||||
}
|
||||
|
||||
result, err := current.GetResult(r)
|
||||
result, err := types100.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Gomega is cranky about slices with different caps
|
||||
Expect(*result.IPs[0]).To(Equal(
|
||||
current.IPConfig{
|
||||
Version: "4",
|
||||
types100.IPConfig{
|
||||
Address: mustCIDR("10.10.0.1/24"),
|
||||
}))
|
||||
Expect(*result.IPs[1]).To(Equal(
|
||||
current.IPConfig{
|
||||
Version: "6",
|
||||
types100.IPConfig{
|
||||
Address: mustCIDR("3ffe:ffff:0:01ff::1/64"),
|
||||
},
|
||||
))
|
||||
@ -405,12 +420,12 @@ var _ = Describe("static Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("allocates and releases multiple addresses with ADD/DEL, from RuntimeConfig/ARGS/CNI_ARGS", func() {
|
||||
It(fmt.Sprintf("[%s] allocates and releases multiple addresses with ADD/DEL, from RuntimeConfig/ARGS/CNI_ARGS", ver), func() {
|
||||
const ifname string = "eth0"
|
||||
const nspath string = "/some/where"
|
||||
|
||||
conf := `{
|
||||
"cniVersion": "0.3.1",
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "ipvlan",
|
||||
"master": "foo0",
|
||||
@ -435,7 +450,7 @@ var _ = Describe("static Operations", func() {
|
||||
"ips" : ["10.10.0.2/24", "3ffe:ffff:0:01ff::2/64"]
|
||||
}
|
||||
}
|
||||
}`
|
||||
}`, ver)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
@ -450,20 +465,20 @@ var _ = Describe("static Operations", func() {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
if testutils.SpecVersionHasIPVersion(ver) {
|
||||
Expect(strings.Index(string(raw), "\"version\":")).Should(BeNumerically(">", 0))
|
||||
}
|
||||
|
||||
result, err := current.GetResult(r)
|
||||
result, err := types100.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// only addresses in runtimeConfig configured because of its priorities
|
||||
Expect(*result.IPs[0]).To(Equal(
|
||||
current.IPConfig{
|
||||
Version: "4",
|
||||
types100.IPConfig{
|
||||
Address: mustCIDR("10.10.0.1/24"),
|
||||
}))
|
||||
Expect(*result.IPs[1]).To(Equal(
|
||||
current.IPConfig{
|
||||
Version: "6",
|
||||
types100.IPConfig{
|
||||
Address: mustCIDR("3ffe:ffff:0:01ff::1/64"),
|
||||
},
|
||||
))
|
||||
@ -479,7 +494,7 @@ var _ = Describe("static Operations", func() {
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
func mustCIDR(s string) net.IPNet {
|
||||
|
@ -29,7 +29,7 @@ import (
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/cni/pkg/version"
|
||||
"github.com/containernetworking/plugins/pkg/ip"
|
||||
"github.com/containernetworking/plugins/pkg/ipam"
|
||||
@ -412,7 +412,14 @@ func cmdAdd(args *skel.CmdArgs) error {
|
||||
}
|
||||
|
||||
// Assume L2 interface only
|
||||
result := ¤t.Result{CNIVersion: cniVersion, Interfaces: []*current.Interface{brInterface, hostInterface, containerInterface}}
|
||||
result := ¤t.Result{
|
||||
CNIVersion: current.ImplementedSpecVersion,
|
||||
Interfaces: []*current.Interface{
|
||||
brInterface,
|
||||
hostInterface,
|
||||
containerInterface,
|
||||
},
|
||||
}
|
||||
|
||||
if isLayer3 {
|
||||
// run the IPAM plugin and get back the config to apply
|
||||
@ -453,7 +460,7 @@ func cmdAdd(args *skel.CmdArgs) error {
|
||||
// bridge. Hairpin mode causes echos of neighbor solicitation
|
||||
// packets, which causes DAD failures.
|
||||
for _, ipc := range result.IPs {
|
||||
if ipc.Version == "6" && (n.HairpinMode || n.PromiscMode) {
|
||||
if ipc.Address.IP.To4() == nil && (n.HairpinMode || n.PromiscMode) {
|
||||
if err := disableIPV6DAD(args.IfName); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -496,7 +503,7 @@ func cmdAdd(args *skel.CmdArgs) error {
|
||||
}
|
||||
|
||||
for _, ipc := range result.IPs {
|
||||
if ipc.Version == "4" {
|
||||
if ipc.Address.IP.To4() != nil {
|
||||
_ = arping.GratuitousArpOverIface(ipc.Address.IP, *contVeth)
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -30,7 +30,7 @@ import (
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/cni/pkg/version"
|
||||
|
||||
"github.com/containernetworking/plugins/pkg/ip"
|
||||
|
@ -23,8 +23,9 @@ import (
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
types020 "github.com/containernetworking/cni/pkg/types/020"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
"github.com/containernetworking/cni/pkg/types/040"
|
||||
"github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/cni/pkg/version"
|
||||
"github.com/containernetworking/plugins/pkg/ns"
|
||||
"github.com/containernetworking/plugins/pkg/testutils"
|
||||
|
||||
@ -44,7 +45,7 @@ type Net struct {
|
||||
IPAM *IPAMConfig `json:"ipam,omitempty"`
|
||||
DNS types.DNS `json:"dns"`
|
||||
RawPrevResult map[string]interface{} `json:"prevResult,omitempty"`
|
||||
PrevResult current.Result `json:"-"`
|
||||
PrevResult types100.Result `json:"-"`
|
||||
}
|
||||
|
||||
type IPAMConfig struct {
|
||||
@ -110,10 +111,8 @@ func LoadIPAMConfig(bytes []byte, envArgs string) (*IPAMConfig, string, error) {
|
||||
}
|
||||
|
||||
if n.IPAM.Addresses[i].Address.IP.To4() != nil {
|
||||
n.IPAM.Addresses[i].Version = "4"
|
||||
numV4++
|
||||
} else {
|
||||
n.IPAM.Addresses[i].Version = "6"
|
||||
numV6++
|
||||
}
|
||||
}
|
||||
@ -136,10 +135,8 @@ func LoadIPAMConfig(bytes []byte, envArgs string) (*IPAMConfig, string, error) {
|
||||
|
||||
addr := Address{Address: net.IPNet{IP: ip, Mask: subnet.Mask}}
|
||||
if addr.Address.IP.To4() != nil {
|
||||
addr.Version = "4"
|
||||
numV4++
|
||||
} else {
|
||||
addr.Version = "6"
|
||||
numV6++
|
||||
}
|
||||
n.IPAM.Addresses = append(n.IPAM.Addresses, addr)
|
||||
@ -164,12 +161,10 @@ func LoadIPAMConfig(bytes []byte, envArgs string) (*IPAMConfig, string, error) {
|
||||
|
||||
// CNI spec 0.2.0 and below supported only one v4 and v6 address
|
||||
if numV4 > 1 || numV6 > 1 {
|
||||
for _, v := range types020.SupportedVersions {
|
||||
if n.CNIVersion == v {
|
||||
if ok, _ := version.GreaterThanOrEqualTo(n.CNIVersion, "0.3.0"); !ok {
|
||||
return nil, "", fmt.Errorf("CNI version %v does not support more than 1 address per family", n.CNIVersion)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy net name into IPAM so not to drag Net struct around
|
||||
n.IPAM.Name = n.Name
|
||||
@ -220,14 +215,79 @@ func buildOneConfig(name, cniVersion string, orig *Net, prevResult types.Result)
|
||||
|
||||
}
|
||||
|
||||
type tester interface {
|
||||
expectInterfaces(result types.Result, name, mac, sandbox string)
|
||||
}
|
||||
|
||||
type testerBase struct{}
|
||||
|
||||
type testerV10x testerBase
|
||||
type testerV04x testerBase
|
||||
type testerV03x testerBase
|
||||
|
||||
func newTesterByVersion(version string) tester {
|
||||
switch {
|
||||
case strings.HasPrefix(version, "1.0."):
|
||||
return &testerV10x{}
|
||||
case strings.HasPrefix(version, "0.4."):
|
||||
return &testerV04x{}
|
||||
case strings.HasPrefix(version, "0.3."):
|
||||
return &testerV03x{}
|
||||
default:
|
||||
Fail(fmt.Sprintf("unsupported config version %s", version))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *testerV10x) expectInterfaces(result types.Result, name, mac, sandbox string) {
|
||||
// check that the result was sane
|
||||
res, err := types100.NewResultFromResult(result)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(res.Interfaces).To(Equal([]*types100.Interface{
|
||||
{
|
||||
Name: name,
|
||||
Mac: mac,
|
||||
Sandbox: sandbox,
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
func (t *testerV04x) expectInterfaces(result types.Result, name, mac, sandbox string) {
|
||||
// check that the result was sane
|
||||
res, err := types040.NewResultFromResult(result)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(res.Interfaces).To(Equal([]*types040.Interface{
|
||||
{
|
||||
Name: name,
|
||||
Mac: mac,
|
||||
Sandbox: sandbox,
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
func (t *testerV03x) expectInterfaces(result types.Result, name, mac, sandbox string) {
|
||||
// check that the result was sane
|
||||
res, err := types040.NewResultFromResult(result)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(res.Interfaces).To(Equal([]*types040.Interface{
|
||||
{
|
||||
Name: name,
|
||||
Mac: mac,
|
||||
Sandbox: sandbox,
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
var _ = Describe("base functionality", func() {
|
||||
var originalNS ns.NetNS
|
||||
var originalNS, targetNS ns.NetNS
|
||||
var ifname string
|
||||
|
||||
BeforeEach(func() {
|
||||
var err error
|
||||
originalNS, err = testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
targetNS, err = testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
ifname = fmt.Sprintf("dummy-%x", rand.Int31())
|
||||
})
|
||||
@ -235,9 +295,16 @@ var _ = Describe("base functionality", func() {
|
||||
AfterEach(func() {
|
||||
Expect(originalNS.Close()).To(Succeed())
|
||||
Expect(testutils.UnmountNS(originalNS)).To(Succeed())
|
||||
Expect(targetNS.Close()).To(Succeed())
|
||||
Expect(testutils.UnmountNS(targetNS)).To(Succeed())
|
||||
})
|
||||
|
||||
It("Works with a valid config without IPAM", func() {
|
||||
for _, ver := range []string{"0.3.0", "0.3.1", "0.4.0", "1.0.0"} {
|
||||
// Redefine ver inside for scope so real value is picked up by each dynamically defined It()
|
||||
// See Gingkgo's "Patterns for dynamically generating tests" documentation.
|
||||
ver := ver
|
||||
|
||||
It(fmt.Sprintf("[%s] works with a valid config without IPAM", ver), func() {
|
||||
var origLink netlink.Link
|
||||
|
||||
// prepare ifname in original namespace
|
||||
@ -257,16 +324,13 @@ var _ = Describe("base functionality", func() {
|
||||
})
|
||||
|
||||
// call CmdAdd
|
||||
targetNS, err := testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
cniName := "eth0"
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.3.0",
|
||||
"cniVersion": "%s",
|
||||
"name": "cni-plugin-host-device-test",
|
||||
"type": "host-device",
|
||||
"device": %q
|
||||
}`, ifname)
|
||||
}`, ver, ifname)
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNS.Path(),
|
||||
@ -274,7 +338,7 @@ var _ = Describe("base functionality", func() {
|
||||
StdinData: []byte(conf),
|
||||
}
|
||||
var resI types.Result
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
var err error
|
||||
resI, _, err = testutils.CmdAddWithArgs(args, func() error { return cmdAdd(args) })
|
||||
@ -283,15 +347,8 @@ var _ = Describe("base functionality", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// check that the result was sane
|
||||
res, err := current.NewResultFromResult(resI)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(res.Interfaces).To(Equal([]*current.Interface{
|
||||
{
|
||||
Name: cniName,
|
||||
Mac: origLink.Attrs().HardwareAddr.String(),
|
||||
Sandbox: targetNS.Path(),
|
||||
},
|
||||
}))
|
||||
t := newTesterByVersion(ver)
|
||||
t.expectInterfaces(resI, cniName, origLink.Attrs().HardwareAddr.String(), targetNS.Path())
|
||||
|
||||
// assert that dummy0 is now in the target namespace
|
||||
_ = targetNS.Do(func(ns.NetNS) error {
|
||||
@ -313,18 +370,18 @@ var _ = Describe("base functionality", func() {
|
||||
// Check that deleting the device moves it back and restores the name
|
||||
_ = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
err = testutils.CmdDelWithArgs(args, func() error {
|
||||
err := testutils.CmdDelWithArgs(args, func() error {
|
||||
return cmdDel(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
_, err := netlink.LinkByName(ifname)
|
||||
_, err = netlink.LinkByName(ifname)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
return nil
|
||||
})
|
||||
})
|
||||
|
||||
It("Test idempotence of CmdDel", func() {
|
||||
It(fmt.Sprintf("[%s] ensures CmdDel is idempotent", ver), func() {
|
||||
var (
|
||||
origLink netlink.Link
|
||||
conflictLink netlink.Link
|
||||
@ -347,16 +404,13 @@ var _ = Describe("base functionality", func() {
|
||||
})
|
||||
|
||||
// call CmdAdd
|
||||
targetNS, err := testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
cniName := "eth0"
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.3.0",
|
||||
"cniVersion": "%s",
|
||||
"name": "cni-plugin-host-device-test",
|
||||
"type": "host-device",
|
||||
"device": %q
|
||||
}`, ifname)
|
||||
}`, ver, ifname)
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNS.Path(),
|
||||
@ -364,7 +418,7 @@ var _ = Describe("base functionality", func() {
|
||||
StdinData: []byte(conf),
|
||||
}
|
||||
var resI types.Result
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
var err error
|
||||
resI, _, err = testutils.CmdAddWithArgs(args, func() error { return cmdAdd(args) })
|
||||
@ -372,16 +426,9 @@ var _ = Describe("base functionality", func() {
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// check that the result is sane
|
||||
res, err := current.NewResultFromResult(resI)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(res.Interfaces).To(Equal([]*current.Interface{
|
||||
{
|
||||
Name: cniName,
|
||||
Mac: origLink.Attrs().HardwareAddr.String(),
|
||||
Sandbox: targetNS.Path(),
|
||||
},
|
||||
}))
|
||||
// check that the result was sane
|
||||
t := newTesterByVersion(ver)
|
||||
t.expectInterfaces(resI, cniName, origLink.Attrs().HardwareAddr.String(), targetNS.Path())
|
||||
|
||||
// assert that dummy0 is now in the target namespace
|
||||
_ = targetNS.Do(func(ns.NetNS) error {
|
||||
@ -462,7 +509,7 @@ var _ = Describe("base functionality", func() {
|
||||
})
|
||||
})
|
||||
|
||||
It("Works with a valid config with IPAM", func() {
|
||||
It(fmt.Sprintf("Works with a valid %s config with IPAM", ver), func() {
|
||||
var origLink netlink.Link
|
||||
|
||||
// prepare ifname in original namespace
|
||||
@ -482,12 +529,10 @@ var _ = Describe("base functionality", func() {
|
||||
})
|
||||
|
||||
// call CmdAdd
|
||||
targetNS, err := testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
targetIP := "10.10.0.1/24"
|
||||
cniName := "eth0"
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.3.0",
|
||||
"cniVersion": "%s",
|
||||
"name": "cni-plugin-host-device-test",
|
||||
"type": "host-device",
|
||||
"ipam": {
|
||||
@ -499,7 +544,7 @@ var _ = Describe("base functionality", func() {
|
||||
}]
|
||||
},
|
||||
"device": %q
|
||||
}`, ifname)
|
||||
}`, ver, ifname)
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNS.Path(),
|
||||
@ -507,7 +552,7 @@ var _ = Describe("base functionality", func() {
|
||||
StdinData: []byte(conf),
|
||||
}
|
||||
var resI types.Result
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
var err error
|
||||
resI, _, err = testutils.CmdAddWithArgs(args, func() error { return cmdAdd(args) })
|
||||
@ -516,15 +561,8 @@ var _ = Describe("base functionality", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// check that the result was sane
|
||||
res, err := current.NewResultFromResult(resI)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(res.Interfaces).To(Equal([]*current.Interface{
|
||||
{
|
||||
Name: cniName,
|
||||
Mac: origLink.Attrs().HardwareAddr.String(),
|
||||
Sandbox: targetNS.Path(),
|
||||
},
|
||||
}))
|
||||
t := newTesterByVersion(ver)
|
||||
t.expectInterfaces(resI, cniName, origLink.Attrs().HardwareAddr.String(), targetNS.Path())
|
||||
|
||||
// assert that dummy0 is now in the target namespace
|
||||
_ = targetNS.Do(func(ns.NetNS) error {
|
||||
@ -565,12 +603,12 @@ var _ = Describe("base functionality", func() {
|
||||
})
|
||||
})
|
||||
|
||||
It("fails an invalid config", func() {
|
||||
conf := `{
|
||||
"cniVersion": "0.3.0",
|
||||
It(fmt.Sprintf("[%s] fails an invalid config", ver), func() {
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"name": "cni-plugin-host-device-test",
|
||||
"type": "host-device"
|
||||
}`
|
||||
}`, ver)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
@ -583,7 +621,7 @@ var _ = Describe("base functionality", func() {
|
||||
|
||||
})
|
||||
|
||||
It("Works with a valid 0.4.0 config without IPAM", func() {
|
||||
It(fmt.Sprintf("[%s] works with a valid config without IPAM", ver), func() {
|
||||
var origLink netlink.Link
|
||||
|
||||
// prepare ifname in original namespace
|
||||
@ -603,16 +641,13 @@ var _ = Describe("base functionality", func() {
|
||||
})
|
||||
|
||||
// call CmdAdd
|
||||
targetNS, err := testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
cniName := "eth0"
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.4.0",
|
||||
"cniVersion": "%s",
|
||||
"name": "cni-plugin-host-device-test",
|
||||
"type": "host-device",
|
||||
"device": %q
|
||||
}`, ifname)
|
||||
}`, ver, ifname)
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNS.Path(),
|
||||
@ -620,7 +655,7 @@ var _ = Describe("base functionality", func() {
|
||||
StdinData: []byte(conf),
|
||||
}
|
||||
var resI types.Result
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
var err error
|
||||
resI, _, err = testutils.CmdAddWithArgs(args, func() error { return cmdAdd(args) })
|
||||
@ -629,15 +664,8 @@ var _ = Describe("base functionality", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// check that the result was sane
|
||||
res, err := current.NewResultFromResult(resI)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(res.Interfaces).To(Equal([]*current.Interface{
|
||||
{
|
||||
Name: cniName,
|
||||
Mac: origLink.Attrs().HardwareAddr.String(),
|
||||
Sandbox: targetNS.Path(),
|
||||
},
|
||||
}))
|
||||
t := newTesterByVersion(ver)
|
||||
t.expectInterfaces(resI, cniName, origLink.Attrs().HardwareAddr.String(), targetNS.Path())
|
||||
|
||||
// assert that dummy0 is now in the target namespace
|
||||
_ = targetNS.Do(func(ns.NetNS) error {
|
||||
@ -656,13 +684,13 @@ var _ = Describe("base functionality", func() {
|
||||
return nil
|
||||
})
|
||||
|
||||
if testutils.SpecVersionHasCHECK(ver) {
|
||||
// call CmdCheck
|
||||
n := &Net{}
|
||||
err = json.Unmarshal([]byte(conf), &n)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
cniVersion := "0.4.0"
|
||||
newConf, err := buildOneConfig("testConfig", cniVersion, n, res)
|
||||
newConf, err := buildOneConfig("testConfig", ver, n, resI)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
confString, err := json.Marshal(newConf)
|
||||
@ -674,11 +702,10 @@ var _ = Describe("base functionality", func() {
|
||||
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
var err error
|
||||
err = testutils.CmdCheckWithArgs(args, func() error { return cmdCheck(args) })
|
||||
return err
|
||||
return testutils.CmdCheckWithArgs(args, func() error { return cmdCheck(args) })
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
|
||||
// Check that deleting the device moves it back and restores the name
|
||||
_ = originalNS.Do(func(ns.NetNS) error {
|
||||
@ -694,7 +721,7 @@ var _ = Describe("base functionality", func() {
|
||||
})
|
||||
})
|
||||
|
||||
It("Works with a valid 0.4.0 config with IPAM", func() {
|
||||
It(fmt.Sprintf("Works with a valid %s config with IPAM", ver), func() {
|
||||
var origLink netlink.Link
|
||||
|
||||
// prepare ifname in original namespace
|
||||
@ -714,12 +741,10 @@ var _ = Describe("base functionality", func() {
|
||||
})
|
||||
|
||||
// call CmdAdd
|
||||
targetNS, err := testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
targetIP := "10.10.0.1/24"
|
||||
cniName := "eth0"
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.4.0",
|
||||
"cniVersion": "%s",
|
||||
"name": "cni-plugin-host-device-test",
|
||||
"type": "host-device",
|
||||
"ipam": {
|
||||
@ -731,7 +756,7 @@ var _ = Describe("base functionality", func() {
|
||||
}]
|
||||
},
|
||||
"device": %q
|
||||
}`, ifname)
|
||||
}`, ver, ifname)
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNS.Path(),
|
||||
@ -739,7 +764,7 @@ var _ = Describe("base functionality", func() {
|
||||
StdinData: []byte(conf),
|
||||
}
|
||||
var resI types.Result
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
var err error
|
||||
resI, _, err = testutils.CmdAddWithArgs(args, func() error { return cmdAdd(args) })
|
||||
@ -748,15 +773,8 @@ var _ = Describe("base functionality", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// check that the result was sane
|
||||
res, err := current.NewResultFromResult(resI)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(res.Interfaces).To(Equal([]*current.Interface{
|
||||
{
|
||||
Name: cniName,
|
||||
Mac: origLink.Attrs().HardwareAddr.String(),
|
||||
Sandbox: targetNS.Path(),
|
||||
},
|
||||
}))
|
||||
t := newTesterByVersion(ver)
|
||||
t.expectInterfaces(resI, cniName, origLink.Attrs().HardwareAddr.String(), targetNS.Path())
|
||||
|
||||
// assert that dummy0 is now in the target namespace
|
||||
_ = targetNS.Do(func(ns.NetNS) error {
|
||||
@ -791,8 +809,8 @@ var _ = Describe("base functionality", func() {
|
||||
n.IPAM, _, err = LoadIPAMConfig([]byte(conf), "")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
cniVersion := "0.4.0"
|
||||
newConf, err := buildOneConfig("testConfig", cniVersion, n, res)
|
||||
if testutils.SpecVersionHasCHECK(ver) {
|
||||
newConf, err := buildOneConfig("testConfig", ver, n, resI)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
confString, err := json.Marshal(newConf)
|
||||
@ -804,11 +822,10 @@ var _ = Describe("base functionality", func() {
|
||||
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
var err error
|
||||
err = testutils.CmdCheckWithArgs(args, func() error { return cmdCheck(args) })
|
||||
return err
|
||||
return testutils.CmdCheckWithArgs(args, func() error { return cmdCheck(args) })
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
|
||||
// Check that deleting the device moves it back and restores the name
|
||||
_ = originalNS.Do(func(ns.NetNS) error {
|
||||
@ -824,7 +841,7 @@ var _ = Describe("base functionality", func() {
|
||||
})
|
||||
})
|
||||
|
||||
It("Test idempotence of CmdDel with 0.4.0 config", func() {
|
||||
It(fmt.Sprintf("Test idempotence of CmdDel with %s config", ver), func() {
|
||||
var (
|
||||
origLink netlink.Link
|
||||
conflictLink netlink.Link
|
||||
@ -847,16 +864,13 @@ var _ = Describe("base functionality", func() {
|
||||
})
|
||||
|
||||
// call CmdAdd
|
||||
targetNS, err := testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
cniName := "eth0"
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.4.0",
|
||||
"cniVersion": "%s",
|
||||
"name": "cni-plugin-host-device-test",
|
||||
"type": "host-device",
|
||||
"device": %q
|
||||
}`, ifname)
|
||||
}`, ver, ifname)
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNS.Path(),
|
||||
@ -864,7 +878,7 @@ var _ = Describe("base functionality", func() {
|
||||
StdinData: []byte(conf),
|
||||
}
|
||||
var resI types.Result
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
var err error
|
||||
resI, _, err = testutils.CmdAddWithArgs(args, func() error { return cmdAdd(args) })
|
||||
@ -872,16 +886,9 @@ var _ = Describe("base functionality", func() {
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// check that the result is sane
|
||||
res, err := current.NewResultFromResult(resI)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(res.Interfaces).To(Equal([]*current.Interface{
|
||||
{
|
||||
Name: cniName,
|
||||
Mac: origLink.Attrs().HardwareAddr.String(),
|
||||
Sandbox: targetNS.Path(),
|
||||
},
|
||||
}))
|
||||
// check that the result was sane
|
||||
t := newTesterByVersion(ver)
|
||||
t.expectInterfaces(resI, cniName, origLink.Attrs().HardwareAddr.String(), targetNS.Path())
|
||||
|
||||
// assert that dummy0 is now in the target namespace
|
||||
_ = targetNS.Do(func(ns.NetNS) error {
|
||||
@ -962,4 +969,5 @@ var _ = Describe("base functionality", func() {
|
||||
return nil
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
|
@ -24,7 +24,7 @@ import (
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/cni/pkg/version"
|
||||
|
||||
"github.com/containernetworking/plugins/pkg/ip"
|
||||
|
@ -17,12 +17,17 @@ package main
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
"github.com/containernetworking/cni/pkg/types/020"
|
||||
"github.com/containernetworking/cni/pkg/types/040"
|
||||
"github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/plugins/pkg/ns"
|
||||
"github.com/containernetworking/plugins/pkg/testutils"
|
||||
|
||||
@ -44,37 +49,33 @@ type Net struct {
|
||||
IPAM *allocator.IPAMConfig `json:"ipam"`
|
||||
DNS types.DNS `json:"dns"`
|
||||
RawPrevResult map[string]interface{} `json:"prevResult,omitempty"`
|
||||
PrevResult current.Result `json:"-"`
|
||||
PrevResult types100.Result `json:"-"`
|
||||
}
|
||||
|
||||
func buildOneConfig(netName string, cniVersion string, master string, orig *Net, prevResult types.Result) (*Net, error) {
|
||||
var err error
|
||||
|
||||
inject := map[string]interface{}{
|
||||
"name": netName,
|
||||
"cniVersion": cniVersion,
|
||||
}
|
||||
// Add previous plugin result
|
||||
if prevResult != nil {
|
||||
inject["prevResult"] = prevResult
|
||||
}
|
||||
if orig.IPAM == nil {
|
||||
inject["master"] = master
|
||||
}
|
||||
|
||||
// Ensure every config uses the same name and version
|
||||
config := make(map[string]interface{})
|
||||
|
||||
func buildOneConfig(cniVersion string, master string, orig *Net, prevResult types.Result) (*Net, error) {
|
||||
confBytes, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
config := make(map[string]interface{})
|
||||
err = json.Unmarshal(confBytes, &config)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unmarshal existing network bytes: %s", err)
|
||||
}
|
||||
|
||||
inject := map[string]interface{}{
|
||||
"name": orig.Name,
|
||||
"cniVersion": orig.CNIVersion,
|
||||
}
|
||||
// Add previous plugin result
|
||||
if prevResult != nil && testutils.SpecVersionHasChaining(cniVersion) {
|
||||
inject["prevResult"] = prevResult
|
||||
}
|
||||
if master != "" {
|
||||
inject["master"] = master
|
||||
}
|
||||
|
||||
for key, value := range inject {
|
||||
config[key] = value
|
||||
}
|
||||
@ -93,122 +94,50 @@ func buildOneConfig(netName string, cniVersion string, master string, orig *Net,
|
||||
|
||||
}
|
||||
|
||||
func ipvlanAddDelTest(conf, IFNAME string, originalNS ns.NetNS) {
|
||||
targetNs, err := testutils.NewNS()
|
||||
func ipvlanAddCheckDelTest(conf, masterName string, originalNS, targetNS ns.NetNS) {
|
||||
// Unmarshal to pull out CNI spec version
|
||||
rawConfig := make(map[string]interface{})
|
||||
err := json.Unmarshal([]byte(conf), &rawConfig)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer targetNs.Close()
|
||||
cniVersion := rawConfig["cniVersion"].(string)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNs.Path(),
|
||||
IfName: IFNAME,
|
||||
Netns: targetNS.Path(),
|
||||
IfName: "ipvl0",
|
||||
StdinData: []byte(conf),
|
||||
}
|
||||
|
||||
var result *current.Result
|
||||
var result types.Result
|
||||
var macAddress string
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
r, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||
result, _, err = testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
result, err = current.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(result.Interfaces)).To(Equal(1))
|
||||
Expect(result.Interfaces[0].Name).To(Equal(IFNAME))
|
||||
Expect(len(result.IPs)).To(Equal(1))
|
||||
t := newTesterByVersion(cniVersion)
|
||||
macAddress = t.verifyResult(result, args.IfName)
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure ipvlan link exists in the target namespace
|
||||
err = targetNs.Do(func(ns.NetNS) error {
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
link, err := netlink.LinkByName(args.IfName)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().Name).To(Equal(IFNAME))
|
||||
Expect(link.Attrs().Name).To(Equal(args.IfName))
|
||||
|
||||
hwaddr, err := net.ParseMAC(result.Interfaces[0].Mac)
|
||||
if macAddress != "" {
|
||||
hwaddr, err := net.ParseMAC(macAddress)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().HardwareAddr).To(Equal(hwaddr))
|
||||
|
||||
addrs, err := netlink.AddrList(link, syscall.AF_INET)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(len(addrs)).To(Equal(1))
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
err = testutils.CmdDelWithArgs(args, func() error {
|
||||
return cmdDel(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure ipvlan link has been deleted
|
||||
err = targetNs.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(link).To(BeNil())
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
|
||||
func ipvlanAddCheckDelTest(conf string, netName string, IFNAME string, originalNS ns.NetNS) {
|
||||
targetNs, err := testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer targetNs.Close()
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNs.Path(),
|
||||
IfName: IFNAME,
|
||||
StdinData: []byte(conf),
|
||||
}
|
||||
|
||||
var result *current.Result
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
r, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
result, err = current.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(result.Interfaces)).To(Equal(1))
|
||||
Expect(result.Interfaces[0].Name).To(Equal(IFNAME))
|
||||
Expect(len(result.IPs)).To(Equal(1))
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure ipvlan link exists in the target namespace
|
||||
err = targetNs.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().Name).To(Equal(IFNAME))
|
||||
|
||||
hwaddr, err := net.ParseMAC(result.Interfaces[0].Mac)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().HardwareAddr).To(Equal(hwaddr))
|
||||
|
||||
addrs, err := netlink.AddrList(link, syscall.AF_INET)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(len(addrs)).To(Equal(1))
|
||||
@ -225,26 +154,26 @@ func ipvlanAddCheckDelTest(conf string, netName string, IFNAME string, originalN
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
|
||||
cniVersion := "0.4.0"
|
||||
newConf, err := buildOneConfig(netName, cniVersion, MASTER_NAME, n, result)
|
||||
// build chained/cached config for DEL
|
||||
newConf, err := buildOneConfig(cniVersion, masterName, n, result)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
confBytes, err := json.Marshal(newConf)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
confString, err := json.Marshal(newConf)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
args.StdinData = confString
|
||||
args.StdinData = confBytes
|
||||
GinkgoT().Logf(string(confBytes))
|
||||
|
||||
if testutils.SpecVersionHasCHECK(cniVersion) {
|
||||
// CNI Check on ipvlan in the target namespace
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
err := testutils.CmdCheckWithArgs(args, func() error {
|
||||
return testutils.CmdCheckWithArgs(args, func() error {
|
||||
return cmdCheck(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
@ -258,10 +187,10 @@ func ipvlanAddCheckDelTest(conf string, netName string, IFNAME string, originalN
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure ipvlan link has been deleted
|
||||
err = targetNs.Do(func(ns.NetNS) error {
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
link, err := netlink.LinkByName(args.IfName)
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(link).To(BeNil())
|
||||
return nil
|
||||
@ -269,8 +198,70 @@ func ipvlanAddCheckDelTest(conf string, netName string, IFNAME string, originalN
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
|
||||
type tester interface {
|
||||
// verifyResult minimally verifies the Result and returns the interface's MAC address
|
||||
verifyResult(result types.Result, name string) string
|
||||
}
|
||||
|
||||
type testerBase struct{}
|
||||
|
||||
type testerV10x testerBase
|
||||
type testerV04x testerBase
|
||||
type testerV02x testerBase
|
||||
|
||||
func newTesterByVersion(version string) tester {
|
||||
switch {
|
||||
case strings.HasPrefix(version, "1.0."):
|
||||
return &testerV10x{}
|
||||
case strings.HasPrefix(version, "0.4.") || strings.HasPrefix(version, "0.3."):
|
||||
return &testerV04x{}
|
||||
case strings.HasPrefix(version, "0.1.") || strings.HasPrefix(version, "0.2."):
|
||||
return &testerV02x{}
|
||||
}
|
||||
Fail(fmt.Sprintf("unsupported config version %s", version))
|
||||
return nil
|
||||
}
|
||||
|
||||
// verifyResult minimally verifies the Result and returns the interface's MAC address
|
||||
func (t *testerV10x) verifyResult(result types.Result, name string) string {
|
||||
r, err := types100.GetResult(result)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(r.Interfaces)).To(Equal(1))
|
||||
Expect(r.Interfaces[0].Name).To(Equal(name))
|
||||
Expect(len(r.IPs)).To(Equal(1))
|
||||
|
||||
return r.Interfaces[0].Mac
|
||||
}
|
||||
|
||||
// verifyResult minimally verifies the Result and returns the interface's MAC address
|
||||
func (t *testerV04x) verifyResult(result types.Result, name string) string {
|
||||
r, err := types040.GetResult(result)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(r.Interfaces)).To(Equal(1))
|
||||
Expect(r.Interfaces[0].Name).To(Equal(name))
|
||||
Expect(len(r.IPs)).To(Equal(1))
|
||||
|
||||
return r.Interfaces[0].Mac
|
||||
}
|
||||
|
||||
// verifyResult minimally verifies the Result and returns the interface's MAC address
|
||||
func (t *testerV02x) verifyResult(result types.Result, name string) string {
|
||||
r, err := types020.GetResult(result)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(r.IP4.IP).NotTo(BeNil())
|
||||
Expect(r.IP4.IP.IP).NotTo(BeNil())
|
||||
Expect(r.IP6).To(BeNil())
|
||||
|
||||
// 0.2 and earlier don't return MAC address
|
||||
return ""
|
||||
}
|
||||
|
||||
var _ = Describe("ipvlan Operations", func() {
|
||||
var originalNS ns.NetNS
|
||||
var originalNS, targetNS ns.NetNS
|
||||
var dataDir string
|
||||
|
||||
BeforeEach(func() {
|
||||
// Create a new NetNS so we don't modify the host
|
||||
@ -278,6 +269,12 @@ var _ = Describe("ipvlan Operations", func() {
|
||||
originalNS, err = testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
targetNS, err = testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
dataDir, err = ioutil.TempDir("", "ipvlan_test")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
@ -296,14 +293,24 @@ var _ = Describe("ipvlan Operations", func() {
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
Expect(os.RemoveAll(dataDir)).To(Succeed())
|
||||
|
||||
Expect(originalNS.Close()).To(Succeed())
|
||||
Expect(testutils.UnmountNS(originalNS)).To(Succeed())
|
||||
|
||||
Expect(targetNS.Close()).To(Succeed())
|
||||
Expect(testutils.UnmountNS(targetNS)).To(Succeed())
|
||||
})
|
||||
|
||||
It("creates an ipvlan link in a non-default namespace", func() {
|
||||
for _, ver := range testutils.AllSpecVersions {
|
||||
// Redefine ver inside for scope so real value is picked up by each dynamically defined It()
|
||||
// See Gingkgo's "Patterns for dynamically generating tests" documentation.
|
||||
ver := ver
|
||||
|
||||
It(fmt.Sprintf("[%s] creates an ipvlan link in a non-default namespace", ver), func() {
|
||||
conf := &NetConf{
|
||||
NetConf: types.NetConf{
|
||||
CNIVersion: "0.3.1",
|
||||
CNIVersion: ver,
|
||||
Name: "testConfig",
|
||||
Type: "ipvlan",
|
||||
},
|
||||
@ -312,15 +319,10 @@ var _ = Describe("ipvlan Operations", func() {
|
||||
MTU: 1500,
|
||||
}
|
||||
|
||||
// Create ipvlan in other namespace
|
||||
targetNs, err := testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer targetNs.Close()
|
||||
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
_, err := createIpvlan(conf, "foobar0", targetNs)
|
||||
_, err := createIpvlan(conf, "foobar0", targetNS)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
return nil
|
||||
})
|
||||
@ -328,7 +330,7 @@ var _ = Describe("ipvlan Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure ipvlan link exists in the target namespace
|
||||
err = targetNs.Do(func(ns.NetNS) error {
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName("foobar0")
|
||||
@ -339,28 +341,26 @@ var _ = Describe("ipvlan Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("configures and deconfigures an iplvan link with ADD/DEL", func() {
|
||||
const IFNAME = "ipvl0"
|
||||
|
||||
It(fmt.Sprintf("[%s] configures and deconfigures an iplvan link with ADD/DEL", ver), func() {
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "ipvlan",
|
||||
"master": "%s",
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": "10.1.2.0/24"
|
||||
"subnet": "10.1.2.0/24",
|
||||
"dataDir": "%s"
|
||||
}
|
||||
}`, MASTER_NAME)
|
||||
}`, ver, MASTER_NAME, dataDir)
|
||||
|
||||
ipvlanAddDelTest(conf, IFNAME, originalNS)
|
||||
ipvlanAddCheckDelTest(conf, "", originalNS, targetNS)
|
||||
})
|
||||
|
||||
It("configures and deconfigures an iplvan link with ADD/DEL when chained", func() {
|
||||
const IFNAME = "ipvl0"
|
||||
|
||||
if testutils.SpecVersionHasChaining(ver) {
|
||||
It(fmt.Sprintf("[%s] configures and deconfigures an iplvan link with ADD/DEL when chained", ver), func() {
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "ipvlan",
|
||||
"prevResult": {
|
||||
@ -379,40 +379,36 @@ var _ = Describe("ipvlan Operations", func() {
|
||||
],
|
||||
"routes": []
|
||||
}
|
||||
}`, MASTER_NAME)
|
||||
}`, ver, MASTER_NAME)
|
||||
|
||||
ipvlanAddDelTest(conf, IFNAME, originalNS)
|
||||
ipvlanAddCheckDelTest(conf, MASTER_NAME, originalNS, targetNS)
|
||||
})
|
||||
}
|
||||
|
||||
It("deconfigures an unconfigured ipvlan link with DEL", func() {
|
||||
const IFNAME = "ipvl0"
|
||||
|
||||
It(fmt.Sprintf("[%s] deconfigures an unconfigured ipvlan link with DEL", ver), func() {
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.3.0",
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "ipvlan",
|
||||
"master": "%s",
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": "10.1.2.0/24"
|
||||
"subnet": "10.1.2.0/24",
|
||||
"dataDir": "%s"
|
||||
}
|
||||
}`, MASTER_NAME)
|
||||
|
||||
targetNs, err := testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer targetNs.Close()
|
||||
}`, ver, MASTER_NAME, dataDir)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNs.Path(),
|
||||
IfName: IFNAME,
|
||||
Netns: targetNS.Path(),
|
||||
IfName: "ipvl0",
|
||||
StdinData: []byte(conf),
|
||||
}
|
||||
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
err = testutils.CmdDelWithArgs(args, func() error {
|
||||
err := testutils.CmdDelWithArgs(args, func() error {
|
||||
return cmdDel(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
@ -421,69 +417,20 @@ var _ = Describe("ipvlan Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("configures and deconfigures a cniVersion 0.4.0 iplvan link with ADD/CHECK/DEL", func() {
|
||||
const IFNAME = "ipvl0"
|
||||
|
||||
It(fmt.Sprintf("[%s] configures and deconfigures a ipvlan link with ADD/DEL, without master config", ver), func() {
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.4.0",
|
||||
"name": "ipvlanTest1",
|
||||
"type": "ipvlan",
|
||||
"master": "%s",
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": "10.1.2.0/24"
|
||||
}
|
||||
}`, MASTER_NAME)
|
||||
|
||||
ipvlanAddCheckDelTest(conf, "ipvlanTest1", IFNAME, originalNS)
|
||||
})
|
||||
|
||||
It("configures and deconfigures a cniVersion 0.4.0 iplvan link with ADD/CHECK/DEL when chained", func() {
|
||||
const IFNAME = "ipvl0"
|
||||
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.4.0",
|
||||
"name": "ipvlanTest2",
|
||||
"type": "ipvlan",
|
||||
"prevResult": {
|
||||
"interfaces": [
|
||||
{
|
||||
"name": "%s"
|
||||
}
|
||||
],
|
||||
"ips": [
|
||||
{
|
||||
"version": "4",
|
||||
"address": "10.1.2.2/24",
|
||||
"gateway": "10.1.2.1",
|
||||
"interface": 0
|
||||
}
|
||||
],
|
||||
"routes": []
|
||||
}
|
||||
}`, MASTER_NAME)
|
||||
|
||||
ipvlanAddCheckDelTest(conf, "ipvlanTest2", IFNAME, originalNS)
|
||||
})
|
||||
|
||||
It("configures and deconfigures a ipvlan link with ADD/DEL, without master config", func() {
|
||||
const IFNAME = "ipvl0"
|
||||
conf := `{
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "ipvlan",
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": "10.1.2.0/24"
|
||||
"subnet": "10.1.2.0/24",
|
||||
"dataDir": "%s"
|
||||
}
|
||||
}`
|
||||
|
||||
targetNs, err := testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer targetNs.Close()
|
||||
}`, ver, dataDir)
|
||||
|
||||
// Make MASTER_NAME as default route interface
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName(MASTER_NAME)
|
||||
@ -509,6 +456,7 @@ var _ = Describe("ipvlan Operations", func() {
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
ipvlanAddDelTest(conf, IFNAME, originalNS)
|
||||
ipvlanAddCheckDelTest(conf, MASTER_NAME, originalNS, targetNS)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
@ -24,7 +24,7 @@ import (
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/cni/pkg/version"
|
||||
|
||||
"github.com/containernetworking/plugins/pkg/ns"
|
||||
@ -109,12 +109,19 @@ func cmdAdd(args *skel.CmdArgs) error {
|
||||
// loopback should pass it transparently
|
||||
result = conf.PrevResult
|
||||
} else {
|
||||
loopbackInterface := ¤t.Interface{Name: args.IfName, Mac: "00:00:00:00:00:00", Sandbox: args.Netns}
|
||||
r := ¤t.Result{CNIVersion: conf.CNIVersion, Interfaces: []*current.Interface{loopbackInterface}}
|
||||
r := ¤t.Result{
|
||||
CNIVersion: conf.CNIVersion,
|
||||
Interfaces: []*current.Interface{
|
||||
¤t.Interface{
|
||||
Name: args.IfName,
|
||||
Mac: "00:00:00:00:00:00",
|
||||
Sandbox: args.Netns,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if v4Addr != nil {
|
||||
r.IPs = append(r.IPs, ¤t.IPConfig{
|
||||
Version: "4",
|
||||
Interface: current.Int(0),
|
||||
Address: *v4Addr,
|
||||
})
|
||||
@ -122,7 +129,6 @@ func cmdAdd(args *skel.CmdArgs) error {
|
||||
|
||||
if v6Addr != nil {
|
||||
r.IPs = append(r.IPs, ¤t.IPConfig{
|
||||
Version: "6",
|
||||
Interface: current.Int(0),
|
||||
Address: *v6Addr,
|
||||
})
|
||||
|
@ -28,6 +28,10 @@ import (
|
||||
"github.com/onsi/gomega/gexec"
|
||||
)
|
||||
|
||||
func generateConfig(cniVersion string) *strings.Reader {
|
||||
return strings.NewReader(fmt.Sprintf(`{ "name": "loopback-test", "cniVersion": "%s" }`, cniVersion))
|
||||
}
|
||||
|
||||
var _ = Describe("Loopback", func() {
|
||||
var (
|
||||
networkNS ns.NetNS
|
||||
@ -49,7 +53,6 @@ var _ = Describe("Loopback", func() {
|
||||
fmt.Sprintf("CNI_ARGS=%s", "none"),
|
||||
fmt.Sprintf("CNI_PATH=%s", "/some/test/path"),
|
||||
}
|
||||
command.Stdin = strings.NewReader(`{ "name": "loopback-test", "cniVersion": "0.1.0" }`)
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
@ -57,8 +60,14 @@ var _ = Describe("Loopback", func() {
|
||||
Expect(testutils.UnmountNS(networkNS)).To(Succeed())
|
||||
})
|
||||
|
||||
for _, ver := range testutils.AllSpecVersions {
|
||||
// Redefine ver inside for scope so real value is picked up by each dynamically defined It()
|
||||
// See Gingkgo's "Patterns for dynamically generating tests" documentation.
|
||||
ver := ver
|
||||
|
||||
Context("when given a network namespace", func() {
|
||||
It("sets the lo device to UP", func() {
|
||||
It(fmt.Sprintf("[%s] sets the lo device to UP", ver), func() {
|
||||
command.Stdin = generateConfig(ver)
|
||||
command.Env = append(environ, fmt.Sprintf("CNI_COMMAND=%s", "ADD"))
|
||||
|
||||
session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
|
||||
@ -78,7 +87,8 @@ var _ = Describe("Loopback", func() {
|
||||
Expect(lo.Flags & net.FlagUp).To(Equal(net.FlagUp))
|
||||
})
|
||||
|
||||
It("sets the lo device to DOWN", func() {
|
||||
It(fmt.Sprintf("[%s] sets the lo device to DOWN", ver), func() {
|
||||
command.Stdin = generateConfig(ver)
|
||||
command.Env = append(environ, fmt.Sprintf("CNI_COMMAND=%s", "DEL"))
|
||||
|
||||
session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
|
||||
@ -98,4 +108,5 @@ var _ = Describe("Loopback", func() {
|
||||
Expect(lo.Flags & net.FlagUp).NotTo(Equal(net.FlagUp))
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
|
@ -26,7 +26,7 @@ import (
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/cni/pkg/version"
|
||||
|
||||
"github.com/containernetworking/plugins/pkg/ip"
|
||||
@ -256,7 +256,10 @@ func cmdAdd(args *skel.CmdArgs) error {
|
||||
}()
|
||||
|
||||
// Assume L2 interface only
|
||||
result := ¤t.Result{CNIVersion: cniVersion, Interfaces: []*current.Interface{macvlanInterface}}
|
||||
result := ¤t.Result{
|
||||
CNIVersion: current.ImplementedSpecVersion,
|
||||
Interfaces: []*current.Interface{macvlanInterface},
|
||||
}
|
||||
|
||||
if isLayer3 {
|
||||
// run the IPAM plugin and get back the config to apply
|
||||
@ -301,7 +304,7 @@ func cmdAdd(args *skel.CmdArgs) error {
|
||||
}
|
||||
|
||||
for _, ipc := range result.IPs {
|
||||
if ipc.Version == "4" {
|
||||
if ipc.Address.IP.To4() != nil {
|
||||
_ = arping.GratuitousArpOverIface(ipc.Address.IP, *contVeth)
|
||||
}
|
||||
}
|
||||
|
@ -17,12 +17,17 @@ package main
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
"github.com/containernetworking/cni/pkg/types/020"
|
||||
"github.com/containernetworking/cni/pkg/types/040"
|
||||
"github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/plugins/pkg/ns"
|
||||
"github.com/containernetworking/plugins/pkg/testutils"
|
||||
|
||||
@ -49,7 +54,7 @@ type Net struct {
|
||||
// A *IPAMArgs `json:"cni"`
|
||||
DNS types.DNS `json:"dns"`
|
||||
RawPrevResult map[string]interface{} `json:"prevResult,omitempty"`
|
||||
PrevResult current.Result `json:"-"`
|
||||
PrevResult types100.Result `json:"-"`
|
||||
}
|
||||
|
||||
func buildOneConfig(netName string, cniVersion string, orig *Net, prevResult types.Result) (*Net, error) {
|
||||
@ -95,14 +100,107 @@ func buildOneConfig(netName string, cniVersion string, orig *Net, prevResult typ
|
||||
|
||||
}
|
||||
|
||||
type tester interface {
|
||||
// verifyResult minimally verifies the Result and returns the interface's MAC address
|
||||
verifyResult(result types.Result, err error, name string, numAddrs int) string
|
||||
}
|
||||
|
||||
type testerBase struct{}
|
||||
|
||||
type testerV10x testerBase
|
||||
type testerV04x testerBase
|
||||
type testerV03x testerBase
|
||||
type testerV01xOr02x testerBase
|
||||
|
||||
func newTesterByVersion(version string) tester {
|
||||
switch {
|
||||
case strings.HasPrefix(version, "1.0."):
|
||||
return &testerV10x{}
|
||||
case strings.HasPrefix(version, "0.4."):
|
||||
return &testerV04x{}
|
||||
case strings.HasPrefix(version, "0.3."):
|
||||
return &testerV03x{}
|
||||
default:
|
||||
return &testerV01xOr02x{}
|
||||
}
|
||||
}
|
||||
|
||||
// verifyResult minimally verifies the Result and returns the interface's MAC address
|
||||
func (t *testerV10x) verifyResult(result types.Result, err error, name string, numAddrs int) string {
|
||||
// Validate error from the CNI ADD
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
r, err := types100.GetResult(result)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(r.Interfaces)).To(Equal(1))
|
||||
Expect(r.Interfaces[0].Name).To(Equal(name))
|
||||
Expect(len(r.IPs)).To(Equal(numAddrs))
|
||||
|
||||
return r.Interfaces[0].Mac
|
||||
}
|
||||
|
||||
func verify0403(result types.Result, err error, name string, numAddrs int) string {
|
||||
// Validate error from the CNI ADD
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
r, err := types040.GetResult(result)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(r.Interfaces)).To(Equal(1))
|
||||
Expect(r.Interfaces[0].Name).To(Equal(name))
|
||||
Expect(len(r.IPs)).To(Equal(numAddrs))
|
||||
|
||||
return r.Interfaces[0].Mac
|
||||
}
|
||||
|
||||
// verifyResult minimally verifies the Result and returns the interface's MAC address
|
||||
func (t *testerV04x) verifyResult(result types.Result, err error, name string, numAddrs int) string {
|
||||
return verify0403(result, err, name, numAddrs)
|
||||
}
|
||||
|
||||
// verifyResult minimally verifies the Result and returns the interface's MAC address
|
||||
func (t *testerV03x) verifyResult(result types.Result, err error, name string, numAddrs int) string {
|
||||
return verify0403(result, err, name, numAddrs)
|
||||
}
|
||||
|
||||
// verifyResult minimally verifies the Result and returns the interface's MAC address
|
||||
func (t *testerV01xOr02x) verifyResult(result types.Result, err error, name string, numAddrs int) string {
|
||||
if result == nil && numAddrs == 0 {
|
||||
Expect(err).To(MatchError("cannot convert: no valid IP addresses"))
|
||||
return ""
|
||||
}
|
||||
|
||||
r, err := types020.GetResult(result)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
var numIPs int
|
||||
if r.IP4 != nil && r.IP4.IP.IP != nil {
|
||||
numIPs++
|
||||
}
|
||||
if r.IP6 != nil && r.IP6.IP.IP != nil {
|
||||
numIPs++
|
||||
}
|
||||
Expect(numIPs).To(Equal(numAddrs))
|
||||
|
||||
// 0.2 and earlier don't return MAC address
|
||||
return ""
|
||||
}
|
||||
|
||||
var _ = Describe("macvlan Operations", func() {
|
||||
var originalNS ns.NetNS
|
||||
var originalNS, targetNS ns.NetNS
|
||||
var dataDir string
|
||||
|
||||
BeforeEach(func() {
|
||||
// Create a new NetNS so we don't modify the host
|
||||
var err error
|
||||
originalNS, err = testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
targetNS, err = testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
dataDir, err = ioutil.TempDir("", "macvlan_test")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
@ -122,14 +220,22 @@ var _ = Describe("macvlan Operations", func() {
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
Expect(os.RemoveAll(dataDir)).To(Succeed())
|
||||
Expect(originalNS.Close()).To(Succeed())
|
||||
Expect(testutils.UnmountNS(originalNS)).To(Succeed())
|
||||
Expect(targetNS.Close()).To(Succeed())
|
||||
Expect(testutils.UnmountNS(targetNS)).To(Succeed())
|
||||
})
|
||||
|
||||
It("creates an macvlan link in a non-default namespace", func() {
|
||||
for _, ver := range testutils.AllSpecVersions {
|
||||
// Redefine ver inside for scope so real value is picked up by each dynamically defined It()
|
||||
// See Gingkgo's "Patterns for dynamically generating tests" documentation.
|
||||
ver := ver
|
||||
|
||||
It(fmt.Sprintf("[%s] creates an macvlan link in a non-default namespace", ver), func() {
|
||||
conf := &NetConf{
|
||||
NetConf: types.NetConf{
|
||||
CNIVersion: "0.3.1",
|
||||
CNIVersion: ver,
|
||||
Name: "testConfig",
|
||||
Type: "macvlan",
|
||||
},
|
||||
@ -138,21 +244,17 @@ var _ = Describe("macvlan Operations", func() {
|
||||
MTU: 1500,
|
||||
}
|
||||
|
||||
targetNs, err := testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer targetNs.Close()
|
||||
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
_, err = createMacvlan(conf, "foobar0", targetNs)
|
||||
_, err := createMacvlan(conf, "foobar0", targetNS)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure macvlan link exists in the target namespace
|
||||
err = targetNs.Do(func(ns.NetNS) error {
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName("foobar0")
|
||||
@ -163,61 +265,55 @@ var _ = Describe("macvlan Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("configures and deconfigures a macvlan link with ADD/DEL", func() {
|
||||
It(fmt.Sprintf("[%s] configures and deconfigures a macvlan link with ADD/DEL", ver), func() {
|
||||
const IFNAME = "macvl0"
|
||||
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "macvlan",
|
||||
"master": "%s",
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": "10.1.2.0/24"
|
||||
"subnet": "10.1.2.0/24",
|
||||
"dataDir": "%s"
|
||||
}
|
||||
}`, MASTER_NAME)
|
||||
|
||||
targetNs, err := testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer targetNs.Close()
|
||||
}`, ver, MASTER_NAME, dataDir)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNs.Path(),
|
||||
Netns: targetNS.Path(),
|
||||
IfName: IFNAME,
|
||||
StdinData: []byte(conf),
|
||||
}
|
||||
|
||||
var result *current.Result
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
var macAddress string
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
r, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||
result, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
result, err = current.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(result.Interfaces)).To(Equal(1))
|
||||
Expect(result.Interfaces[0].Name).To(Equal(IFNAME))
|
||||
Expect(len(result.IPs)).To(Equal(1))
|
||||
t := newTesterByVersion(ver)
|
||||
macAddress = t.verifyResult(result, err, IFNAME, 1)
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure macvlan link exists in the target namespace
|
||||
err = targetNs.Do(func(ns.NetNS) error {
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().Name).To(Equal(IFNAME))
|
||||
|
||||
hwaddr, err := net.ParseMAC(result.Interfaces[0].Mac)
|
||||
if macAddress != "" {
|
||||
hwaddr, err := net.ParseMAC(macAddress)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().HardwareAddr).To(Equal(hwaddr))
|
||||
}
|
||||
|
||||
addrs, err := netlink.AddrList(link, syscall.AF_INET)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
@ -238,7 +334,7 @@ var _ = Describe("macvlan Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure macvlan link has been deleted
|
||||
err = targetNs.Do(func(ns.NetNS) error {
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
@ -249,32 +345,29 @@ var _ = Describe("macvlan Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("deconfigures an unconfigured macvlan link with DEL", func() {
|
||||
It(fmt.Sprintf("[%s] deconfigures an unconfigured macvlan link with DEL", ver), func() {
|
||||
const IFNAME = "macvl0"
|
||||
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.3.0",
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "macvlan",
|
||||
"master": "%s",
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": "10.1.2.0/24"
|
||||
"subnet": "10.1.2.0/24",
|
||||
"dataDir": "%s"
|
||||
}
|
||||
}`, MASTER_NAME)
|
||||
|
||||
targetNs, err := testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer targetNs.Close()
|
||||
}`, ver, MASTER_NAME, dataDir)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNs.Path(),
|
||||
Netns: targetNS.Path(),
|
||||
IfName: IFNAME,
|
||||
StdinData: []byte(conf),
|
||||
}
|
||||
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
err := testutils.CmdDelWithArgs(args, func() error {
|
||||
@ -287,58 +380,51 @@ var _ = Describe("macvlan Operations", func() {
|
||||
|
||||
})
|
||||
|
||||
It("configures and deconfigures a l2 macvlan link with ADD/DEL", func() {
|
||||
It(fmt.Sprintf("[%s] configures and deconfigures a l2 macvlan link with ADD/DEL", ver), func() {
|
||||
const IFNAME = "macvl0"
|
||||
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "macvlan",
|
||||
"master": "%s",
|
||||
"ipam": {}
|
||||
}`, MASTER_NAME)
|
||||
|
||||
targetNs, err := testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer targetNs.Close()
|
||||
}`, ver, MASTER_NAME)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNs.Path(),
|
||||
Netns: targetNS.Path(),
|
||||
IfName: IFNAME,
|
||||
StdinData: []byte(conf),
|
||||
}
|
||||
|
||||
var result *current.Result
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
var macAddress string
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
r, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||
result, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
result, err = current.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(result.Interfaces)).To(Equal(1))
|
||||
Expect(result.Interfaces[0].Name).To(Equal(IFNAME))
|
||||
Expect(len(result.IPs)).To(Equal(0))
|
||||
t := newTesterByVersion(ver)
|
||||
macAddress = t.verifyResult(result, err, IFNAME, 0)
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure macvlan link exists in the target namespace
|
||||
err = targetNs.Do(func(ns.NetNS) error {
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().Name).To(Equal(IFNAME))
|
||||
|
||||
hwaddr, err := net.ParseMAC(result.Interfaces[0].Mac)
|
||||
if macAddress != "" {
|
||||
hwaddr, err := net.ParseMAC(macAddress)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().HardwareAddr).To(Equal(hwaddr))
|
||||
}
|
||||
|
||||
addrs, err := netlink.AddrList(link, syscall.AF_INET)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
@ -359,7 +445,7 @@ var _ = Describe("macvlan Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure macvlan link has been deleted
|
||||
err = targetNs.Do(func(ns.NetNS) error {
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
@ -370,61 +456,60 @@ var _ = Describe("macvlan Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("configures and deconfigures a cniVersion 0.4.0 macvlan link with ADD/DEL", func() {
|
||||
It(fmt.Sprintf("[%s] configures and deconfigures a macvlan link with ADD/CHECK/DEL", ver), func() {
|
||||
const IFNAME = "macvl0"
|
||||
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.4.0",
|
||||
"cniVersion": "%s",
|
||||
"name": "macvlanTestv4",
|
||||
"type": "macvlan",
|
||||
"master": "%s",
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"ranges": [[ {"subnet": "10.1.2.0/24", "gateway": "10.1.2.1"} ]]
|
||||
"ranges": [[ {"subnet": "10.1.2.0/24", "gateway": "10.1.2.1"} ]],
|
||||
"dataDir": "%s"
|
||||
}
|
||||
}`, MASTER_NAME)
|
||||
|
||||
targetNs, err := testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer targetNs.Close()
|
||||
}`, ver, MASTER_NAME, dataDir)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNs.Path(),
|
||||
Netns: targetNS.Path(),
|
||||
IfName: IFNAME,
|
||||
StdinData: []byte(conf),
|
||||
}
|
||||
|
||||
var result *current.Result
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
var (
|
||||
macAddress string
|
||||
t tester
|
||||
result types.Result
|
||||
)
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
r, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||
var err error
|
||||
result, _, err = testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
result, err = current.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(result.Interfaces)).To(Equal(1))
|
||||
Expect(result.Interfaces[0].Name).To(Equal(IFNAME))
|
||||
Expect(len(result.IPs)).To(Equal(1))
|
||||
t = newTesterByVersion(ver)
|
||||
macAddress = t.verifyResult(result, err, IFNAME, 1)
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure macvlan link exists in the target namespace
|
||||
err = targetNs.Do(func(ns.NetNS) error {
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().Name).To(Equal(IFNAME))
|
||||
|
||||
hwaddr, err := net.ParseMAC(result.Interfaces[0].Mac)
|
||||
if macAddress != "" {
|
||||
hwaddr, err := net.ParseMAC(macAddress)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().HardwareAddr).To(Equal(hwaddr))
|
||||
}
|
||||
|
||||
addrs, err := netlink.AddrList(link, syscall.AF_INET)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
@ -440,8 +525,7 @@ var _ = Describe("macvlan Operations", func() {
|
||||
n.IPAM, _, err = allocator.LoadIPAMConfig([]byte(conf), "")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
cniVersion := "0.4.0"
|
||||
newConf, err := buildOneConfig("macvlanTestv4", cniVersion, n, result)
|
||||
newConf, err := buildOneConfig("macvlanTestv4", ver, n, result)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
confString, err := json.Marshal(newConf)
|
||||
@ -453,13 +537,15 @@ var _ = Describe("macvlan Operations", func() {
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
err := testutils.CmdCheckWithArgs(args, func() error {
|
||||
return testutils.CmdCheckWithArgs(args, func() error {
|
||||
return cmdCheck(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
return nil
|
||||
})
|
||||
if testutils.SpecVersionHasCHECK(ver) {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
} else {
|
||||
Expect(err).To(MatchError("config version does not allow CHECK"))
|
||||
}
|
||||
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
@ -473,7 +559,7 @@ var _ = Describe("macvlan Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure macvlan link has been deleted
|
||||
err = targetNs.Do(func(ns.NetNS) error {
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
@ -484,32 +570,29 @@ var _ = Describe("macvlan Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("configures and deconfigures a macvlan link with ADD/DEL, without master config", func() {
|
||||
It(fmt.Sprintf("[%s] configures and deconfigures a macvlan link with ADD/DEL, without master config", ver), func() {
|
||||
const IFNAME = "macvl0"
|
||||
|
||||
conf := `{
|
||||
"cniVersion": "0.3.1",
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "macvlan",
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": "10.1.2.0/24"
|
||||
"subnet": "10.1.2.0/24",
|
||||
"dataDir": "%s"
|
||||
}
|
||||
}`
|
||||
|
||||
targetNs, err := testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer targetNs.Close()
|
||||
}`, ver, dataDir)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNs.Path(),
|
||||
Netns: targetNS.Path(),
|
||||
IfName: IFNAME,
|
||||
StdinData: []byte(conf),
|
||||
}
|
||||
|
||||
// Make MASTER_NAME as default route interface
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName(MASTER_NAME)
|
||||
@ -535,34 +618,33 @@ var _ = Describe("macvlan Operations", func() {
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
var result *current.Result
|
||||
var macAddress string
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
r, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
result, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
result, err = current.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(result.Interfaces)).To(Equal(1))
|
||||
Expect(result.Interfaces[0].Name).To(Equal(IFNAME))
|
||||
Expect(len(result.IPs)).To(Equal(1))
|
||||
t := newTesterByVersion(ver)
|
||||
macAddress = t.verifyResult(result, err, IFNAME, 1)
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure macvlan link exists in the target namespace
|
||||
err = targetNs.Do(func(ns.NetNS) error {
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().Name).To(Equal(IFNAME))
|
||||
|
||||
hwaddr, err := net.ParseMAC(result.Interfaces[0].Mac)
|
||||
if macAddress != "" {
|
||||
hwaddr, err := net.ParseMAC(macAddress)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().HardwareAddr).To(Equal(hwaddr))
|
||||
}
|
||||
|
||||
addrs, err := netlink.AddrList(link, syscall.AF_INET)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
@ -583,7 +665,7 @@ var _ = Describe("macvlan Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure macvlan link has been deleted
|
||||
err = targetNs.Do(func(ns.NetNS) error {
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
@ -594,58 +676,54 @@ var _ = Describe("macvlan Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("configures and deconfigures l2 macvlan link with mac address (from CNI_ARGS) with CNI v4 ADD/DEL", func() {
|
||||
const IFNAME = "macvl0"
|
||||
It(fmt.Sprintf("[%s] configures and deconfigures l2 macvlan link with mac address (from CNI_ARGS) with ADD/DEL", ver), func() {
|
||||
const (
|
||||
IFNAME = "macvl0"
|
||||
EXPECTED_MAC = "c2:11:22:33:44:55"
|
||||
)
|
||||
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "macvlan",
|
||||
"master": "%s",
|
||||
"ipam": {}
|
||||
}`, MASTER_NAME)
|
||||
|
||||
targetNs, err := testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer targetNs.Close()
|
||||
}`, ver, MASTER_NAME)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNs.Path(),
|
||||
Netns: targetNS.Path(),
|
||||
IfName: IFNAME,
|
||||
StdinData: []byte(conf),
|
||||
Args: "IgnoreUnknown=true;MAC=c2:11:22:33:44:55",
|
||||
Args: fmt.Sprintf("IgnoreUnknown=true;MAC=%s", EXPECTED_MAC),
|
||||
}
|
||||
|
||||
var result *current.Result
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
var macAddress string
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
r, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||
result, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
result, err = current.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(result.Interfaces)).To(Equal(1))
|
||||
Expect(result.Interfaces[0].Name).To(Equal(IFNAME))
|
||||
Expect(len(result.IPs)).To(Equal(0))
|
||||
|
||||
t := newTesterByVersion(ver)
|
||||
macAddress = t.verifyResult(result, err, IFNAME, 0)
|
||||
if macAddress != "" {
|
||||
Expect(macAddress).To(Equal(EXPECTED_MAC))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure macvlan link exists in the target namespace
|
||||
err = targetNs.Do(func(ns.NetNS) error {
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().Name).To(Equal(IFNAME))
|
||||
|
||||
hwaddr, err := net.ParseMAC("c2:11:22:33:44:55")
|
||||
hwaddr, err := net.ParseMAC(EXPECTED_MAC)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().HardwareAddr).To(Equal(hwaddr))
|
||||
|
||||
@ -668,7 +746,7 @@ var _ = Describe("macvlan Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure macvlan link has been deleted
|
||||
err = targetNs.Do(func(ns.NetNS) error {
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
@ -679,11 +757,14 @@ var _ = Describe("macvlan Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("configures and deconfigures l2 macvlan link with mac address (from RuntimeConfig) with ADD/DEL", func() {
|
||||
const IFNAME = "macvl0"
|
||||
It(fmt.Sprintf("[%s] configures and deconfigures l2 macvlan link with mac address (from RuntimeConfig) with ADD/DEL", ver), func() {
|
||||
const (
|
||||
IFNAME = "macvl0"
|
||||
EXPECTED_MAC = "c2:11:22:33:44:55"
|
||||
)
|
||||
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"capabilities": {"mac": true},
|
||||
"RuntimeConfig": {
|
||||
"mac": "c2:11:22:33:44:55"
|
||||
@ -692,48 +773,41 @@ var _ = Describe("macvlan Operations", func() {
|
||||
"type": "macvlan",
|
||||
"master": "%s",
|
||||
"ipam": {}
|
||||
}`, MASTER_NAME)
|
||||
|
||||
targetNs, err := testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer targetNs.Close()
|
||||
}`, ver, MASTER_NAME)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNs.Path(),
|
||||
Netns: targetNS.Path(),
|
||||
IfName: IFNAME,
|
||||
StdinData: []byte(conf),
|
||||
}
|
||||
|
||||
var result *current.Result
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
var macAddress string
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
r, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||
result, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
result, err = current.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(result.Interfaces)).To(Equal(1))
|
||||
Expect(result.Interfaces[0].Name).To(Equal(IFNAME))
|
||||
Expect(len(result.IPs)).To(Equal(0))
|
||||
|
||||
t := newTesterByVersion(ver)
|
||||
macAddress = t.verifyResult(result, err, IFNAME, 0)
|
||||
if macAddress != "" {
|
||||
Expect(macAddress).To(Equal(EXPECTED_MAC))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure macvlan link exists in the target namespace
|
||||
err = targetNs.Do(func(ns.NetNS) error {
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().Name).To(Equal(IFNAME))
|
||||
|
||||
hwaddr, err := net.ParseMAC("c2:11:22:33:44:55")
|
||||
hwaddr, err := net.ParseMAC(EXPECTED_MAC)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().HardwareAddr).To(Equal(hwaddr))
|
||||
|
||||
@ -756,7 +830,7 @@ var _ = Describe("macvlan Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure macvlan link has been deleted
|
||||
err = targetNs.Do(func(ns.NetNS) error {
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
@ -766,4 +840,5 @@ var _ = Describe("macvlan Operations", func() {
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
}
|
||||
})
|
||||
|
@ -27,7 +27,7 @@ import (
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/cni/pkg/version"
|
||||
|
||||
"github.com/containernetworking/plugins/pkg/ip"
|
||||
@ -108,7 +108,7 @@ func setupContainerVeth(netns ns.NetNS, ifName string, mtu int, pr *current.Resu
|
||||
}
|
||||
|
||||
addrBits := 32
|
||||
if ipc.Version == "6" {
|
||||
if ipc.Address.IP.To4() == nil {
|
||||
addrBits = 128
|
||||
}
|
||||
|
||||
@ -141,7 +141,7 @@ func setupContainerVeth(netns ns.NetNS, ifName string, mtu int, pr *current.Resu
|
||||
|
||||
// Send a gratuitous arp for all v4 addresses
|
||||
for _, ipc := range pr.IPs {
|
||||
if ipc.Version == "4" {
|
||||
if ipc.Address.IP.To4() != nil {
|
||||
_ = arping.GratuitousArpOverIface(ipc.Address.IP, *contVeth)
|
||||
}
|
||||
}
|
||||
|
@ -17,11 +17,15 @@ package main
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
"github.com/containernetworking/cni/pkg/types/020"
|
||||
"github.com/containernetworking/cni/pkg/types/040"
|
||||
"github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/plugins/pkg/ns"
|
||||
"github.com/containernetworking/plugins/pkg/testutils"
|
||||
|
||||
@ -41,7 +45,7 @@ type Net struct {
|
||||
IPAM *allocator.IPAMConfig `json:"ipam"`
|
||||
DNS types.DNS `json:"dns"`
|
||||
RawPrevResult map[string]interface{} `json:"prevResult,omitempty"`
|
||||
PrevResult current.Result `json:"-"`
|
||||
PrevResult types100.Result `json:"-"`
|
||||
}
|
||||
|
||||
func buildOneConfig(netName string, cniVersion string, orig *Net, prevResult types.Result) (*Net, error) {
|
||||
@ -87,43 +91,166 @@ func buildOneConfig(netName string, cniVersion string, orig *Net, prevResult typ
|
||||
|
||||
}
|
||||
|
||||
type tester interface {
|
||||
// verifyResult minimally verifies the Result and returns the interface's IP addresses and MAC address
|
||||
verifyResult(result types.Result, expectedIfName, expectedSandbox string, expectedDNS types.DNS) ([]resultIP, string)
|
||||
}
|
||||
|
||||
type testerBase struct{}
|
||||
|
||||
type testerV10x testerBase
|
||||
type testerV04x testerBase
|
||||
type testerV03x testerBase
|
||||
type testerV01xOr02x testerBase
|
||||
|
||||
func newTesterByVersion(version string) tester {
|
||||
switch {
|
||||
case strings.HasPrefix(version, "1.0."):
|
||||
return &testerV10x{}
|
||||
case strings.HasPrefix(version, "0.4."):
|
||||
return &testerV04x{}
|
||||
case strings.HasPrefix(version, "0.3."):
|
||||
return &testerV03x{}
|
||||
default:
|
||||
return &testerV01xOr02x{}
|
||||
}
|
||||
}
|
||||
|
||||
type resultIP struct {
|
||||
ip string
|
||||
gw string
|
||||
}
|
||||
|
||||
// verifyResult minimally verifies the Result and returns the interface's IP addresses and MAC address
|
||||
func (t *testerV10x) verifyResult(result types.Result, expectedIfName, expectedSandbox string, expectedDNS types.DNS) ([]resultIP, string) {
|
||||
r, err := types100.GetResult(result)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(r.Interfaces).To(HaveLen(2))
|
||||
Expect(r.Interfaces[0].Name).To(HavePrefix("veth"))
|
||||
Expect(r.Interfaces[0].Mac).To(HaveLen(17))
|
||||
Expect(r.Interfaces[0].Sandbox).To(BeEmpty())
|
||||
Expect(r.Interfaces[1].Name).To(Equal(expectedIfName))
|
||||
Expect(r.Interfaces[1].Sandbox).To(Equal(expectedSandbox))
|
||||
|
||||
Expect(r.DNS).To(Equal(expectedDNS))
|
||||
|
||||
// Grab IPs from container interface
|
||||
ips := []resultIP{}
|
||||
for _, ipc := range r.IPs {
|
||||
if *ipc.Interface == 1 {
|
||||
ips = append(ips, resultIP{
|
||||
ip: ipc.Address.IP.String(),
|
||||
gw: ipc.Gateway.String(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return ips, r.Interfaces[1].Mac
|
||||
}
|
||||
|
||||
func verify0403(result types.Result, expectedIfName, expectedSandbox string, expectedDNS types.DNS) ([]resultIP, string) {
|
||||
r, err := types040.GetResult(result)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(r.Interfaces).To(HaveLen(2))
|
||||
Expect(r.Interfaces[0].Name).To(HavePrefix("veth"))
|
||||
Expect(r.Interfaces[0].Mac).To(HaveLen(17))
|
||||
Expect(r.Interfaces[0].Sandbox).To(BeEmpty())
|
||||
Expect(r.Interfaces[1].Name).To(Equal(expectedIfName))
|
||||
Expect(r.Interfaces[1].Sandbox).To(Equal(expectedSandbox))
|
||||
|
||||
Expect(r.DNS).To(Equal(expectedDNS))
|
||||
|
||||
// Grab IPs from container interface
|
||||
ips := []resultIP{}
|
||||
for _, ipc := range r.IPs {
|
||||
if *ipc.Interface == 1 {
|
||||
ips = append(ips, resultIP{
|
||||
ip: ipc.Address.IP.String(),
|
||||
gw: ipc.Gateway.String(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return ips, r.Interfaces[1].Mac
|
||||
}
|
||||
|
||||
// verifyResult minimally verifies the Result and returns the interface's IP addresses and MAC address
|
||||
func (t *testerV04x) verifyResult(result types.Result, expectedIfName, expectedSandbox string, expectedDNS types.DNS) ([]resultIP, string) {
|
||||
return verify0403(result, expectedIfName, expectedSandbox, expectedDNS)
|
||||
}
|
||||
|
||||
// verifyResult minimally verifies the Result and returns the interface's IP addresses and MAC address
|
||||
func (t *testerV03x) verifyResult(result types.Result, expectedIfName, expectedSandbox string, expectedDNS types.DNS) ([]resultIP, string) {
|
||||
return verify0403(result, expectedIfName, expectedSandbox, expectedDNS)
|
||||
}
|
||||
|
||||
// verifyResult minimally verifies the Result and returns the interface's IP addresses and MAC address
|
||||
func (t *testerV01xOr02x) verifyResult(result types.Result, expectedIfName, expectedSandbox string, expectedDNS types.DNS) ([]resultIP, string) {
|
||||
r, err := types020.GetResult(result)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
ips := []resultIP{}
|
||||
if r.IP4 != nil && r.IP4.IP.IP != nil {
|
||||
ips = append(ips, resultIP{
|
||||
ip: r.IP4.IP.IP.String(),
|
||||
gw: r.IP4.Gateway.String(),
|
||||
})
|
||||
}
|
||||
if r.IP6 != nil && r.IP6.IP.IP != nil {
|
||||
ips = append(ips, resultIP{
|
||||
ip: r.IP6.IP.IP.String(),
|
||||
gw: r.IP6.Gateway.String(),
|
||||
})
|
||||
}
|
||||
|
||||
// 0.2 and earlier don't return MAC address
|
||||
return ips, ""
|
||||
}
|
||||
|
||||
var _ = Describe("ptp Operations", func() {
|
||||
var originalNS ns.NetNS
|
||||
var originalNS, targetNS ns.NetNS
|
||||
var dataDir string
|
||||
|
||||
BeforeEach(func() {
|
||||
// Create a new NetNS so we don't modify the host
|
||||
var err error
|
||||
originalNS, err = testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
targetNS, err = testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
dataDir, err = ioutil.TempDir("", "ptp_test")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
Expect(os.RemoveAll(dataDir)).To(Succeed())
|
||||
Expect(originalNS.Close()).To(Succeed())
|
||||
Expect(testutils.UnmountNS(originalNS)).To(Succeed())
|
||||
Expect(targetNS.Close()).To(Succeed())
|
||||
Expect(testutils.UnmountNS(targetNS)).To(Succeed())
|
||||
})
|
||||
|
||||
doTest := func(conf string, numIPs int, expectedDNSConf types.DNS) {
|
||||
doTest := func(conf, cniVersion string, numIPs int, expectedDNSConf types.DNS, targetNS ns.NetNS) {
|
||||
const IFNAME = "ptp0"
|
||||
|
||||
targetNs, err := testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer targetNs.Close()
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNs.Path(),
|
||||
Netns: targetNS.Path(),
|
||||
IfName: IFNAME,
|
||||
StdinData: []byte(conf),
|
||||
}
|
||||
|
||||
var resI types.Result
|
||||
var res *current.Result
|
||||
var result types.Result
|
||||
|
||||
// Execute the plugin with the ADD command, creating the veth endpoints
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
resI, _, err = testutils.CmdAddWithArgs(args, func() error {
|
||||
var err error
|
||||
result, _, err = testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
@ -131,32 +258,25 @@ var _ = Describe("ptp Operations", func() {
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
res, err = current.NewResultFromResult(resI)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
t := newTesterByVersion(cniVersion)
|
||||
ips, mac := t.verifyResult(result, IFNAME, targetNS.Path(), expectedDNSConf)
|
||||
Expect(len(ips)).To(Equal(numIPs))
|
||||
|
||||
// Make sure ptp link exists in the target namespace
|
||||
// Then, ping the gateway
|
||||
seenIPs := 0
|
||||
|
||||
wantMac := ""
|
||||
err = targetNs.Do(func(ns.NetNS) error {
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
wantMac = link.Attrs().HardwareAddr.String()
|
||||
|
||||
for _, ipc := range res.IPs {
|
||||
if *ipc.Interface != 1 {
|
||||
continue
|
||||
if mac != "" {
|
||||
Expect(mac).To(Equal(link.Attrs().HardwareAddr.String()))
|
||||
}
|
||||
seenIPs += 1
|
||||
saddr := ipc.Address.IP.String()
|
||||
daddr := ipc.Gateway.String()
|
||||
fmt.Fprintln(GinkgoWriter, "ping", saddr, "->", daddr)
|
||||
|
||||
if err := testutils.Ping(saddr, daddr, (ipc.Version == "6"), 30); err != nil {
|
||||
return fmt.Errorf("ping %s -> %s failed: %s", saddr, daddr, err)
|
||||
for _, ipc := range ips {
|
||||
fmt.Fprintln(GinkgoWriter, "ping", ipc.ip, "->", ipc.gw)
|
||||
if err := testutils.Ping(ipc.ip, ipc.gw, 30); err != nil {
|
||||
return fmt.Errorf("ping %s -> %s failed: %s", ipc.ip, ipc.gw, err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -164,121 +284,6 @@ var _ = Describe("ptp Operations", func() {
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(seenIPs).To(Equal(numIPs))
|
||||
|
||||
// make sure the interfaces are correct
|
||||
Expect(res.Interfaces).To(HaveLen(2))
|
||||
|
||||
Expect(res.Interfaces[0].Name).To(HavePrefix("veth"))
|
||||
Expect(res.Interfaces[0].Mac).To(HaveLen(17))
|
||||
Expect(res.Interfaces[0].Sandbox).To(BeEmpty())
|
||||
|
||||
Expect(res.Interfaces[1].Name).To(Equal(IFNAME))
|
||||
Expect(res.Interfaces[1].Mac).To(Equal(wantMac))
|
||||
Expect(res.Interfaces[1].Sandbox).To(Equal(targetNs.Path()))
|
||||
|
||||
// make sure DNS is correct
|
||||
Expect(res.DNS).To(Equal(expectedDNSConf))
|
||||
|
||||
// Call the plugins with the DEL command, deleting the veth endpoints
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
err := testutils.CmdDelWithArgs(args, func() error {
|
||||
return cmdDel(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure ptp link has been deleted
|
||||
err = targetNs.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(link).To(BeNil())
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
|
||||
doTestv4 := func(conf string, netName string, numIPs int) {
|
||||
const IFNAME = "ptp0"
|
||||
|
||||
targetNs, err := testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer targetNs.Close()
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNs.Path(),
|
||||
IfName: IFNAME,
|
||||
StdinData: []byte(conf),
|
||||
}
|
||||
|
||||
var resI types.Result
|
||||
var res *current.Result
|
||||
|
||||
// Execute the plugin with the ADD command, creating the veth endpoints
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
resI, _, err = testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
res, err = current.NewResultFromResult(resI)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure ptp link exists in the target namespace
|
||||
// Then, ping the gateway
|
||||
seenIPs := 0
|
||||
|
||||
wantMac := ""
|
||||
err = targetNs.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
wantMac = link.Attrs().HardwareAddr.String()
|
||||
|
||||
for _, ipc := range res.IPs {
|
||||
if *ipc.Interface != 1 {
|
||||
continue
|
||||
}
|
||||
seenIPs += 1
|
||||
saddr := ipc.Address.IP.String()
|
||||
daddr := ipc.Gateway.String()
|
||||
fmt.Fprintln(GinkgoWriter, "ping", saddr, "->", daddr)
|
||||
|
||||
if err := testutils.Ping(saddr, daddr, (ipc.Version == "6"), 30); err != nil {
|
||||
return fmt.Errorf("ping %s -> %s failed: %s", saddr, daddr, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(seenIPs).To(Equal(numIPs))
|
||||
|
||||
// make sure the interfaces are correct
|
||||
Expect(res.Interfaces).To(HaveLen(2))
|
||||
|
||||
Expect(res.Interfaces[0].Name).To(HavePrefix("veth"))
|
||||
Expect(res.Interfaces[0].Mac).To(HaveLen(17))
|
||||
Expect(res.Interfaces[0].Sandbox).To(BeEmpty())
|
||||
|
||||
Expect(res.Interfaces[1].Name).To(Equal(IFNAME))
|
||||
Expect(res.Interfaces[1].Mac).To(Equal(wantMac))
|
||||
Expect(res.Interfaces[1].Sandbox).To(Equal(targetNs.Path()))
|
||||
|
||||
// call CmdCheck
|
||||
n := &Net{}
|
||||
err = json.Unmarshal([]byte(conf), &n)
|
||||
@ -287,8 +292,7 @@ var _ = Describe("ptp Operations", func() {
|
||||
n.IPAM, _, err = allocator.LoadIPAMConfig([]byte(conf), "")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
cniVersion := "0.4.0"
|
||||
newConf, err := buildOneConfig(netName, cniVersion, n, res)
|
||||
newConf, err := buildOneConfig(n.Name, cniVersion, n, result)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
confString, err := json.Marshal(newConf)
|
||||
@ -299,11 +303,13 @@ var _ = Describe("ptp Operations", func() {
|
||||
// CNI Check host-device in the target namespace
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
var err error
|
||||
err = testutils.CmdCheckWithArgs(args, func() error { return cmdCheck(args) })
|
||||
return err
|
||||
return testutils.CmdCheckWithArgs(args, func() error { return cmdCheck(args) })
|
||||
})
|
||||
if testutils.SpecVersionHasCHECK(cniVersion) {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
} else {
|
||||
Expect(err).To(MatchError("config version does not allow CHECK"))
|
||||
}
|
||||
|
||||
args.StdinData = []byte(conf)
|
||||
|
||||
@ -320,7 +326,7 @@ var _ = Describe("ptp Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure ptp link has been deleted
|
||||
err = targetNs.Do(func(ns.NetNS) error {
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
@ -331,7 +337,12 @@ var _ = Describe("ptp Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
|
||||
It("configures and deconfigures a ptp link with ADD/DEL", func() {
|
||||
for _, ver := range testutils.AllSpecVersions {
|
||||
// Redefine ver inside for scope so real value is picked up by each dynamically defined It()
|
||||
// See Gingkgo's "Patterns for dynamically generating tests" documentation.
|
||||
ver := ver
|
||||
|
||||
It(fmt.Sprintf("[%s] configures and deconfigures a ptp link with ADD/DEL", ver), func() {
|
||||
dnsConf := types.DNS{
|
||||
Nameservers: []string{"10.1.2.123"},
|
||||
Domain: "some.domain.test",
|
||||
@ -342,24 +353,25 @@ var _ = Describe("ptp Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "ptp",
|
||||
"ipMasq": true,
|
||||
"mtu": 5000,
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": "10.1.2.0/24"
|
||||
"subnet": "10.1.2.0/24",
|
||||
"dataDir": "%s"
|
||||
},
|
||||
"dns": %s
|
||||
}`, string(dnsConfBytes))
|
||||
}`, ver, dataDir, string(dnsConfBytes))
|
||||
|
||||
doTest(conf, 1, dnsConf)
|
||||
doTest(conf, ver, 1, dnsConf, targetNS)
|
||||
})
|
||||
|
||||
It("configures and deconfigures a dual-stack ptp link with ADD/DEL", func() {
|
||||
conf := `{
|
||||
"cniVersion": "0.3.1",
|
||||
It(fmt.Sprintf("[%s] configures and deconfigures a dual-stack ptp link with ADD/DEL", ver), func() {
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "ptp",
|
||||
"ipMasq": true,
|
||||
@ -369,14 +381,15 @@ var _ = Describe("ptp Operations", func() {
|
||||
"ranges": [
|
||||
[{ "subnet": "10.1.2.0/24"}],
|
||||
[{ "subnet": "2001:db8:1::0/66"}]
|
||||
]
|
||||
],
|
||||
"dataDir": "%s"
|
||||
}
|
||||
}`
|
||||
}`, ver, dataDir)
|
||||
|
||||
doTest(conf, 2, types.DNS{})
|
||||
doTest(conf, ver, 2, types.DNS{}, targetNS)
|
||||
})
|
||||
|
||||
It("does not override IPAM DNS settings if no DNS settings provided", func() {
|
||||
It(fmt.Sprintf("[%s] does not override IPAM DNS settings if no DNS settings provided", ver), func() {
|
||||
ipamDNSConf := types.DNS{
|
||||
Nameservers: []string{"10.1.2.123"},
|
||||
Domain: "some.domain.test",
|
||||
@ -388,7 +401,7 @@ var _ = Describe("ptp Operations", func() {
|
||||
defer os.RemoveAll(resolvConfPath)
|
||||
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "ptp",
|
||||
"ipMasq": true,
|
||||
@ -396,14 +409,15 @@ var _ = Describe("ptp Operations", func() {
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": "10.1.2.0/24",
|
||||
"resolvConf": "%s"
|
||||
"resolvConf": "%s",
|
||||
"dataDir": "%s"
|
||||
}
|
||||
}`, resolvConfPath)
|
||||
}`, ver, resolvConfPath, dataDir)
|
||||
|
||||
doTest(conf, 1, ipamDNSConf)
|
||||
doTest(conf, ver, 1, ipamDNSConf, targetNS)
|
||||
})
|
||||
|
||||
It("overrides IPAM DNS settings if any DNS settings provided", func() {
|
||||
It(fmt.Sprintf("[%s] overrides IPAM DNS settings if any DNS settings provided", ver), func() {
|
||||
ipamDNSConf := types.DNS{
|
||||
Nameservers: []string{"10.1.2.123"},
|
||||
Domain: "some.domain.test",
|
||||
@ -432,7 +446,7 @@ var _ = Describe("ptp Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "ptp",
|
||||
"ipMasq": true,
|
||||
@ -440,16 +454,17 @@ var _ = Describe("ptp Operations", func() {
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": "10.1.2.0/24",
|
||||
"resolvConf": "%s"
|
||||
"resolvConf": "%s",
|
||||
"dataDir": "%s"
|
||||
},
|
||||
"dns": %s
|
||||
}`, resolvConfPath, string(dnsConfBytes))
|
||||
}`, ver, resolvConfPath, dataDir, string(dnsConfBytes))
|
||||
|
||||
doTest(conf, 1, ptpDNSConf)
|
||||
doTest(conf, ver, 1, ptpDNSConf, targetNS)
|
||||
}
|
||||
})
|
||||
|
||||
It("overrides IPAM DNS settings if any empty list DNS settings provided", func() {
|
||||
It(fmt.Sprintf("[%s] overrides IPAM DNS settings if any empty list DNS settings provided", ver), func() {
|
||||
ipamDNSConf := types.DNS{
|
||||
Nameservers: []string{"10.1.2.123"},
|
||||
Domain: "some.domain.test",
|
||||
@ -461,7 +476,7 @@ var _ = Describe("ptp Operations", func() {
|
||||
defer os.RemoveAll(resolvConfPath)
|
||||
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "ptp",
|
||||
"ipMasq": true,
|
||||
@ -469,6 +484,7 @@ var _ = Describe("ptp Operations", func() {
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": "10.1.2.0/24",
|
||||
"dataDir": "%s",
|
||||
"resolvConf": "%s"
|
||||
},
|
||||
"dns": {
|
||||
@ -476,39 +492,36 @@ var _ = Describe("ptp Operations", func() {
|
||||
"search": [],
|
||||
"options": []
|
||||
}
|
||||
}`, resolvConfPath)
|
||||
}`, ver, dataDir, resolvConfPath)
|
||||
|
||||
doTest(conf, 1, types.DNS{})
|
||||
doTest(conf, ver, 1, types.DNS{}, targetNS)
|
||||
})
|
||||
|
||||
It("deconfigures an unconfigured ptp link with DEL", func() {
|
||||
It(fmt.Sprintf("[%s] deconfigures an unconfigured ptp link with DEL", ver), func() {
|
||||
const IFNAME = "ptp0"
|
||||
|
||||
conf := `{
|
||||
"cniVersion": "0.3.0",
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "ptp",
|
||||
"ipMasq": true,
|
||||
"mtu": 5000,
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"dataDir": "%s",
|
||||
"subnet": "10.1.2.0/24"
|
||||
}
|
||||
}`
|
||||
|
||||
targetNs, err := testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer targetNs.Close()
|
||||
}`, ver, dataDir)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNs.Path(),
|
||||
Netns: targetNS.Path(),
|
||||
IfName: IFNAME,
|
||||
StdinData: []byte(conf),
|
||||
}
|
||||
|
||||
// Call the plugins with the DEL command. It should not error even though the veth doesn't exist.
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
err := testutils.CmdDelWithArgs(args, func() error {
|
||||
@ -519,39 +532,5 @@ var _ = Describe("ptp Operations", func() {
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("configures and deconfigures a CNI V4 ptp link with ADD/DEL", func() {
|
||||
conf := `{
|
||||
"cniVersion": "0.4.0",
|
||||
"name": "ptpNetv4",
|
||||
"type": "ptp",
|
||||
"ipMasq": true,
|
||||
"mtu": 5000,
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": "10.1.2.0/24"
|
||||
}
|
||||
}`
|
||||
|
||||
doTestv4(conf, "ptpNetv4", 1)
|
||||
})
|
||||
|
||||
It("configures and deconfigures a CNI V4 dual-stack ptp link with ADD/DEL", func() {
|
||||
conf := `{
|
||||
"cniVersion": "0.4.0",
|
||||
"name": "ptpNetv4ds",
|
||||
"type": "ptp",
|
||||
"ipMasq": true,
|
||||
"mtu": 5000,
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"ranges": [
|
||||
[{ "subnet": "10.1.2.0/24"}],
|
||||
[{ "subnet": "2001:db8:1::0/66"}]
|
||||
]
|
||||
}
|
||||
}`
|
||||
|
||||
doTestv4(conf, "ptpNetv4ds", 2)
|
||||
})
|
||||
})
|
||||
|
@ -24,7 +24,7 @@ import (
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/cni/pkg/version"
|
||||
|
||||
"github.com/containernetworking/plugins/pkg/ip"
|
||||
|
@ -17,12 +17,17 @@ package main
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
"github.com/containernetworking/cni/pkg/types/020"
|
||||
"github.com/containernetworking/cni/pkg/types/040"
|
||||
"github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/plugins/pkg/ns"
|
||||
"github.com/containernetworking/plugins/pkg/testutils"
|
||||
|
||||
@ -45,7 +50,7 @@ type Net struct {
|
||||
IPAM *allocator.IPAMConfig `json:"ipam"`
|
||||
DNS types.DNS `json:"dns"`
|
||||
RawPrevResult map[string]interface{} `json:"prevResult,omitempty"`
|
||||
PrevResult current.Result `json:"-"`
|
||||
PrevResult types100.Result `json:"-"`
|
||||
}
|
||||
|
||||
func buildOneConfig(netName string, cniVersion string, orig *Net, prevResult types.Result) (*Net, error) {
|
||||
@ -91,14 +96,90 @@ func buildOneConfig(netName string, cniVersion string, orig *Net, prevResult typ
|
||||
|
||||
}
|
||||
|
||||
type tester interface {
|
||||
// verifyResult minimally verifies the Result and returns the interface's MAC address
|
||||
verifyResult(result types.Result, name string) string
|
||||
}
|
||||
|
||||
type testerBase struct{}
|
||||
|
||||
type testerV10x testerBase
|
||||
type testerV04x testerBase
|
||||
type testerV03x testerBase
|
||||
type testerV01xOr02x testerBase
|
||||
|
||||
func newTesterByVersion(version string) tester {
|
||||
switch {
|
||||
case strings.HasPrefix(version, "1.0."):
|
||||
return &testerV10x{}
|
||||
case strings.HasPrefix(version, "0.4."):
|
||||
return &testerV04x{}
|
||||
case strings.HasPrefix(version, "0.3."):
|
||||
return &testerV03x{}
|
||||
default:
|
||||
return &testerV01xOr02x{}
|
||||
}
|
||||
}
|
||||
|
||||
// verifyResult minimally verifies the Result and returns the interface's MAC address
|
||||
func (t *testerV10x) verifyResult(result types.Result, name string) string {
|
||||
r, err := types100.GetResult(result)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(r.Interfaces)).To(Equal(1))
|
||||
Expect(r.Interfaces[0].Name).To(Equal(name))
|
||||
Expect(len(r.IPs)).To(Equal(1))
|
||||
|
||||
return r.Interfaces[0].Mac
|
||||
}
|
||||
|
||||
func verify0403(result types.Result, name string) string {
|
||||
r, err := types040.GetResult(result)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(r.Interfaces)).To(Equal(1))
|
||||
Expect(r.Interfaces[0].Name).To(Equal(name))
|
||||
Expect(len(r.IPs)).To(Equal(1))
|
||||
|
||||
return r.Interfaces[0].Mac
|
||||
}
|
||||
|
||||
// verifyResult minimally verifies the Result and returns the interface's MAC address
|
||||
func (t *testerV04x) verifyResult(result types.Result, name string) string {
|
||||
return verify0403(result, name)
|
||||
}
|
||||
|
||||
// verifyResult minimally verifies the Result and returns the interface's MAC address
|
||||
func (t *testerV03x) verifyResult(result types.Result, name string) string {
|
||||
return verify0403(result, name)
|
||||
}
|
||||
|
||||
// verifyResult minimally verifies the Result and returns the interface's MAC address
|
||||
func (t *testerV01xOr02x) verifyResult(result types.Result, name string) string {
|
||||
r, err := types020.GetResult(result)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(r.IP4.IP.IP).NotTo(BeNil())
|
||||
Expect(r.IP6).To(BeNil())
|
||||
|
||||
// 0.2 and earlier don't return MAC address
|
||||
return ""
|
||||
}
|
||||
|
||||
var _ = Describe("vlan Operations", func() {
|
||||
var originalNS ns.NetNS
|
||||
var originalNS, targetNS ns.NetNS
|
||||
var dataDir string
|
||||
|
||||
BeforeEach(func() {
|
||||
// Create a new NetNS so we don't modify the host
|
||||
var err error
|
||||
originalNS, err = testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
targetNS, err = testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
dataDir, err = ioutil.TempDir("", "vlan_test")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
@ -120,14 +201,22 @@ var _ = Describe("vlan Operations", func() {
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
Expect(os.RemoveAll(dataDir)).To(Succeed())
|
||||
Expect(originalNS.Close()).To(Succeed())
|
||||
Expect(testutils.UnmountNS(originalNS)).To(Succeed())
|
||||
Expect(targetNS.Close()).To(Succeed())
|
||||
Expect(testutils.UnmountNS(targetNS)).To(Succeed())
|
||||
})
|
||||
|
||||
It("creates an vlan link in a non-default namespace with given MTU", func() {
|
||||
for _, ver := range testutils.AllSpecVersions {
|
||||
// Redefine ver inside for scope so real value is picked up by each dynamically defined It()
|
||||
// See Gingkgo's "Patterns for dynamically generating tests" documentation.
|
||||
ver := ver
|
||||
|
||||
It(fmt.Sprintf("[%s] creates an vlan link in a non-default namespace with given MTU", ver), func() {
|
||||
conf := &NetConf{
|
||||
NetConf: types.NetConf{
|
||||
CNIVersion: "0.3.0",
|
||||
CNIVersion: ver,
|
||||
Name: "testConfig",
|
||||
Type: "vlan",
|
||||
},
|
||||
@ -137,22 +226,17 @@ var _ = Describe("vlan Operations", func() {
|
||||
}
|
||||
|
||||
// Create vlan in other namespace
|
||||
targetNs, err := testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer targetNs.Close()
|
||||
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
_, err := createVlan(conf, "foobar0", targetNs)
|
||||
_, err := createVlan(conf, "foobar0", targetNS)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
return nil
|
||||
})
|
||||
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure vlan link exists in the target namespace
|
||||
err = targetNs.Do(func(ns.NetNS) error {
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName("foobar0")
|
||||
@ -164,10 +248,10 @@ var _ = Describe("vlan Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("creates an vlan link in a non-default namespace with master's MTU", func() {
|
||||
It(fmt.Sprintf("[%s] creates an vlan link in a non-default namespace with master's MTU", ver), func() {
|
||||
conf := &NetConf{
|
||||
NetConf: types.NetConf{
|
||||
CNIVersion: "0.3.0",
|
||||
CNIVersion: ver,
|
||||
Name: "testConfig",
|
||||
Type: "vlan",
|
||||
},
|
||||
@ -176,11 +260,7 @@ var _ = Describe("vlan Operations", func() {
|
||||
}
|
||||
|
||||
// Create vlan in other namespace
|
||||
targetNs, err := testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer targetNs.Close()
|
||||
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
m, err := netlink.LinkByName(MASTER_NAME)
|
||||
@ -188,15 +268,14 @@ var _ = Describe("vlan Operations", func() {
|
||||
err = netlink.LinkSetMTU(m, 1200)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
_, err = createVlan(conf, "foobar0", targetNs)
|
||||
_, err = createVlan(conf, "foobar0", targetNS)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
return nil
|
||||
})
|
||||
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure vlan link exists in the target namespace
|
||||
err = targetNs.Do(func(ns.NetNS) error {
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName("foobar0")
|
||||
@ -208,61 +287,60 @@ var _ = Describe("vlan Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("configures and deconfigures an vlan link with ADD/DEL", func() {
|
||||
It(fmt.Sprintf("[%s] configures and deconfigures a vlan link with ADD/CHECK/DEL", ver), func() {
|
||||
const IFNAME = "eth0"
|
||||
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.3.0",
|
||||
"name": "mynet",
|
||||
"cniVersion": "%s",
|
||||
"name": "vlanTestv4",
|
||||
"type": "vlan",
|
||||
"master": "%s",
|
||||
"vlanId": 1234,
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": "10.1.2.0/24"
|
||||
"subnet": "10.1.2.0/24",
|
||||
"dataDir": "%s"
|
||||
}
|
||||
}`, MASTER_NAME)
|
||||
|
||||
targetNs, err := testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer targetNs.Close()
|
||||
}`, ver, MASTER_NAME, dataDir)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNs.Path(),
|
||||
Netns: targetNS.Path(),
|
||||
IfName: IFNAME,
|
||||
StdinData: []byte(conf),
|
||||
}
|
||||
|
||||
var result *current.Result
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
t := newTesterByVersion(ver)
|
||||
|
||||
var result types.Result
|
||||
var macAddress string
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
r, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||
var err error
|
||||
result, _, err = testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
result, err = current.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(result.Interfaces)).To(Equal(1))
|
||||
Expect(result.Interfaces[0].Name).To(Equal(IFNAME))
|
||||
Expect(len(result.IPs)).To(Equal(1))
|
||||
macAddress = t.verifyResult(result, IFNAME)
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure vlan link exists in the target namespace
|
||||
err = targetNs.Do(func(ns.NetNS) error {
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().Name).To(Equal(IFNAME))
|
||||
|
||||
hwaddr, err := net.ParseMAC(result.Interfaces[0].Mac)
|
||||
if macAddress != "" {
|
||||
hwaddr, err := net.ParseMAC(macAddress)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().HardwareAddr).To(Equal(hwaddr))
|
||||
}
|
||||
|
||||
addrs, err := netlink.AddrList(link, syscall.AF_INET)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
@ -271,6 +349,35 @@ var _ = Describe("vlan Operations", func() {
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// call CmdCheck
|
||||
n := &Net{}
|
||||
err = json.Unmarshal([]byte(conf), &n)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
n.IPAM, _, err = allocator.LoadIPAMConfig([]byte(conf), "")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
newConf, err := buildOneConfig("vlanTestv4", ver, n, result)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
confString, err := json.Marshal(newConf)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
args.StdinData = confString
|
||||
|
||||
// CNI Check host-device in the target namespace
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
return testutils.CmdCheckWithArgs(args, func() error { return cmdCheck(args) })
|
||||
})
|
||||
if testutils.SpecVersionHasCHECK(ver) {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
} else {
|
||||
Expect(err).To(MatchError("config version does not allow CHECK"))
|
||||
}
|
||||
|
||||
args.StdinData = []byte(conf)
|
||||
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
@ -283,7 +390,7 @@ var _ = Describe("vlan Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure vlan link has been deleted
|
||||
err = targetNs.Do(func(ns.NetNS) error {
|
||||
err = targetNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
@ -307,133 +414,20 @@ var _ = Describe("vlan Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("configures and deconfigures an CNI V4 vlan link with ADD/CHECK/DEL", func() {
|
||||
const IFNAME = "eth0"
|
||||
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "0.4.0",
|
||||
"name": "vlanTestv4",
|
||||
"type": "vlan",
|
||||
"master": "%s",
|
||||
"vlanId": 1234,
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": "10.1.2.0/24"
|
||||
}
|
||||
}`, MASTER_NAME)
|
||||
|
||||
targetNs, err := testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer targetNs.Close()
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNs.Path(),
|
||||
IfName: IFNAME,
|
||||
StdinData: []byte(conf),
|
||||
}
|
||||
|
||||
var result *current.Result
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
r, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
result, err = current.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(result.Interfaces)).To(Equal(1))
|
||||
Expect(result.Interfaces[0].Name).To(Equal(IFNAME))
|
||||
Expect(len(result.IPs)).To(Equal(1))
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure vlan link exists in the target namespace
|
||||
err = targetNs.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().Name).To(Equal(IFNAME))
|
||||
|
||||
hwaddr, err := net.ParseMAC(result.Interfaces[0].Mac)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().HardwareAddr).To(Equal(hwaddr))
|
||||
|
||||
addrs, err := netlink.AddrList(link, syscall.AF_INET)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(len(addrs)).To(Equal(1))
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// call CmdCheck
|
||||
n := &Net{}
|
||||
err = json.Unmarshal([]byte(conf), &n)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
n.IPAM, _, err = allocator.LoadIPAMConfig([]byte(conf), "")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
cniVersion := "0.4.0"
|
||||
newConf, err := buildOneConfig("vlanTestv4", cniVersion, n, result)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
confString, err := json.Marshal(newConf)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
args.StdinData = confString
|
||||
|
||||
// CNI Check host-device in the target namespace
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
var err error
|
||||
err = testutils.CmdCheckWithArgs(args, func() error { return cmdCheck(args) })
|
||||
return err
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
args.StdinData = []byte(conf)
|
||||
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
err = testutils.CmdDelWithArgs(args, func() error {
|
||||
return cmdDel(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Make sure vlan link has been deleted
|
||||
err = targetNs.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(link).To(BeNil())
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
Describe("fails to create vlan link with invalid MTU", func() {
|
||||
conf := `{
|
||||
"cniVersion": "0.3.1",
|
||||
const confFmt = `{
|
||||
"cniVersion": "%s",
|
||||
"name": "mynet",
|
||||
"type": "vlan",
|
||||
"master": "%s",
|
||||
"mtu": %d,
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": "10.1.2.0/24"
|
||||
"subnet": "10.1.2.0/24",
|
||||
"dataDir": "%s"
|
||||
}
|
||||
}`
|
||||
}`
|
||||
|
||||
BeforeEach(func() {
|
||||
var err error
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
@ -450,14 +444,14 @@ var _ = Describe("vlan Operations", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("fails to create vlan link with greater MTU than master interface", func() {
|
||||
It(fmt.Sprintf("[%s] fails to create vlan link with greater MTU than master interface", ver), func() {
|
||||
var err error
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: "/var/run/netns/test",
|
||||
IfName: "eth0",
|
||||
StdinData: []byte(fmt.Sprintf(conf, MASTER_NAME, 1600)),
|
||||
StdinData: []byte(fmt.Sprintf(confFmt, ver, MASTER_NAME, 1600, dataDir)),
|
||||
}
|
||||
|
||||
_ = originalNS.Do(func(netNS ns.NetNS) error {
|
||||
@ -471,14 +465,14 @@ var _ = Describe("vlan Operations", func() {
|
||||
})
|
||||
})
|
||||
|
||||
It("fails to create vlan link with negative MTU", func() {
|
||||
It(fmt.Sprintf("[%s] fails to create vlan link with negative MTU", ver), func() {
|
||||
var err error
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: "/var/run/netns/test",
|
||||
IfName: "eth0",
|
||||
StdinData: []byte(fmt.Sprintf(conf, MASTER_NAME, -100)),
|
||||
StdinData: []byte(fmt.Sprintf(confFmt, ver, MASTER_NAME, -100, dataDir)),
|
||||
}
|
||||
|
||||
_ = originalNS.Do(func(netNS ns.NetNS) error {
|
||||
@ -492,4 +486,5 @@ var _ = Describe("vlan Operations", func() {
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
|
@ -25,7 +25,7 @@ import (
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/cni/pkg/version"
|
||||
|
||||
"github.com/containernetworking/plugins/pkg/errors"
|
||||
|
@ -24,7 +24,7 @@ import (
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/cni/pkg/version"
|
||||
|
||||
"github.com/containernetworking/plugins/pkg/errors"
|
||||
|
@ -18,7 +18,9 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/vishvananda/netlink"
|
||||
@ -26,7 +28,7 @@ import (
|
||||
"github.com/containernetworking/cni/pkg/invoke"
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
"github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/plugins/pkg/ns"
|
||||
"github.com/containernetworking/plugins/pkg/testutils"
|
||||
|
||||
@ -44,7 +46,9 @@ func buildOneConfig(name, cniVersion string, orig *PluginConf, prevResult types.
|
||||
}
|
||||
// Add previous plugin result
|
||||
if prevResult != nil {
|
||||
inject["prevResult"] = prevResult
|
||||
r, err := prevResult.GetAsVersion(cniVersion)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
inject["prevResult"] = r
|
||||
}
|
||||
|
||||
// Ensure every config uses the same name and version
|
||||
@ -107,18 +111,27 @@ var _ = Describe("bandwidth test", func() {
|
||||
hostIfaceMTU = 1024
|
||||
ifbDeviceName = "bwpa8eda89404b7"
|
||||
|
||||
createVeth(hostNs.Path(), hostIfname, containerNs.Path(), containerIfname, hostIP, containerIP, hostIfaceMTU)
|
||||
createVeth(hostNs, hostIfname, containerNs, containerIfname, hostIP, containerIP, hostIfaceMTU)
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
containerNs.Close()
|
||||
hostNs.Close()
|
||||
Expect(containerNs.Close()).To(Succeed())
|
||||
Expect(testutils.UnmountNS(containerNs)).To(Succeed())
|
||||
Expect(hostNs.Close()).To(Succeed())
|
||||
Expect(testutils.UnmountNS(hostNs)).To(Succeed())
|
||||
})
|
||||
|
||||
// Bandwidth requires host-side interface info, and thus only
|
||||
// supports 0.3.0 and later CNI versions
|
||||
for _, ver := range []string{"0.3.0", "0.3.1", "0.4.0", "1.0.0"} {
|
||||
// Redefine ver inside for scope so real value is picked up by each dynamically defined It()
|
||||
// See Gingkgo's "Patterns for dynamically generating tests" documentation.
|
||||
ver := ver
|
||||
|
||||
Describe("cmdADD", func() {
|
||||
It("Works with a Veth pair using 0.3.0 config", func() {
|
||||
conf := `{
|
||||
"cniVersion": "0.3.0",
|
||||
It(fmt.Sprintf("[%s] works with a Veth pair", ver), func() {
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"name": "cni-plugin-bandwidth-test",
|
||||
"type": "bandwidth",
|
||||
"ingressRate": 8,
|
||||
@ -146,9 +159,8 @@ var _ = Describe("bandwidth test", func() {
|
||||
],
|
||||
"routes": []
|
||||
}
|
||||
}`
|
||||
}`, ver, hostIfname, containerIfname, containerNs.Path(), containerIP.String())
|
||||
|
||||
conf = fmt.Sprintf(conf, hostIfname, containerIfname, containerNs.Path(), containerIP.String())
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: containerNs.Path(),
|
||||
@ -160,7 +172,7 @@ var _ = Describe("bandwidth test", func() {
|
||||
defer GinkgoRecover()
|
||||
r, out, err := testutils.CmdAdd(containerNs.Path(), args.ContainerID, "", []byte(conf), func() error { return cmdAdd(args) })
|
||||
Expect(err).NotTo(HaveOccurred(), string(out))
|
||||
result, err := current.GetResult(r)
|
||||
result, err := types100.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(result.Interfaces).To(HaveLen(3))
|
||||
@ -213,9 +225,9 @@ var _ = Describe("bandwidth test", func() {
|
||||
|
||||
})
|
||||
|
||||
It("Does not apply ingress when disabled", func() {
|
||||
conf := `{
|
||||
"cniVersion": "0.3.0",
|
||||
It(fmt.Sprintf("[%s] does not apply ingress when disabled", ver), func() {
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"name": "cni-plugin-bandwidth-test",
|
||||
"type": "bandwidth",
|
||||
"ingressRate": 0,
|
||||
@ -243,9 +255,8 @@ var _ = Describe("bandwidth test", func() {
|
||||
],
|
||||
"routes": []
|
||||
}
|
||||
}`
|
||||
}`, ver, hostIfname, containerIfname, containerNs.Path(), containerIP.String())
|
||||
|
||||
conf = fmt.Sprintf(conf, hostIfname, containerIfname, containerNs.Path(), containerIP.String())
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: containerNs.Path(),
|
||||
@ -282,9 +293,9 @@ var _ = Describe("bandwidth test", func() {
|
||||
|
||||
})
|
||||
|
||||
It("Does not apply egress when disabled", func() {
|
||||
conf := `{
|
||||
"cniVersion": "0.3.0",
|
||||
It(fmt.Sprintf("[%s] does not apply egress when disabled", ver), func() {
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"name": "cni-plugin-bandwidth-test",
|
||||
"type": "bandwidth",
|
||||
"egressRate": 0,
|
||||
@ -312,9 +323,8 @@ var _ = Describe("bandwidth test", func() {
|
||||
],
|
||||
"routes": []
|
||||
}
|
||||
}`
|
||||
}`, ver, hostIfname, containerIfname, containerNs.Path(), containerIP.String())
|
||||
|
||||
conf = fmt.Sprintf(conf, hostIfname, containerIfname, containerNs.Path(), containerIP.String())
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: containerNs.Path(),
|
||||
@ -353,9 +363,9 @@ var _ = Describe("bandwidth test", func() {
|
||||
|
||||
})
|
||||
|
||||
It("fails an invalid ingress config", func() {
|
||||
conf := `{
|
||||
"cniVersion": "0.3.0",
|
||||
It(fmt.Sprintf("[%s] fails an invalid ingress config", ver), func() {
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"name": "cni-plugin-bandwidth-test",
|
||||
"type": "bandwidth",
|
||||
"ingressRate": 0,
|
||||
@ -383,9 +393,7 @@ var _ = Describe("bandwidth test", func() {
|
||||
],
|
||||
"routes": []
|
||||
}
|
||||
}`
|
||||
|
||||
conf = fmt.Sprintf(conf, hostIfname, containerIfname, containerNs.Path(), containerIP.String())
|
||||
}`, ver, hostIfname, containerIfname, containerNs.Path(), containerIP.String())
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
@ -403,9 +411,9 @@ var _ = Describe("bandwidth test", func() {
|
||||
})).To(Succeed())
|
||||
})
|
||||
|
||||
It("Works with a Veth pair using runtime config", func() {
|
||||
conf := `{
|
||||
"cniVersion": "0.3.0",
|
||||
It(fmt.Sprintf("[%s] works with a Veth pair using runtime config", ver), func() {
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"name": "cni-plugin-bandwidth-test",
|
||||
"type": "bandwidth",
|
||||
"runtimeConfig": {
|
||||
@ -437,9 +445,8 @@ var _ = Describe("bandwidth test", func() {
|
||||
],
|
||||
"routes": []
|
||||
}
|
||||
}`
|
||||
}`, ver, hostIfname, containerIfname, containerNs.Path(), containerIP.String())
|
||||
|
||||
conf = fmt.Sprintf(conf, hostIfname, containerIfname, containerNs.Path(), containerIP.String())
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: containerNs.Path(),
|
||||
@ -451,7 +458,7 @@ var _ = Describe("bandwidth test", func() {
|
||||
defer GinkgoRecover()
|
||||
r, out, err := testutils.CmdAdd(containerNs.Path(), args.ContainerID, "", []byte(conf), func() error { return cmdAdd(args) })
|
||||
Expect(err).NotTo(HaveOccurred(), string(out))
|
||||
result, err := current.GetResult(r)
|
||||
result, err := types100.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(result.Interfaces).To(HaveLen(3))
|
||||
@ -504,9 +511,9 @@ var _ = Describe("bandwidth test", func() {
|
||||
|
||||
})
|
||||
|
||||
It("Should apply static config when both static config and runtime config exist", func() {
|
||||
conf := `{
|
||||
"cniVersion": "0.3.0",
|
||||
It(fmt.Sprintf("[%s] should apply static config when both static config and runtime config exist", ver), func() {
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"name": "cni-plugin-bandwidth-test",
|
||||
"type": "bandwidth",
|
||||
"ingressRate": 0,
|
||||
@ -542,9 +549,7 @@ var _ = Describe("bandwidth test", func() {
|
||||
],
|
||||
"routes": []
|
||||
}
|
||||
}`
|
||||
|
||||
conf = fmt.Sprintf(conf, hostIfname, containerIfname, containerNs.Path(), containerIP.String())
|
||||
}`, ver, hostIfname, containerIfname, containerNs.Path(), containerIP.String())
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
@ -564,9 +569,9 @@ var _ = Describe("bandwidth test", func() {
|
||||
})
|
||||
|
||||
Describe("cmdDEL", func() {
|
||||
It("Works with a Veth pair using 0.3.0 config", func() {
|
||||
conf := `{
|
||||
"cniVersion": "0.3.0",
|
||||
It(fmt.Sprintf("[%s] works with a Veth pair using 0.3.0 config", ver), func() {
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"name": "cni-plugin-bandwidth-test",
|
||||
"type": "bandwidth",
|
||||
"ingressRate": 8,
|
||||
@ -594,9 +599,8 @@ var _ = Describe("bandwidth test", func() {
|
||||
],
|
||||
"routes": []
|
||||
}
|
||||
}`
|
||||
}`, ver, hostIfname, containerIfname, containerNs.Path(), containerIP.String())
|
||||
|
||||
conf = fmt.Sprintf(conf, hostIfname, containerIfname, containerNs.Path(), containerIP.String())
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: containerNs.Path(),
|
||||
@ -621,25 +625,14 @@ var _ = Describe("bandwidth test", func() {
|
||||
})
|
||||
})
|
||||
|
||||
Describe("Validating input", func() {
|
||||
It("Should allow only 4GB burst rate", func() {
|
||||
err := validateRateAndBurst(5000, 4*1024*1024*1024*8-16) // 2 bytes less than the max should pass
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
err = validateRateAndBurst(5000, 4*1024*1024*1024*8) // we're 1 bit above MaxUint32
|
||||
Expect(err).To(HaveOccurred())
|
||||
err = validateRateAndBurst(0, 1)
|
||||
Expect(err).To(HaveOccurred())
|
||||
err = validateRateAndBurst(1, 0)
|
||||
Expect(err).To(HaveOccurred())
|
||||
err = validateRateAndBurst(0, 0)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
})
|
||||
|
||||
Describe("Getting the host interface which plugin should work on from veth peer of container interface", func() {
|
||||
It("Should work with multiple host veth interfaces", func() {
|
||||
conf := `{
|
||||
"cniVersion": "0.4.0",
|
||||
It(fmt.Sprintf("[%s] should work with multiple host veth interfaces", ver), func() {
|
||||
// create veth peer in host ns
|
||||
vethName, peerName := "host-veth-peer1", "host-veth-peer2"
|
||||
createVethInOneNs(hostNs, vethName, peerName)
|
||||
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"name": "cni-plugin-bandwidth-test",
|
||||
"type": "bandwidth",
|
||||
"ingressRate": 8,
|
||||
@ -675,13 +668,8 @@ var _ = Describe("bandwidth test", func() {
|
||||
],
|
||||
"routes": []
|
||||
}
|
||||
}`
|
||||
}`, ver, vethName, peerName, hostIfname, containerIfname, containerNs.Path(), containerIP.String())
|
||||
|
||||
// create veth peer in host ns
|
||||
vethName, peerName := "host-veth-peer1", "host-veth-peer2"
|
||||
createVethInOneNs(hostNs.Path(), vethName, peerName)
|
||||
|
||||
conf = fmt.Sprintf(conf, vethName, peerName, hostIfname, containerIfname, containerNs.Path(), containerIP.String())
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: containerNs.Path(),
|
||||
@ -693,7 +681,7 @@ var _ = Describe("bandwidth test", func() {
|
||||
defer GinkgoRecover()
|
||||
r, out, err := testutils.CmdAdd(containerNs.Path(), args.ContainerID, "", []byte(conf), func() error { return cmdAdd(args) })
|
||||
Expect(err).NotTo(HaveOccurred(), string(out))
|
||||
result, err := current.GetResult(r)
|
||||
result, err := types100.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(result.Interfaces).To(HaveLen(5))
|
||||
@ -746,9 +734,13 @@ var _ = Describe("bandwidth test", func() {
|
||||
|
||||
})
|
||||
|
||||
It("Should fail when container interface has no veth peer", func() {
|
||||
conf := `{
|
||||
"cniVersion": "0.4.0",
|
||||
It(fmt.Sprintf("[%s] should fail when container interface has no veth peer", ver), func() {
|
||||
// create a macvlan device to be container interface
|
||||
macvlanContainerIfname := "container-macv"
|
||||
createMacvlan(containerNs, containerIfname, macvlanContainerIfname)
|
||||
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"name": "cni-plugin-bandwidth-test",
|
||||
"type": "bandwidth",
|
||||
"ingressRate": 8,
|
||||
@ -776,13 +768,8 @@ var _ = Describe("bandwidth test", func() {
|
||||
],
|
||||
"routes": []
|
||||
}
|
||||
}`
|
||||
}`, ver, hostIfname, macvlanContainerIfname, containerNs.Path(), containerIP.String())
|
||||
|
||||
// create a macvlan device to be container interface
|
||||
macvlanContainerIfname := "container-macv"
|
||||
createMacvlan(containerNs.Path(), containerIfname, macvlanContainerIfname)
|
||||
|
||||
conf = fmt.Sprintf(conf, hostIfname, macvlanContainerIfname, containerNs.Path(), containerIP.String())
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: containerNs.Path(),
|
||||
@ -800,9 +787,9 @@ var _ = Describe("bandwidth test", func() {
|
||||
})).To(Succeed())
|
||||
})
|
||||
|
||||
It("Should fail when preResult has no interfaces", func() {
|
||||
conf := `{
|
||||
"cniVersion": "0.4.0",
|
||||
It(fmt.Sprintf("[%s] should fail when preResult has no interfaces", ver), func() {
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"name": "cni-plugin-bandwidth-test",
|
||||
"type": "bandwidth",
|
||||
"ingressRate": 8,
|
||||
@ -814,7 +801,7 @@ var _ = Describe("bandwidth test", func() {
|
||||
"ips": [],
|
||||
"routes": []
|
||||
}
|
||||
}`
|
||||
}`, ver)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
@ -833,9 +820,12 @@ var _ = Describe("bandwidth test", func() {
|
||||
})).To(Succeed())
|
||||
})
|
||||
|
||||
It("Should fail when veth peer of container interface does not match any of host interfaces in preResult", func() {
|
||||
conf := `{
|
||||
"cniVersion": "0.4.0",
|
||||
It(fmt.Sprintf("[%s] should fail when veth peer of container interface does not match any of host interfaces in preResult", ver), func() {
|
||||
// fake a non-exist host interface name
|
||||
fakeHostIfname := fmt.Sprintf("%s-fake", hostIfname)
|
||||
|
||||
conf := fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"name": "cni-plugin-bandwidth-test",
|
||||
"type": "bandwidth",
|
||||
"ingressRate": 8,
|
||||
@ -863,12 +853,8 @@ var _ = Describe("bandwidth test", func() {
|
||||
],
|
||||
"routes": []
|
||||
}
|
||||
}`
|
||||
}`, ver, fakeHostIfname, containerIfname, containerNs.Path(), containerIP.String())
|
||||
|
||||
// fake a non-exist host interface name
|
||||
fakeHostIfname := fmt.Sprintf("%s-fake", hostIfname)
|
||||
|
||||
conf = fmt.Sprintf(conf, fakeHostIfname, containerIfname, containerNs.Path(), containerIP.String())
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: containerNs.Path(),
|
||||
@ -887,7 +873,7 @@ var _ = Describe("bandwidth test", func() {
|
||||
})
|
||||
})
|
||||
|
||||
Context("when chaining bandwidth plugin with PTP using 0.3.0 config", func() {
|
||||
Context(fmt.Sprintf("[%s] when chaining bandwidth plugin with PTP", ver), func() {
|
||||
var ptpConf string
|
||||
var rateInBits uint64
|
||||
var burstInBits uint64
|
||||
@ -901,6 +887,7 @@ var _ = Describe("bandwidth test", func() {
|
||||
var containerWithoutTbfRes types.Result
|
||||
var echoServerWithTbf *gexec.Session
|
||||
var echoServerWithoutTbf *gexec.Session
|
||||
var dataDir string
|
||||
|
||||
BeforeEach(func() {
|
||||
rateInBytes := 1000
|
||||
@ -908,169 +895,28 @@ var _ = Describe("bandwidth test", func() {
|
||||
burstInBits = rateInBits * 2
|
||||
packetInBytes = rateInBytes * 25
|
||||
|
||||
ptpConf = `{
|
||||
"cniVersion": "0.3.0",
|
||||
"name": "mynet",
|
||||
"type": "ptp",
|
||||
"ipMasq": true,
|
||||
"mtu": 512,
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": "10.1.2.0/24"
|
||||
}
|
||||
}`
|
||||
|
||||
containerWithTbfIFName := "ptp0"
|
||||
containerWithoutTbfIFName := "ptp1"
|
||||
|
||||
var err error
|
||||
containerWithTbfNS, err = testutils.NewNS()
|
||||
dataDir, err = ioutil.TempDir("", "bandwidth_linux_test")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
containerWithoutTbfNS, err = testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
By("create two containers, and use the bandwidth plugin on one of them")
|
||||
Expect(hostNs.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
containerWithTbfRes, _, err = testutils.CmdAdd(containerWithTbfNS.Path(), "dummy", containerWithTbfIFName, []byte(ptpConf), func() error {
|
||||
r, err := invoke.DelegateAdd(context.TODO(), "ptp", []byte(ptpConf), nil)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(r.Print()).To(Succeed())
|
||||
|
||||
return err
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
containerWithoutTbfRes, _, err = testutils.CmdAdd(containerWithoutTbfNS.Path(), "dummy2", containerWithoutTbfIFName, []byte(ptpConf), func() error {
|
||||
r, err := invoke.DelegateAdd(context.TODO(), "ptp", []byte(ptpConf), nil)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(r.Print()).To(Succeed())
|
||||
|
||||
return err
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
containerWithTbfResult, err := current.GetResult(containerWithTbfRes)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
tbfPluginConf := PluginConf{}
|
||||
tbfPluginConf.RuntimeConfig.Bandwidth = &BandwidthEntry{
|
||||
IngressBurst: burstInBits,
|
||||
IngressRate: rateInBits,
|
||||
EgressBurst: burstInBits,
|
||||
EgressRate: rateInBits,
|
||||
}
|
||||
tbfPluginConf.Name = "mynet"
|
||||
tbfPluginConf.CNIVersion = "0.3.0"
|
||||
tbfPluginConf.Type = "bandwidth"
|
||||
tbfPluginConf.RawPrevResult = map[string]interface{}{
|
||||
"ips": containerWithTbfResult.IPs,
|
||||
"interfaces": containerWithTbfResult.Interfaces,
|
||||
}
|
||||
|
||||
tbfPluginConf.PrevResult = ¤t.Result{
|
||||
IPs: containerWithTbfResult.IPs,
|
||||
Interfaces: containerWithTbfResult.Interfaces,
|
||||
}
|
||||
conf, err := json.Marshal(tbfPluginConf)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy3",
|
||||
Netns: containerWithTbfNS.Path(),
|
||||
IfName: containerWithTbfIFName,
|
||||
StdinData: []byte(conf),
|
||||
}
|
||||
|
||||
_, out, err := testutils.CmdAdd(containerWithTbfNS.Path(), args.ContainerID, "", []byte(conf), func() error { return cmdAdd(args) })
|
||||
Expect(err).NotTo(HaveOccurred(), string(out))
|
||||
|
||||
return nil
|
||||
})).To(Succeed())
|
||||
|
||||
By("starting a tcp server on both containers")
|
||||
portServerWithTbf, echoServerWithTbf, err = startEchoServerInNamespace(containerWithTbfNS)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
portServerWithoutTbf, echoServerWithoutTbf, err = startEchoServerInNamespace(containerWithoutTbfNS)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
containerWithTbfNS.Close()
|
||||
containerWithoutTbfNS.Close()
|
||||
if echoServerWithoutTbf != nil {
|
||||
echoServerWithoutTbf.Kill()
|
||||
}
|
||||
if echoServerWithTbf != nil {
|
||||
echoServerWithTbf.Kill()
|
||||
}
|
||||
})
|
||||
|
||||
Measure("limits ingress traffic on veth device", func(b Benchmarker) {
|
||||
var runtimeWithLimit time.Duration
|
||||
var runtimeWithoutLimit time.Duration
|
||||
|
||||
By("gather timing statistics about both containers")
|
||||
By("sending tcp traffic to the container that has traffic shaped", func() {
|
||||
runtimeWithLimit = b.Time("with tbf", func() {
|
||||
result, err := current.GetResult(containerWithTbfRes)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
makeTcpClientInNS(hostNs.Path(), result.IPs[0].Address.IP.String(), portServerWithTbf, packetInBytes)
|
||||
})
|
||||
})
|
||||
|
||||
By("sending tcp traffic to the container that does not have traffic shaped", func() {
|
||||
runtimeWithoutLimit = b.Time("without tbf", func() {
|
||||
result, err := current.GetResult(containerWithoutTbfRes)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
makeTcpClientInNS(hostNs.Path(), result.IPs[0].Address.IP.String(), portServerWithoutTbf, packetInBytes)
|
||||
})
|
||||
})
|
||||
|
||||
Expect(runtimeWithLimit).To(BeNumerically(">", runtimeWithoutLimit+1000*time.Millisecond))
|
||||
}, 1)
|
||||
})
|
||||
|
||||
Context("when chaining bandwidth plugin with PTP using 0.4.0 config", func() {
|
||||
var ptpConf string
|
||||
var rateInBits uint64
|
||||
var burstInBits uint64
|
||||
var packetInBytes int
|
||||
var containerWithoutTbfNS ns.NetNS
|
||||
var containerWithTbfNS ns.NetNS
|
||||
var portServerWithTbf int
|
||||
var portServerWithoutTbf int
|
||||
|
||||
var containerWithTbfRes types.Result
|
||||
var containerWithoutTbfRes types.Result
|
||||
var echoServerWithTbf *gexec.Session
|
||||
var echoServerWithoutTbf *gexec.Session
|
||||
|
||||
BeforeEach(func() {
|
||||
rateInBytes := 1000
|
||||
rateInBits = uint64(rateInBytes * 8)
|
||||
burstInBits = rateInBits * 2
|
||||
packetInBytes = rateInBytes * 25
|
||||
|
||||
ptpConf = `{
|
||||
"cniVersion": "0.4.0",
|
||||
ptpConf = fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"name": "myBWnet",
|
||||
"type": "ptp",
|
||||
"ipMasq": true,
|
||||
"mtu": 512,
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": "10.1.2.0/24"
|
||||
"subnet": "10.1.2.0/24",
|
||||
"dataDir": "%s"
|
||||
}
|
||||
}`
|
||||
}`, ver, dataDir)
|
||||
|
||||
containerWithTbfIFName := "ptp0"
|
||||
containerWithoutTbfIFName := "ptp1"
|
||||
const (
|
||||
containerWithTbfIFName = "ptp0"
|
||||
containerWithoutTbfIFName = "ptp1"
|
||||
)
|
||||
|
||||
var err error
|
||||
containerWithTbfNS, err = testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
@ -1099,7 +945,7 @@ var _ = Describe("bandwidth test", func() {
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
containerWithTbfResult, err := current.GetResult(containerWithTbfRes)
|
||||
containerWithTbfResult, err := types100.GetResult(containerWithTbfRes)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
tbfPluginConf := &PluginConf{}
|
||||
@ -1113,8 +959,7 @@ var _ = Describe("bandwidth test", func() {
|
||||
EgressRate: rateInBits,
|
||||
}
|
||||
tbfPluginConf.Type = "bandwidth"
|
||||
cniVersion := "0.4.0"
|
||||
_, newConfBytes, err := buildOneConfig("myBWnet", cniVersion, tbfPluginConf, containerWithTbfResult)
|
||||
_, newConfBytes, err := buildOneConfig("myBWnet", ver, tbfPluginConf, containerWithTbfResult)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
@ -1127,6 +972,7 @@ var _ = Describe("bandwidth test", func() {
|
||||
result, out, err := testutils.CmdAdd(containerWithTbfNS.Path(), args.ContainerID, "", newConfBytes, func() error { return cmdAdd(args) })
|
||||
Expect(err).NotTo(HaveOccurred(), string(out))
|
||||
|
||||
if testutils.SpecVersionHasCHECK(ver) {
|
||||
// Do CNI Check
|
||||
checkConf := &PluginConf{}
|
||||
err = json.Unmarshal([]byte(ptpConf), &checkConf)
|
||||
@ -1140,7 +986,7 @@ var _ = Describe("bandwidth test", func() {
|
||||
}
|
||||
checkConf.Type = "bandwidth"
|
||||
|
||||
_, newCheckBytes, err := buildOneConfig("myBWnet", cniVersion, checkConf, result)
|
||||
_, newCheckBytes, err := buildOneConfig("myBWnet", ver, checkConf, result)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
args = &skel.CmdArgs{
|
||||
@ -1152,6 +998,7 @@ var _ = Describe("bandwidth test", func() {
|
||||
|
||||
err = testutils.CmdCheck(containerWithTbfNS.Path(), args.ContainerID, "", newCheckBytes, func() error { return cmdCheck(args) })
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
|
||||
return nil
|
||||
})).To(Succeed())
|
||||
@ -1164,8 +1011,13 @@ var _ = Describe("bandwidth test", func() {
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
containerWithTbfNS.Close()
|
||||
containerWithoutTbfNS.Close()
|
||||
Expect(os.RemoveAll(dataDir)).To(Succeed())
|
||||
|
||||
Expect(containerWithTbfNS.Close()).To(Succeed())
|
||||
Expect(testutils.UnmountNS(containerWithTbfNS)).To(Succeed())
|
||||
Expect(containerWithoutTbfNS.Close()).To(Succeed())
|
||||
Expect(testutils.UnmountNS(containerWithoutTbfNS)).To(Succeed())
|
||||
|
||||
if echoServerWithoutTbf != nil {
|
||||
echoServerWithoutTbf.Kill()
|
||||
}
|
||||
@ -1181,7 +1033,7 @@ var _ = Describe("bandwidth test", func() {
|
||||
By("gather timing statistics about both containers")
|
||||
By("sending tcp traffic to the container that has traffic shaped", func() {
|
||||
runtimeWithLimit = b.Time("with tbf", func() {
|
||||
result, err := current.GetResult(containerWithTbfRes)
|
||||
result, err := types100.GetResult(containerWithTbfRes)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
makeTcpClientInNS(hostNs.Path(), result.IPs[0].Address.IP.String(), portServerWithTbf, packetInBytes)
|
||||
@ -1190,7 +1042,7 @@ var _ = Describe("bandwidth test", func() {
|
||||
|
||||
By("sending tcp traffic to the container that does not have traffic shaped", func() {
|
||||
runtimeWithoutLimit = b.Time("without tbf", func() {
|
||||
result, err := current.GetResult(containerWithoutTbfRes)
|
||||
result, err := types100.GetResult(containerWithoutTbfRes)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
makeTcpClientInNS(hostNs.Path(), result.IPs[0].Address.IP.String(), portServerWithoutTbf, packetInBytes)
|
||||
@ -1200,5 +1052,20 @@ var _ = Describe("bandwidth test", func() {
|
||||
Expect(runtimeWithLimit).To(BeNumerically(">", runtimeWithoutLimit+1000*time.Millisecond))
|
||||
}, 1)
|
||||
})
|
||||
}
|
||||
|
||||
Describe("Validating input", func() {
|
||||
It("Should allow only 4GB burst rate", func() {
|
||||
err := validateRateAndBurst(5000, 4*1024*1024*1024*8-16) // 2 bytes less than the max should pass
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
err = validateRateAndBurst(5000, 4*1024*1024*1024*8) // we're 1 bit above MaxUint32
|
||||
Expect(err).To(HaveOccurred())
|
||||
err = validateRateAndBurst(0, 1)
|
||||
Expect(err).To(HaveOccurred())
|
||||
err = validateRateAndBurst(1, 0)
|
||||
Expect(err).To(HaveOccurred())
|
||||
err = validateRateAndBurst(0, 0)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -106,7 +106,7 @@ func makeTcpClientInNS(netns string, address string, port int, numBytes int) {
|
||||
Expect(string(out)).To(Equal(message))
|
||||
}
|
||||
|
||||
func createVeth(hostNamespace string, hostVethIfName string, containerNamespace string, containerVethIfName string, hostIP []byte, containerIP []byte, hostIfaceMTU int) {
|
||||
func createVeth(hostNs ns.NetNS, hostVethIfName string, containerNs ns.NetNS, containerVethIfName string, hostIP []byte, containerIP []byte, hostIfaceMTU int) {
|
||||
vethDeviceRequest := &netlink.Veth{
|
||||
LinkAttrs: netlink.LinkAttrs{
|
||||
Name: hostVethIfName,
|
||||
@ -116,10 +116,7 @@ func createVeth(hostNamespace string, hostVethIfName string, containerNamespace
|
||||
PeerName: containerVethIfName,
|
||||
}
|
||||
|
||||
hostNs, err := ns.GetNS(hostNamespace)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
err = hostNs.Do(func(_ ns.NetNS) error {
|
||||
err := hostNs.Do(func(_ ns.NetNS) error {
|
||||
if err := netlink.LinkAdd(vethDeviceRequest); err != nil {
|
||||
return fmt.Errorf("creating veth pair: %s", err)
|
||||
}
|
||||
@ -129,11 +126,6 @@ func createVeth(hostNamespace string, hostVethIfName string, containerNamespace
|
||||
return fmt.Errorf("failed to find newly-created veth device %q: %v", containerVethIfName, err)
|
||||
}
|
||||
|
||||
containerNs, err := ns.GetNS(containerNamespace)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = netlink.LinkSetNsFd(containerVeth, int(containerNs.Fd()))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to move veth to container namespace: %s", err)
|
||||
@ -169,8 +161,6 @@ func createVeth(hostNamespace string, hostVethIfName string, containerNamespace
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
containerNs, err := ns.GetNS(containerNamespace)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
err = containerNs.Do(func(_ ns.NetNS) error {
|
||||
peerAddr := &net.IPNet{
|
||||
IP: hostIP,
|
||||
@ -203,7 +193,7 @@ func createVeth(hostNamespace string, hostVethIfName string, containerNamespace
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
|
||||
func createVethInOneNs(namespace, vethName, peerName string) {
|
||||
func createVethInOneNs(netNS ns.NetNS, vethName, peerName string) {
|
||||
vethDeviceRequest := &netlink.Veth{
|
||||
LinkAttrs: netlink.LinkAttrs{
|
||||
Name: vethName,
|
||||
@ -212,10 +202,7 @@ func createVethInOneNs(namespace, vethName, peerName string) {
|
||||
PeerName: peerName,
|
||||
}
|
||||
|
||||
netNS, err := ns.GetNS(namespace)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
err = netNS.Do(func(_ ns.NetNS) error {
|
||||
err := netNS.Do(func(_ ns.NetNS) error {
|
||||
if err := netlink.LinkAdd(vethDeviceRequest); err != nil {
|
||||
return fmt.Errorf("failed to create veth pair: %v", err)
|
||||
}
|
||||
@ -229,11 +216,8 @@ func createVethInOneNs(namespace, vethName, peerName string) {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
|
||||
func createMacvlan(namespace, master, macvlanName string) {
|
||||
netNS, err := ns.GetNS(namespace)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
err = netNS.Do(func(_ ns.NetNS) error {
|
||||
func createMacvlan(netNS ns.NetNS, master, macvlanName string) {
|
||||
err := netNS.Do(func(_ ns.NetNS) error {
|
||||
m, err := netlink.LinkByName(master)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to lookup master %q: %v", master, err)
|
||||
|
@ -23,7 +23,7 @@ import (
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/cni/pkg/version"
|
||||
|
||||
"github.com/containernetworking/plugins/pkg/ip"
|
||||
|
@ -24,7 +24,7 @@ import (
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/cni/pkg/version"
|
||||
|
||||
bv "github.com/containernetworking/plugins/pkg/utils/buildversion"
|
||||
@ -130,7 +130,9 @@ func cmdAdd(args *skel.CmdArgs) error {
|
||||
}
|
||||
|
||||
if result == nil {
|
||||
result = ¤t.Result{}
|
||||
result = ¤t.Result{
|
||||
CNIVersion: current.ImplementedSpecVersion,
|
||||
}
|
||||
}
|
||||
return types.PrintResult(result, conf.CNIVersion)
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ import (
|
||||
|
||||
"github.com/containernetworking/cni/pkg/invoke"
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/plugins/pkg/ns"
|
||||
"github.com/containernetworking/plugins/pkg/testutils"
|
||||
|
||||
@ -34,30 +34,7 @@ import (
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
const (
|
||||
confTmpl = `{
|
||||
"cniVersion": "0.3.1",
|
||||
"name": "firewalld-test",
|
||||
"type": "firewall",
|
||||
"backend": "firewalld",
|
||||
"zone": "trusted",
|
||||
"prevResult": {
|
||||
"cniVersion": "0.3.0",
|
||||
"interfaces": [
|
||||
{"name": "%s", "sandbox": "%s"}
|
||||
],
|
||||
"ips": [
|
||||
{
|
||||
"version": "4",
|
||||
"address": "10.0.0.2/24",
|
||||
"gateway": "10.0.0.1",
|
||||
"interface": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
}`
|
||||
ifname = "eth0"
|
||||
)
|
||||
const ifname = "eth0"
|
||||
|
||||
type fakeFirewalld struct {
|
||||
zone string
|
||||
@ -125,6 +102,30 @@ func spawnSessionDbus(wg *sync.WaitGroup) (string, *exec.Cmd) {
|
||||
return busAddr, cmd
|
||||
}
|
||||
|
||||
func makeFirewalldConf(ver, ifname string, ns ns.NetNS) []byte {
|
||||
return []byte(fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"name": "firewalld-test",
|
||||
"type": "firewall",
|
||||
"backend": "firewalld",
|
||||
"zone": "trusted",
|
||||
"prevResult": {
|
||||
"cniVersion": "%s",
|
||||
"interfaces": [
|
||||
{"name": "%s", "sandbox": "%s"}
|
||||
],
|
||||
"ips": [
|
||||
{
|
||||
"version": "4",
|
||||
"address": "10.0.0.2/24",
|
||||
"gateway": "10.0.0.1",
|
||||
"interface": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
}`, ver, ver, ifname, ns.Path()))
|
||||
}
|
||||
|
||||
var _ = Describe("firewalld test", func() {
|
||||
var (
|
||||
targetNs ns.NetNS
|
||||
@ -177,12 +178,22 @@ var _ = Describe("firewalld test", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
wg.Wait()
|
||||
|
||||
Expect(targetNs.Close()).To(Succeed())
|
||||
Expect(testutils.UnmountNS(targetNs)).To(Succeed())
|
||||
})
|
||||
|
||||
It("works with a 0.3.1 config", func() {
|
||||
// firewall plugin requires a prevResult and thus only supports 0.3.0
|
||||
// and later CNI versions
|
||||
for _, ver := range []string{"0.3.0", "0.3.1", "0.4.0", "1.0.0"} {
|
||||
// Redefine ver inside for scope so real value is picked up by each dynamically defined It()
|
||||
// See Gingkgo's "Patterns for dynamically generating tests" documentation.
|
||||
ver := ver
|
||||
|
||||
It(fmt.Sprintf("[%s] works with a config", ver), func() {
|
||||
Expect(isFirewalldRunning()).To(BeTrue())
|
||||
|
||||
conf := fmt.Sprintf(confTmpl, ifname, targetNs.Path())
|
||||
conf := makeFirewalldConf(ver, ifname, targetNs)
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNs.Path(),
|
||||
@ -205,30 +216,10 @@ var _ = Describe("firewalld test", func() {
|
||||
Expect(fwd.source).To(Equal("10.0.0.2/32"))
|
||||
})
|
||||
|
||||
It("defaults to the firewalld backend", func() {
|
||||
conf := `{
|
||||
"cniVersion": "0.3.1",
|
||||
"name": "firewalld-test",
|
||||
"type": "firewall",
|
||||
"zone": "trusted",
|
||||
"prevResult": {
|
||||
"cniVersion": "0.3.0",
|
||||
"interfaces": [
|
||||
{"name": "eth0", "sandbox": "/foobar"}
|
||||
],
|
||||
"ips": [
|
||||
{
|
||||
"version": "4",
|
||||
"address": "10.0.0.2/24",
|
||||
"gateway": "10.0.0.1",
|
||||
"interface": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
}`
|
||||
|
||||
It(fmt.Sprintf("[%s] defaults to the firewalld backend", ver), func() {
|
||||
Expect(isFirewalldRunning()).To(BeTrue())
|
||||
|
||||
conf := makeFirewalldConf(ver, ifname, targetNs)
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNs.Path(),
|
||||
@ -243,30 +234,10 @@ var _ = Describe("firewalld test", func() {
|
||||
Expect(fwd.source).To(Equal("10.0.0.2/32"))
|
||||
})
|
||||
|
||||
It("passes through the prevResult", func() {
|
||||
conf := `{
|
||||
"cniVersion": "0.3.1",
|
||||
"name": "firewalld-test",
|
||||
"type": "firewall",
|
||||
"zone": "trusted",
|
||||
"prevResult": {
|
||||
"cniVersion": "0.3.0",
|
||||
"interfaces": [
|
||||
{"name": "eth0", "sandbox": "/foobar"}
|
||||
],
|
||||
"ips": [
|
||||
{
|
||||
"version": "4",
|
||||
"address": "10.0.0.2/24",
|
||||
"gateway": "10.0.0.1",
|
||||
"interface": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
}`
|
||||
|
||||
It(fmt.Sprintf("[%s] passes through the prevResult", ver), func() {
|
||||
Expect(isFirewalldRunning()).To(BeTrue())
|
||||
|
||||
conf := makeFirewalldConf(ver, ifname, targetNs)
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNs.Path(),
|
||||
@ -287,31 +258,10 @@ var _ = Describe("firewalld test", func() {
|
||||
Expect(result.IPs[0].Address.String()).To(Equal("10.0.0.2/24"))
|
||||
})
|
||||
|
||||
It("works with a 0.4.0 config, including Check", func() {
|
||||
It(fmt.Sprintf("[%s] works with Check", ver), func() {
|
||||
Expect(isFirewalldRunning()).To(BeTrue())
|
||||
|
||||
conf := `{
|
||||
"cniVersion": "0.4.0",
|
||||
"name": "firewalld-test",
|
||||
"type": "firewall",
|
||||
"backend": "firewalld",
|
||||
"zone": "trusted",
|
||||
"prevResult": {
|
||||
"cniVersion": "0.4.0",
|
||||
"interfaces": [
|
||||
{"name": "eth0", "sandbox": "/foobar"}
|
||||
],
|
||||
"ips": [
|
||||
{
|
||||
"version": "4",
|
||||
"address": "10.0.0.2/24",
|
||||
"gateway": "10.0.0.1",
|
||||
"interface": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
}`
|
||||
|
||||
conf := makeFirewalldConf(ver, ifname, targetNs)
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNs.Path(),
|
||||
@ -325,6 +275,7 @@ var _ = Describe("firewalld test", func() {
|
||||
Expect(fwd.zone).To(Equal("trusted"))
|
||||
Expect(fwd.source).To(Equal("10.0.0.2/32"))
|
||||
|
||||
if testutils.SpecVersionHasCHECK(ver) {
|
||||
_, err = current.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
@ -332,6 +283,7 @@ var _ = Describe("firewalld test", func() {
|
||||
return cmdCheck(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
|
||||
err = testutils.CmdDelWithArgs(args, func() error {
|
||||
return cmdDel(args)
|
||||
@ -340,4 +292,5 @@ var _ = Describe("firewalld test", func() {
|
||||
Expect(fwd.zone).To(Equal("trusted"))
|
||||
Expect(fwd.source).To(Equal("10.0.0.2/32"))
|
||||
})
|
||||
}
|
||||
})
|
||||
|
@ -21,7 +21,8 @@ import (
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
"github.com/containernetworking/cni/pkg/types/040"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/cni/pkg/version"
|
||||
"github.com/containernetworking/plugins/pkg/ns"
|
||||
"github.com/containernetworking/plugins/pkg/testutils"
|
||||
@ -165,17 +166,15 @@ func validateCleanedUp(bytes []byte) {
|
||||
}
|
||||
}
|
||||
|
||||
var _ = Describe("firewall plugin iptables backend", func() {
|
||||
var originalNS, targetNS ns.NetNS
|
||||
const IFNAME string = "dummy0"
|
||||
|
||||
fullConf := []byte(`{
|
||||
func makeIptablesConf(ver string) []byte {
|
||||
return []byte(fmt.Sprintf(`{
|
||||
"name": "test",
|
||||
"type": "firewall",
|
||||
"backend": "iptables",
|
||||
"ifName": "dummy0",
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"prevResult": {
|
||||
"cniVersion": "%s",
|
||||
"interfaces": [
|
||||
{"name": "dummy0"}
|
||||
],
|
||||
@ -192,7 +191,12 @@ var _ = Describe("firewall plugin iptables backend", func() {
|
||||
}
|
||||
]
|
||||
}
|
||||
}`)
|
||||
}`, ver, ver))
|
||||
}
|
||||
|
||||
var _ = Describe("firewall plugin iptables backend", func() {
|
||||
var originalNS, targetNS ns.NetNS
|
||||
const IFNAME string = "dummy0"
|
||||
|
||||
BeforeEach(func() {
|
||||
// Create a new NetNS so we don't modify the host
|
||||
@ -224,7 +228,15 @@ var _ = Describe("firewall plugin iptables backend", func() {
|
||||
Expect(targetNS.Close()).To(Succeed())
|
||||
})
|
||||
|
||||
It("passes prevResult through unchanged", func() {
|
||||
// firewall plugin requires a prevResult and thus only supports 0.3.0
|
||||
// and later CNI versions
|
||||
for _, ver := range []string{"0.3.0", "0.3.1", "0.4.0", "1.0.0"} {
|
||||
// Redefine ver inside for scope so real value is picked up by each dynamically defined It()
|
||||
// See Gingkgo's "Patterns for dynamically generating tests" documentation.
|
||||
ver := ver
|
||||
|
||||
It(fmt.Sprintf("[%s] passes prevResult through unchanged", ver), func() {
|
||||
fullConf := makeIptablesConf(ver)
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNS.Path(),
|
||||
@ -253,7 +265,8 @@ var _ = Describe("firewall plugin iptables backend", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("installs the right iptables rules on the host", func() {
|
||||
It(fmt.Sprintf("[%s] installs the right iptables rules on the host", ver), func() {
|
||||
fullConf := makeIptablesConf(ver)
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNS.Path(),
|
||||
@ -282,15 +295,16 @@ var _ = Describe("firewall plugin iptables backend", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("correctly handles a custom IptablesAdminChainName", func() {
|
||||
conf := []byte(`{
|
||||
It(fmt.Sprintf("[%s] correctly handles a custom IptablesAdminChainName", ver), func() {
|
||||
conf := []byte(fmt.Sprintf(`{
|
||||
"name": "test",
|
||||
"type": "firewall",
|
||||
"backend": "iptables",
|
||||
"ifName": "dummy0",
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"iptablesAdminChainName": "CNI-foobar",
|
||||
"prevResult": {
|
||||
"cniVersion": "%s",
|
||||
"interfaces": [
|
||||
{"name": "dummy0"}
|
||||
],
|
||||
@ -307,7 +321,7 @@ var _ = Describe("firewall plugin iptables backend", func() {
|
||||
}
|
||||
]
|
||||
}
|
||||
}`)
|
||||
}`, ver, ver))
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
@ -346,143 +360,8 @@ var _ = Describe("firewall plugin iptables backend", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("cleans up on delete", func() {
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNS.Path(),
|
||||
IfName: IFNAME,
|
||||
StdinData: fullConf,
|
||||
}
|
||||
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
_, _, err := testutils.CmdAdd(targetNS.Path(), args.ContainerID, IFNAME, fullConf, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
validateFullRuleset(fullConf)
|
||||
|
||||
err = testutils.CmdDel(targetNS.Path(), args.ContainerID, IFNAME, func() error {
|
||||
return cmdDel(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
validateCleanedUp(fullConf)
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("installs the right iptables rules on the host v4.0.x and check is successful", func() {
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNS.Path(),
|
||||
IfName: IFNAME,
|
||||
StdinData: fullConf,
|
||||
}
|
||||
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
_, _, err := testutils.CmdAdd(targetNS.Path(), args.ContainerID, IFNAME, fullConf, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
validateFullRuleset(fullConf)
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("cleans up on delete v4.0.x", func() {
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNS.Path(),
|
||||
IfName: IFNAME,
|
||||
StdinData: fullConf,
|
||||
}
|
||||
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
_, _, err := testutils.CmdAdd(targetNS.Path(), args.ContainerID, IFNAME, fullConf, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
validateFullRuleset(fullConf)
|
||||
|
||||
err = testutils.CmdDel(targetNS.Path(), args.ContainerID, IFNAME, func() error {
|
||||
return cmdDel(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
validateCleanedUp(fullConf)
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
})
|
||||
|
||||
var _ = Describe("firewall plugin iptables backend v0.4.x", func() {
|
||||
var originalNS, targetNS ns.NetNS
|
||||
const IFNAME string = "dummy0"
|
||||
|
||||
fullConf := []byte(`{
|
||||
"name": "test",
|
||||
"type": "firewall",
|
||||
"backend": "iptables",
|
||||
"ifName": "dummy0",
|
||||
"cniVersion": "0.4.0",
|
||||
"prevResult": {
|
||||
"interfaces": [
|
||||
{"name": "dummy0"}
|
||||
],
|
||||
"ips": [
|
||||
{
|
||||
"version": "4",
|
||||
"address": "10.0.0.2/24",
|
||||
"interface": 0
|
||||
},
|
||||
{
|
||||
"version": "6",
|
||||
"address": "2001:db8:1:2::1/64",
|
||||
"interface": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
}`)
|
||||
|
||||
BeforeEach(func() {
|
||||
// Create a new NetNS so we don't modify the host
|
||||
var err error
|
||||
originalNS, err = testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
err = netlink.LinkAdd(&netlink.Dummy{
|
||||
LinkAttrs: netlink.LinkAttrs{
|
||||
Name: IFNAME,
|
||||
},
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
_, err = netlink.LinkByName(IFNAME)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
targetNS, err = testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
Expect(originalNS.Close()).To(Succeed())
|
||||
Expect(targetNS.Close()).To(Succeed())
|
||||
})
|
||||
|
||||
It("installs iptables rules, Check rules then cleans up on delete using v4.0.x", func() {
|
||||
It(fmt.Sprintf("[%s] installs iptables rules, checks rules, then cleans up on delete", ver), func() {
|
||||
fullConf := makeIptablesConf(ver)
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNS.Path(),
|
||||
@ -498,14 +377,16 @@ var _ = Describe("firewall plugin iptables backend v0.4.x", func() {
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
_, err = current.GetResult(r)
|
||||
_, err = types040.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
if testutils.SpecVersionHasCHECK(ver) {
|
||||
err = testutils.CmdCheckWithArgs(args, func() error {
|
||||
return cmdCheck(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
validateFullRuleset(fullConf)
|
||||
}
|
||||
|
||||
err = testutils.CmdDelWithArgs(args, func() error {
|
||||
return cmdDel(args)
|
||||
@ -516,4 +397,5 @@ var _ = Describe("firewall plugin iptables backend v0.4.x", func() {
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
}
|
||||
})
|
||||
|
@ -18,7 +18,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/godbus/dbus"
|
||||
)
|
||||
|
||||
|
@ -21,7 +21,7 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/plugins/pkg/utils"
|
||||
"github.com/coreos/go-iptables/iptables"
|
||||
)
|
||||
|
@ -189,7 +189,7 @@ func consumeScratchNetConf(containerID, dataDir string) (func(error), []byte, er
|
||||
return cleanup, netConfBytes, err
|
||||
}
|
||||
|
||||
func delegateAdd(cid, dataDir string, netconf map[string]interface{}) error {
|
||||
func delegateAdd(cid, dataDir, cniVersion string, netconf map[string]interface{}) error {
|
||||
netconfBytes, err := json.Marshal(netconf)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error serializing delegate netconf: %v", err)
|
||||
@ -205,7 +205,7 @@ func delegateAdd(cid, dataDir string, netconf map[string]interface{}) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return result.Print()
|
||||
return types.PrintResult(result, cniVersion)
|
||||
}
|
||||
|
||||
func hasKey(m map[string]interface{}, k string) bool {
|
||||
@ -247,7 +247,10 @@ func cmdAdd(args *skel.CmdArgs) error {
|
||||
n.Delegate["runtimeConfig"] = n.RuntimeConfig
|
||||
}
|
||||
|
||||
return doCmdAdd(args, n, fenv)
|
||||
// Delegate CNI config version must match flannel plugin config version
|
||||
n.Delegate["cniVersion"] = n.CNIVersion
|
||||
|
||||
return doCmdAdd(args, n.CNIVersion, n, fenv)
|
||||
}
|
||||
|
||||
func cmdDel(args *skel.CmdArgs) error {
|
||||
|
@ -72,7 +72,7 @@ func getDelegateIPAM(n *NetConf, fenv *subnetEnv) (map[string]interface{}, error
|
||||
return ipam, nil
|
||||
}
|
||||
|
||||
func doCmdAdd(args *skel.CmdArgs, n *NetConf, fenv *subnetEnv) error {
|
||||
func doCmdAdd(args *skel.CmdArgs, cniVersion string, n *NetConf, fenv *subnetEnv) error {
|
||||
n.Delegate["name"] = n.Name
|
||||
|
||||
if !hasKey(n.Delegate, "type") {
|
||||
@ -105,7 +105,7 @@ func doCmdAdd(args *skel.CmdArgs, n *NetConf, fenv *subnetEnv) error {
|
||||
}
|
||||
n.Delegate["ipam"] = ipam
|
||||
|
||||
return delegateAdd(args.ContainerID, n.DataDir, n.Delegate)
|
||||
return delegateAdd(args.ContainerID, n.DataDir, cniVersion, n.Delegate)
|
||||
}
|
||||
|
||||
func doCmdDel(args *skel.CmdArgs, n *NetConf) (err error) {
|
||||
|
@ -20,7 +20,7 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/plugins/pkg/ns"
|
||||
"github.com/containernetworking/plugins/pkg/testutils"
|
||||
|
||||
@ -31,6 +31,7 @@ import (
|
||||
var _ = Describe("Flannel", func() {
|
||||
var (
|
||||
originalNS ns.NetNS
|
||||
targetNS ns.NetNS
|
||||
onlyIpv4Input string
|
||||
onlyIpv6Input string
|
||||
dualStackInput string
|
||||
@ -40,20 +41,10 @@ var _ = Describe("Flannel", func() {
|
||||
dataDir string
|
||||
)
|
||||
|
||||
BeforeEach(func() {
|
||||
var err error
|
||||
originalNS, err = testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
Expect(originalNS.Close()).To(Succeed())
|
||||
})
|
||||
|
||||
const inputTemplate = `
|
||||
{
|
||||
const inputTemplate = `{
|
||||
"name": "cni-flannel",
|
||||
"type": "flannel",
|
||||
"cniVersion": "%s",
|
||||
"subnetFile": "%s",
|
||||
"dataDir": "%s"%s
|
||||
}`
|
||||
@ -95,6 +86,8 @@ FLANNEL_MTU=1472
|
||||
FLANNEL_IPMASQ=true
|
||||
`
|
||||
|
||||
const IFNAME = "eth0"
|
||||
|
||||
var writeSubnetEnv = func(contents string) string {
|
||||
file, err := ioutil.TempFile("", "subnet.env")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
@ -114,17 +107,29 @@ FLANNEL_IPMASQ=true
|
||||
return c
|
||||
}
|
||||
|
||||
var makeInput = func(inputIPAM string, subnetFile string) string {
|
||||
var makeInput = func(cniVersion, inputIPAM string, subnetFile string) string {
|
||||
ipamPart := ""
|
||||
if len(inputIPAM) > 0 {
|
||||
ipamPart = ",\n \"ipam\":\n" + inputIPAM
|
||||
}
|
||||
|
||||
return fmt.Sprintf(inputTemplate, subnetFile, dataDir, ipamPart)
|
||||
return fmt.Sprintf(inputTemplate, cniVersion, subnetFile, dataDir, ipamPart)
|
||||
}
|
||||
|
||||
var makeHostLocalIPAM = func(dataDir string) string {
|
||||
return fmt.Sprintf(`{
|
||||
"type": "host-local",
|
||||
"dataDir": "%s"
|
||||
}`, dataDir)
|
||||
}
|
||||
|
||||
BeforeEach(func() {
|
||||
var err error
|
||||
originalNS, err = testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
targetNS, err = testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// flannel subnet.env
|
||||
onlyIpv4SubnetFile = writeSubnetEnv(onlyIpv4FlannelSubnetEnv)
|
||||
onlyIpv6SubnetFile = writeSubnetEnv(onlyIpv6FlannelSubnetEnv)
|
||||
@ -133,38 +138,42 @@ FLANNEL_IPMASQ=true
|
||||
// flannel state dir
|
||||
dataDir, err = ioutil.TempDir("", "dataDir")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
onlyIpv4Input = makeInput("", onlyIpv4SubnetFile)
|
||||
onlyIpv6Input = makeInput("", onlyIpv6SubnetFile)
|
||||
dualStackInput = makeInput("", dualStackSubnetFile)
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
Expect(targetNS.Close()).To(Succeed())
|
||||
Expect(testutils.UnmountNS(targetNS)).To(Succeed())
|
||||
Expect(originalNS.Close()).To(Succeed())
|
||||
Expect(testutils.UnmountNS(originalNS)).To(Succeed())
|
||||
|
||||
os.Remove(onlyIpv4SubnetFile)
|
||||
os.Remove(onlyIpv6SubnetFile)
|
||||
os.Remove(dualStackSubnetFile)
|
||||
os.Remove(dataDir)
|
||||
Expect(os.RemoveAll(dataDir)).To(Succeed())
|
||||
})
|
||||
|
||||
Describe("CNI lifecycle", func() {
|
||||
for _, ver := range testutils.AllSpecVersions {
|
||||
// Redefine ver inside for scope so real value is picked up by each dynamically defined It()
|
||||
// See Gingkgo's "Patterns for dynamically generating tests" documentation.
|
||||
ver := ver
|
||||
|
||||
Context("when using only ipv4 stack", func() {
|
||||
It("uses dataDir for storing network configuration with ipv4 stack", func() {
|
||||
const IFNAME = "eth0"
|
||||
|
||||
targetNs, err := testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer targetNs.Close()
|
||||
|
||||
It(fmt.Sprintf("[%s] uses dataDir for storing network configuration with ipv4 stack", ver), func() {
|
||||
inputIPAM := makeHostLocalIPAM(dataDir)
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "some-container-id-ipv4",
|
||||
Netns: targetNs.Path(),
|
||||
Netns: targetNS.Path(),
|
||||
IfName: IFNAME,
|
||||
StdinData: []byte(onlyIpv4Input),
|
||||
StdinData: []byte(makeInput(ver, inputIPAM, onlyIpv4SubnetFile)),
|
||||
}
|
||||
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
By("calling ADD with ipv4 stack")
|
||||
GinkgoT().Logf("dataDir is %s", dataDir)
|
||||
GinkgoT().Logf("conf is %s", args.StdinData)
|
||||
resI, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
@ -176,7 +185,8 @@ FLANNEL_IPMASQ=true
|
||||
|
||||
netConfBytes, err := ioutil.ReadFile(path)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
expected := `{
|
||||
expected := fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"ipMasq": false,
|
||||
"ipam": {
|
||||
"routes": [
|
||||
@ -189,14 +199,14 @@ FLANNEL_IPMASQ=true
|
||||
"subnet": "10.1.17.0/24"
|
||||
}]
|
||||
],
|
||||
"type": "host-local"
|
||||
"type": "host-local",
|
||||
"dataDir": "%s"
|
||||
},
|
||||
"isGateway": true,
|
||||
"mtu": 1472,
|
||||
"name": "cni-flannel",
|
||||
"type": "bridge"
|
||||
}
|
||||
`
|
||||
}`, ver, dataDir)
|
||||
Expect(netConfBytes).Should(MatchJSON(expected))
|
||||
|
||||
result, err := current.NewResultFromResult(resI)
|
||||
@ -226,21 +236,16 @@ FLANNEL_IPMASQ=true
|
||||
})
|
||||
|
||||
Context("when using only ipv6 stack", func() {
|
||||
It("uses dataDir for storing network configuration with ipv6 stack", func() {
|
||||
const IFNAME = "eth0"
|
||||
|
||||
targetNs, err := testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer targetNs.Close()
|
||||
|
||||
It(fmt.Sprintf("[%s] uses dataDir for storing network configuration with ipv6 stack", ver), func() {
|
||||
inputIPAM := makeHostLocalIPAM(dataDir)
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "some-container-id-ipv6",
|
||||
Netns: targetNs.Path(),
|
||||
Netns: targetNS.Path(),
|
||||
IfName: IFNAME,
|
||||
StdinData: []byte(onlyIpv6Input),
|
||||
StdinData: []byte(makeInput(ver, inputIPAM, onlyIpv6SubnetFile)),
|
||||
}
|
||||
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
By("calling ADD with ipv6 stack")
|
||||
@ -255,7 +260,8 @@ FLANNEL_IPMASQ=true
|
||||
|
||||
netConfBytes, err := ioutil.ReadFile(path)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
expected := `{
|
||||
expected := fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"ipMasq": false,
|
||||
"ipam": {
|
||||
"routes": [
|
||||
@ -268,14 +274,14 @@ FLANNEL_IPMASQ=true
|
||||
"subnet": "fc00::/64"
|
||||
}]
|
||||
],
|
||||
"type": "host-local"
|
||||
"type": "host-local",
|
||||
"dataDir": "%s"
|
||||
},
|
||||
"isGateway": true,
|
||||
"mtu": 1472,
|
||||
"name": "cni-flannel",
|
||||
"type": "bridge"
|
||||
}
|
||||
`
|
||||
}`, ver, dataDir)
|
||||
Expect(netConfBytes).Should(MatchJSON(expected))
|
||||
|
||||
result, err := current.NewResultFromResult(resI)
|
||||
@ -305,21 +311,16 @@ FLANNEL_IPMASQ=true
|
||||
})
|
||||
|
||||
Context("when using dual stack", func() {
|
||||
It("uses dataDir for storing network configuration with dual stack", func() {
|
||||
const IFNAME = "eth0"
|
||||
|
||||
targetNs, err := testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer targetNs.Close()
|
||||
|
||||
It(fmt.Sprintf("[%s] uses dataDir for storing network configuration with dual stack", ver), func() {
|
||||
inputIPAM := makeHostLocalIPAM(dataDir)
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "some-container-id-dual-stack",
|
||||
Netns: targetNs.Path(),
|
||||
Netns: targetNS.Path(),
|
||||
IfName: IFNAME,
|
||||
StdinData: []byte(dualStackInput),
|
||||
StdinData: []byte(makeInput(ver, inputIPAM, dualStackSubnetFile)),
|
||||
}
|
||||
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
By("calling ADD with dual stack")
|
||||
@ -334,7 +335,8 @@ FLANNEL_IPMASQ=true
|
||||
|
||||
netConfBytes, err := ioutil.ReadFile(path)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
expected := `{
|
||||
expected := fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"ipMasq": false,
|
||||
"ipam": {
|
||||
"routes": [
|
||||
@ -353,14 +355,14 @@ FLANNEL_IPMASQ=true
|
||||
"subnet": "fc00::/64"
|
||||
}]
|
||||
],
|
||||
"type": "host-local"
|
||||
"type": "host-local",
|
||||
"dataDir": "%s"
|
||||
},
|
||||
"isGateway": true,
|
||||
"mtu": 1472,
|
||||
"name": "cni-flannel",
|
||||
"type": "bridge"
|
||||
}
|
||||
`
|
||||
}`, ver, dataDir)
|
||||
Expect(netConfBytes).Should(MatchJSON(expected))
|
||||
|
||||
result, err := current.NewResultFromResult(resI)
|
||||
@ -388,9 +390,22 @@ FLANNEL_IPMASQ=true
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
Describe("loadFlannelNetConf", func() {
|
||||
var (
|
||||
onlyIpv4Input string
|
||||
onlyIpv6Input string
|
||||
dualStackInput string
|
||||
)
|
||||
|
||||
BeforeEach(func() {
|
||||
onlyIpv4Input = makeInput(current.ImplementedSpecVersion, "", onlyIpv4SubnetFile)
|
||||
onlyIpv6Input = makeInput(current.ImplementedSpecVersion, "", onlyIpv6SubnetFile)
|
||||
dualStackInput = makeInput(current.ImplementedSpecVersion, "", dualStackSubnetFile)
|
||||
})
|
||||
|
||||
Context("when subnetFile and dataDir are specified with ipv4 stack", func() {
|
||||
It("loads flannel network config with ipv4 stack", func() {
|
||||
conf, err := loadFlannelNetConf([]byte(onlyIpv4Input))
|
||||
@ -553,7 +568,7 @@ FLANNEL_IPMASQ=true
|
||||
Context("when input IPAM is provided with ipv4 stack", func() {
|
||||
BeforeEach(func() {
|
||||
inputIPAM := makeInputIPAM(inputIPAMType, inputIPAMRoutes, "")
|
||||
onlyIpv4Input = makeInput(inputIPAM, onlyIpv4SubnetFile)
|
||||
onlyIpv4Input = makeInput(current.ImplementedSpecVersion, inputIPAM, onlyIpv4SubnetFile)
|
||||
})
|
||||
It("configures Delegate IPAM accordingly with ipv4 stack", func() {
|
||||
conf, err := loadFlannelNetConf([]byte(onlyIpv4Input))
|
||||
@ -575,7 +590,7 @@ FLANNEL_IPMASQ=true
|
||||
Context("when input IPAM is provided with ipv6 stack", func() {
|
||||
BeforeEach(func() {
|
||||
inputIPAM := makeInputIPAM(inputIPAMType, inputIPAMRoutes, "")
|
||||
onlyIpv6Input = makeInput(inputIPAM, onlyIpv6SubnetFile)
|
||||
onlyIpv6Input = makeInput(current.ImplementedSpecVersion, inputIPAM, onlyIpv6SubnetFile)
|
||||
})
|
||||
It("configures Delegate IPAM accordingly with ipv6 stack", func() {
|
||||
conf, err := loadFlannelNetConf([]byte(onlyIpv6Input))
|
||||
@ -597,7 +612,7 @@ FLANNEL_IPMASQ=true
|
||||
Context("when input IPAM is provided with dual stack", func() {
|
||||
BeforeEach(func() {
|
||||
inputIPAM := makeInputIPAM(inputIPAMType, inputIPAMRoutes, "")
|
||||
dualStackInput = makeInput(inputIPAM, dualStackSubnetFile)
|
||||
dualStackInput = makeInput(current.ImplementedSpecVersion, inputIPAM, dualStackSubnetFile)
|
||||
})
|
||||
It("configures Delegate IPAM accordingly with dual stack", func() {
|
||||
conf, err := loadFlannelNetConf([]byte(dualStackInput))
|
||||
@ -619,7 +634,7 @@ FLANNEL_IPMASQ=true
|
||||
Context("when input IPAM is provided without 'type' with ipv4 stack", func() {
|
||||
BeforeEach(func() {
|
||||
inputIPAM := makeInputIPAM("", inputIPAMRoutes, "")
|
||||
onlyIpv4Input = makeInput(inputIPAM, onlyIpv4SubnetFile)
|
||||
onlyIpv4Input = makeInput(current.ImplementedSpecVersion, inputIPAM, onlyIpv4SubnetFile)
|
||||
})
|
||||
It("configures Delegate IPAM with 'host-local' ipam with ipv4 stack", func() {
|
||||
conf, err := loadFlannelNetConf([]byte(onlyIpv4Input))
|
||||
@ -640,7 +655,7 @@ FLANNEL_IPMASQ=true
|
||||
Context("when input IPAM is provided without 'type' with ipv6 stack", func() {
|
||||
BeforeEach(func() {
|
||||
inputIPAM := makeInputIPAM("", inputIPAMRoutes, "")
|
||||
onlyIpv6Input = makeInput(inputIPAM, onlyIpv6SubnetFile)
|
||||
onlyIpv6Input = makeInput(current.ImplementedSpecVersion, inputIPAM, onlyIpv6SubnetFile)
|
||||
})
|
||||
It("configures Delegate IPAM with 'host-local' ipam with ipv6 stack", func() {
|
||||
conf, err := loadFlannelNetConf([]byte(onlyIpv6Input))
|
||||
@ -661,7 +676,7 @@ FLANNEL_IPMASQ=true
|
||||
Context("when input IPAM is provided without 'type' with dual stack", func() {
|
||||
BeforeEach(func() {
|
||||
inputIPAM := makeInputIPAM("", inputIPAMRoutes, "")
|
||||
dualStackInput = makeInput(inputIPAM, dualStackSubnetFile)
|
||||
dualStackInput = makeInput(current.ImplementedSpecVersion, inputIPAM, dualStackSubnetFile)
|
||||
})
|
||||
It("configures Delegate IPAM with 'host-local' ipam with dual stack", func() {
|
||||
conf, err := loadFlannelNetConf([]byte(dualStackInput))
|
||||
|
@ -30,7 +30,7 @@ import (
|
||||
"os"
|
||||
)
|
||||
|
||||
func doCmdAdd(args *skel.CmdArgs, n *NetConf, fenv *subnetEnv) error {
|
||||
func doCmdAdd(args *skel.CmdArgs, cniVersion string, n *NetConf, fenv *subnetEnv) error {
|
||||
n.Delegate["name"] = n.Name
|
||||
|
||||
if !hasKey(n.Delegate, "type") {
|
||||
@ -52,7 +52,8 @@ func doCmdAdd(args *skel.CmdArgs, n *NetConf, fenv *subnetEnv) error {
|
||||
"subnet": fenv.sn.String(),
|
||||
}
|
||||
|
||||
return delegateAdd(hns.GetSandboxContainerID(args.ContainerID, args.Netns), n.DataDir, n.Delegate)
|
||||
sandboxID := hns.GetSandboxContainerID(args.ContainerID, args.Netns)
|
||||
return delegateAdd(sandboxID, n.DataDir, cniVersion, n.Delegate)
|
||||
}
|
||||
|
||||
func doCmdDel(args *skel.CmdArgs, n *NetConf) (err error) {
|
||||
|
@ -33,7 +33,7 @@ import (
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/cni/pkg/version"
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
@ -223,9 +223,10 @@ func parseConfig(stdin []byte, ifName string) (*PortMapConf, *current.Result, er
|
||||
|
||||
if conf.PrevResult != nil {
|
||||
for _, ip := range result.IPs {
|
||||
if ip.Version == "6" && conf.ContIPv6.IP != nil {
|
||||
isIPv4 := ip.Address.IP.To4() != nil
|
||||
if !isIPv4 && conf.ContIPv6.IP != nil {
|
||||
continue
|
||||
} else if ip.Version == "4" && conf.ContIPv4.IP != nil {
|
||||
} else if isIPv4 && conf.ContIPv4.IP != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
@ -239,11 +240,10 @@ func parseConfig(stdin []byte, ifName string) (*PortMapConf, *current.Result, er
|
||||
continue
|
||||
}
|
||||
}
|
||||
switch ip.Version {
|
||||
case "6":
|
||||
conf.ContIPv6 = ip.Address
|
||||
case "4":
|
||||
if ip.Address.IP.To4() != nil {
|
||||
conf.ContIPv4 = ip.Address
|
||||
} else {
|
||||
conf.ContIPv6 = ip.Address
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/containernetworking/cni/libcni"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
"github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/plugins/pkg/ns"
|
||||
"github.com/containernetworking/plugins/pkg/testutils"
|
||||
"github.com/coreos/go-iptables/iptables"
|
||||
@ -37,19 +37,9 @@ import (
|
||||
|
||||
const TIMEOUT = 90
|
||||
|
||||
var _ = Describe("portmap integration tests", func() {
|
||||
var (
|
||||
configList *libcni.NetworkConfigList
|
||||
cniConf *libcni.CNIConfig
|
||||
targetNS ns.NetNS
|
||||
containerPort int
|
||||
session *gexec.Session
|
||||
)
|
||||
|
||||
BeforeEach(func() {
|
||||
var err error
|
||||
rawConfig := `{
|
||||
"cniVersion": "0.3.0",
|
||||
func makeConfig(ver string) *libcni.NetworkConfigList {
|
||||
configList, err := libcni.ConfListFromBytes([]byte(fmt.Sprintf(`{
|
||||
"cniVersion": "%s",
|
||||
"name": "cni-portmap-unit-test",
|
||||
"plugins": [
|
||||
{
|
||||
@ -70,15 +60,25 @@ var _ = Describe("portmap integration tests", func() {
|
||||
}
|
||||
}
|
||||
]
|
||||
}`
|
||||
|
||||
configList, err = libcni.ConfListFromBytes([]byte(rawConfig))
|
||||
}`, ver)))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
return configList
|
||||
}
|
||||
|
||||
var _ = Describe("portmap integration tests", func() {
|
||||
var (
|
||||
cniConf *libcni.CNIConfig
|
||||
targetNS ns.NetNS
|
||||
containerPort int
|
||||
session *gexec.Session
|
||||
)
|
||||
|
||||
BeforeEach(func() {
|
||||
// turn PATH in to CNI_PATH
|
||||
dirs := filepath.SplitList(os.Getenv("PATH"))
|
||||
cniConf = &libcni.CNIConfig{Path: dirs}
|
||||
|
||||
var err error
|
||||
targetNS, err = testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
fmt.Fprintln(GinkgoWriter, "namespace:", targetNS.Path())
|
||||
@ -90,14 +90,18 @@ var _ = Describe("portmap integration tests", func() {
|
||||
|
||||
AfterEach(func() {
|
||||
session.Terminate().Wait()
|
||||
if targetNS != nil {
|
||||
targetNS.Close()
|
||||
}
|
||||
testutils.UnmountNS(targetNS)
|
||||
})
|
||||
|
||||
for _, ver := range []string{"0.3.0", "0.3.1", "0.4.0", "1.0.0"} {
|
||||
// Redefine ver inside for scope so real value is picked up by each dynamically defined It()
|
||||
// See Gingkgo's "Patterns for dynamically generating tests" documentation.
|
||||
ver := ver
|
||||
|
||||
Describe("Creating an interface in a namespace with the ptp plugin", func() {
|
||||
// This needs to be done using Ginkgo's asynchronous testing mode.
|
||||
It("forwards a TCP port on ipv4", func(done Done) {
|
||||
It(fmt.Sprintf("[%s] forwards a TCP port on ipv4", ver), func(done Done) {
|
||||
var err error
|
||||
hostPort := rand.Intn(10000) + 1025
|
||||
runtimeConfig := libcni.RuntimeConf{
|
||||
@ -114,6 +118,7 @@ var _ = Describe("portmap integration tests", func() {
|
||||
},
|
||||
},
|
||||
}
|
||||
configList := makeConfig(ver)
|
||||
|
||||
// Make delete idempotent, so we can clean up on failure
|
||||
netDeleted := false
|
||||
@ -146,7 +151,7 @@ var _ = Describe("portmap integration tests", func() {
|
||||
_, err = ipt.List("nat", dnatChainName)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
result, err := current.GetResult(resI)
|
||||
result, err := types100.GetResult(resI)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
var contIP net.IP
|
||||
|
||||
@ -221,7 +226,7 @@ var _ = Describe("portmap integration tests", func() {
|
||||
close(done)
|
||||
}, TIMEOUT*9)
|
||||
|
||||
It("forwards a UDP port on ipv4 and keep working after creating a second container with the same HostPort", func(done Done) {
|
||||
It(fmt.Sprintf("[%s] forwards a UDP port on ipv4 and keep working after creating a second container with the same HostPort", ver), func(done Done) {
|
||||
var err error
|
||||
hostPort := rand.Intn(10000) + 1025
|
||||
runtimeConfig := libcni.RuntimeConf{
|
||||
@ -238,6 +243,7 @@ var _ = Describe("portmap integration tests", func() {
|
||||
},
|
||||
},
|
||||
}
|
||||
configList := makeConfig(ver)
|
||||
|
||||
// Make delete idempotent, so we can clean up on failure
|
||||
netDeleted := false
|
||||
@ -261,7 +267,7 @@ var _ = Describe("portmap integration tests", func() {
|
||||
err = cmd.Run()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
result, err := current.GetResult(resI)
|
||||
result, err := types100.GetResult(resI)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
var contIP net.IP
|
||||
|
||||
@ -357,7 +363,7 @@ var _ = Describe("portmap integration tests", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer deleteNetwork2()
|
||||
|
||||
result2, err := current.GetResult(resI2)
|
||||
result2, err := types100.GetResult(resI2)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
var contIP2 net.IP
|
||||
|
||||
@ -417,6 +423,7 @@ var _ = Describe("portmap integration tests", func() {
|
||||
close(done)
|
||||
}, TIMEOUT*9)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// testEchoServer returns true if we found an echo server on the port
|
||||
|
@ -27,12 +27,17 @@ var _ = Describe("portmapping configuration", func() {
|
||||
netName := "testNetName"
|
||||
containerID := "icee6giejonei6sohng6ahngee7laquohquee9shiGo7fohferakah3Feiyoolu2pei7ciPhoh7shaoX6vai3vuf0ahfaeng8yohb9ceu0daez5hashee8ooYai5wa3y"
|
||||
|
||||
for _, ver := range []string{"0.3.0", "0.3.1", "0.4.0", "1.0.0"} {
|
||||
// Redefine ver inside for scope so real value is picked up by each dynamically defined It()
|
||||
// See Gingkgo's "Patterns for dynamically generating tests" documentation.
|
||||
ver := ver
|
||||
|
||||
Context("config parsing", func() {
|
||||
It("Correctly parses an ADD config", func() {
|
||||
configBytes := []byte(`{
|
||||
It(fmt.Sprintf("[%s] correctly parses an ADD config", ver), func() {
|
||||
configBytes := []byte(fmt.Sprintf(`{
|
||||
"name": "test",
|
||||
"type": "portmap",
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"runtimeConfig": {
|
||||
"portMappings": [
|
||||
{ "hostPort": 8080, "containerPort": 80, "protocol": "tcp"},
|
||||
@ -68,10 +73,10 @@ var _ = Describe("portmapping configuration", func() {
|
||||
}
|
||||
]
|
||||
}
|
||||
}`)
|
||||
}`, ver))
|
||||
c, _, err := parseConfig(configBytes, "container")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(c.CNIVersion).To(Equal("0.3.1"))
|
||||
Expect(c.CNIVersion).To(Equal(ver))
|
||||
Expect(c.ConditionsV4).To(Equal(&[]string{"a", "b"}))
|
||||
Expect(c.ConditionsV6).To(Equal(&[]string{"c", "d"}))
|
||||
fvar := false
|
||||
@ -84,19 +89,19 @@ var _ = Describe("portmapping configuration", func() {
|
||||
Expect(c.ContIPv6).To(Equal(*n))
|
||||
})
|
||||
|
||||
It("Correctly parses a DEL config", func() {
|
||||
It(fmt.Sprintf("[%s] correctly parses a DEL config", ver), func() {
|
||||
// When called with DEL, neither runtimeConfig nor prevResult may be specified
|
||||
configBytes := []byte(`{
|
||||
configBytes := []byte(fmt.Sprintf(`{
|
||||
"name": "test",
|
||||
"type": "portmap",
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"snat": false,
|
||||
"conditionsV4": ["a", "b"],
|
||||
"conditionsV6": ["c", "d"]
|
||||
}`)
|
||||
}`, ver))
|
||||
c, _, err := parseConfig(configBytes, "container")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(c.CNIVersion).To(Equal("0.3.1"))
|
||||
Expect(c.CNIVersion).To(Equal(ver))
|
||||
Expect(c.ConditionsV4).To(Equal(&[]string{"a", "b"}))
|
||||
Expect(c.ConditionsV6).To(Equal(&[]string{"c", "d"}))
|
||||
fvar := false
|
||||
@ -104,11 +109,11 @@ var _ = Describe("portmapping configuration", func() {
|
||||
Expect(c.Name).To(Equal("test"))
|
||||
})
|
||||
|
||||
It("fails with invalid mappings", func() {
|
||||
configBytes := []byte(`{
|
||||
It(fmt.Sprintf("[%s] fails with invalid mappings", ver), func() {
|
||||
configBytes := []byte(fmt.Sprintf(`{
|
||||
"name": "test",
|
||||
"type": "portmap",
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"snat": false,
|
||||
"conditionsV4": ["a", "b"],
|
||||
"conditionsV6": ["c", "d"],
|
||||
@ -117,16 +122,16 @@ var _ = Describe("portmapping configuration", func() {
|
||||
{ "hostPort": 0, "containerPort": 80, "protocol": "tcp"}
|
||||
]
|
||||
}
|
||||
}`)
|
||||
}`, ver))
|
||||
_, _, err := parseConfig(configBytes, "container")
|
||||
Expect(err).To(MatchError("Invalid host port number: 0"))
|
||||
})
|
||||
|
||||
It("Does not fail on missing prevResult interface index", func() {
|
||||
configBytes := []byte(`{
|
||||
It(fmt.Sprintf("[%s] does not fail on missing prevResult interface index", ver), func() {
|
||||
configBytes := []byte(fmt.Sprintf(`{
|
||||
"name": "test",
|
||||
"type": "portmap",
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"runtimeConfig": {
|
||||
"portMappings": [
|
||||
{ "hostPort": 8080, "containerPort": 80, "protocol": "tcp"}
|
||||
@ -145,7 +150,7 @@ var _ = Describe("portmapping configuration", func() {
|
||||
}
|
||||
]
|
||||
}
|
||||
}`)
|
||||
}`, ver))
|
||||
_, _, err := parseConfig(configBytes, "container")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
@ -153,7 +158,7 @@ var _ = Describe("portmapping configuration", func() {
|
||||
|
||||
Describe("Generating chains", func() {
|
||||
Context("for DNAT", func() {
|
||||
It("generates a correct standard container chain", func() {
|
||||
It(fmt.Sprintf("[%s] generates a correct standard container chain", ver), func() {
|
||||
ch := genDnatChain(netName, containerID)
|
||||
|
||||
Expect(ch).To(Equal(chain{
|
||||
@ -161,10 +166,10 @@ var _ = Describe("portmapping configuration", func() {
|
||||
name: "CNI-DN-bfd599665540dd91d5d28",
|
||||
entryChains: []string{TopLevelDNATChainName},
|
||||
}))
|
||||
configBytes := []byte(`{
|
||||
configBytes := []byte(fmt.Sprintf(`{
|
||||
"name": "test",
|
||||
"type": "portmap",
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"runtimeConfig": {
|
||||
"portMappings": [
|
||||
{ "hostPort": 8080, "containerPort": 80, "protocol": "tcp"},
|
||||
@ -180,7 +185,7 @@ var _ = Describe("portmapping configuration", func() {
|
||||
"snat": true,
|
||||
"conditionsV4": ["a", "b"],
|
||||
"conditionsV6": ["c", "d"]
|
||||
}`)
|
||||
}`, ver))
|
||||
|
||||
conf, _, err := parseConfig(configBytes, "foo")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
@ -279,7 +284,7 @@ var _ = Describe("portmapping configuration", func() {
|
||||
}))
|
||||
})
|
||||
|
||||
It("generates a correct chain with external mark", func() {
|
||||
It(fmt.Sprintf("[%s] generates a correct chain with external mark", ver), func() {
|
||||
ch := genDnatChain(netName, containerID)
|
||||
|
||||
Expect(ch).To(Equal(chain{
|
||||
@ -287,10 +292,10 @@ var _ = Describe("portmapping configuration", func() {
|
||||
name: "CNI-DN-bfd599665540dd91d5d28",
|
||||
entryChains: []string{TopLevelDNATChainName},
|
||||
}))
|
||||
configBytes := []byte(`{
|
||||
configBytes := []byte(fmt.Sprintf(`{
|
||||
"name": "test",
|
||||
"type": "portmap",
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"runtimeConfig": {
|
||||
"portMappings": [
|
||||
{ "hostPort": 8080, "containerPort": 80, "protocol": "tcp"}
|
||||
@ -299,7 +304,7 @@ var _ = Describe("portmapping configuration", func() {
|
||||
"externalSetMarkChain": "PLZ-SET-MARK",
|
||||
"conditionsV4": ["a", "b"],
|
||||
"conditionsV6": ["c", "d"]
|
||||
}`)
|
||||
}`, ver))
|
||||
|
||||
conf, _, err := parseConfig(configBytes, "foo")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
@ -315,7 +320,7 @@ var _ = Describe("portmapping configuration", func() {
|
||||
}))
|
||||
})
|
||||
|
||||
It("generates a correct top-level chain", func() {
|
||||
It(fmt.Sprintf("[%s] generates a correct top-level chain", ver), func() {
|
||||
ch := genToplevelDnatChain()
|
||||
|
||||
Expect(ch).To(Equal(chain{
|
||||
@ -326,7 +331,7 @@ var _ = Describe("portmapping configuration", func() {
|
||||
}))
|
||||
})
|
||||
|
||||
It("generates the correct mark chains", func() {
|
||||
It(fmt.Sprintf("[%s] generates the correct mark chains", ver), func() {
|
||||
masqBit := 5
|
||||
ch := genSetMarkChain(masqBit)
|
||||
Expect(ch).To(Equal(chain{
|
||||
@ -359,4 +364,5 @@ var _ = Describe("portmapping configuration", func() {
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
|
@ -26,7 +26,7 @@ import (
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/cni/pkg/version"
|
||||
|
||||
"github.com/containernetworking/plugins/pkg/ns"
|
||||
@ -234,7 +234,7 @@ func doRoutes(ipCfgs []*current.IPConfig, origRoutes []*types.Route, iface strin
|
||||
// Source must be restricted to a single IP, not a full subnet
|
||||
var src net.IPNet
|
||||
src.IP = ipCfg.Address.IP
|
||||
if ipCfg.Version == "4" {
|
||||
if src.IP.To4() != nil {
|
||||
src.Mask = net.CIDRMask(32, 32)
|
||||
} else {
|
||||
src.Mask = net.CIDRMask(128, 128)
|
||||
@ -253,7 +253,7 @@ func doRoutes(ipCfgs []*current.IPConfig, origRoutes []*types.Route, iface strin
|
||||
log.Printf("Adding default route to gateway %s", ipCfg.Gateway.String())
|
||||
|
||||
var dest net.IPNet
|
||||
if ipCfg.Version == "4" {
|
||||
if ipCfg.Address.IP.To4() != nil {
|
||||
dest.IP = net.IPv4zero
|
||||
dest.Mask = net.CIDRMask(0, 32)
|
||||
} else {
|
||||
|
@ -241,6 +241,7 @@ var _ = Describe("sbr test", func() {
|
||||
"name": "cni-plugin-sbr-test",
|
||||
"type": "sbr",
|
||||
"prevResult": {
|
||||
"cniVersion": "0.3.0",
|
||||
"interfaces": [
|
||||
{
|
||||
"name": "%s",
|
||||
@ -332,6 +333,7 @@ var _ = Describe("sbr test", func() {
|
||||
"name": "cni-plugin-sbr-test",
|
||||
"type": "sbr",
|
||||
"prevResult": {
|
||||
"cniVersion": "0.3.0",
|
||||
"interfaces": [
|
||||
{
|
||||
"name": "%s",
|
||||
@ -399,19 +401,12 @@ var _ = Describe("sbr test", func() {
|
||||
Expect(equalRoutes(expNet1.Routes, devNet1.Routes)).To(BeTrue())
|
||||
})
|
||||
|
||||
It("works with a 0.2.0 config", func() {
|
||||
It("fails with CNI spec versions that don't support plugin chaining", func() {
|
||||
conf := `{
|
||||
"cniVersion": "0.2.0",
|
||||
"name": "cni-plugin-sbr-test",
|
||||
"type": "sbr",
|
||||
"anotherAwesomeArg": "foo",
|
||||
"prevResult": {
|
||||
"ip4": {
|
||||
"ip": "192.168.1.209/24",
|
||||
"gateway": "192.168.1.1",
|
||||
"routes": []
|
||||
}
|
||||
}
|
||||
"anotherAwesomeArg": "foo"
|
||||
}`
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
@ -424,7 +419,7 @@ var _ = Describe("sbr test", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
_, _, err = testutils.CmdAddWithArgs(args, func() error { return cmdAdd(args) })
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(err).To(MatchError("This plugin must be called as chained plugin"))
|
||||
})
|
||||
|
||||
})
|
||||
|
@ -32,7 +32,7 @@ import (
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/cni/pkg/version"
|
||||
|
||||
"github.com/containernetworking/plugins/pkg/ns"
|
||||
@ -322,7 +322,7 @@ func cmdAdd(args *skel.CmdArgs) error {
|
||||
}
|
||||
|
||||
for _, ipc := range result.IPs {
|
||||
if ipc.Version == "4" {
|
||||
if ipc.Address.IP.To4() != nil {
|
||||
_ = arping.GratuitousArpOverIfaceByName(ipc.Address.IP, args.IfName)
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ import (
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
"github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/plugins/pkg/ns"
|
||||
"github.com/containernetworking/plugins/pkg/testutils"
|
||||
|
||||
@ -75,7 +75,7 @@ func buildOneConfig(name, cniVersion string, orig *TuningConf, prevResult types.
|
||||
}
|
||||
|
||||
var _ = Describe("tuning plugin", func() {
|
||||
var originalNS ns.NetNS
|
||||
var originalNS, targetNS ns.NetNS
|
||||
const IFNAME string = "dummy0"
|
||||
var beforeConf configToRestore
|
||||
|
||||
@ -85,6 +85,9 @@ var _ = Describe("tuning plugin", func() {
|
||||
originalNS, err = testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
targetNS, err = testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
@ -108,13 +111,21 @@ var _ = Describe("tuning plugin", func() {
|
||||
|
||||
AfterEach(func() {
|
||||
Expect(originalNS.Close()).To(Succeed())
|
||||
Expect(testutils.UnmountNS(originalNS)).To(Succeed())
|
||||
Expect(targetNS.Close()).To(Succeed())
|
||||
Expect(testutils.UnmountNS(targetNS)).To(Succeed())
|
||||
})
|
||||
|
||||
It("passes prevResult through unchanged", func() {
|
||||
conf := []byte(`{
|
||||
for _, ver := range []string{"0.3.0", "0.3.1", "0.4.0", "1.0.0"} {
|
||||
// Redefine ver inside for scope so real value is picked up by each dynamically defined It()
|
||||
// See Gingkgo's "Patterns for dynamically generating tests" documentation.
|
||||
ver := ver
|
||||
|
||||
It(fmt.Sprintf("[%s] passes prevResult through unchanged", ver), func() {
|
||||
conf := []byte(fmt.Sprintf(`{
|
||||
"name": "test",
|
||||
"type": "tuning",
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"sysctl": {
|
||||
"net.ipv4.conf.all.log_martians": "1"
|
||||
},
|
||||
@ -131,22 +142,18 @@ var _ = Describe("tuning plugin", func() {
|
||||
}
|
||||
]
|
||||
}
|
||||
}`)
|
||||
|
||||
targetNs, err := testutils.NewNS()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer targetNs.Close()
|
||||
}`, ver))
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: targetNs.Path(),
|
||||
Netns: targetNS.Path(),
|
||||
IfName: IFNAME,
|
||||
StdinData: conf,
|
||||
}
|
||||
|
||||
beforeConf = configToRestore{}
|
||||
|
||||
err = originalNS.Do(func(ns.NetNS) error {
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
r, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||
@ -154,7 +161,7 @@ var _ = Describe("tuning plugin", func() {
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
result, err := current.GetResult(r)
|
||||
result, err := types100.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(result.Interfaces)).To(Equal(1))
|
||||
@ -173,11 +180,11 @@ var _ = Describe("tuning plugin", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("configures and deconfigures promiscuous mode with ADD/DEL", func() {
|
||||
conf := []byte(`{
|
||||
It(fmt.Sprintf("[%s] configures and deconfigures promiscuous mode with ADD/DEL", ver), func() {
|
||||
conf := []byte(fmt.Sprintf(`{
|
||||
"name": "test",
|
||||
"type": "iplink",
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"promisc": true,
|
||||
"prevResult": {
|
||||
"interfaces": [
|
||||
@ -192,7 +199,7 @@ var _ = Describe("tuning plugin", func() {
|
||||
}
|
||||
]
|
||||
}
|
||||
}`)
|
||||
}`, ver))
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
@ -209,7 +216,7 @@ var _ = Describe("tuning plugin", func() {
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
result, err := current.GetResult(r)
|
||||
result, err := types100.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(result.Interfaces)).To(Equal(1))
|
||||
@ -221,6 +228,22 @@ var _ = Describe("tuning plugin", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().Promisc).To(Equal(1))
|
||||
|
||||
if testutils.SpecVersionHasCHECK(ver) {
|
||||
n := &TuningConf{}
|
||||
err = json.Unmarshal([]byte(conf), &n)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
_, confString, err := buildOneConfig("testConfig", ver, n, r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
args.StdinData = confString
|
||||
|
||||
err = testutils.CmdCheckWithArgs(args, func() error {
|
||||
return cmdCheck(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
|
||||
err = testutils.CmdDel(originalNS.Path(),
|
||||
args.ContainerID, "", func() error { return cmdDel(args) })
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
@ -234,11 +257,11 @@ var _ = Describe("tuning plugin", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("configures and deconfigures promiscuous mode from args with ADD/DEL", func() {
|
||||
conf := []byte(`{
|
||||
It(fmt.Sprintf("[%s] configures and deconfigures promiscuous mode from args with ADD/DEL", ver), func() {
|
||||
conf := []byte(fmt.Sprintf(`{
|
||||
"name": "test",
|
||||
"type": "iplink",
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"args": {
|
||||
"cni": {
|
||||
"promisc": true
|
||||
@ -257,7 +280,7 @@ var _ = Describe("tuning plugin", func() {
|
||||
}
|
||||
]
|
||||
}
|
||||
}`)
|
||||
}`, ver))
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
@ -274,7 +297,7 @@ var _ = Describe("tuning plugin", func() {
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
result, err := current.GetResult(r)
|
||||
result, err := types100.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(result.Interfaces)).To(Equal(1))
|
||||
@ -299,11 +322,11 @@ var _ = Describe("tuning plugin", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("configures and deconfigures mtu with ADD/DEL", func() {
|
||||
conf := []byte(`{
|
||||
It(fmt.Sprintf("[%s] configures and deconfigures mtu with ADD/DEL", ver), func() {
|
||||
conf := []byte(fmt.Sprintf(`{
|
||||
"name": "test",
|
||||
"type": "iplink",
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"mtu": 1454,
|
||||
"prevResult": {
|
||||
"interfaces": [
|
||||
@ -318,7 +341,7 @@ var _ = Describe("tuning plugin", func() {
|
||||
}
|
||||
]
|
||||
}
|
||||
}`)
|
||||
}`, ver))
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
@ -335,7 +358,7 @@ var _ = Describe("tuning plugin", func() {
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
result, err := current.GetResult(r)
|
||||
result, err := types100.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(result.Interfaces)).To(Equal(1))
|
||||
@ -347,6 +370,22 @@ var _ = Describe("tuning plugin", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().MTU).To(Equal(1454))
|
||||
|
||||
if testutils.SpecVersionHasCHECK(ver) {
|
||||
n := &TuningConf{}
|
||||
err = json.Unmarshal([]byte(conf), &n)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
_, confString, err := buildOneConfig("testConfig", ver, n, r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
args.StdinData = confString
|
||||
|
||||
err = testutils.CmdCheckWithArgs(args, func() error {
|
||||
return cmdCheck(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
|
||||
err = testutils.CmdDel(originalNS.Path(),
|
||||
args.ContainerID, "", func() error { return cmdDel(args) })
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
@ -360,11 +399,11 @@ var _ = Describe("tuning plugin", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("configures and deconfigures mtu from args with ADD/DEL", func() {
|
||||
conf := []byte(`{
|
||||
It(fmt.Sprintf("[%s] configures and deconfigures mtu from args with ADD/DEL", ver), func() {
|
||||
conf := []byte(fmt.Sprintf(`{
|
||||
"name": "test",
|
||||
"type": "iplink",
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"args": {
|
||||
"cni": {
|
||||
"mtu": 1454
|
||||
@ -383,7 +422,7 @@ var _ = Describe("tuning plugin", func() {
|
||||
}
|
||||
]
|
||||
}
|
||||
}`)
|
||||
}`, ver))
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
@ -400,7 +439,7 @@ var _ = Describe("tuning plugin", func() {
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
result, err := current.GetResult(r)
|
||||
result, err := types100.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(result.Interfaces)).To(Equal(1))
|
||||
@ -425,11 +464,11 @@ var _ = Describe("tuning plugin", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("configures and deconfigures mac address (from conf file) with ADD/DEL", func() {
|
||||
conf := []byte(`{
|
||||
It(fmt.Sprintf("[%s] configures and deconfigures mac address (from conf file) with ADD/DEL", ver), func() {
|
||||
conf := []byte(fmt.Sprintf(`{
|
||||
"name": "test",
|
||||
"type": "iplink",
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"mac": "c2:11:22:33:44:55",
|
||||
"prevResult": {
|
||||
"interfaces": [
|
||||
@ -444,7 +483,7 @@ var _ = Describe("tuning plugin", func() {
|
||||
}
|
||||
]
|
||||
}
|
||||
}`)
|
||||
}`, ver))
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
@ -461,7 +500,7 @@ var _ = Describe("tuning plugin", func() {
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
result, err := current.GetResult(r)
|
||||
result, err := types100.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(result.Interfaces)).To(Equal(1))
|
||||
@ -475,6 +514,22 @@ var _ = Describe("tuning plugin", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().HardwareAddr).To(Equal(hw))
|
||||
|
||||
if testutils.SpecVersionHasCHECK(ver) {
|
||||
n := &TuningConf{}
|
||||
err = json.Unmarshal([]byte(conf), &n)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
_, confString, err := buildOneConfig("testConfig", ver, n, r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
args.StdinData = confString
|
||||
|
||||
err = testutils.CmdCheckWithArgs(args, func() error {
|
||||
return cmdCheck(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
|
||||
err = testutils.CmdDel(originalNS.Path(),
|
||||
args.ContainerID, "", func() error { return cmdDel(args) })
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
@ -488,11 +543,11 @@ var _ = Describe("tuning plugin", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("configures and deconfigures mac address (from args) with ADD/DEL", func() {
|
||||
conf := []byte(`{
|
||||
It(fmt.Sprintf("[%s] configures and deconfigures mac address (from args) with ADD/DEL", ver), func() {
|
||||
conf := []byte(fmt.Sprintf(`{
|
||||
"name": "test",
|
||||
"type": "iplink",
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"args": {
|
||||
"cni": {
|
||||
"mac": "c2:11:22:33:44:55"
|
||||
@ -511,7 +566,7 @@ var _ = Describe("tuning plugin", func() {
|
||||
}
|
||||
]
|
||||
}
|
||||
}`)
|
||||
}`, ver))
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
@ -528,7 +583,7 @@ var _ = Describe("tuning plugin", func() {
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
result, err := current.GetResult(r)
|
||||
result, err := types100.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(result.Interfaces)).To(Equal(1))
|
||||
@ -555,11 +610,11 @@ var _ = Describe("tuning plugin", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("configures and deconfigures mac address (from CNI_ARGS) with ADD/DEL", func() {
|
||||
conf := []byte(`{
|
||||
It(fmt.Sprintf("[%s] configures and deconfigures mac address (from CNI_ARGS) with ADD/DEL", ver), func() {
|
||||
conf := []byte(fmt.Sprintf(`{
|
||||
"name": "test",
|
||||
"type": "iplink",
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"prevResult": {
|
||||
"interfaces": [
|
||||
{"name": "dummy0", "sandbox":"netns"}
|
||||
@ -573,7 +628,7 @@ var _ = Describe("tuning plugin", func() {
|
||||
}
|
||||
]
|
||||
}
|
||||
}`)
|
||||
}`, ver))
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
@ -591,301 +646,7 @@ var _ = Describe("tuning plugin", func() {
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
result, err := current.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(result.Interfaces)).To(Equal(1))
|
||||
Expect(result.Interfaces[0].Name).To(Equal(IFNAME))
|
||||
Expect(len(result.IPs)).To(Equal(1))
|
||||
Expect(result.IPs[0].Address.String()).To(Equal("10.0.0.2/24"))
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
hw, err := net.ParseMAC("c2:11:22:33:44:66")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
fmt.Printf("%v, %v\n", link.Attrs().HardwareAddr, hw)
|
||||
Expect(link.Attrs().HardwareAddr).To(Equal(hw))
|
||||
|
||||
err = testutils.CmdDel(originalNS.Path(),
|
||||
args.ContainerID, "", func() error { return cmdDel(args) })
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
link, err = netlink.LinkByName(IFNAME)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().HardwareAddr.String()).To(Equal(beforeConf.Mac))
|
||||
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("configures and deconfigures promiscuous mode with CNI 0.4.0 ADD/DEL", func() {
|
||||
conf := []byte(`{
|
||||
"name": "test",
|
||||
"type": "iplink",
|
||||
"cniVersion": "0.4.0",
|
||||
"promisc": true,
|
||||
"prevResult": {
|
||||
"interfaces": [
|
||||
{"name": "dummy0", "sandbox":"netns"}
|
||||
],
|
||||
"ips": [
|
||||
{
|
||||
"version": "4",
|
||||
"address": "10.0.0.2/24",
|
||||
"gateway": "10.0.0.1",
|
||||
"interface": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
}`)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: originalNS.Path(),
|
||||
IfName: IFNAME,
|
||||
StdinData: conf,
|
||||
}
|
||||
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
r, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
result, err := current.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(result.Interfaces)).To(Equal(1))
|
||||
Expect(result.Interfaces[0].Name).To(Equal(IFNAME))
|
||||
Expect(len(result.IPs)).To(Equal(1))
|
||||
Expect(result.IPs[0].Address.String()).To(Equal("10.0.0.2/24"))
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().Promisc).To(Equal(1))
|
||||
|
||||
n := &TuningConf{}
|
||||
err = json.Unmarshal([]byte(conf), &n)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
cniVersion := "0.4.0"
|
||||
_, confString, err := buildOneConfig("testConfig", cniVersion, n, r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
args.StdinData = confString
|
||||
|
||||
err = testutils.CmdCheckWithArgs(args, func() error {
|
||||
return cmdCheck(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
err = testutils.CmdDel(originalNS.Path(),
|
||||
args.ContainerID, "", func() error { return cmdDel(args) })
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
link, err = netlink.LinkByName(IFNAME)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().Promisc != 0).To(Equal(*beforeConf.Promisc))
|
||||
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("configures and deconfigures mtu with CNI 0.4.0 ADD/DEL", func() {
|
||||
conf := []byte(`{
|
||||
"name": "test",
|
||||
"type": "iplink",
|
||||
"cniVersion": "0.4.0",
|
||||
"mtu": 1454,
|
||||
"prevResult": {
|
||||
"interfaces": [
|
||||
{"name": "dummy0", "sandbox":"netns"}
|
||||
],
|
||||
"ips": [
|
||||
{
|
||||
"version": "4",
|
||||
"address": "10.0.0.2/24",
|
||||
"gateway": "10.0.0.1",
|
||||
"interface": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
}`)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: originalNS.Path(),
|
||||
IfName: IFNAME,
|
||||
StdinData: conf,
|
||||
}
|
||||
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
r, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
result, err := current.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(result.Interfaces)).To(Equal(1))
|
||||
Expect(result.Interfaces[0].Name).To(Equal(IFNAME))
|
||||
Expect(len(result.IPs)).To(Equal(1))
|
||||
Expect(result.IPs[0].Address.String()).To(Equal("10.0.0.2/24"))
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().MTU).To(Equal(1454))
|
||||
|
||||
n := &TuningConf{}
|
||||
err = json.Unmarshal([]byte(conf), &n)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
cniVersion := "0.4.0"
|
||||
_, confString, err := buildOneConfig("testConfig", cniVersion, n, r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
args.StdinData = confString
|
||||
|
||||
err = testutils.CmdCheckWithArgs(args, func() error {
|
||||
return cmdCheck(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
err = testutils.CmdDel(originalNS.Path(),
|
||||
args.ContainerID, "", func() error { return cmdDel(args) })
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
link, err = netlink.LinkByName(IFNAME)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().MTU).To(Equal(beforeConf.Mtu))
|
||||
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("configures and deconfigures mac address (from conf file) with CNI v4.0 ADD/DEL", func() {
|
||||
conf := []byte(`{
|
||||
"name": "test",
|
||||
"type": "iplink",
|
||||
"cniVersion": "0.4.0",
|
||||
"mac": "c2:11:22:33:44:55",
|
||||
"prevResult": {
|
||||
"interfaces": [
|
||||
{"name": "dummy0", "sandbox":"netns"}
|
||||
],
|
||||
"ips": [
|
||||
{
|
||||
"version": "4",
|
||||
"address": "10.0.0.2/24",
|
||||
"gateway": "10.0.0.1",
|
||||
"interface": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
}`)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: originalNS.Path(),
|
||||
IfName: IFNAME,
|
||||
StdinData: conf,
|
||||
}
|
||||
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
r, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
result, err := current.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(result.Interfaces)).To(Equal(1))
|
||||
Expect(result.Interfaces[0].Name).To(Equal(IFNAME))
|
||||
Expect(len(result.IPs)).To(Equal(1))
|
||||
Expect(result.IPs[0].Address.String()).To(Equal("10.0.0.2/24"))
|
||||
|
||||
link, err := netlink.LinkByName(IFNAME)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
hw, err := net.ParseMAC("c2:11:22:33:44:55")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().HardwareAddr).To(Equal(hw))
|
||||
|
||||
n := &TuningConf{}
|
||||
err = json.Unmarshal([]byte(conf), &n)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
cniVersion := "0.4.0"
|
||||
_, confString, err := buildOneConfig("testConfig", cniVersion, n, r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
args.StdinData = confString
|
||||
|
||||
err = testutils.CmdCheckWithArgs(args, func() error {
|
||||
return cmdCheck(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
err = testutils.CmdDel(originalNS.Path(),
|
||||
args.ContainerID, "", func() error { return cmdDel(args) })
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
link, err = netlink.LinkByName(IFNAME)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().HardwareAddr.String()).To(Equal(beforeConf.Mac))
|
||||
|
||||
return nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("configures and deconfigures mac address (from CNI_ARGS) with CNI v4 ADD/DEL", func() {
|
||||
conf := []byte(`{
|
||||
"name": "test",
|
||||
"type": "iplink",
|
||||
"cniVersion": "0.4.0",
|
||||
"prevResult": {
|
||||
"interfaces": [
|
||||
{"name": "dummy0", "sandbox":"netns"}
|
||||
],
|
||||
"ips": [
|
||||
{
|
||||
"version": "4",
|
||||
"address": "10.0.0.2/24",
|
||||
"gateway": "10.0.0.1",
|
||||
"interface": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
}`)
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
Netns: originalNS.Path(),
|
||||
IfName: IFNAME,
|
||||
StdinData: conf,
|
||||
Args: "IgnoreUnknown=true;MAC=c2:11:22:33:44:66",
|
||||
}
|
||||
|
||||
err := originalNS.Do(func(ns.NetNS) error {
|
||||
defer GinkgoRecover()
|
||||
|
||||
r, _, err := testutils.CmdAddWithArgs(args, func() error {
|
||||
return cmdAdd(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
result, err := current.GetResult(r)
|
||||
result, err := types100.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(result.Interfaces)).To(Equal(1))
|
||||
@ -899,12 +660,12 @@ var _ = Describe("tuning plugin", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(link.Attrs().HardwareAddr).To(Equal(hw))
|
||||
|
||||
if testutils.SpecVersionHasCHECK(ver) {
|
||||
n := &TuningConf{}
|
||||
err = json.Unmarshal([]byte(conf), &n)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
cniVersion := "0.4.0"
|
||||
_, confString, err := buildOneConfig("testConfig", cniVersion, n, r)
|
||||
_, confString, err := buildOneConfig("testConfig", ver, n, r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
args.StdinData = confString
|
||||
@ -913,6 +674,7 @@ var _ = Describe("tuning plugin", func() {
|
||||
return cmdCheck(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
|
||||
err = testutils.CmdDel(originalNS.Path(),
|
||||
args.ContainerID, "", func() error { return cmdDel(args) })
|
||||
@ -927,11 +689,11 @@ var _ = Describe("tuning plugin", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("configures and deconfigures mac address (from RuntimeConfig) with ADD/DEL", func() {
|
||||
conf := []byte(`{
|
||||
It(fmt.Sprintf("[%s] configures and deconfigures mac address (from RuntimeConfig) with ADD/DEL", ver), func() {
|
||||
conf := []byte(fmt.Sprintf(`{
|
||||
"name": "test",
|
||||
"type": "iplink",
|
||||
"cniVersion": "0.3.1",
|
||||
"cniVersion": "%s",
|
||||
"capabilities": {"mac": true},
|
||||
"RuntimeConfig": {
|
||||
"mac": "c2:11:22:33:44:55"
|
||||
@ -949,7 +711,7 @@ var _ = Describe("tuning plugin", func() {
|
||||
}
|
||||
]
|
||||
}
|
||||
}`)
|
||||
}`, ver))
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
@ -966,7 +728,7 @@ var _ = Describe("tuning plugin", func() {
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
result, err := current.GetResult(r)
|
||||
result, err := types100.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(result.Interfaces)).To(Equal(1))
|
||||
@ -993,11 +755,11 @@ var _ = Describe("tuning plugin", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
It("configures and deconfigures mac address, promisc mode and MTU (from conf file) with custom dataDir", func() {
|
||||
conf := []byte(`{
|
||||
It(fmt.Sprintf("[%s] configures and deconfigures mac address, promisc mode and MTU (from conf file) with custom dataDir", ver), func() {
|
||||
conf := []byte(fmt.Sprintf(`{
|
||||
"name": "test",
|
||||
"type": "iplink",
|
||||
"cniVersion": "0.4.0",
|
||||
"cniVersion": "%s",
|
||||
"mac": "c2:11:22:33:44:77",
|
||||
"promisc": true,
|
||||
"mtu": 4000,
|
||||
@ -1015,7 +777,7 @@ var _ = Describe("tuning plugin", func() {
|
||||
}
|
||||
]
|
||||
}
|
||||
}`)
|
||||
}`, ver))
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
ContainerID: "dummy",
|
||||
@ -1032,7 +794,7 @@ var _ = Describe("tuning plugin", func() {
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
result, err := current.GetResult(r)
|
||||
result, err := types100.GetResult(r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(len(result.Interfaces)).To(Equal(1))
|
||||
@ -1050,12 +812,12 @@ var _ = Describe("tuning plugin", func() {
|
||||
|
||||
Expect("/tmp/tuning-test/dummy_dummy0.json").Should(BeAnExistingFile())
|
||||
|
||||
if testutils.SpecVersionHasCHECK(ver) {
|
||||
n := &TuningConf{}
|
||||
err = json.Unmarshal([]byte(conf), &n)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
cniVersion := "0.4.0"
|
||||
_, confString, err := buildOneConfig("testConfig", cniVersion, n, r)
|
||||
_, confString, err := buildOneConfig("testConfig", ver, n, r)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
args.StdinData = confString
|
||||
@ -1064,6 +826,7 @@ var _ = Describe("tuning plugin", func() {
|
||||
return cmdCheck(args)
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
|
||||
err = testutils.CmdDel(originalNS.Path(),
|
||||
args.ContainerID, "", func() error { return cmdDel(args) })
|
||||
@ -1079,5 +842,5 @@ var _ = Describe("tuning plugin", func() {
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
|
||||
}
|
||||
})
|
||||
|
@ -22,7 +22,7 @@ import (
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/cni/pkg/version"
|
||||
|
||||
"github.com/containernetworking/plugins/pkg/ns"
|
||||
|
@ -20,7 +20,7 @@ import (
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/plugins/pkg/ns"
|
||||
"github.com/containernetworking/plugins/pkg/testutils"
|
||||
|
||||
|
@ -19,11 +19,10 @@ package main
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
current "github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/cni/pkg/version"
|
||||
|
||||
bv "github.com/containernetworking/plugins/pkg/utils/buildversion"
|
||||
@ -33,21 +32,15 @@ import (
|
||||
// is passed in on stdin. Your plugin may wish to expose its functionality via
|
||||
// runtime args, see CONVENTIONS.md in the CNI spec.
|
||||
type PluginConf struct {
|
||||
types.NetConf // You may wish to not nest this type
|
||||
// This embeds the standard NetConf structure which allows your plugin
|
||||
// to more easily parse standard fields like Name, Type, CNIVersion,
|
||||
// and PrevResult.
|
||||
types.NetConf
|
||||
|
||||
RuntimeConfig *struct {
|
||||
SampleConfig map[string]interface{} `json:"sample"`
|
||||
} `json:"runtimeConfig"`
|
||||
|
||||
// This is the previous result, when called in the context of a chained
|
||||
// plugin. Because this plugin supports multiple versions, we'll have to
|
||||
// parse this in two passes. If your plugin is not chained, this can be
|
||||
// removed (though you may wish to error if a non-chainable plugin is
|
||||
// chained.
|
||||
// If you need to modify the result before returning it, you will need
|
||||
// to actually convert it to a concrete versioned struct.
|
||||
RawPrevResult *map[string]interface{} `json:"prevResult"`
|
||||
PrevResult *current.Result `json:"-"`
|
||||
|
||||
// Add plugin-specifc flags here
|
||||
MyAwesomeFlag bool `json:"myAwesomeFlag"`
|
||||
AnotherAwesomeArg string `json:"anotherAwesomeArg"`
|
||||
@ -61,22 +54,13 @@ func parseConfig(stdin []byte) (*PluginConf, error) {
|
||||
return nil, fmt.Errorf("failed to parse network configuration: %v", err)
|
||||
}
|
||||
|
||||
// Parse previous result. Remove this if your plugin is not chained.
|
||||
if conf.RawPrevResult != nil {
|
||||
resultBytes, err := json.Marshal(conf.RawPrevResult)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not serialize prevResult: %v", err)
|
||||
}
|
||||
res, err := version.NewResult(conf.CNIVersion, resultBytes)
|
||||
if err != nil {
|
||||
// Parse previous result. This will parse, validate, and place the
|
||||
// previous result object into conf.PrevResult. If you need to modify
|
||||
// or inspect the PrevResult you will need to convert it to a concrete
|
||||
// versioned Result struct.
|
||||
if err := version.ParsePrevResult(&conf.NetConf); err != nil {
|
||||
return nil, fmt.Errorf("could not parse prevResult: %v", err)
|
||||
}
|
||||
conf.RawPrevResult = nil
|
||||
conf.PrevResult, err = current.NewResultFromResult(res)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not convert result to current version: %v", err)
|
||||
}
|
||||
}
|
||||
// End previous result parsing
|
||||
|
||||
// Do any validation here
|
||||
@ -94,50 +78,62 @@ func cmdAdd(args *skel.CmdArgs) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Remove this if this is an "originating" plugin
|
||||
// A plugin can be either an "originating" plugin or a "chained" plugin.
|
||||
// Originating plugins perform initial sandbox setup and do not require
|
||||
// any result from a previous plugin in the chain. A chained plugin
|
||||
// modifies sandbox configuration that was previously set up by an
|
||||
// originating plugin and may optionally require a PrevResult from
|
||||
// earlier plugins in the chain.
|
||||
|
||||
// START chained plugin code
|
||||
if conf.PrevResult == nil {
|
||||
return fmt.Errorf("must be called as chained plugin")
|
||||
}
|
||||
|
||||
// Uncomment if this is an "originating" plugin
|
||||
// Convert the PrevResult to a concrete Result type that can be modified.
|
||||
prevResult, err := current.GetResult(conf.PrevResult)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to convert prevResult: %v", err)
|
||||
}
|
||||
|
||||
//if conf.PrevResult != nil {
|
||||
if len(prevResult.IPs) == 0 {
|
||||
return fmt.Errorf("got no container IPs")
|
||||
}
|
||||
|
||||
// Pass the prevResult through this plugin to the next one
|
||||
result := prevResult
|
||||
|
||||
// END chained plugin code
|
||||
|
||||
// START originating plugin code
|
||||
// if conf.PrevResult != nil {
|
||||
// return fmt.Errorf("must be called as the first plugin")
|
||||
// }
|
||||
|
||||
// This is some sample code to generate the list of container-side IPs.
|
||||
// We're casting the prevResult to a 0.3.0 response, which can also include
|
||||
// host-side IPs (but doesn't when converted from a 0.2.0 response).
|
||||
//
|
||||
// You don't need this if you are writing an "originating" plugin.
|
||||
containerIPs := make([]net.IP, 0, len(conf.PrevResult.IPs))
|
||||
if conf.CNIVersion != "0.3.0" {
|
||||
for _, ip := range conf.PrevResult.IPs {
|
||||
containerIPs = append(containerIPs, ip.Address.IP)
|
||||
}
|
||||
} else {
|
||||
for _, ip := range conf.PrevResult.IPs {
|
||||
if ip.Interface == nil {
|
||||
continue
|
||||
}
|
||||
intIdx := *ip.Interface
|
||||
// Every IP is indexed in to the interfaces array, with "-1" standing
|
||||
// for an unknown interface (which we'll assume to be Container-side
|
||||
// Skip all IPs we know belong to an interface with the wrong name.
|
||||
if intIdx >= 0 && intIdx < len(conf.PrevResult.Interfaces) && conf.PrevResult.Interfaces[intIdx].Name != args.IfName {
|
||||
continue
|
||||
}
|
||||
containerIPs = append(containerIPs, ip.Address.IP)
|
||||
}
|
||||
}
|
||||
if len(containerIPs) == 0 {
|
||||
return fmt.Errorf("got no container IPs")
|
||||
}
|
||||
// Generate some fake container IPs and add to the result
|
||||
// result := ¤t.Result{CNIVersion: current.ImplementedSpecVersion}
|
||||
// result.Interfaces = []*current.Interface{
|
||||
// {
|
||||
// Name: "intf0",
|
||||
// Sandbox: args.Netns,
|
||||
// Mac: "00:11:22:33:44:55",
|
||||
// },
|
||||
// }
|
||||
// result.IPs = []*current.IPConfig{
|
||||
// {
|
||||
// Address: "1.2.3.4/24",
|
||||
// Gateway: "1.2.3.1",
|
||||
// // Interface is an index into the Interfaces array
|
||||
// // of the Interface element this IP applies to
|
||||
// Interface: current.Int(0),
|
||||
// }
|
||||
// }
|
||||
// END originating plugin code
|
||||
|
||||
// Implement your plugin here
|
||||
|
||||
// Pass through the result for the next plugin
|
||||
return types.PrintResult(conf.PrevResult, conf.CNIVersion)
|
||||
return types.PrintResult(result, conf.CNIVersion)
|
||||
}
|
||||
|
||||
// cmdDel is called for DELETE requests
|
||||
|
@ -45,6 +45,7 @@ var _ = Describe("sample test", func() {
|
||||
"type": "sample",
|
||||
"anotherAwesomeArg": "awesome",
|
||||
"prevResult": {
|
||||
"cniVersion": "0.3.0",
|
||||
"interfaces": [
|
||||
{
|
||||
"name": "%s",
|
||||
@ -71,7 +72,6 @@ var _ = Describe("sample test", func() {
|
||||
}
|
||||
_, _, err := testutils.CmdAddWithArgs(args, func() error { return cmdAdd(args) })
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
})
|
||||
|
||||
It("fails an invalid config", func() {
|
||||
@ -106,22 +106,14 @@ var _ = Describe("sample test", func() {
|
||||
}
|
||||
_, _, err := testutils.CmdAddWithArgs(args, func() error { return cmdAdd(args) })
|
||||
Expect(err).To(MatchError("anotherAwesomeArg must be specified"))
|
||||
|
||||
})
|
||||
|
||||
It("works with a 0.2.0 config", func() {
|
||||
It("fails with CNI spec versions that don't support plugin chaining", func() {
|
||||
conf := `{
|
||||
"cniVersion": "0.2.0",
|
||||
"name": "cni-plugin-sample-test",
|
||||
"type": "sample",
|
||||
"anotherAwesomeArg": "foo",
|
||||
"prevResult": {
|
||||
"ip4": {
|
||||
"ip": "10.0.0.2/24",
|
||||
"gateway": "10.0.0.1",
|
||||
"routes": []
|
||||
}
|
||||
}
|
||||
"anotherAwesomeArg": "foo"
|
||||
}`
|
||||
|
||||
args := &skel.CmdArgs{
|
||||
@ -131,8 +123,7 @@ var _ = Describe("sample test", func() {
|
||||
StdinData: []byte(conf),
|
||||
}
|
||||
_, _, err := testutils.CmdAddWithArgs(args, func() error { return cmdAdd(args) })
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(err).To(MatchError("must be called as chained plugin"))
|
||||
})
|
||||
|
||||
})
|
||||
|
80
vendor/github.com/containernetworking/cni/pkg/types/020/types.go
generated
vendored
80
vendor/github.com/containernetworking/cni/pkg/types/020/types.go
generated
vendored
@ -22,25 +22,44 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
convert "github.com/containernetworking/cni/pkg/types/internal"
|
||||
)
|
||||
|
||||
const ImplementedSpecVersion string = "0.2.0"
|
||||
|
||||
var SupportedVersions = []string{"", "0.1.0", ImplementedSpecVersion}
|
||||
var supportedVersions = []string{"", "0.1.0", ImplementedSpecVersion}
|
||||
|
||||
// Register converters for all versions less than the implemented spec version
|
||||
func init() {
|
||||
convert.RegisterConverter("0.1.0", []string{ImplementedSpecVersion}, convertFrom010)
|
||||
convert.RegisterConverter(ImplementedSpecVersion, []string{"0.1.0"}, convertTo010)
|
||||
|
||||
// Creator
|
||||
convert.RegisterCreator(supportedVersions, NewResult)
|
||||
}
|
||||
|
||||
// Compatibility types for CNI version 0.1.0 and 0.2.0
|
||||
|
||||
// NewResult creates a new Result object from JSON data. The JSON data
|
||||
// must be compatible with the CNI versions implemented by this type.
|
||||
func NewResult(data []byte) (types.Result, error) {
|
||||
result := &Result{}
|
||||
if err := json.Unmarshal(data, result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, v := range supportedVersions {
|
||||
if result.CNIVersion == v {
|
||||
return result, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("result type supports %v but unmarshalled CNIVersion is %q",
|
||||
supportedVersions, result.CNIVersion)
|
||||
}
|
||||
|
||||
// GetResult converts the given Result object to the ImplementedSpecVersion
|
||||
// and returns the concrete type or an error
|
||||
func GetResult(r types.Result) (*Result, error) {
|
||||
// We expect version 0.1.0/0.2.0 results
|
||||
result020, err := r.GetAsVersion(ImplementedSpecVersion)
|
||||
result020, err := convert.Convert(r, ImplementedSpecVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -51,6 +70,32 @@ func GetResult(r types.Result) (*Result, error) {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func convertFrom010(from types.Result, toVersion string) (types.Result, error) {
|
||||
if toVersion != "0.2.0" {
|
||||
panic("only converts to version 0.2.0")
|
||||
}
|
||||
fromResult := from.(*Result)
|
||||
return &Result{
|
||||
CNIVersion: ImplementedSpecVersion,
|
||||
IP4: fromResult.IP4.Copy(),
|
||||
IP6: fromResult.IP6.Copy(),
|
||||
DNS: *fromResult.DNS.Copy(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func convertTo010(from types.Result, toVersion string) (types.Result, error) {
|
||||
if toVersion != "0.1.0" {
|
||||
panic("only converts to version 0.1.0")
|
||||
}
|
||||
fromResult := from.(*Result)
|
||||
return &Result{
|
||||
CNIVersion: "0.1.0",
|
||||
IP4: fromResult.IP4.Copy(),
|
||||
IP6: fromResult.IP6.Copy(),
|
||||
DNS: *fromResult.DNS.Copy(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Result is what gets returned from the plugin (via stdout) to the caller
|
||||
type Result struct {
|
||||
CNIVersion string `json:"cniVersion,omitempty"`
|
||||
@ -60,17 +105,16 @@ type Result struct {
|
||||
}
|
||||
|
||||
func (r *Result) Version() string {
|
||||
return ImplementedSpecVersion
|
||||
return r.CNIVersion
|
||||
}
|
||||
|
||||
func (r *Result) GetAsVersion(version string) (types.Result, error) {
|
||||
for _, supportedVersion := range SupportedVersions {
|
||||
if version == supportedVersion {
|
||||
r.CNIVersion = version
|
||||
return r, nil
|
||||
// If the creator of the result did not set the CNIVersion, assume it
|
||||
// should be the highest spec version implemented by this Result
|
||||
if r.CNIVersion == "" {
|
||||
r.CNIVersion = ImplementedSpecVersion
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("cannot convert version %q to %s", SupportedVersions, version)
|
||||
return convert.Convert(r, version)
|
||||
}
|
||||
|
||||
func (r *Result) Print() error {
|
||||
@ -93,6 +137,22 @@ type IPConfig struct {
|
||||
Routes []types.Route
|
||||
}
|
||||
|
||||
func (i *IPConfig) Copy() *IPConfig {
|
||||
if i == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var routes []types.Route
|
||||
for _, fromRoute := range i.Routes {
|
||||
routes = append(routes, *fromRoute.Copy())
|
||||
}
|
||||
return &IPConfig{
|
||||
IP: i.IP,
|
||||
Gateway: i.Gateway,
|
||||
Routes: routes,
|
||||
}
|
||||
}
|
||||
|
||||
// net.IPNet is not JSON (un)marshallable so this duality is needed
|
||||
// for our custom IPNet type
|
||||
|
||||
|
305
vendor/github.com/containernetworking/cni/pkg/types/040/types.go
generated
vendored
Normal file
305
vendor/github.com/containernetworking/cni/pkg/types/040/types.go
generated
vendored
Normal file
@ -0,0 +1,305 @@
|
||||
// Copyright 2016 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package types040
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
types020 "github.com/containernetworking/cni/pkg/types/020"
|
||||
convert "github.com/containernetworking/cni/pkg/types/internal"
|
||||
)
|
||||
|
||||
const ImplementedSpecVersion string = "0.4.0"
|
||||
|
||||
var supportedVersions = []string{"0.3.0", "0.3.1", ImplementedSpecVersion}
|
||||
|
||||
// Register converters for all versions less than the implemented spec version
|
||||
func init() {
|
||||
// Up-converters
|
||||
convert.RegisterConverter("0.1.0", supportedVersions, convertFrom02x)
|
||||
convert.RegisterConverter("0.2.0", supportedVersions, convertFrom02x)
|
||||
convert.RegisterConverter("0.3.0", supportedVersions, convertInternal)
|
||||
convert.RegisterConverter("0.3.1", supportedVersions, convertInternal)
|
||||
|
||||
// Down-converters
|
||||
convert.RegisterConverter("0.4.0", []string{"0.3.0", "0.3.1"}, convertInternal)
|
||||
convert.RegisterConverter("0.4.0", []string{"0.1.0", "0.2.0"}, convertTo02x)
|
||||
convert.RegisterConverter("0.3.1", []string{"0.1.0", "0.2.0"}, convertTo02x)
|
||||
convert.RegisterConverter("0.3.0", []string{"0.1.0", "0.2.0"}, convertTo02x)
|
||||
|
||||
// Creator
|
||||
convert.RegisterCreator(supportedVersions, NewResult)
|
||||
}
|
||||
|
||||
func NewResult(data []byte) (types.Result, error) {
|
||||
result := &Result{}
|
||||
if err := json.Unmarshal(data, result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, v := range supportedVersions {
|
||||
if result.CNIVersion == v {
|
||||
return result, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("result type supports %v but unmarshalled CNIVersion is %q",
|
||||
supportedVersions, result.CNIVersion)
|
||||
}
|
||||
|
||||
func GetResult(r types.Result) (*Result, error) {
|
||||
resultCurrent, err := r.GetAsVersion(ImplementedSpecVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result, ok := resultCurrent.(*Result)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("failed to convert result")
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func NewResultFromResult(result types.Result) (*Result, error) {
|
||||
newResult, err := convert.Convert(result, ImplementedSpecVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return newResult.(*Result), nil
|
||||
}
|
||||
|
||||
// Result is what gets returned from the plugin (via stdout) to the caller
|
||||
type Result struct {
|
||||
CNIVersion string `json:"cniVersion,omitempty"`
|
||||
Interfaces []*Interface `json:"interfaces,omitempty"`
|
||||
IPs []*IPConfig `json:"ips,omitempty"`
|
||||
Routes []*types.Route `json:"routes,omitempty"`
|
||||
DNS types.DNS `json:"dns,omitempty"`
|
||||
}
|
||||
|
||||
func convert020IPConfig(from *types020.IPConfig, ipVersion string) *IPConfig {
|
||||
return &IPConfig{
|
||||
Version: ipVersion,
|
||||
Address: from.IP,
|
||||
Gateway: from.Gateway,
|
||||
}
|
||||
}
|
||||
|
||||
func convertFrom02x(from types.Result, toVersion string) (types.Result, error) {
|
||||
fromResult := from.(*types020.Result)
|
||||
toResult := &Result{
|
||||
CNIVersion: toVersion,
|
||||
DNS: *fromResult.DNS.Copy(),
|
||||
Routes: []*types.Route{},
|
||||
}
|
||||
if fromResult.IP4 != nil {
|
||||
toResult.IPs = append(toResult.IPs, convert020IPConfig(fromResult.IP4, "4"))
|
||||
for _, fromRoute := range fromResult.IP4.Routes {
|
||||
toResult.Routes = append(toResult.Routes, fromRoute.Copy())
|
||||
}
|
||||
}
|
||||
|
||||
if fromResult.IP6 != nil {
|
||||
toResult.IPs = append(toResult.IPs, convert020IPConfig(fromResult.IP6, "6"))
|
||||
for _, fromRoute := range fromResult.IP6.Routes {
|
||||
toResult.Routes = append(toResult.Routes, fromRoute.Copy())
|
||||
}
|
||||
}
|
||||
|
||||
return toResult, nil
|
||||
}
|
||||
|
||||
func convertInternal(from types.Result, toVersion string) (types.Result, error) {
|
||||
fromResult := from.(*Result)
|
||||
toResult := &Result{
|
||||
CNIVersion: toVersion,
|
||||
DNS: *fromResult.DNS.Copy(),
|
||||
Routes: []*types.Route{},
|
||||
}
|
||||
for _, fromIntf := range fromResult.Interfaces {
|
||||
toResult.Interfaces = append(toResult.Interfaces, fromIntf.Copy())
|
||||
}
|
||||
for _, fromIPC := range fromResult.IPs {
|
||||
toResult.IPs = append(toResult.IPs, fromIPC.Copy())
|
||||
}
|
||||
for _, fromRoute := range fromResult.Routes {
|
||||
toResult.Routes = append(toResult.Routes, fromRoute.Copy())
|
||||
}
|
||||
return toResult, nil
|
||||
}
|
||||
|
||||
func convertTo02x(from types.Result, toVersion string) (types.Result, error) {
|
||||
fromResult := from.(*Result)
|
||||
toResult := &types020.Result{
|
||||
CNIVersion: toVersion,
|
||||
DNS: *fromResult.DNS.Copy(),
|
||||
}
|
||||
|
||||
for _, fromIP := range fromResult.IPs {
|
||||
// Only convert the first IP address of each version as 0.2.0
|
||||
// and earlier cannot handle multiple IP addresses
|
||||
if fromIP.Version == "4" && toResult.IP4 == nil {
|
||||
toResult.IP4 = &types020.IPConfig{
|
||||
IP: fromIP.Address,
|
||||
Gateway: fromIP.Gateway,
|
||||
}
|
||||
} else if fromIP.Version == "6" && toResult.IP6 == nil {
|
||||
toResult.IP6 = &types020.IPConfig{
|
||||
IP: fromIP.Address,
|
||||
Gateway: fromIP.Gateway,
|
||||
}
|
||||
}
|
||||
if toResult.IP4 != nil && toResult.IP6 != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for _, fromRoute := range fromResult.Routes {
|
||||
is4 := fromRoute.Dst.IP.To4() != nil
|
||||
if is4 && toResult.IP4 != nil {
|
||||
toResult.IP4.Routes = append(toResult.IP4.Routes, types.Route{
|
||||
Dst: fromRoute.Dst,
|
||||
GW: fromRoute.GW,
|
||||
})
|
||||
} else if !is4 && toResult.IP6 != nil {
|
||||
toResult.IP6.Routes = append(toResult.IP6.Routes, types.Route{
|
||||
Dst: fromRoute.Dst,
|
||||
GW: fromRoute.GW,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if toResult.IP4 == nil && toResult.IP6 == nil {
|
||||
return nil, fmt.Errorf("cannot convert: no valid IP addresses")
|
||||
}
|
||||
|
||||
return toResult, nil
|
||||
}
|
||||
|
||||
func (r *Result) Version() string {
|
||||
return r.CNIVersion
|
||||
}
|
||||
|
||||
func (r *Result) GetAsVersion(version string) (types.Result, error) {
|
||||
// If the creator of the result did not set the CNIVersion, assume it
|
||||
// should be the highest spec version implemented by this Result
|
||||
if r.CNIVersion == "" {
|
||||
r.CNIVersion = ImplementedSpecVersion
|
||||
}
|
||||
return convert.Convert(r, version)
|
||||
}
|
||||
|
||||
func (r *Result) Print() error {
|
||||
return r.PrintTo(os.Stdout)
|
||||
}
|
||||
|
||||
func (r *Result) PrintTo(writer io.Writer) error {
|
||||
data, err := json.MarshalIndent(r, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = writer.Write(data)
|
||||
return err
|
||||
}
|
||||
|
||||
// Interface contains values about the created interfaces
|
||||
type Interface struct {
|
||||
Name string `json:"name"`
|
||||
Mac string `json:"mac,omitempty"`
|
||||
Sandbox string `json:"sandbox,omitempty"`
|
||||
}
|
||||
|
||||
func (i *Interface) String() string {
|
||||
return fmt.Sprintf("%+v", *i)
|
||||
}
|
||||
|
||||
func (i *Interface) Copy() *Interface {
|
||||
if i == nil {
|
||||
return nil
|
||||
}
|
||||
newIntf := *i
|
||||
return &newIntf
|
||||
}
|
||||
|
||||
// Int returns a pointer to the int value passed in. Used to
|
||||
// set the IPConfig.Interface field.
|
||||
func Int(v int) *int {
|
||||
return &v
|
||||
}
|
||||
|
||||
// IPConfig contains values necessary to configure an IP address on an interface
|
||||
type IPConfig struct {
|
||||
// IP version, either "4" or "6"
|
||||
Version string
|
||||
// Index into Result structs Interfaces list
|
||||
Interface *int
|
||||
Address net.IPNet
|
||||
Gateway net.IP
|
||||
}
|
||||
|
||||
func (i *IPConfig) String() string {
|
||||
return fmt.Sprintf("%+v", *i)
|
||||
}
|
||||
|
||||
func (i *IPConfig) Copy() *IPConfig {
|
||||
if i == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
ipc := &IPConfig{
|
||||
Version: i.Version,
|
||||
Address: i.Address,
|
||||
Gateway: i.Gateway,
|
||||
}
|
||||
if i.Interface != nil {
|
||||
intf := *i.Interface
|
||||
ipc.Interface = &intf
|
||||
}
|
||||
return ipc
|
||||
}
|
||||
|
||||
// JSON (un)marshallable types
|
||||
type ipConfig struct {
|
||||
Version string `json:"version"`
|
||||
Interface *int `json:"interface,omitempty"`
|
||||
Address types.IPNet `json:"address"`
|
||||
Gateway net.IP `json:"gateway,omitempty"`
|
||||
}
|
||||
|
||||
func (c *IPConfig) MarshalJSON() ([]byte, error) {
|
||||
ipc := ipConfig{
|
||||
Version: c.Version,
|
||||
Interface: c.Interface,
|
||||
Address: types.IPNet(c.Address),
|
||||
Gateway: c.Gateway,
|
||||
}
|
||||
|
||||
return json.Marshal(ipc)
|
||||
}
|
||||
|
||||
func (c *IPConfig) UnmarshalJSON(data []byte) error {
|
||||
ipc := ipConfig{}
|
||||
if err := json.Unmarshal(data, &ipc); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.Version = ipc.Version
|
||||
c.Interface = ipc.Interface
|
||||
c.Address = net.IPNet(ipc.Address)
|
||||
c.Gateway = ipc.Gateway
|
||||
return nil
|
||||
}
|
307
vendor/github.com/containernetworking/cni/pkg/types/100/types.go
generated
vendored
Normal file
307
vendor/github.com/containernetworking/cni/pkg/types/100/types.go
generated
vendored
Normal file
@ -0,0 +1,307 @@
|
||||
// Copyright 2016 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package types100
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
types040 "github.com/containernetworking/cni/pkg/types/040"
|
||||
convert "github.com/containernetworking/cni/pkg/types/internal"
|
||||
)
|
||||
|
||||
const ImplementedSpecVersion string = "1.0.0"
|
||||
|
||||
var supportedVersions = []string{ImplementedSpecVersion}
|
||||
|
||||
// Register converters for all versions less than the implemented spec version
|
||||
func init() {
|
||||
// Up-converters
|
||||
convert.RegisterConverter("0.1.0", supportedVersions, convertFrom02x)
|
||||
convert.RegisterConverter("0.2.0", supportedVersions, convertFrom02x)
|
||||
convert.RegisterConverter("0.3.0", supportedVersions, convertFrom04x)
|
||||
convert.RegisterConverter("0.3.1", supportedVersions, convertFrom04x)
|
||||
convert.RegisterConverter("0.4.0", supportedVersions, convertFrom04x)
|
||||
|
||||
// Down-converters
|
||||
convert.RegisterConverter("1.0.0", []string{"0.3.0", "0.3.1", "0.4.0"}, convertTo04x)
|
||||
convert.RegisterConverter("1.0.0", []string{"0.1.0", "0.2.0"}, convertTo02x)
|
||||
|
||||
// Creator
|
||||
convert.RegisterCreator(supportedVersions, NewResult)
|
||||
}
|
||||
|
||||
func NewResult(data []byte) (types.Result, error) {
|
||||
result := &Result{}
|
||||
if err := json.Unmarshal(data, result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, v := range supportedVersions {
|
||||
if result.CNIVersion == v {
|
||||
return result, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("result type supports %v but unmarshalled CNIVersion is %q",
|
||||
supportedVersions, result.CNIVersion)
|
||||
}
|
||||
|
||||
func GetResult(r types.Result) (*Result, error) {
|
||||
resultCurrent, err := r.GetAsVersion(ImplementedSpecVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result, ok := resultCurrent.(*Result)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("failed to convert result")
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func NewResultFromResult(result types.Result) (*Result, error) {
|
||||
newResult, err := convert.Convert(result, ImplementedSpecVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return newResult.(*Result), nil
|
||||
}
|
||||
|
||||
// Result is what gets returned from the plugin (via stdout) to the caller
|
||||
type Result struct {
|
||||
CNIVersion string `json:"cniVersion,omitempty"`
|
||||
Interfaces []*Interface `json:"interfaces,omitempty"`
|
||||
IPs []*IPConfig `json:"ips,omitempty"`
|
||||
Routes []*types.Route `json:"routes,omitempty"`
|
||||
DNS types.DNS `json:"dns,omitempty"`
|
||||
}
|
||||
|
||||
func convertFrom02x(from types.Result, toVersion string) (types.Result, error) {
|
||||
result040, err := convert.Convert(from, "0.4.0")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result100, err := convertFrom04x(result040, ImplementedSpecVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result100, nil
|
||||
}
|
||||
|
||||
func convertIPConfigFrom040(from *types040.IPConfig) *IPConfig {
|
||||
to := &IPConfig{
|
||||
Address: from.Address,
|
||||
Gateway: from.Gateway,
|
||||
}
|
||||
if from.Interface != nil {
|
||||
intf := *from.Interface
|
||||
to.Interface = &intf
|
||||
}
|
||||
return to
|
||||
}
|
||||
|
||||
func convertInterfaceFrom040(from *types040.Interface) *Interface {
|
||||
return &Interface{
|
||||
Name: from.Name,
|
||||
Mac: from.Mac,
|
||||
Sandbox: from.Sandbox,
|
||||
}
|
||||
}
|
||||
|
||||
func convertFrom04x(from types.Result, toVersion string) (types.Result, error) {
|
||||
fromResult := from.(*types040.Result)
|
||||
toResult := &Result{
|
||||
CNIVersion: toVersion,
|
||||
DNS: *fromResult.DNS.Copy(),
|
||||
Routes: []*types.Route{},
|
||||
}
|
||||
for _, fromIntf := range fromResult.Interfaces {
|
||||
toResult.Interfaces = append(toResult.Interfaces, convertInterfaceFrom040(fromIntf))
|
||||
}
|
||||
for _, fromIPC := range fromResult.IPs {
|
||||
toResult.IPs = append(toResult.IPs, convertIPConfigFrom040(fromIPC))
|
||||
}
|
||||
for _, fromRoute := range fromResult.Routes {
|
||||
toResult.Routes = append(toResult.Routes, fromRoute.Copy())
|
||||
}
|
||||
return toResult, nil
|
||||
}
|
||||
|
||||
func convertIPConfigTo040(from *IPConfig) *types040.IPConfig {
|
||||
version := "6"
|
||||
if from.Address.IP.To4() != nil {
|
||||
version = "4"
|
||||
}
|
||||
to := &types040.IPConfig{
|
||||
Version: version,
|
||||
Address: from.Address,
|
||||
Gateway: from.Gateway,
|
||||
}
|
||||
if from.Interface != nil {
|
||||
intf := *from.Interface
|
||||
to.Interface = &intf
|
||||
}
|
||||
return to
|
||||
}
|
||||
|
||||
func convertInterfaceTo040(from *Interface) *types040.Interface {
|
||||
return &types040.Interface{
|
||||
Name: from.Name,
|
||||
Mac: from.Mac,
|
||||
Sandbox: from.Sandbox,
|
||||
}
|
||||
}
|
||||
|
||||
func convertTo04x(from types.Result, toVersion string) (types.Result, error) {
|
||||
fromResult := from.(*Result)
|
||||
toResult := &types040.Result{
|
||||
CNIVersion: toVersion,
|
||||
DNS: *fromResult.DNS.Copy(),
|
||||
Routes: []*types.Route{},
|
||||
}
|
||||
for _, fromIntf := range fromResult.Interfaces {
|
||||
toResult.Interfaces = append(toResult.Interfaces, convertInterfaceTo040(fromIntf))
|
||||
}
|
||||
for _, fromIPC := range fromResult.IPs {
|
||||
toResult.IPs = append(toResult.IPs, convertIPConfigTo040(fromIPC))
|
||||
}
|
||||
for _, fromRoute := range fromResult.Routes {
|
||||
toResult.Routes = append(toResult.Routes, fromRoute.Copy())
|
||||
}
|
||||
return toResult, nil
|
||||
}
|
||||
|
||||
func convertTo02x(from types.Result, toVersion string) (types.Result, error) {
|
||||
// First convert to 0.4.0
|
||||
result040, err := convertTo04x(from, "0.4.0")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result02x, err := convert.Convert(result040, toVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result02x, nil
|
||||
}
|
||||
|
||||
func (r *Result) Version() string {
|
||||
return r.CNIVersion
|
||||
}
|
||||
|
||||
func (r *Result) GetAsVersion(version string) (types.Result, error) {
|
||||
// If the creator of the result did not set the CNIVersion, assume it
|
||||
// should be the highest spec version implemented by this Result
|
||||
if r.CNIVersion == "" {
|
||||
r.CNIVersion = ImplementedSpecVersion
|
||||
}
|
||||
return convert.Convert(r, version)
|
||||
}
|
||||
|
||||
func (r *Result) Print() error {
|
||||
return r.PrintTo(os.Stdout)
|
||||
}
|
||||
|
||||
func (r *Result) PrintTo(writer io.Writer) error {
|
||||
data, err := json.MarshalIndent(r, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = writer.Write(data)
|
||||
return err
|
||||
}
|
||||
|
||||
// Interface contains values about the created interfaces
|
||||
type Interface struct {
|
||||
Name string `json:"name"`
|
||||
Mac string `json:"mac,omitempty"`
|
||||
Sandbox string `json:"sandbox,omitempty"`
|
||||
}
|
||||
|
||||
func (i *Interface) String() string {
|
||||
return fmt.Sprintf("%+v", *i)
|
||||
}
|
||||
|
||||
func (i *Interface) Copy() *Interface {
|
||||
if i == nil {
|
||||
return nil
|
||||
}
|
||||
newIntf := *i
|
||||
return &newIntf
|
||||
}
|
||||
|
||||
// Int returns a pointer to the int value passed in. Used to
|
||||
// set the IPConfig.Interface field.
|
||||
func Int(v int) *int {
|
||||
return &v
|
||||
}
|
||||
|
||||
// IPConfig contains values necessary to configure an IP address on an interface
|
||||
type IPConfig struct {
|
||||
// Index into Result structs Interfaces list
|
||||
Interface *int
|
||||
Address net.IPNet
|
||||
Gateway net.IP
|
||||
}
|
||||
|
||||
func (i *IPConfig) String() string {
|
||||
return fmt.Sprintf("%+v", *i)
|
||||
}
|
||||
|
||||
func (i *IPConfig) Copy() *IPConfig {
|
||||
if i == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
ipc := &IPConfig{
|
||||
Address: i.Address,
|
||||
Gateway: i.Gateway,
|
||||
}
|
||||
if i.Interface != nil {
|
||||
intf := *i.Interface
|
||||
ipc.Interface = &intf
|
||||
}
|
||||
return ipc
|
||||
}
|
||||
|
||||
// JSON (un)marshallable types
|
||||
type ipConfig struct {
|
||||
Interface *int `json:"interface,omitempty"`
|
||||
Address types.IPNet `json:"address"`
|
||||
Gateway net.IP `json:"gateway,omitempty"`
|
||||
}
|
||||
|
||||
func (c *IPConfig) MarshalJSON() ([]byte, error) {
|
||||
ipc := ipConfig{
|
||||
Interface: c.Interface,
|
||||
Address: types.IPNet(c.Address),
|
||||
Gateway: c.Gateway,
|
||||
}
|
||||
|
||||
return json.Marshal(ipc)
|
||||
}
|
||||
|
||||
func (c *IPConfig) UnmarshalJSON(data []byte) error {
|
||||
ipc := ipConfig{}
|
||||
if err := json.Unmarshal(data, &ipc); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.Interface = ipc.Interface
|
||||
c.Address = net.IPNet(ipc.Address)
|
||||
c.Gateway = ipc.Gateway
|
||||
return nil
|
||||
}
|
26
vendor/github.com/containernetworking/cni/pkg/types/create/create.go
generated
vendored
Normal file
26
vendor/github.com/containernetworking/cni/pkg/types/create/create.go
generated
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2016 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package create
|
||||
|
||||
import (
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
convert "github.com/containernetworking/cni/pkg/types/internal"
|
||||
)
|
||||
|
||||
// Create creates a CNI Result using the given JSON, or an error if the creation
|
||||
// could not be performed
|
||||
func Create(version string, bytes []byte) (types.Result, error) {
|
||||
return convert.Create(version, bytes)
|
||||
}
|
276
vendor/github.com/containernetworking/cni/pkg/types/current/types.go
generated
vendored
276
vendor/github.com/containernetworking/cni/pkg/types/current/types.go
generated
vendored
@ -1,276 +0,0 @@
|
||||
// Copyright 2016 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package current
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/020"
|
||||
)
|
||||
|
||||
const ImplementedSpecVersion string = "0.4.0"
|
||||
|
||||
var SupportedVersions = []string{"0.3.0", "0.3.1", ImplementedSpecVersion}
|
||||
|
||||
func NewResult(data []byte) (types.Result, error) {
|
||||
result := &Result{}
|
||||
if err := json.Unmarshal(data, result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func GetResult(r types.Result) (*Result, error) {
|
||||
resultCurrent, err := r.GetAsVersion(ImplementedSpecVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result, ok := resultCurrent.(*Result)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("failed to convert result")
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
var resultConverters = []struct {
|
||||
versions []string
|
||||
convert func(types.Result) (*Result, error)
|
||||
}{
|
||||
{types020.SupportedVersions, convertFrom020},
|
||||
{SupportedVersions, convertFrom030},
|
||||
}
|
||||
|
||||
func convertFrom020(result types.Result) (*Result, error) {
|
||||
oldResult, err := types020.GetResult(result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newResult := &Result{
|
||||
CNIVersion: ImplementedSpecVersion,
|
||||
DNS: oldResult.DNS,
|
||||
Routes: []*types.Route{},
|
||||
}
|
||||
|
||||
if oldResult.IP4 != nil {
|
||||
newResult.IPs = append(newResult.IPs, &IPConfig{
|
||||
Version: "4",
|
||||
Address: oldResult.IP4.IP,
|
||||
Gateway: oldResult.IP4.Gateway,
|
||||
})
|
||||
for _, route := range oldResult.IP4.Routes {
|
||||
newResult.Routes = append(newResult.Routes, &types.Route{
|
||||
Dst: route.Dst,
|
||||
GW: route.GW,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if oldResult.IP6 != nil {
|
||||
newResult.IPs = append(newResult.IPs, &IPConfig{
|
||||
Version: "6",
|
||||
Address: oldResult.IP6.IP,
|
||||
Gateway: oldResult.IP6.Gateway,
|
||||
})
|
||||
for _, route := range oldResult.IP6.Routes {
|
||||
newResult.Routes = append(newResult.Routes, &types.Route{
|
||||
Dst: route.Dst,
|
||||
GW: route.GW,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return newResult, nil
|
||||
}
|
||||
|
||||
func convertFrom030(result types.Result) (*Result, error) {
|
||||
newResult, ok := result.(*Result)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("failed to convert result")
|
||||
}
|
||||
newResult.CNIVersion = ImplementedSpecVersion
|
||||
return newResult, nil
|
||||
}
|
||||
|
||||
func NewResultFromResult(result types.Result) (*Result, error) {
|
||||
version := result.Version()
|
||||
for _, converter := range resultConverters {
|
||||
for _, supportedVersion := range converter.versions {
|
||||
if version == supportedVersion {
|
||||
return converter.convert(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("unsupported CNI result22 version %q", version)
|
||||
}
|
||||
|
||||
// Result is what gets returned from the plugin (via stdout) to the caller
|
||||
type Result struct {
|
||||
CNIVersion string `json:"cniVersion,omitempty"`
|
||||
Interfaces []*Interface `json:"interfaces,omitempty"`
|
||||
IPs []*IPConfig `json:"ips,omitempty"`
|
||||
Routes []*types.Route `json:"routes,omitempty"`
|
||||
DNS types.DNS `json:"dns,omitempty"`
|
||||
}
|
||||
|
||||
// Convert to the older 0.2.0 CNI spec Result type
|
||||
func (r *Result) convertTo020() (*types020.Result, error) {
|
||||
oldResult := &types020.Result{
|
||||
CNIVersion: types020.ImplementedSpecVersion,
|
||||
DNS: r.DNS,
|
||||
}
|
||||
|
||||
for _, ip := range r.IPs {
|
||||
// Only convert the first IP address of each version as 0.2.0
|
||||
// and earlier cannot handle multiple IP addresses
|
||||
if ip.Version == "4" && oldResult.IP4 == nil {
|
||||
oldResult.IP4 = &types020.IPConfig{
|
||||
IP: ip.Address,
|
||||
Gateway: ip.Gateway,
|
||||
}
|
||||
} else if ip.Version == "6" && oldResult.IP6 == nil {
|
||||
oldResult.IP6 = &types020.IPConfig{
|
||||
IP: ip.Address,
|
||||
Gateway: ip.Gateway,
|
||||
}
|
||||
}
|
||||
|
||||
if oldResult.IP4 != nil && oldResult.IP6 != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for _, route := range r.Routes {
|
||||
is4 := route.Dst.IP.To4() != nil
|
||||
if is4 && oldResult.IP4 != nil {
|
||||
oldResult.IP4.Routes = append(oldResult.IP4.Routes, types.Route{
|
||||
Dst: route.Dst,
|
||||
GW: route.GW,
|
||||
})
|
||||
} else if !is4 && oldResult.IP6 != nil {
|
||||
oldResult.IP6.Routes = append(oldResult.IP6.Routes, types.Route{
|
||||
Dst: route.Dst,
|
||||
GW: route.GW,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if oldResult.IP4 == nil && oldResult.IP6 == nil {
|
||||
return nil, fmt.Errorf("cannot convert: no valid IP addresses")
|
||||
}
|
||||
|
||||
return oldResult, nil
|
||||
}
|
||||
|
||||
func (r *Result) Version() string {
|
||||
return ImplementedSpecVersion
|
||||
}
|
||||
|
||||
func (r *Result) GetAsVersion(version string) (types.Result, error) {
|
||||
switch version {
|
||||
case "0.3.0", "0.3.1", ImplementedSpecVersion:
|
||||
r.CNIVersion = version
|
||||
return r, nil
|
||||
case types020.SupportedVersions[0], types020.SupportedVersions[1], types020.SupportedVersions[2]:
|
||||
return r.convertTo020()
|
||||
}
|
||||
return nil, fmt.Errorf("cannot convert version 0.3.x to %q", version)
|
||||
}
|
||||
|
||||
func (r *Result) Print() error {
|
||||
return r.PrintTo(os.Stdout)
|
||||
}
|
||||
|
||||
func (r *Result) PrintTo(writer io.Writer) error {
|
||||
data, err := json.MarshalIndent(r, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = writer.Write(data)
|
||||
return err
|
||||
}
|
||||
|
||||
// Convert this old version result to the current CNI version result
|
||||
func (r *Result) Convert() (*Result, error) {
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// Interface contains values about the created interfaces
|
||||
type Interface struct {
|
||||
Name string `json:"name"`
|
||||
Mac string `json:"mac,omitempty"`
|
||||
Sandbox string `json:"sandbox,omitempty"`
|
||||
}
|
||||
|
||||
func (i *Interface) String() string {
|
||||
return fmt.Sprintf("%+v", *i)
|
||||
}
|
||||
|
||||
// Int returns a pointer to the int value passed in. Used to
|
||||
// set the IPConfig.Interface field.
|
||||
func Int(v int) *int {
|
||||
return &v
|
||||
}
|
||||
|
||||
// IPConfig contains values necessary to configure an IP address on an interface
|
||||
type IPConfig struct {
|
||||
// IP version, either "4" or "6"
|
||||
Version string
|
||||
// Index into Result structs Interfaces list
|
||||
Interface *int
|
||||
Address net.IPNet
|
||||
Gateway net.IP
|
||||
}
|
||||
|
||||
func (i *IPConfig) String() string {
|
||||
return fmt.Sprintf("%+v", *i)
|
||||
}
|
||||
|
||||
// JSON (un)marshallable types
|
||||
type ipConfig struct {
|
||||
Version string `json:"version"`
|
||||
Interface *int `json:"interface,omitempty"`
|
||||
Address types.IPNet `json:"address"`
|
||||
Gateway net.IP `json:"gateway,omitempty"`
|
||||
}
|
||||
|
||||
func (c *IPConfig) MarshalJSON() ([]byte, error) {
|
||||
ipc := ipConfig{
|
||||
Version: c.Version,
|
||||
Interface: c.Interface,
|
||||
Address: types.IPNet(c.Address),
|
||||
Gateway: c.Gateway,
|
||||
}
|
||||
|
||||
return json.Marshal(ipc)
|
||||
}
|
||||
|
||||
func (c *IPConfig) UnmarshalJSON(data []byte) error {
|
||||
ipc := ipConfig{}
|
||||
if err := json.Unmarshal(data, &ipc); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.Version = ipc.Version
|
||||
c.Interface = ipc.Interface
|
||||
c.Address = net.IPNet(ipc.Address)
|
||||
c.Gateway = ipc.Gateway
|
||||
return nil
|
||||
}
|
88
vendor/github.com/containernetworking/cni/pkg/types/internal/convert.go
generated
vendored
Normal file
88
vendor/github.com/containernetworking/cni/pkg/types/internal/convert.go
generated
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
// Copyright 2016 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package convert
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
)
|
||||
|
||||
// ConvertFn should convert from the given arbitrary Result type into a
|
||||
// Result implementing CNI specification version passed in toVersion.
|
||||
// The function is guaranteed to be passed a Result type matching the
|
||||
// fromVersion it was registered with, and is guaranteed to be
|
||||
// passed a toVersion matching one of the toVersions it was registered with.
|
||||
type ConvertFn func(from types.Result, toVersion string) (types.Result, error)
|
||||
|
||||
type converter struct {
|
||||
// fromVersion is the CNI Result spec version that convertFn accepts
|
||||
fromVersion string
|
||||
// toVersions is a list of versions that convertFn can convert to
|
||||
toVersions []string
|
||||
convertFn ConvertFn
|
||||
}
|
||||
|
||||
var converters []*converter
|
||||
|
||||
func findConverter(fromVersion, toVersion string) *converter {
|
||||
for _, c := range converters {
|
||||
if c.fromVersion == fromVersion {
|
||||
for _, v := range c.toVersions {
|
||||
if v == toVersion {
|
||||
return c
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert converts a CNI Result to the requested CNI specification version,
|
||||
// or returns an error if the converstion could not be performed or failed
|
||||
func Convert(from types.Result, toVersion string) (types.Result, error) {
|
||||
fromVersion := from.Version()
|
||||
|
||||
// Shortcut for same version
|
||||
if fromVersion == toVersion {
|
||||
return from, nil
|
||||
}
|
||||
|
||||
// Otherwise find the right converter
|
||||
c := findConverter(fromVersion, toVersion)
|
||||
if c == nil {
|
||||
return nil, fmt.Errorf("no converter for CNI result version %s to %s",
|
||||
fromVersion, toVersion)
|
||||
}
|
||||
return c.convertFn(from, toVersion)
|
||||
}
|
||||
|
||||
// RegisterConverter registers a CNI Result converter. SHOULD NOT BE CALLED
|
||||
// EXCEPT FROM CNI ITSELF.
|
||||
func RegisterConverter(fromVersion string, toVersions []string, convertFn ConvertFn) {
|
||||
// Make sure there is no converter already registered for these
|
||||
// from and to versions
|
||||
for _, v := range toVersions {
|
||||
if findConverter(fromVersion, v) != nil {
|
||||
panic(fmt.Sprintf("converter already registered for %s to %s",
|
||||
fromVersion, v))
|
||||
}
|
||||
}
|
||||
converters = append(converters, &converter{
|
||||
fromVersion: fromVersion,
|
||||
toVersions: toVersions,
|
||||
convertFn: convertFn,
|
||||
})
|
||||
}
|
66
vendor/github.com/containernetworking/cni/pkg/types/internal/create.go
generated
vendored
Normal file
66
vendor/github.com/containernetworking/cni/pkg/types/internal/create.go
generated
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
// Copyright 2016 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package convert
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
)
|
||||
|
||||
type ResultFactoryFunc func([]byte) (types.Result, error)
|
||||
|
||||
type creator struct {
|
||||
// CNI Result spec versions that createFn can create a Result for
|
||||
versions []string
|
||||
createFn ResultFactoryFunc
|
||||
}
|
||||
|
||||
var creators []*creator
|
||||
|
||||
func findCreator(version string) *creator {
|
||||
for _, c := range creators {
|
||||
for _, v := range c.versions {
|
||||
if v == version {
|
||||
return c
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create creates a CNI Result using the given JSON, or an error if the creation
|
||||
// could not be performed
|
||||
func Create(version string, bytes []byte) (types.Result, error) {
|
||||
if c := findCreator(version); c != nil {
|
||||
return c.createFn(bytes)
|
||||
}
|
||||
return nil, fmt.Errorf("unsupported CNI result version %q", version)
|
||||
}
|
||||
|
||||
// RegisterCreator registers a CNI Result creator. SHOULD NOT BE CALLED
|
||||
// EXCEPT FROM CNI ITSELF.
|
||||
func RegisterCreator(versions []string, createFn ResultFactoryFunc) {
|
||||
// Make sure there is no creator already registered for these versions
|
||||
for _, v := range versions {
|
||||
if findCreator(v) != nil {
|
||||
panic(fmt.Sprintf("creator already registered for %s", v))
|
||||
}
|
||||
}
|
||||
creators = append(creators, &creator{
|
||||
versions: versions,
|
||||
createFn: createFn,
|
||||
})
|
||||
}
|
31
vendor/github.com/containernetworking/cni/pkg/types/types.go
generated
vendored
31
vendor/github.com/containernetworking/cni/pkg/types/types.go
generated
vendored
@ -83,8 +83,6 @@ type NetConfList struct {
|
||||
Plugins []*NetConf `json:"plugins,omitempty"`
|
||||
}
|
||||
|
||||
type ResultFactoryFunc func([]byte) (Result, error)
|
||||
|
||||
// Result is an interface that provides the result of plugin execution
|
||||
type Result interface {
|
||||
// The highest CNI specification result version the result supports
|
||||
@ -118,6 +116,24 @@ type DNS struct {
|
||||
Options []string `json:"options,omitempty"`
|
||||
}
|
||||
|
||||
func (d *DNS) Copy() *DNS {
|
||||
if d == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
to := &DNS{Domain: d.Domain}
|
||||
for _, ns := range d.Nameservers {
|
||||
to.Nameservers = append(to.Nameservers, ns)
|
||||
}
|
||||
for _, s := range d.Search {
|
||||
to.Search = append(to.Search, s)
|
||||
}
|
||||
for _, o := range d.Options {
|
||||
to.Options = append(to.Options, o)
|
||||
}
|
||||
return to
|
||||
}
|
||||
|
||||
type Route struct {
|
||||
Dst net.IPNet
|
||||
GW net.IP
|
||||
@ -127,6 +143,17 @@ func (r *Route) String() string {
|
||||
return fmt.Sprintf("%+v", *r)
|
||||
}
|
||||
|
||||
func (r *Route) Copy() *Route {
|
||||
if r == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &Route{
|
||||
Dst: r.Dst,
|
||||
GW: r.GW,
|
||||
}
|
||||
}
|
||||
|
||||
// Well known error codes
|
||||
// see https://github.com/containernetworking/cni/blob/master/SPEC.md#well-known-error-codes
|
||||
const (
|
||||
|
34
vendor/github.com/containernetworking/cni/pkg/version/version.go
generated
vendored
34
vendor/github.com/containernetworking/cni/pkg/version/version.go
generated
vendored
@ -19,13 +19,13 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/020"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
"github.com/containernetworking/cni/pkg/types/100"
|
||||
"github.com/containernetworking/cni/pkg/types/create"
|
||||
)
|
||||
|
||||
// Current reports the version of the CNI spec implemented by this library
|
||||
func Current() string {
|
||||
return "0.4.0"
|
||||
return types100.ImplementedSpecVersion
|
||||
}
|
||||
|
||||
// Legacy PluginInfo describes a plugin that is backwards compatible with the
|
||||
@ -36,29 +36,12 @@ func Current() string {
|
||||
// Any future CNI spec versions which meet this definition should be added to
|
||||
// this list.
|
||||
var Legacy = PluginSupports("0.1.0", "0.2.0")
|
||||
var All = PluginSupports("0.1.0", "0.2.0", "0.3.0", "0.3.1", "0.4.0")
|
||||
|
||||
var resultFactories = []struct {
|
||||
supportedVersions []string
|
||||
newResult types.ResultFactoryFunc
|
||||
}{
|
||||
{current.SupportedVersions, current.NewResult},
|
||||
{types020.SupportedVersions, types020.NewResult},
|
||||
}
|
||||
var All = PluginSupports("0.1.0", "0.2.0", "0.3.0", "0.3.1", "0.4.0", "1.0.0")
|
||||
|
||||
// Finds a Result object matching the requested version (if any) and asks
|
||||
// that object to parse the plugin result, returning an error if parsing failed.
|
||||
func NewResult(version string, resultBytes []byte) (types.Result, error) {
|
||||
reconciler := &Reconciler{}
|
||||
for _, resultFactory := range resultFactories {
|
||||
err := reconciler.CheckRaw(version, resultFactory.supportedVersions)
|
||||
if err == nil {
|
||||
// Result supports this version
|
||||
return resultFactory.newResult(resultBytes)
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("unsupported CNI result version %q", version)
|
||||
return create.Create(version, resultBytes)
|
||||
}
|
||||
|
||||
// ParsePrevResult parses a prevResult in a NetConf structure and sets
|
||||
@ -68,6 +51,13 @@ func ParsePrevResult(conf *types.NetConf) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Prior to 1.0.0, Result types may not marshal a CNIVersion. Since the
|
||||
// result version must match the config version, if the Result's version
|
||||
// is empty, inject the config version.
|
||||
if ver, ok := conf.RawPrevResult["CNIVersion"]; !ok || ver == "" {
|
||||
conf.RawPrevResult["CNIVersion"] = conf.CNIVersion
|
||||
}
|
||||
|
||||
resultBytes, err := json.Marshal(conf.RawPrevResult)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not serialize prevResult: %v", err)
|
||||
|
9
vendor/github.com/fsnotify/fsnotify/.editorconfig
generated
vendored
9
vendor/github.com/fsnotify/fsnotify/.editorconfig
generated
vendored
@ -1,5 +1,12 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
[*.go]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
insert_final_newline = true
|
||||
|
||||
[*.{yml,yaml}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
1
vendor/github.com/fsnotify/fsnotify/.gitattributes
generated
vendored
Normal file
1
vendor/github.com/fsnotify/fsnotify/.gitattributes
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
go.sum linguist-generated
|
20
vendor/github.com/fsnotify/fsnotify/.travis.yml
generated
vendored
20
vendor/github.com/fsnotify/fsnotify/.travis.yml
generated
vendored
@ -2,29 +2,35 @@ sudo: false
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.8.x
|
||||
- 1.9.x
|
||||
- tip
|
||||
- "stable"
|
||||
- "1.11.x"
|
||||
- "1.10.x"
|
||||
- "1.9.x"
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- go: "stable"
|
||||
env: GOLINT=true
|
||||
allow_failures:
|
||||
- go: tip
|
||||
fast_finish: true
|
||||
|
||||
before_script:
|
||||
- go get -u github.com/golang/lint/golint
|
||||
|
||||
before_install:
|
||||
- if [ ! -z "${GOLINT}" ]; then go get -u golang.org/x/lint/golint; fi
|
||||
|
||||
script:
|
||||
- go test -v --race ./...
|
||||
- go test --race ./...
|
||||
|
||||
after_script:
|
||||
- test -z "$(gofmt -s -l -w . | tee /dev/stderr)"
|
||||
- test -z "$(golint ./... | tee /dev/stderr)"
|
||||
- if [ ! -z "${GOLINT}" ]; then echo running golint; golint --set_exit_status ./...; else echo skipping golint; fi
|
||||
- go vet ./...
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
- windows
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
|
2
vendor/github.com/fsnotify/fsnotify/LICENSE
generated
vendored
2
vendor/github.com/fsnotify/fsnotify/LICENSE
generated
vendored
@ -1,5 +1,5 @@
|
||||
Copyright (c) 2012 The Go Authors. All rights reserved.
|
||||
Copyright (c) 2012 fsnotify Authors. All rights reserved.
|
||||
Copyright (c) 2012-2019 fsnotify Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
|
71
vendor/github.com/fsnotify/fsnotify/README.md
generated
vendored
71
vendor/github.com/fsnotify/fsnotify/README.md
generated
vendored
@ -10,16 +10,16 @@ go get -u golang.org/x/sys/...
|
||||
|
||||
Cross platform: Windows, Linux, BSD and macOS.
|
||||
|
||||
|Adapter |OS |Status |
|
||||
|----------|----------|----------|
|
||||
|inotify |Linux 2.6.27 or later, Android\*|Supported [](https://travis-ci.org/fsnotify/fsnotify)|
|
||||
|kqueue |BSD, macOS, iOS\*|Supported [](https://travis-ci.org/fsnotify/fsnotify)|
|
||||
|ReadDirectoryChangesW|Windows|Supported [](https://ci.appveyor.com/project/NathanYoungman/fsnotify/branch/master)|
|
||||
|FSEvents |macOS |[Planned](https://github.com/fsnotify/fsnotify/issues/11)|
|
||||
|FEN |Solaris 11 |[In Progress](https://github.com/fsnotify/fsnotify/issues/12)|
|
||||
|fanotify |Linux 2.6.37+ | |
|
||||
|USN Journals |Windows |[Maybe](https://github.com/fsnotify/fsnotify/issues/53)|
|
||||
|Polling |*All* |[Maybe](https://github.com/fsnotify/fsnotify/issues/9)|
|
||||
| Adapter | OS | Status |
|
||||
| --------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| inotify | Linux 2.6.27 or later, Android\* | Supported [](https://travis-ci.org/fsnotify/fsnotify) |
|
||||
| kqueue | BSD, macOS, iOS\* | Supported [](https://travis-ci.org/fsnotify/fsnotify) |
|
||||
| ReadDirectoryChangesW | Windows | Supported [](https://travis-ci.org/fsnotify/fsnotify) |
|
||||
| FSEvents | macOS | [Planned](https://github.com/fsnotify/fsnotify/issues/11) |
|
||||
| FEN | Solaris 11 | [In Progress](https://github.com/fsnotify/fsnotify/issues/12) |
|
||||
| fanotify | Linux 2.6.37+ | [Planned](https://github.com/fsnotify/fsnotify/issues/114) |
|
||||
| USN Journals | Windows | [Maybe](https://github.com/fsnotify/fsnotify/issues/53) |
|
||||
| Polling | *All* | [Maybe](https://github.com/fsnotify/fsnotify/issues/9) |
|
||||
|
||||
\* Android and iOS are untested.
|
||||
|
||||
@ -33,6 +33,53 @@ All [releases](https://github.com/fsnotify/fsnotify/releases) are tagged based o
|
||||
|
||||
Go 1.6 supports dependencies located in the `vendor/` folder. Unless you are creating a library, it is recommended that you copy fsnotify into `vendor/github.com/fsnotify/fsnotify` within your project, and likewise for `golang.org/x/sys`.
|
||||
|
||||
## Usage
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/fsnotify/fsnotify"
|
||||
)
|
||||
|
||||
func main() {
|
||||
watcher, err := fsnotify.NewWatcher()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer watcher.Close()
|
||||
|
||||
done := make(chan bool)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case event, ok := <-watcher.Events:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
log.Println("event:", event)
|
||||
if event.Op&fsnotify.Write == fsnotify.Write {
|
||||
log.Println("modified file:", event.Name)
|
||||
}
|
||||
case err, ok := <-watcher.Errors:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
log.Println("error:", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
err = watcher.Add("/tmp/foo")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
<-done
|
||||
}
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
Please refer to [CONTRIBUTING][] before opening an issue or pull request.
|
||||
@ -65,6 +112,10 @@ There are OS-specific limits as to how many watches can be created:
|
||||
* Linux: /proc/sys/fs/inotify/max_user_watches contains the limit, reaching this limit results in a "no space left on device" error.
|
||||
* BSD / OSX: sysctl variables "kern.maxfiles" and "kern.maxfilesperproc", reaching these limits results in a "too many open files" error.
|
||||
|
||||
**Why don't notifications work with NFS filesystems or filesystem in userspace (FUSE)?**
|
||||
|
||||
fsnotify requires support from underlying OS to work. The current NFS protocol does not provide network level support for file notifications.
|
||||
|
||||
[#62]: https://github.com/howeyc/fsnotify/issues/62
|
||||
[#18]: https://github.com/fsnotify/fsnotify/issues/18
|
||||
[#11]: https://github.com/fsnotify/fsnotify/issues/11
|
||||
|
4
vendor/github.com/fsnotify/fsnotify/fsnotify.go
generated
vendored
4
vendor/github.com/fsnotify/fsnotify/fsnotify.go
generated
vendored
@ -63,4 +63,6 @@ func (e Event) String() string {
|
||||
}
|
||||
|
||||
// Common errors that can be reported by a watcher
|
||||
var ErrEventOverflow = errors.New("fsnotify queue overflow")
|
||||
var (
|
||||
ErrEventOverflow = errors.New("fsnotify queue overflow")
|
||||
)
|
||||
|
5
vendor/github.com/fsnotify/fsnotify/go.mod
generated
vendored
Normal file
5
vendor/github.com/fsnotify/fsnotify/go.mod
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
module github.com/fsnotify/fsnotify
|
||||
|
||||
go 1.13
|
||||
|
||||
require golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9
|
2
vendor/github.com/fsnotify/fsnotify/go.sum
generated
vendored
Normal file
2
vendor/github.com/fsnotify/fsnotify/go.sum
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9 h1:L2auWcuQIvxz9xSEqzESnV/QN/gNRXNApHi3fYwl2w0=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
4
vendor/github.com/fsnotify/fsnotify/inotify_poller.go
generated
vendored
4
vendor/github.com/fsnotify/fsnotify/inotify_poller.go
generated
vendored
@ -40,12 +40,12 @@ func newFdPoller(fd int) (*fdPoller, error) {
|
||||
poller.fd = fd
|
||||
|
||||
// Create epoll fd
|
||||
poller.epfd, errno = unix.EpollCreate1(0)
|
||||
poller.epfd, errno = unix.EpollCreate1(unix.EPOLL_CLOEXEC)
|
||||
if poller.epfd == -1 {
|
||||
return nil, errno
|
||||
}
|
||||
// Create pipe; pipe[0] is the read end, pipe[1] the write end.
|
||||
errno = unix.Pipe2(poller.pipe[:], unix.O_NONBLOCK)
|
||||
errno = unix.Pipe2(poller.pipe[:], unix.O_NONBLOCK|unix.O_CLOEXEC)
|
||||
if errno != nil {
|
||||
return nil, errno
|
||||
}
|
||||
|
2
vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go
generated
vendored
2
vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go
generated
vendored
@ -8,4 +8,4 @@ package fsnotify
|
||||
|
||||
import "golang.org/x/sys/unix"
|
||||
|
||||
const openMode = unix.O_NONBLOCK | unix.O_RDONLY
|
||||
const openMode = unix.O_NONBLOCK | unix.O_RDONLY | unix.O_CLOEXEC
|
||||
|
2
vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go
generated
vendored
2
vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go
generated
vendored
@ -9,4 +9,4 @@ package fsnotify
|
||||
import "golang.org/x/sys/unix"
|
||||
|
||||
// note: this constant is not defined on BSD
|
||||
const openMode = unix.O_EVTONLY
|
||||
const openMode = unix.O_EVTONLY | unix.O_CLOEXEC
|
||||
|
23
vendor/github.com/onsi/ginkgo/CHANGELOG.md
generated
vendored
23
vendor/github.com/onsi/ginkgo/CHANGELOG.md
generated
vendored
@ -1,3 +1,26 @@
|
||||
## 1.13.0
|
||||
|
||||
### Features
|
||||
- Add a version of table.Entry that allows dumping the entry parameters. (#689) [21eaef2]
|
||||
|
||||
### Fixes
|
||||
- Ensure integration tests pass in an environment sans GOPATH [606fba2]
|
||||
- Add books package (#568) [fc0e44e]
|
||||
- doc(readme): installation via "tools package" (#677) [83bb20e]
|
||||
- Solve the undefined: unix.Dup2 compile error on mips64le (#680) [0624f75]
|
||||
- Import package without dot (#687) [6321024]
|
||||
- Fix integration tests to stop require GOPATH (#686) [a912ec5]
|
||||
|
||||
## 1.12.3
|
||||
|
||||
### Fixes
|
||||
- Print correct code location of failing table test (#666) [c6d7afb]
|
||||
|
||||
## 1.12.2
|
||||
|
||||
### Fixes
|
||||
- Update dependencies [ea4a036]
|
||||
|
||||
## 1.12.1
|
||||
|
||||
### Fixes
|
||||
|
47
vendor/github.com/onsi/ginkgo/README.md
generated
vendored
47
vendor/github.com/onsi/ginkgo/README.md
generated
vendored
@ -4,7 +4,23 @@
|
||||
|
||||
Jump to the [docs](https://onsi.github.io/ginkgo/) to learn more. To start rolling your Ginkgo tests *now* [keep reading](#set-me-up)!
|
||||
|
||||
If you have a question, comment, bug report, feature request, etc. please open a GitHub issue.
|
||||
If you have a question, comment, bug report, feature request, etc. please open a GitHub issue, or visit the [Ginkgo Slack channel](https://app.slack.com/client/T029RQSE6/CQQ50BBNW).
|
||||
|
||||
## TLDR
|
||||
Ginkgo builds on Go's `testing` package, allowing expressive [Behavior-Driven Development](https://en.wikipedia.org/wiki/Behavior-driven_development) ("BDD") style tests.
|
||||
It is typically (and optionally) paired with the [Gomega](https://github.com/onsi/gomega) matcher library.
|
||||
|
||||
```go
|
||||
Describe("the strings package", func() {
|
||||
Context("strings.Contains()", func() {
|
||||
When("the string contains the substring in the middle", func() {
|
||||
It("returns `true`", func() {
|
||||
Expect(strings.Contains("Ginkgo is awesome", "is")).To(BeTrue())
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## Feature List
|
||||
|
||||
@ -59,15 +75,36 @@ Ginkgo is best paired with Gomega. Learn more about Gomega [here](https://onsi.
|
||||
|
||||
Agouti allows you run WebDriver integration tests. Learn more about Agouti [here](https://agouti.org)
|
||||
|
||||
## Set Me Up!
|
||||
## Getting Started
|
||||
|
||||
You'll need the Go command-line tools. Ginkgo is tested with Go 1.6+, but preferably you should get the latest. Follow the [installation instructions](https://golang.org/doc/install) if you don't have it installed.
|
||||
You'll need the Go command-line tools. Follow the [installation instructions](https://golang.org/doc/install) if you don't have it installed.
|
||||
|
||||
### Global installation
|
||||
To install the Ginkgo command line interface into the `$PATH` (actually to `$GOBIN`):
|
||||
```bash
|
||||
go get -u github.com/onsi/ginkgo/ginkgo
|
||||
```
|
||||
|
||||
go get -u github.com/onsi/ginkgo/ginkgo # installs the ginkgo CLI
|
||||
go get -u github.com/onsi/gomega/... # fetches the matcher library
|
||||
### Go module ["tools package"](https://github.com/golang/go/issues/25922):
|
||||
Create (or update) a file called `tools/tools.go` with the following contents:
|
||||
```go
|
||||
// +build tools
|
||||
|
||||
package tools
|
||||
|
||||
import (
|
||||
_ "github.com/onsi/ginkgo"
|
||||
)
|
||||
|
||||
// This file imports packages that are used when running go generate, or used
|
||||
// during the development process but not otherwise depended on by built code.
|
||||
```
|
||||
The Ginkgo command can then be run via `go run github.com/onsi/ginkgo/ginkgo`.
|
||||
This approach allows the version of Ginkgo to be maintained under source control for reproducible results,
|
||||
and is well suited to automated test pipelines.
|
||||
|
||||
### Bootstrapping
|
||||
```bash
|
||||
cd path/to/package/you/want/to/test
|
||||
|
||||
ginkgo bootstrap # set up a new ginkgo suite
|
||||
|
2
vendor/github.com/onsi/ginkgo/config/config.go
generated
vendored
2
vendor/github.com/onsi/ginkgo/config/config.go
generated
vendored
@ -20,7 +20,7 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const VERSION = "1.12.1"
|
||||
const VERSION = "1.13.0"
|
||||
|
||||
type GinkgoConfigType struct {
|
||||
RandomSeed int64
|
||||
|
56
vendor/github.com/onsi/ginkgo/extensions/table/table.go
generated
vendored
56
vendor/github.com/onsi/ginkgo/extensions/table/table.go
generated
vendored
@ -12,7 +12,9 @@ import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/onsi/ginkgo"
|
||||
"github.com/onsi/ginkgo/internal/codelocation"
|
||||
"github.com/onsi/ginkgo/internal/global"
|
||||
"github.com/onsi/ginkgo/types"
|
||||
)
|
||||
|
||||
/*
|
||||
@ -40,9 +42,28 @@ Under the hood, `DescribeTable` simply generates a new Ginkgo `Describe`. Each
|
||||
It's important to understand that the `Describe`s and `It`s are generated at evaluation time (i.e. when Ginkgo constructs the tree of tests and before the tests run).
|
||||
|
||||
Individual Entries can be focused (with FEntry) or marked pending (with PEntry or XEntry). In addition, the entire table can be focused or marked pending with FDescribeTable and PDescribeTable/XDescribeTable.
|
||||
|
||||
A description function can be passed to Entry in place of the description. The function is then fed with the entry parameters to generate the description of the It corresponding to that particular Entry.
|
||||
|
||||
For example:
|
||||
|
||||
describe := func(desc string) func(int, int, bool) string {
|
||||
return func(x, y int, expected bool) string {
|
||||
return fmt.Sprintf("%s x=%d y=%d expected:%t", desc, x, y, expected)
|
||||
}
|
||||
}
|
||||
|
||||
DescribeTable("a simple table",
|
||||
func(x int, y int, expected bool) {
|
||||
Ω(x > y).Should(Equal(expected))
|
||||
},
|
||||
Entry(describe("x > y"), 1, 0, true),
|
||||
Entry(describe("x == y"), 0, 0, false),
|
||||
Entry(describe("x < y"), 0, 1, false),
|
||||
)
|
||||
*/
|
||||
func DescribeTable(description string, itBody interface{}, entries ...TableEntry) bool {
|
||||
describeTable(description, itBody, entries, false, false)
|
||||
describeTable(description, itBody, entries, types.FlagTypeNone)
|
||||
return true
|
||||
}
|
||||
|
||||
@ -50,7 +71,7 @@ func DescribeTable(description string, itBody interface{}, entries ...TableEntry
|
||||
You can focus a table with `FDescribeTable`. This is equivalent to `FDescribe`.
|
||||
*/
|
||||
func FDescribeTable(description string, itBody interface{}, entries ...TableEntry) bool {
|
||||
describeTable(description, itBody, entries, false, true)
|
||||
describeTable(description, itBody, entries, types.FlagTypeFocused)
|
||||
return true
|
||||
}
|
||||
|
||||
@ -58,7 +79,7 @@ func FDescribeTable(description string, itBody interface{}, entries ...TableEntr
|
||||
You can mark a table as pending with `PDescribeTable`. This is equivalent to `PDescribe`.
|
||||
*/
|
||||
func PDescribeTable(description string, itBody interface{}, entries ...TableEntry) bool {
|
||||
describeTable(description, itBody, entries, true, false)
|
||||
describeTable(description, itBody, entries, types.FlagTypePending)
|
||||
return true
|
||||
}
|
||||
|
||||
@ -66,33 +87,24 @@ func PDescribeTable(description string, itBody interface{}, entries ...TableEntr
|
||||
You can mark a table as pending with `XDescribeTable`. This is equivalent to `XDescribe`.
|
||||
*/
|
||||
func XDescribeTable(description string, itBody interface{}, entries ...TableEntry) bool {
|
||||
describeTable(description, itBody, entries, true, false)
|
||||
describeTable(description, itBody, entries, types.FlagTypePending)
|
||||
return true
|
||||
}
|
||||
|
||||
func describeTable(description string, itBody interface{}, entries []TableEntry, pending bool, focused bool) {
|
||||
func describeTable(description string, itBody interface{}, entries []TableEntry, flag types.FlagType) {
|
||||
itBodyValue := reflect.ValueOf(itBody)
|
||||
if itBodyValue.Kind() != reflect.Func {
|
||||
panic(fmt.Sprintf("DescribeTable expects a function, got %#v", itBody))
|
||||
}
|
||||
|
||||
if pending {
|
||||
ginkgo.PDescribe(description, func() {
|
||||
global.Suite.PushContainerNode(
|
||||
description,
|
||||
func() {
|
||||
for _, entry := range entries {
|
||||
entry.generateIt(itBodyValue)
|
||||
}
|
||||
})
|
||||
} else if focused {
|
||||
ginkgo.FDescribe(description, func() {
|
||||
for _, entry := range entries {
|
||||
entry.generateIt(itBodyValue)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
ginkgo.Describe(description, func() {
|
||||
for _, entry := range entries {
|
||||
entry.generateIt(itBodyValue)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
flag,
|
||||
codelocation.New(2),
|
||||
)
|
||||
}
|
||||
|
105
vendor/github.com/onsi/ginkgo/extensions/table/table_entry.go
generated
vendored
105
vendor/github.com/onsi/ginkgo/extensions/table/table_entry.go
generated
vendored
@ -1,49 +1,82 @@
|
||||
package table
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/onsi/ginkgo"
|
||||
"github.com/onsi/ginkgo/internal/codelocation"
|
||||
"github.com/onsi/ginkgo/internal/global"
|
||||
"github.com/onsi/ginkgo/types"
|
||||
)
|
||||
|
||||
/*
|
||||
TableEntry represents an entry in a table test. You generally use the `Entry` constructor.
|
||||
*/
|
||||
type TableEntry struct {
|
||||
Description string
|
||||
Description interface{}
|
||||
Parameters []interface{}
|
||||
Pending bool
|
||||
Focused bool
|
||||
codeLocation types.CodeLocation
|
||||
}
|
||||
|
||||
func (t TableEntry) generateIt(itBody reflect.Value) {
|
||||
if t.codeLocation == (types.CodeLocation{}) {
|
||||
// The user created the TableEntry struct directly instead of having used the (F/P/X)Entry constructors.
|
||||
// Therefore default to the code location of the surrounding DescribeTable.
|
||||
t.codeLocation = codelocation.New(5)
|
||||
}
|
||||
|
||||
var description string
|
||||
descriptionValue := reflect.ValueOf(t.Description)
|
||||
switch descriptionValue.Kind() {
|
||||
case reflect.String:
|
||||
description = descriptionValue.String()
|
||||
case reflect.Func:
|
||||
values := castParameters(descriptionValue, t.Parameters)
|
||||
res := descriptionValue.Call(values)
|
||||
if len(res) != 1 {
|
||||
panic(fmt.Sprintf("The describe function should return only a value, returned %d", len(res)))
|
||||
}
|
||||
if res[0].Kind() != reflect.String {
|
||||
panic(fmt.Sprintf("The describe function should return a string, returned %#v", res[0]))
|
||||
}
|
||||
description = res[0].String()
|
||||
default:
|
||||
panic(fmt.Sprintf("Description can either be a string or a function, got %#v", descriptionValue))
|
||||
}
|
||||
|
||||
if t.Pending {
|
||||
ginkgo.PIt(t.Description)
|
||||
global.Suite.PushItNode(description, func() {}, types.FlagTypePending, t.codeLocation, 0)
|
||||
return
|
||||
}
|
||||
|
||||
values := make([]reflect.Value, len(t.Parameters))
|
||||
iBodyType := itBody.Type()
|
||||
for i, param := range t.Parameters {
|
||||
if param == nil {
|
||||
inType := iBodyType.In(i)
|
||||
values[i] = reflect.Zero(inType)
|
||||
} else {
|
||||
values[i] = reflect.ValueOf(param)
|
||||
}
|
||||
}
|
||||
|
||||
values := castParameters(itBody, t.Parameters)
|
||||
body := func() {
|
||||
itBody.Call(values)
|
||||
}
|
||||
|
||||
if t.Focused {
|
||||
ginkgo.FIt(t.Description, body)
|
||||
global.Suite.PushItNode(description, body, types.FlagTypeFocused, t.codeLocation, global.DefaultTimeout)
|
||||
} else {
|
||||
ginkgo.It(t.Description, body)
|
||||
global.Suite.PushItNode(description, body, types.FlagTypeNone, t.codeLocation, global.DefaultTimeout)
|
||||
}
|
||||
}
|
||||
|
||||
func castParameters(function reflect.Value, parameters []interface{}) []reflect.Value {
|
||||
res := make([]reflect.Value, len(parameters))
|
||||
funcType := function.Type()
|
||||
for i, param := range parameters {
|
||||
if param == nil {
|
||||
inType := funcType.In(i)
|
||||
res[i] = reflect.Zero(inType)
|
||||
} else {
|
||||
res[i] = reflect.ValueOf(param)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
/*
|
||||
Entry constructs a TableEntry.
|
||||
|
||||
@ -52,27 +85,51 @@ Subsequent parameters are saved off and sent to the callback passed in to `Descr
|
||||
|
||||
Each Entry ends up generating an individual Ginkgo It.
|
||||
*/
|
||||
func Entry(description string, parameters ...interface{}) TableEntry {
|
||||
return TableEntry{description, parameters, false, false}
|
||||
func Entry(description interface{}, parameters ...interface{}) TableEntry {
|
||||
return TableEntry{
|
||||
Description: description,
|
||||
Parameters: parameters,
|
||||
Pending: false,
|
||||
Focused: false,
|
||||
codeLocation: codelocation.New(1),
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
You can focus a particular entry with FEntry. This is equivalent to FIt.
|
||||
*/
|
||||
func FEntry(description string, parameters ...interface{}) TableEntry {
|
||||
return TableEntry{description, parameters, false, true}
|
||||
func FEntry(description interface{}, parameters ...interface{}) TableEntry {
|
||||
return TableEntry{
|
||||
Description: description,
|
||||
Parameters: parameters,
|
||||
Pending: false,
|
||||
Focused: true,
|
||||
codeLocation: codelocation.New(1),
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
You can mark a particular entry as pending with PEntry. This is equivalent to PIt.
|
||||
*/
|
||||
func PEntry(description string, parameters ...interface{}) TableEntry {
|
||||
return TableEntry{description, parameters, true, false}
|
||||
func PEntry(description interface{}, parameters ...interface{}) TableEntry {
|
||||
return TableEntry{
|
||||
Description: description,
|
||||
Parameters: parameters,
|
||||
Pending: true,
|
||||
Focused: false,
|
||||
codeLocation: codelocation.New(1),
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
You can mark a particular entry as pending with XEntry. This is equivalent to XIt.
|
||||
*/
|
||||
func XEntry(description string, parameters ...interface{}) TableEntry {
|
||||
return TableEntry{description, parameters, true, false}
|
||||
func XEntry(description interface{}, parameters ...interface{}) TableEntry {
|
||||
return TableEntry{
|
||||
Description: description,
|
||||
Parameters: parameters,
|
||||
Pending: true,
|
||||
Focused: false,
|
||||
codeLocation: codelocation.New(1),
|
||||
}
|
||||
}
|
||||
|
85
vendor/github.com/onsi/ginkgo/ginkgo_dsl.go
generated
vendored
85
vendor/github.com/onsi/ginkgo/ginkgo_dsl.go
generated
vendored
@ -22,9 +22,8 @@ import (
|
||||
|
||||
"github.com/onsi/ginkgo/config"
|
||||
"github.com/onsi/ginkgo/internal/codelocation"
|
||||
"github.com/onsi/ginkgo/internal/failer"
|
||||
"github.com/onsi/ginkgo/internal/global"
|
||||
"github.com/onsi/ginkgo/internal/remote"
|
||||
"github.com/onsi/ginkgo/internal/suite"
|
||||
"github.com/onsi/ginkgo/internal/testingtproxy"
|
||||
"github.com/onsi/ginkgo/internal/writer"
|
||||
"github.com/onsi/ginkgo/reporters"
|
||||
@ -46,16 +45,10 @@ To circumvent this, you should call
|
||||
|
||||
at the top of the goroutine that caused this panic.
|
||||
`
|
||||
const defaultTimeout = 1
|
||||
|
||||
var globalSuite *suite.Suite
|
||||
var globalFailer *failer.Failer
|
||||
|
||||
func init() {
|
||||
config.Flags(flag.CommandLine, "ginkgo", true)
|
||||
GinkgoWriter = writer.New(os.Stdout)
|
||||
globalFailer = failer.New()
|
||||
globalSuite = suite.New(globalFailer)
|
||||
}
|
||||
|
||||
//GinkgoWriter implements an io.Writer
|
||||
@ -156,7 +149,7 @@ type GinkgoTestDescription struct {
|
||||
|
||||
//CurrentGinkgoTestDescripton returns information about the current running test.
|
||||
func CurrentGinkgoTestDescription() GinkgoTestDescription {
|
||||
summary, ok := globalSuite.CurrentRunningSpecSummary()
|
||||
summary, ok := global.Suite.CurrentRunningSpecSummary()
|
||||
if !ok {
|
||||
return GinkgoTestDescription{}
|
||||
}
|
||||
@ -223,7 +216,7 @@ func RunSpecsWithCustomReporters(t GinkgoTestingT, description string, specRepor
|
||||
for i, reporter := range specReporters {
|
||||
reporters[i] = reporter
|
||||
}
|
||||
passed, hasFocusedTests := globalSuite.Run(t, description, reporters, writer, config.GinkgoConfig)
|
||||
passed, hasFocusedTests := global.Suite.Run(t, description, reporters, writer, config.GinkgoConfig)
|
||||
if passed && hasFocusedTests && strings.TrimSpace(os.Getenv("GINKGO_EDITOR_INTEGRATION")) == "" {
|
||||
fmt.Println("PASS | FOCUSED")
|
||||
os.Exit(types.GINKGO_FOCUS_EXIT_CODE)
|
||||
@ -252,7 +245,7 @@ func Skip(message string, callerSkip ...int) {
|
||||
skip = callerSkip[0]
|
||||
}
|
||||
|
||||
globalFailer.Skip(message, codelocation.New(skip+1))
|
||||
global.Failer.Skip(message, codelocation.New(skip+1))
|
||||
panic(GINKGO_PANIC)
|
||||
}
|
||||
|
||||
@ -263,7 +256,7 @@ func Fail(message string, callerSkip ...int) {
|
||||
skip = callerSkip[0]
|
||||
}
|
||||
|
||||
globalFailer.Fail(message, codelocation.New(skip+1))
|
||||
global.Failer.Fail(message, codelocation.New(skip+1))
|
||||
panic(GINKGO_PANIC)
|
||||
}
|
||||
|
||||
@ -280,7 +273,7 @@ func Fail(message string, callerSkip ...int) {
|
||||
func GinkgoRecover() {
|
||||
e := recover()
|
||||
if e != nil {
|
||||
globalFailer.Panic(codelocation.New(1), e)
|
||||
global.Failer.Panic(codelocation.New(1), e)
|
||||
}
|
||||
}
|
||||
|
||||
@ -291,25 +284,25 @@ func GinkgoRecover() {
|
||||
//equivalent. The difference is purely semantic -- you typically Describe the behavior of an object
|
||||
//or method and, within that Describe, outline a number of Contexts and Whens.
|
||||
func Describe(text string, body func()) bool {
|
||||
globalSuite.PushContainerNode(text, body, types.FlagTypeNone, codelocation.New(1))
|
||||
global.Suite.PushContainerNode(text, body, types.FlagTypeNone, codelocation.New(1))
|
||||
return true
|
||||
}
|
||||
|
||||
//You can focus the tests within a describe block using FDescribe
|
||||
func FDescribe(text string, body func()) bool {
|
||||
globalSuite.PushContainerNode(text, body, types.FlagTypeFocused, codelocation.New(1))
|
||||
global.Suite.PushContainerNode(text, body, types.FlagTypeFocused, codelocation.New(1))
|
||||
return true
|
||||
}
|
||||
|
||||
//You can mark the tests within a describe block as pending using PDescribe
|
||||
func PDescribe(text string, body func()) bool {
|
||||
globalSuite.PushContainerNode(text, body, types.FlagTypePending, codelocation.New(1))
|
||||
global.Suite.PushContainerNode(text, body, types.FlagTypePending, codelocation.New(1))
|
||||
return true
|
||||
}
|
||||
|
||||
//You can mark the tests within a describe block as pending using XDescribe
|
||||
func XDescribe(text string, body func()) bool {
|
||||
globalSuite.PushContainerNode(text, body, types.FlagTypePending, codelocation.New(1))
|
||||
global.Suite.PushContainerNode(text, body, types.FlagTypePending, codelocation.New(1))
|
||||
return true
|
||||
}
|
||||
|
||||
@ -320,25 +313,25 @@ func XDescribe(text string, body func()) bool {
|
||||
//equivalent. The difference is purely semantic -- you typical Describe the behavior of an object
|
||||
//or method and, within that Describe, outline a number of Contexts and Whens.
|
||||
func Context(text string, body func()) bool {
|
||||
globalSuite.PushContainerNode(text, body, types.FlagTypeNone, codelocation.New(1))
|
||||
global.Suite.PushContainerNode(text, body, types.FlagTypeNone, codelocation.New(1))
|
||||
return true
|
||||
}
|
||||
|
||||
//You can focus the tests within a describe block using FContext
|
||||
func FContext(text string, body func()) bool {
|
||||
globalSuite.PushContainerNode(text, body, types.FlagTypeFocused, codelocation.New(1))
|
||||
global.Suite.PushContainerNode(text, body, types.FlagTypeFocused, codelocation.New(1))
|
||||
return true
|
||||
}
|
||||
|
||||
//You can mark the tests within a describe block as pending using PContext
|
||||
func PContext(text string, body func()) bool {
|
||||
globalSuite.PushContainerNode(text, body, types.FlagTypePending, codelocation.New(1))
|
||||
global.Suite.PushContainerNode(text, body, types.FlagTypePending, codelocation.New(1))
|
||||
return true
|
||||
}
|
||||
|
||||
//You can mark the tests within a describe block as pending using XContext
|
||||
func XContext(text string, body func()) bool {
|
||||
globalSuite.PushContainerNode(text, body, types.FlagTypePending, codelocation.New(1))
|
||||
global.Suite.PushContainerNode(text, body, types.FlagTypePending, codelocation.New(1))
|
||||
return true
|
||||
}
|
||||
|
||||
@ -349,25 +342,25 @@ func XContext(text string, body func()) bool {
|
||||
//equivalent. The difference is purely semantic -- you typical Describe the behavior of an object
|
||||
//or method and, within that Describe, outline a number of Contexts and Whens.
|
||||
func When(text string, body func()) bool {
|
||||
globalSuite.PushContainerNode("when "+text, body, types.FlagTypeNone, codelocation.New(1))
|
||||
global.Suite.PushContainerNode("when "+text, body, types.FlagTypeNone, codelocation.New(1))
|
||||
return true
|
||||
}
|
||||
|
||||
//You can focus the tests within a describe block using FWhen
|
||||
func FWhen(text string, body func()) bool {
|
||||
globalSuite.PushContainerNode("when "+text, body, types.FlagTypeFocused, codelocation.New(1))
|
||||
global.Suite.PushContainerNode("when "+text, body, types.FlagTypeFocused, codelocation.New(1))
|
||||
return true
|
||||
}
|
||||
|
||||
//You can mark the tests within a describe block as pending using PWhen
|
||||
func PWhen(text string, body func()) bool {
|
||||
globalSuite.PushContainerNode("when "+text, body, types.FlagTypePending, codelocation.New(1))
|
||||
global.Suite.PushContainerNode("when "+text, body, types.FlagTypePending, codelocation.New(1))
|
||||
return true
|
||||
}
|
||||
|
||||
//You can mark the tests within a describe block as pending using XWhen
|
||||
func XWhen(text string, body func()) bool {
|
||||
globalSuite.PushContainerNode("when "+text, body, types.FlagTypePending, codelocation.New(1))
|
||||
global.Suite.PushContainerNode("when "+text, body, types.FlagTypePending, codelocation.New(1))
|
||||
return true
|
||||
}
|
||||
|
||||
@ -377,25 +370,25 @@ func XWhen(text string, body func()) bool {
|
||||
//Ginkgo will normally run It blocks synchronously. To perform asynchronous tests, pass a
|
||||
//function that accepts a Done channel. When you do this, you can also provide an optional timeout.
|
||||
func It(text string, body interface{}, timeout ...float64) bool {
|
||||
globalSuite.PushItNode(text, body, types.FlagTypeNone, codelocation.New(1), parseTimeout(timeout...))
|
||||
global.Suite.PushItNode(text, body, types.FlagTypeNone, codelocation.New(1), parseTimeout(timeout...))
|
||||
return true
|
||||
}
|
||||
|
||||
//You can focus individual Its using FIt
|
||||
func FIt(text string, body interface{}, timeout ...float64) bool {
|
||||
globalSuite.PushItNode(text, body, types.FlagTypeFocused, codelocation.New(1), parseTimeout(timeout...))
|
||||
global.Suite.PushItNode(text, body, types.FlagTypeFocused, codelocation.New(1), parseTimeout(timeout...))
|
||||
return true
|
||||
}
|
||||
|
||||
//You can mark Its as pending using PIt
|
||||
func PIt(text string, _ ...interface{}) bool {
|
||||
globalSuite.PushItNode(text, func() {}, types.FlagTypePending, codelocation.New(1), 0)
|
||||
global.Suite.PushItNode(text, func() {}, types.FlagTypePending, codelocation.New(1), 0)
|
||||
return true
|
||||
}
|
||||
|
||||
//You can mark Its as pending using XIt
|
||||
func XIt(text string, _ ...interface{}) bool {
|
||||
globalSuite.PushItNode(text, func() {}, types.FlagTypePending, codelocation.New(1), 0)
|
||||
global.Suite.PushItNode(text, func() {}, types.FlagTypePending, codelocation.New(1), 0)
|
||||
return true
|
||||
}
|
||||
|
||||
@ -403,25 +396,25 @@ func XIt(text string, _ ...interface{}) bool {
|
||||
//which "It" does not fit into a natural sentence flow. All the same protocols apply for Specify blocks
|
||||
//which apply to It blocks.
|
||||
func Specify(text string, body interface{}, timeout ...float64) bool {
|
||||
globalSuite.PushItNode(text, body, types.FlagTypeNone, codelocation.New(1), parseTimeout(timeout...))
|
||||
global.Suite.PushItNode(text, body, types.FlagTypeNone, codelocation.New(1), parseTimeout(timeout...))
|
||||
return true
|
||||
}
|
||||
|
||||
//You can focus individual Specifys using FSpecify
|
||||
func FSpecify(text string, body interface{}, timeout ...float64) bool {
|
||||
globalSuite.PushItNode(text, body, types.FlagTypeFocused, codelocation.New(1), parseTimeout(timeout...))
|
||||
global.Suite.PushItNode(text, body, types.FlagTypeFocused, codelocation.New(1), parseTimeout(timeout...))
|
||||
return true
|
||||
}
|
||||
|
||||
//You can mark Specifys as pending using PSpecify
|
||||
func PSpecify(text string, is ...interface{}) bool {
|
||||
globalSuite.PushItNode(text, func() {}, types.FlagTypePending, codelocation.New(1), 0)
|
||||
global.Suite.PushItNode(text, func() {}, types.FlagTypePending, codelocation.New(1), 0)
|
||||
return true
|
||||
}
|
||||
|
||||
//You can mark Specifys as pending using XSpecify
|
||||
func XSpecify(text string, is ...interface{}) bool {
|
||||
globalSuite.PushItNode(text, func() {}, types.FlagTypePending, codelocation.New(1), 0)
|
||||
global.Suite.PushItNode(text, func() {}, types.FlagTypePending, codelocation.New(1), 0)
|
||||
return true
|
||||
}
|
||||
|
||||
@ -452,25 +445,25 @@ func By(text string, callbacks ...func()) {
|
||||
//The body function must have the signature:
|
||||
// func(b Benchmarker)
|
||||
func Measure(text string, body interface{}, samples int) bool {
|
||||
globalSuite.PushMeasureNode(text, body, types.FlagTypeNone, codelocation.New(1), samples)
|
||||
global.Suite.PushMeasureNode(text, body, types.FlagTypeNone, codelocation.New(1), samples)
|
||||
return true
|
||||
}
|
||||
|
||||
//You can focus individual Measures using FMeasure
|
||||
func FMeasure(text string, body interface{}, samples int) bool {
|
||||
globalSuite.PushMeasureNode(text, body, types.FlagTypeFocused, codelocation.New(1), samples)
|
||||
global.Suite.PushMeasureNode(text, body, types.FlagTypeFocused, codelocation.New(1), samples)
|
||||
return true
|
||||
}
|
||||
|
||||
//You can mark Measurements as pending using PMeasure
|
||||
func PMeasure(text string, _ ...interface{}) bool {
|
||||
globalSuite.PushMeasureNode(text, func(b Benchmarker) {}, types.FlagTypePending, codelocation.New(1), 0)
|
||||
global.Suite.PushMeasureNode(text, func(b Benchmarker) {}, types.FlagTypePending, codelocation.New(1), 0)
|
||||
return true
|
||||
}
|
||||
|
||||
//You can mark Measurements as pending using XMeasure
|
||||
func XMeasure(text string, _ ...interface{}) bool {
|
||||
globalSuite.PushMeasureNode(text, func(b Benchmarker) {}, types.FlagTypePending, codelocation.New(1), 0)
|
||||
global.Suite.PushMeasureNode(text, func(b Benchmarker) {}, types.FlagTypePending, codelocation.New(1), 0)
|
||||
return true
|
||||
}
|
||||
|
||||
@ -481,7 +474,7 @@ func XMeasure(text string, _ ...interface{}) bool {
|
||||
//
|
||||
//You may only register *one* BeforeSuite handler per test suite. You typically do so in your bootstrap file at the top level.
|
||||
func BeforeSuite(body interface{}, timeout ...float64) bool {
|
||||
globalSuite.SetBeforeSuiteNode(body, codelocation.New(1), parseTimeout(timeout...))
|
||||
global.Suite.SetBeforeSuiteNode(body, codelocation.New(1), parseTimeout(timeout...))
|
||||
return true
|
||||
}
|
||||
|
||||
@ -494,7 +487,7 @@ func BeforeSuite(body interface{}, timeout ...float64) bool {
|
||||
//
|
||||
//You may only register *one* AfterSuite handler per test suite. You typically do so in your bootstrap file at the top level.
|
||||
func AfterSuite(body interface{}, timeout ...float64) bool {
|
||||
globalSuite.SetAfterSuiteNode(body, codelocation.New(1), parseTimeout(timeout...))
|
||||
global.Suite.SetAfterSuiteNode(body, codelocation.New(1), parseTimeout(timeout...))
|
||||
return true
|
||||
}
|
||||
|
||||
@ -539,7 +532,7 @@ func AfterSuite(body interface{}, timeout ...float64) bool {
|
||||
// Ω(err).ShouldNot(HaveOccurred())
|
||||
// })
|
||||
func SynchronizedBeforeSuite(node1Body interface{}, allNodesBody interface{}, timeout ...float64) bool {
|
||||
globalSuite.SetSynchronizedBeforeSuiteNode(
|
||||
global.Suite.SetSynchronizedBeforeSuiteNode(
|
||||
node1Body,
|
||||
allNodesBody,
|
||||
codelocation.New(1),
|
||||
@ -566,7 +559,7 @@ func SynchronizedBeforeSuite(node1Body interface{}, allNodesBody interface{}, ti
|
||||
// dbRunner.Stop()
|
||||
// })
|
||||
func SynchronizedAfterSuite(allNodesBody interface{}, node1Body interface{}, timeout ...float64) bool {
|
||||
globalSuite.SetSynchronizedAfterSuiteNode(
|
||||
global.Suite.SetSynchronizedAfterSuiteNode(
|
||||
allNodesBody,
|
||||
node1Body,
|
||||
codelocation.New(1),
|
||||
@ -581,7 +574,7 @@ func SynchronizedAfterSuite(allNodesBody interface{}, node1Body interface{}, tim
|
||||
//Like It blocks, BeforeEach blocks can be made asynchronous by providing a body function that accepts
|
||||
//a Done channel
|
||||
func BeforeEach(body interface{}, timeout ...float64) bool {
|
||||
globalSuite.PushBeforeEachNode(body, codelocation.New(1), parseTimeout(timeout...))
|
||||
global.Suite.PushBeforeEachNode(body, codelocation.New(1), parseTimeout(timeout...))
|
||||
return true
|
||||
}
|
||||
|
||||
@ -591,7 +584,7 @@ func BeforeEach(body interface{}, timeout ...float64) bool {
|
||||
//Like It blocks, BeforeEach blocks can be made asynchronous by providing a body function that accepts
|
||||
//a Done channel
|
||||
func JustBeforeEach(body interface{}, timeout ...float64) bool {
|
||||
globalSuite.PushJustBeforeEachNode(body, codelocation.New(1), parseTimeout(timeout...))
|
||||
global.Suite.PushJustBeforeEachNode(body, codelocation.New(1), parseTimeout(timeout...))
|
||||
return true
|
||||
}
|
||||
|
||||
@ -601,7 +594,7 @@ func JustBeforeEach(body interface{}, timeout ...float64) bool {
|
||||
//Like It blocks, JustAfterEach blocks can be made asynchronous by providing a body function that accepts
|
||||
//a Done channel
|
||||
func JustAfterEach(body interface{}, timeout ...float64) bool {
|
||||
globalSuite.PushJustAfterEachNode(body, codelocation.New(1), parseTimeout(timeout...))
|
||||
global.Suite.PushJustAfterEachNode(body, codelocation.New(1), parseTimeout(timeout...))
|
||||
return true
|
||||
}
|
||||
|
||||
@ -611,13 +604,13 @@ func JustAfterEach(body interface{}, timeout ...float64) bool {
|
||||
//Like It blocks, AfterEach blocks can be made asynchronous by providing a body function that accepts
|
||||
//a Done channel
|
||||
func AfterEach(body interface{}, timeout ...float64) bool {
|
||||
globalSuite.PushAfterEachNode(body, codelocation.New(1), parseTimeout(timeout...))
|
||||
global.Suite.PushAfterEachNode(body, codelocation.New(1), parseTimeout(timeout...))
|
||||
return true
|
||||
}
|
||||
|
||||
func parseTimeout(timeout ...float64) time.Duration {
|
||||
if len(timeout) == 0 {
|
||||
return time.Duration(defaultTimeout * int64(time.Second))
|
||||
return global.DefaultTimeout
|
||||
} else {
|
||||
return time.Duration(timeout[0] * float64(time.Second))
|
||||
}
|
||||
|
9
vendor/github.com/onsi/ginkgo/go.mod
generated
vendored
9
vendor/github.com/onsi/ginkgo/go.mod
generated
vendored
@ -1,9 +1,12 @@
|
||||
module github.com/onsi/ginkgo
|
||||
|
||||
require (
|
||||
github.com/fsnotify/fsnotify v1.4.9 // indirect
|
||||
github.com/nxadm/tail v1.4.4
|
||||
github.com/onsi/gomega v1.7.1
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e
|
||||
github.com/onsi/gomega v1.10.1
|
||||
github.com/sclevine/agouti v3.0.0+incompatible // indirect
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299
|
||||
golang.org/x/text v0.3.2 // indirect
|
||||
)
|
||||
|
||||
go 1.12
|
||||
go 1.13
|
||||
|
40
vendor/github.com/onsi/ginkgo/go.sum
generated
vendored
40
vendor/github.com/onsi/ginkgo/go.sum
generated
vendored
@ -1,24 +1,62 @@
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/sclevine/agouti v3.0.0+incompatible h1:8IBJS6PWz3uTlMP3YBIR5f+KAldcGuOeFkFbUWfBgK4=
|
||||
github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 h1:AeiKBIuRw3UomYXSbLy0Mc2dDLfdtbT/IVn4keq83P0=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e h1:N7DeIrjYszNmSW409R3frPPwglRwMkXSBzwVbkOjLLA=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7NkNAQs+6Q8b9WEB/F4=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
@ -27,3 +65,5 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
18
vendor/github.com/onsi/ginkgo/internal/global/init.go
generated
vendored
Normal file
18
vendor/github.com/onsi/ginkgo/internal/global/init.go
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
package global
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/onsi/ginkgo/internal/failer"
|
||||
"github.com/onsi/ginkgo/internal/suite"
|
||||
)
|
||||
|
||||
const DefaultTimeout = time.Duration(1 * time.Second)
|
||||
|
||||
var Suite *suite.Suite
|
||||
var Failer *failer.Failer
|
||||
|
||||
func init() {
|
||||
Failer = failer.New()
|
||||
Suite = suite.New(Failer)
|
||||
}
|
11
vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_darwin.go
generated
vendored
Normal file
11
vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_darwin.go
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
// +build darwin
|
||||
|
||||
package remote
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func interceptorDupx(oldfd int, newfd int) {
|
||||
unix.Dup2(oldfd, newfd)
|
||||
}
|
11
vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_dragonfly.go
generated
vendored
Normal file
11
vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_dragonfly.go
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
// +build dragonfly
|
||||
|
||||
package remote
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func interceptorDupx(oldfd int, newfd int) {
|
||||
unix.Dup2(oldfd, newfd)
|
||||
}
|
11
vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_freebsd.go
generated
vendored
Normal file
11
vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_freebsd.go
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
// +build freebsd
|
||||
|
||||
package remote
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func interceptorDupx(oldfd int, newfd int) {
|
||||
unix.Dup2(oldfd, newfd)
|
||||
}
|
12
vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_linux.go
generated
vendored
Normal file
12
vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_linux.go
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
// +build linux
|
||||
// +build !mips64le
|
||||
|
||||
package remote
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func interceptorDupx(oldfd int, newfd int) {
|
||||
unix.Dup2(oldfd, newfd)
|
||||
}
|
12
vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_linux_mips64le.go
generated
vendored
Normal file
12
vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_linux_mips64le.go
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
// +build linux
|
||||
// +build mips64le
|
||||
|
||||
package remote
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func interceptorDupx(oldfd int, newfd int) {
|
||||
unix.Dup3(oldfd, newfd, 0)
|
||||
}
|
11
vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_netbsd.go
generated
vendored
Normal file
11
vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_netbsd.go
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
// +build netbsd
|
||||
|
||||
package remote
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func interceptorDupx(oldfd int, newfd int) {
|
||||
unix.Dup2(oldfd, newfd)
|
||||
}
|
11
vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_openbsd.go
generated
vendored
Normal file
11
vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_openbsd.go
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
// +build openbsd
|
||||
|
||||
package remote
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func interceptorDupx(oldfd int, newfd int) {
|
||||
unix.Dup2(oldfd, newfd)
|
||||
}
|
11
vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_solaris.go
generated
vendored
Normal file
11
vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_solaris.go
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
// +build solaris
|
||||
|
||||
package remote
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func interceptorDupx(oldfd int, newfd int) {
|
||||
unix.Dup2(oldfd, newfd)
|
||||
}
|
7
vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_unix.go
generated
vendored
7
vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_unix.go
generated
vendored
@ -8,7 +8,6 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/nxadm/tail"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func NewOutputInterceptor() OutputInterceptor {
|
||||
@ -36,10 +35,8 @@ func (interceptor *outputInterceptor) StartInterceptingOutput() error {
|
||||
return err
|
||||
}
|
||||
|
||||
// This might call Dup3 if the dup2 syscall is not available, e.g. on
|
||||
// linux/arm64 or linux/riscv64
|
||||
unix.Dup2(int(interceptor.redirectFile.Fd()), 1)
|
||||
unix.Dup2(int(interceptor.redirectFile.Fd()), 2)
|
||||
interceptorDupx(int(interceptor.redirectFile.Fd()), 1)
|
||||
interceptorDupx(int(interceptor.redirectFile.Fd()), 2)
|
||||
|
||||
if interceptor.streamTarget != nil {
|
||||
interceptor.tailer, _ = tail.TailFile(interceptor.redirectFile.Name(), tail.Config{Follow: true})
|
||||
|
12
vendor/modules.txt
vendored
12
vendor/modules.txt
vendored
@ -28,14 +28,17 @@ github.com/alexflint/go-filemutex
|
||||
# github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44
|
||||
## explicit
|
||||
github.com/buger/jsonparser
|
||||
# github.com/containernetworking/cni v0.8.1
|
||||
# github.com/containernetworking/cni v0.8.1-0.20201216164644-62e54113f44a
|
||||
## explicit
|
||||
github.com/containernetworking/cni/libcni
|
||||
github.com/containernetworking/cni/pkg/invoke
|
||||
github.com/containernetworking/cni/pkg/skel
|
||||
github.com/containernetworking/cni/pkg/types
|
||||
github.com/containernetworking/cni/pkg/types/020
|
||||
github.com/containernetworking/cni/pkg/types/current
|
||||
github.com/containernetworking/cni/pkg/types/040
|
||||
github.com/containernetworking/cni/pkg/types/100
|
||||
github.com/containernetworking/cni/pkg/types/create
|
||||
github.com/containernetworking/cni/pkg/types/internal
|
||||
github.com/containernetworking/cni/pkg/utils
|
||||
github.com/containernetworking/cni/pkg/version
|
||||
# github.com/coreos/go-iptables v0.5.0
|
||||
@ -57,7 +60,7 @@ github.com/d2g/dhcp4server/leasepool
|
||||
github.com/d2g/dhcp4server/leasepool/memorypool
|
||||
# github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4
|
||||
## explicit
|
||||
# github.com/fsnotify/fsnotify v1.4.7
|
||||
# github.com/fsnotify/fsnotify v1.4.9
|
||||
github.com/fsnotify/fsnotify
|
||||
# github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c
|
||||
## explicit
|
||||
@ -74,7 +77,7 @@ github.com/nxadm/tail/ratelimiter
|
||||
github.com/nxadm/tail/util
|
||||
github.com/nxadm/tail/watch
|
||||
github.com/nxadm/tail/winfile
|
||||
# github.com/onsi/ginkgo v1.12.1
|
||||
# github.com/onsi/ginkgo v1.13.0
|
||||
## explicit
|
||||
github.com/onsi/ginkgo
|
||||
github.com/onsi/ginkgo/config
|
||||
@ -82,6 +85,7 @@ github.com/onsi/ginkgo/extensions/table
|
||||
github.com/onsi/ginkgo/internal/codelocation
|
||||
github.com/onsi/ginkgo/internal/containernode
|
||||
github.com/onsi/ginkgo/internal/failer
|
||||
github.com/onsi/ginkgo/internal/global
|
||||
github.com/onsi/ginkgo/internal/leafnodes
|
||||
github.com/onsi/ginkgo/internal/remote
|
||||
github.com/onsi/ginkgo/internal/spec
|
||||
|
Loading…
x
Reference in New Issue
Block a user