return ""
}
+func pluginErr(err error, output []byte) error {
+ if _, ok := err.(*exec.ExitError); ok {
+ emsg := Error{}
+ if perr := json.Unmarshal(output, &emsg); perr != nil {
+ return fmt.Errorf("netplugin failed but error parsing its diagnostic message %q: %v", string(output), perr)
+ }
+ details := ""
+ if emsg.Details != "" {
+ details = fmt.Sprintf("; %v", emsg.Details)
+ }
+ return fmt.Errorf("%v%v", emsg.Msg, details)
+ }
+
+ return err
+}
+
// ExecAdd executes IPAM plugin, assuming CNI_COMMAND == ADD.
// Parses and returns resulting IPConfig
func ExecAdd(plugin string, netconf []byte) (*Result, error) {
Stderr: os.Stderr,
}
if err := c.Run(); err != nil {
- return nil, err
+ return nil, pluginErr(err, stdout.Bytes())
}
res := &Result{}
return fmt.Errorf("could not find %q plugin", plugin)
}
+ stdout := &bytes.Buffer{}
+
c := exec.Cmd{
Path: pluginPath,
Args: []string{pluginPath},
Stdin: bytes.NewBuffer(netconf),
+ Stdout: stdout,
Stderr: os.Stderr,
}
- return c.Run()
+ if err := c.Run(); err != nil {
+ return pluginErr(err, stdout.Bytes())
+ }
+ return nil
}
// ConfigureIface takes the result of IPAM plugin and
return nil
}
-
-// PrintResult writes out prettified Result JSON to stdout
-func PrintResult(res *Result) error {
- return prettyPrint(res)
-}
-
-// PrintError writes out prettified Error JSON to stdout
-func PrintError(err *Error) error {
- return prettyPrint(err)
-}
-
-func prettyPrint(obj interface{}) error {
- data, err := json.MarshalIndent(obj, "", " ")
- if err != nil {
- return err
- }
- _, err = os.Stdout.Write(data)
- return err
-}
import (
"encoding/json"
"net"
+ "os"
"github.com/appc/cni/pkg/ip"
)
IP6 *IPConfig `json:"ip6,omitempty"`
}
+func (r *Result) Print() error {
+ return prettyPrint(r)
+}
+
// IPConfig contains values necessary to configure an interface
type IPConfig struct {
IP net.IPNet
Details string `json:"details,omitempty"`
}
+func (e *Error) Error() string {
+ return e.Msg
+}
+
+func (e *Error) Print() error {
+ return prettyPrint(e)
+}
+
// net.IPNet is not JSON (un)marshallable so this duality is needed
// for our custom ip.IPNet type
return json.Marshal(rt)
}
+
+func prettyPrint(obj interface{}) error {
+ data, err := json.MarshalIndent(obj, "", " ")
+ if err != nil {
+ return err
+ }
+ _, err = os.Stdout.Write(data)
+ return err
+}
}
if argsMissing {
- die("required env variables missing")
+ dieMsg("required env variables missing")
}
stdinData, err := ioutil.ReadAll(os.Stdin)
if err != nil {
- die("error reading from stdin: %v", err)
+ dieMsg("error reading from stdin: %v", err)
}
cmdArgs := &CmdArgs{
err = cmdDel(cmdArgs)
default:
- die("unknown CNI_COMMAND: %v", cmd)
+ dieMsg("unknown CNI_COMMAND: %v", cmd)
}
if err != nil {
- die(err.Error())
+ if e, ok := err.(*plugin.Error); ok {
+ // don't wrap Error in Error
+ dieErr(e)
+ }
+ dieMsg(err.Error())
}
}
-func die(f string, args ...interface{}) {
- plugin.PrintError(&plugin.Error{
+func dieMsg(f string, args ...interface{}) {
+ e := &plugin.Error{
Code: 100,
Msg: fmt.Sprintf(f, args...),
- })
+ }
+ dieErr(e)
+}
+
+func dieErr(e *plugin.Error) {
+ if err := e.Print(); err != nil {
+ log.Print("Error writing error JSON to stdout: ", err)
+ }
os.Exit(1)
}
return fmt.Errorf("error calling DHCP.Add: %v", err)
}
- return plugin.PrintResult(result)
+ return result.Print()
}
func cmdDel(args *skel.CmdArgs) error {
return err
}
- return plugin.PrintResult(&plugin.Result{
+ r := &plugin.Result{
IP4: ipConf,
- })
+ }
+ return r.Print()
}
func cmdDel(args *skel.CmdArgs) error {
}
}
- return plugin.PrintResult(result)
+ return result.Print()
}
func cmdDel(args *skel.CmdArgs) error {
}
}
- return plugin.PrintResult(result)
+ return result.Print()
}
func cmdDel(args *skel.CmdArgs) error {
}
}
- return plugin.PrintResult(result)
+ return result.Print()
}
func cmdDel(args *skel.CmdArgs) error {
}
}
- return plugin.PrintResult(result)
+ return result.Print()
}
func cmdDel(args *skel.CmdArgs) error {
plugin=$(jq -r '.type' <$netconf)
export CNI_IFNAME=$(printf eth%d $i)
- $plugin <$netconf >/dev/null
+ res=$($plugin <$netconf)
if [ $? -ne 0 ]; then
- echo "${name} : error executing $CNI_COMMAND"
+ errmsg=$(echo $res | jq -r '.msg')
+ if [ -z "$errmsg" ]; then
+ errmsg=$res
+ fi
+
+ echo "${name} : error executing $CNI_COMMAND: $errmsg"
exit 1
fi