summaryrefslogtreecommitdiff
path: root/vendor/github.com/containernetworking/cni/pkg
diff options
context:
space:
mode:
authorMatthew Heon <matthew.heon@gmail.com>2017-11-01 11:24:59 -0400
committerMatthew Heon <matthew.heon@gmail.com>2017-11-01 11:24:59 -0400
commita031b83a09a8628435317a03f199cdc18b78262f (patch)
treebc017a96769ce6de33745b8b0b1304ccf38e9df0 /vendor/github.com/containernetworking/cni/pkg
parent2b74391cd5281f6fdf391ff8ad50fd1490f6bf89 (diff)
downloadpodman-a031b83a09a8628435317a03f199cdc18b78262f.tar.gz
podman-a031b83a09a8628435317a03f199cdc18b78262f.tar.bz2
podman-a031b83a09a8628435317a03f199cdc18b78262f.zip
Initial checkin from CRI-O repo
Signed-off-by: Matthew Heon <matthew.heon@gmail.com>
Diffstat (limited to 'vendor/github.com/containernetworking/cni/pkg')
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/invoke/args.go82
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/invoke/delegate.go53
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/invoke/exec.go95
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/invoke/find.go43
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/invoke/os_unix.go20
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/invoke/os_windows.go18
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go59
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/types/020/types.go135
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/types/args.go112
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/types/current/types.go300
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/types/types.go189
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/version/conf.go37
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/version/plugin.go81
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/version/reconcile.go49
-rw-r--r--vendor/github.com/containernetworking/cni/pkg/version/version.go61
15 files changed, 1334 insertions, 0 deletions
diff --git a/vendor/github.com/containernetworking/cni/pkg/invoke/args.go b/vendor/github.com/containernetworking/cni/pkg/invoke/args.go
new file mode 100644
index 000000000..39b639723
--- /dev/null
+++ b/vendor/github.com/containernetworking/cni/pkg/invoke/args.go
@@ -0,0 +1,82 @@
+// Copyright 2015 CNI authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package invoke
+
+import (
+ "os"
+ "strings"
+)
+
+type CNIArgs interface {
+ // For use with os/exec; i.e., return nil to inherit the
+ // environment from this process
+ AsEnv() []string
+}
+
+type inherited struct{}
+
+var inheritArgsFromEnv inherited
+
+func (_ *inherited) AsEnv() []string {
+ return nil
+}
+
+func ArgsFromEnv() CNIArgs {
+ return &inheritArgsFromEnv
+}
+
+type Args struct {
+ Command string
+ ContainerID string
+ NetNS string
+ PluginArgs [][2]string
+ PluginArgsStr string
+ IfName string
+ Path string
+}
+
+// Args implements the CNIArgs interface
+var _ CNIArgs = &Args{}
+
+func (args *Args) AsEnv() []string {
+ env := os.Environ()
+ pluginArgsStr := args.PluginArgsStr
+ if pluginArgsStr == "" {
+ pluginArgsStr = stringify(args.PluginArgs)
+ }
+
+ // Ensure that the custom values are first, so any value present in
+ // the process environment won't override them.
+ env = append([]string{
+ "CNI_COMMAND=" + args.Command,
+ "CNI_CONTAINERID=" + args.ContainerID,
+ "CNI_NETNS=" + args.NetNS,
+ "CNI_ARGS=" + pluginArgsStr,
+ "CNI_IFNAME=" + args.IfName,
+ "CNI_PATH=" + args.Path,
+ }, env...)
+ return env
+}
+
+// taken from rkt/networking/net_plugin.go
+func stringify(pluginArgs [][2]string) string {
+ entries := make([]string, len(pluginArgs))
+
+ for i, kv := range pluginArgs {
+ entries[i] = strings.Join(kv[:], "=")
+ }
+
+ return strings.Join(entries, ";")
+}
diff --git a/vendor/github.com/containernetworking/cni/pkg/invoke/delegate.go b/vendor/github.com/containernetworking/cni/pkg/invoke/delegate.go
new file mode 100644
index 000000000..c78a69eeb
--- /dev/null
+++ b/vendor/github.com/containernetworking/cni/pkg/invoke/delegate.go
@@ -0,0 +1,53 @@
+// Copyright 2016 CNI authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package invoke
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+
+ "github.com/containernetworking/cni/pkg/types"
+)
+
+func DelegateAdd(delegatePlugin string, netconf []byte) (types.Result, error) {
+ if os.Getenv("CNI_COMMAND") != "ADD" {
+ return nil, fmt.Errorf("CNI_COMMAND is not ADD")
+ }
+
+ paths := filepath.SplitList(os.Getenv("CNI_PATH"))
+
+ pluginPath, err := FindInPath(delegatePlugin, paths)
+ if err != nil {
+ return nil, err
+ }
+
+ return ExecPluginWithResult(pluginPath, netconf, ArgsFromEnv())
+}
+
+func DelegateDel(delegatePlugin string, netconf []byte) error {
+ if os.Getenv("CNI_COMMAND") != "DEL" {
+ return fmt.Errorf("CNI_COMMAND is not DEL")
+ }
+
+ paths := filepath.SplitList(os.Getenv("CNI_PATH"))
+
+ pluginPath, err := FindInPath(delegatePlugin, paths)
+ if err != nil {
+ return err
+ }
+
+ return ExecPluginWithoutResult(pluginPath, netconf, ArgsFromEnv())
+}
diff --git a/vendor/github.com/containernetworking/cni/pkg/invoke/exec.go b/vendor/github.com/containernetworking/cni/pkg/invoke/exec.go
new file mode 100644
index 000000000..fc47e7c82
--- /dev/null
+++ b/vendor/github.com/containernetworking/cni/pkg/invoke/exec.go
@@ -0,0 +1,95 @@
+// Copyright 2015 CNI authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package invoke
+
+import (
+ "fmt"
+ "os"
+
+ "github.com/containernetworking/cni/pkg/types"
+ "github.com/containernetworking/cni/pkg/version"
+)
+
+func ExecPluginWithResult(pluginPath string, netconf []byte, args CNIArgs) (types.Result, error) {
+ return defaultPluginExec.WithResult(pluginPath, netconf, args)
+}
+
+func ExecPluginWithoutResult(pluginPath string, netconf []byte, args CNIArgs) error {
+ return defaultPluginExec.WithoutResult(pluginPath, netconf, args)
+}
+
+func GetVersionInfo(pluginPath string) (version.PluginInfo, error) {
+ return defaultPluginExec.GetVersionInfo(pluginPath)
+}
+
+var defaultPluginExec = &PluginExec{
+ RawExec: &RawExec{Stderr: os.Stderr},
+ VersionDecoder: &version.PluginDecoder{},
+}
+
+type PluginExec struct {
+ RawExec interface {
+ ExecPlugin(pluginPath string, stdinData []byte, environ []string) ([]byte, error)
+ }
+ VersionDecoder interface {
+ Decode(jsonBytes []byte) (version.PluginInfo, error)
+ }
+}
+
+func (e *PluginExec) WithResult(pluginPath string, netconf []byte, args CNIArgs) (types.Result, error) {
+ stdoutBytes, err := e.RawExec.ExecPlugin(pluginPath, netconf, args.AsEnv())
+ if err != nil {
+ return nil, err
+ }
+
+ // Plugin must return result in same version as specified in netconf
+ versionDecoder := &version.ConfigDecoder{}
+ confVersion, err := versionDecoder.Decode(netconf)
+ if err != nil {
+ return nil, err
+ }
+
+ return version.NewResult(confVersion, stdoutBytes)
+}
+
+func (e *PluginExec) WithoutResult(pluginPath string, netconf []byte, args CNIArgs) error {
+ _, err := e.RawExec.ExecPlugin(pluginPath, netconf, args.AsEnv())
+ return err
+}
+
+// GetVersionInfo returns the version information available about the plugin.
+// For recent-enough plugins, it uses the information returned by the VERSION
+// command. For older plugins which do not recognize that command, it reports
+// version 0.1.0
+func (e *PluginExec) GetVersionInfo(pluginPath string) (version.PluginInfo, error) {
+ args := &Args{
+ Command: "VERSION",
+
+ // set fake values required by plugins built against an older version of skel
+ NetNS: "dummy",
+ IfName: "dummy",
+ Path: "dummy",
+ }
+ stdin := []byte(fmt.Sprintf(`{"cniVersion":%q}`, version.Current()))
+ stdoutBytes, err := e.RawExec.ExecPlugin(pluginPath, stdin, args.AsEnv())
+ if err != nil {
+ if err.Error() == "unknown CNI_COMMAND: VERSION" {
+ return version.PluginSupports("0.1.0"), nil
+ }
+ return nil, err
+ }
+
+ return e.VersionDecoder.Decode(stdoutBytes)
+}
diff --git a/vendor/github.com/containernetworking/cni/pkg/invoke/find.go b/vendor/github.com/containernetworking/cni/pkg/invoke/find.go
new file mode 100644
index 000000000..e815404c8
--- /dev/null
+++ b/vendor/github.com/containernetworking/cni/pkg/invoke/find.go
@@ -0,0 +1,43 @@
+// Copyright 2015 CNI authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package invoke
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+)
+
+// FindInPath returns the full path of the plugin by searching in the provided path
+func FindInPath(plugin string, paths []string) (string, error) {
+ if plugin == "" {
+ return "", fmt.Errorf("no plugin name provided")
+ }
+
+ if len(paths) == 0 {
+ return "", fmt.Errorf("no paths provided")
+ }
+
+ for _, path := range paths {
+ for _, fe := range ExecutableFileExtensions {
+ fullpath := filepath.Join(path, plugin) + fe
+ if fi, err := os.Stat(fullpath); err == nil && fi.Mode().IsRegular() {
+ return fullpath, nil
+ }
+ }
+ }
+
+ return "", fmt.Errorf("failed to find plugin %q in path %s", plugin, paths)
+}
diff --git a/vendor/github.com/containernetworking/cni/pkg/invoke/os_unix.go b/vendor/github.com/containernetworking/cni/pkg/invoke/os_unix.go
new file mode 100644
index 000000000..bab5737a9
--- /dev/null
+++ b/vendor/github.com/containernetworking/cni/pkg/invoke/os_unix.go
@@ -0,0 +1,20 @@
+// Copyright 2016 CNI authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build darwin dragonfly freebsd linux netbsd opensbd solaris
+
+package invoke
+
+// Valid file extensions for plugin executables.
+var ExecutableFileExtensions = []string{""}
diff --git a/vendor/github.com/containernetworking/cni/pkg/invoke/os_windows.go b/vendor/github.com/containernetworking/cni/pkg/invoke/os_windows.go
new file mode 100644
index 000000000..7665125b1
--- /dev/null
+++ b/vendor/github.com/containernetworking/cni/pkg/invoke/os_windows.go
@@ -0,0 +1,18 @@
+// Copyright 2016 CNI authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package invoke
+
+// Valid file extensions for plugin executables.
+var ExecutableFileExtensions = []string{".exe", ""}
diff --git a/vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go b/vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go
new file mode 100644
index 000000000..93f1e75d9
--- /dev/null
+++ b/vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go
@@ -0,0 +1,59 @@
+// Copyright 2016 CNI authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package invoke
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io"
+ "os/exec"
+
+ "github.com/containernetworking/cni/pkg/types"
+)
+
+type RawExec struct {
+ Stderr io.Writer
+}
+
+func (e *RawExec) ExecPlugin(pluginPath string, stdinData []byte, environ []string) ([]byte, error) {
+ stdout := &bytes.Buffer{}
+
+ c := exec.Cmd{
+ Env: environ,
+ Path: pluginPath,
+ Args: []string{pluginPath},
+ Stdin: bytes.NewBuffer(stdinData),
+ Stdout: stdout,
+ Stderr: e.Stderr,
+ }
+ if err := c.Run(); err != nil {
+ return nil, pluginErr(err, stdout.Bytes())
+ }
+
+ return stdout.Bytes(), nil
+}
+
+func pluginErr(err error, output []byte) error {
+ if _, ok := err.(*exec.ExitError); ok {
+ emsg := types.Error{}
+ if perr := json.Unmarshal(output, &emsg); perr != nil {
+ emsg.Msg = fmt.Sprintf("netplugin failed but error parsing its diagnostic message %q: %v", string(output), perr)
+ }
+ return &emsg
+ }
+
+ return err
+}
diff --git a/vendor/github.com/containernetworking/cni/pkg/types/020/types.go b/vendor/github.com/containernetworking/cni/pkg/types/020/types.go
new file mode 100644
index 000000000..2833aba78
--- /dev/null
+++ b/vendor/github.com/containernetworking/cni/pkg/types/020/types.go
@@ -0,0 +1,135 @@
+// Copyright 2016 CNI authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package types020
+
+import (
+ "encoding/json"
+ "fmt"
+ "net"
+ "os"
+
+ "github.com/containernetworking/cni/pkg/types"
+)
+
+const ImplementedSpecVersion string = "0.2.0"
+
+var SupportedVersions = []string{"", "0.1.0", ImplementedSpecVersion}
+
+// Compatibility types for CNI version 0.1.0 and 0.2.0
+
+func NewResult(data []byte) (types.Result, error) {
+ result := &Result{}
+ if err := json.Unmarshal(data, result); err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+func GetResult(r types.Result) (*Result, error) {
+ // We expect version 0.1.0/0.2.0 results
+ result020, err := r.GetAsVersion(ImplementedSpecVersion)
+ if err != nil {
+ return nil, err
+ }
+ result, ok := result020.(*Result)
+ if !ok {
+ return nil, fmt.Errorf("failed to convert result")
+ }
+ return result, nil
+}
+
+// Result is what gets returned from the plugin (via stdout) to the caller
+type Result struct {
+ CNIVersion string `json:"cniVersion,omitempty"`
+ IP4 *IPConfig `json:"ip4,omitempty"`
+ IP6 *IPConfig `json:"ip6,omitempty"`
+ DNS types.DNS `json:"dns,omitempty"`
+}
+
+func (r *Result) Version() string {
+ return ImplementedSpecVersion
+}
+
+func (r *Result) GetAsVersion(version string) (types.Result, error) {
+ for _, supportedVersion := range SupportedVersions {
+ if version == supportedVersion {
+ r.CNIVersion = version
+ return r, nil
+ }
+ }
+ return nil, fmt.Errorf("cannot convert version %q to %s", SupportedVersions, version)
+}
+
+func (r *Result) Print() error {
+ data, err := json.MarshalIndent(r, "", " ")
+ if err != nil {
+ return err
+ }
+ _, err = os.Stdout.Write(data)
+ return err
+}
+
+// String returns a formatted string in the form of "[IP4: $1,][ IP6: $2,] DNS: $3" where
+// $1 represents the receiver's IPv4, $2 represents the receiver's IPv6 and $3 the
+// receiver's DNS. If $1 or $2 are nil, they won't be present in the returned string.
+func (r *Result) String() string {
+ var str string
+ if r.IP4 != nil {
+ str = fmt.Sprintf("IP4:%+v, ", *r.IP4)
+ }
+ if r.IP6 != nil {
+ str += fmt.Sprintf("IP6:%+v, ", *r.IP6)
+ }
+ return fmt.Sprintf("%sDNS:%+v", str, r.DNS)
+}
+
+// IPConfig contains values necessary to configure an interface
+type IPConfig struct {
+ IP net.IPNet
+ Gateway net.IP
+ Routes []types.Route
+}
+
+// net.IPNet is not JSON (un)marshallable so this duality is needed
+// for our custom IPNet type
+
+// JSON (un)marshallable types
+type ipConfig struct {
+ IP types.IPNet `json:"ip"`
+ Gateway net.IP `json:"gateway,omitempty"`
+ Routes []types.Route `json:"routes,omitempty"`
+}
+
+func (c *IPConfig) MarshalJSON() ([]byte, error) {
+ ipc := ipConfig{
+ IP: types.IPNet(c.IP),
+ Gateway: c.Gateway,
+ Routes: c.Routes,
+ }
+
+ return json.Marshal(ipc)
+}
+
+func (c *IPConfig) UnmarshalJSON(data []byte) error {
+ ipc := ipConfig{}
+ if err := json.Unmarshal(data, &ipc); err != nil {
+ return err
+ }
+
+ c.IP = net.IPNet(ipc.IP)
+ c.Gateway = ipc.Gateway
+ c.Routes = ipc.Routes
+ return nil
+}
diff --git a/vendor/github.com/containernetworking/cni/pkg/types/args.go b/vendor/github.com/containernetworking/cni/pkg/types/args.go
new file mode 100644
index 000000000..bd8640fc9
--- /dev/null
+++ b/vendor/github.com/containernetworking/cni/pkg/types/args.go
@@ -0,0 +1,112 @@
+// Copyright 2015 CNI authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package types
+
+import (
+ "encoding"
+ "fmt"
+ "reflect"
+ "strings"
+)
+
+// UnmarshallableBool typedef for builtin bool
+// because builtin type's methods can't be declared
+type UnmarshallableBool bool
+
+// UnmarshalText implements the encoding.TextUnmarshaler interface.
+// Returns boolean true if the string is "1" or "[Tt]rue"
+// Returns boolean false if the string is "0" or "[Ff]alse"
+func (b *UnmarshallableBool) UnmarshalText(data []byte) error {
+ s := strings.ToLower(string(data))
+ switch s {
+ case "1", "true":
+ *b = true
+ case "0", "false":
+ *b = false
+ default:
+ return fmt.Errorf("Boolean unmarshal error: invalid input %s", s)
+ }
+ return nil
+}
+
+// UnmarshallableString typedef for builtin string
+type UnmarshallableString string
+
+// UnmarshalText implements the encoding.TextUnmarshaler interface.
+// Returns the string
+func (s *UnmarshallableString) UnmarshalText(data []byte) error {
+ *s = UnmarshallableString(data)
+ return nil
+}
+
+// CommonArgs contains the IgnoreUnknown argument
+// and must be embedded by all Arg structs
+type CommonArgs struct {
+ IgnoreUnknown UnmarshallableBool `json:"ignoreunknown,omitempty"`
+}
+
+// GetKeyField is a helper function to receive Values
+// Values that represent a pointer to a struct
+func GetKeyField(keyString string, v reflect.Value) reflect.Value {
+ return v.Elem().FieldByName(keyString)
+}
+
+// UnmarshalableArgsError is used to indicate error unmarshalling args
+// from the args-string in the form "K=V;K2=V2;..."
+type UnmarshalableArgsError struct {
+ error
+}
+
+// LoadArgs parses args from a string in the form "K=V;K2=V2;..."
+func LoadArgs(args string, container interface{}) error {
+ if args == "" {
+ return nil
+ }
+
+ containerValue := reflect.ValueOf(container)
+
+ pairs := strings.Split(args, ";")
+ unknownArgs := []string{}
+ for _, pair := range pairs {
+ kv := strings.Split(pair, "=")
+ if len(kv) != 2 {
+ return fmt.Errorf("ARGS: invalid pair %q", pair)
+ }
+ keyString := kv[0]
+ valueString := kv[1]
+ keyField := GetKeyField(keyString, containerValue)
+ if !keyField.IsValid() {
+ unknownArgs = append(unknownArgs, pair)
+ continue
+ }
+ keyFieldIface := keyField.Addr().Interface()
+ u, ok := keyFieldIface.(encoding.TextUnmarshaler)
+ if !ok {
+ return UnmarshalableArgsError{fmt.Errorf(
+ "ARGS: cannot unmarshal into field '%s' - type '%s' does not implement encoding.TextUnmarshaler",
+ keyString, reflect.TypeOf(keyFieldIface))}
+ }
+ err := u.UnmarshalText([]byte(valueString))
+ if err != nil {
+ return fmt.Errorf("ARGS: error parsing value of pair %q: %v)", pair, err)
+ }
+ }
+
+ isIgnoreUnknown := GetKeyField("IgnoreUnknown", containerValue).Bool()
+ if len(unknownArgs) > 0 && !isIgnoreUnknown {
+ return fmt.Errorf("ARGS: unknown args %q", unknownArgs)
+ }
+ return nil
+}
diff --git a/vendor/github.com/containernetworking/cni/pkg/types/current/types.go b/vendor/github.com/containernetworking/cni/pkg/types/current/types.go
new file mode 100644
index 000000000..caac92ba7
--- /dev/null
+++ b/vendor/github.com/containernetworking/cni/pkg/types/current/types.go
@@ -0,0 +1,300 @@
+// Copyright 2016 CNI authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package current
+
+import (
+ "encoding/json"
+ "fmt"
+ "net"
+ "os"
+
+ "github.com/containernetworking/cni/pkg/types"
+ "github.com/containernetworking/cni/pkg/types/020"
+)
+
+const ImplementedSpecVersion string = "0.3.1"
+
+var SupportedVersions = []string{"0.3.0", ImplementedSpecVersion}
+
+func NewResult(data []byte) (types.Result, error) {
+ result := &Result{}
+ if err := json.Unmarshal(data, result); err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+func GetResult(r types.Result) (*Result, error) {
+ resultCurrent, err := r.GetAsVersion(ImplementedSpecVersion)
+ if err != nil {
+ return nil, err
+ }
+ result, ok := resultCurrent.(*Result)
+ if !ok {
+ return nil, fmt.Errorf("failed to convert result")
+ }
+ return result, nil
+}
+
+var resultConverters = []struct {
+ versions []string
+ convert func(types.Result) (*Result, error)
+}{
+ {types020.SupportedVersions, convertFrom020},
+ {SupportedVersions, convertFrom030},
+}
+
+func convertFrom020(result types.Result) (*Result, error) {
+ oldResult, err := types020.GetResult(result)
+ if err != nil {
+ return nil, err
+ }
+
+ newResult := &Result{
+ CNIVersion: ImplementedSpecVersion,
+ DNS: oldResult.DNS,
+ Routes: []*types.Route{},
+ }
+
+ if oldResult.IP4 != nil {
+ newResult.IPs = append(newResult.IPs, &IPConfig{
+ Version: "4",
+ Address: oldResult.IP4.IP,
+ Gateway: oldResult.IP4.Gateway,
+ })
+ for _, route := range oldResult.IP4.Routes {
+ gw := route.GW
+ if gw == nil {
+ gw = oldResult.IP4.Gateway
+ }
+ newResult.Routes = append(newResult.Routes, &types.Route{
+ Dst: route.Dst,
+ GW: gw,
+ })
+ }
+ }
+
+ if oldResult.IP6 != nil {
+ newResult.IPs = append(newResult.IPs, &IPConfig{
+ Version: "6",
+ Address: oldResult.IP6.IP,
+ Gateway: oldResult.IP6.Gateway,
+ })
+ for _, route := range oldResult.IP6.Routes {
+ gw := route.GW
+ if gw == nil {
+ gw = oldResult.IP6.Gateway
+ }
+ newResult.Routes = append(newResult.Routes, &types.Route{
+ Dst: route.Dst,
+ GW: gw,
+ })
+ }
+ }
+
+ if len(newResult.IPs) == 0 {
+ return nil, fmt.Errorf("cannot convert: no valid IP addresses")
+ }
+
+ return newResult, nil
+}
+
+func convertFrom030(result types.Result) (*Result, error) {
+ newResult, ok := result.(*Result)
+ if !ok {
+ return nil, fmt.Errorf("failed to convert result")
+ }
+ newResult.CNIVersion = ImplementedSpecVersion
+ return newResult, nil
+}
+
+func NewResultFromResult(result types.Result) (*Result, error) {
+ version := result.Version()
+ for _, converter := range resultConverters {
+ for _, supportedVersion := range converter.versions {
+ if version == supportedVersion {
+ return converter.convert(result)
+ }
+ }
+ }
+ return nil, fmt.Errorf("unsupported CNI result22 version %q", version)
+}
+
+// Result is what gets returned from the plugin (via stdout) to the caller
+type Result struct {
+ CNIVersion string `json:"cniVersion,omitempty"`
+ Interfaces []*Interface `json:"interfaces,omitempty"`
+ IPs []*IPConfig `json:"ips,omitempty"`
+ Routes []*types.Route `json:"routes,omitempty"`
+ DNS types.DNS `json:"dns,omitempty"`
+}
+
+// Convert to the older 0.2.0 CNI spec Result type
+func (r *Result) convertTo020() (*types020.Result, error) {
+ oldResult := &types020.Result{
+ CNIVersion: types020.ImplementedSpecVersion,
+ DNS: r.DNS,
+ }
+
+ for _, ip := range r.IPs {
+ // Only convert the first IP address of each version as 0.2.0
+ // and earlier cannot handle multiple IP addresses
+ if ip.Version == "4" && oldResult.IP4 == nil {
+ oldResult.IP4 = &types020.IPConfig{
+ IP: ip.Address,
+ Gateway: ip.Gateway,
+ }
+ } else if ip.Version == "6" && oldResult.IP6 == nil {
+ oldResult.IP6 = &types020.IPConfig{
+ IP: ip.Address,
+ Gateway: ip.Gateway,
+ }
+ }
+
+ if oldResult.IP4 != nil && oldResult.IP6 != nil {
+ break
+ }
+ }
+
+ for _, route := range r.Routes {
+ is4 := route.Dst.IP.To4() != nil
+ if is4 && oldResult.IP4 != nil {
+ oldResult.IP4.Routes = append(oldResult.IP4.Routes, types.Route{
+ Dst: route.Dst,
+ GW: route.GW,
+ })
+ } else if !is4 && oldResult.IP6 != nil {
+ oldResult.IP6.Routes = append(oldResult.IP6.Routes, types.Route{
+ Dst: route.Dst,
+ GW: route.GW,
+ })
+ }
+ }
+
+ if oldResult.IP4 == nil && oldResult.IP6 == nil {
+ return nil, fmt.Errorf("cannot convert: no valid IP addresses")
+ }
+
+ return oldResult, nil
+}
+
+func (r *Result) Version() string {
+ return ImplementedSpecVersion
+}
+
+func (r *Result) GetAsVersion(version string) (types.Result, error) {
+ switch version {
+ case "0.3.0", ImplementedSpecVersion:
+ r.CNIVersion = version
+ return r, nil
+ case types020.SupportedVersions[0], types020.SupportedVersions[1], types020.SupportedVersions[2]:
+ return r.convertTo020()
+ }
+ return nil, fmt.Errorf("cannot convert version 0.3.x to %q", version)
+}
+
+func (r *Result) Print() error {
+ data, err := json.MarshalIndent(r, "", " ")
+ if err != nil {
+ return err
+ }
+ _, err = os.Stdout.Write(data)
+ return err
+}
+
+// String returns a formatted string in the form of "[Interfaces: $1,][ IP: $2,] DNS: $3" where
+// $1 represents the receiver's Interfaces, $2 represents the receiver's IP addresses and $3 the
+// receiver's DNS. If $1 or $2 are nil, they won't be present in the returned string.
+func (r *Result) String() string {
+ var str string
+ if len(r.Interfaces) > 0 {
+ str += fmt.Sprintf("Interfaces:%+v, ", r.Interfaces)
+ }
+ if len(r.IPs) > 0 {
+ str += fmt.Sprintf("IP:%+v, ", r.IPs)
+ }
+ if len(r.Routes) > 0 {
+ str += fmt.Sprintf("Routes:%+v, ", r.Routes)
+ }
+ return fmt.Sprintf("%sDNS:%+v", str, r.DNS)
+}
+
+// Convert this old version result to the current CNI version result
+func (r *Result) Convert() (*Result, error) {
+ return r, nil
+}
+
+// Interface contains values about the created interfaces
+type Interface struct {
+ Name string `json:"name"`
+ Mac string `json:"mac,omitempty"`
+ Sandbox string `json:"sandbox,omitempty"`
+}
+
+func (i *Interface) String() string {
+ return fmt.Sprintf("%+v", *i)
+}
+
+// Int returns a pointer to the int value passed in. Used to
+// set the IPConfig.Interface field.
+func Int(v int) *int {
+ return &v
+}
+
+// IPConfig contains values necessary to configure an IP address on an interface
+type IPConfig struct {
+ // IP version, either "4" or "6"
+ Version string
+ // Index into Result structs Interfaces list
+ Interface *int
+ Address net.IPNet
+ Gateway net.IP
+}
+
+func (i *IPConfig) String() string {
+ return fmt.Sprintf("%+v", *i)
+}
+
+// JSON (un)marshallable types
+type ipConfig struct {
+ Version string `json:"version"`
+ Interface *int `json:"interface,omitempty"`
+ Address types.IPNet `json:"address"`
+ Gateway net.IP `json:"gateway,omitempty"`
+}
+
+func (c *IPConfig) MarshalJSON() ([]byte, error) {
+ ipc := ipConfig{
+ Version: c.Version,
+ Interface: c.Interface,
+ Address: types.IPNet(c.Address),
+ Gateway: c.Gateway,
+ }
+
+ return json.Marshal(ipc)
+}
+
+func (c *IPConfig) UnmarshalJSON(data []byte) error {
+ ipc := ipConfig{}
+ if err := json.Unmarshal(data, &ipc); err != nil {
+ return err
+ }
+
+ c.Version = ipc.Version
+ c.Interface = ipc.Interface
+ c.Address = net.IPNet(ipc.Address)
+ c.Gateway = ipc.Gateway
+ return nil
+}
diff --git a/vendor/github.com/containernetworking/cni/pkg/types/types.go b/vendor/github.com/containernetworking/cni/pkg/types/types.go
new file mode 100644
index 000000000..641275600
--- /dev/null
+++ b/vendor/github.com/containernetworking/cni/pkg/types/types.go
@@ -0,0 +1,189 @@
+// Copyright 2015 CNI authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package types
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "net"
+ "os"
+)
+
+// like net.IPNet but adds JSON marshalling and unmarshalling
+type IPNet net.IPNet
+
+// ParseCIDR takes a string like "10.2.3.1/24" and
+// return IPNet with "10.2.3.1" and /24 mask
+func ParseCIDR(s string) (*net.IPNet, error) {
+ ip, ipn, err := net.ParseCIDR(s)
+ if err != nil {
+ return nil, err
+ }
+
+ ipn.IP = ip
+ return ipn, nil
+}
+
+func (n IPNet) MarshalJSON() ([]byte, error) {
+ return json.Marshal((*net.IPNet)(&n).String())
+}
+
+func (n *IPNet) UnmarshalJSON(data []byte) error {
+ var s string
+ if err := json.Unmarshal(data, &s); err != nil {
+ return err
+ }
+
+ tmp, err := ParseCIDR(s)
+ if err != nil {
+ return err
+ }
+
+ *n = IPNet(*tmp)
+ return nil
+}
+
+// NetConf describes a network.
+type NetConf struct {
+ CNIVersion string `json:"cniVersion,omitempty"`
+
+ Name string `json:"name,omitempty"`
+ Type string `json:"type,omitempty"`
+ Capabilities map[string]bool `json:"capabilities,omitempty"`
+ IPAM struct {
+ Type string `json:"type,omitempty"`
+ } `json:"ipam,omitempty"`
+ DNS DNS `json:"dns"`
+}
+
+// NetConfList describes an ordered list of networks.
+type NetConfList struct {
+ CNIVersion string `json:"cniVersion,omitempty"`
+
+ Name string `json:"name,omitempty"`
+ Plugins []*NetConf `json:"plugins,omitempty"`
+}
+
+type ResultFactoryFunc func([]byte) (Result, error)
+
+// Result is an interface that provides the result of plugin execution
+type Result interface {
+ // The highest CNI specification result verison the result supports
+ // without having to convert
+ Version() string
+
+ // Returns the result converted into the requested CNI specification
+ // result version, or an error if conversion failed
+ GetAsVersion(version string) (Result, error)
+
+ // Prints the result in JSON format to stdout
+ Print() error
+
+ // Returns a JSON string representation of the result
+ String() string
+}
+
+func PrintResult(result Result, version string) error {
+ newResult, err := result.GetAsVersion(version)
+ if err != nil {
+ return err
+ }
+ return newResult.Print()
+}
+
+// DNS contains values interesting for DNS resolvers
+type DNS struct {
+ Nameservers []string `json:"nameservers,omitempty"`
+ Domain string `json:"domain,omitempty"`
+ Search []string `json:"search,omitempty"`
+ Options []string `json:"options,omitempty"`
+}
+
+type Route struct {
+ Dst net.IPNet
+ GW net.IP
+}
+
+func (r *Route) String() string {
+ return fmt.Sprintf("%+v", *r)
+}
+
+// Well known error codes
+// see https://github.com/containernetworking/cni/blob/master/SPEC.md#well-known-error-codes
+const (
+ ErrUnknown uint = iota // 0
+ ErrIncompatibleCNIVersion // 1
+ ErrUnsupportedField // 2
+)
+
+type Error struct {
+ Code uint `json:"code"`
+ Msg string `json:"msg"`
+ Details string `json:"details,omitempty"`
+}
+
+func (e *Error) Error() string {
+ details := ""
+ if e.Details != "" {
+ details = fmt.Sprintf("; %v", e.Details)
+ }
+ return fmt.Sprintf("%v%v", e.Msg, details)
+}
+
+func (e *Error) Print() error {
+ return prettyPrint(e)
+}
+
+// net.IPNet is not JSON (un)marshallable so this duality is needed
+// for our custom IPNet type
+
+// JSON (un)marshallable types
+type route struct {
+ Dst IPNet `json:"dst"`
+ GW net.IP `json:"gw,omitempty"`
+}
+
+func (r *Route) UnmarshalJSON(data []byte) error {
+ rt := route{}
+ if err := json.Unmarshal(data, &rt); err != nil {
+ return err
+ }
+
+ r.Dst = net.IPNet(rt.Dst)
+ r.GW = rt.GW
+ return nil
+}
+
+func (r *Route) MarshalJSON() ([]byte, error) {
+ rt := route{
+ Dst: IPNet(r.Dst),
+ GW: r.GW,
+ }
+
+ 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
+}
+
+// NotImplementedError is used to indicate that a method is not implemented for the given platform
+var NotImplementedError = errors.New("Not Implemented")
diff --git a/vendor/github.com/containernetworking/cni/pkg/version/conf.go b/vendor/github.com/containernetworking/cni/pkg/version/conf.go
new file mode 100644
index 000000000..3cca58bbe
--- /dev/null
+++ b/vendor/github.com/containernetworking/cni/pkg/version/conf.go
@@ -0,0 +1,37 @@
+// Copyright 2016 CNI authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package version
+
+import (
+ "encoding/json"
+ "fmt"
+)
+
+// ConfigDecoder can decode the CNI version available in network config data
+type ConfigDecoder struct{}
+
+func (*ConfigDecoder) Decode(jsonBytes []byte) (string, error) {
+ var conf struct {
+ CNIVersion string `json:"cniVersion"`
+ }
+ err := json.Unmarshal(jsonBytes, &conf)
+ if err != nil {
+ return "", fmt.Errorf("decoding version from network config: %s", err)
+ }
+ if conf.CNIVersion == "" {
+ return "0.1.0", nil
+ }
+ return conf.CNIVersion, nil
+}
diff --git a/vendor/github.com/containernetworking/cni/pkg/version/plugin.go b/vendor/github.com/containernetworking/cni/pkg/version/plugin.go
new file mode 100644
index 000000000..8a4672810
--- /dev/null
+++ b/vendor/github.com/containernetworking/cni/pkg/version/plugin.go
@@ -0,0 +1,81 @@
+// Copyright 2016 CNI authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package version
+
+import (
+ "encoding/json"
+ "fmt"
+ "io"
+)
+
+// PluginInfo reports information about CNI versioning
+type PluginInfo interface {
+ // SupportedVersions returns one or more CNI spec versions that the plugin
+ // supports. If input is provided in one of these versions, then the plugin
+ // promises to use the same CNI version in its response
+ SupportedVersions() []string
+
+ // Encode writes this CNI version information as JSON to the given Writer
+ Encode(io.Writer) error
+}
+
+type pluginInfo struct {
+ CNIVersion_ string `json:"cniVersion"`
+ SupportedVersions_ []string `json:"supportedVersions,omitempty"`
+}
+
+// pluginInfo implements the PluginInfo interface
+var _ PluginInfo = &pluginInfo{}
+
+func (p *pluginInfo) Encode(w io.Writer) error {
+ return json.NewEncoder(w).Encode(p)
+}
+
+func (p *pluginInfo) SupportedVersions() []string {
+ return p.SupportedVersions_
+}
+
+// PluginSupports returns a new PluginInfo that will report the given versions
+// as supported
+func PluginSupports(supportedVersions ...string) PluginInfo {
+ if len(supportedVersions) < 1 {
+ panic("programmer error: you must support at least one version")
+ }
+ return &pluginInfo{
+ CNIVersion_: Current(),
+ SupportedVersions_: supportedVersions,
+ }
+}
+
+// PluginDecoder can decode the response returned by a plugin's VERSION command
+type PluginDecoder struct{}
+
+func (*PluginDecoder) Decode(jsonBytes []byte) (PluginInfo, error) {
+ var info pluginInfo
+ err := json.Unmarshal(jsonBytes, &info)
+ if err != nil {
+ return nil, fmt.Errorf("decoding version info: %s", err)
+ }
+ if info.CNIVersion_ == "" {
+ return nil, fmt.Errorf("decoding version info: missing field cniVersion")
+ }
+ if len(info.SupportedVersions_) == 0 {
+ if info.CNIVersion_ == "0.2.0" {
+ return PluginSupports("0.1.0", "0.2.0"), nil
+ }
+ return nil, fmt.Errorf("decoding version info: missing field supportedVersions")
+ }
+ return &info, nil
+}
diff --git a/vendor/github.com/containernetworking/cni/pkg/version/reconcile.go b/vendor/github.com/containernetworking/cni/pkg/version/reconcile.go
new file mode 100644
index 000000000..25c3810b2
--- /dev/null
+++ b/vendor/github.com/containernetworking/cni/pkg/version/reconcile.go
@@ -0,0 +1,49 @@
+// Copyright 2016 CNI authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package version
+
+import "fmt"
+
+type ErrorIncompatible struct {
+ Config string
+ Supported []string
+}
+
+func (e *ErrorIncompatible) Details() string {
+ return fmt.Sprintf("config is %q, plugin supports %q", e.Config, e.Supported)
+}
+
+func (e *ErrorIncompatible) Error() string {
+ return fmt.Sprintf("incompatible CNI versions: %s", e.Details())
+}
+
+type Reconciler struct{}
+
+func (r *Reconciler) Check(configVersion string, pluginInfo PluginInfo) *ErrorIncompatible {
+ return r.CheckRaw(configVersion, pluginInfo.SupportedVersions())
+}
+
+func (*Reconciler) CheckRaw(configVersion string, supportedVersions []string) *ErrorIncompatible {
+ for _, supportedVersion := range supportedVersions {
+ if configVersion == supportedVersion {
+ return nil
+ }
+ }
+
+ return &ErrorIncompatible{
+ Config: configVersion,
+ Supported: supportedVersions,
+ }
+}
diff --git a/vendor/github.com/containernetworking/cni/pkg/version/version.go b/vendor/github.com/containernetworking/cni/pkg/version/version.go
new file mode 100644
index 000000000..efe8ea871
--- /dev/null
+++ b/vendor/github.com/containernetworking/cni/pkg/version/version.go
@@ -0,0 +1,61 @@
+// Copyright 2016 CNI authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package version
+
+import (
+ "fmt"
+
+ "github.com/containernetworking/cni/pkg/types"
+ "github.com/containernetworking/cni/pkg/types/020"
+ "github.com/containernetworking/cni/pkg/types/current"
+)
+
+// Current reports the version of the CNI spec implemented by this library
+func Current() string {
+ return "0.3.1"
+}
+
+// Legacy PluginInfo describes a plugin that is backwards compatible with the
+// CNI spec version 0.1.0. In particular, a runtime compiled against the 0.1.0
+// library ought to work correctly with a plugin that reports support for
+// Legacy versions.
+//
+// Any future CNI spec versions which meet this definition should be added to
+// this list.
+var Legacy = PluginSupports("0.1.0", "0.2.0")
+var All = PluginSupports("0.1.0", "0.2.0", "0.3.0", "0.3.1")
+
+var resultFactories = []struct {
+ supportedVersions []string
+ newResult types.ResultFactoryFunc
+}{
+ {current.SupportedVersions, current.NewResult},
+ {types020.SupportedVersions, types020.NewResult},
+}
+
+// Finds a Result object matching the requested version (if any) and asks
+// that object to parse the plugin result, returning an error if parsing failed.
+func NewResult(version string, resultBytes []byte) (types.Result, error) {
+ reconciler := &Reconciler{}
+ for _, resultFactory := range resultFactories {
+ err := reconciler.CheckRaw(version, resultFactory.supportedVersions)
+ if err == nil {
+ // Result supports this version
+ return resultFactory.newResult(resultBytes)
+ }
+ }
+
+ return nil, fmt.Errorf("unsupported CNI result version %q", version)
+}