diff --git a/plugins/main/ptp/ptp_test.go b/plugins/main/ptp/ptp_test.go index d5f53d38..fd362b86 100644 --- a/plugins/main/ptp/ptp_test.go +++ b/plugins/main/ptp/ptp_test.go @@ -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" - current "github.com/containernetworking/cni/pkg/types/100" + "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() + if mac != "" { + Expect(mac).To(Equal(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, 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, 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, resI) + 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) }) }) - Expect(err).NotTo(HaveOccurred()) + 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,227 +337,200 @@ var _ = Describe("ptp Operations", func() { Expect(err).NotTo(HaveOccurred()) } - It("configures and deconfigures a ptp link with ADD/DEL", func() { - dnsConf := types.DNS{ - Nameservers: []string{"10.1.2.123"}, - Domain: "some.domain.test", - Search: []string{"search.test"}, - Options: []string{"option1:foo"}, - } - dnsConfBytes, err := json.Marshal(dnsConf) - Expect(err).NotTo(HaveOccurred()) + 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 - conf := fmt.Sprintf(`{ - "cniVersion": "0.3.1", - "name": "mynet", - "type": "ptp", - "ipMasq": true, - "mtu": 5000, - "ipam": { - "type": "host-local", - "subnet": "10.1.2.0/24" - }, - "dns": %s -}`, string(dnsConfBytes)) - - doTest(conf, 1, dnsConf) - }) - - It("configures and deconfigures a dual-stack ptp link with ADD/DEL", func() { - conf := `{ - "cniVersion": "0.3.1", - "name": "mynet", - "type": "ptp", - "ipMasq": true, - "mtu": 5000, - "ipam": { - "type": "host-local", - "ranges": [ - [{ "subnet": "10.1.2.0/24"}], - [{ "subnet": "2001:db8:1::0/66"}] - ] - } -}` - - doTest(conf, 2, types.DNS{}) - }) - - It("does not override IPAM DNS settings if no DNS settings provided", func() { - ipamDNSConf := types.DNS{ - Nameservers: []string{"10.1.2.123"}, - Domain: "some.domain.test", - Search: []string{"search.test"}, - Options: []string{"option1:foo"}, - } - resolvConfPath, err := testutils.TmpResolvConf(ipamDNSConf) - Expect(err).NotTo(HaveOccurred()) - defer os.RemoveAll(resolvConfPath) - - conf := fmt.Sprintf(`{ - "cniVersion": "0.3.1", - "name": "mynet", - "type": "ptp", - "ipMasq": true, - "mtu": 5000, - "ipam": { - "type": "host-local", - "subnet": "10.1.2.0/24", - "resolvConf": "%s" - } -}`, resolvConfPath) - - doTest(conf, 1, ipamDNSConf) - }) - - It("overrides IPAM DNS settings if any DNS settings provided", func() { - ipamDNSConf := types.DNS{ - Nameservers: []string{"10.1.2.123"}, - Domain: "some.domain.test", - Search: []string{"search.test"}, - Options: []string{"option1:foo"}, - } - resolvConfPath, err := testutils.TmpResolvConf(ipamDNSConf) - Expect(err).NotTo(HaveOccurred()) - defer os.RemoveAll(resolvConfPath) - - for _, ptpDNSConf := range []types.DNS{ - { - Nameservers: []string{"10.1.2.234"}, - }, - { - Domain: "someother.domain.test", - }, - { - Search: []string{"search.elsewhere.test"}, - }, - { - Options: []string{"option2:bar"}, - }, - } { - dnsConfBytes, err := json.Marshal(ptpDNSConf) + 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", + Search: []string{"search.test"}, + Options: []string{"option1:foo"}, + } + dnsConfBytes, err := json.Marshal(dnsConf) Expect(err).NotTo(HaveOccurred()) conf := fmt.Sprintf(`{ - "cniVersion": "0.3.1", - "name": "mynet", - "type": "ptp", - "ipMasq": true, - "mtu": 5000, - "ipam": { - "type": "host-local", - "subnet": "10.1.2.0/24", - "resolvConf": "%s" - }, - "dns": %s -}`, resolvConfPath, string(dnsConfBytes)) + "cniVersion": "%s", + "name": "mynet", + "type": "ptp", + "ipMasq": true, + "mtu": 5000, + "ipam": { + "type": "host-local", + "subnet": "10.1.2.0/24", + "dataDir": "%s" + }, + "dns": %s + }`, ver, dataDir, string(dnsConfBytes)) - doTest(conf, 1, ptpDNSConf) - } - }) + doTest(conf, ver, 1, dnsConf, targetNS) + }) - It("overrides IPAM DNS settings if any empty list DNS settings provided", func() { - ipamDNSConf := types.DNS{ - Nameservers: []string{"10.1.2.123"}, - Domain: "some.domain.test", - Search: []string{"search.test"}, - Options: []string{"option1:foo"}, - } - resolvConfPath, err := testutils.TmpResolvConf(ipamDNSConf) - Expect(err).NotTo(HaveOccurred()) - defer os.RemoveAll(resolvConfPath) + 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, + "mtu": 5000, + "ipam": { + "type": "host-local", + "ranges": [ + [{ "subnet": "10.1.2.0/24"}], + [{ "subnet": "2001:db8:1::0/66"}] + ], + "dataDir": "%s" + } + }`, ver, dataDir) - conf := fmt.Sprintf(`{ - "cniVersion": "0.3.1", - "name": "mynet", - "type": "ptp", - "ipMasq": true, - "mtu": 5000, - "ipam": { - "type": "host-local", - "subnet": "10.1.2.0/24", - "resolvConf": "%s" - }, - "dns": { - "nameservers": [], - "search": [], - "options": [] - } -}`, resolvConfPath) + doTest(conf, ver, 2, types.DNS{}, targetNS) + }) - doTest(conf, 1, types.DNS{}) - }) + 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", + Search: []string{"search.test"}, + Options: []string{"option1:foo"}, + } + resolvConfPath, err := testutils.TmpResolvConf(ipamDNSConf) + Expect(err).NotTo(HaveOccurred()) + defer os.RemoveAll(resolvConfPath) - It("deconfigures an unconfigured ptp link with DEL", func() { - const IFNAME = "ptp0" + conf := fmt.Sprintf(`{ + "cniVersion": "%s", + "name": "mynet", + "type": "ptp", + "ipMasq": true, + "mtu": 5000, + "ipam": { + "type": "host-local", + "subnet": "10.1.2.0/24", + "resolvConf": "%s", + "dataDir": "%s" + } + }`, ver, resolvConfPath, dataDir) - conf := fmt.Sprintf(`{ - "cniVersion": "%s", - "name": "mynet", - "type": "ptp", - "ipMasq": true, - "mtu": 5000, - "ipam": { - "type": "host-local", - "subnet": "10.1.2.0/24" - } -}`, current.ImplementedSpecVersion) + doTest(conf, ver, 1, ipamDNSConf, targetNS) + }) - targetNs, err := testutils.NewNS() - Expect(err).NotTo(HaveOccurred()) - defer targetNs.Close() + 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", + Search: []string{"search.test"}, + Options: []string{"option1:foo"}, + } + resolvConfPath, err := testutils.TmpResolvConf(ipamDNSConf) + Expect(err).NotTo(HaveOccurred()) + defer os.RemoveAll(resolvConfPath) - args := &skel.CmdArgs{ - ContainerID: "dummy", - Netns: targetNs.Path(), - IfName: IFNAME, - StdinData: []byte(conf), - } + for _, ptpDNSConf := range []types.DNS{ + { + Nameservers: []string{"10.1.2.234"}, + }, + { + Domain: "someother.domain.test", + }, + { + Search: []string{"search.elsewhere.test"}, + }, + { + Options: []string{"option2:bar"}, + }, + } { + dnsConfBytes, err := json.Marshal(ptpDNSConf) + Expect(err).NotTo(HaveOccurred()) - // 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 { - defer GinkgoRecover() + conf := fmt.Sprintf(`{ + "cniVersion": "%s", + "name": "mynet", + "type": "ptp", + "ipMasq": true, + "mtu": 5000, + "ipam": { + "type": "host-local", + "subnet": "10.1.2.0/24", + "resolvConf": "%s", + "dataDir": "%s" + }, + "dns": %s + }`, ver, resolvConfPath, dataDir, string(dnsConfBytes)) - err := testutils.CmdDelWithArgs(args, func() error { - return cmdDel(args) + doTest(conf, ver, 1, ptpDNSConf, targetNS) + } + }) + + 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", + Search: []string{"search.test"}, + Options: []string{"option1:foo"}, + } + resolvConfPath, err := testutils.TmpResolvConf(ipamDNSConf) + Expect(err).NotTo(HaveOccurred()) + defer os.RemoveAll(resolvConfPath) + + conf := fmt.Sprintf(`{ + "cniVersion": "%s", + "name": "mynet", + "type": "ptp", + "ipMasq": true, + "mtu": 5000, + "ipam": { + "type": "host-local", + "subnet": "10.1.2.0/24", + "dataDir": "%s", + "resolvConf": "%s" + }, + "dns": { + "nameservers": [], + "search": [], + "options": [] + } + }`, ver, dataDir, resolvConfPath) + + doTest(conf, ver, 1, types.DNS{}, targetNS) + }) + + It(fmt.Sprintf("[%s] deconfigures an unconfigured ptp link with DEL", ver), func() { + const IFNAME = "ptp0" + + 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" + } + }`, ver, dataDir) + + args := &skel.CmdArgs{ + ContainerID: "dummy", + 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 { + defer GinkgoRecover() + + err := testutils.CmdDelWithArgs(args, func() error { + return cmdDel(args) + }) + Expect(err).NotTo(HaveOccurred()) + return nil }) Expect(err).NotTo(HaveOccurred()) - return nil }) - 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) - }) + } })