noop: allow specifying debug file in config JSON
Chaining sends different config JSON to each plugin, but the same environment, and if we want to test multiple noop plugin runs in the same chain we need a way of telling each run to use a different debug file.
This commit is contained in:
@ -22,19 +22,38 @@ the JSON encoding of a Debug.
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/containernetworking/cni/pkg/skel"
|
"github.com/containernetworking/cni/pkg/skel"
|
||||||
|
"github.com/containernetworking/cni/pkg/types"
|
||||||
"github.com/containernetworking/cni/pkg/version"
|
"github.com/containernetworking/cni/pkg/version"
|
||||||
noop_debug "github.com/containernetworking/cni/plugins/test/noop/debug"
|
noop_debug "github.com/containernetworking/cni/plugins/test/noop/debug"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type NetConf struct {
|
||||||
|
types.NetConf
|
||||||
|
DebugFile string `json:"debugFile"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadConf(bytes []byte) (*NetConf, error) {
|
||||||
|
n := &NetConf{}
|
||||||
|
if err := json.Unmarshal(bytes, n); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to load netconf: %v", err)
|
||||||
|
}
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
// parse extra args i.e. FOO=BAR;ABC=123
|
// parse extra args i.e. FOO=BAR;ABC=123
|
||||||
func parseExtraArgs(args string) (map[string]string, error) {
|
func parseExtraArgs(args string) (map[string]string, error) {
|
||||||
m := make(map[string]string)
|
m := make(map[string]string)
|
||||||
|
if len(args) == 0 {
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
items := strings.Split(args, ";")
|
items := strings.Split(args, ";")
|
||||||
for _, item := range items {
|
for _, item := range items {
|
||||||
@ -47,16 +66,34 @@ func parseExtraArgs(args string) (map[string]string, error) {
|
|||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func debugBehavior(args *skel.CmdArgs, command string) error {
|
func getDebugFilePath(stdinData []byte, args string) (string, error) {
|
||||||
extraArgs, err := parseExtraArgs(args.Args)
|
netConf, err := loadConf(stdinData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
extraArgs, err := parseExtraArgs(args)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
debugFilePath, ok := extraArgs["DEBUG"]
|
debugFilePath, ok := extraArgs["DEBUG"]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
debugFilePath = netConf.DebugFile
|
||||||
|
}
|
||||||
|
|
||||||
|
return debugFilePath, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func debugBehavior(args *skel.CmdArgs, command string) error {
|
||||||
|
debugFilePath, err := getDebugFilePath(args.StdinData, args.Args)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if debugFilePath == "" {
|
||||||
fmt.Printf(`{}`)
|
fmt.Printf(`{}`)
|
||||||
os.Stderr.WriteString("CNI_ARGS empty, no debug behavior\n")
|
os.Stderr.WriteString("CNI_ARGS or config empty, no debug behavior\n")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,21 +125,16 @@ func debugBehavior(args *skel.CmdArgs, command string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func debugGetSupportedVersions() []string {
|
func debugGetSupportedVersions(stdinData []byte) []string {
|
||||||
vers := []string{"0.-42.0", "0.1.0", "0.2.0"}
|
vers := []string{"0.-42.0", "0.1.0", "0.2.0"}
|
||||||
cniArgs := os.Getenv("CNI_ARGS")
|
cniArgs := os.Getenv("CNI_ARGS")
|
||||||
if cniArgs == "" {
|
if cniArgs == "" {
|
||||||
return vers
|
return vers
|
||||||
}
|
}
|
||||||
|
|
||||||
extraArgs, err := parseExtraArgs(cniArgs)
|
debugFilePath, err := getDebugFilePath(stdinData, cniArgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("test setup error: invalid CNI_ARGS format")
|
panic("test setup error: unable to get debug file path: " + err.Error())
|
||||||
}
|
|
||||||
|
|
||||||
debugFilePath, ok := extraArgs["DEBUG"]
|
|
||||||
if !ok {
|
|
||||||
panic("test setup error: missing DEBUG in CNI_ARGS")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
debug, err := noop_debug.ReadDebug(debugFilePath)
|
debug, err := noop_debug.ReadDebug(debugFilePath)
|
||||||
@ -123,7 +155,36 @@ func cmdDel(args *skel.CmdArgs) error {
|
|||||||
return debugBehavior(args, "DEL")
|
return debugBehavior(args, "DEL")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func saveStdin() ([]byte, error) {
|
||||||
|
// Read original stdin
|
||||||
|
stdinData, err := ioutil.ReadAll(os.Stdin)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make a new pipe for stdin, and write original stdin data to it
|
||||||
|
r, w, err := os.Pipe()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if _, err := w.Write(stdinData); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := w.Close(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
os.Stdin = r
|
||||||
|
return stdinData, nil
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
supportedVersions := debugGetSupportedVersions()
|
// Grab and read stdin before pkg/skel gets it
|
||||||
|
stdinData, err := saveStdin()
|
||||||
|
if err != nil {
|
||||||
|
panic("test setup error: unable to read stdin: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
supportedVersions := debugGetSupportedVersions(stdinData)
|
||||||
skel.PluginMain(cmdAdd, cmdDel, version.PluginSupports(supportedVersions...))
|
skel.PluginMain(cmdAdd, cmdDel, version.PluginSupports(supportedVersions...))
|
||||||
}
|
}
|
||||||
|
@ -58,10 +58,11 @@ var _ = Describe("No-op plugin", func() {
|
|||||||
cmd.Env = []string{
|
cmd.Env = []string{
|
||||||
"CNI_COMMAND=ADD",
|
"CNI_COMMAND=ADD",
|
||||||
"CNI_CONTAINERID=some-container-id",
|
"CNI_CONTAINERID=some-container-id",
|
||||||
"CNI_ARGS=" + args,
|
|
||||||
"CNI_NETNS=/some/netns/path",
|
"CNI_NETNS=/some/netns/path",
|
||||||
"CNI_IFNAME=some-eth0",
|
"CNI_IFNAME=some-eth0",
|
||||||
"CNI_PATH=/some/bin/path",
|
"CNI_PATH=/some/bin/path",
|
||||||
|
// Keep this last
|
||||||
|
"CNI_ARGS=" + args,
|
||||||
}
|
}
|
||||||
cmd.Stdin = strings.NewReader(`{"some":"stdin-json", "cniVersion": "0.2.0"}`)
|
cmd.Stdin = strings.NewReader(`{"some":"stdin-json", "cniVersion": "0.2.0"}`)
|
||||||
expectedCmdArgs = skel.CmdArgs{
|
expectedCmdArgs = skel.CmdArgs{
|
||||||
@ -85,6 +86,36 @@ var _ = Describe("No-op plugin", func() {
|
|||||||
Expect(session.Out.Contents()).To(MatchJSON(reportResult))
|
Expect(session.Out.Contents()).To(MatchJSON(reportResult))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("panics when no debug file is given", func() {
|
||||||
|
// Remove the DEBUG option from CNI_ARGS and regular args
|
||||||
|
cmd.Env[len(cmd.Env)-1] = "CNI_ARGS=FOO=BAR"
|
||||||
|
expectedCmdArgs.Args = "FOO=BAR"
|
||||||
|
|
||||||
|
session, err := gexec.Start(cmd, GinkgoWriter, GinkgoWriter)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Eventually(session).Should(gexec.Exit(2))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("allows passing debug file in config JSON", func() {
|
||||||
|
// Remove the DEBUG option from CNI_ARGS and regular args
|
||||||
|
newArgs := "FOO=BAR"
|
||||||
|
cmd.Env[len(cmd.Env)-1] = "CNI_ARGS=" + newArgs
|
||||||
|
newStdin := fmt.Sprintf(`{"some":"stdin-json", "cniVersion": "0.2.0", "debugFile": "%s"}`, debugFileName)
|
||||||
|
cmd.Stdin = strings.NewReader(newStdin)
|
||||||
|
expectedCmdArgs.Args = newArgs
|
||||||
|
expectedCmdArgs.StdinData = []byte(newStdin)
|
||||||
|
|
||||||
|
session, err := gexec.Start(cmd, GinkgoWriter, GinkgoWriter)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Eventually(session).Should(gexec.Exit(0))
|
||||||
|
Expect(session.Out.Contents()).To(MatchJSON(reportResult))
|
||||||
|
|
||||||
|
debug, err := noop_debug.ReadDebug(debugFileName)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(debug.Command).To(Equal("ADD"))
|
||||||
|
Expect(debug.CmdArgs).To(Equal(expectedCmdArgs))
|
||||||
|
})
|
||||||
|
|
||||||
It("records all the args provided by skel.PluginMain", func() {
|
It("records all the args provided by skel.PluginMain", func() {
|
||||||
session, err := gexec.Start(cmd, GinkgoWriter, GinkgoWriter)
|
session, err := gexec.Start(cmd, GinkgoWriter, GinkgoWriter)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Reference in New Issue
Block a user