tuning: pass prevResult through
authorDan Williams <dcbw@redhat.com>
Tue, 25 Jul 2017 04:31:29 +0000 (23:31 -0500)
committerDan Williams <dcbw@redhat.com>
Wed, 26 Jul 2017 19:39:01 +0000 (14:39 -0500)
plugins/meta/tuning/tuning.go
plugins/meta/tuning/tuning_suite_test.go [new file with mode: 0644]
plugins/meta/tuning/tuning_test.go [new file with mode: 0644]

index 98a242f..ec9fe2e 100644 (file)
@@ -34,19 +34,47 @@ import (
 // TuningConf represents the network tuning configuration.
 type TuningConf struct {
        types.NetConf
-       SysCtl map[string]string `json:"sysctl"`
+       SysCtl        map[string]string      `json:"sysctl"`
+       RawPrevResult map[string]interface{} `json:"prevResult,omitempty"`
+       PrevResult    *current.Result        `json:"-"`
+}
+
+func parseConf(data []byte) (*TuningConf, error) {
+       conf := TuningConf{}
+       if err := json.Unmarshal(data, &conf); err != nil {
+               return nil, fmt.Errorf("failed to load netconf: %v", err)
+       }
+
+       // Parse previous result.
+       if conf.RawPrevResult != nil {
+               resultBytes, err := json.Marshal(conf.RawPrevResult)
+               if err != nil {
+                       return nil, fmt.Errorf("could not serialize prevResult: %v", err)
+               }
+               res, err := version.NewResult(conf.CNIVersion, resultBytes)
+               if err != nil {
+                       return nil, fmt.Errorf("could not parse prevResult: %v", err)
+               }
+               conf.RawPrevResult = nil
+               conf.PrevResult, err = current.NewResultFromResult(res)
+               if err != nil {
+                       return nil, fmt.Errorf("could not convert result to current version: %v", err)
+               }
+       }
+
+       return &conf, nil
 }
 
 func cmdAdd(args *skel.CmdArgs) error {
-       tuningConf := TuningConf{}
-       if err := json.Unmarshal(args.StdinData, &tuningConf); err != nil {
-               return fmt.Errorf("failed to load netconf: %v", err)
+       tuningConf, err := parseConf(args.StdinData)
+       if err != nil {
+               return err
        }
 
        // The directory /proc/sys/net is per network namespace. Enter in the
        // network namespace before writing on it.
 
-       err := ns.WithNetNSPath(args.Netns, func(_ ns.NetNS) error {
+       err = ns.WithNetNSPath(args.Netns, func(_ ns.NetNS) error {
                for key, value := range tuningConf.SysCtl {
                        fileName := filepath.Join("/proc/sys", strings.Replace(key, ".", "/", -1))
                        fileName = filepath.Clean(fileName)
@@ -68,8 +96,7 @@ func cmdAdd(args *skel.CmdArgs) error {
                return err
        }
 
-       result := current.Result{}
-       return result.Print()
+       return types.PrintResult(tuningConf.PrevResult, tuningConf.CNIVersion)
 }
 
 func cmdDel(args *skel.CmdArgs) error {
diff --git a/plugins/meta/tuning/tuning_suite_test.go b/plugins/meta/tuning/tuning_suite_test.go
new file mode 100644 (file)
index 0000000..cdd7b12
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 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 main
+
+import (
+       . "github.com/onsi/ginkgo"
+       . "github.com/onsi/gomega"
+
+       "testing"
+)
+
+func TestTuning(t *testing.T) {
+       RegisterFailHandler(Fail)
+       RunSpecs(t, "tuning Suite")
+}
diff --git a/plugins/meta/tuning/tuning_test.go b/plugins/meta/tuning/tuning_test.go
new file mode 100644 (file)
index 0000000..e03b0f0
--- /dev/null
@@ -0,0 +1,112 @@
+// Copyright 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 main
+
+import (
+       "github.com/containernetworking/cni/pkg/skel"
+       "github.com/containernetworking/cni/pkg/types/current"
+       "github.com/containernetworking/plugins/pkg/ns"
+       "github.com/containernetworking/plugins/pkg/testutils"
+
+       "github.com/vishvananda/netlink"
+
+       . "github.com/onsi/ginkgo"
+       . "github.com/onsi/gomega"
+)
+
+var _ = Describe("tuning plugin", func() {
+       var originalNS ns.NetNS
+       const IFNAME string = "dummy0"
+
+       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()
+
+                       err = netlink.LinkAdd(&netlink.Dummy{
+                               LinkAttrs: netlink.LinkAttrs{
+                                       Name: IFNAME,
+                               },
+                       })
+                       Expect(err).NotTo(HaveOccurred())
+                       _, err = netlink.LinkByName(IFNAME)
+                       Expect(err).NotTo(HaveOccurred())
+                       return nil
+               })
+               Expect(err).NotTo(HaveOccurred())
+       })
+
+       AfterEach(func() {
+               Expect(originalNS.Close()).To(Succeed())
+       })
+
+       It("passes prevResult through unchanged", func() {
+               conf := []byte(`{
+       "name": "test",
+       "type": "tuning",
+       "cniVersion": "0.3.1",
+       "sysctl": {
+               "net.ipv4.conf.all.log_martians": "1"
+       },
+       "prevResult": {
+               "interfaces": [
+                       {"name": "dummy0", "sandbox":"netns"}
+               ],
+               "ips": [
+                       {
+                               "version": "4",
+                               "address": "10.0.0.2/24",
+                               "gateway": "10.0.0.1",
+                               "interface": 0
+                       }
+               ]
+       }
+}`)
+
+               targetNs, err := ns.NewNS()
+               Expect(err).NotTo(HaveOccurred())
+               defer targetNs.Close()
+
+               args := &skel.CmdArgs{
+                       ContainerID: "dummy",
+                       Netns:       targetNs.Path(),
+                       IfName:      IFNAME,
+                       StdinData:   conf,
+               }
+
+               err = originalNS.Do(func(ns.NetNS) error {
+                       defer GinkgoRecover()
+
+                       r, _, err := testutils.CmdAddWithResult(targetNs.Path(), IFNAME, []byte(conf), func() error {
+                               return cmdAdd(args)
+                       })
+                       Expect(err).NotTo(HaveOccurred())
+
+                       result, err := current.GetResult(r)
+                       Expect(err).NotTo(HaveOccurred())
+
+                       Expect(len(result.Interfaces)).To(Equal(1))
+                       Expect(result.Interfaces[0].Name).To(Equal(IFNAME))
+                       Expect(len(result.IPs)).To(Equal(1))
+                       Expect(result.IPs[0].Address.String()).To(Equal("10.0.0.2/24"))
+                       return nil
+               })
+               Expect(err).NotTo(HaveOccurred())
+       })
+})