host-local: trim whitespace from container IDs and disk file contents
authorDan Williams <dcbw@redhat.com>
Sat, 10 Dec 2016 00:16:38 +0000 (18:16 -0600)
committerDan Williams <dcbw@redhat.com>
Sat, 10 Dec 2016 00:16:38 +0000 (18:16 -0600)
It doesn't seem like container IDs should really have whitespace or
newlines in them.  As a complete edge-case, manipulating the host-local
store's IP reservations with 'echo' puts a newline at the end, which
caused matching to fail in ReleaseByID().  Don't ask...

plugins/ipam/host-local/backend/disk/backend.go
plugins/ipam/host-local/host_local_test.go

index 14dd40d..703ec09 100644 (file)
@@ -20,6 +20,7 @@ import (
        "net"
        "os"
        "path/filepath"
+       "strings"
 )
 
 const lastIPFile = "last_reserved_ip"
@@ -56,7 +57,7 @@ func (s *Store) Reserve(id string, ip net.IP) (bool, error) {
        if err != nil {
                return false, err
        }
-       if _, err := f.WriteString(id); err != nil {
+       if _, err := f.WriteString(strings.TrimSpace(id)); err != nil {
                f.Close()
                os.Remove(f.Name())
                return false, err
@@ -99,7 +100,7 @@ func (s *Store) ReleaseByID(id string) error {
                if err != nil {
                        return nil
                }
-               if string(data) == id {
+               if strings.TrimSpace(string(data)) == strings.TrimSpace(id) {
                        if err := os.Remove(path); err != nil {
                                return nil
                        }
index 41dba71..97b3b6f 100644 (file)
@@ -89,4 +89,52 @@ var _ = Describe("host-local Operations", func() {
                _, err = os.Stat(ipFilePath)
                Expect(err).To(HaveOccurred())
        })
+
+       It("ignores whitespace in disk files", func() {
+               const ifname string = "eth0"
+               const nspath string = "/some/where"
+
+               tmpDir, err := ioutil.TempDir("", "host_local_artifacts")
+               Expect(err).NotTo(HaveOccurred())
+               defer os.RemoveAll(tmpDir)
+
+               conf := fmt.Sprintf(`{
+    "cniVersion": "0.2.0",
+    "name": "mynet",
+    "type": "ipvlan",
+    "master": "foo0",
+    "ipam": {
+        "type": "host-local",
+        "subnet": "10.1.2.0/24",
+        "dataDir": "%s"
+    }
+}`, tmpDir)
+
+               args := &skel.CmdArgs{
+                       ContainerID: "   dummy\n ",
+                       Netns:       nspath,
+                       IfName:      ifname,
+                       StdinData:   []byte(conf),
+               }
+
+               // Allocate the IP
+               result, err := testutils.CmdAddWithResult(nspath, ifname, func() error {
+                       return cmdAdd(args)
+               })
+               Expect(err).NotTo(HaveOccurred())
+
+               ipFilePath := filepath.Join(tmpDir, "mynet", result.IP4.IP.IP.String())
+               contents, err := ioutil.ReadFile(ipFilePath)
+               Expect(err).NotTo(HaveOccurred())
+               Expect(string(contents)).To(Equal("dummy"))
+
+               // Release the IP
+               err = testutils.CmdDelWithResult(nspath, ifname, func() error {
+                       return cmdDel(args)
+               })
+               Expect(err).NotTo(HaveOccurred())
+
+               _, err = os.Stat(ipFilePath)
+               Expect(err).To(HaveOccurred())
+       })
 })