diff --git a/plugins/meta/tuning/tuning.go b/plugins/meta/tuning/tuning.go index 98a242f6..ec9fe2e4 100644 --- a/plugins/meta/tuning/tuning.go +++ b/plugins/meta/tuning/tuning.go @@ -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 index 00000000..cdd7b12a --- /dev/null +++ b/plugins/meta/tuning/tuning_suite_test.go @@ -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 index 00000000..e03b0f01 --- /dev/null +++ b/plugins/meta/tuning/tuning_test.go @@ -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()) + }) +})