Merge pull request #1238 from crosbymichael/cni-update
Update cni and go-cni to the v0.7.1 release
This commit is contained in:
commit
92603895fd
@ -146,7 +146,7 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox
|
||||
defer func() {
|
||||
if retErr != nil {
|
||||
// Teardown network if an error is returned.
|
||||
if err := c.teardownPod(id, sandbox.NetNSPath, config); err != nil {
|
||||
if err := c.teardownPod(ctx, id, sandbox.NetNSPath, config); err != nil {
|
||||
log.G(ctx).WithError(err).Errorf("Failed to destroy network for sandbox %q", id)
|
||||
}
|
||||
}
|
||||
@ -559,7 +559,7 @@ func (c *criService) setupPod(ctx context.Context, id string, path string, confi
|
||||
return "", nil, errors.Wrap(err, "failed to get bandwidth info from annotations")
|
||||
}
|
||||
|
||||
result, err := c.netPlugin.Setup(id,
|
||||
result, err := c.netPlugin.Setup(ctx, id,
|
||||
path,
|
||||
cni.WithLabels(labels),
|
||||
cni.WithCapabilityPortMap(toCNIPortMappings(config.GetPortMappings())),
|
||||
@ -575,7 +575,7 @@ func (c *criService) setupPod(ctx context.Context, id string, path string, confi
|
||||
return selectPodIP(configs.IPConfigs), result, nil
|
||||
}
|
||||
// If it comes here then the result was invalid so destroy the pod network and return error
|
||||
if err := c.teardownPod(id, path, config); err != nil {
|
||||
if err := c.teardownPod(ctx, id, path, config); err != nil {
|
||||
log.G(ctx).WithError(err).Errorf("Failed to destroy network for sandbox %q", id)
|
||||
}
|
||||
return "", result, errors.Errorf("failed to find network info for sandbox %q", id)
|
||||
|
@ -80,7 +80,7 @@ func (c *criService) StopPodSandbox(ctx context.Context, r *runtime.StopPodSandb
|
||||
} else if closed {
|
||||
netNSPath = ""
|
||||
}
|
||||
if err := c.teardownPod(id, netNSPath, sandbox.Config); err != nil {
|
||||
if err := c.teardownPod(ctx, id, netNSPath, sandbox.Config); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to destroy network for sandbox %q", id)
|
||||
}
|
||||
if err = sandbox.NetNS.Remove(); err != nil {
|
||||
@ -157,13 +157,13 @@ func (c *criService) waitSandboxStop(ctx context.Context, sandbox sandboxstore.S
|
||||
}
|
||||
|
||||
// teardownPod removes the network from the pod
|
||||
func (c *criService) teardownPod(id string, path string, config *runtime.PodSandboxConfig) error {
|
||||
func (c *criService) teardownPod(ctx context.Context, id string, path string, config *runtime.PodSandboxConfig) error {
|
||||
if c.netPlugin == nil {
|
||||
return errors.New("cni config not initialized")
|
||||
}
|
||||
|
||||
labels := getPodCNILabels(id, config)
|
||||
return c.netPlugin.Remove(id,
|
||||
return c.netPlugin.Remove(ctx, id,
|
||||
path,
|
||||
cni.WithLabels(labels),
|
||||
cni.WithCapabilityPortMap(toCNIPortMappings(config.GetPortMappings())))
|
||||
|
@ -17,6 +17,8 @@ limitations under the License.
|
||||
package testing
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
cni "github.com/containerd/go-cni"
|
||||
)
|
||||
|
||||
@ -32,12 +34,12 @@ func NewFakeCNIPlugin() *FakeCNIPlugin {
|
||||
}
|
||||
|
||||
// Setup setups the network of PodSandbox.
|
||||
func (f *FakeCNIPlugin) Setup(id, path string, opts ...cni.NamespaceOpts) (*cni.CNIResult, error) {
|
||||
func (f *FakeCNIPlugin) Setup(ctx context.Context, id, path string, opts ...cni.NamespaceOpts) (*cni.CNIResult, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Remove teardown the network of PodSandbox.
|
||||
func (f *FakeCNIPlugin) Remove(id, path string, opts ...cni.NamespaceOpts) error {
|
||||
func (f *FakeCNIPlugin) Remove(ctx context.Context, id, path string, opts ...cni.NamespaceOpts) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -76,5 +76,5 @@ github.com/davecgh/go-spew v1.1.1
|
||||
|
||||
# cni dependencies
|
||||
github.com/containernetworking/plugins v0.7.5
|
||||
github.com/containernetworking/cni v0.6.0
|
||||
github.com/containerd/go-cni 22460c018b64cf8bf4151b3ff9c4d077e6a88cbf
|
||||
github.com/containernetworking/cni v0.7.1
|
||||
github.com/containerd/go-cni 49fbd9b210f3c8ee3b7fd3cd797aabaf364627c1
|
||||
|
4
vendor/github.com/containerd/go-cni/README.md
generated
vendored
4
vendor/github.com/containerd/go-cni/README.md
generated
vendored
@ -12,7 +12,7 @@ A generic CNI library to provide APIs for CNI plugin interactions. The library p
|
||||
go-cni aims to support plugins that implement [Container Network Interface](https://github.com/containernetworking/cni)
|
||||
|
||||
## Usage
|
||||
```
|
||||
```go
|
||||
func main() {
|
||||
id := "123456"
|
||||
netns := "/proc/9999/ns/net"
|
||||
@ -24,7 +24,7 @@ func main() {
|
||||
gocni.WithDefaultIfName(defaultIfName))
|
||||
|
||||
// Load the cni configuration
|
||||
err:= l.Load(gocni.WithLoNetwork,gocni.WithDefaultConf)
|
||||
err:= l.Load(gocni.WithLoNetwork, gocni.WithDefaultConf)
|
||||
if err != nil{
|
||||
log.Errorf("failed to load cni configuration: %v", err)
|
||||
return
|
||||
|
13
vendor/github.com/containerd/go-cni/cni.go
generated
vendored
13
vendor/github.com/containerd/go-cni/cni.go
generated
vendored
@ -17,6 +17,7 @@
|
||||
package cni
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
@ -29,9 +30,9 @@ import (
|
||||
|
||||
type CNI interface {
|
||||
// Setup setup the network for the namespace
|
||||
Setup(id string, path string, opts ...NamespaceOpts) (*CNIResult, error)
|
||||
Setup(ctx context.Context, id string, path string, opts ...NamespaceOpts) (*CNIResult, error)
|
||||
// Remove tears down the network of the namespace.
|
||||
Remove(id string, path string, opts ...NamespaceOpts) error
|
||||
Remove(ctx context.Context, id string, path string, opts ...NamespaceOpts) error
|
||||
// Load loads the cni network config
|
||||
Load(opts ...CNIOpt) error
|
||||
// Status checks the status of the cni initialization
|
||||
@ -139,7 +140,7 @@ func (c *libcni) Networks() []*Network {
|
||||
}
|
||||
|
||||
// Setup setups the network in the namespace
|
||||
func (c *libcni) Setup(id string, path string, opts ...NamespaceOpts) (*CNIResult, error) {
|
||||
func (c *libcni) Setup(ctx context.Context, id string, path string, opts ...NamespaceOpts) (*CNIResult, error) {
|
||||
if err := c.Status(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -149,7 +150,7 @@ func (c *libcni) Setup(id string, path string, opts ...NamespaceOpts) (*CNIResul
|
||||
}
|
||||
var results []*current.Result
|
||||
for _, network := range c.Networks() {
|
||||
r, err := network.Attach(ns)
|
||||
r, err := network.Attach(ctx, ns)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -159,7 +160,7 @@ func (c *libcni) Setup(id string, path string, opts ...NamespaceOpts) (*CNIResul
|
||||
}
|
||||
|
||||
// Remove removes the network config from the namespace
|
||||
func (c *libcni) Remove(id string, path string, opts ...NamespaceOpts) error {
|
||||
func (c *libcni) Remove(ctx context.Context, id string, path string, opts ...NamespaceOpts) error {
|
||||
if err := c.Status(); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -168,7 +169,7 @@ func (c *libcni) Remove(id string, path string, opts ...NamespaceOpts) error {
|
||||
return err
|
||||
}
|
||||
for _, network := range c.Networks() {
|
||||
if err := network.Remove(ns); err != nil {
|
||||
if err := network.Remove(ctx, ns); err != nil {
|
||||
// Based on CNI spec v0.7.0, empty network namespace is allowed to
|
||||
// do best effort cleanup. However, it is not handled consistently
|
||||
// right now:
|
||||
|
4
vendor/github.com/containerd/go-cni/helper.go
generated
vendored
4
vendor/github.com/containerd/go-cni/helper.go
generated
vendored
@ -24,10 +24,10 @@ import (
|
||||
|
||||
func validateInterfaceConfig(ipConf *current.IPConfig, ifs int) error {
|
||||
if ipConf == nil {
|
||||
return fmt.Errorf("invalid IP configuration")
|
||||
return fmt.Errorf("invalid IP configuration (nil)")
|
||||
}
|
||||
if ipConf.Interface != nil && *ipConf.Interface > ifs {
|
||||
return fmt.Errorf("invalid IP configuration with invalid interface %d", *ipConf.Interface)
|
||||
return fmt.Errorf("invalid IP configuration (interface number %d is > number of interfaces %d)", *ipConf.Interface, ifs)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
10
vendor/github.com/containerd/go-cni/namespace.go
generated
vendored
10
vendor/github.com/containerd/go-cni/namespace.go
generated
vendored
@ -17,6 +17,8 @@
|
||||
package cni
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
cnilibrary "github.com/containernetworking/cni/libcni"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
)
|
||||
@ -27,16 +29,16 @@ type Network struct {
|
||||
ifName string
|
||||
}
|
||||
|
||||
func (n *Network) Attach(ns *Namespace) (*current.Result, error) {
|
||||
r, err := n.cni.AddNetworkList(n.config, ns.config(n.ifName))
|
||||
func (n *Network) Attach(ctx context.Context, ns *Namespace) (*current.Result, error) {
|
||||
r, err := n.cni.AddNetworkList(ctx, n.config, ns.config(n.ifName))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return current.NewResultFromResult(r)
|
||||
}
|
||||
|
||||
func (n *Network) Remove(ns *Namespace) error {
|
||||
return n.cni.DelNetworkList(n.config, ns.config(n.ifName))
|
||||
func (n *Network) Remove(ctx context.Context, ns *Namespace) error {
|
||||
return n.cni.DelNetworkList(ctx, n.config, ns.config(n.ifName))
|
||||
}
|
||||
|
||||
type Namespace struct {
|
||||
|
4
vendor/github.com/containerd/go-cni/opts.go
generated
vendored
4
vendor/github.com/containerd/go-cni/opts.go
generated
vendored
@ -220,11 +220,11 @@ func loadFromConfDir(c *libcni, max int) error {
|
||||
|
||||
confList, err = cnilibrary.ConfListFromConf(conf)
|
||||
if err != nil {
|
||||
return errors.Wrapf(ErrInvalidConfig, "failed to convert CNI config file %s to list: %v", confFile, err)
|
||||
return errors.Wrapf(ErrInvalidConfig, "failed to convert CNI config file %s to CNI config list: %v", confFile, err)
|
||||
}
|
||||
}
|
||||
if len(confList.Plugins) == 0 {
|
||||
return errors.Wrapf(ErrInvalidConfig, "CNI config list %s has no networks, skipping", confFile)
|
||||
return errors.Wrapf(ErrInvalidConfig, "CNI config list in config file %s has no networks, skipping", confFile)
|
||||
|
||||
}
|
||||
networks = append(networks, &Network{
|
||||
|
4
vendor/github.com/containerd/go-cni/result.go
generated
vendored
4
vendor/github.com/containerd/go-cni/result.go
generated
vendored
@ -79,7 +79,7 @@ func (c *libcni) GetCNIResultFromResults(results []*current.Result) (*CNIResult,
|
||||
// interfaces
|
||||
for _, ipConf := range result.IPs {
|
||||
if err := validateInterfaceConfig(ipConf, len(result.Interfaces)); err != nil {
|
||||
return nil, errors.Wrapf(ErrInvalidResult, "failed to valid interface config: %v", err)
|
||||
return nil, errors.Wrapf(ErrInvalidResult, "invalid interface config: %v", err)
|
||||
}
|
||||
name := c.getInterfaceName(result.Interfaces, ipConf)
|
||||
r.Interfaces[name].IPConfigs = append(r.Interfaces[name].IPConfigs,
|
||||
@ -89,7 +89,7 @@ func (c *libcni) GetCNIResultFromResults(results []*current.Result) (*CNIResult,
|
||||
r.Routes = append(r.Routes, result.Routes...)
|
||||
}
|
||||
if _, ok := r.Interfaces[defaultInterface(c.prefix)]; !ok {
|
||||
return nil, errors.Wrapf(ErrNotFound, "default network not found")
|
||||
return nil, errors.Wrapf(ErrNotFound, "default network not found for: %s", defaultInterface(c.prefix))
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
2
vendor/github.com/containerd/go-cni/vendor.conf
generated
vendored
2
vendor/github.com/containerd/go-cni/vendor.conf
generated
vendored
@ -2,5 +2,5 @@ github.com/stretchr/testify b89eecf5ca5db6d3ba60b237ffe3df7bafb7662f
|
||||
github.com/davecgh/go-spew 8991bc29aa16c548c550c7ff78260e27b9ab7c73
|
||||
github.com/pmezard/go-difflib 792786c7400a136282c1664665ae0a8db921c6c2
|
||||
github.com/stretchr/objx 8a3f7159479fbc75b30357fbc48f380b7320f08e
|
||||
github.com/containernetworking/cni 142cde0c766cd6055cc7fdfdcb44579c0c9c35bf
|
||||
github.com/containernetworking/cni v0.7.1
|
||||
github.com/pkg/errors v0.8.0
|
||||
|
29
vendor/github.com/containernetworking/cni/README.md
generated
vendored
29
vendor/github.com/containernetworking/cni/README.md
generated
vendored
@ -1,4 +1,5 @@
|
||||
[](https://travis-ci.org/containernetworking/cni)
|
||||
[](https://travis-ci.org/containernetworking/cni)
|
||||
[](https://ci.appveyor.com/project/cni-bot/cni/branch/master)
|
||||
[](https://coveralls.io/github/containernetworking/cni?branch=master)
|
||||
[](https://cryptic-tundra-43194.herokuapp.com/)
|
||||
|
||||
@ -8,7 +9,9 @@
|
||||
|
||||
# Community Sync Meeting
|
||||
|
||||
There is a community sync meeting for users and developers every 1-2 months. The next meeting will help on a Google Hangout and the link is in the [agenda](https://docs.google.com/document/d/10ECyT2mBGewsJUcmYmS8QNo1AcNgy2ZIe2xS7lShYhE/edit?usp=sharing) (Notes from previous meeting are also in this doc). The next meeting will be held on *Wednesday, June 21th* at *3:00pm UTC* [Add to Calendar]https://www.worldtimebuddy.com/?qm=1&lid=100,5,2643743,5391959&h=100&date=2017-6-21&sln=15-16).
|
||||
There is a community sync meeting for users and developers every 1-2 months. The next meeting will help on a Google Hangout and the link is in the [agenda](https://docs.google.com/document/d/10ECyT2mBGewsJUcmYmS8QNo1AcNgy2ZIe2xS7lShYhE/edit?usp=sharing) (Notes from previous meeting are also in this doc).
|
||||
|
||||
The next meeting will be held on *Wednesday, January 30th, 2019* at *4:00pm UTC / 11:00am EDT / 8:00am PDT* [Add to Calendar](https://www.worldtimebuddy.com/?qm=1&lid=100,5,2643743,5391959&h=100&date=2019-01-30&sln=16-17).
|
||||
|
||||
---
|
||||
|
||||
@ -35,11 +38,13 @@ To avoid duplication, we think it is prudent to define a common interface betwee
|
||||
## Who is using CNI?
|
||||
### Container runtimes
|
||||
- [rkt - container engine](https://coreos.com/blog/rkt-cni-networking.html)
|
||||
- [Kurma - container runtime](http://kurma.io/)
|
||||
- [Kubernetes - a system to simplify container operations](http://kubernetes.io/docs/admin/network-plugins/)
|
||||
- [Kubernetes - a system to simplify container operations](https://kubernetes.io/docs/admin/network-plugins/)
|
||||
- [OpenShift - Kubernetes with additional enterprise features](https://github.com/openshift/origin/blob/master/docs/openshift_networking_requirements.md)
|
||||
- [Cloud Foundry - a platform for cloud applications](https://github.com/cloudfoundry-incubator/cf-networking-release)
|
||||
- [Mesos - a distributed systems kernel](https://github.com/apache/mesos/blob/master/docs/cni.md)
|
||||
- [Apache Mesos - a distributed systems kernel](https://github.com/apache/mesos/blob/master/docs/cni.md)
|
||||
- [Amazon ECS - a highly scalable, high performance container management service](https://aws.amazon.com/ecs/)
|
||||
- [Singularity - container platform optimized for HPC, EPC, and AI](https://github.com/sylabs/singularity)
|
||||
- [OpenSVC - orchestrator for legacy and containerized application stacks](https://docs.opensvc.com/latest/fr/agent.configure.cni.html)
|
||||
|
||||
### 3rd party plugins
|
||||
- [Project Calico - a layer 3 virtual network](https://github.com/projectcalico/calico-cni)
|
||||
@ -54,6 +59,15 @@ To avoid duplication, we think it is prudent to define a common interface betwee
|
||||
- [Nuage CNI - Nuage Networks SDN plugin for network policy kubernetes support ](https://github.com/nuagenetworks/nuage-cni)
|
||||
- [Silk - a CNI plugin designed for Cloud Foundry](https://github.com/cloudfoundry-incubator/silk)
|
||||
- [Linen - a CNI plugin designed for overlay networks with Open vSwitch and fit in SDN/OpenFlow network environment](https://github.com/John-Lin/linen-cni)
|
||||
- [Vhostuser - a Dataplane network plugin - Supports OVS-DPDK & VPP](https://github.com/intel/vhost-user-net-plugin)
|
||||
- [Amazon ECS CNI Plugins - a collection of CNI Plugins to configure containers with Amazon EC2 elastic network interfaces (ENIs)](https://github.com/aws/amazon-ecs-cni-plugins)
|
||||
- [Bonding CNI - a Link aggregating plugin to address failover and high availability network](https://github.com/Intel-Corp/bond-cni)
|
||||
- [ovn-kubernetes - an container network plugin built on Open vSwitch (OVS) and Open Virtual Networking (OVN) with support for both Linux and Windows](https://github.com/openvswitch/ovn-kubernetes)
|
||||
- [Juniper Contrail](https://www.juniper.net/cloud) / [TungstenFabric](https://tungstenfabric.io) - Provides overlay SDN solution, delivering multicloud networking, hybrid cloud networking, simultaneous overlay-underlay support, network policy enforcement, network isolation, service chaining and flexible load balancing
|
||||
- [Knitter - a CNI plugin supporting multiple networking for Kubernetes](https://github.com/ZTE/Knitter)
|
||||
- [DANM - a CNI-compliant networking solution for TelCo workloads running on Kubernetes](https://github.com/nokia/danm)
|
||||
- [VMware NSX – a CNI plugin that enables automated NSX L2/L3 networking and L4/L7 Load Balancing; network isolation at the pod, node, and cluster level; and zero-trust security policy for your Kubernetes cluster.](https://docs.vmware.com/en/VMware-NSX-T/2.2/com.vmware.nsxt.ncp_kubernetes.doc/GUID-6AFA724E-BB62-4693-B95C-321E8DDEA7E1.html)
|
||||
- [cni-route-override - a meta CNI plugin that override route information](https://github.com/redhat-nfvpe/cni-route-override)
|
||||
|
||||
The CNI team also maintains some [core plugins in a separate repository](https://github.com/containernetworking/plugins).
|
||||
|
||||
@ -67,7 +81,7 @@ If you intend to contribute to code or documentation, please read [CONTRIBUTING.
|
||||
|
||||
### Requirements
|
||||
|
||||
The CNI spec is language agnostic. To use the Go language libraries in this repository, you'll need a recent version of Go. Our [automated tests](https://travis-ci.org/containernetworking/cni/builds) cover Go versions 1.7 and 1.8.
|
||||
The CNI spec is language agnostic. To use the Go language libraries in this repository, you'll need a recent version of Go. You can find the Go versions covered by our [automated tests](https://travis-ci.org/containernetworking/cni/builds) in [.travis.yaml](.travis.yml).
|
||||
|
||||
### Reference Plugins
|
||||
|
||||
@ -104,6 +118,7 @@ EOF
|
||||
$ cat >/etc/cni/net.d/99-loopback.conf <<EOF
|
||||
{
|
||||
"cniVersion": "0.2.0",
|
||||
"name": "lo",
|
||||
"type": "loopback"
|
||||
}
|
||||
EOF
|
||||
@ -115,7 +130,7 @@ Next, build the plugins:
|
||||
|
||||
```bash
|
||||
$ cd $GOPATH/src/github.com/containernetworking/plugins
|
||||
$ ./build.sh
|
||||
$ ./build_linux.sh # or build_windows.sh
|
||||
```
|
||||
|
||||
Finally, execute a command (`ifconfig` in this example) in a private network namespace that has joined the `mynet` network:
|
||||
|
374
vendor/github.com/containernetworking/cni/libcni/api.go
generated
vendored
374
vendor/github.com/containernetworking/cni/libcni/api.go
generated
vendored
@ -15,7 +15,12 @@
|
||||
package libcni
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/invoke"
|
||||
@ -23,6 +28,14 @@ import (
|
||||
"github.com/containernetworking/cni/pkg/version"
|
||||
)
|
||||
|
||||
var (
|
||||
CacheDir = "/var/lib/cni"
|
||||
)
|
||||
|
||||
// A RuntimeConf holds the arguments to one invocation of a CNI plugin
|
||||
// excepting the network configuration, with the nested exception that
|
||||
// the `runtimeConfig` from the network configuration is included
|
||||
// here.
|
||||
type RuntimeConf struct {
|
||||
ContainerID string
|
||||
NetNS string
|
||||
@ -34,6 +47,9 @@ type RuntimeConf struct {
|
||||
// in this map which match the capabilities of the plugin are passed
|
||||
// to the plugin
|
||||
CapabilityArgs map[string]interface{}
|
||||
|
||||
// A cache directory in which to library data. Defaults to CacheDir
|
||||
CacheDir string
|
||||
}
|
||||
|
||||
type NetworkConfig struct {
|
||||
@ -44,31 +60,50 @@ type NetworkConfig struct {
|
||||
type NetworkConfigList struct {
|
||||
Name string
|
||||
CNIVersion string
|
||||
DisableCheck bool
|
||||
Plugins []*NetworkConfig
|
||||
Bytes []byte
|
||||
}
|
||||
|
||||
type CNI interface {
|
||||
AddNetworkList(net *NetworkConfigList, rt *RuntimeConf) (types.Result, error)
|
||||
DelNetworkList(net *NetworkConfigList, rt *RuntimeConf) error
|
||||
AddNetworkList(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) (types.Result, error)
|
||||
CheckNetworkList(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) error
|
||||
DelNetworkList(ctx context.Context, net *NetworkConfigList, rt *RuntimeConf) error
|
||||
GetNetworkListCachedResult(net *NetworkConfigList, rt *RuntimeConf) (types.Result, error)
|
||||
|
||||
AddNetwork(net *NetworkConfig, rt *RuntimeConf) (types.Result, error)
|
||||
DelNetwork(net *NetworkConfig, rt *RuntimeConf) error
|
||||
AddNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) (types.Result, error)
|
||||
CheckNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) error
|
||||
DelNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) error
|
||||
GetNetworkCachedResult(net *NetworkConfig, rt *RuntimeConf) (types.Result, error)
|
||||
|
||||
ValidateNetworkList(ctx context.Context, net *NetworkConfigList) ([]string, error)
|
||||
ValidateNetwork(ctx context.Context, net *NetworkConfig) ([]string, error)
|
||||
}
|
||||
|
||||
type CNIConfig struct {
|
||||
Path []string
|
||||
exec invoke.Exec
|
||||
}
|
||||
|
||||
// CNIConfig implements the CNI interface
|
||||
var _ CNI = &CNIConfig{}
|
||||
|
||||
func buildOneConfig(list *NetworkConfigList, orig *NetworkConfig, prevResult types.Result, rt *RuntimeConf) (*NetworkConfig, error) {
|
||||
// NewCNIConfig returns a new CNIConfig object that will search for plugins
|
||||
// in the given paths and use the given exec interface to run those plugins,
|
||||
// or if the exec interface is not given, will use a default exec handler.
|
||||
func NewCNIConfig(path []string, exec invoke.Exec) *CNIConfig {
|
||||
return &CNIConfig{
|
||||
Path: path,
|
||||
exec: exec,
|
||||
}
|
||||
}
|
||||
|
||||
func buildOneConfig(name, cniVersion string, orig *NetworkConfig, prevResult types.Result, rt *RuntimeConf) (*NetworkConfig, error) {
|
||||
var err error
|
||||
|
||||
inject := map[string]interface{}{
|
||||
"name": list.Name,
|
||||
"cniVersion": list.CNIVersion,
|
||||
"name": name,
|
||||
"cniVersion": cniVersion,
|
||||
}
|
||||
// Add previous plugin result
|
||||
if prevResult != nil {
|
||||
@ -92,7 +127,7 @@ func buildOneConfig(list *NetworkConfigList, orig *NetworkConfig, prevResult typ
|
||||
// These capabilities arguments are filtered through the plugin's advertised
|
||||
// capabilities from its config JSON, and any keys in the CapabilityArgs
|
||||
// matching plugin capabilities are added to the "runtimeConfig" dictionary
|
||||
// sent to the plugin via JSON on stdin. For exmaple, if the plugin's
|
||||
// sent to the plugin via JSON on stdin. For example, if the plugin's
|
||||
// capabilities include "portMappings", and the CapabilityArgs map includes a
|
||||
// "portMappings" key, that key and its value are added to the "runtimeConfig"
|
||||
// dictionary to be passed to the plugin's stdin.
|
||||
@ -119,45 +154,154 @@ func injectRuntimeConfig(orig *NetworkConfig, rt *RuntimeConf) (*NetworkConfig,
|
||||
return orig, nil
|
||||
}
|
||||
|
||||
// AddNetworkList executes a sequence of plugins with the ADD command
|
||||
func (c *CNIConfig) AddNetworkList(list *NetworkConfigList, rt *RuntimeConf) (types.Result, error) {
|
||||
var prevResult types.Result
|
||||
for _, net := range list.Plugins {
|
||||
pluginPath, err := invoke.FindInPath(net.Network.Type, c.Path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newConf, err := buildOneConfig(list, net, prevResult, rt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
prevResult, err = invoke.ExecPluginWithResult(pluginPath, newConf.Bytes, c.args("ADD", rt))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// ensure we have a usable exec if the CNIConfig was not given one
|
||||
func (c *CNIConfig) ensureExec() invoke.Exec {
|
||||
if c.exec == nil {
|
||||
c.exec = &invoke.DefaultExec{
|
||||
RawExec: &invoke.RawExec{Stderr: os.Stderr},
|
||||
PluginDecoder: version.PluginDecoder{},
|
||||
}
|
||||
}
|
||||
|
||||
return prevResult, nil
|
||||
return c.exec
|
||||
}
|
||||
|
||||
// DelNetworkList executes a sequence of plugins with the DEL command
|
||||
func (c *CNIConfig) DelNetworkList(list *NetworkConfigList, rt *RuntimeConf) error {
|
||||
for i := len(list.Plugins) - 1; i >= 0; i-- {
|
||||
net := list.Plugins[i]
|
||||
func getResultCacheFilePath(netName string, rt *RuntimeConf) string {
|
||||
cacheDir := rt.CacheDir
|
||||
if cacheDir == "" {
|
||||
cacheDir = CacheDir
|
||||
}
|
||||
return filepath.Join(cacheDir, "results", fmt.Sprintf("%s-%s-%s", netName, rt.ContainerID, rt.IfName))
|
||||
}
|
||||
|
||||
pluginPath, err := invoke.FindInPath(net.Network.Type, c.Path)
|
||||
func setCachedResult(result types.Result, netName string, rt *RuntimeConf) error {
|
||||
data, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fname := getResultCacheFilePath(netName, rt)
|
||||
if err := os.MkdirAll(filepath.Dir(fname), 0700); err != nil {
|
||||
return err
|
||||
}
|
||||
return ioutil.WriteFile(fname, data, 0600)
|
||||
}
|
||||
|
||||
func delCachedResult(netName string, rt *RuntimeConf) error {
|
||||
fname := getResultCacheFilePath(netName, rt)
|
||||
return os.Remove(fname)
|
||||
}
|
||||
|
||||
func getCachedResult(netName, cniVersion string, rt *RuntimeConf) (types.Result, error) {
|
||||
fname := getResultCacheFilePath(netName, rt)
|
||||
data, err := ioutil.ReadFile(fname)
|
||||
if err != nil {
|
||||
// Ignore read errors; the cached result may not exist on-disk
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Read the version of the cached result
|
||||
decoder := version.ConfigDecoder{}
|
||||
resultCniVersion, err := decoder.Decode(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure we can understand the result
|
||||
result, err := version.NewResult(resultCniVersion, data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Convert to the config version to ensure plugins get prevResult
|
||||
// in the same version as the config. The cached result version
|
||||
// should match the config version unless the config was changed
|
||||
// while the container was running.
|
||||
result, err = result.GetAsVersion(cniVersion)
|
||||
if err != nil && resultCniVersion != cniVersion {
|
||||
return nil, fmt.Errorf("failed to convert cached result version %q to config version %q: %v", resultCniVersion, cniVersion, err)
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
|
||||
// GetNetworkListCachedResult returns the cached Result of the previous
|
||||
// previous AddNetworkList() operation for a network list, or an error.
|
||||
func (c *CNIConfig) GetNetworkListCachedResult(list *NetworkConfigList, rt *RuntimeConf) (types.Result, error) {
|
||||
return getCachedResult(list.Name, list.CNIVersion, rt)
|
||||
}
|
||||
|
||||
// GetNetworkCachedResult returns the cached Result of the previous
|
||||
// previous AddNetwork() operation for a network, or an error.
|
||||
func (c *CNIConfig) GetNetworkCachedResult(net *NetworkConfig, rt *RuntimeConf) (types.Result, error) {
|
||||
return getCachedResult(net.Network.Name, net.Network.CNIVersion, rt)
|
||||
}
|
||||
|
||||
func (c *CNIConfig) addNetwork(ctx context.Context, name, cniVersion string, net *NetworkConfig, prevResult types.Result, rt *RuntimeConf) (types.Result, error) {
|
||||
c.ensureExec()
|
||||
pluginPath, err := c.exec.FindInPath(net.Network.Type, c.Path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newConf, err := buildOneConfig(name, cniVersion, net, prevResult, rt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return invoke.ExecPluginWithResult(ctx, pluginPath, newConf.Bytes, c.args("ADD", rt), c.exec)
|
||||
}
|
||||
|
||||
// AddNetworkList executes a sequence of plugins with the ADD command
|
||||
func (c *CNIConfig) AddNetworkList(ctx context.Context, list *NetworkConfigList, rt *RuntimeConf) (types.Result, error) {
|
||||
var err error
|
||||
var result types.Result
|
||||
for _, net := range list.Plugins {
|
||||
result, err = c.addNetwork(ctx, list.Name, list.CNIVersion, net, result, rt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if err = setCachedResult(result, list.Name, rt); err != nil {
|
||||
return nil, fmt.Errorf("failed to set network %q cached result: %v", list.Name, err)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *CNIConfig) checkNetwork(ctx context.Context, name, cniVersion string, net *NetworkConfig, prevResult types.Result, rt *RuntimeConf) error {
|
||||
c.ensureExec()
|
||||
pluginPath, err := c.exec.FindInPath(net.Network.Type, c.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
newConf, err := buildOneConfig(list, net, nil, rt)
|
||||
newConf, err := buildOneConfig(name, cniVersion, net, prevResult, rt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := invoke.ExecPluginWithoutResult(pluginPath, newConf.Bytes, c.args("DEL", rt)); err != nil {
|
||||
return invoke.ExecPluginWithoutResult(ctx, pluginPath, newConf.Bytes, c.args("CHECK", rt), c.exec)
|
||||
}
|
||||
|
||||
// CheckNetworkList executes a sequence of plugins with the CHECK command
|
||||
func (c *CNIConfig) CheckNetworkList(ctx context.Context, list *NetworkConfigList, rt *RuntimeConf) error {
|
||||
// CHECK was added in CNI spec version 0.4.0 and higher
|
||||
if gtet, err := version.GreaterThanOrEqualTo(list.CNIVersion, "0.4.0"); err != nil {
|
||||
return err
|
||||
} else if !gtet {
|
||||
return fmt.Errorf("configuration version %q does not support the CHECK command", list.CNIVersion)
|
||||
}
|
||||
|
||||
if list.DisableCheck {
|
||||
return nil
|
||||
}
|
||||
|
||||
cachedResult, err := getCachedResult(list.Name, list.CNIVersion, rt)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get network %q cached result: %v", list.Name, err)
|
||||
}
|
||||
|
||||
for _, net := range list.Plugins {
|
||||
if err := c.checkNetwork(ctx, list.Name, list.CNIVersion, net, cachedResult, rt); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -165,45 +309,179 @@ func (c *CNIConfig) DelNetworkList(list *NetworkConfigList, rt *RuntimeConf) err
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CNIConfig) delNetwork(ctx context.Context, name, cniVersion string, net *NetworkConfig, prevResult types.Result, rt *RuntimeConf) error {
|
||||
c.ensureExec()
|
||||
pluginPath, err := c.exec.FindInPath(net.Network.Type, c.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
newConf, err := buildOneConfig(name, cniVersion, net, prevResult, rt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return invoke.ExecPluginWithoutResult(ctx, pluginPath, newConf.Bytes, c.args("DEL", rt), c.exec)
|
||||
}
|
||||
|
||||
// DelNetworkList executes a sequence of plugins with the DEL command
|
||||
func (c *CNIConfig) DelNetworkList(ctx context.Context, list *NetworkConfigList, rt *RuntimeConf) error {
|
||||
var cachedResult types.Result
|
||||
|
||||
// Cached result on DEL was added in CNI spec version 0.4.0 and higher
|
||||
if gtet, err := version.GreaterThanOrEqualTo(list.CNIVersion, "0.4.0"); err != nil {
|
||||
return err
|
||||
} else if gtet {
|
||||
cachedResult, err = getCachedResult(list.Name, list.CNIVersion, rt)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get network %q cached result: %v", list.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
for i := len(list.Plugins) - 1; i >= 0; i-- {
|
||||
net := list.Plugins[i]
|
||||
if err := c.delNetwork(ctx, list.Name, list.CNIVersion, net, cachedResult, rt); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
_ = delCachedResult(list.Name, rt)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddNetwork executes the plugin with the ADD command
|
||||
func (c *CNIConfig) AddNetwork(net *NetworkConfig, rt *RuntimeConf) (types.Result, error) {
|
||||
pluginPath, err := invoke.FindInPath(net.Network.Type, c.Path)
|
||||
func (c *CNIConfig) AddNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) (types.Result, error) {
|
||||
result, err := c.addNetwork(ctx, net.Network.Name, net.Network.CNIVersion, net, nil, rt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
net, err = injectRuntimeConfig(net, rt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if err = setCachedResult(result, net.Network.Name, rt); err != nil {
|
||||
return nil, fmt.Errorf("failed to set network %q cached result: %v", net.Network.Name, err)
|
||||
}
|
||||
|
||||
return invoke.ExecPluginWithResult(pluginPath, net.Bytes, c.args("ADD", rt))
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// CheckNetwork executes the plugin with the CHECK command
|
||||
func (c *CNIConfig) CheckNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) error {
|
||||
// CHECK was added in CNI spec version 0.4.0 and higher
|
||||
if gtet, err := version.GreaterThanOrEqualTo(net.Network.CNIVersion, "0.4.0"); err != nil {
|
||||
return err
|
||||
} else if !gtet {
|
||||
return fmt.Errorf("configuration version %q does not support the CHECK command", net.Network.CNIVersion)
|
||||
}
|
||||
|
||||
cachedResult, err := getCachedResult(net.Network.Name, net.Network.CNIVersion, rt)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get network %q cached result: %v", net.Network.Name, err)
|
||||
}
|
||||
return c.checkNetwork(ctx, net.Network.Name, net.Network.CNIVersion, net, cachedResult, rt)
|
||||
}
|
||||
|
||||
// DelNetwork executes the plugin with the DEL command
|
||||
func (c *CNIConfig) DelNetwork(net *NetworkConfig, rt *RuntimeConf) error {
|
||||
pluginPath, err := invoke.FindInPath(net.Network.Type, c.Path)
|
||||
func (c *CNIConfig) DelNetwork(ctx context.Context, net *NetworkConfig, rt *RuntimeConf) error {
|
||||
var cachedResult types.Result
|
||||
|
||||
// Cached result on DEL was added in CNI spec version 0.4.0 and higher
|
||||
if gtet, err := version.GreaterThanOrEqualTo(net.Network.CNIVersion, "0.4.0"); err != nil {
|
||||
return err
|
||||
} else if gtet {
|
||||
cachedResult, err = getCachedResult(net.Network.Name, net.Network.CNIVersion, rt)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get network %q cached result: %v", net.Network.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := c.delNetwork(ctx, net.Network.Name, net.Network.CNIVersion, net, cachedResult, rt); err != nil {
|
||||
return err
|
||||
}
|
||||
_ = delCachedResult(net.Network.Name, rt)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateNetworkList checks that a configuration is reasonably valid.
|
||||
// - all the specified plugins exist on disk
|
||||
// - every plugin supports the desired version.
|
||||
//
|
||||
// Returns a list of all capabilities supported by the configuration, or error
|
||||
func (c *CNIConfig) ValidateNetworkList(ctx context.Context, list *NetworkConfigList) ([]string, error) {
|
||||
version := list.CNIVersion
|
||||
|
||||
// holding map for seen caps (in case of duplicates)
|
||||
caps := map[string]interface{}{}
|
||||
|
||||
errs := []error{}
|
||||
for _, net := range list.Plugins {
|
||||
if err := c.validatePlugin(ctx, net.Network.Type, version); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
for c, enabled := range net.Network.Capabilities {
|
||||
if !enabled {
|
||||
continue
|
||||
}
|
||||
caps[c] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
if len(errs) > 0 {
|
||||
return nil, fmt.Errorf("%v", errs)
|
||||
}
|
||||
|
||||
// make caps list
|
||||
cc := make([]string, 0, len(caps))
|
||||
for c := range caps {
|
||||
cc = append(cc, c)
|
||||
}
|
||||
|
||||
return cc, nil
|
||||
}
|
||||
|
||||
// ValidateNetwork checks that a configuration is reasonably valid.
|
||||
// It uses the same logic as ValidateNetworkList)
|
||||
// Returns a list of capabilities
|
||||
func (c *CNIConfig) ValidateNetwork(ctx context.Context, net *NetworkConfig) ([]string, error) {
|
||||
caps := []string{}
|
||||
for c, ok := range net.Network.Capabilities {
|
||||
if ok {
|
||||
caps = append(caps, c)
|
||||
}
|
||||
}
|
||||
if err := c.validatePlugin(ctx, net.Network.Type, net.Network.CNIVersion); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return caps, nil
|
||||
}
|
||||
|
||||
// validatePlugin checks that an individual plugin's configuration is sane
|
||||
func (c *CNIConfig) validatePlugin(ctx context.Context, pluginName, expectedVersion string) error {
|
||||
pluginPath, err := invoke.FindInPath(pluginName, c.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
net, err = injectRuntimeConfig(net, rt)
|
||||
vi, err := invoke.GetVersionInfo(ctx, pluginPath, c.exec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return invoke.ExecPluginWithoutResult(pluginPath, net.Bytes, c.args("DEL", rt))
|
||||
for _, vers := range vi.SupportedVersions() {
|
||||
if vers == expectedVersion {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("plugin %s does not support config version %q", pluginName, expectedVersion)
|
||||
}
|
||||
|
||||
// GetVersionInfo reports which versions of the CNI spec are supported by
|
||||
// the given plugin.
|
||||
func (c *CNIConfig) GetVersionInfo(pluginType string) (version.PluginInfo, error) {
|
||||
pluginPath, err := invoke.FindInPath(pluginType, c.Path)
|
||||
func (c *CNIConfig) GetVersionInfo(ctx context.Context, pluginType string) (version.PluginInfo, error) {
|
||||
c.ensureExec()
|
||||
pluginPath, err := c.exec.FindInPath(pluginType, c.Path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return invoke.GetVersionInfo(pluginPath)
|
||||
return invoke.GetVersionInfo(ctx, pluginPath, c.exec)
|
||||
}
|
||||
|
||||
// =====
|
||||
|
12
vendor/github.com/containernetworking/cni/libcni/conf.go
generated
vendored
12
vendor/github.com/containernetworking/cni/libcni/conf.go
generated
vendored
@ -45,6 +45,9 @@ func ConfFromBytes(bytes []byte) (*NetworkConfig, error) {
|
||||
if err := json.Unmarshal(bytes, &conf.Network); err != nil {
|
||||
return nil, fmt.Errorf("error parsing configuration: %s", err)
|
||||
}
|
||||
if conf.Network.Type == "" {
|
||||
return nil, fmt.Errorf("error parsing configuration: missing 'type'")
|
||||
}
|
||||
return conf, nil
|
||||
}
|
||||
|
||||
@ -80,8 +83,17 @@ func ConfListFromBytes(bytes []byte) (*NetworkConfigList, error) {
|
||||
}
|
||||
}
|
||||
|
||||
disableCheck := false
|
||||
if rawDisableCheck, ok := rawList["disableCheck"]; ok {
|
||||
disableCheck, ok = rawDisableCheck.(bool)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("error parsing configuration list: invalid disableCheck type %T", rawDisableCheck)
|
||||
}
|
||||
}
|
||||
|
||||
list := &NetworkConfigList{
|
||||
Name: name,
|
||||
DisableCheck: disableCheck,
|
||||
CNIVersion: cniVersion,
|
||||
Bytes: bytes,
|
||||
}
|
||||
|
68
vendor/github.com/containernetworking/cni/pkg/invoke/args.go
generated
vendored
68
vendor/github.com/containernetworking/cni/pkg/invoke/args.go
generated
vendored
@ -15,6 +15,7 @@
|
||||
package invoke
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
@ -22,6 +23,8 @@ import (
|
||||
type CNIArgs interface {
|
||||
// For use with os/exec; i.e., return nil to inherit the
|
||||
// environment from this process
|
||||
// For use in delegation; inherit the environment from this
|
||||
// process and allow overrides
|
||||
AsEnv() []string
|
||||
}
|
||||
|
||||
@ -57,17 +60,17 @@ func (args *Args) AsEnv() []string {
|
||||
pluginArgsStr = stringify(args.PluginArgs)
|
||||
}
|
||||
|
||||
// Ensure that the custom values are first, so any value present in
|
||||
// the process environment won't override them.
|
||||
env = append([]string{
|
||||
"CNI_COMMAND=" + args.Command,
|
||||
"CNI_CONTAINERID=" + args.ContainerID,
|
||||
"CNI_NETNS=" + args.NetNS,
|
||||
"CNI_ARGS=" + pluginArgsStr,
|
||||
"CNI_IFNAME=" + args.IfName,
|
||||
"CNI_PATH=" + args.Path,
|
||||
}, env...)
|
||||
return env
|
||||
// Duplicated values which come first will be overrided, so we must put the
|
||||
// custom values in the end to avoid being overrided by the process environments.
|
||||
env = append(env,
|
||||
"CNI_COMMAND="+args.Command,
|
||||
"CNI_CONTAINERID="+args.ContainerID,
|
||||
"CNI_NETNS="+args.NetNS,
|
||||
"CNI_ARGS="+pluginArgsStr,
|
||||
"CNI_IFNAME="+args.IfName,
|
||||
"CNI_PATH="+args.Path,
|
||||
)
|
||||
return dedupEnv(env)
|
||||
}
|
||||
|
||||
// taken from rkt/networking/net_plugin.go
|
||||
@ -80,3 +83,46 @@ func stringify(pluginArgs [][2]string) string {
|
||||
|
||||
return strings.Join(entries, ";")
|
||||
}
|
||||
|
||||
// DelegateArgs implements the CNIArgs interface
|
||||
// used for delegation to inherit from environments
|
||||
// and allow some overrides like CNI_COMMAND
|
||||
var _ CNIArgs = &DelegateArgs{}
|
||||
|
||||
type DelegateArgs struct {
|
||||
Command string
|
||||
}
|
||||
|
||||
func (d *DelegateArgs) AsEnv() []string {
|
||||
env := os.Environ()
|
||||
|
||||
// The custom values should come in the end to override the existing
|
||||
// process environment of the same key.
|
||||
env = append(env,
|
||||
"CNI_COMMAND="+d.Command,
|
||||
)
|
||||
return dedupEnv(env)
|
||||
}
|
||||
|
||||
// dedupEnv returns a copy of env with any duplicates removed, in favor of later values.
|
||||
// Items not of the normal environment "key=value" form are preserved unchanged.
|
||||
func dedupEnv(env []string) []string {
|
||||
out := make([]string, 0, len(env))
|
||||
envMap := map[string]string{}
|
||||
|
||||
for _, kv := range env {
|
||||
// find the first "=" in environment, if not, just keep it
|
||||
eq := strings.Index(kv, "=")
|
||||
if eq < 0 {
|
||||
out = append(out, kv)
|
||||
continue
|
||||
}
|
||||
envMap[kv[:eq]] = kv[eq+1:]
|
||||
}
|
||||
|
||||
for k, v := range envMap {
|
||||
out = append(out, fmt.Sprintf("%s=%s", k, v))
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
57
vendor/github.com/containernetworking/cni/pkg/invoke/delegate.go
generated
vendored
57
vendor/github.com/containernetworking/cni/pkg/invoke/delegate.go
generated
vendored
@ -15,39 +15,66 @@
|
||||
package invoke
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
)
|
||||
|
||||
func DelegateAdd(delegatePlugin string, netconf []byte) (types.Result, error) {
|
||||
if os.Getenv("CNI_COMMAND") != "ADD" {
|
||||
return nil, fmt.Errorf("CNI_COMMAND is not ADD")
|
||||
func delegateCommon(delegatePlugin string, exec Exec) (string, Exec, error) {
|
||||
if exec == nil {
|
||||
exec = defaultExec
|
||||
}
|
||||
|
||||
paths := filepath.SplitList(os.Getenv("CNI_PATH"))
|
||||
pluginPath, err := exec.FindInPath(delegatePlugin, paths)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
pluginPath, err := FindInPath(delegatePlugin, paths)
|
||||
return pluginPath, exec, nil
|
||||
}
|
||||
|
||||
// DelegateAdd calls the given delegate plugin with the CNI ADD action and
|
||||
// JSON configuration
|
||||
func DelegateAdd(ctx context.Context, delegatePlugin string, netconf []byte, exec Exec) (types.Result, error) {
|
||||
pluginPath, realExec, err := delegateCommon(delegatePlugin, exec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ExecPluginWithResult(pluginPath, netconf, ArgsFromEnv())
|
||||
// DelegateAdd will override the original "CNI_COMMAND" env from process with ADD
|
||||
return ExecPluginWithResult(ctx, pluginPath, netconf, delegateArgs("ADD"), realExec)
|
||||
}
|
||||
|
||||
func DelegateDel(delegatePlugin string, netconf []byte) error {
|
||||
if os.Getenv("CNI_COMMAND") != "DEL" {
|
||||
return fmt.Errorf("CNI_COMMAND is not DEL")
|
||||
}
|
||||
|
||||
paths := filepath.SplitList(os.Getenv("CNI_PATH"))
|
||||
|
||||
pluginPath, err := FindInPath(delegatePlugin, paths)
|
||||
// DelegateCheck calls the given delegate plugin with the CNI CHECK action and
|
||||
// JSON configuration
|
||||
func DelegateCheck(ctx context.Context, delegatePlugin string, netconf []byte, exec Exec) error {
|
||||
pluginPath, realExec, err := delegateCommon(delegatePlugin, exec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ExecPluginWithoutResult(pluginPath, netconf, ArgsFromEnv())
|
||||
// DelegateCheck will override the original CNI_COMMAND env from process with CHECK
|
||||
return ExecPluginWithoutResult(ctx, pluginPath, netconf, delegateArgs("CHECK"), realExec)
|
||||
}
|
||||
|
||||
// DelegateDel calls the given delegate plugin with the CNI DEL action and
|
||||
// JSON configuration
|
||||
func DelegateDel(ctx context.Context, delegatePlugin string, netconf []byte, exec Exec) error {
|
||||
pluginPath, realExec, err := delegateCommon(delegatePlugin, exec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// DelegateDel will override the original CNI_COMMAND env from process with DEL
|
||||
return ExecPluginWithoutResult(ctx, pluginPath, netconf, delegateArgs("DEL"), realExec)
|
||||
}
|
||||
|
||||
// return CNIArgs used by delegation
|
||||
func delegateArgs(action string) *DelegateArgs {
|
||||
return &DelegateArgs{
|
||||
Command: action,
|
||||
}
|
||||
}
|
||||
|
109
vendor/github.com/containernetworking/cni/pkg/invoke/exec.go
generated
vendored
109
vendor/github.com/containernetworking/cni/pkg/invoke/exec.go
generated
vendored
@ -15,6 +15,7 @@
|
||||
package invoke
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
@ -22,34 +23,62 @@ import (
|
||||
"github.com/containernetworking/cni/pkg/version"
|
||||
)
|
||||
|
||||
func ExecPluginWithResult(pluginPath string, netconf []byte, args CNIArgs) (types.Result, error) {
|
||||
return defaultPluginExec.WithResult(pluginPath, netconf, args)
|
||||
}
|
||||
|
||||
func ExecPluginWithoutResult(pluginPath string, netconf []byte, args CNIArgs) error {
|
||||
return defaultPluginExec.WithoutResult(pluginPath, netconf, args)
|
||||
}
|
||||
|
||||
func GetVersionInfo(pluginPath string) (version.PluginInfo, error) {
|
||||
return defaultPluginExec.GetVersionInfo(pluginPath)
|
||||
}
|
||||
|
||||
var defaultPluginExec = &PluginExec{
|
||||
RawExec: &RawExec{Stderr: os.Stderr},
|
||||
VersionDecoder: &version.PluginDecoder{},
|
||||
}
|
||||
|
||||
type PluginExec struct {
|
||||
RawExec interface {
|
||||
ExecPlugin(pluginPath string, stdinData []byte, environ []string) ([]byte, error)
|
||||
}
|
||||
VersionDecoder interface {
|
||||
// Exec is an interface encapsulates all operations that deal with finding
|
||||
// and executing a CNI plugin. Tests may provide a fake implementation
|
||||
// to avoid writing fake plugins to temporary directories during the test.
|
||||
type Exec interface {
|
||||
ExecPlugin(ctx context.Context, pluginPath string, stdinData []byte, environ []string) ([]byte, error)
|
||||
FindInPath(plugin string, paths []string) (string, error)
|
||||
Decode(jsonBytes []byte) (version.PluginInfo, error)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *PluginExec) WithResult(pluginPath string, netconf []byte, args CNIArgs) (types.Result, error) {
|
||||
stdoutBytes, err := e.RawExec.ExecPlugin(pluginPath, netconf, args.AsEnv())
|
||||
// For example, a testcase could pass an instance of the following fakeExec
|
||||
// object to ExecPluginWithResult() to verify the incoming stdin and environment
|
||||
// and provide a tailored response:
|
||||
//
|
||||
//import (
|
||||
// "encoding/json"
|
||||
// "path"
|
||||
// "strings"
|
||||
//)
|
||||
//
|
||||
//type fakeExec struct {
|
||||
// version.PluginDecoder
|
||||
//}
|
||||
//
|
||||
//func (f *fakeExec) ExecPlugin(pluginPath string, stdinData []byte, environ []string) ([]byte, error) {
|
||||
// net := &types.NetConf{}
|
||||
// err := json.Unmarshal(stdinData, net)
|
||||
// if err != nil {
|
||||
// return nil, fmt.Errorf("failed to unmarshal configuration: %v", err)
|
||||
// }
|
||||
// pluginName := path.Base(pluginPath)
|
||||
// if pluginName != net.Type {
|
||||
// return nil, fmt.Errorf("plugin name %q did not match config type %q", pluginName, net.Type)
|
||||
// }
|
||||
// for _, e := range environ {
|
||||
// // Check environment for forced failure request
|
||||
// parts := strings.Split(e, "=")
|
||||
// if len(parts) > 0 && parts[0] == "FAIL" {
|
||||
// return nil, fmt.Errorf("failed to execute plugin %s", pluginName)
|
||||
// }
|
||||
// }
|
||||
// return []byte("{\"CNIVersion\":\"0.4.0\"}"), nil
|
||||
//}
|
||||
//
|
||||
//func (f *fakeExec) FindInPath(plugin string, paths []string) (string, error) {
|
||||
// if len(paths) > 0 {
|
||||
// return path.Join(paths[0], plugin), nil
|
||||
// }
|
||||
// return "", fmt.Errorf("failed to find plugin %s in paths %v", plugin, paths)
|
||||
//}
|
||||
|
||||
func ExecPluginWithResult(ctx context.Context, pluginPath string, netconf []byte, args CNIArgs, exec Exec) (types.Result, error) {
|
||||
if exec == nil {
|
||||
exec = defaultExec
|
||||
}
|
||||
|
||||
stdoutBytes, err := exec.ExecPlugin(ctx, pluginPath, netconf, args.AsEnv())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -64,8 +93,11 @@ func (e *PluginExec) WithResult(pluginPath string, netconf []byte, args CNIArgs)
|
||||
return version.NewResult(confVersion, stdoutBytes)
|
||||
}
|
||||
|
||||
func (e *PluginExec) WithoutResult(pluginPath string, netconf []byte, args CNIArgs) error {
|
||||
_, err := e.RawExec.ExecPlugin(pluginPath, netconf, args.AsEnv())
|
||||
func ExecPluginWithoutResult(ctx context.Context, pluginPath string, netconf []byte, args CNIArgs, exec Exec) error {
|
||||
if exec == nil {
|
||||
exec = defaultExec
|
||||
}
|
||||
_, err := exec.ExecPlugin(ctx, pluginPath, netconf, args.AsEnv())
|
||||
return err
|
||||
}
|
||||
|
||||
@ -73,7 +105,10 @@ func (e *PluginExec) WithoutResult(pluginPath string, netconf []byte, args CNIAr
|
||||
// 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) {
|
||||
func GetVersionInfo(ctx context.Context, pluginPath string, exec Exec) (version.PluginInfo, error) {
|
||||
if exec == nil {
|
||||
exec = defaultExec
|
||||
}
|
||||
args := &Args{
|
||||
Command: "VERSION",
|
||||
|
||||
@ -83,7 +118,7 @@ func (e *PluginExec) GetVersionInfo(pluginPath string) (version.PluginInfo, erro
|
||||
Path: "dummy",
|
||||
}
|
||||
stdin := []byte(fmt.Sprintf(`{"cniVersion":%q}`, version.Current()))
|
||||
stdoutBytes, err := e.RawExec.ExecPlugin(pluginPath, stdin, args.AsEnv())
|
||||
stdoutBytes, err := exec.ExecPlugin(ctx, pluginPath, stdin, args.AsEnv())
|
||||
if err != nil {
|
||||
if err.Error() == "unknown CNI_COMMAND: VERSION" {
|
||||
return version.PluginSupports("0.1.0"), nil
|
||||
@ -91,5 +126,19 @@ func (e *PluginExec) GetVersionInfo(pluginPath string) (version.PluginInfo, erro
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return e.VersionDecoder.Decode(stdoutBytes)
|
||||
return exec.Decode(stdoutBytes)
|
||||
}
|
||||
|
||||
// DefaultExec is an object that implements the Exec interface which looks
|
||||
// for and executes plugins from disk.
|
||||
type DefaultExec struct {
|
||||
*RawExec
|
||||
version.PluginDecoder
|
||||
}
|
||||
|
||||
// DefaultExec implements the Exec interface
|
||||
var _ Exec = &DefaultExec{}
|
||||
|
||||
var defaultExec = &DefaultExec{
|
||||
RawExec: &RawExec{Stderr: os.Stderr},
|
||||
}
|
||||
|
2
vendor/github.com/containernetworking/cni/pkg/invoke/os_unix.go
generated
vendored
2
vendor/github.com/containernetworking/cni/pkg/invoke/os_unix.go
generated
vendored
@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build darwin dragonfly freebsd linux netbsd opensbd solaris
|
||||
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
|
||||
package invoke
|
||||
|
||||
|
25
vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go
generated
vendored
25
vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go
generated
vendored
@ -16,6 +16,7 @@ package invoke
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
@ -28,17 +29,13 @@ type RawExec struct {
|
||||
Stderr io.Writer
|
||||
}
|
||||
|
||||
func (e *RawExec) ExecPlugin(pluginPath string, stdinData []byte, environ []string) ([]byte, error) {
|
||||
func (e *RawExec) ExecPlugin(ctx context.Context, pluginPath string, stdinData []byte, environ []string) ([]byte, error) {
|
||||
stdout := &bytes.Buffer{}
|
||||
|
||||
c := exec.Cmd{
|
||||
Env: environ,
|
||||
Path: pluginPath,
|
||||
Args: []string{pluginPath},
|
||||
Stdin: bytes.NewBuffer(stdinData),
|
||||
Stdout: stdout,
|
||||
Stderr: e.Stderr,
|
||||
}
|
||||
c := exec.CommandContext(ctx, pluginPath)
|
||||
c.Env = environ
|
||||
c.Stdin = bytes.NewBuffer(stdinData)
|
||||
c.Stdout = stdout
|
||||
c.Stderr = e.Stderr
|
||||
if err := c.Run(); err != nil {
|
||||
return nil, pluginErr(err, stdout.Bytes())
|
||||
}
|
||||
@ -49,7 +46,9 @@ func (e *RawExec) ExecPlugin(pluginPath string, stdinData []byte, environ []stri
|
||||
func pluginErr(err error, output []byte) error {
|
||||
if _, ok := err.(*exec.ExitError); ok {
|
||||
emsg := types.Error{}
|
||||
if perr := json.Unmarshal(output, &emsg); perr != nil {
|
||||
if len(output) == 0 {
|
||||
emsg.Msg = "netplugin failed with no error message"
|
||||
} else if perr := json.Unmarshal(output, &emsg); perr != nil {
|
||||
emsg.Msg = fmt.Sprintf("netplugin failed but error parsing its diagnostic message %q: %v", string(output), perr)
|
||||
}
|
||||
return &emsg
|
||||
@ -57,3 +56,7 @@ func pluginErr(err error, output []byte) error {
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (e *RawExec) FindInPath(plugin string, paths []string) (string, error) {
|
||||
return FindInPath(plugin, paths)
|
||||
}
|
||||
|
7
vendor/github.com/containernetworking/cni/pkg/types/020/types.go
generated
vendored
7
vendor/github.com/containernetworking/cni/pkg/types/020/types.go
generated
vendored
@ -17,6 +17,7 @@ package types020
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
@ -73,11 +74,15 @@ func (r *Result) GetAsVersion(version string) (types.Result, error) {
|
||||
}
|
||||
|
||||
func (r *Result) Print() error {
|
||||
return r.PrintTo(os.Stdout)
|
||||
}
|
||||
|
||||
func (r *Result) PrintTo(writer io.Writer) error {
|
||||
data, err := json.MarshalIndent(r, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = os.Stdout.Write(data)
|
||||
_, err = writer.Write(data)
|
||||
return err
|
||||
}
|
||||
|
||||
|
29
vendor/github.com/containernetworking/cni/pkg/types/current/types.go
generated
vendored
29
vendor/github.com/containernetworking/cni/pkg/types/current/types.go
generated
vendored
@ -17,6 +17,7 @@ package current
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
@ -24,9 +25,9 @@ import (
|
||||
"github.com/containernetworking/cni/pkg/types/020"
|
||||
)
|
||||
|
||||
const ImplementedSpecVersion string = "0.3.1"
|
||||
const ImplementedSpecVersion string = "0.4.0"
|
||||
|
||||
var SupportedVersions = []string{"0.3.0", ImplementedSpecVersion}
|
||||
var SupportedVersions = []string{"0.3.0", "0.3.1", ImplementedSpecVersion}
|
||||
|
||||
func NewResult(data []byte) (types.Result, error) {
|
||||
result := &Result{}
|
||||
@ -75,13 +76,9 @@ func convertFrom020(result types.Result) (*Result, error) {
|
||||
Gateway: oldResult.IP4.Gateway,
|
||||
})
|
||||
for _, route := range oldResult.IP4.Routes {
|
||||
gw := route.GW
|
||||
if gw == nil {
|
||||
gw = oldResult.IP4.Gateway
|
||||
}
|
||||
newResult.Routes = append(newResult.Routes, &types.Route{
|
||||
Dst: route.Dst,
|
||||
GW: gw,
|
||||
GW: route.GW,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -93,21 +90,13 @@ func convertFrom020(result types.Result) (*Result, error) {
|
||||
Gateway: oldResult.IP6.Gateway,
|
||||
})
|
||||
for _, route := range oldResult.IP6.Routes {
|
||||
gw := route.GW
|
||||
if gw == nil {
|
||||
gw = oldResult.IP6.Gateway
|
||||
}
|
||||
newResult.Routes = append(newResult.Routes, &types.Route{
|
||||
Dst: route.Dst,
|
||||
GW: gw,
|
||||
GW: route.GW,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if len(newResult.IPs) == 0 {
|
||||
return nil, fmt.Errorf("cannot convert: no valid IP addresses")
|
||||
}
|
||||
|
||||
return newResult, nil
|
||||
}
|
||||
|
||||
@ -196,7 +185,7 @@ func (r *Result) Version() string {
|
||||
|
||||
func (r *Result) GetAsVersion(version string) (types.Result, error) {
|
||||
switch version {
|
||||
case "0.3.0", ImplementedSpecVersion:
|
||||
case "0.3.0", "0.3.1", ImplementedSpecVersion:
|
||||
r.CNIVersion = version
|
||||
return r, nil
|
||||
case types020.SupportedVersions[0], types020.SupportedVersions[1], types020.SupportedVersions[2]:
|
||||
@ -206,11 +195,15 @@ func (r *Result) GetAsVersion(version string) (types.Result, error) {
|
||||
}
|
||||
|
||||
func (r *Result) Print() error {
|
||||
return r.PrintTo(os.Stdout)
|
||||
}
|
||||
|
||||
func (r *Result) PrintTo(writer io.Writer) error {
|
||||
data, err := json.MarshalIndent(r, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = os.Stdout.Write(data)
|
||||
_, err = writer.Write(data)
|
||||
return err
|
||||
}
|
||||
|
||||
|
20
vendor/github.com/containernetworking/cni/pkg/types/types.go
generated
vendored
20
vendor/github.com/containernetworking/cni/pkg/types/types.go
generated
vendored
@ -18,6 +18,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
)
|
||||
@ -63,10 +64,15 @@ type NetConf struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
Capabilities map[string]bool `json:"capabilities,omitempty"`
|
||||
IPAM struct {
|
||||
Type string `json:"type,omitempty"`
|
||||
} `json:"ipam,omitempty"`
|
||||
IPAM IPAM `json:"ipam,omitempty"`
|
||||
DNS DNS `json:"dns"`
|
||||
|
||||
RawPrevResult map[string]interface{} `json:"prevResult,omitempty"`
|
||||
PrevResult Result `json:"-"`
|
||||
}
|
||||
|
||||
type IPAM struct {
|
||||
Type string `json:"type,omitempty"`
|
||||
}
|
||||
|
||||
// NetConfList describes an ordered list of networks.
|
||||
@ -74,6 +80,7 @@ type NetConfList struct {
|
||||
CNIVersion string `json:"cniVersion,omitempty"`
|
||||
|
||||
Name string `json:"name,omitempty"`
|
||||
DisableCheck bool `json:"disableCheck,omitempty"`
|
||||
Plugins []*NetConf `json:"plugins,omitempty"`
|
||||
}
|
||||
|
||||
@ -81,7 +88,7 @@ type ResultFactoryFunc func([]byte) (Result, error)
|
||||
|
||||
// Result is an interface that provides the result of plugin execution
|
||||
type Result interface {
|
||||
// The highest CNI specification result verison the result supports
|
||||
// The highest CNI specification result version the result supports
|
||||
// without having to convert
|
||||
Version() string
|
||||
|
||||
@ -92,6 +99,9 @@ type Result interface {
|
||||
// Prints the result in JSON format to stdout
|
||||
Print() error
|
||||
|
||||
// Prints the result in JSON format to provided writer
|
||||
PrintTo(writer io.Writer) error
|
||||
|
||||
// Returns a JSON string representation of the result
|
||||
String() string
|
||||
}
|
||||
@ -167,7 +177,7 @@ func (r *Route) UnmarshalJSON(data []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Route) MarshalJSON() ([]byte, error) {
|
||||
func (r Route) MarshalJSON() ([]byte, error) {
|
||||
rt := route{
|
||||
Dst: IPNet(r.Dst),
|
||||
GW: r.GW,
|
||||
|
63
vendor/github.com/containernetworking/cni/pkg/version/plugin.go
generated
vendored
63
vendor/github.com/containernetworking/cni/pkg/version/plugin.go
generated
vendored
@ -18,6 +18,8 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// PluginInfo reports information about CNI versioning
|
||||
@ -79,3 +81,64 @@ func (*PluginDecoder) Decode(jsonBytes []byte) (PluginInfo, error) {
|
||||
}
|
||||
return &info, nil
|
||||
}
|
||||
|
||||
// ParseVersion parses a version string like "3.0.1" or "0.4.5" into major,
|
||||
// minor, and micro numbers or returns an error
|
||||
func ParseVersion(version string) (int, int, int, error) {
|
||||
var major, minor, micro int
|
||||
if version == "" {
|
||||
return -1, -1, -1, fmt.Errorf("invalid version %q: the version is empty", version)
|
||||
}
|
||||
|
||||
parts := strings.Split(version, ".")
|
||||
if len(parts) >= 4 {
|
||||
return -1, -1, -1, fmt.Errorf("invalid version %q: too many parts", version)
|
||||
}
|
||||
|
||||
major, err := strconv.Atoi(parts[0])
|
||||
if err != nil {
|
||||
return -1, -1, -1, fmt.Errorf("failed to convert major version part %q: %v", parts[0], err)
|
||||
}
|
||||
|
||||
if len(parts) >= 2 {
|
||||
minor, err = strconv.Atoi(parts[1])
|
||||
if err != nil {
|
||||
return -1, -1, -1, fmt.Errorf("failed to convert minor version part %q: %v", parts[1], err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(parts) >= 3 {
|
||||
micro, err = strconv.Atoi(parts[2])
|
||||
if err != nil {
|
||||
return -1, -1, -1, fmt.Errorf("failed to convert micro version part %q: %v", parts[2], err)
|
||||
}
|
||||
}
|
||||
|
||||
return major, minor, micro, nil
|
||||
}
|
||||
|
||||
// GreaterThanOrEqualTo takes two string versions, parses them into major/minor/micro
|
||||
// numbers, and compares them to determine whether the first version is greater
|
||||
// than or equal to the second
|
||||
func GreaterThanOrEqualTo(version, otherVersion string) (bool, error) {
|
||||
firstMajor, firstMinor, firstMicro, err := ParseVersion(version)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
secondMajor, secondMinor, secondMicro, err := ParseVersion(otherVersion)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if firstMajor > secondMajor {
|
||||
return true, nil
|
||||
} else if firstMajor == secondMajor {
|
||||
if firstMinor > secondMinor {
|
||||
return true, nil
|
||||
} else if firstMinor == secondMinor && firstMicro >= secondMicro {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
26
vendor/github.com/containernetworking/cni/pkg/version/version.go
generated
vendored
26
vendor/github.com/containernetworking/cni/pkg/version/version.go
generated
vendored
@ -15,6 +15,7 @@
|
||||
package version
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
@ -24,7 +25,7 @@ import (
|
||||
|
||||
// Current reports the version of the CNI spec implemented by this library
|
||||
func Current() string {
|
||||
return "0.3.1"
|
||||
return "0.4.0"
|
||||
}
|
||||
|
||||
// Legacy PluginInfo describes a plugin that is backwards compatible with the
|
||||
@ -35,7 +36,7 @@ func Current() string {
|
||||
// Any future CNI spec versions which meet this definition should be added to
|
||||
// this list.
|
||||
var Legacy = PluginSupports("0.1.0", "0.2.0")
|
||||
var All = PluginSupports("0.1.0", "0.2.0", "0.3.0", "0.3.1")
|
||||
var All = PluginSupports("0.1.0", "0.2.0", "0.3.0", "0.3.1", "0.4.0")
|
||||
|
||||
var resultFactories = []struct {
|
||||
supportedVersions []string
|
||||
@ -59,3 +60,24 @@ func NewResult(version string, resultBytes []byte) (types.Result, error) {
|
||||
|
||||
return nil, fmt.Errorf("unsupported CNI result version %q", version)
|
||||
}
|
||||
|
||||
// ParsePrevResult parses a prevResult in a NetConf structure and sets
|
||||
// the NetConf's PrevResult member to the parsed Result object.
|
||||
func ParsePrevResult(conf *types.NetConf) error {
|
||||
if conf.RawPrevResult == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
resultBytes, err := json.Marshal(conf.RawPrevResult)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not serialize prevResult: %v", err)
|
||||
}
|
||||
|
||||
conf.RawPrevResult = nil
|
||||
conf.PrevResult, err = NewResult(conf.CNIVersion, resultBytes)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse prevResult: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user