vendoring latest go-cni with fixes

Signed-off-by: Abhinandan Prativadi <abhi@docker.com>
This commit is contained in:
Abhinandan Prativadi 2018-06-21 18:59:00 +00:00
parent 263b0b99d0
commit 860971025f
4 changed files with 110 additions and 122 deletions

View File

@ -7,7 +7,7 @@ github.com/containerd/console cb7008ab3d8359b78c5f464cb7cf160107ad5925
github.com/containerd/containerd 84bebdd91d347c99069d1705b7d4e6d6f746160c github.com/containerd/containerd 84bebdd91d347c99069d1705b7d4e6d6f746160c
github.com/containerd/continuity d3c23511c1bf5851696cba83143d9cbcd666869b github.com/containerd/continuity d3c23511c1bf5851696cba83143d9cbcd666869b
github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c
github.com/containerd/go-cni f2d7272f12d045b16ed924f50e91f9f9cecc55a7 github.com/containerd/go-cni 5882530828ecf62032409b298a3e8b19e08b6534
github.com/containerd/go-runc f271fa2021de855d4d918dbef83c5fe19db1bdd5 github.com/containerd/go-runc f271fa2021de855d4d918dbef83c5fe19db1bdd5
github.com/containerd/typeurl f6943554a7e7e88b3c14aad190bf05932da84788 github.com/containerd/typeurl f6943554a7e7e88b3c14aad190bf05932da84788
github.com/containernetworking/cni v0.6.0 github.com/containernetworking/cni v0.6.0

View File

