Create a plugin for up'ing a lo device

- Believe we need sudo to create netns
- Use syscall instead of relying on ip netns
- Add sudo to .travis.yml
- Needs more -E
- Revert Godeps GoVersion to 1.4.2
- in travis, test command is run with all necessary env vars
- Loopback plugin only works on 'lo' interface
- Update README, add loopback plugin config
- note script dependency on jq

Signed-off-by: Gabe Rosenhouse <grosenhouse@pivotal.io>
This commit is contained in:
Zachary Gershman 2016-02-12 09:30:10 -08:00 committed by zachgersh
parent ebd5be8475
commit 2708bdf2f5
7 changed files with 182 additions and 4 deletions

View File

@ -1,4 +1,5 @@
language: go language: go
sudo: required
go: go:
- 1.4 - 1.4
@ -12,4 +13,7 @@ install:
- go get ${TOOLS_CMD}/vet - go get ${TOOLS_CMD}/vet
script: script:
- ./test - sudo -E /bin/bash -c 'PATH=$GOROOT/bin:$PATH ./test'
notifications:
email: false

2
Godeps/Godeps.json generated
View File

@ -1,6 +1,6 @@
{ {
"ImportPath": "github.com/appc/cni", "ImportPath": "github.com/appc/cni",
"GoVersion": "go1.5.3", "GoVersion": "go1.4.2",
"Packages": [ "Packages": [
"./..." "./..."
], ],

View File

@ -24,7 +24,9 @@ This repository includes a number of common plugins that can be found in plugins
Please see Documentation/ folder for documentation about particular plugins. Please see Documentation/ folder for documentation about particular plugins.
## Running the plugins ## Running the plugins
The scripts/ directory contains two scripts, priv-net-run.sh and docker-run.sh, that can be used to exercise the plugins. The scripts/ directory contains two scripts, `priv-net-run.sh` and `docker-run.sh`, that can be used to exercise the plugins.
**note - priv-net-run.sh depends on `jq`**
Start out by creating a netconf file to describe a network: Start out by creating a netconf file to describe a network:
@ -46,6 +48,11 @@ $ cat >/etc/cni/net.d/10-mynet.conf <<EOF
} }
} }
EOF EOF
$ cat >/etc/cni/net.d/99-loopback.conf <<EOF
{
"type": "loopback"
}
EOF
``` ```
The directory `/etc/cni/net.d` is the default location in which the scripts will look for net configurations. The directory `/etc/cni/net.d` is the default location in which the scripts will look for net configurations.

View File

@ -0,0 +1,40 @@
package main
import (
"os"
"github.com/appc/cni/pkg/ns"
"github.com/appc/cni/pkg/skel"
"github.com/vishvananda/netlink"
)
func cmdAdd(args *skel.CmdArgs) error {
args.IfName = "lo" // ignore config, this only works for loopback
err := ns.WithNetNSPath(args.Netns, false, func(hostNS *os.File) error {
link, err := netlink.LinkByName(args.IfName)
if err != nil {
return err // not tested
}
err = netlink.LinkSetUp(link)
if err != nil {
return err // not tested
}
return nil
})
if err != nil {
return err // not tested
}
return nil
}
func cmdDel(args *skel.CmdArgs) error {
// del does nothing, we're going to destroy the device anyway
return nil
}
func main() {
skel.PluginMain(cmdAdd, cmdDel)
}

View File

@ -0,0 +1,58 @@
package main_test
import (
"os"
"github.com/onsi/gomega/gexec"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
"golang.org/x/sys/unix"
)
var pathToLoPlugin string
func TestLoopback(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Loopback Suite")
}
var _ = BeforeSuite(func() {
var err error
pathToLoPlugin, err = gexec.Build("github.com/appc/cni/plugins/main/loopback")
Expect(err).NotTo(HaveOccurred())
})
var _ = AfterSuite(func() {
gexec.CleanupBuildArtifacts()
})
func makeNetworkNS(containerID string) string {
namespace := "/var/run/netns/" + containerID
err := os.MkdirAll("/var/run/netns", 0600)
Expect(err).NotTo(HaveOccurred())
err = unix.Unshare(unix.CLONE_NEWNET)
Expect(err).NotTo(HaveOccurred())
fd, err := os.Create(namespace)
Expect(err).NotTo(HaveOccurred())
defer fd.Close()
err = unix.Mount("/proc/self/ns/net", namespace, "none", unix.MS_BIND, "")
Expect(err).NotTo(HaveOccurred())
Expect(namespace).To(BeAnExistingFile())
return namespace
}
func removeNetworkNS(networkNS string) error {
err := unix.Unmount(networkNS, unix.MNT_DETACH)
err = os.RemoveAll(networkNS)
return err
}

View File

@ -0,0 +1,70 @@
package main_test
import (
"fmt"
"net"
"os"
"os/exec"
"strings"
"github.com/appc/cni/pkg/ns"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gexec"
)
var _ = Describe("Loopback", func() {
var (
networkNS string
containerID string
command *exec.Cmd
)
BeforeEach(func() {
command = exec.Command(pathToLoPlugin)
environ := os.Environ()
containerID = "some-container-id"
networkNS = makeNetworkNS(containerID)
cniEnvVars := []string{
fmt.Sprintf("CNI_COMMAND=%s", "ADD"),
fmt.Sprintf("CNI_CONTAINERID=%s", containerID),
fmt.Sprintf("CNI_NETNS=%s", networkNS),
fmt.Sprintf("CNI_IFNAME=%s", "this is ignored"),
fmt.Sprintf("CNI_ARGS=%s", "none"),
fmt.Sprintf("CNI_PATH=%s", "/some/test/path"),
}
for _, v := range cniEnvVars {
environ = append(environ, v)
}
command.Env = environ
command.Stdin = strings.NewReader("this doesn't matter")
})
AfterEach(func() {
Expect(removeNetworkNS(networkNS)).To(Succeed())
})
Context("when given a network namespace", func() {
It("sets the lo device to UP", func() {
session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
Eventually(session).Should(gexec.Exit(0))
var lo *net.Interface
err = ns.WithNetNSPath(networkNS, false, func(hostNS *os.File) error {
var err error
lo, err = net.InterfaceByName("lo")
return err
})
Expect(err).NotTo(HaveOccurred())
Expect(lo.Flags & net.FlagUp).To(Equal(net.FlagUp))
})
})
})

View File

@ -8,7 +8,6 @@ contid=$(printf '%x%x%x%x' $RANDOM $RANDOM $RANDOM $RANDOM)
netnspath=/var/run/netns/$contid netnspath=/var/run/netns/$contid
ip netns add $contid ip netns add $contid
ip netns exec $contid ip link set lo up
./exec-plugins.sh add $contid $netnspath ./exec-plugins.sh add $contid $netnspath