flannel: add integration test suite
authorMark St.Godard <markstgodard@gmail.com>
Sat, 5 Nov 2016 15:47:07 +0000 (10:47 -0500)
committerMark St.Godard <markstgodard@gmail.com>
Sat, 5 Nov 2016 15:47:07 +0000 (10:47 -0500)
add new test for flannel plugin that delegates to the noop plugin and
validates that 'storeDir' can be configurable

plugins/meta/flannel/flannel_suite_test.go [new file with mode: 0644]
plugins/meta/flannel/flannel_test.go [new file with mode: 0644]
test

diff --git a/plugins/meta/flannel/flannel_suite_test.go b/plugins/meta/flannel/flannel_suite_test.go
new file mode 100644 (file)
index 0000000..ec8c611
--- /dev/null
@@ -0,0 +1,66 @@
+// 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 main_test
+
+import (
+       "encoding/json"
+       "fmt"
+       "path/filepath"
+
+       . "github.com/onsi/ginkgo"
+       . "github.com/onsi/gomega"
+       "github.com/onsi/gomega/gexec"
+
+       "testing"
+)
+
+func TestFlannel(t *testing.T) {
+       RegisterFailHandler(Fail)
+       RunSpecs(t, "Flannel Suite")
+}
+
+const flannelPackage = "github.com/containernetworking/cni/plugins/meta/flannel"
+const noopPackage = "github.com/containernetworking/cni/plugins/test/noop"
+
+var paths testPaths
+
+type testPaths struct {
+       PathToPlugin string
+       CNIPath      string
+}
+
+var _ = SynchronizedBeforeSuite(func() []byte {
+       noopBin, err := gexec.Build(noopPackage)
+       Expect(err).NotTo(HaveOccurred())
+       noopDir, _ := filepath.Split(noopBin)
+
+       pathToPlugin, err := gexec.Build(flannelPackage)
+       Expect(err).NotTo(HaveOccurred())
+       flannelDir, _ := filepath.Split(pathToPlugin)
+
+       paths := testPaths{
+               PathToPlugin: pathToPlugin,
+               CNIPath:      fmt.Sprintf("%s:%s", flannelDir, noopDir),
+       }
+
+       data, err := json.Marshal(paths)
+       Expect(err).NotTo(HaveOccurred())
+       return data
+}, func(data []byte) {
+       Expect(json.Unmarshal(data, &paths)).To(Succeed())
+})
+
+var _ = SynchronizedAfterSuite(func() {}, func() {
+       gexec.CleanupBuildArtifacts()
+})
diff --git a/plugins/meta/flannel/flannel_test.go b/plugins/meta/flannel/flannel_test.go
new file mode 100644 (file)
index 0000000..d7b47eb
--- /dev/null
@@ -0,0 +1,173 @@
+// 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 main_test
+
+import (
+       "fmt"
+       "io/ioutil"
+       "os"
+       "os/exec"
+       "strings"
+
+       "github.com/containernetworking/cni/pkg/skel"
+
+       noop_debug "github.com/containernetworking/cni/plugins/test/noop/debug"
+       . "github.com/onsi/ginkgo"
+       . "github.com/onsi/gomega"
+       "github.com/onsi/gomega/gexec"
+)
+
+var _ = Describe("Flannel", func() {
+       var (
+               cmd             *exec.Cmd
+               debugFileName   string
+               input           string
+               debug           *noop_debug.Debug
+               expectedCmdArgs skel.CmdArgs
+       )
+
+       const delegateInput = `
+{
+               "type": "noop",
+               "some": "other data"
+}
+`
+
+       const inputTemplate = `
+{
+  "name": "cni-flannel",
+  "type": "flannel",
+       "subnetFile": "%s",
+       "stateDir": "%s",
+       "delegate": ` +
+               delegateInput +
+               `}`
+
+       const flannelSubnetEnv = `
+FLANNEL_NETWORK=10.1.0.0/16
+FLANNEL_SUBNET=10.1.17.1/24
+FLANNEL_MTU=1472
+FLANNEL_IPMASQ=true
+`
+
+       var cniCommand = func(command, input string) *exec.Cmd {
+               toReturn := exec.Command(paths.PathToPlugin)
+               toReturn.Env = []string{
+                       "CNI_COMMAND=" + command,
+                       "CNI_CONTAINERID=some-container-id",
+                       "CNI_NETNS=/some/netns/path",
+                       "CNI_IFNAME=some-eth0",
+                       "CNI_PATH=" + paths.CNIPath,
+                       "CNI_ARGS=DEBUG=" + debugFileName,
+               }
+               toReturn.Stdin = strings.NewReader(input)
+               return toReturn
+       }
+
+       BeforeEach(func() {
+               debugFile, err := ioutil.TempFile("", "cni_debug")
+               Expect(err).NotTo(HaveOccurred())
+               Expect(debugFile.Close()).To(Succeed())
+               debugFileName = debugFile.Name()
+
+               debug = &noop_debug.Debug{
+                       ReportResult:         `{ "ip4": { "ip": "1.2.3.4/32" } }`,
+                       ReportVersionSupport: []string{"0.1.0", "0.2.0", "0.3.0"},
+               }
+               Expect(debug.WriteDebug(debugFileName)).To(Succeed())
+       })
+
+       AfterEach(func() {
+               os.Remove(debugFileName)
+       })
+
+       Describe("CNI lifecycle", func() {
+               Context("when subnetFile and stateDir are specified", func() {
+                       var (
+                               subnetFile string
+                               stateDir   string
+                       )
+
+                       BeforeEach(func() {
+                               var err error
+                               file, err := ioutil.TempFile("", "subnet.env")
+                               Expect(err).NotTo(HaveOccurred())
+                               _, err = file.WriteString(flannelSubnetEnv)
+                               Expect(err).NotTo(HaveOccurred())
+                               subnetFile = file.Name()
+
+                               stateDir, err = ioutil.TempDir("", "stateDir")
+                               Expect(err).NotTo(HaveOccurred())
+                               input = fmt.Sprintf(inputTemplate, subnetFile, stateDir)
+
+                               expectedCmdArgs = skel.CmdArgs{
+                                       ContainerID: "some-container-id",
+                                       Netns:       "/some/netns/path",
+                                       IfName:      "some-eth0",
+                                       Args:        "DEBUG=" + debugFileName,
+                                       Path:        "/some/bin/path",
+                                       StdinData:   []byte(input),
+                               }
+                               cmd = cniCommand("ADD", input)
+                       })
+
+                       AfterEach(func() {
+                               os.Remove(subnetFile)
+                               os.Remove(stateDir)
+                       })
+
+                       It("uses stateDir for storing network configuration", func() {
+                               By("calling ADD")
+                               session, err := gexec.Start(cmd, GinkgoWriter, GinkgoWriter)
+                               Expect(err).NotTo(HaveOccurred())
+                               Eventually(session).Should(gexec.Exit(0))
+                               Expect(session.Out.Contents()).To(MatchJSON(`{ "ip4": { "ip": "1.2.3.4/32" }, "dns":{} }`))
+
+                               By("check that plugin writes to net config to stateDir")
+                               path := fmt.Sprintf("%s/%s", stateDir, "some-container-id")
+                               Expect(path).Should(BeAnExistingFile())
+
+                               netConfBytes, err := ioutil.ReadFile(path)
+                               Expect(err).NotTo(HaveOccurred())
+                               expected := `{
+   "name" : "cni-flannel",
+   "type" : "noop",
+   "ipam" : {
+      "type" : "host-local",
+      "subnet" : "10.1.17.0/24",
+      "routes" : [
+         {
+            "dst" : "10.1.0.0/16"
+         }
+      ]
+   },
+   "mtu" : 1472,
+   "ipMasq" : false,
+   "some" : "other data"
+}
+`
+                               Expect(netConfBytes).Should(MatchJSON(expected))
+
+                               By("calling DEL")
+                               cmd = cniCommand("DEL", input)
+                               session, err = gexec.Start(cmd, GinkgoWriter, GinkgoWriter)
+                               Expect(err).NotTo(HaveOccurred())
+                               Eventually(session).Should(gexec.Exit(0))
+
+                               By("check that plugin removes net config from state dir")
+                               Expect(path).ShouldNot(BeAnExistingFile())
+                       })
+               })
+       })
+})
diff --git a/test b/test
index 8c2b3ce..d32b134 100755 (executable)
--- a/test
+++ b/test
@@ -11,7 +11,7 @@ set -e
 
 source ./build
 
-TESTABLE="libcni plugins/ipam/dhcp plugins/ipam/host-local plugins/main/loopback pkg/invoke pkg/ns pkg/skel pkg/types 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"
+TESTABLE="libcni plugins/ipam/dhcp plugins/ipam/host-local plugins/main/loopback pkg/invoke pkg/ns pkg/skel pkg/types 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"
 FORMATTABLE="$TESTABLE pkg/testutils plugins/meta/flannel plugins/meta/tuning"
 
 # user has not provided PKG override