pkg/ipam: add testcases
authorDan Williams <dcbw@redhat.com>
Thu, 19 Jan 2017 14:44:35 +0000 (08:44 -0600)
committerDan Williams <dcbw@redhat.com>
Wed, 25 Jan 2017 17:31:18 +0000 (11:31 -0600)
pkg/ipam/ipam_test.go [new file with mode: 0644]
test

diff --git a/pkg/ipam/ipam_test.go b/pkg/ipam/ipam_test.go
new file mode 100644 (file)
index 0000000..622e4c8
--- /dev/null
@@ -0,0 +1,196 @@
+// Copyright 2015 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 ipam
+
+import (
+       "net"
+       "syscall"
+
+       "github.com/containernetworking/cni/pkg/ns"
+       "github.com/containernetworking/cni/pkg/types"
+       "github.com/containernetworking/cni/pkg/types/current"
+
+       "github.com/vishvananda/netlink"
+
+       . "github.com/onsi/ginkgo"
+       . "github.com/onsi/gomega"
+)
+
+const LINK_NAME = "eth0"
+
+func ipNetEqual(a, b *net.IPNet) bool {
+       aPrefix, aBits := a.Mask.Size()
+       bPrefix, bBits := b.Mask.Size()
+       if aPrefix != bPrefix || aBits != bBits {
+               return false
+       }
+       return a.IP.Equal(b.IP)
+}
+
+var _ = Describe("IPAM Operations", func() {
+       var originalNS ns.NetNS
+       var ipv4, ipv6, routev4, routev6 *net.IPNet
+       var ipgw4, ipgw6, routegwv4, routegwv6 net.IP
+       var result *current.Result
+
+       BeforeEach(func() {
+               // Create a new NetNS so we don't modify the host
+               var err error
+               originalNS, err = ns.NewNS()
+               Expect(err).NotTo(HaveOccurred())
+
+               err = originalNS.Do(func(ns.NetNS) error {
+                       defer GinkgoRecover()
+
+                       // Add master
+                       err = netlink.LinkAdd(&netlink.Dummy{
+                               LinkAttrs: netlink.LinkAttrs{
+                                       Name: LINK_NAME,
+                               },
+                       })
+                       Expect(err).NotTo(HaveOccurred())
+                       _, err = netlink.LinkByName(LINK_NAME)
+                       Expect(err).NotTo(HaveOccurred())
+                       return nil
+               })
+               Expect(err).NotTo(HaveOccurred())
+
+               ipv4, err = types.ParseCIDR("1.2.3.30/24")
+               Expect(err).NotTo(HaveOccurred())
+               Expect(ipv4).NotTo(BeNil())
+
+               _, routev4, err = net.ParseCIDR("15.5.6.8/24")
+               Expect(err).NotTo(HaveOccurred())
+               Expect(routev4).NotTo(BeNil())
+               routegwv4 = net.ParseIP("1.2.3.5")
+               Expect(routegwv4).NotTo(BeNil())
+
+               ipgw4 = net.ParseIP("1.2.3.1")
+               Expect(ipgw4).NotTo(BeNil())
+
+               ipv6, err = types.ParseCIDR("abcd:1234:ffff::cdde/64")
+               Expect(err).NotTo(HaveOccurred())
+               Expect(ipv6).NotTo(BeNil())
+
+               _, routev6, err = net.ParseCIDR("1111:dddd::aaaa/80")
+               Expect(err).NotTo(HaveOccurred())
+               Expect(routev6).NotTo(BeNil())
+               routegwv6 = net.ParseIP("abcd:1234:ffff::10")
+               Expect(routegwv6).NotTo(BeNil())
+
+               ipgw6 = net.ParseIP("abcd:1234:ffff::1")
+               Expect(ipgw6).NotTo(BeNil())
+
+               result = &current.Result{
+                       IP4: &current.IPConfig{
+                               IP:      *ipv4,
+                               Gateway: ipgw4,
+                               Routes: []types.Route{
+                                       {Dst: *routev4, GW: routegwv4},
+                               },
+                       },
+                       IP6: &current.IPConfig{
+                               IP:      *ipv6,
+                               Gateway: ipgw6,
+                               Routes: []types.Route{
+                                       {Dst: *routev6, GW: routegwv6},
+                               },
+                       },
+               }
+       })
+
+       AfterEach(func() {
+               Expect(originalNS.Close()).To(Succeed())
+       })
+
+       It("configures a link with addresses and routes", func() {
+               err := originalNS.Do(func(ns.NetNS) error {
+                       defer GinkgoRecover()
+
+                       err := ConfigureIface(LINK_NAME, result)
+                       Expect(err).NotTo(HaveOccurred())
+
+                       link, err := netlink.LinkByName(LINK_NAME)
+                       Expect(err).NotTo(HaveOccurred())
+                       Expect(link.Attrs().Name).To(Equal(LINK_NAME))
+
+                       v4addrs, err := netlink.AddrList(link, syscall.AF_INET)
+                       Expect(err).NotTo(HaveOccurred())
+                       Expect(len(v4addrs)).To(Equal(1))
+                       Expect(ipNetEqual(v4addrs[0].IPNet, ipv4)).To(Equal(true))
+
+                       // Doesn't support IPv6 yet so only link-local address expected
+                       v6addrs, err := netlink.AddrList(link, syscall.AF_INET6)
+                       Expect(err).NotTo(HaveOccurred())
+                       Expect(len(v6addrs)).To(Equal(1))
+
+                       // Ensure the v4 route
+                       routes, err := netlink.RouteList(link, 0)
+                       Expect(err).NotTo(HaveOccurred())
+
+                       var v4found bool
+                       for _, route := range routes {
+                               isv4 := route.Dst.IP.To4() != nil
+                               if isv4 && ipNetEqual(route.Dst, routev4) && route.Gw.Equal(routegwv4) {
+                                       v4found = true
+                                       break
+                               }
+                       }
+                       Expect(v4found).To(Equal(true))
+
+                       return nil
+               })
+               Expect(err).NotTo(HaveOccurred())
+       })
+
+       It("configures a link with routes using address gateways", func() {
+               result.IP4.Routes[0].GW = nil
+               result.IP6.Routes[0].GW = nil
+               err := originalNS.Do(func(ns.NetNS) error {
+                       defer GinkgoRecover()
+
+                       err := ConfigureIface(LINK_NAME, result)
+                       Expect(err).NotTo(HaveOccurred())
+
+                       link, err := netlink.LinkByName(LINK_NAME)
+                       Expect(err).NotTo(HaveOccurred())
+                       Expect(link.Attrs().Name).To(Equal(LINK_NAME))
+
+                       // Ensure the v4 route
+                       routes, err := netlink.RouteList(link, 0)
+                       Expect(err).NotTo(HaveOccurred())
+
+                       var v4found bool
+                       for _, route := range routes {
+                               isv4 := route.Dst.IP.To4() != nil
+                               if isv4 && ipNetEqual(route.Dst, routev4) && route.Gw.Equal(ipgw4) {
+                                       v4found = true
+                                       break
+                               }
+                       }
+                       Expect(v4found).To(Equal(true))
+
+                       return nil
+               })
+               Expect(err).NotTo(HaveOccurred())
+       })
+
+       It("returns an error when configuring the wrong interface", func() {
+               err := originalNS.Do(func(ns.NetNS) error {
+                       return ConfigureIface("asdfasdf", result)
+               })
+               Expect(err).To(HaveOccurred())
+       })
+})
diff --git a/test b/test
index 511997a..d8a1fe3 100755 (executable)
--- a/test
+++ b/test
@@ -11,7 +11,7 @@ set -e
 
 source ./build
 
-TESTABLE="libcni plugins/ipam/dhcp plugins/ipam/host-local plugins/ipam/host-local/backend/allocator plugins/main/loopback pkg/invoke pkg/ns pkg/skel pkg/types pkg/types/current pkg/utils plugins/main/ipvlan plugins/main/macvlan plugins/main/bridge plugins/main/ptp plugins/test/noop pkg/utils/hwaddr pkg/ip pkg/version pkg/version/testhelpers plugins/meta/flannel"
+TESTABLE="libcni plugins/ipam/dhcp plugins/ipam/host-local plugins/ipam/host-local/backend/allocator plugins/main/loopback pkg/invoke pkg/ns pkg/skel pkg/types pkg/types/current pkg/utils plugins/main/ipvlan plugins/main/macvlan plugins/main/bridge plugins/main/ptp plugins/test/noop pkg/utils/hwaddr pkg/ip pkg/version pkg/version/testhelpers plugins/meta/flannel pkg/ipam"
 FORMATTABLE="$TESTABLE pkg/testutils plugins/meta/flannel plugins/meta/tuning"
 
 # user has not provided PKG override