versioning: plugins report a list of supported versions
Further progress on versioning support (Issue #266). Bump CNI spec version to 0.3.0
This commit is contained in:
@ -23,6 +23,7 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
||||||
"github.com/containernetworking/cni/pkg/types"
|
"github.com/containernetworking/cni/pkg/types"
|
||||||
|
"github.com/containernetworking/cni/pkg/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
func pluginErr(err error, output []byte) error {
|
func pluginErr(err error, output []byte) error {
|
||||||
@ -57,6 +58,15 @@ func ExecPluginWithoutResult(pluginPath string, netconf []byte, args CNIArgs) er
|
|||||||
return err
|
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) {
|
func execPlugin(pluginPath string, netconf []byte, args CNIArgs) ([]byte, error) {
|
||||||
return defaultRawExec.ExecPlugin(pluginPath, netconf, args.AsEnv())
|
return defaultRawExec.ExecPlugin(pluginPath, netconf, args.AsEnv())
|
||||||
}
|
}
|
||||||
|
26
skel/skel.go
26
skel/skel.go
@ -39,11 +39,10 @@ type CmdArgs struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type dispatcher struct {
|
type dispatcher struct {
|
||||||
Getenv func(string) string
|
Getenv func(string) string
|
||||||
Stdin io.Reader
|
Stdin io.Reader
|
||||||
Stdout io.Writer
|
Stdout io.Writer
|
||||||
Stderr io.Writer
|
Stderr io.Writer
|
||||||
Versioner version.PluginVersioner
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type reqForCmdEntry map[string]bool
|
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()
|
cmd, cmdArgs, err := t.getCmdArgsFromEnv()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return createTypedError(err.Error())
|
return createTypedError(err.Error())
|
||||||
@ -158,7 +157,7 @@ func (t *dispatcher) pluginMain(cmdAdd, cmdDel func(_ *CmdArgs) error) *types.Er
|
|||||||
err = cmdDel(cmdArgs)
|
err = cmdDel(cmdArgs)
|
||||||
|
|
||||||
case "VERSION":
|
case "VERSION":
|
||||||
err = t.Versioner.Encode(t.Stdout)
|
err = versionInfo.Encode(t.Stdout)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return createTypedError("unknown CNI_COMMAND: %v", cmd)
|
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
|
// PluginMain is the "main" for a plugin. It accepts
|
||||||
// two callback functions for add and del commands.
|
// 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{
|
caller := dispatcher{
|
||||||
Getenv: os.Getenv,
|
Getenv: os.Getenv,
|
||||||
Stdin: os.Stdin,
|
Stdin: os.Stdin,
|
||||||
Stdout: os.Stdout,
|
Stdout: os.Stdout,
|
||||||
Stderr: os.Stderr,
|
Stderr: os.Stderr,
|
||||||
Versioner: version.DefaultPluginVersioner,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err := caller.pluginMain(cmdAdd, cmdDel)
|
err := caller.pluginMain(cmdAdd, cmdDel, versionInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
dieErr(err)
|
dieErr(err)
|
||||||
}
|
}
|
||||||
|
@ -53,6 +53,7 @@ var _ = Describe("dispatching to the correct callback", func() {
|
|||||||
cmdAdd, cmdDel *fakeCmd
|
cmdAdd, cmdDel *fakeCmd
|
||||||
dispatch *dispatcher
|
dispatch *dispatcher
|
||||||
expectedCmdArgs *CmdArgs
|
expectedCmdArgs *CmdArgs
|
||||||
|
versionInfo version.PluginInfo
|
||||||
)
|
)
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
@ -67,13 +68,12 @@ var _ = Describe("dispatching to the correct callback", func() {
|
|||||||
stdin = strings.NewReader(`{ "some": "config" }`)
|
stdin = strings.NewReader(`{ "some": "config" }`)
|
||||||
stdout = &bytes.Buffer{}
|
stdout = &bytes.Buffer{}
|
||||||
stderr = &bytes.Buffer{}
|
stderr = &bytes.Buffer{}
|
||||||
versioner := &version.BasicVersioner{CNIVersion: "9.8.7"}
|
versionInfo = version.PluginSupports("9.8.7")
|
||||||
dispatch = &dispatcher{
|
dispatch = &dispatcher{
|
||||||
Getenv: func(key string) string { return environment[key] },
|
Getenv: func(key string) string { return environment[key] },
|
||||||
Stdin: stdin,
|
Stdin: stdin,
|
||||||
Stdout: stdout,
|
Stdout: stdout,
|
||||||
Stderr: stderr,
|
Stderr: stderr,
|
||||||
Versioner: versioner,
|
|
||||||
}
|
}
|
||||||
cmdAdd = &fakeCmd{}
|
cmdAdd = &fakeCmd{}
|
||||||
cmdDel = &fakeCmd{}
|
cmdDel = &fakeCmd{}
|
||||||
@ -90,7 +90,7 @@ var _ = Describe("dispatching to the correct callback", func() {
|
|||||||
var envVarChecker = func(envVar string, isRequired bool) {
|
var envVarChecker = func(envVar string, isRequired bool) {
|
||||||
delete(environment, envVar)
|
delete(environment, envVar)
|
||||||
|
|
||||||
err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func)
|
err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)
|
||||||
if isRequired {
|
if isRequired {
|
||||||
Expect(err).To(Equal(&types.Error{
|
Expect(err).To(Equal(&types.Error{
|
||||||
Code: 100,
|
Code: 100,
|
||||||
@ -104,7 +104,7 @@ var _ = Describe("dispatching to the correct callback", func() {
|
|||||||
|
|
||||||
Context("when the CNI_COMMAND is ADD", func() {
|
Context("when the CNI_COMMAND is ADD", func() {
|
||||||
It("extracts env vars and stdin data and calls cmdAdd", 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(err).NotTo(HaveOccurred())
|
||||||
Expect(cmdAdd.CallCount).To(Equal(1))
|
Expect(cmdAdd.CallCount).To(Equal(1))
|
||||||
@ -113,7 +113,7 @@ var _ = Describe("dispatching to the correct callback", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("does not call cmdDel", 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(err).NotTo(HaveOccurred())
|
||||||
Expect(cmdDel.CallCount).To(Equal(0))
|
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() {
|
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()
|
log := stderr.String()
|
||||||
Expect(log).To(ContainSubstring("CNI_NETNS env variable missing\n"))
|
Expect(log).To(ContainSubstring("CNI_NETNS env variable missing\n"))
|
||||||
Expect(log).To(ContainSubstring("CNI_IFNAME 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() {
|
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(err).NotTo(HaveOccurred())
|
||||||
Expect(cmdDel.CallCount).To(Equal(1))
|
Expect(cmdDel.CallCount).To(Equal(1))
|
||||||
@ -160,7 +160,7 @@ var _ = Describe("dispatching to the correct callback", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("does not call cmdAdd", 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(err).NotTo(HaveOccurred())
|
||||||
Expect(cmdAdd.CallCount).To(Equal(0))
|
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() {
|
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(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() {
|
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(err).NotTo(HaveOccurred())
|
||||||
Expect(cmdAdd.CallCount).To(Equal(0))
|
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() {
|
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(cmdAdd.CallCount).To(Equal(0))
|
||||||
Expect(cmdDel.CallCount).To(Equal(0))
|
Expect(cmdDel.CallCount).To(Equal(0))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("returns an error", func() {
|
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{
|
Expect(err).To(Equal(&types.Error{
|
||||||
Code: 100,
|
Code: 100,
|
||||||
@ -234,14 +237,14 @@ var _ = Describe("dispatching to the correct callback", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("does not call any cmd 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(cmdAdd.CallCount).To(Equal(0))
|
||||||
Expect(cmdDel.CallCount).To(Equal(0))
|
Expect(cmdDel.CallCount).To(Equal(0))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("wraps and returns the error", 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{
|
Expect(err).To(Equal(&types.Error{
|
||||||
Code: 100,
|
Code: 100,
|
||||||
@ -260,7 +263,7 @@ var _ = Describe("dispatching to the correct callback", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("returns the error as-is", 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{
|
Expect(err).To(Equal(&types.Error{
|
||||||
Code: 1234,
|
Code: 1234,
|
||||||
@ -275,7 +278,7 @@ var _ = Describe("dispatching to the correct callback", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("wraps and returns the error", 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{
|
Expect(err).To(Equal(&types.Error{
|
||||||
Code: 100,
|
Code: 100,
|
||||||
|
@ -16,27 +16,67 @@ package version
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A PluginVersioner can encode information about its version
|
// Current reports the version of the CNI spec implemented by this library
|
||||||
type PluginVersioner interface {
|
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
|
Encode(io.Writer) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// BasicVersioner is a PluginVersioner which reports a single cniVersion string
|
type simple struct {
|
||||||
type BasicVersioner struct {
|
CNIVersion_ string `json:"cniVersion"`
|
||||||
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)
|
return json.NewEncoder(w).Encode(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Current reports the version of the CNI spec implemented by this library
|
func (p *simple) SupportedVersions() []string {
|
||||||
func Current() string {
|
return p.SupportedVersions_
|
||||||
return "0.2.0"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultPluginVersioner reports the Current library spec version as the cniVersion
|
// PluginSupports returns a new PluginInfo that will report the given versions
|
||||||
var DefaultPluginVersioner = &BasicVersioner{CNIVersion: Current()}
|
// 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")
|
||||||
|
27
version/version_suite_test.go
Normal file
27
version/version_suite_test.go
Normal file
@ -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")
|
||||||
|
}
|
72
version/version_test.go
Normal file
72
version/version_test.go
Normal file
@ -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"))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
Reference in New Issue
Block a user