Skip to content

Commit

Permalink
libcni: add version v1.1.0
Browse files Browse the repository at this point in the history
This adds support for CNI spec v1.1.0. Since there are no result type
changes expected, this means that we can use the existing v1.0.0 types.
That takes a bit of plumbing to decouple the type from the version.

Signed-off-by: Casey Callendrello <c1@caseyc.net>
  • Loading branch information
squeed committed Jul 13, 2023
1 parent c768dcb commit a899051
Show file tree
Hide file tree
Showing 8 changed files with 76 additions and 41 deletions.
31 changes: 16 additions & 15 deletions libcni/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
"github.com/containernetworking/cni/pkg/skel"
"github.com/containernetworking/cni/pkg/types"
current "github.com/containernetworking/cni/pkg/types/100"
"github.com/containernetworking/cni/pkg/version"
noop_debug "github.com/containernetworking/cni/plugins/test/noop/debug"
)

Expand Down Expand Up @@ -179,7 +180,7 @@ var _ = Describe("Invoking plugins", func() {

debug = &noop_debug.Debug{
ReportResult: `{
"cniVersion": "1.0.0",
"cniVersion": "` + version.Current() + `",
"ips": [{"address": "10.1.2.3/24"}],
"dns": {}
}`,
Expand All @@ -195,7 +196,7 @@ var _ = Describe("Invoking plugins", func() {
"somethingElse": true,
"noCapability": false
}
}`, current.ImplementedSpecVersion))
}`, version.Current()))
netConfig, err = libcni.ConfFromBytes(pluginConfig)
Expect(err).NotTo(HaveOccurred())

Expand Down Expand Up @@ -301,7 +302,7 @@ var _ = Describe("Invoking plugins", func() {

debug = &noop_debug.Debug{
ReportResult: `{
"cniVersion": "1.0.0",
"cniVersion": "` + version.Current() + `",
"ips": [{"address": "10.1.2.3/24"}],
"dns": {}
}`,
Expand All @@ -319,7 +320,7 @@ var _ = Describe("Invoking plugins", func() {
"some-key": "some-value",
"cniVersion": "%s",
"capabilities": { "portMappings": true }
}`, current.ImplementedSpecVersion)
}`, version.Current())
cniConfig = libcni.NewCNIConfigWithCacheDir([]string{cniBinPath}, cacheDirPath, nil)
netConfig, err = libcni.ConfFromBytes([]byte(pluginConfig))
Expect(err).NotTo(HaveOccurred())
Expand Down Expand Up @@ -476,7 +477,7 @@ var _ = Describe("Invoking plugins", func() {
err := os.MkdirAll(filepath.Dir(cacheFile), 0o700)
Expect(err).NotTo(HaveOccurred())
cachedJson := `{
"cniVersion": "1.0.0",
"cniVersion": "` + version.Current() + `",
"ips": [{"address": "10.1.2.3/24"}],
"dns": {}
}`
Expand Down Expand Up @@ -561,7 +562,7 @@ var _ = Describe("Invoking plugins", func() {
Context("containing only a cached result", func() {
It("only passes a prevResult to the plugin", func() {
err := os.WriteFile(cacheFile, []byte(`{
"cniVersion": "1.0.0",
"cniVersion": "`+version.Current()+`",
"ips": [{"address": "10.1.2.3/24"}],
"dns": {}
}`), 0o600)
Expand Down Expand Up @@ -666,7 +667,7 @@ var _ = Describe("Invoking plugins", func() {
err := os.MkdirAll(filepath.Dir(cacheFile), 0o700)
Expect(err).NotTo(HaveOccurred())
cachedJson := `{
"cniVersion": "1.0.0",
"cniVersion": "` + version.Current() + `",
"ips": [{"address": "10.1.2.3/24"}],
"dns": {}
}`
Expand Down Expand Up @@ -874,7 +875,7 @@ var _ = Describe("Invoking plugins", func() {

Expect(versionInfo).NotTo(BeNil())
Expect(versionInfo.SupportedVersions()).To(Equal([]string{
"0.-42.0", "0.1.0", "0.2.0", "0.3.0", "0.3.1", "0.4.0", "1.0.0",
"0.-42.0", "0.1.0", "0.2.0", "0.3.0", "0.3.1", "0.4.0", "1.0.0", "1.1.0",
}))
})

Expand Down Expand Up @@ -962,8 +963,8 @@ var _ = Describe("Invoking plugins", func() {
"otherCapability": capabilityArgs["otherCapability"],
}

ipResult = fmt.Sprintf(`{"cniVersion": "%s", "dns":{},"ips":[{"address": "10.1.2.3/24"}]}`, current.ImplementedSpecVersion)
netConfigList, plugins = makePluginList(current.ImplementedSpecVersion, ipResult, rcMap)
ipResult = fmt.Sprintf(`{"cniVersion": "%s", "dns":{},"ips":[{"address": "10.1.2.3/24"}]}`, version.Current())
netConfigList, plugins = makePluginList(version.Current(), ipResult, rcMap)

ctx = context.TODO()
})
Expand Down Expand Up @@ -1533,7 +1534,7 @@ var _ = Describe("Invoking plugins", func() {
"some-key": "some-value",
"cniVersion": "%s",
"capabilities": { "portMappings": true }
}`, current.ImplementedSpecVersion)
}`, version.Current())

cniBinPath = filepath.Dir(pluginPaths["sleep"])
cniConfig = libcni.NewCNIConfig([]string{cniBinPath}, nil)
Expand All @@ -1560,7 +1561,7 @@ var _ = Describe("Invoking plugins", func() {
"plugins": [
%s
]
}`, current.ImplementedSpecVersion, pluginConfig))
}`, version.Current(), pluginConfig))

netConfigList, err = libcni.ConfListFromBytes(configList)
Expect(err).NotTo(HaveOccurred())
Expand Down Expand Up @@ -1703,7 +1704,7 @@ var _ = Describe("Invoking plugins", func() {
ReportResult: fmt.Sprintf(`{
"cniVersion": "%s",
"ips": [{"version": "4", "address": "%s"}]
}`, current.ImplementedSpecVersion, firstIP),
}`, version.Current(), firstIP),
}
Expect(debug.WriteDebug(debugFilePath)).To(Succeed())

Expand All @@ -1712,7 +1713,7 @@ var _ = Describe("Invoking plugins", func() {
"type": "noop",
"name": "%s",
"cniVersion": "%s"
}`, netName, current.ImplementedSpecVersion)
}`, netName, version.Current())
cniConfig = libcni.NewCNIConfigWithCacheDir([]string{cniBinPath}, cacheDirPath, nil)
netConfig, err = libcni.ConfFromBytes([]byte(pluginConfig))
Expect(err).NotTo(HaveOccurred())
Expand All @@ -1736,7 +1737,7 @@ var _ = Describe("Invoking plugins", func() {
debug.ReportResult = fmt.Sprintf(`{
"cniVersion": "%s",
"ips": [{"version": "4", "address": "%s"}]
}`, current.ImplementedSpecVersion, secondIP)
}`, version.Current(), secondIP)
Expect(debug.WriteDebug(debugFilePath)).To(Succeed())
runtimeConfig.IfName = secondIfname
_, err = cniConfig.AddNetwork(ctx, netConfig, runtimeConfig)
Expand Down
3 changes: 2 additions & 1 deletion pkg/invoke/delegate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (

"github.com/containernetworking/cni/pkg/invoke"
current "github.com/containernetworking/cni/pkg/types/100"
"github.com/containernetworking/cni/pkg/version"
"github.com/containernetworking/cni/plugins/test/noop/debug"
)

Expand All @@ -42,7 +43,7 @@ var _ = Describe("Delegate", func() {
BeforeEach(func() {
netConf, _ = json.Marshal(map[string]string{
"name": "delegate-test",
"cniVersion": current.ImplementedSpecVersion,
"cniVersion": version.Current(),
})

expectedResult = &current.Result{
Expand Down
5 changes: 2 additions & 3 deletions pkg/skel/skel_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import (
. "github.com/onsi/gomega"

"github.com/containernetworking/cni/pkg/types"
current "github.com/containernetworking/cni/pkg/types/100"
"github.com/containernetworking/cni/pkg/version"
)

Expand Down Expand Up @@ -430,7 +429,7 @@ var _ = Describe("dispatching to the correct callback", func() {
Expect(stdout).To(MatchJSON(fmt.Sprintf(`{
"cniVersion": "%s",
"supportedVersions": ["9.8.7", "10.0.0"]
}`, current.ImplementedSpecVersion)))
}`, version.Current())))
})

It("does not call cmdAdd or cmdDel", func() {
Expand Down Expand Up @@ -461,7 +460,7 @@ var _ = Describe("dispatching to the correct callback", func() {
Expect(stdout).To(MatchJSON(fmt.Sprintf(`{
"cniVersion": "%s",
"supportedVersions": ["9.8.7", "10.0.0"]
}`, current.ImplementedSpecVersion)))
}`, version.Current())))
})
})

Expand Down
25 changes: 22 additions & 3 deletions pkg/types/100/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ import (
convert "github.com/containernetworking/cni/pkg/types/internal"
)

const ImplementedSpecVersion string = "1.0.0"
// The types did not change between v1.0 and v1.1
const ImplementedSpecVersion string = "1.1.0"

var supportedVersions = []string{ImplementedSpecVersion}
var supportedVersions = []string{"1.0.0", "1.1.0"}

// Register converters for all versions less than the implemented spec version
func init() {
Expand All @@ -38,10 +39,14 @@ func init() {
convert.RegisterConverter("0.3.0", supportedVersions, convertFrom04x)
convert.RegisterConverter("0.3.1", supportedVersions, convertFrom04x)
convert.RegisterConverter("0.4.0", supportedVersions, convertFrom04x)
convert.RegisterConverter("1.0.0", []string{"1.1.0"}, convertFrom100)

// Down-converters
convert.RegisterConverter("1.0.0", []string{"0.3.0", "0.3.1", "0.4.0"}, convertTo04x)
convert.RegisterConverter("1.0.0", []string{"0.1.0", "0.2.0"}, convertTo02x)
convert.RegisterConverter("1.1.0", []string{"0.3.0", "0.3.1", "0.4.0"}, convertTo04x)
convert.RegisterConverter("1.1.0", []string{"0.1.0", "0.2.0"}, convertTo02x)
convert.RegisterConverter("1.1.0", []string{"1.0.0"}, convertFrom100)

// Creator
convert.RegisterCreator(supportedVersions, NewResult)
Expand Down Expand Up @@ -90,12 +95,26 @@ type Result struct {
DNS types.DNS `json:"dns,omitempty"`
}

// convertFrom100 does nothing except set the version; the types are the same
func convertFrom100(from types.Result, toVersion string) (types.Result, error) {
fromResult := from.(*Result)

result := &Result{
CNIVersion: toVersion,
Interfaces: fromResult.Interfaces,
IPs: fromResult.IPs,
Routes: fromResult.Routes,
DNS: fromResult.DNS,
}
return result, nil
}

func convertFrom02x(from types.Result, toVersion string) (types.Result, error) {
result040, err := convert.Convert(from, "0.4.0")
if err != nil {
return nil, err
}
result100, err := convertFrom04x(result040, ImplementedSpecVersion)
result100, err := convertFrom04x(result040, toVersion)
if err != nil {
return nil, err
}
Expand Down
22 changes: 19 additions & 3 deletions pkg/types/100/types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func testResult() *current.Result {

// Set every field of the struct to ensure source compatibility
return &current.Result{
CNIVersion: "1.0.0",
CNIVersion: current.ImplementedSpecVersion,
Interfaces: []*current.Interface{
{
Name: "eth0",
Expand Down Expand Up @@ -82,7 +82,7 @@ func testResult() *current.Result {
}

var _ = Describe("Current types operations", func() {
It("correctly encodes a 1.0.0 Result", func() {
It("correctly encodes a 1.1.0 Result", func() {
res := testResult()

// Redirect stdout to capture JSON result
Expand All @@ -101,7 +101,7 @@ var _ = Describe("Current types operations", func() {
Expect(err).NotTo(HaveOccurred())

Expect(string(out)).To(MatchJSON(`{
"cniVersion": "1.0.0",
"cniVersion": "` + current.ImplementedSpecVersion + `",
"interfaces": [
{
"name": "eth0",
Expand Down Expand Up @@ -149,6 +149,22 @@ var _ = Describe("Current types operations", func() {
}`))
})

It("correctly converts a 1.0.0 Result to 1.1.0", func() {
tr, err := testResult().GetAsVersion("1.0.0")
Expect(err).NotTo(HaveOccurred())

trv1, ok := tr.(*current.Result)
Expect(ok).To(BeTrue())

// 1.0.0 and 1.1.0 should be the same except for CNI version
Expect(trv1.CNIVersion).To(Equal("1.0.0"))

// If we convert 1.0.0 back to 1.1.0 it should be identical
trv11, err := trv1.GetAsVersion("1.1.0")
Expect(err).NotTo(HaveOccurred())
Expect(trv11).To(Equal(testResult()))
})

It("correctly encodes a 0.1.0 Result", func() {
res, err := testResult().GetAsVersion("0.1.0")
Expect(err).NotTo(HaveOccurred())
Expand Down
5 changes: 2 additions & 3 deletions pkg/version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,12 @@ import (
"fmt"

"github.com/containernetworking/cni/pkg/types"
types100 "github.com/containernetworking/cni/pkg/types/100"
"github.com/containernetworking/cni/pkg/types/create"
)

// Current reports the version of the CNI spec implemented by this library
func Current() string {
return types100.ImplementedSpecVersion
return "1.1.0"
}

// Legacy PluginInfo describes a plugin that is backwards compatible with the
Expand All @@ -37,7 +36,7 @@ func Current() string {
// this list.
var (
Legacy = PluginSupports("0.1.0", "0.2.0")
All = PluginSupports("0.1.0", "0.2.0", "0.3.0", "0.3.1", "0.4.0", "1.0.0")
All = PluginSupports("0.1.0", "0.2.0", "0.3.0", "0.3.1", "0.4.0", "1.0.0", "1.1.0")
)

// VersionsFrom returns a list of versions starting from min, inclusive
Expand Down
24 changes: 12 additions & 12 deletions pkg/version/version_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ import (
. "github.com/onsi/gomega"

"github.com/containernetworking/cni/pkg/types"
current "github.com/containernetworking/cni/pkg/types/100"
cniv1 "github.com/containernetworking/cni/pkg/types/100"
"github.com/containernetworking/cni/pkg/version"
)

var _ = Describe("Version operations", func() {
It("computes a list of versions correctly", func() {
actual := version.VersionsStartingFrom("0.3.1")
Expect(actual.SupportedVersions()).To(Equal([]string{"0.3.1", "0.4.0", "1.0.0"}))
Expect(actual.SupportedVersions()).To(Equal([]string{"0.3.1", "0.4.0", "1.0.0", "1.1.0"}))
})

Context("when a prevResult is available", func() {
Expand Down Expand Up @@ -67,18 +67,18 @@ var _ = Describe("Version operations", func() {
err = version.ParsePrevResult(conf)
Expect(err).NotTo(HaveOccurred())

expectedResult := &current.Result{
CNIVersion: current.ImplementedSpecVersion,
Interfaces: []*current.Interface{
expectedResult := &cniv1.Result{
CNIVersion: "1.0.0",
Interfaces: []*cniv1.Interface{
{
Name: "eth0",
Mac: "00:11:22:33:44:55",
Sandbox: "/proc/3553/ns/net",
},
},
IPs: []*current.IPConfig{
IPs: []*cniv1.IPConfig{
{
Interface: current.Int(0),
Interface: cniv1.Int(0),
Address: net.IPNet{
IP: net.ParseIP("1.2.3.30"),
Mask: net.IPv4Mask(255, 255, 255, 0),
Expand All @@ -92,7 +92,7 @@ var _ = Describe("Version operations", func() {

It("fails if the prevResult version is unknown", func() {
conf := &types.NetConf{
CNIVersion: current.ImplementedSpecVersion,
CNIVersion: version.Current(),
Name: "foobar",
Type: "baz",
RawPrevResult: map[string]interface{}{
Expand All @@ -101,12 +101,12 @@ var _ = Describe("Version operations", func() {
}

err := version.ParsePrevResult(conf)
Expect(err).To(MatchError("could not parse prevResult: result type supports [1.0.0] but unmarshalled CNIVersion is \"5678.456\""))
Expect(err).To(MatchError(`could not parse prevResult: result type supports [1.0.0 1.1.0] but unmarshalled CNIVersion is "5678.456"`))
})

It("fails if the prevResult version does not match the prevResult version", func() {
conf := &types.NetConf{
CNIVersion: current.ImplementedSpecVersion,
CNIVersion: version.Current(),
Name: "foobar",
Type: "baz",
RawPrevResult: map[string]interface{}{
Expand All @@ -119,14 +119,14 @@ var _ = Describe("Version operations", func() {
}

err := version.ParsePrevResult(conf)
Expect(err).To(MatchError("could not parse prevResult: result type supports [1.0.0] but unmarshalled CNIVersion is \"0.2.0\""))
Expect(err).To(MatchError("could not parse prevResult: result type supports [1.0.0 1.1.0] but unmarshalled CNIVersion is \"0.2.0\""))
})
})

Context("when a prevResult is not available", func() {
It("does not fail", func() {
conf := &types.NetConf{
CNIVersion: current.ImplementedSpecVersion,
CNIVersion: version.Current(),
Name: "foobar",
Type: "baz",
}
Expand Down
2 changes: 1 addition & 1 deletion plugins/test/noop/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ func debugBehavior(args *skel.CmdArgs, command string) error {
}

func debugGetSupportedVersions(stdinData []byte) []string {
vers := []string{"0.-42.0", "0.1.0", "0.2.0", "0.3.0", "0.3.1", "0.4.0", "1.0.0"}
vers := []string{"0.-42.0", "0.1.0", "0.2.0", "0.3.0", "0.3.1", "0.4.0", "1.0.0", "1.1.0"}
cniArgs := os.Getenv("CNI_ARGS")
if cniArgs == "" {
return vers
Expand Down

0 comments on commit a899051

Please sign in to comment.