@ -1,7 +1,10 @@
[![Build Status](https://travis-ci.org/containerd/go-cni.svg?branch=master)](https://travis-ci.org/containerd/go-cni)
# go-cni # go-cni
A generic CNI library to provide APIs for CNI plugin interactions. The library provides APIs to: A generic CNI library to provide APIs for CNI plugin interactions. The library provides APIs to:
- Load CNI network config from different sources
- Setup networks for container namespace - Setup networks for container namespace
- Remove networks from container namespace - Remove networks from container namespace
- Query status of CNI network plugin initialization - Query status of CNI network plugin initialization
@ -16,11 +19,17 @@ func main() {
defaultIfName := "eth0" defaultIfName := "eth0"
// Initialize library // Initialize library
l = gocni.New(gocni.WithMinNetworkCount(2), l = gocni.New(gocni.WithMinNetworkCount(2),
gocni.WithLoNetwork(),
gocni.WithPluginConfDir("/etc/mycni/net.d"), gocni.WithPluginConfDir("/etc/mycni/net.d"),
gocni.WithPluginDir([]string{"/opt/mycni/bin", "/opt/cni/bin"}), gocni.WithPluginDir([]string{"/opt/mycni/bin", "/opt/cni/bin"}),
gocni.WithDefaultIfName(defaultIfName)) gocni.WithDefaultIfName(defaultIfName))
// Load the cni configuration
err:= l.Load(gocni.WithLoNetwork,gocni.WithDefaultConf)
if err != nil{
log.Errorf("failed to load cni configuration: %v", err)
return
}
// Setup network for namespace. // Setup network for namespace.
labels := map[string]string{ labels := map[string]string{
"K8S_POD_NAMESPACE": "namespace1", "K8S_POD_NAMESPACE": "namespace1",
@ -29,16 +38,10 @@ func main() {
} }
result, err := l.Setup(id, netns, gocni.WithLabels(labels)) result, err := l.Setup(id, netns, gocni.WithLabels(labels))
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to setup network for namespace %q: %v", id, err) log.Errorf("failed to setup network for namespace %q: %v",id, err)
return
} }
defer func() {
if retErr != nil {
// Teardown network if an error is returned.
if err := l.Remove(id, netns, gocni.WithLabels(labels)); err != nil {
fmt.Errorf("Failed to destroy network for namespace %q", id)
}
}
}()
// Get IP of the default interface // Get IP of the default interface
IP := result.Interfaces[defaultIfName].IPConfigs[0].IP.String() IP := result.Interfaces[defaultIfName].IPConfigs[0].IP.String()
fmt.Printf("IP of the default interface %s:%s", defaultIfName, IP) fmt.Printf("IP of the default interface %s:%s", defaultIfName, IP)

View File

@ -31,7 +31,7 @@ type CNI interface {
// Remove tears down the network of the namespace. // Remove tears down the network of the namespace.
Remove(id string, path string, opts ...NamespaceOpts) error Remove(id string, path string, opts ...NamespaceOpts) error
// Load loads the cni network config // Load loads the cni network config
Load(opts ...LoadOption) error Load(opts ...CNIOpt) error
// Status checks the status of the cni initialization // Status checks the status of the cni initialization
Status() error Status() error
} }
@ -59,7 +59,7 @@ func defaultCNIConfig() *libcni {
} }
} }
func New(config ...ConfigOption) (CNI, error) { func New(config ...CNIOpt) (CNI, error) {
cni := defaultCNIConfig() cni := defaultCNIConfig()
var err error var err error
for _, c := range config { for _, c := range config {
@ -70,8 +70,10 @@ func New(config ...ConfigOption) (CNI, error) {
return cni, nil return cni, nil
} }
func (c *libcni) Load(opts ...LoadOption) error { func (c *libcni) Load(opts ...CNIOpt) error {
var err error var err error
c.Lock()
defer c.Unlock()
// Reset the networks on a load operation to ensure // Reset the networks on a load operation to ensure
// config happens on a clean slate // config happens on a clean slate
c.reset() c.reset()
@ -81,30 +83,27 @@ func (c *libcni) Load(opts ...LoadOption) error {
return errors.Wrapf(ErrLoad, fmt.Sprintf("cni config load failed: %v", err)) return errors.Wrapf(ErrLoad, fmt.Sprintf("cni config load failed: %v", err))
} }
} }
return c.Status() return nil
} }
func (c *libcni) Status() error { func (c *libcni) Status() error {
c.RLock() c.RLock()
defer c.RUnlock() defer c.RUnlock()
if len(c.networks) < c.networkCount { return c.status()
return ErrCNINotInitialized
}
return nil
} }
// Setup setups the network in the namespace // Setup setups the network in the namespace
func (c *libcni) Setup(id string, path string, opts ...NamespaceOpts) (*CNIResult, error) { func (c *libcni) Setup(id string, path string, opts ...NamespaceOpts) (*CNIResult, error) {
if err:=c.Status();err!=nil{ c.RLock()
return nil,err defer c.RUnlock()
if err := c.status(); err != nil {
return nil, err
} }
ns, err := newNamespace(id, path, opts...) ns, err := newNamespace(id, path, opts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var results []*current.Result var results []*current.Result
c.RLock()
defer c.RUnlock()
for _, network := range c.networks { for _, network := range c.networks {
r, err := network.Attach(ns) r, err := network.Attach(ns)
if err != nil { if err != nil {
@ -117,15 +116,15 @@ func (c *libcni) Setup(id string, path string, opts ...NamespaceOpts) (*CNIResul
// Remove removes the network config from the namespace // Remove removes the network config from the namespace
func (c *libcni) Remove(id string, path string, opts ...NamespaceOpts) error { func (c *libcni) Remove(id string, path string, opts ...NamespaceOpts) error {
if err:=c.Status();err!=nil{ c.RLock()
return err defer c.RUnlock()
} if err := c.status(); err != nil {
return err
}
ns, err := newNamespace(id, path, opts...) ns, err := newNamespace(id, path, opts...)
if err != nil { if err != nil {
return err return err
} }
c.RLock()
defer c.RUnlock()
for _, network := range c.networks { for _, network := range c.networks {
if err := network.Remove(ns); err != nil { if err := network.Remove(ns); err != nil {
return err return err
@ -135,7 +134,12 @@ func (c *libcni) Remove(id string, path string, opts ...NamespaceOpts) error {
} }
func (c *libcni) reset() { func (c *libcni) reset() {
c.Lock()
defer c.Unlock()
c.networks = nil c.networks = nil
} }
func (c *libcni) status() error {
if len(c.networks) < c.networkCount {
return ErrCNINotInitialized
}
return nil
}

View File

@ -24,11 +24,11 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
) )
type ConfigOption func(c *libcni) error type CNIOpt func(c *libcni) error
// WithInterfacePrefix sets the prefix for network interfaces // WithInterfacePrefix sets the prefix for network interfaces
// e.g. eth or wlan // e.g. eth or wlan
func WithInterfacePrefix(prefix string) ConfigOption { func WithInterfacePrefix(prefix string) CNIOpt {
return func(c *libcni) error { return func(c *libcni) error {
c.prefix = prefix c.prefix = prefix
return nil return nil
@ -37,7 +37,7 @@ func WithInterfacePrefix(prefix string) ConfigOption {
// WithPluginDir can be used to set the locations of // WithPluginDir can be used to set the locations of
// the cni plugin binaries // the cni plugin binaries
func WithPluginDir(dirs []string) ConfigOption { func WithPluginDir(dirs []string) CNIOpt {
return func(c *libcni) error { return func(c *libcni) error {
c.pluginDirs = dirs c.pluginDirs = dirs
c.cniConfig = &cnilibrary.CNIConfig{Path: dirs} c.cniConfig = &cnilibrary.CNIConfig{Path: dirs}
@ -47,7 +47,7 @@ func WithPluginDir(dirs []string) ConfigOption {
// WithPluginConfDir can be used to configure the // WithPluginConfDir can be used to configure the
// cni configuration directory. // cni configuration directory.
func WithPluginConfDir(dir string) ConfigOption { func WithPluginConfDir(dir string) CNIOpt {
return func(c *libcni) error { return func(c *libcni) error {
c.pluginConfDir = dir c.pluginConfDir = dir
return nil return nil
@ -57,23 +57,17 @@ func WithPluginConfDir(dir string) ConfigOption {
// WithMinNetworkCount can be used to configure the // WithMinNetworkCount can be used to configure the
// minimum networks to be configured and initalized // minimum networks to be configured and initalized
// for the status to report success. By default its 1. // for the status to report success. By default its 1.
func WithMinNetworkCount(count int) ConfigOption { func WithMinNetworkCount(count int) CNIOpt {
return func(c *libcni) error { return func(c *libcni) error {
c.networkCount = count c.networkCount = count
return nil return nil
} }
} }
// LoadOption can be used with Load API
// to load network configuration from different
// sources.
type LoadOption func(c *libcni) error
// WithLoNetwork can be used to load the loopback // WithLoNetwork can be used to load the loopback
// network config. // network config.
func WithLoNetwork() LoadOption { func WithLoNetwork(c *libcni) error {
return func(c *libcni) error { loConfig, _ := cnilibrary.ConfListFromBytes([]byte(`{
loConfig, _ := cnilibrary.ConfListFromBytes([]byte(`{
"cniVersion": "0.3.1", "cniVersion": "0.3.1",
"name": "cni-loopback", "name": "cni-loopback",
"plugins": [{ "plugins": [{
@ -81,20 +75,17 @@ func WithLoNetwork() LoadOption {
}] }]
}`)) }`))
c.Lock() c.networks = append(c.networks, &Network{
defer c.Unlock() cni: c.cniConfig,
c.networks = append(c.networks,&Network{ config: loConfig,
cni: c.cniConfig, ifName: "lo",
config: loConfig, })
ifName: "lo", return nil
})
return nil
}
} }
// WithConf can be used to load config directly // WithConf can be used to load config directly
// from byte. // from byte.
func WithConf(bytes []byte) LoadOption { func WithConf(bytes []byte) CNIOpt {
return func(c *libcni) error { return func(c *libcni) error {
conf, err := cnilibrary.ConfFromBytes(bytes) conf, err := cnilibrary.ConfFromBytes(bytes)
if err != nil { if err != nil {
@ -104,8 +95,6 @@ func WithConf(bytes []byte) LoadOption {
if err != nil { if err != nil {
return err return err
} }
c.Lock()
defer c.Unlock()
c.networks = append(c.networks, &Network{ c.networks = append(c.networks, &Network{
cni: c.cniConfig, cni: c.cniConfig,
config: confList, config: confList,
@ -118,7 +107,7 @@ func WithConf(bytes []byte) LoadOption {
// WithConfFile can be used to load network config // WithConfFile can be used to load network config
// from an .conf file. Supported with absolute fileName // from an .conf file. Supported with absolute fileName
// with path only. // with path only.
func WithConfFile(fileName string) LoadOption { func WithConfFile(fileName string) CNIOpt {
return func(c *libcni) error { return func(c *libcni) error {
conf, err := cnilibrary.ConfFromFile(fileName) conf, err := cnilibrary.ConfFromFile(fileName)
if err != nil { if err != nil {
@ -129,8 +118,6 @@ func WithConfFile(fileName string) LoadOption {
if err != nil { if err != nil {
return err return err
} }
c.Lock()
defer c.Unlock()
c.networks = append(c.networks, &Network{ c.networks = append(c.networks, &Network{
cni: c.cniConfig, cni: c.cniConfig,
config: confList, config: confList,
@ -143,15 +130,13 @@ func WithConfFile(fileName string) LoadOption {
// WithConfListFile can be used to load network config // WithConfListFile can be used to load network config
// from an .conflist file. Supported with absolute fileName // from an .conflist file. Supported with absolute fileName
// with path only. // with path only.
func WithConfListFile(fileName string) LoadOption { func WithConfListFile(fileName string) CNIOpt {
return func(c *libcni) error { return func(c *libcni) error {
confList, err := cnilibrary.ConfListFromFile(fileName) confList, err := cnilibrary.ConfListFromFile(fileName)
if err != nil { if err != nil {
return err return err
} }
c.Lock() c.networks = append(c.networks, &Network{
defer c.Unlock()
c.networks = append(c.networks,&Network{
cni: c.cniConfig, cni: c.cniConfig,
config: confList, config: confList,
ifName: getIfName(c.prefix, 0), ifName: getIfName(c.prefix, 0),
@ -163,64 +148,60 @@ func WithConfListFile(fileName string) LoadOption {
// WithDefaultConf can be used to detect network config // WithDefaultConf can be used to detect network config
// files from the configured cni config directory and load // files from the configured cni config directory and load
// them. // them.
func WithDefaultConf() LoadOption { func WithDefaultConf(c *libcni) error {
return func(c *libcni) error { files, err := cnilibrary.ConfFiles(c.pluginConfDir, []string{".conf", ".conflist", ".json"})
files, err := cnilibrary.ConfFiles(c.pluginConfDir, []string{".conf", ".conflist", ".json"}) switch {
switch { case err != nil:
case err != nil: return errors.Wrapf(ErrRead, "failed to read config file: %v", err)
return errors.Wrapf(ErrRead, "failed to read config file: %v", err) case len(files) == 0:
case len(files) == 0: return errors.Wrapf(ErrCNINotInitialized, "no network config found in %s", c.pluginConfDir)
return errors.Wrapf(ErrCNINotInitialized, "no network config found in %s", c.pluginConfDir)
}
// files contains the network config files associated with cni network.
// Use lexicographical way as a defined order for network config files.
sort.Strings(files)
// Since the CNI spec does not specify a way to detect default networks,
// the convention chosen is - the first network configuration in the sorted
// list of network conf files as the default network and choose the default
// interface provided during init as the network interface for this default
// network. For every other network use a generated interface id.
i := 0
c.Lock()
defer c.Unlock()
for _, confFile := range files {
var confList *cnilibrary.NetworkConfigList
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)
}
} else {
conf, err := cnilibrary.ConfFromFile(confFile)
if err != nil {
return errors.Wrapf(ErrInvalidConfig, "failed to load CNI config file %s: %v", confFile, err)
}
// 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)
}
confList, err = cnilibrary.ConfListFromConf(conf)
if err != nil {
return errors.Wrapf(ErrInvalidConfig, "failed to convert CNI config file %s to list: %v", confFile, err)
}
}
if len(confList.Plugins) == 0 {
return errors.Wrapf(ErrInvalidConfig, "CNI config list %s has no networks, skipping", confFile)
}
c.networks = append(c.networks, &Network{
cni: c.cniConfig,
config: confList,
ifName: getIfName(c.prefix, i),
})
i++
}
if len(c.networks) == 0 {
return errors.Wrapf(ErrCNINotInitialized, "no valid networks found in %s", c.pluginDirs)
}
return nil
} }
// files contains the network config files associated with cni network.
// Use lexicographical way as a defined order for network config files.
sort.Strings(files)
// Since the CNI spec does not specify a way to detect default networks,
// the convention chosen is - the first network configuration in the sorted
// list of network conf files as the default network and choose the default
// interface provided during init as the network interface for this default
// network. For every other network use a generated interface id.
i := 0
for _, confFile := range files {
var confList *cnilibrary.NetworkConfigList
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)
}
} else {
conf, err := cnilibrary.ConfFromFile(confFile)
if err != nil {
return errors.Wrapf(ErrInvalidConfig, "failed to load CNI config file %s: %v", confFile, err)
}
// 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)
}
confList, err = cnilibrary.ConfListFromConf(conf)
if err != nil {
return errors.Wrapf(ErrInvalidConfig, "failed to convert CNI config file %s to list: %v", confFile, err)
}
}
if len(confList.Plugins) == 0 {
return errors.Wrapf(ErrInvalidConfig, "CNI config list %s has no networks, skipping", confFile)
}
c.networks = append(c.networks, &Network{
cni: c.cniConfig,
config: confList,
ifName: getIfName(c.prefix, i),
})
i++
}
if len(c.networks) == 0 {
return errors.Wrapf(ErrCNINotInitialized, "no valid networks found in %s", c.pluginDirs)
}
return nil
} }