Upgrade containerd to 1.6.2 and CNI to 0.9.1

Upgrades containerd, and switches to the official 64-bit ARM
binary.

Continues to use my binary for 32-bit arm hosts.

CNI upgraded to v0.9.1

Signed-off-by: Alex Ellis (OpenFaaS Ltd) <alexellis2@gmail.com>
This commit is contained in:
Alex Ellis (OpenFaaS Ltd)
2022-04-10 18:23:34 +01:00
committed by Alex Ellis
parent 449bcf2691
commit 912ac265f4
614 changed files with 21609 additions and 16284 deletions

View File

@ -2,7 +2,7 @@
[![PkgGoDev](https://pkg.go.dev/badge/github.com/containerd/go-cni)](https://pkg.go.dev/github.com/containerd/go-cni)
[![Build Status](https://github.com/containerd/go-cni/workflows/CI/badge.svg)](https://github.com/containerd/go-cni/actions?query=workflow%3ACI)
[![codecov](https://codecov.io/gh/containerd/go-cni/branch/master/graph/badge.svg)](https://codecov.io/gh/containerd/go-cni)
[![codecov](https://codecov.io/gh/containerd/go-cni/branch/main/graph/badge.svg)](https://codecov.io/gh/containerd/go-cni)
[![Go Report Card](https://goreportcard.com/badge/github.com/containerd/go-cni)](https://goreportcard.com/report/github.com/containerd/go-cni)
A generic CNI library to provide APIs for CNI plugin interactions. The library provides APIs to:
@ -11,6 +11,7 @@ A generic CNI library to provide APIs for CNI plugin interactions. The library p
- Setup networks for container namespace
- Remove networks from container namespace
- Query status of CNI network plugin initialization
- Check verifies the network is still in desired state
go-cni aims to support plugins that implement [Container Network Interface](https://github.com/containernetworking/cni)
@ -88,8 +89,8 @@ func main() {
The go-cni is a containerd sub-project, licensed under the [Apache 2.0 license](./LICENSE).
As a containerd sub-project, you will find the:
* [Project governance](https://github.com/containerd/project/blob/master/GOVERNANCE.md),
* [Maintainers](https://github.com/containerd/project/blob/master/MAINTAINERS),
* and [Contributing guidelines](https://github.com/containerd/project/blob/master/CONTRIBUTING.md)
* [Project governance](https://github.com/containerd/project/blob/main/GOVERNANCE.md),
* [Maintainers](https://github.com/containerd/project/blob/main/MAINTAINERS),
* and [Contributing guidelines](https://github.com/containerd/project/blob/main/CONTRIBUTING.md)
information in our [`containerd/project`](https://github.com/containerd/project) repository.

View File

@ -19,13 +19,15 @@ package cni
import (
"context"
"fmt"
"os"
"strings"
"sync"
cnilibrary "github.com/containernetworking/cni/libcni"
"github.com/containernetworking/cni/pkg/invoke"
"github.com/containernetworking/cni/pkg/types"
"github.com/containernetworking/cni/pkg/types/current"
"github.com/pkg/errors"
types100 "github.com/containernetworking/cni/pkg/types/100"
"github.com/containernetworking/cni/pkg/version"
)
type CNI interface {
@ -33,6 +35,8 @@ type CNI interface {
Setup(ctx context.Context, id string, path string, opts ...NamespaceOpts) (*Result, error)
// Remove tears down the network of the namespace.
Remove(ctx context.Context, id string, path string, opts ...NamespaceOpts) error
// Check checks if the network is still in desired state
Check(ctx context.Context, id string, path string, opts ...NamespaceOpts) error
// Load loads the cni network config
Load(opts ...Opt) error
// Status checks the status of the cni initialization
@ -85,9 +89,15 @@ func defaultCNIConfig() *libcni {
pluginMaxConfNum: DefaultMaxConfNum,
prefix: DefaultPrefix,
},
cniConfig: &cnilibrary.CNIConfig{
Path: []string{DefaultCNIDir},
},
cniConfig: cnilibrary.NewCNIConfig(
[]string{
DefaultCNIDir,
},
&invoke.DefaultExec{
RawExec: &invoke.RawExec{Stderr: os.Stderr},
PluginDecoder: version.PluginDecoder{},
},
),
networkCount: 1,
}
}
@ -115,7 +125,7 @@ func (c *libcni) Load(opts ...Opt) error {
for _, o := range opts {
if err = o(c); err != nil {
return errors.Wrapf(ErrLoad, fmt.Sprintf("cni config load failed: %v", err))
return fmt.Errorf("cni config load failed: %v: %w", err, ErrLoad)
}
}
return nil
@ -155,16 +165,39 @@ func (c *libcni) Setup(ctx context.Context, id string, path string, opts ...Name
return c.createResult(result)
}
func (c *libcni) attachNetworks(ctx context.Context, ns *Namespace) ([]*current.Result, error) {
var results []*current.Result
for _, network := range c.Networks() {
r, err := network.Attach(ctx, ns)
if err != nil {
return nil, err
}
results = append(results, r)
type asynchAttachResult struct {
index int
res *types100.Result
err error
}
func asynchAttach(ctx context.Context, index int, n *Network, ns *Namespace, wg *sync.WaitGroup, rc chan asynchAttachResult) {
defer wg.Done()
r, err := n.Attach(ctx, ns)
rc <- asynchAttachResult{index: index, res: r, err: err}
}
func (c *libcni) attachNetworks(ctx context.Context, ns *Namespace) ([]*types100.Result, error) {
var wg sync.WaitGroup
var firstError error
results := make([]*types100.Result, len(c.Networks()))
rc := make(chan asynchAttachResult)
for i, network := range c.Networks() {
wg.Add(1)
go asynchAttach(ctx, i, network, ns, &wg, rc)
}
return results, nil
for range c.Networks() {
rs := <-rc
if rs.err != nil && firstError == nil {
firstError = rs.err
}
results[rs.index] = rs.res
}
wg.Wait()
return results, firstError
}
// Remove removes the network config from the namespace
@ -184,7 +217,9 @@ func (c *libcni) Remove(ctx context.Context, id string, path string, opts ...Nam
// https://github.com/containernetworking/plugins/issues/210
// TODO(random-liu): Remove the error handling when the issue is
// fixed and the CNI spec v0.6.0 support is deprecated.
if path == "" && strings.Contains(err.Error(), "no such file or directory") {
// NOTE(claudiub): Some CNIs could return a "not found" error, which could mean that
// it was already deleted.
if (path == "" && strings.Contains(err.Error(), "no such file or directory")) || strings.Contains(err.Error(), "not found") {
continue
}
return err
@ -193,6 +228,25 @@ func (c *libcni) Remove(ctx context.Context, id string, path string, opts ...Nam
return nil
}
// Check checks if the network is still in desired state
func (c *libcni) Check(ctx context.Context, id string, path string, opts ...NamespaceOpts) error {
if err := c.Status(); err != nil {
return err
}
ns, err := newNamespace(id, path, opts...)
if err != nil {
return err
}
for _, network := range c.Networks() {
err := network.Check(ctx, ns)
if err != nil {
return err
}
}
return nil
}
// GetConfig returns a copy of the CNI plugin configurations as parsed by CNI
func (c *libcni) GetConfig() *ConfigResult {
c.RLock()

View File

@ -16,7 +16,7 @@
package cni
import "github.com/containernetworking/cni/pkg/types/current"
import types100 "github.com/containernetworking/cni/pkg/types/100"
// Deprecated: use cni.Opt instead
type CNIOpt = Opt //nolint: golint // type name will be used as cni.CNIOpt by other packages, and that stutters
@ -24,11 +24,11 @@ type CNIOpt = Opt //nolint: golint // type name will be used as cni.CNIOpt by ot
// Deprecated: use cni.Result instead
type CNIResult = Result //nolint: golint // type name will be used as cni.CNIResult by other packages, and that stutters
// GetCNIResultFromResults creates a Result from the given slice of current.Result,
// GetCNIResultFromResults creates a Result from the given slice of types100.Result,
// adding structured data containing the interface configuration for each of the
// interfaces created in the namespace. It returns an error if validation of
// results fails, or if a network could not be found.
// Deprecated: do not use
func (c *libcni) GetCNIResultFromResults(results []*current.Result) (*Result, error) {
func (c *libcni) GetCNIResultFromResults(results []*types100.Result) (*Result, error) {
return c.createResult(results)
}

View File

@ -17,7 +17,7 @@
package cni
import (
"github.com/pkg/errors"
"errors"
)
var (

View File

@ -1,12 +0,0 @@
module github.com/containerd/go-cni
require (
github.com/containernetworking/cni v0.8.0
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/onsi/ginkgo v1.10.3 // indirect
github.com/onsi/gomega v1.7.1 // indirect
github.com/pkg/errors v0.9.1
github.com/stretchr/testify v1.6.1
)
go 1.13

View File

@ -1,42 +0,0 @@
github.com/containernetworking/cni v0.8.0 h1:BT9lpgGoH4jw3lFC7Odz2prU5ruiYKcgAjMCbgybcKI=
github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.3 h1:OoxbjfXVZyod1fmWYhI7SEyaD8B00ynP3T+D5GiyHOY=
github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -19,10 +19,10 @@ package cni
import (
"fmt"
"github.com/containernetworking/cni/pkg/types/current"
types100 "github.com/containernetworking/cni/pkg/types/100"
)
func validateInterfaceConfig(ipConf *current.IPConfig, ifs int) error {
func validateInterfaceConfig(ipConf *types100.IPConfig, ifs int) error {
if ipConf == nil {
return fmt.Errorf("invalid IP configuration (nil)")
}

View File

@ -20,7 +20,7 @@ import (
"context"
cnilibrary "github.com/containernetworking/cni/libcni"
"github.com/containernetworking/cni/pkg/types/current"
types100 "github.com/containernetworking/cni/pkg/types/100"
)
type Network struct {
@ -29,18 +29,22 @@ type Network struct {
ifName string
}
func (n *Network) Attach(ctx context.Context, ns *Namespace) (*current.Result, error) {
func (n *Network) Attach(ctx context.Context, ns *Namespace) (*types100.Result, error) {
r, err := n.cni.AddNetworkList(ctx, n.config, ns.config(n.ifName))
if err != nil {
return nil, err
}
return current.NewResultFromResult(r)
return types100.NewResultFromResult(r)
}
func (n *Network) Remove(ctx context.Context, ns *Namespace) error {
return n.cni.DelNetworkList(ctx, n.config, ns.config(n.ifName))
}
func (n *Network) Check(ctx context.Context, ns *Namespace) error {
return n.cni.CheckNetworkList(ctx, n.config, ns.config(n.ifName))
}
type Namespace struct {
id string
path string

View File

@ -17,11 +17,14 @@
package cni
import (
"fmt"
"os"
"sort"
"strings"
cnilibrary "github.com/containernetworking/cni/libcni"
"github.com/pkg/errors"
"github.com/containernetworking/cni/pkg/invoke"
"github.com/containernetworking/cni/pkg/version"
)
// Opt sets options for a CNI instance
@ -41,7 +44,13 @@ func WithInterfacePrefix(prefix string) Opt {
func WithPluginDir(dirs []string) Opt {
return func(c *libcni) error {
c.pluginDirs = dirs
c.cniConfig = &cnilibrary.CNIConfig{Path: dirs}
c.cniConfig = cnilibrary.NewCNIConfig(
dirs,
&invoke.DefaultExec{
RawExec: &invoke.RawExec{Stderr: os.Stderr},
PluginDecoder: version.PluginDecoder{},
},
)
return nil
}
}
@ -204,9 +213,9 @@ func loadFromConfDir(c *libcni, max int) error {
files, err := cnilibrary.ConfFiles(c.pluginConfDir, []string{".conf", ".conflist", ".json"})
switch {
case err != nil:
return errors.Wrapf(ErrRead, "failed to read config file: %v", err)
return fmt.Errorf("failed to read config file: %v: %w", err, ErrRead)
case len(files) == 0:
return errors.Wrapf(ErrCNINotInitialized, "no network config found in %s", c.pluginConfDir)
return fmt.Errorf("no network config found in %s: %w", c.pluginConfDir, ErrCNINotInitialized)
}
// files contains the network config files associated with cni network.
@ -224,26 +233,26 @@ func loadFromConfDir(c *libcni, max int) error {
if strings.HasSuffix(confFile, ".conflist") {
confList, err = cnilibrary.ConfListFromFile(confFile)
if err != nil {
return errors.Wrapf(ErrInvalidConfig, "failed to load CNI config list file %s: %v", confFile, err)
return fmt.Errorf("failed to load CNI config list file %s: %v: %w", confFile, err, ErrInvalidConfig)
}
} else {
conf, err := cnilibrary.ConfFromFile(confFile)
if err != nil {
return errors.Wrapf(ErrInvalidConfig, "failed to load CNI config file %s: %v", confFile, err)
return fmt.Errorf("failed to load CNI config file %s: %v: %w", confFile, err, ErrInvalidConfig)
}
// Ensure the config has a "type" so we know what plugin to run.
// Also catches the case where somebody put a conflist into a conf file.
if conf.Network.Type == "" {
return errors.Wrapf(ErrInvalidConfig, "network type not found in %s", confFile)
return fmt.Errorf("network type not found in %s: %w", confFile, ErrInvalidConfig)
}
confList, err = cnilibrary.ConfListFromConf(conf)
if err != nil {
return errors.Wrapf(ErrInvalidConfig, "failed to convert CNI config file %s to CNI config list: %v", confFile, err)
return fmt.Errorf("failed to convert CNI config file %s to CNI config list: %v: %w", confFile, err, ErrInvalidConfig)
}
}
if len(confList.Plugins) == 0 {
return errors.Wrapf(ErrInvalidConfig, "CNI config list in config file %s has no networks, skipping", confFile)
return fmt.Errorf("CNI config list in config file %s has no networks, skipping: %w", confFile, ErrInvalidConfig)
}
networks = append(networks, &Network{
@ -257,7 +266,7 @@ func loadFromConfDir(c *libcni, max int) error {
}
}
if len(networks) == 0 {
return errors.Wrapf(ErrCNINotInitialized, "no valid networks found in %s", c.pluginDirs)
return fmt.Errorf("no valid networks found in %s: %w", c.pluginDirs, ErrCNINotInitialized)
}
c.networks = append(c.networks, networks...)
return nil

View File

@ -17,11 +17,11 @@
package cni
import (
"fmt"
"net"
"github.com/containernetworking/cni/pkg/types"
"github.com/containernetworking/cni/pkg/types/current"
"github.com/pkg/errors"
types100 "github.com/containernetworking/cni/pkg/types/100"
)
type IPConfig struct {
@ -43,6 +43,12 @@ type Result struct {
Interfaces map[string]*Config
DNS []types.DNS
Routes []*types.Route
raw []*types100.Result
}
// Raw returns the raw CNI results of multiple networks.
func (r *Result) Raw() []*types100.Result {
return r.raw
}
type Config struct {
@ -51,15 +57,16 @@ type Config struct {
Sandbox string
}
// createResult creates a Result from the given slice of current.Result, adding
// createResult creates a Result from the given slice of types100.Result, adding
// structured data containing the interface configuration for each of the
// interfaces created in the namespace. It returns an error if validation of
// results fails, or if a network could not be found.
func (c *libcni) createResult(results []*current.Result) (*Result, error) {
func (c *libcni) createResult(results []*types100.Result) (*Result, error) {
c.RLock()
defer c.RUnlock()
r := &Result{
Interfaces: make(map[string]*Config),
raw: results,
}
// Plugins may not need to return Interfaces in result if
@ -80,7 +87,7 @@ func (c *libcni) createResult(results []*current.Result) (*Result, error) {
// interfaces
for _, ipConf := range result.IPs {
if err := validateInterfaceConfig(ipConf, len(result.Interfaces)); err != nil {
return nil, errors.Wrapf(ErrInvalidResult, "invalid interface config: %v", err)
return nil, fmt.Errorf("invalid interface config: %v: %w", err, ErrInvalidResult)
}
name := c.getInterfaceName(result.Interfaces, ipConf)
r.Interfaces[name].IPConfigs = append(r.Interfaces[name].IPConfigs,
@ -90,7 +97,7 @@ func (c *libcni) createResult(results []*current.Result) (*Result, error) {
r.Routes = append(r.Routes, result.Routes...)
}
if _, ok := r.Interfaces[defaultInterface(c.prefix)]; !ok {
return nil, errors.Wrapf(ErrNotFound, "default network not found for: %s", defaultInterface(c.prefix))
return nil, fmt.Errorf("default network not found for: %s: %w", defaultInterface(c.prefix), ErrNotFound)
}
return r, nil
}
@ -98,8 +105,8 @@ func (c *libcni) createResult(results []*current.Result) (*Result, error) {
// getInterfaceName returns the interface name if the plugins
// return the result with associated interfaces. If interface
// is not present then default interface name is used
func (c *libcni) getInterfaceName(interfaces []*current.Interface,
ipConf *current.IPConfig) string {
func (c *libcni) getInterfaceName(interfaces []*types100.Interface,
ipConf *types100.IPConfig) string {
if ipConf.Interface != nil {
return interfaces[*ipConf.Interface].Name
}