versioning: misc cleanups
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
This commit is contained in:
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
77
version/plugin.go
Normal file
77
version/plugin.go
Normal file
@ -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
|
||||
}
|
@ -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() {
|
@ -14,73 +14,11 @@
|
||||
|
||||
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
|
||||
|
Reference in New Issue
Block a user