versioning: misc cleanups
authorGabe Rosenhouse <rosenhouse@gmail.com>
Tue, 6 Sep 2016 15:22:27 +0000 (11:22 -0400)
committerGabe Rosenhouse <rosenhouse@gmail.com>
Tue, 6 Sep 2016 19:35:58 +0000 (15:35 -0400)
highlights:
 - NetConf struct finally includes cniVersion field
 - improve test coverage of current version report behavior
 - godoc a few key functions
 - allow tests to control version list reported by no-op plugin

invoke/exec.go
invoke/get_version_integration_test.go [moved from invoke/exec_integration_test.go with 78% similarity]
types/types.go
version/plugin.go [new file with mode: 0644]
version/plugin_test.go [moved from version/version_test.go with 94% similarity]
version/version.go

index 68efbb9..7eb0615 100644 (file)
@@ -36,7 +36,7 @@ func GetVersionInfo(pluginPath string) (version.PluginInfo, error) {
 
 var defaultPluginExec = &PluginExec{
        RawExec:        &RawExec{Stderr: os.Stderr},
-       VersionDecoder: &version.Decoder{},
+       VersionDecoder: &version.PluginDecoder{},
 }
 
 type PluginExec struct {
@@ -64,6 +64,10 @@ func (e *PluginExec) WithoutResult(pluginPath string, netconf []byte, args CNIAr
        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",
similarity index 78%
rename from invoke/exec_integration_test.go
rename to invoke/get_version_integration_test.go
index f02374c..d10826d 100644 (file)
@@ -54,9 +54,26 @@ var _ = Describe("GetVersion, integration tests", func() {
                },
                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
 
index 6948dcb..ba02580 100644 (file)
@@ -57,6 +57,8 @@ func (n *IPNet) UnmarshalJSON(data []byte) error {
 
 // NetConf describes a network.
 type NetConf struct {
+       CNIVersion string `json:"cniVersion,omitempty"`
+
        Name string `json:"name,omitempty"`
        Type string `json:"type,omitempty"`
        IPAM struct {
diff --git a/version/plugin.go b/version/plugin.go
new file mode 100644 (file)
index 0000000..9bd7dc8
--- /dev/null
@@ -0,0 +1,77 @@
+// 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
+}
similarity index 94%
rename from version/version_test.go
rename to version/plugin_test.go
index 98a386d..a58bd35 100644 (file)
@@ -20,11 +20,11 @@ import (
        . "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() {
index cdb531c..5f937f7 100644 (file)
 
 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