diff --git a/SPEC.md b/SPEC.md index cf752226..91c85d30 100644 --- a/SPEC.md +++ b/SPEC.md @@ -64,8 +64,14 @@ The operations that the CNI plugin needs to support are: - Report version - Parameters: NONE. - - Result: - - The version of the CNI spec implemented by the plugin: `{ "cniVersion": "0.2.0" }` + - Result: information about the CNI spec versions supported by the plugin + + ``` + { + "cniVersion": "0.3.0", // the version of the CNI spec in use for this output + "supportedVersions": [ "0.1.0", "0.2.0", "0.3.0" ] // the list of CNI spec versions that this plugin supports + } + ``` The executable command-line API uses the type of network (see [Network Configuration](#network-configuration) below) as the name of the executable to invoke. It will then look for this executable in a list of predefined directories. Once found, it will invoke the executable using the following environment variables for argument passing: @@ -85,7 +91,7 @@ Success is indicated by a return code of zero and the following JSON printed to ``` { - "cniVersion": "0.2.0", + "cniVersion": "0.3.0", "ip4": { "ip": , "gateway": , (optional) @@ -114,7 +120,7 @@ Examples include generating an `/etc/resolv.conf` file to be injected into the c Errors are indicated by a non-zero return code and the following JSON being printed to stdout: ``` { - "cniVersion": "0.2.0", + "cniVersion": "0.3.0", "code": , "msg": , "details": (optional) @@ -151,7 +157,7 @@ Plugins may define additional fields that they accept and may generate an error ```json { - "cniVersion": "0.2.0", + "cniVersion": "0.3.0", "name": "dbnet", "type": "bridge", // type (plugin) specific @@ -170,7 +176,7 @@ Plugins may define additional fields that they accept and may generate an error ```json { - "cniVersion": "0.2.0", + "cniVersion": "0.3.0", "name": "pci", "type": "ovs", // type (plugin) specific @@ -220,7 +226,7 @@ Success is indicated by a zero return code and the following JSON being printed ``` { - "cniVersion": "0.2.0", + "cniVersion": "0.3.0", "ip4": { "ip": , "gateway": , (optional) diff --git a/libcni/api.go b/libcni/api.go index 340a20cc..6e616da6 100644 --- a/libcni/api.go +++ b/libcni/api.go @@ -19,6 +19,7 @@ import ( "github.com/containernetworking/cni/pkg/invoke" "github.com/containernetworking/cni/pkg/types" + "github.com/containernetworking/cni/pkg/version" ) type RuntimeConf struct { @@ -60,6 +61,17 @@ func (c *CNIConfig) DelNetwork(net *NetworkConfig, rt *RuntimeConf) error { return invoke.ExecPluginWithoutResult(pluginPath, net.Bytes, c.args("DEL", rt)) } +func (c *CNIConfig) GetVersionInfo(pluginType string) (version.PluginInfo, error) { + pluginPath, err := invoke.FindInPath(pluginType, c.Path) + if err != nil { + return nil, err + } + + // TODO: if error is because plugin is old and VERSION command is unrecognized + // then do the right thing and return version.PluginSupports("0.1.0"), nil + return invoke.ExecPluginForVersion(pluginPath) +} + // ===== func (c *CNIConfig) args(action string, rt *RuntimeConf) *invoke.Args { return &invoke.Args{ diff --git a/libcni/api_test.go b/libcni/api_test.go index 2df6b4e3..5e0dd0fe 100644 --- a/libcni/api_test.go +++ b/libcni/api_test.go @@ -155,4 +155,23 @@ var _ = Describe("Invoking the plugin", func() { }) }) }) + + Describe("GetVersionInfo", func() { + It("executes the plugin with the command VERSION", func() { + versionInfo, err := cniConfig.GetVersionInfo("noop") + Expect(err).NotTo(HaveOccurred()) + + Expect(versionInfo).NotTo(BeNil()) + Expect(versionInfo.SupportedVersions()).To(Equal([]string{ + "0.-42.0", "0.1.0", "0.2.0", "0.3.0", + })) + }) + + Context("when finding the plugin fails", func() { + It("returns the error", func() { + _, err := cniConfig.GetVersionInfo("does-not-exist") + Expect(err).To(MatchError(ContainSubstring(`failed to find plugin "does-not-exist"`))) + }) + }) + }) }) diff --git a/pkg/invoke/exec.go b/pkg/invoke/exec.go index d7e38f21..3d32ab7c 100644 --- a/pkg/invoke/exec.go +++ b/pkg/invoke/exec.go @@ -23,6 +23,7 @@ import ( "os/exec" "github.com/containernetworking/cni/pkg/types" + "github.com/containernetworking/cni/pkg/version" ) func pluginErr(err error, output []byte) error { @@ -57,6 +58,15 @@ func ExecPluginWithoutResult(pluginPath string, netconf []byte, args CNIArgs) er return err } +func ExecPluginForVersion(pluginPath string) (version.PluginInfo, error) { + stdoutBytes, err := execPlugin(pluginPath, nil, &Args{Command: "VERSION"}) + if err != nil { + return nil, err + } + + return version.Decode(stdoutBytes) +} + func execPlugin(pluginPath string, netconf []byte, args CNIArgs) ([]byte, error) { return defaultRawExec.ExecPlugin(pluginPath, netconf, args.AsEnv()) } diff --git a/pkg/skel/skel.go b/pkg/skel/skel.go index 19ddf249..de64d7dd 100644 --- a/pkg/skel/skel.go +++ b/pkg/skel/skel.go @@ -39,11 +39,10 @@ type CmdArgs struct { } type dispatcher struct { - Getenv func(string) string - Stdin io.Reader - Stdout io.Writer - Stderr io.Writer - Versioner version.PluginVersioner + Getenv func(string) string + Stdin io.Reader + Stdout io.Writer + Stderr io.Writer } type reqForCmdEntry map[string]bool @@ -144,7 +143,7 @@ func createTypedError(f string, args ...interface{}) *types.Error { } } -func (t *dispatcher) pluginMain(cmdAdd, cmdDel func(_ *CmdArgs) error) *types.Error { +func (t *dispatcher) pluginMain(cmdAdd, cmdDel func(_ *CmdArgs) error, versionInfo version.PluginInfo) *types.Error { cmd, cmdArgs, err := t.getCmdArgsFromEnv() if err != nil { return createTypedError(err.Error()) @@ -158,7 +157,7 @@ func (t *dispatcher) pluginMain(cmdAdd, cmdDel func(_ *CmdArgs) error) *types.Er err = cmdDel(cmdArgs) case "VERSION": - err = t.Versioner.Encode(t.Stdout) + err = versionInfo.Encode(t.Stdout) default: return createTypedError("unknown CNI_COMMAND: %v", cmd) @@ -176,16 +175,15 @@ func (t *dispatcher) pluginMain(cmdAdd, cmdDel func(_ *CmdArgs) error) *types.Er // PluginMain is the "main" for a plugin. It accepts // two callback functions for add and del commands. -func PluginMain(cmdAdd, cmdDel func(_ *CmdArgs) error) { +func PluginMain(cmdAdd, cmdDel func(_ *CmdArgs) error, versionInfo version.PluginInfo) { caller := dispatcher{ - Getenv: os.Getenv, - Stdin: os.Stdin, - Stdout: os.Stdout, - Stderr: os.Stderr, - Versioner: version.DefaultPluginVersioner, + Getenv: os.Getenv, + Stdin: os.Stdin, + Stdout: os.Stdout, + Stderr: os.Stderr, } - err := caller.pluginMain(cmdAdd, cmdDel) + err := caller.pluginMain(cmdAdd, cmdDel, versionInfo) if err != nil { dieErr(err) } diff --git a/pkg/skel/skel_test.go b/pkg/skel/skel_test.go index e6304f5e..0431abbb 100644 --- a/pkg/skel/skel_test.go +++ b/pkg/skel/skel_test.go @@ -53,6 +53,7 @@ var _ = Describe("dispatching to the correct callback", func() { cmdAdd, cmdDel *fakeCmd dispatch *dispatcher expectedCmdArgs *CmdArgs + versionInfo version.PluginInfo ) BeforeEach(func() { @@ -67,13 +68,12 @@ var _ = Describe("dispatching to the correct callback", func() { stdin = strings.NewReader(`{ "some": "config" }`) stdout = &bytes.Buffer{} stderr = &bytes.Buffer{} - versioner := &version.BasicVersioner{CNIVersion: "9.8.7"} + versionInfo = version.PluginSupports("9.8.7") dispatch = &dispatcher{ - Getenv: func(key string) string { return environment[key] }, - Stdin: stdin, - Stdout: stdout, - Stderr: stderr, - Versioner: versioner, + Getenv: func(key string) string { return environment[key] }, + Stdin: stdin, + Stdout: stdout, + Stderr: stderr, } cmdAdd = &fakeCmd{} cmdDel = &fakeCmd{} @@ -90,7 +90,7 @@ var _ = Describe("dispatching to the correct callback", func() { var envVarChecker = func(envVar string, isRequired bool) { delete(environment, envVar) - err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func) + err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo) if isRequired { Expect(err).To(Equal(&types.Error{ Code: 100, @@ -104,7 +104,7 @@ var _ = Describe("dispatching to the correct callback", func() { Context("when the CNI_COMMAND is ADD", func() { It("extracts env vars and stdin data and calls cmdAdd", func() { - err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func) + err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo) Expect(err).NotTo(HaveOccurred()) Expect(cmdAdd.CallCount).To(Equal(1)) @@ -113,7 +113,7 @@ var _ = Describe("dispatching to the correct callback", func() { }) It("does not call cmdDel", func() { - err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func) + err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo) Expect(err).NotTo(HaveOccurred()) Expect(cmdDel.CallCount).To(Equal(0)) @@ -136,7 +136,7 @@ var _ = Describe("dispatching to the correct callback", func() { }) It("reports that all of them are missing, not just the first", func() { - Expect(dispatch.pluginMain(cmdAdd.Func, cmdDel.Func)).NotTo(Succeed()) + Expect(dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)).NotTo(Succeed()) log := stderr.String() Expect(log).To(ContainSubstring("CNI_NETNS env variable missing\n")) Expect(log).To(ContainSubstring("CNI_IFNAME env variable missing\n")) @@ -152,7 +152,7 @@ var _ = Describe("dispatching to the correct callback", func() { }) It("calls cmdDel with the env vars and stdin data", func() { - err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func) + err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo) Expect(err).NotTo(HaveOccurred()) Expect(cmdDel.CallCount).To(Equal(1)) @@ -160,7 +160,7 @@ var _ = Describe("dispatching to the correct callback", func() { }) It("does not call cmdAdd", func() { - err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func) + err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo) Expect(err).NotTo(HaveOccurred()) Expect(cmdAdd.CallCount).To(Equal(0)) @@ -182,14 +182,17 @@ var _ = Describe("dispatching to the correct callback", func() { }) It("prints the version to stdout", func() { - err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func) + err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo) Expect(err).NotTo(HaveOccurred()) - Expect(stdout).To(MatchJSON(`{ "cniVersion": "9.8.7" }`)) + Expect(stdout).To(MatchJSON(`{ + "cniVersion": "0.3.0", + "supportedVersions": ["9.8.7"] + }`)) }) It("does not call cmdAdd or cmdDel", func() { - err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func) + err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo) Expect(err).NotTo(HaveOccurred()) Expect(cmdAdd.CallCount).To(Equal(0)) @@ -212,14 +215,14 @@ var _ = Describe("dispatching to the correct callback", func() { }) It("does not call any cmd callback", func() { - dispatch.pluginMain(cmdAdd.Func, cmdDel.Func) + dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo) Expect(cmdAdd.CallCount).To(Equal(0)) Expect(cmdDel.CallCount).To(Equal(0)) }) It("returns an error", func() { - err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func) + err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo) Expect(err).To(Equal(&types.Error{ Code: 100, @@ -234,14 +237,14 @@ var _ = Describe("dispatching to the correct callback", func() { }) It("does not call any cmd callback", func() { - dispatch.pluginMain(cmdAdd.Func, cmdDel.Func) + dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo) Expect(cmdAdd.CallCount).To(Equal(0)) Expect(cmdDel.CallCount).To(Equal(0)) }) It("wraps and returns the error", func() { - err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func) + err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo) Expect(err).To(Equal(&types.Error{ Code: 100, @@ -260,7 +263,7 @@ var _ = Describe("dispatching to the correct callback", func() { }) It("returns the error as-is", func() { - err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func) + err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo) Expect(err).To(Equal(&types.Error{ Code: 1234, @@ -275,7 +278,7 @@ var _ = Describe("dispatching to the correct callback", func() { }) It("wraps and returns the error", func() { - err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func) + err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo) Expect(err).To(Equal(&types.Error{ Code: 100, diff --git a/pkg/version/version.go b/pkg/version/version.go index 2cb075fb..72b6e9b8 100644 --- a/pkg/version/version.go +++ b/pkg/version/version.go @@ -16,27 +16,67 @@ package version import ( "encoding/json" + "fmt" "io" ) -// A PluginVersioner can encode information about its version -type PluginVersioner interface { +// Current reports the version of the CNI spec implemented by this library +func Current() string { + return "0.3.0" +} + +// 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 } -// BasicVersioner is a PluginVersioner which reports a single cniVersion string -type BasicVersioner struct { - CNIVersion string `json:"cniVersion"` +type simple struct { + CNIVersion_ string `json:"cniVersion"` + SupportedVersions_ []string `json:"supportedVersions,omitempty"` } -func (p *BasicVersioner) Encode(w io.Writer) error { +func (p *simple) Encode(w io.Writer) error { return json.NewEncoder(w).Encode(p) } -// Current reports the version of the CNI spec implemented by this library -func Current() string { - return "0.2.0" +func (p *simple) SupportedVersions() []string { + return p.SupportedVersions_ } -// DefaultPluginVersioner reports the Current library spec version as the cniVersion -var DefaultPluginVersioner = &BasicVersioner{CNIVersion: Current()} +// 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 &simple{ + CNIVersion_: Current(), + SupportedVersions_: supportedVersions, + } +} + +func Decode(jsonBytes []byte) (PluginInfo, error) { + var info simple + 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 +} + +var Legacy = PluginSupports("0.1.0", "0.2.0", "0.3.0") diff --git a/pkg/version/version_suite_test.go b/pkg/version/version_suite_test.go new file mode 100644 index 00000000..25d503c8 --- /dev/null +++ b/pkg/version/version_suite_test.go @@ -0,0 +1,27 @@ +// 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_test + +import ( + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + "testing" +) + +func TestVersion(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Version Suite") +} diff --git a/pkg/version/version_test.go b/pkg/version/version_test.go new file mode 100644 index 00000000..08b89aed --- /dev/null +++ b/pkg/version/version_test.go @@ -0,0 +1,72 @@ +// 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_test + +import ( + "github.com/containernetworking/cni/pkg/version" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("Decode", func() { + It("returns a PluginInfo that represents the given json bytes", func() { + pluginInfo, err := version.Decode([]byte(`{ + "cniVersion": "some-library-version", + "supportedVersions": [ "some-version", "some-other-version" ] + }`)) + Expect(err).NotTo(HaveOccurred()) + Expect(pluginInfo).NotTo(BeNil()) + Expect(pluginInfo.SupportedVersions()).To(Equal([]string{ + "some-version", + "some-other-version", + })) + }) + + Context("when the bytes cannot be decoded as json", func() { + It("returns a meaningful error", func() { + _, err := version.Decode([]byte(`{{{`)) + Expect(err).To(MatchError("decoding version info: invalid character '{' looking for beginning of object key string")) + }) + }) + + Context("when the json bytes are missing the required CNIVersion field", func() { + It("returns a meaningful error", func() { + _, err := version.Decode([]byte(`{ "supportedVersions": [ "foo" ] }`)) + Expect(err).To(MatchError("decoding version info: missing field cniVersion")) + }) + }) + + Context("when there are no supported versions", func() { + Context("when the cniVersion is 0.2.0", func() { + It("infers the supported versions are 0.1.0 and 0.2.0", func() { + pluginInfo, err := version.Decode([]byte(`{ "cniVersion": "0.2.0" }`)) + Expect(err).NotTo(HaveOccurred()) + Expect(pluginInfo).NotTo(BeNil()) + Expect(pluginInfo.SupportedVersions()).To(Equal([]string{ + "0.1.0", + "0.2.0", + })) + }) + }) + + Context("when the cniVersion is >= 0.3.0", func() { + It("returns a meaningful error", func() { + _, err := version.Decode([]byte(`{ "cniVersion": "0.3.0" }`)) + Expect(err).To(MatchError("decoding version info: missing field supportedVersions")) + }) + }) + }) + +}) diff --git a/plugins/ipam/dhcp/main.go b/plugins/ipam/dhcp/main.go index b5378315..0e46af91 100644 --- a/plugins/ipam/dhcp/main.go +++ b/plugins/ipam/dhcp/main.go @@ -22,6 +22,7 @@ import ( "github.com/containernetworking/cni/pkg/skel" "github.com/containernetworking/cni/pkg/types" + "github.com/containernetworking/cni/pkg/version" ) const socketPath = "/run/cni/dhcp.sock" @@ -30,7 +31,7 @@ func main() { if len(os.Args) > 1 && os.Args[1] == "daemon" { runDaemon() } else { - skel.PluginMain(cmdAdd, cmdDel) + skel.PluginMain(cmdAdd, cmdDel, version.Legacy) } } diff --git a/plugins/ipam/host-local/main.go b/plugins/ipam/host-local/main.go index d2f3c305..0e1b0639 100644 --- a/plugins/ipam/host-local/main.go +++ b/plugins/ipam/host-local/main.go @@ -19,10 +19,11 @@ import ( "github.com/containernetworking/cni/pkg/skel" "github.com/containernetworking/cni/pkg/types" + "github.com/containernetworking/cni/pkg/version" ) func main() { - skel.PluginMain(cmdAdd, cmdDel) + skel.PluginMain(cmdAdd, cmdDel, version.Legacy) } func cmdAdd(args *skel.CmdArgs) error { diff --git a/plugins/main/bridge/bridge.go b/plugins/main/bridge/bridge.go index 2fef878d..bc173017 100644 --- a/plugins/main/bridge/bridge.go +++ b/plugins/main/bridge/bridge.go @@ -28,6 +28,7 @@ import ( "github.com/containernetworking/cni/pkg/skel" "github.com/containernetworking/cni/pkg/types" "github.com/containernetworking/cni/pkg/utils" + "github.com/containernetworking/cni/pkg/version" "github.com/vishvananda/netlink" ) @@ -354,5 +355,5 @@ func cmdDel(args *skel.CmdArgs) error { } func main() { - skel.PluginMain(cmdAdd, cmdDel) + skel.PluginMain(cmdAdd, cmdDel, version.Legacy) } diff --git a/plugins/main/ipvlan/ipvlan.go b/plugins/main/ipvlan/ipvlan.go index d7cfc39f..4c58109b 100644 --- a/plugins/main/ipvlan/ipvlan.go +++ b/plugins/main/ipvlan/ipvlan.go @@ -25,6 +25,7 @@ import ( "github.com/containernetworking/cni/pkg/ns" "github.com/containernetworking/cni/pkg/skel" "github.com/containernetworking/cni/pkg/types" + "github.com/containernetworking/cni/pkg/version" "github.com/vishvananda/netlink" ) @@ -171,5 +172,5 @@ func renameLink(curName, newName string) error { } func main() { - skel.PluginMain(cmdAdd, cmdDel) + skel.PluginMain(cmdAdd, cmdDel, version.Legacy) } diff --git a/plugins/main/loopback/loopback.go b/plugins/main/loopback/loopback.go index 186fd54c..1344c130 100644 --- a/plugins/main/loopback/loopback.go +++ b/plugins/main/loopback/loopback.go @@ -18,6 +18,7 @@ import ( "github.com/containernetworking/cni/pkg/ns" "github.com/containernetworking/cni/pkg/skel" "github.com/containernetworking/cni/pkg/types" + "github.com/containernetworking/cni/pkg/version" "github.com/vishvananda/netlink" ) @@ -67,5 +68,5 @@ func cmdDel(args *skel.CmdArgs) error { } func main() { - skel.PluginMain(cmdAdd, cmdDel) + skel.PluginMain(cmdAdd, cmdDel, version.Legacy) } diff --git a/plugins/main/macvlan/macvlan.go b/plugins/main/macvlan/macvlan.go index 63c9f7f0..ef012696 100644 --- a/plugins/main/macvlan/macvlan.go +++ b/plugins/main/macvlan/macvlan.go @@ -26,6 +26,7 @@ import ( "github.com/containernetworking/cni/pkg/skel" "github.com/containernetworking/cni/pkg/types" "github.com/containernetworking/cni/pkg/utils/sysctl" + "github.com/containernetworking/cni/pkg/version" "github.com/vishvananda/netlink" ) @@ -193,5 +194,5 @@ func renameLink(curName, newName string) error { } func main() { - skel.PluginMain(cmdAdd, cmdDel) + skel.PluginMain(cmdAdd, cmdDel, version.Legacy) } diff --git a/plugins/main/ptp/ptp.go b/plugins/main/ptp/ptp.go index 014b472c..a26b09ee 100644 --- a/plugins/main/ptp/ptp.go +++ b/plugins/main/ptp/ptp.go @@ -30,6 +30,7 @@ import ( "github.com/containernetworking/cni/pkg/skel" "github.com/containernetworking/cni/pkg/types" "github.com/containernetworking/cni/pkg/utils" + "github.com/containernetworking/cni/pkg/version" ) func init() { @@ -236,5 +237,5 @@ func cmdDel(args *skel.CmdArgs) error { } func main() { - skel.PluginMain(cmdAdd, cmdDel) + skel.PluginMain(cmdAdd, cmdDel, version.Legacy) } diff --git a/plugins/meta/flannel/flannel.go b/plugins/meta/flannel/flannel.go index 096fe6d6..334bd41b 100644 --- a/plugins/meta/flannel/flannel.go +++ b/plugins/meta/flannel/flannel.go @@ -32,6 +32,7 @@ import ( "github.com/containernetworking/cni/pkg/invoke" "github.com/containernetworking/cni/pkg/skel" "github.com/containernetworking/cni/pkg/types" + "github.com/containernetworking/cni/pkg/version" ) const ( @@ -249,5 +250,5 @@ func cmdDel(args *skel.CmdArgs) error { } func main() { - skel.PluginMain(cmdAdd, cmdDel) + skel.PluginMain(cmdAdd, cmdDel, version.Legacy) } diff --git a/plugins/meta/tuning/tuning.go b/plugins/meta/tuning/tuning.go index 75ba852c..98e92ec9 100644 --- a/plugins/meta/tuning/tuning.go +++ b/plugins/meta/tuning/tuning.go @@ -27,6 +27,7 @@ import ( "github.com/containernetworking/cni/pkg/ns" "github.com/containernetworking/cni/pkg/skel" "github.com/containernetworking/cni/pkg/types" + "github.com/containernetworking/cni/pkg/version" ) // TuningConf represents the network tuning configuration. @@ -78,5 +79,5 @@ func cmdDel(args *skel.CmdArgs) error { } func main() { - skel.PluginMain(cmdAdd, cmdDel) + skel.PluginMain(cmdAdd, cmdDel, version.Legacy) } diff --git a/plugins/test/noop/main.go b/plugins/test/noop/main.go index ddb1acae..1ebc7350 100644 --- a/plugins/test/noop/main.go +++ b/plugins/test/noop/main.go @@ -28,6 +28,7 @@ import ( "strings" "github.com/containernetworking/cni/pkg/skel" + "github.com/containernetworking/cni/pkg/version" "github.com/containernetworking/cni/plugins/test/noop/debug" ) @@ -71,5 +72,6 @@ func cmdDel(args *skel.CmdArgs) error { } func main() { - skel.PluginMain(cmdAdd, cmdDel) + skel.PluginMain(cmdAdd, cmdDel, + version.PluginSupports("0.-42.0", "0.1.0", "0.2.0", "0.3.0")) } diff --git a/test b/test index afb1c94b..7537b40f 100755 --- a/test +++ b/test @@ -11,7 +11,7 @@ set -e source ./build -TESTABLE="libcni plugins/ipam/dhcp plugins/ipam/host-local plugins/main/loopback pkg/invoke pkg/ns pkg/skel pkg/types pkg/utils plugins/main/ipvlan plugins/main/macvlan plugins/main/bridge plugins/main/ptp plugins/test/noop pkg/utils/hwaddr pkg/ip" +TESTABLE="libcni plugins/ipam/dhcp plugins/ipam/host-local plugins/main/loopback pkg/invoke pkg/ns pkg/skel pkg/types pkg/utils plugins/main/ipvlan plugins/main/macvlan plugins/main/bridge plugins/main/ptp plugins/test/noop pkg/utils/hwaddr pkg/ip pkg/version" FORMATTABLE="$TESTABLE pkg/testutils plugins/meta/flannel plugins/meta/tuning" # user has not provided PKG override