var defaultPluginExec = &PluginExec{
RawExec: &RawExec{Stderr: os.Stderr},
- VersionDecoder: &version.Decoder{},
+ VersionDecoder: &version.PluginDecoder{},
}
type PluginExec struct {
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",
},
Entry("old plugin, before VERSION was introduced", git_ref_v010, plugin_source_v010, version.PluginSupports("0.1.0")),
Entry("when VERSION was introduced", git_ref_v020, plugin_source_v010, version.PluginSupports("0.1.0", "0.2.0")),
+ Entry("when plugins report their own version support", git_ref_v030, plugin_source_v030, version.PluginSupports("0.3.0", "0.999.0")),
+ Entry("HEAD", "HEAD", plugin_source_v030, version.PluginSupports("0.3.0", "0.999.0")),
)
})
+// a 0.3.0 plugin that can report its own versions
+const plugin_source_v030 = `package main
+
+import (
+ "github.com/containernetworking/cni/pkg/skel"
+ "github.com/containernetworking/cni/pkg/version"
+ "fmt"
+)
+
+func c(_ *skel.CmdArgs) error { fmt.Println("{}"); return nil }
+
+func main() { skel.PluginMain(c, c, version.PluginSupports("0.3.0", "0.999.0")) }
+`
+const git_ref_v030 = "bf31ed15"
+
// a minimal 0.1.0 / 0.2.0 plugin
const plugin_source_v010 = `package main
// NetConf describes a network.
type NetConf struct {
+ CNIVersion string `json:"cniVersion,omitempty"`
+
Name string `json:"name,omitempty"`
Type string `json:"type,omitempty"`
IPAM struct {
--- /dev/null
+// 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"`
+}
+
+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,
+ }
+}
+
+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
+}
. "github.com/onsi/gomega"
)
-var _ = Describe("Decode", func() {
- var decoder *version.Decoder
+var _ = Describe("Decoding versions reported by a plugin", func() {
+ var decoder *version.PluginDecoder
BeforeEach(func() {
- decoder = &version.Decoder{}
+ decoder = &version.PluginDecoder{}
})
It("returns a PluginInfo that represents the given json bytes", func() {
package version
-import (
- "encoding/json"
- "fmt"
- "io"
-)
-
// 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
-}
-
-type simple struct {
- CNIVersion_ string `json:"cniVersion"`
- SupportedVersions_ []string `json:"supportedVersions,omitempty"`
-}
-
-func (p *simple) Encode(w io.Writer) error {
- return json.NewEncoder(w).Encode(p)
-}
-
-func (p *simple) 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 &simple{
- CNIVersion_: Current(),
- SupportedVersions_: supportedVersions,
- }
-}
-
-type Decoder struct{}
-
-func (_ *Decoder) 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
-}
-
// 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