From: Casey Callendrello Date: Fri, 2 Jun 2017 14:25:42 +0000 (+0200) Subject: pkg: move packages from cni to plugins X-Git-Url: https://git.halfball.org/?a=commitdiff_plain;h=fe14708aeeea0eb74b08728fb6a6ad4b748d1383;p=cni.git pkg: move packages from cni to plugins --- diff --git a/pkg/ip/cidr.go b/pkg/ip/cidr.go deleted file mode 100644 index dae2c4d..0000000 --- a/pkg/ip/cidr.go +++ /dev/null @@ -1,51 +0,0 @@ -// 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 ip - -import ( - "math/big" - "net" -) - -// NextIP returns IP incremented by 1 -func NextIP(ip net.IP) net.IP { - i := ipToInt(ip) - return intToIP(i.Add(i, big.NewInt(1))) -} - -// PrevIP returns IP decremented by 1 -func PrevIP(ip net.IP) net.IP { - i := ipToInt(ip) - return intToIP(i.Sub(i, big.NewInt(1))) -} - -func ipToInt(ip net.IP) *big.Int { - if v := ip.To4(); v != nil { - return big.NewInt(0).SetBytes(v) - } - return big.NewInt(0).SetBytes(ip.To16()) -} - -func intToIP(i *big.Int) net.IP { - return net.IP(i.Bytes()) -} - -// Network masks off the host portion of the IP -func Network(ipn *net.IPNet) *net.IPNet { - return &net.IPNet{ - IP: ipn.IP.Mask(ipn.Mask), - Mask: ipn.Mask, - } -} diff --git a/pkg/ip/ip_suite_test.go b/pkg/ip/ip_suite_test.go deleted file mode 100644 index 3fdd57e..0000000 --- a/pkg/ip/ip_suite_test.go +++ /dev/null @@ -1,27 +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 ip_test - -import ( - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - - "testing" -) - -func TestIp(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Ip Suite") -} diff --git a/pkg/ip/ipforward.go b/pkg/ip/ipforward.go deleted file mode 100644 index 77ee746..0000000 --- a/pkg/ip/ipforward.go +++ /dev/null @@ -1,31 +0,0 @@ -// 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 ip - -import ( - "io/ioutil" -) - -func EnableIP4Forward() error { - return echo1("/proc/sys/net/ipv4/ip_forward") -} - -func EnableIP6Forward() error { - return echo1("/proc/sys/net/ipv6/conf/all/forwarding") -} - -func echo1(f string) error { - return ioutil.WriteFile(f, []byte("1"), 0644) -} diff --git a/pkg/ip/ipmasq.go b/pkg/ip/ipmasq.go deleted file mode 100644 index 8ee2797..0000000 --- a/pkg/ip/ipmasq.go +++ /dev/null @@ -1,66 +0,0 @@ -// 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 ip - -import ( - "fmt" - "net" - - "github.com/coreos/go-iptables/iptables" -) - -// SetupIPMasq installs iptables rules to masquerade traffic -// coming from ipn and going outside of it -func SetupIPMasq(ipn *net.IPNet, chain string, comment string) error { - ipt, err := iptables.New() - if err != nil { - return fmt.Errorf("failed to locate iptables: %v", err) - } - - if err = ipt.NewChain("nat", chain); err != nil { - if err.(*iptables.Error).ExitStatus() != 1 { - // TODO(eyakubovich): assumes exit status 1 implies chain exists - return err - } - } - - if err = ipt.AppendUnique("nat", chain, "-d", ipn.String(), "-j", "ACCEPT", "-m", "comment", "--comment", comment); err != nil { - return err - } - - if err = ipt.AppendUnique("nat", chain, "!", "-d", "224.0.0.0/4", "-j", "MASQUERADE", "-m", "comment", "--comment", comment); err != nil { - return err - } - - return ipt.AppendUnique("nat", "POSTROUTING", "-s", ipn.String(), "-j", chain, "-m", "comment", "--comment", comment) -} - -// TeardownIPMasq undoes the effects of SetupIPMasq -func TeardownIPMasq(ipn *net.IPNet, chain string, comment string) error { - ipt, err := iptables.New() - if err != nil { - return fmt.Errorf("failed to locate iptables: %v", err) - } - - if err = ipt.Delete("nat", "POSTROUTING", "-s", ipn.String(), "-j", chain, "-m", "comment", "--comment", comment); err != nil { - return err - } - - if err = ipt.ClearChain("nat", chain); err != nil { - return err - } - - return ipt.DeleteChain("nat", chain) -} diff --git a/pkg/ip/link.go b/pkg/ip/link.go deleted file mode 100644 index a984262..0000000 --- a/pkg/ip/link.go +++ /dev/null @@ -1,219 +0,0 @@ -// 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 ip - -import ( - "crypto/rand" - "errors" - "fmt" - "net" - "os" - - "github.com/containernetworking/cni/pkg/ns" - "github.com/containernetworking/cni/pkg/utils/hwaddr" - "github.com/vishvananda/netlink" -) - -var ( - ErrLinkNotFound = errors.New("link not found") -) - -func makeVethPair(name, peer string, mtu int) (netlink.Link, error) { - veth := &netlink.Veth{ - LinkAttrs: netlink.LinkAttrs{ - Name: name, - Flags: net.FlagUp, - MTU: mtu, - }, - PeerName: peer, - } - if err := netlink.LinkAdd(veth); err != nil { - return nil, err - } - - return veth, nil -} - -func peerExists(name string) bool { - if _, err := netlink.LinkByName(name); err != nil { - return false - } - return true -} - -func makeVeth(name string, mtu int) (peerName string, veth netlink.Link, err error) { - for i := 0; i < 10; i++ { - peerName, err = RandomVethName() - if err != nil { - return - } - - veth, err = makeVethPair(name, peerName, mtu) - switch { - case err == nil: - return - - case os.IsExist(err): - if peerExists(peerName) { - continue - } - err = fmt.Errorf("container veth name provided (%v) already exists", name) - return - - default: - err = fmt.Errorf("failed to make veth pair: %v", err) - return - } - } - - // should really never be hit - err = fmt.Errorf("failed to find a unique veth name") - return -} - -// RandomVethName returns string "veth" with random prefix (hashed from entropy) -func RandomVethName() (string, error) { - entropy := make([]byte, 4) - _, err := rand.Reader.Read(entropy) - if err != nil { - return "", fmt.Errorf("failed to generate random veth name: %v", err) - } - - // NetworkManager (recent versions) will ignore veth devices that start with "veth" - return fmt.Sprintf("veth%x", entropy), nil -} - -func RenameLink(curName, newName string) error { - link, err := netlink.LinkByName(curName) - if err == nil { - err = netlink.LinkSetName(link, newName) - } - return err -} - -func ifaceFromNetlinkLink(l netlink.Link) net.Interface { - a := l.Attrs() - return net.Interface{ - Index: a.Index, - MTU: a.MTU, - Name: a.Name, - HardwareAddr: a.HardwareAddr, - Flags: a.Flags, - } -} - -// SetupVeth sets up a pair of virtual ethernet devices. -// Call SetupVeth from inside the container netns. It will create both veth -// devices and move the host-side veth into the provided hostNS namespace. -// On success, SetupVeth returns (hostVeth, containerVeth, nil) -func SetupVeth(contVethName string, mtu int, hostNS ns.NetNS) (net.Interface, net.Interface, error) { - hostVethName, contVeth, err := makeVeth(contVethName, mtu) - if err != nil { - return net.Interface{}, net.Interface{}, err - } - - if err = netlink.LinkSetUp(contVeth); err != nil { - return net.Interface{}, net.Interface{}, fmt.Errorf("failed to set %q up: %v", contVethName, err) - } - - hostVeth, err := netlink.LinkByName(hostVethName) - if err != nil { - return net.Interface{}, net.Interface{}, fmt.Errorf("failed to lookup %q: %v", hostVethName, err) - } - - if err = netlink.LinkSetNsFd(hostVeth, int(hostNS.Fd())); err != nil { - return net.Interface{}, net.Interface{}, fmt.Errorf("failed to move veth to host netns: %v", err) - } - - err = hostNS.Do(func(_ ns.NetNS) error { - hostVeth, err = netlink.LinkByName(hostVethName) - if err != nil { - return fmt.Errorf("failed to lookup %q in %q: %v", hostVethName, hostNS.Path(), err) - } - - if err = netlink.LinkSetUp(hostVeth); err != nil { - return fmt.Errorf("failed to set %q up: %v", hostVethName, err) - } - return nil - }) - if err != nil { - return net.Interface{}, net.Interface{}, err - } - return ifaceFromNetlinkLink(hostVeth), ifaceFromNetlinkLink(contVeth), nil -} - -// DelLinkByName removes an interface link. -func DelLinkByName(ifName string) error { - iface, err := netlink.LinkByName(ifName) - if err != nil { - return fmt.Errorf("failed to lookup %q: %v", ifName, err) - } - - if err = netlink.LinkDel(iface); err != nil { - return fmt.Errorf("failed to delete %q: %v", ifName, err) - } - - return nil -} - -// DelLinkByNameAddr remove an interface returns its IP address -// of the specified family -func DelLinkByNameAddr(ifName string, family int) (*net.IPNet, error) { - iface, err := netlink.LinkByName(ifName) - if err != nil { - if err != nil && err.Error() == "Link not found" { - return nil, ErrLinkNotFound - } - return nil, fmt.Errorf("failed to lookup %q: %v", ifName, err) - } - - addrs, err := netlink.AddrList(iface, family) - if err != nil || len(addrs) == 0 { - return nil, fmt.Errorf("failed to get IP addresses for %q: %v", ifName, err) - } - - if err = netlink.LinkDel(iface); err != nil { - return nil, fmt.Errorf("failed to delete %q: %v", ifName, err) - } - - return addrs[0].IPNet, nil -} - -func SetHWAddrByIP(ifName string, ip4 net.IP, ip6 net.IP) error { - iface, err := netlink.LinkByName(ifName) - if err != nil { - return fmt.Errorf("failed to lookup %q: %v", ifName, err) - } - - switch { - case ip4 == nil && ip6 == nil: - return fmt.Errorf("neither ip4 or ip6 specified") - - case ip4 != nil: - { - hwAddr, err := hwaddr.GenerateHardwareAddr4(ip4, hwaddr.PrivateMACPrefix) - if err != nil { - return fmt.Errorf("failed to generate hardware addr: %v", err) - } - if err = netlink.LinkSetHardwareAddr(iface, hwAddr); err != nil { - return fmt.Errorf("failed to add hardware addr to %q: %v", ifName, err) - } - } - case ip6 != nil: - // TODO: IPv6 - } - - return nil -} diff --git a/pkg/ip/link_test.go b/pkg/ip/link_test.go deleted file mode 100644 index 23182a5..0000000 --- a/pkg/ip/link_test.go +++ /dev/null @@ -1,273 +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 ip_test - -import ( - "bytes" - "crypto/rand" - "fmt" - "net" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - - "github.com/containernetworking/cni/pkg/ip" - "github.com/containernetworking/cni/pkg/ns" - - "github.com/vishvananda/netlink" - "github.com/vishvananda/netlink/nl" -) - -func getHwAddr(linkname string) string { - veth, err := netlink.LinkByName(linkname) - Expect(err).NotTo(HaveOccurred()) - return fmt.Sprintf("%s", veth.Attrs().HardwareAddr) -} - -var _ = Describe("Link", func() { - const ( - ifaceFormatString string = "i%d" - mtu int = 1400 - ip4onehwaddr = "0a:58:01:01:01:01" - ) - var ( - hostNetNS ns.NetNS - containerNetNS ns.NetNS - ifaceCounter int = 0 - hostVeth net.Interface - containerVeth net.Interface - hostVethName string - containerVethName string - - ip4one = net.ParseIP("1.1.1.1") - ip4two = net.ParseIP("1.1.1.2") - originalRandReader = rand.Reader - ) - - BeforeEach(func() { - var err error - - hostNetNS, err = ns.NewNS() - Expect(err).NotTo(HaveOccurred()) - - containerNetNS, err = ns.NewNS() - Expect(err).NotTo(HaveOccurred()) - - fakeBytes := make([]byte, 20) - //to be reset in AfterEach block - rand.Reader = bytes.NewReader(fakeBytes) - - _ = containerNetNS.Do(func(ns.NetNS) error { - defer GinkgoRecover() - - hostVeth, containerVeth, err = ip.SetupVeth(fmt.Sprintf(ifaceFormatString, ifaceCounter), mtu, hostNetNS) - if err != nil { - return err - } - Expect(err).NotTo(HaveOccurred()) - - hostVethName = hostVeth.Name - containerVethName = containerVeth.Name - - return nil - }) - }) - - AfterEach(func() { - Expect(containerNetNS.Close()).To(Succeed()) - Expect(hostNetNS.Close()).To(Succeed()) - ifaceCounter++ - rand.Reader = originalRandReader - }) - - It("SetupVeth must put the veth endpoints into the separate namespaces", func() { - _ = containerNetNS.Do(func(ns.NetNS) error { - defer GinkgoRecover() - - containerVethFromName, err := netlink.LinkByName(containerVethName) - Expect(err).NotTo(HaveOccurred()) - Expect(containerVethFromName.Attrs().Index).To(Equal(containerVeth.Index)) - - return nil - }) - - _ = hostNetNS.Do(func(ns.NetNS) error { - defer GinkgoRecover() - - hostVethFromName, err := netlink.LinkByName(hostVethName) - Expect(err).NotTo(HaveOccurred()) - Expect(hostVethFromName.Attrs().Index).To(Equal(hostVeth.Index)) - - return nil - }) - }) - - Context("when container already has an interface with the same name", func() { - It("returns useful error", func() { - _ = containerNetNS.Do(func(ns.NetNS) error { - defer GinkgoRecover() - - _, _, err := ip.SetupVeth(containerVethName, mtu, hostNetNS) - Expect(err.Error()).To(Equal(fmt.Sprintf("container veth name provided (%s) already exists", containerVethName))) - - return nil - }) - }) - }) - - Context("deleting an non-existent device", func() { - It("returns known error", func() { - _ = containerNetNS.Do(func(ns.NetNS) error { - defer GinkgoRecover() - - // This string should match the expected error codes in the cmdDel functions of some of the plugins - _, err := ip.DelLinkByNameAddr("THIS_DONT_EXIST", netlink.FAMILY_V4) - Expect(err).To(Equal(ip.ErrLinkNotFound)) - - return nil - }) - }) - }) - - Context("when there is no name available for the host-side", func() { - BeforeEach(func() { - //adding different interface to container ns - containerVethName += "0" - }) - It("returns useful error", func() { - _ = containerNetNS.Do(func(ns.NetNS) error { - defer GinkgoRecover() - - _, _, err := ip.SetupVeth(containerVethName, mtu, hostNetNS) - Expect(err.Error()).To(Equal("failed to move veth to host netns: file exists")) - - return nil - }) - }) - }) - - Context("when there is no name conflict for the host or container interfaces", func() { - BeforeEach(func() { - //adding different interface to container and host ns - containerVethName += "0" - rand.Reader = originalRandReader - }) - It("successfully creates the second veth pair", func() { - _ = containerNetNS.Do(func(ns.NetNS) error { - defer GinkgoRecover() - - hostVeth, _, err := ip.SetupVeth(containerVethName, mtu, hostNetNS) - Expect(err).NotTo(HaveOccurred()) - hostVethName = hostVeth.Name - return nil - }) - - //verify veths are in different namespaces - _ = containerNetNS.Do(func(ns.NetNS) error { - defer GinkgoRecover() - - _, err := netlink.LinkByName(containerVethName) - Expect(err).NotTo(HaveOccurred()) - - return nil - }) - - _ = hostNetNS.Do(func(ns.NetNS) error { - defer GinkgoRecover() - - _, err := netlink.LinkByName(hostVethName) - Expect(err).NotTo(HaveOccurred()) - - return nil - }) - }) - - }) - - It("DelLinkByName must delete the veth endpoints", func() { - _ = containerNetNS.Do(func(ns.NetNS) error { - defer GinkgoRecover() - - // this will delete the host endpoint too - err := ip.DelLinkByName(containerVethName) - Expect(err).NotTo(HaveOccurred()) - - _, err = netlink.LinkByName(containerVethName) - Expect(err).To(HaveOccurred()) - - return nil - }) - - _ = hostNetNS.Do(func(ns.NetNS) error { - defer GinkgoRecover() - - _, err := netlink.LinkByName(hostVethName) - Expect(err).To(HaveOccurred()) - - return nil - }) - }) - - It("DelLinkByNameAddr must throw an error for configured interfaces", func() { - _ = containerNetNS.Do(func(ns.NetNS) error { - defer GinkgoRecover() - - // this will delete the host endpoint too - addr, err := ip.DelLinkByNameAddr(containerVethName, nl.FAMILY_V4) - Expect(err).To(HaveOccurred()) - - var ipNetNil *net.IPNet - Expect(addr).To(Equal(ipNetNil)) - return nil - }) - }) - - It("SetHWAddrByIP must change the interface hwaddr and be predictable", func() { - - _ = containerNetNS.Do(func(ns.NetNS) error { - defer GinkgoRecover() - - var err error - hwaddrBefore := getHwAddr(containerVethName) - - err = ip.SetHWAddrByIP(containerVethName, ip4one, nil) - Expect(err).NotTo(HaveOccurred()) - hwaddrAfter1 := getHwAddr(containerVethName) - - Expect(hwaddrBefore).NotTo(Equal(hwaddrAfter1)) - Expect(hwaddrAfter1).To(Equal(ip4onehwaddr)) - - return nil - }) - }) - - It("SetHWAddrByIP must be injective", func() { - - _ = containerNetNS.Do(func(ns.NetNS) error { - defer GinkgoRecover() - - err := ip.SetHWAddrByIP(containerVethName, ip4one, nil) - Expect(err).NotTo(HaveOccurred()) - hwaddrAfter1 := getHwAddr(containerVethName) - - err = ip.SetHWAddrByIP(containerVethName, ip4two, nil) - Expect(err).NotTo(HaveOccurred()) - hwaddrAfter2 := getHwAddr(containerVethName) - - Expect(hwaddrAfter1).NotTo(Equal(hwaddrAfter2)) - return nil - }) - }) -}) diff --git a/pkg/ip/route.go b/pkg/ip/route.go deleted file mode 100644 index 1325a47..0000000 --- a/pkg/ip/route.go +++ /dev/null @@ -1,27 +0,0 @@ -// 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 ip - -import ( - "net" - - "github.com/vishvananda/netlink" -) - -// AddDefaultRoute sets the default route on the given gateway. -func AddDefaultRoute(gw net.IP, dev netlink.Link) error { - _, defNet, _ := net.ParseCIDR("0.0.0.0/0") - return AddRoute(defNet, gw, dev) -} diff --git a/pkg/ip/route_linux.go b/pkg/ip/route_linux.go deleted file mode 100644 index 8b11807..0000000 --- a/pkg/ip/route_linux.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2015-2017 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 ip - -import ( - "net" - - "github.com/vishvananda/netlink" -) - -// AddRoute adds a universally-scoped route to a device. -func AddRoute(ipn *net.IPNet, gw net.IP, dev netlink.Link) error { - return netlink.RouteAdd(&netlink.Route{ - LinkIndex: dev.Attrs().Index, - Scope: netlink.SCOPE_UNIVERSE, - Dst: ipn, - Gw: gw, - }) -} - -// AddHostRoute adds a host-scoped route to a device. -func AddHostRoute(ipn *net.IPNet, gw net.IP, dev netlink.Link) error { - return netlink.RouteAdd(&netlink.Route{ - LinkIndex: dev.Attrs().Index, - Scope: netlink.SCOPE_HOST, - Dst: ipn, - Gw: gw, - }) -} diff --git a/pkg/ip/route_unspecified.go b/pkg/ip/route_unspecified.go deleted file mode 100644 index 7e79fde..0000000 --- a/pkg/ip/route_unspecified.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2015-2017 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. - -// +build !linux - -package ip - -import ( - "net" - - "github.com/containernetworking/cni/pkg/types" - "github.com/vishvananda/netlink" -) - -// AddRoute adds a universally-scoped route to a device. -func AddRoute(ipn *net.IPNet, gw net.IP, dev netlink.Link) error { - return types.NotImplementedError -} - -// AddHostRoute adds a host-scoped route to a device. -func AddHostRoute(ipn *net.IPNet, gw net.IP, dev netlink.Link) error { - return types.NotImplementedError -} diff --git a/pkg/ipam/ipam.go b/pkg/ipam/ipam.go deleted file mode 100644 index b76780f..0000000 --- a/pkg/ipam/ipam.go +++ /dev/null @@ -1,93 +0,0 @@ -// 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 ( - "fmt" - "net" - "os" - - "github.com/containernetworking/cni/pkg/invoke" - "github.com/containernetworking/cni/pkg/ip" - "github.com/containernetworking/cni/pkg/types" - "github.com/containernetworking/cni/pkg/types/current" - - "github.com/vishvananda/netlink" -) - -func ExecAdd(plugin string, netconf []byte) (types.Result, error) { - return invoke.DelegateAdd(plugin, netconf) -} - -func ExecDel(plugin string, netconf []byte) error { - return invoke.DelegateDel(plugin, netconf) -} - -// ConfigureIface takes the result of IPAM plugin and -// applies to the ifName interface -func ConfigureIface(ifName string, res *current.Result) error { - if len(res.Interfaces) == 0 { - return fmt.Errorf("no interfaces to configure") - } - - link, err := netlink.LinkByName(ifName) - if err != nil { - return fmt.Errorf("failed to lookup %q: %v", ifName, err) - } - - if err := netlink.LinkSetUp(link); err != nil { - return fmt.Errorf("failed to set %q UP: %v", ifName, err) - } - - var v4gw, v6gw net.IP - for _, ipc := range res.IPs { - if int(ipc.Interface) >= len(res.Interfaces) || res.Interfaces[ipc.Interface].Name != ifName { - // IP address is for a different interface - return fmt.Errorf("failed to add IP addr %v to %q: invalid interface index", ipc, ifName) - } - - addr := &netlink.Addr{IPNet: &ipc.Address, Label: ""} - if err = netlink.AddrAdd(link, addr); err != nil { - return fmt.Errorf("failed to add IP addr %v to %q: %v", ipc, ifName, err) - } - - gwIsV4 := ipc.Gateway.To4() != nil - if gwIsV4 && v4gw == nil { - v4gw = ipc.Gateway - } else if !gwIsV4 && v6gw == nil { - v6gw = ipc.Gateway - } - } - - for _, r := range res.Routes { - routeIsV4 := r.Dst.IP.To4() != nil - gw := r.GW - if gw == nil { - if routeIsV4 && v4gw != nil { - gw = v4gw - } else if !routeIsV4 && v6gw != nil { - gw = v6gw - } - } - if err = ip.AddRoute(&r.Dst, gw, link); err != nil { - // we skip over duplicate routes as we assume the first one wins - if !os.IsExist(err) { - return fmt.Errorf("failed to add route '%v via %v dev %v': %v", r.Dst, gw, ifName, err) - } - } - } - - return nil -} diff --git a/pkg/ipam/ipam_suite_test.go b/pkg/ipam/ipam_suite_test.go deleted file mode 100644 index e80c867..0000000 --- a/pkg/ipam/ipam_suite_test.go +++ /dev/null @@ -1,27 +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 ipam_test - -import ( - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - - "testing" -) - -func TestIpam(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Ipam Suite") -} diff --git a/pkg/ipam/ipam_test.go b/pkg/ipam/ipam_test.go deleted file mode 100644 index 2d27825..0000000 --- a/pkg/ipam/ipam_test.go +++ /dev/null @@ -1,258 +0,0 @@ -// 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 = ¤t.Result{ - Interfaces: []*current.Interface{ - { - Name: "eth0", - Mac: "00:11:22:33:44:55", - Sandbox: "/proc/3553/ns/net", - }, - { - Name: "fake0", - Mac: "00:33:44:55:66:77", - Sandbox: "/proc/1234/ns/net", - }, - }, - IPs: []*current.IPConfig{ - { - Version: "4", - Interface: 0, - Address: *ipv4, - Gateway: ipgw4, - }, - { - Version: "6", - Interface: 0, - Address: *ipv6, - Gateway: ipgw6, - }, - }, - Routes: []*types.Route{ - {Dst: *routev4, GW: routegwv4}, - {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)) - - v6addrs, err := netlink.AddrList(link, syscall.AF_INET6) - Expect(err).NotTo(HaveOccurred()) - Expect(len(v6addrs)).To(Equal(2)) - - var found bool - for _, a := range v6addrs { - if ipNetEqual(a.IPNet, ipv6) { - found = true - break - } - } - Expect(found).To(Equal(true)) - - // Ensure the v4 route, v6 route, and subnet route - routes, err := netlink.RouteList(link, 0) - Expect(err).NotTo(HaveOccurred()) - - var v4found, v6found bool - for _, route := range routes { - isv4 := route.Dst.IP.To4() != nil - if isv4 && ipNetEqual(route.Dst, routev4) && route.Gw.Equal(routegwv4) { - v4found = true - } - if !isv4 && ipNetEqual(route.Dst, routev6) && route.Gw.Equal(routegwv6) { - v6found = true - } - - if v4found && v6found { - break - } - } - Expect(v4found).To(Equal(true)) - Expect(v6found).To(Equal(true)) - - return nil - }) - Expect(err).NotTo(HaveOccurred()) - }) - - It("configures a link with routes using address gateways", func() { - result.Routes[0].GW = nil - result.Routes[1].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, v6 route, and subnet route - routes, err := netlink.RouteList(link, 0) - Expect(err).NotTo(HaveOccurred()) - - var v4found, v6found bool - for _, route := range routes { - isv4 := route.Dst.IP.To4() != nil - if isv4 && ipNetEqual(route.Dst, routev4) && route.Gw.Equal(ipgw4) { - v4found = true - } - if !isv4 && ipNetEqual(route.Dst, routev6) && route.Gw.Equal(ipgw6) { - v6found = true - } - - if v4found && v6found { - break - } - } - Expect(v4found).To(Equal(true)) - Expect(v6found).To(Equal(true)) - - return nil - }) - Expect(err).NotTo(HaveOccurred()) - }) - - It("returns an error when the interface index doesn't match the link name", func() { - result.IPs[0].Interface = 1 - err := originalNS.Do(func(ns.NetNS) error { - return ConfigureIface(LINK_NAME, result) - }) - Expect(err).To(HaveOccurred()) - }) - - It("returns an error when the interface index is too big", func() { - result.IPs[0].Interface = 2 - err := originalNS.Do(func(ns.NetNS) error { - return ConfigureIface(LINK_NAME, result) - }) - Expect(err).To(HaveOccurred()) - }) - - It("returns an error when there are no interfaces to configure", func() { - result.Interfaces = []*current.Interface{} - err := originalNS.Do(func(ns.NetNS) error { - return ConfigureIface(LINK_NAME, result) - }) - Expect(err).To(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/pkg/ns/README.md b/pkg/ns/README.md deleted file mode 100644 index 99aed9c..0000000 --- a/pkg/ns/README.md +++ /dev/null @@ -1,34 +0,0 @@ -### Namespaces, Threads, and Go -On Linux each OS thread can have a different network namespace. Go's thread scheduling model switches goroutines between OS threads based on OS thread load and whether the goroutine would block other goroutines. This can result in a goroutine switching network namespaces without notice and lead to errors in your code. - -### Namespace Switching -Switching namespaces with the `ns.Set()` method is not recommended without additional strategies to prevent unexpected namespace changes when your goroutines switch OS threads. - -Go provides the `runtime.LockOSThread()` function to ensure a specific goroutine executes on its current OS thread and prevents any other goroutine from running in that thread until the locked one exits. Careful usage of `LockOSThread()` and goroutines can provide good control over which network namespace a given goroutine executes in. - -For example, you cannot rely on the `ns.Set()` namespace being the current namespace after the `Set()` call unless you do two things. First, the goroutine calling `Set()` must have previously called `LockOSThread()`. Second, you must ensure `runtime.UnlockOSThread()` is not called somewhere in-between. You also cannot rely on the initial network namespace remaining the current network namespace if any other code in your program switches namespaces, unless you have already called `LockOSThread()` in that goroutine. Note that `LockOSThread()` prevents the Go scheduler from optimally scheduling goroutines for best performance, so `LockOSThread()` should only be used in small, isolated goroutines that release the lock quickly. - -### Do() The Recommended Thing -The `ns.Do()` method provides control over network namespaces for you by implementing these strategies. All code dependent on a particular network namespace (including the root namespace) should be wrapped in the `ns.Do()` method to ensure the correct namespace is selected for the duration of your code. For example: - -```go -targetNs, err := ns.NewNS() -if err != nil { - return err -} -err = targetNs.Do(func(hostNs ns.NetNS) error { - dummy := &netlink.Dummy{ - LinkAttrs: netlink.LinkAttrs{ - Name: "dummy0", - }, - } - return netlink.LinkAdd(dummy) -}) -``` - -Note this requirement to wrap every network call is very onerous - any libraries you call might call out to network services such as DNS, and all such calls need to be protected after you call `ns.Do()`. The CNI plugins all exit very soon after calling `ns.Do()` which helps to minimize the problem. - -### Further Reading - - https://github.com/golang/go/wiki/LockOSThread - - http://morsmachine.dk/go-scheduler - - https://github.com/containernetworking/cni/issues/262 diff --git a/pkg/ns/ns.go b/pkg/ns/ns.go deleted file mode 100644 index c212f48..0000000 --- a/pkg/ns/ns.go +++ /dev/null @@ -1,178 +0,0 @@ -// 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 ns - -import ( - "fmt" - "os" - "runtime" - "sync" - "syscall" -) - -type NetNS interface { - // Executes the passed closure in this object's network namespace, - // attempting to restore the original namespace before returning. - // However, since each OS thread can have a different network namespace, - // and Go's thread scheduling is highly variable, callers cannot - // guarantee any specific namespace is set unless operations that - // require that namespace are wrapped with Do(). Also, no code called - // from Do() should call runtime.UnlockOSThread(), or the risk - // of executing code in an incorrect namespace will be greater. See - // https://github.com/golang/go/wiki/LockOSThread for further details. - Do(toRun func(NetNS) error) error - - // Sets the current network namespace to this object's network namespace. - // Note that since Go's thread scheduling is highly variable, callers - // cannot guarantee the requested namespace will be the current namespace - // after this function is called; to ensure this wrap operations that - // require the namespace with Do() instead. - Set() error - - // Returns the filesystem path representing this object's network namespace - Path() string - - // Returns a file descriptor representing this object's network namespace - Fd() uintptr - - // Cleans up this instance of the network namespace; if this instance - // is the last user the namespace will be destroyed - Close() error -} - -type netNS struct { - file *os.File - mounted bool - closed bool -} - -// netNS implements the NetNS interface -var _ NetNS = &netNS{} - -const ( - // https://github.com/torvalds/linux/blob/master/include/uapi/linux/magic.h - NSFS_MAGIC = 0x6e736673 - PROCFS_MAGIC = 0x9fa0 -) - -type NSPathNotExistErr struct{ msg string } - -func (e NSPathNotExistErr) Error() string { return e.msg } - -type NSPathNotNSErr struct{ msg string } - -func (e NSPathNotNSErr) Error() string { return e.msg } - -func IsNSorErr(nspath string) error { - stat := syscall.Statfs_t{} - if err := syscall.Statfs(nspath, &stat); err != nil { - if os.IsNotExist(err) { - err = NSPathNotExistErr{msg: fmt.Sprintf("failed to Statfs %q: %v", nspath, err)} - } else { - err = fmt.Errorf("failed to Statfs %q: %v", nspath, err) - } - return err - } - - switch stat.Type { - case PROCFS_MAGIC, NSFS_MAGIC: - return nil - default: - return NSPathNotNSErr{msg: fmt.Sprintf("unknown FS magic on %q: %x", nspath, stat.Type)} - } -} - -// Returns an object representing the namespace referred to by @path -func GetNS(nspath string) (NetNS, error) { - err := IsNSorErr(nspath) - if err != nil { - return nil, err - } - - fd, err := os.Open(nspath) - if err != nil { - return nil, err - } - - return &netNS{file: fd}, nil -} - -func (ns *netNS) Path() string { - return ns.file.Name() -} - -func (ns *netNS) Fd() uintptr { - return ns.file.Fd() -} - -func (ns *netNS) errorIfClosed() error { - if ns.closed { - return fmt.Errorf("%q has already been closed", ns.file.Name()) - } - return nil -} - -func (ns *netNS) Do(toRun func(NetNS) error) error { - if err := ns.errorIfClosed(); err != nil { - return err - } - - containedCall := func(hostNS NetNS) error { - threadNS, err := GetCurrentNS() - if err != nil { - return fmt.Errorf("failed to open current netns: %v", err) - } - defer threadNS.Close() - - // switch to target namespace - if err = ns.Set(); err != nil { - return fmt.Errorf("error switching to ns %v: %v", ns.file.Name(), err) - } - defer threadNS.Set() // switch back - - return toRun(hostNS) - } - - // save a handle to current network namespace - hostNS, err := GetCurrentNS() - if err != nil { - return fmt.Errorf("Failed to open current namespace: %v", err) - } - defer hostNS.Close() - - var wg sync.WaitGroup - wg.Add(1) - - var innerError error - go func() { - defer wg.Done() - runtime.LockOSThread() - innerError = containedCall(hostNS) - }() - wg.Wait() - - return innerError -} - -// WithNetNSPath executes the passed closure under the given network -// namespace, restoring the original namespace afterwards. -func WithNetNSPath(nspath string, toRun func(NetNS) error) error { - ns, err := GetNS(nspath) - if err != nil { - return err - } - defer ns.Close() - return ns.Do(toRun) -} diff --git a/pkg/ns/ns_linux.go b/pkg/ns/ns_linux.go deleted file mode 100644 index c9e1b4f..0000000 --- a/pkg/ns/ns_linux.go +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright 2015-2017 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 ns - -import ( - "crypto/rand" - "fmt" - "os" - "path" - "runtime" - "sync" - - "golang.org/x/sys/unix" -) - -// Returns an object representing the current OS thread's network namespace -func GetCurrentNS() (NetNS, error) { - return GetNS(getCurrentThreadNetNSPath()) -} - -func getCurrentThreadNetNSPath() string { - // /proc/self/ns/net returns the namespace of the main thread, not - // of whatever thread this goroutine is running on. Make sure we - // use the thread's net namespace since the thread is switching around - return fmt.Sprintf("/proc/%d/task/%d/ns/net", os.Getpid(), unix.Gettid()) -} - -// Creates a new persistent network namespace and returns an object -// representing that namespace, without switching to it -func NewNS() (NetNS, error) { - const nsRunDir = "/var/run/netns" - - b := make([]byte, 16) - _, err := rand.Reader.Read(b) - if err != nil { - return nil, fmt.Errorf("failed to generate random netns name: %v", err) - } - - err = os.MkdirAll(nsRunDir, 0755) - if err != nil { - return nil, err - } - - // create an empty file at the mount point - nsName := fmt.Sprintf("cni-%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:]) - nsPath := path.Join(nsRunDir, nsName) - mountPointFd, err := os.Create(nsPath) - if err != nil { - return nil, err - } - mountPointFd.Close() - - // Ensure the mount point is cleaned up on errors; if the namespace - // was successfully mounted this will have no effect because the file - // is in-use - defer os.RemoveAll(nsPath) - - var wg sync.WaitGroup - wg.Add(1) - - // do namespace work in a dedicated goroutine, so that we can safely - // Lock/Unlock OSThread without upsetting the lock/unlock state of - // the caller of this function - var fd *os.File - go (func() { - defer wg.Done() - runtime.LockOSThread() - - var origNS NetNS - origNS, err = GetNS(getCurrentThreadNetNSPath()) - if err != nil { - return - } - defer origNS.Close() - - // create a new netns on the current thread - err = unix.Unshare(unix.CLONE_NEWNET) - if err != nil { - return - } - defer origNS.Set() - - // bind mount the new netns from the current thread onto the mount point - err = unix.Mount(getCurrentThreadNetNSPath(), nsPath, "none", unix.MS_BIND, "") - if err != nil { - return - } - - fd, err = os.Open(nsPath) - if err != nil { - return - } - })() - wg.Wait() - - if err != nil { - unix.Unmount(nsPath, unix.MNT_DETACH) - return nil, fmt.Errorf("failed to create namespace: %v", err) - } - - return &netNS{file: fd, mounted: true}, nil -} - -func (ns *netNS) Close() error { - if err := ns.errorIfClosed(); err != nil { - return err - } - - if err := ns.file.Close(); err != nil { - return fmt.Errorf("Failed to close %q: %v", ns.file.Name(), err) - } - ns.closed = true - - if ns.mounted { - if err := unix.Unmount(ns.file.Name(), unix.MNT_DETACH); err != nil { - return fmt.Errorf("Failed to unmount namespace %s: %v", ns.file.Name(), err) - } - if err := os.RemoveAll(ns.file.Name()); err != nil { - return fmt.Errorf("Failed to clean up namespace %s: %v", ns.file.Name(), err) - } - ns.mounted = false - } - - return nil -} - -func (ns *netNS) Set() error { - if err := ns.errorIfClosed(); err != nil { - return err - } - - if _, _, err := unix.Syscall(unix.SYS_SETNS, ns.Fd(), uintptr(unix.CLONE_NEWNET), 0); err != 0 { - return fmt.Errorf("Error switching to ns %v: %v", ns.file.Name(), err) - } - - return nil -} diff --git a/pkg/ns/ns_suite_test.go b/pkg/ns/ns_suite_test.go deleted file mode 100644 index e2adaa4..0000000 --- a/pkg/ns/ns_suite_test.go +++ /dev/null @@ -1,34 +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 ns_test - -import ( - "math/rand" - "runtime" - - . "github.com/onsi/ginkgo" - "github.com/onsi/ginkgo/config" - . "github.com/onsi/gomega" - - "testing" -) - -func TestNs(t *testing.T) { - rand.Seed(config.GinkgoConfig.RandomSeed) - runtime.LockOSThread() - - RegisterFailHandler(Fail) - RunSpecs(t, "pkg/ns Suite") -} diff --git a/pkg/ns/ns_test.go b/pkg/ns/ns_test.go deleted file mode 100644 index 44ed272..0000000 --- a/pkg/ns/ns_test.go +++ /dev/null @@ -1,252 +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 ns_test - -import ( - "errors" - "fmt" - "io/ioutil" - "os" - "path/filepath" - - "github.com/containernetworking/cni/pkg/ns" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - "golang.org/x/sys/unix" -) - -func getInodeCurNetNS() (uint64, error) { - curNS, err := ns.GetCurrentNS() - if err != nil { - return 0, err - } - defer curNS.Close() - return getInodeNS(curNS) -} - -func getInodeNS(netns ns.NetNS) (uint64, error) { - return getInodeFd(int(netns.Fd())) -} - -func getInode(path string) (uint64, error) { - file, err := os.Open(path) - if err != nil { - return 0, err - } - defer file.Close() - return getInodeFd(int(file.Fd())) -} - -func getInodeFd(fd int) (uint64, error) { - stat := &unix.Stat_t{} - err := unix.Fstat(fd, stat) - return stat.Ino, err -} - -var _ = Describe("Linux namespace operations", func() { - Describe("WithNetNS", func() { - var ( - originalNetNS ns.NetNS - targetNetNS ns.NetNS - ) - - BeforeEach(func() { - var err error - - originalNetNS, err = ns.NewNS() - Expect(err).NotTo(HaveOccurred()) - - targetNetNS, err = ns.NewNS() - Expect(err).NotTo(HaveOccurred()) - }) - - AfterEach(func() { - Expect(targetNetNS.Close()).To(Succeed()) - Expect(originalNetNS.Close()).To(Succeed()) - }) - - It("executes the callback within the target network namespace", func() { - expectedInode, err := getInodeNS(targetNetNS) - Expect(err).NotTo(HaveOccurred()) - - err = targetNetNS.Do(func(ns.NetNS) error { - defer GinkgoRecover() - - actualInode, err := getInodeCurNetNS() - Expect(err).NotTo(HaveOccurred()) - Expect(actualInode).To(Equal(expectedInode)) - return nil - }) - Expect(err).NotTo(HaveOccurred()) - }) - - It("provides the original namespace as the argument to the callback", func() { - // Ensure we start in originalNetNS - err := originalNetNS.Do(func(ns.NetNS) error { - defer GinkgoRecover() - - origNSInode, err := getInodeNS(originalNetNS) - Expect(err).NotTo(HaveOccurred()) - - err = targetNetNS.Do(func(hostNS ns.NetNS) error { - defer GinkgoRecover() - - hostNSInode, err := getInodeNS(hostNS) - Expect(err).NotTo(HaveOccurred()) - Expect(hostNSInode).To(Equal(origNSInode)) - return nil - }) - return nil - }) - Expect(err).NotTo(HaveOccurred()) - }) - - Context("when the callback returns an error", func() { - It("restores the calling thread to the original namespace before returning", func() { - err := originalNetNS.Do(func(ns.NetNS) error { - defer GinkgoRecover() - - preTestInode, err := getInodeCurNetNS() - Expect(err).NotTo(HaveOccurred()) - - _ = targetNetNS.Do(func(ns.NetNS) error { - return errors.New("potato") - }) - - postTestInode, err := getInodeCurNetNS() - Expect(err).NotTo(HaveOccurred()) - Expect(postTestInode).To(Equal(preTestInode)) - return nil - }) - Expect(err).NotTo(HaveOccurred()) - }) - - It("returns the error from the callback", func() { - err := targetNetNS.Do(func(ns.NetNS) error { - return errors.New("potato") - }) - Expect(err).To(MatchError("potato")) - }) - }) - - Describe("validating inode mapping to namespaces", func() { - It("checks that different namespaces have different inodes", func() { - origNSInode, err := getInodeNS(originalNetNS) - Expect(err).NotTo(HaveOccurred()) - - testNsInode, err := getInodeNS(targetNetNS) - Expect(err).NotTo(HaveOccurred()) - - Expect(testNsInode).NotTo(Equal(0)) - Expect(testNsInode).NotTo(Equal(origNSInode)) - }) - - It("should not leak a closed netns onto any threads in the process", func() { - By("creating a new netns") - createdNetNS, err := ns.NewNS() - Expect(err).NotTo(HaveOccurred()) - - By("discovering the inode of the created netns") - createdNetNSInode, err := getInodeNS(createdNetNS) - Expect(err).NotTo(HaveOccurred()) - createdNetNS.Close() - - By("comparing against the netns inode of every thread in the process") - for _, netnsPath := range allNetNSInCurrentProcess() { - netnsInode, err := getInode(netnsPath) - Expect(err).NotTo(HaveOccurred()) - Expect(netnsInode).NotTo(Equal(createdNetNSInode)) - } - }) - - It("fails when the path is not a namespace", func() { - tempFile, err := ioutil.TempFile("", "nstest") - Expect(err).NotTo(HaveOccurred()) - defer tempFile.Close() - - nspath := tempFile.Name() - defer os.Remove(nspath) - - _, err = ns.GetNS(nspath) - Expect(err).To(HaveOccurred()) - Expect(err).To(BeAssignableToTypeOf(ns.NSPathNotNSErr{})) - Expect(err).NotTo(BeAssignableToTypeOf(ns.NSPathNotExistErr{})) - }) - }) - - Describe("closing a network namespace", func() { - It("should prevent further operations", func() { - createdNetNS, err := ns.NewNS() - Expect(err).NotTo(HaveOccurred()) - - err = createdNetNS.Close() - Expect(err).NotTo(HaveOccurred()) - - err = createdNetNS.Do(func(ns.NetNS) error { return nil }) - Expect(err).To(HaveOccurred()) - - err = createdNetNS.Set() - Expect(err).To(HaveOccurred()) - }) - - It("should only work once", func() { - createdNetNS, err := ns.NewNS() - Expect(err).NotTo(HaveOccurred()) - - err = createdNetNS.Close() - Expect(err).NotTo(HaveOccurred()) - - err = createdNetNS.Close() - Expect(err).To(HaveOccurred()) - }) - }) - }) - - Describe("IsNSorErr", func() { - It("should detect a namespace", func() { - createdNetNS, err := ns.NewNS() - err = ns.IsNSorErr(createdNetNS.Path()) - Expect(err).NotTo(HaveOccurred()) - }) - - It("should refuse other paths", func() { - tempFile, err := ioutil.TempFile("", "nstest") - Expect(err).NotTo(HaveOccurred()) - defer tempFile.Close() - - nspath := tempFile.Name() - defer os.Remove(nspath) - - err = ns.IsNSorErr(nspath) - Expect(err).To(HaveOccurred()) - Expect(err).To(BeAssignableToTypeOf(ns.NSPathNotNSErr{})) - Expect(err).NotTo(BeAssignableToTypeOf(ns.NSPathNotExistErr{})) - }) - - It("should error on non-existing paths", func() { - err := ns.IsNSorErr("/tmp/IDoNotExist") - Expect(err).To(HaveOccurred()) - Expect(err).To(BeAssignableToTypeOf(ns.NSPathNotExistErr{})) - Expect(err).NotTo(BeAssignableToTypeOf(ns.NSPathNotNSErr{})) - }) - }) -}) - -func allNetNSInCurrentProcess() []string { - pid := unix.Getpid() - paths, err := filepath.Glob(fmt.Sprintf("/proc/%d/task/*/ns/net", pid)) - Expect(err).NotTo(HaveOccurred()) - return paths -} diff --git a/pkg/ns/ns_unspecified.go b/pkg/ns/ns_unspecified.go deleted file mode 100644 index 41b4468..0000000 --- a/pkg/ns/ns_unspecified.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2015-2017 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. - -// +build !linux - -package ns - -import "github.com/containernetworking/cni/pkg/types" - -// Returns an object representing the current OS thread's network namespace -func GetCurrentNS() (NetNS, error) { - return nil, types.NotImplementedError -} - -func NewNS() (NetNS, error) { - return nil, types.NotImplementedError -} - -func (ns *netNS) Close() error { - return types.NotImplementedError -} - -func (ns *netNS) Set() error { - return types.NotImplementedError -} diff --git a/pkg/skel/skel_test.go b/pkg/skel/skel_test.go index ad29308..e85bc2b 100644 --- a/pkg/skel/skel_test.go +++ b/pkg/skel/skel_test.go @@ -22,7 +22,6 @@ import ( "github.com/containernetworking/cni/pkg/types" "github.com/containernetworking/cni/pkg/version" - "github.com/containernetworking/cni/pkg/testutils" . "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo/extensions/table" . "github.com/onsi/gomega" @@ -289,7 +288,7 @@ var _ = Describe("dispatching to the correct callback", func() { Context("when stdin cannot be read", func() { BeforeEach(func() { - dispatch.Stdin = &testutils.BadReader{} + dispatch.Stdin = &BadReader{} }) It("does not call any cmd callback", func() { @@ -344,3 +343,19 @@ var _ = Describe("dispatching to the correct callback", func() { }) }) }) + +// BadReader is an io.Reader which always errors +type BadReader struct { + Error error +} + +func (r *BadReader) Read(buffer []byte) (int, error) { + if r.Error != nil { + return 0, r.Error + } + return 0, errors.New("banana") +} + +func (r *BadReader) Close() error { + return nil +} diff --git a/pkg/testutils/bad_reader.go b/pkg/testutils/bad_reader.go deleted file mode 100644 index f9d0ade..0000000 --- a/pkg/testutils/bad_reader.go +++ /dev/null @@ -1,33 +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 testutils - -import "errors" - -// BadReader is an io.Reader which always errors -type BadReader struct { - Error error -} - -func (r *BadReader) Read(buffer []byte) (int, error) { - if r.Error != nil { - return 0, r.Error - } - return 0, errors.New("banana") -} - -func (r *BadReader) Close() error { - return nil -} diff --git a/pkg/testutils/cmd.go b/pkg/testutils/cmd.go deleted file mode 100644 index a6045b3..0000000 --- a/pkg/testutils/cmd.go +++ /dev/null @@ -1,85 +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 testutils - -import ( - "io/ioutil" - "os" - - "github.com/containernetworking/cni/pkg/types" - "github.com/containernetworking/cni/pkg/version" -) - -func envCleanup() { - os.Unsetenv("CNI_COMMAND") - os.Unsetenv("CNI_PATH") - os.Unsetenv("CNI_NETNS") - os.Unsetenv("CNI_IFNAME") -} - -func CmdAddWithResult(cniNetns, cniIfname string, conf []byte, f func() error) (types.Result, []byte, error) { - os.Setenv("CNI_COMMAND", "ADD") - os.Setenv("CNI_PATH", os.Getenv("PATH")) - os.Setenv("CNI_NETNS", cniNetns) - os.Setenv("CNI_IFNAME", cniIfname) - defer envCleanup() - - // Redirect stdout to capture plugin result - oldStdout := os.Stdout - r, w, err := os.Pipe() - if err != nil { - return nil, nil, err - } - - os.Stdout = w - err = f() - w.Close() - - var out []byte - if err == nil { - out, err = ioutil.ReadAll(r) - } - os.Stdout = oldStdout - - // Return errors after restoring stdout so Ginkgo will correctly - // emit verbose error information on stdout - if err != nil { - return nil, nil, err - } - - // Plugin must return result in same version as specified in netconf - versionDecoder := &version.ConfigDecoder{} - confVersion, err := versionDecoder.Decode(conf) - if err != nil { - return nil, nil, err - } - - result, err := version.NewResult(confVersion, out) - if err != nil { - return nil, nil, err - } - - return result, out, nil -} - -func CmdDelWithResult(cniNetns, cniIfname string, f func() error) error { - os.Setenv("CNI_COMMAND", "DEL") - os.Setenv("CNI_PATH", os.Getenv("PATH")) - os.Setenv("CNI_NETNS", cniNetns) - os.Setenv("CNI_IFNAME", cniIfname) - defer envCleanup() - - return f() -} diff --git a/pkg/utils/hwaddr/hwaddr.go b/pkg/utils/hwaddr/hwaddr.go deleted file mode 100644 index aaf3b8a..0000000 --- a/pkg/utils/hwaddr/hwaddr.go +++ /dev/null @@ -1,63 +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 hwaddr - -import ( - "fmt" - "net" -) - -const ( - ipRelevantByteLen = 4 - PrivateMACPrefixString = "0a:58" -) - -var ( - // private mac prefix safe to use - PrivateMACPrefix = []byte{0x0a, 0x58} -) - -type SupportIp4OnlyErr struct{ msg string } - -func (e SupportIp4OnlyErr) Error() string { return e.msg } - -type MacParseErr struct{ msg string } - -func (e MacParseErr) Error() string { return e.msg } - -type InvalidPrefixLengthErr struct{ msg string } - -func (e InvalidPrefixLengthErr) Error() string { return e.msg } - -// GenerateHardwareAddr4 generates 48 bit virtual mac addresses based on the IP4 input. -func GenerateHardwareAddr4(ip net.IP, prefix []byte) (net.HardwareAddr, error) { - switch { - - case ip.To4() == nil: - return nil, SupportIp4OnlyErr{msg: "GenerateHardwareAddr4 only supports valid IPv4 address as input"} - - case len(prefix) != len(PrivateMACPrefix): - return nil, InvalidPrefixLengthErr{msg: fmt.Sprintf( - "Prefix has length %d instead of %d", len(prefix), len(PrivateMACPrefix)), - } - } - - ipByteLen := len(ip) - return (net.HardwareAddr)( - append( - prefix, - ip[ipByteLen-ipRelevantByteLen:ipByteLen]...), - ), nil -} diff --git a/pkg/utils/hwaddr/hwaddr_suite_test.go b/pkg/utils/hwaddr/hwaddr_suite_test.go deleted file mode 100644 index e3bbfe9..0000000 --- a/pkg/utils/hwaddr/hwaddr_suite_test.go +++ /dev/null @@ -1,27 +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 hwaddr_test - -import ( - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - - "testing" -) - -func TestHwaddr(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Hwaddr Suite") -} diff --git a/pkg/utils/hwaddr/hwaddr_test.go b/pkg/utils/hwaddr/hwaddr_test.go deleted file mode 100644 index b77ccd8..0000000 --- a/pkg/utils/hwaddr/hwaddr_test.go +++ /dev/null @@ -1,74 +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 hwaddr_test - -import ( - "net" - - "github.com/containernetworking/cni/pkg/utils/hwaddr" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("Hwaddr", func() { - Context("Generate Hardware Address", func() { - It("generate hardware address based on ipv4 address", func() { - testCases := []struct { - ip net.IP - expectedMAC net.HardwareAddr - }{ - { - ip: net.ParseIP("10.0.0.2"), - expectedMAC: (net.HardwareAddr)(append(hwaddr.PrivateMACPrefix, 0x0a, 0x00, 0x00, 0x02)), - }, - { - ip: net.ParseIP("10.250.0.244"), - expectedMAC: (net.HardwareAddr)(append(hwaddr.PrivateMACPrefix, 0x0a, 0xfa, 0x00, 0xf4)), - }, - { - ip: net.ParseIP("172.17.0.2"), - expectedMAC: (net.HardwareAddr)(append(hwaddr.PrivateMACPrefix, 0xac, 0x11, 0x00, 0x02)), - }, - { - ip: net.IPv4(byte(172), byte(17), byte(0), byte(2)), - expectedMAC: (net.HardwareAddr)(append(hwaddr.PrivateMACPrefix, 0xac, 0x11, 0x00, 0x02)), - }, - } - - for _, tc := range testCases { - mac, err := hwaddr.GenerateHardwareAddr4(tc.ip, hwaddr.PrivateMACPrefix) - Expect(err).NotTo(HaveOccurred()) - Expect(mac).To(Equal(tc.expectedMAC)) - } - }) - - It("return error if input is not ipv4 address", func() { - testCases := []net.IP{ - net.ParseIP(""), - net.ParseIP("2001:db8:0:1:1:1:1:1"), - } - for _, tc := range testCases { - _, err := hwaddr.GenerateHardwareAddr4(tc, hwaddr.PrivateMACPrefix) - Expect(err).To(BeAssignableToTypeOf(hwaddr.SupportIp4OnlyErr{})) - } - }) - - It("return error if prefix is invalid", func() { - _, err := hwaddr.GenerateHardwareAddr4(net.ParseIP("10.0.0.2"), []byte{0x58}) - Expect(err).To(BeAssignableToTypeOf(hwaddr.InvalidPrefixLengthErr{})) - }) - }) -}) diff --git a/pkg/utils/sysctl/sysctl_linux.go b/pkg/utils/sysctl/sysctl_linux.go deleted file mode 100644 index fe06d2d..0000000 --- a/pkg/utils/sysctl/sysctl_linux.go +++ /dev/null @@ -1,56 +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 sysctl - -import ( - "fmt" - "io/ioutil" - "path/filepath" - "strings" -) - -// Sysctl provides a method to set/get values from /proc/sys - in linux systems -// new interface to set/get values of variables formerly handled by sysctl syscall -// If optional `params` have only one string value - this function will -// set this value into corresponding sysctl variable -func Sysctl(name string, params ...string) (string, error) { - if len(params) > 1 { - return "", fmt.Errorf("unexcepted additional parameters") - } else if len(params) == 1 { - return setSysctl(name, params[0]) - } - return getSysctl(name) -} - -func getSysctl(name string) (string, error) { - fullName := filepath.Join("/proc/sys", strings.Replace(name, ".", "/", -1)) - fullName = filepath.Clean(fullName) - data, err := ioutil.ReadFile(fullName) - if err != nil { - return "", err - } - - return string(data[:len(data)-1]), nil -} - -func setSysctl(name, value string) (string, error) { - fullName := filepath.Join("/proc/sys", strings.Replace(name, ".", "/", -1)) - fullName = filepath.Clean(fullName) - if err := ioutil.WriteFile(fullName, []byte(value), 0644); err != nil { - return "", err - } - - return getSysctl(name) -} diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go deleted file mode 100644 index 33a2aa7..0000000 --- a/pkg/utils/utils.go +++ /dev/null @@ -1,41 +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 utils - -import ( - "crypto/sha512" - "fmt" -) - -const ( - maxChainLength = 28 - chainPrefix = "CNI-" - prefixLength = len(chainPrefix) -) - -// Generates a chain name to be used with iptables. -// Ensures that the generated chain name is exactly -// maxChainLength chars in length -func FormatChainName(name string, id string) string { - chainBytes := sha512.Sum512([]byte(name + id)) - chain := fmt.Sprintf("%s%x", chainPrefix, chainBytes) - return chain[:maxChainLength] -} - -// FormatComment returns a comment used for easier -// rule identification within iptables. -func FormatComment(name string, id string) string { - return fmt.Sprintf("name: %q id: %q", name, id) -} diff --git a/pkg/utils/utils_suite_test.go b/pkg/utils/utils_suite_test.go deleted file mode 100644 index ee614a7..0000000 --- a/pkg/utils/utils_suite_test.go +++ /dev/null @@ -1,27 +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 utils_test - -import ( - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - - "testing" -) - -func TestUtils(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Utils Suite") -} diff --git a/pkg/utils/utils_test.go b/pkg/utils/utils_test.go deleted file mode 100644 index d703de4..0000000 --- a/pkg/utils/utils_test.go +++ /dev/null @@ -1,51 +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 utils - -import ( - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("Utils", func() { - It("must format a short name", func() { - chain := FormatChainName("test", "1234") - Expect(len(chain)).To(Equal(maxChainLength)) - Expect(chain).To(Equal("CNI-2bbe0c48b91a7d1b8a6753a8")) - }) - - It("must truncate a long name", func() { - chain := FormatChainName("testalongnamethatdoesnotmakesense", "1234") - Expect(len(chain)).To(Equal(maxChainLength)) - Expect(chain).To(Equal("CNI-374f33fe84ab0ed84dcdebe3")) - }) - - It("must be predictable", func() { - chain1 := FormatChainName("testalongnamethatdoesnotmakesense", "1234") - chain2 := FormatChainName("testalongnamethatdoesnotmakesense", "1234") - Expect(len(chain1)).To(Equal(maxChainLength)) - Expect(len(chain2)).To(Equal(maxChainLength)) - Expect(chain1).To(Equal(chain2)) - }) - - It("must change when a character changes", func() { - chain1 := FormatChainName("testalongnamethatdoesnotmakesense", "1234") - chain2 := FormatChainName("testalongnamethatdoesnotmakesense", "1235") - Expect(len(chain1)).To(Equal(maxChainLength)) - Expect(len(chain2)).To(Equal(maxChainLength)) - Expect(chain1).To(Equal("CNI-374f33fe84ab0ed84dcdebe3")) - Expect(chain1).NotTo(Equal(chain2)) - }) -}) diff --git a/test.sh b/test.sh index 7232c61..bcdbd3d 100755 --- a/test.sh +++ b/test.sh @@ -11,8 +11,8 @@ set -e source ./build.sh -TESTABLE="libcni pkg/invoke pkg/ns pkg/skel pkg/types pkg/types/current pkg/types/020 pkg/utils plugins/test/noop pkg/utils/hwaddr pkg/ip pkg/version pkg/version/testhelpers pkg/ipam" -FORMATTABLE="$TESTABLE pkg/testutils" +TESTABLE="libcni pkg/invoke pkg/skel pkg/types pkg/types/current pkg/types/020 pkg/version pkg/version/testhelpers plugins/test/noop" +FORMATTABLE="$TESTABLE" # user has not provided PKG override if [ -z "$PKG" ]; then