package main
import (
- "encoding/json"
- "fmt"
- "path/filepath"
-
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
- "github.com/onsi/gomega/gexec"
"testing"
)
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()
-})
"fmt"
"io/ioutil"
"os"
- "os/exec"
- "strings"
+ "github.com/containernetworking/cni/pkg/ns"
"github.com/containernetworking/cni/pkg/skel"
+ "github.com/containernetworking/cni/pkg/testutils"
- 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
- subnetFile string
- stateDir string
+ originalNS ns.NetNS
+ input string
+ subnetFile string
+ stateDir string
)
- const delegateInput = `
-{
- "type": "noop",
- "some": "other data"
-}
-`
+ BeforeEach(func() {
+ var err error
+ originalNS, err = ns.NewNS()
+ Expect(err).NotTo(HaveOccurred())
+ })
+
+ AfterEach(func() {
+ Expect(originalNS.Close()).To(Succeed())
+ })
const inputTemplate = `
{
"name": "cni-flannel",
"type": "flannel",
"subnetFile": "%s",
- "stateDir": "%s",
- "delegate": ` +
- delegateInput +
- `}`
+ "stateDir": "%s"
+}`
const flannelSubnetEnv = `
FLANNEL_NETWORK=10.1.0.0/16
return file.Name()
}
- 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())
-
+ var err error
// flannel subnet.env
subnetFile = writeSubnetEnv(flannelSubnetEnv)
})
AfterEach(func() {
- os.Remove(debugFileName)
os.Remove(subnetFile)
os.Remove(stateDir)
})
Describe("CNI lifecycle", func() {
+ It("uses stateDir for storing network configuration", func() {
+ const IFNAME = "eth0"
+
+ targetNs, err := ns.NewNS()
+ Expect(err).NotTo(HaveOccurred())
+ defer targetNs.Close()
- BeforeEach(func() {
- expectedCmdArgs = skel.CmdArgs{
+ args := &skel.CmdArgs{
ContainerID: "some-container-id",
- Netns: "/some/netns/path",
- IfName: "some-eth0",
- Args: "DEBUG=" + debugFileName,
- Path: "/some/bin/path",
+ Netns: targetNs.Path(),
+ IfName: IFNAME,
StdinData: []byte(input),
}
- cmd = cniCommand("ADD", input)
- })
- 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":{} }`))
+ err = originalNS.Do(func(ns.NetNS) error {
+ defer GinkgoRecover()
- By("check that plugin writes to net config to stateDir")
- path := fmt.Sprintf("%s/%s", stateDir, "some-container-id")
- Expect(path).Should(BeAnExistingFile())
+ By("calling ADD")
+ _, err := testutils.CmdAddWithResult(targetNs.Path(), IFNAME, func() error {
+ return cmdAdd(args)
+ })
+ Expect(err).NotTo(HaveOccurred())
- netConfBytes, err := ioutil.ReadFile(path)
- Expect(err).NotTo(HaveOccurred())
- expected := `{
+ 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",
+ "type" : "bridge",
"ipam" : {
"type" : "host-local",
"subnet" : "10.1.17.0/24",
},
"mtu" : 1472,
"ipMasq" : false,
- "some" : "other data"
+ "isGateway": true
}
`
- Expect(netConfBytes).Should(MatchJSON(expected))
+ 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("calling DEL")
+ err = testutils.CmdDelWithResult(targetNs.Path(), IFNAME, func() error {
+ return cmdDel(args)
+ })
+ Expect(err).NotTo(HaveOccurred())
- By("check that plugin removes net config from state dir")
- Expect(path).ShouldNot(BeAnExistingFile())
+ By("check that plugin removes net config from state dir")
+ Expect(path).ShouldNot(BeAnExistingFile())
+ return nil
+ })
+ Expect(err).NotTo(HaveOccurred())
})
})
BeforeEach(func() {
input = `{
"name": "cni-flannel",
-"type": "flannel",
-"delegate": ` +
- delegateInput +
- `}`
+"type": "flannel"
+}`
})
It("loads flannel network config with defaults", func() {