Compare commits
5 Commits
v0.3.0-rc2
...
v0.3.0-rc3
Author | SHA1 | Date | |
---|---|---|---|
35f3a090b2 | |||
131ecc4055 | |||
d582c9ce8f | |||
72337159c1 | |||
7f90f9d559 |
38
pkg/ns/ns.go
38
pkg/ns/ns.go
@ -81,11 +81,23 @@ const (
|
||||
PROCFS_MAGIC = 0x9fa0
|
||||
)
|
||||
|
||||
func IsNS(nspath string) (isNS bool, msg string, err error) {
|
||||
type NSPathNotExistErr struct{ msg string }
|
||||
|
||||
func (e NSPathNotExistErr) Error() string { return e.msg }
|
||||
|
||||
type NSPathNotNSErr struct{ msg string }
|
||||
|
||||
func (e NSPathNotNSErr) Error() string { return e.msg }
|
||||
|
||||
func IsNSorErr(nspath string) error {
|
||||
stat := syscall.Statfs_t{}
|
||||
if err = syscall.Statfs(nspath, &stat); err != nil {
|
||||
err = fmt.Errorf("failed to Statfs %s: %v", nspath, err)
|
||||
return
|
||||
if err := syscall.Statfs(nspath, &stat); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
err = NSPathNotExistErr{msg: fmt.Sprintf("failed to Statfs %q: %v", nspath, err)}
|
||||
} else {
|
||||
err = fmt.Errorf("failed to Statfs %q: %v", nspath, err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
switch stat.Type {
|
||||
@ -95,33 +107,29 @@ func IsNS(nspath string) (isNS bool, msg string, err error) {
|
||||
validPathContent := "ns/"
|
||||
validName := strings.Contains(nspath, validPathContent)
|
||||
if !validName {
|
||||
msg = fmt.Sprintf("path doesn't contain %q", validPathContent)
|
||||
return
|
||||
return NSPathNotNSErr{msg: fmt.Sprintf("path %q doesn't contain %q", nspath, validPathContent)}
|
||||
}
|
||||
isNS = true
|
||||
|
||||
return nil
|
||||
case NSFS_MAGIC:
|
||||
// Kernel >= 3.19
|
||||
|
||||
isNS = true
|
||||
return nil
|
||||
default:
|
||||
msg = fmt.Sprintf("unknown FS magic: %x", stat.Type)
|
||||
return NSPathNotNSErr{msg: fmt.Sprintf("unknown FS magic on %q: %x", nspath, stat.Type)}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Returns an object representing the namespace referred to by @path
|
||||
func GetNS(nspath string) (NetNS, error) {
|
||||
isNS, msg, err := IsNS(nspath)
|
||||
err := IsNSorErr(nspath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !isNS {
|
||||
return nil, fmt.Errorf("no network namespace detected on %s: %s", nspath, msg)
|
||||
}
|
||||
|
||||
fd, err := os.Open(nspath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to open %v: %v", nspath, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &netNS{file: fd}, nil
|
||||
|
@ -181,8 +181,8 @@ var _ = Describe("Linux namespace operations", func() {
|
||||
|
||||
_, err = ns.GetNS(nspath)
|
||||
Expect(err).To(HaveOccurred())
|
||||
errString := fmt.Sprintf("%v", err)
|
||||
Expect(errString).To(HavePrefix("no network namespace detected on %s", nspath))
|
||||
Expect(err).To(BeAssignableToTypeOf(ns.NSPathNotNSErr{}))
|
||||
Expect(err).NotTo(BeAssignableToTypeOf(ns.NSPathNotExistErr{}))
|
||||
})
|
||||
})
|
||||
|
||||
@ -214,13 +214,11 @@ var _ = Describe("Linux namespace operations", func() {
|
||||
})
|
||||
})
|
||||
|
||||
Describe("IsNS", func() {
|
||||
Describe("IsNSorErr", func() {
|
||||
It("should detect a namespace", func() {
|
||||
createdNetNS, err := ns.NewNS()
|
||||
isNSFS, msg, err := ns.IsNS(createdNetNS.Path())
|
||||
err = ns.IsNSorErr(createdNetNS.Path())
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(msg).To(Equal(""))
|
||||
Expect(isNSFS).To(Equal(true))
|
||||
})
|
||||
|
||||
It("should refuse other paths", func() {
|
||||
@ -231,9 +229,17 @@ var _ = Describe("Linux namespace operations", func() {
|
||||
nspath := tempFile.Name()
|
||||
defer os.Remove(nspath)
|
||||
|
||||
isNSFS, _, err := ns.IsNS(nspath)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(isNSFS).To(Equal(false))
|
||||
err = ns.IsNSorErr(nspath)
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(err).To(BeAssignableToTypeOf(ns.NSPathNotNSErr{}))
|
||||
Expect(err).NotTo(BeAssignableToTypeOf(ns.NSPathNotExistErr{}))
|
||||
})
|
||||
|
||||
It("should error on non-existing paths", func() {
|
||||
err := ns.IsNSorErr("/tmp/IDoNotExist")
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(err).To(BeAssignableToTypeOf(ns.NSPathNotExistErr{}))
|
||||
Expect(err).NotTo(BeAssignableToTypeOf(ns.NSPathNotNSErr{}))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -36,28 +36,72 @@ type CmdArgs struct {
|
||||
StdinData []byte
|
||||
}
|
||||
|
||||
type reqForCmdEntry map[string]bool
|
||||
|
||||
// PluginMain is the "main" for a plugin. It accepts
|
||||
// two callback functions for add and del commands.
|
||||
func PluginMain(cmdAdd, cmdDel func(_ *CmdArgs) error) {
|
||||
var cmd, contID, netns, ifName, args, path string
|
||||
|
||||
vars := []struct {
|
||||
name string
|
||||
val *string
|
||||
req bool
|
||||
name string
|
||||
val *string
|
||||
reqForCmd reqForCmdEntry
|
||||
}{
|
||||
{"CNI_COMMAND", &cmd, true},
|
||||
{"CNI_CONTAINERID", &contID, false},
|
||||
{"CNI_NETNS", &netns, true},
|
||||
{"CNI_IFNAME", &ifName, true},
|
||||
{"CNI_ARGS", &args, false},
|
||||
{"CNI_PATH", &path, true},
|
||||
{
|
||||
"CNI_COMMAND",
|
||||
&cmd,
|
||||
reqForCmdEntry{
|
||||
"ADD": true,
|
||||
"DEL": true,
|
||||
},
|
||||
},
|
||||
{
|
||||
"CNI_CONTAINERID",
|
||||
&contID,
|
||||
reqForCmdEntry{
|
||||
"ADD": false,
|
||||
"DEL": false,
|
||||
},
|
||||
},
|
||||
{
|
||||
"CNI_NETNS",
|
||||
&netns,
|
||||
reqForCmdEntry{
|
||||
"ADD": true,
|
||||
"DEL": false,
|
||||
},
|
||||
},
|
||||
{
|
||||
"CNI_IFNAME",
|
||||
&ifName,
|
||||
reqForCmdEntry{
|
||||
"ADD": true,
|
||||
"DEL": true,
|
||||
},
|
||||
},
|
||||
{
|
||||
"CNI_ARGS",
|
||||
&args,
|
||||
reqForCmdEntry{
|
||||
"ADD": false,
|
||||
"DEL": false,
|
||||
},
|
||||
},
|
||||
{
|
||||
"CNI_PATH",
|
||||
&path,
|
||||
reqForCmdEntry{
|
||||
"ADD": true,
|
||||
"DEL": true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
argsMissing := false
|
||||
for _, v := range vars {
|
||||
*v.val = os.Getenv(v.name)
|
||||
if v.req && *v.val == "" {
|
||||
if v.reqForCmd[cmd] && *v.val == "" {
|
||||
log.Printf("%v env variable missing", v.name)
|
||||
argsMissing = true
|
||||
}
|
||||
|
@ -71,5 +71,14 @@ var _ = Describe("Skel", func() {
|
||||
// Expect(err).NotTo(HaveOccurred())
|
||||
// PluginMain(fErr, nil)
|
||||
// })
|
||||
|
||||
It("should not fail with DEL and no NETNS and noop callback", func() {
|
||||
err := os.Setenv("CNI_COMMAND", "DEL")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
err = os.Unsetenv("CNI_NETNS")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
PluginMain(nil, fNoop)
|
||||
})
|
||||
|
||||
})
|
||||
})
|
||||
|
@ -289,6 +289,10 @@ func cmdDel(args *skel.CmdArgs) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if args.Netns == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var ipn *net.IPNet
|
||||
err = ns.WithNetNSPath(args.Netns, func(_ ns.NetNS) error {
|
||||
var err error
|
||||
|
@ -152,6 +152,10 @@ func cmdDel(args *skel.CmdArgs) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if args.Netns == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
return ns.WithNetNSPath(args.Netns, func(_ ns.NetNS) error {
|
||||
return ip.DelLinkByName(args.IfName)
|
||||
})
|
||||
|
@ -170,6 +170,10 @@ func cmdDel(args *skel.CmdArgs) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if args.Netns == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
return ns.WithNetNSPath(args.Netns, func(_ ns.NetNS) error {
|
||||
return ip.DelLinkByName(args.IfName)
|
||||
})
|
||||
|
@ -199,6 +199,10 @@ func cmdDel(args *skel.CmdArgs) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if args.Netns == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var ipn *net.IPNet
|
||||
err := ns.WithNetNSPath(args.Netns, func(_ ns.NetNS) error {
|
||||
var err error
|
||||
|
Reference in New Issue
Block a user