bug fix: exec of DEL cmd caused JSON decode error
authorEugene Yakubovich <eugene.yakubovich@coreos.com>
Fri, 18 Sep 2015 17:30:10 +0000 (10:30 -0700)
committerEugene Yakubovich <eugene.yakubovich@coreos.com>
Fri, 18 Sep 2015 17:30:10 +0000 (10:30 -0700)
When plugin is executed with a DEL command, it does not
print result to stdout unless there is an error. Therefore
it stdout bytes should not be passed to json.Unmarshal.

libcni/api.go
pkg/invoke/exec.go
pkg/ipam/ipam.go

index feaed8d..4ad714a 100644 (file)
@@ -43,20 +43,18 @@ type CNIConfig struct {
 }
 
 func (c *CNIConfig) AddNetwork(net *NetworkConfig, rt *RuntimeConf) (*types.Result, error) {
-       return c.execPlugin("ADD", net, rt)
+       pluginPath := invoke.FindInPath(net.Network.Type, c.Path)
+       return invoke.ExecPluginWithResult(pluginPath, net.Bytes, c.args("ADD", rt))
 }
 
 func (c *CNIConfig) DelNetwork(net *NetworkConfig, rt *RuntimeConf) error {
-       _, err := c.execPlugin("DEL", net, rt)
-       return err
+       pluginPath := invoke.FindInPath(net.Network.Type, c.Path)
+       return invoke.ExecPluginWithoutResult(pluginPath, net.Bytes, c.args("DEL", rt))
 }
 
 // =====
-
-func (c *CNIConfig) execPlugin(action string, conf *NetworkConfig, rt *RuntimeConf) (*types.Result, error) {
-       pluginPath := invoke.FindInPath(conf.Network.Type, c.Path)
-
-       args := &invoke.Args{
+func (c *CNIConfig) args(action string, rt *RuntimeConf) *invoke.Args {
+       return &invoke.Args{
                Command:     action,
                ContainerID: rt.ContainerID,
                NetNS:       rt.NetNS,
@@ -64,5 +62,4 @@ func (c *CNIConfig) execPlugin(action string, conf *NetworkConfig, rt *RuntimeCo
                IfName:      rt.IfName,
                Path:        strings.Join(c.Path, ":"),
        }
-       return invoke.ExecPlugin(pluginPath, conf.Bytes, args)
 }
index d7c5b7a..cf0cff4 100644 (file)
@@ -41,7 +41,23 @@ func pluginErr(err error, output []byte) error {
        return err
 }
 
-func ExecPlugin(pluginPath string, netconf []byte, args CNIArgs) (*types.Result, error) {
+func ExecPluginWithResult(pluginPath string, netconf []byte, args CNIArgs) (*types.Result, error) {
+       stdoutBytes, err := execPlugin(pluginPath, netconf, args)
+       if err != nil {
+               return nil, err
+       }
+
+       res := &types.Result{}
+       err = json.Unmarshal(stdoutBytes, res)
+       return res, err
+}
+
+func ExecPluginWithoutResult(pluginPath string, netconf []byte, args CNIArgs) error {
+       _, err := execPlugin(pluginPath, netconf, args)
+       return err
+}
+
+func execPlugin(pluginPath string, netconf []byte, args CNIArgs) ([]byte, error) {
        if pluginPath == "" {
                return nil, fmt.Errorf("could not find %q plugin", filepath.Base(pluginPath))
        }
@@ -60,7 +76,5 @@ func ExecPlugin(pluginPath string, netconf []byte, args CNIArgs) (*types.Result,
                return nil, pluginErr(err, stdout.Bytes())
        }
 
-       res := &types.Result{}
-       err := json.Unmarshal(stdout.Bytes(), res)
-       return res, err
+       return stdout.Bytes(), nil
 }
index a76299d..6a593a2 100644 (file)
@@ -29,15 +29,14 @@ func ExecAdd(plugin string, netconf []byte) (*types.Result, error) {
        if os.Getenv("CNI_COMMAND") != "ADD" {
                return nil, fmt.Errorf("CNI_COMMAND is not ADD")
        }
-       return invoke.ExecPlugin(invoke.Find(plugin), netconf, invoke.ArgsFromEnv())
+       return invoke.ExecPluginWithResult(invoke.Find(plugin), netconf, invoke.ArgsFromEnv())
 }
 
 func ExecDel(plugin string, netconf []byte) error {
        if os.Getenv("CNI_COMMAND") != "DEL" {
                return fmt.Errorf("CNI_COMMAND is not DEL")
        }
-       _, err := invoke.ExecPlugin(invoke.Find(plugin), netconf, invoke.ArgsFromEnv())
-       return err
+       return invoke.ExecPluginWithoutResult(invoke.Find(plugin), netconf, invoke.ArgsFromEnv())
 }
 
 // ConfigureIface takes the result of IPAM plugin and