From af83d3e1f7c26ea409c827daa5fb5873a50e8e90 Mon Sep 17 00:00:00 2001 From: Lantao Liu Date: Wed, 23 Aug 2017 01:23:24 +0000 Subject: [PATCH 1/3] Update CNI to v0.6.0 Signed-off-by: Lantao Liu --- hack/versions | 2 +- .../containernetworking/cni/README.md | 57 ++-- .../containernetworking/cni/libcni/api.go | 135 +++++++- .../containernetworking/cni/libcni/conf.go | 173 +++++++++- .../cni/pkg/invoke/args.go | 17 +- .../cni/pkg/invoke/delegate.go | 8 +- .../cni/pkg/invoke/exec.go | 16 +- .../cni/pkg/invoke/find.go | 16 +- .../cni/pkg/invoke/os_unix.go | 20 ++ .../cni/pkg/invoke/os_windows.go | 18 ++ .../cni/pkg/invoke/raw_exec.go | 8 +- .../cni/pkg/types/020/types.go | 135 ++++++++ .../containernetworking/cni/pkg/types/args.go | 15 +- .../cni/pkg/types/current/types.go | 300 ++++++++++++++++++ .../cni/pkg/types/types.go | 102 +++--- .../cni/pkg/version/reconcile.go | 20 +- .../cni/pkg/version/version.go | 34 +- 17 files changed, 935 insertions(+), 141 deletions(-) create mode 100644 vendor/github.com/containernetworking/cni/pkg/invoke/os_unix.go create mode 100644 vendor/github.com/containernetworking/cni/pkg/invoke/os_windows.go create mode 100644 vendor/github.com/containernetworking/cni/pkg/types/020/types.go create mode 100644 vendor/github.com/containernetworking/cni/pkg/types/current/types.go diff --git a/hack/versions b/hack/versions index eba720f4a..8351268f9 100644 --- a/hack/versions +++ b/hack/versions @@ -1,5 +1,5 @@ RUNC_VERSION=e775f0fba3ea329b8b766451c892c41a3d49594d -CNI_VERSION=v0.4.0 +CNI_VERSION=v0.6.0 CONTAINERD_VERSION=938810e706bbcdbcb937ce63ba3e7c9ca329af64 CRITEST_VERSION=74bbd4e142f752f13c648d9dde23defed3e472a2 KUBERNETES_VERSION=493ee8b28560c118cebd2165ba9ef0959cfa2bc3 diff --git a/vendor/github.com/containernetworking/cni/README.md b/vendor/github.com/containernetworking/cni/README.md index 27f08506b..793187c79 100644 --- a/vendor/github.com/containernetworking/cni/README.md +++ b/vendor/github.com/containernetworking/cni/README.md @@ -2,15 +2,25 @@ [![Coverage Status](https://coveralls.io/repos/github/containernetworking/cni/badge.svg?branch=master)](https://coveralls.io/github/containernetworking/cni?branch=master) [![Slack Status](https://cryptic-tundra-43194.herokuapp.com/badge.svg)](https://cryptic-tundra-43194.herokuapp.com/) +![CNI Logo](logo.png) + +--- + +# 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). + +--- + # CNI - the Container Network Interface ## What is CNI? -The CNI (_Container Network Interface_) project consists of a specification and libraries for writing plugins to configure network interfaces in Linux containers, along with a number of supported plugins. +CNI (_Container Network Interface_), a [Cloud Native Computing Foundation](https://cncf.io) project, consists of a specification and libraries for writing plugins to configure network interfaces in Linux containers, along with a number of supported plugins. CNI concerns itself only with network connectivity of containers and removing allocated resources when the container is deleted. Because of this focus, CNI has a wide range of support and the specification is simple to implement. -As well as the [specification](SPEC.md), this repository contains the Go source code of a library for integrating CNI into applications, an example command-line tool, a template for making new plugins, and the supported plugins. +As well as the [specification](SPEC.md), this repository contains the Go source code of a [library for integrating CNI into applications](libcni) and an [example command-line tool](cnitool) for executing CNI plugins. A [separate repository contains reference plugins](https://github.com/containernetworking/plugins) and a template for making new plugins. The template code makes it straight-forward to create a CNI plugin for an existing container networking project. CNI also makes a good framework for creating a new container networking project from scratch. @@ -27,7 +37,8 @@ To avoid duplication, we think it is prudent to define a common interface betwee - [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/) -- [Cloud Foundry - a platform for cloud applications](https://github.com/cloudfoundry-incubator/netman-release) +- [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) ### 3rd party plugins @@ -37,8 +48,14 @@ To avoid duplication, we think it is prudent to define a common interface betwee - [SR-IOV](https://github.com/hustcat/sriov-cni) - [Cilium - BPF & XDP for containers](https://github.com/cilium/cilium) - [Infoblox - enterprise IP address management for containers](https://github.com/infobloxopen/cni-infoblox) +- [Multus - a Multi plugin](https://github.com/Intel-Corp/multus-cni) +- [Romana - Layer 3 CNI plugin supporting network policy for Kubernetes](https://github.com/romana/kube) +- [CNI-Genie - generic CNI network plugin](https://github.com/Huawei-PaaS/CNI-Genie) +- [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) -The CNI team also maintains some [core plugins](plugins). +The CNI team also maintains some [core plugins in a separate repository](https://github.com/containernetworking/plugins). ## Contributing to CNI @@ -50,19 +67,16 @@ If you intend to contribute to code or documentation, please read [CONTRIBUTING. ### Requirements -CNI requires Go 1.5+ to build. +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. -Go 1.5 users will need to set GO15VENDOREXPERIMENT=1 to get vendored -dependencies. This flag is set by default in 1.6. +### Reference Plugins -### Included Plugins - -This repository includes a number of common plugins in the `plugins/` directory. -Please see the [Documentation/](Documentation/) directory for documentation about particular plugins. +The CNI project maintains a set of [reference plugins](https://github.com/containernetworking/plugins) that implement the CNI specification. +NOTE: the reference plugins used to live in this repository but have been split out into a [separate repository](https://github.com/containernetworking/plugins) as of May 2017. ### Running the plugins -The scripts/ directory contains two scripts, `priv-net-run.sh` and `docker-run.sh`, that can be used to exercise the plugins. +After building and installing the [reference plugins](https://github.com/containernetworking/plugins), you can use the `priv-net-run.sh` and `docker-run.sh` scripts in the `scripts/` directory to exercise the plugins. **note - priv-net-run.sh depends on `jq`** @@ -100,14 +114,15 @@ The directory `/etc/cni/net.d` is the default location in which the scripts will Next, build the plugins: ```bash -$ ./build +$ cd $GOPATH/src/github.com/containernetworking/plugins +$ ./build.sh ``` Finally, execute a command (`ifconfig` in this example) in a private network namespace that has joined the `mynet` network: ```bash -$ CNI_PATH=`pwd`/bin -$ cd scripts +$ CNI_PATH=$GOPATH/src/github.com/containernetworking/plugins/bin +$ cd $GOPATH/src/github.com/containernetworking/cni/scripts $ sudo CNI_PATH=$CNI_PATH ./priv-net-run.sh ifconfig eth0 Link encap:Ethernet HWaddr f2:c2:6f:54:b8:2b inet addr:10.22.0.2 Bcast:0.0.0.0 Mask:255.255.0.0 @@ -115,7 +130,7 @@ eth0 Link encap:Ethernet HWaddr f2:c2:6f:54:b8:2b UP BROADCAST MULTICAST MTU:1500 Metric:1 RX packets:1 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:1 overruns:0 carrier:0 - collisions:0 txqueuelen:0 + collisions:0 txqueuelen:0 RX bytes:90 (90.0 B) TX bytes:0 (0.0 B) lo Link encap:Local Loopback @@ -124,7 +139,7 @@ lo Link encap:Local Loopback UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:0 + collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) ``` @@ -136,8 +151,8 @@ Use the instructions in the previous section to define a netconf and build the p Next, docker-run.sh script wraps `docker run`, to execute the plugins prior to entering the container: ```bash -$ CNI_PATH=`pwd`/bin -$ cd scripts +$ CNI_PATH=$GOPATH/src/github.com/containernetworking/plugins/bin +$ cd $GOPATH/src/github.com/containernetworking/cni/scripts $ sudo CNI_PATH=$CNI_PATH ./docker-run.sh --rm busybox:latest ifconfig eth0 Link encap:Ethernet HWaddr fa:60:70:aa:07:d1 inet addr:10.22.0.2 Bcast:0.0.0.0 Mask:255.255.0.0 @@ -145,7 +160,7 @@ eth0 Link encap:Ethernet HWaddr fa:60:70:aa:07:d1 UP BROADCAST MULTICAST MTU:1500 Metric:1 RX packets:1 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:1 overruns:0 carrier:0 - collisions:0 txqueuelen:0 + collisions:0 txqueuelen:0 RX bytes:90 (90.0 B) TX bytes:0 (0.0 B) lo Link encap:Local Loopback @@ -154,7 +169,7 @@ lo Link encap:Local Loopback UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:0 + collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) ``` diff --git a/vendor/github.com/containernetworking/cni/libcni/api.go b/vendor/github.com/containernetworking/cni/libcni/api.go index dfc30cab1..a23cbb2c5 100644 --- a/vendor/github.com/containernetworking/cni/libcni/api.go +++ b/vendor/github.com/containernetworking/cni/libcni/api.go @@ -15,6 +15,7 @@ package libcni import ( + "os" "strings" "github.com/containernetworking/cni/pkg/invoke" @@ -27,6 +28,12 @@ type RuntimeConf struct { NetNS string IfName string Args [][2]string + // A dictionary of capability-specific data passed by the runtime + // to plugins as top-level keys in the 'runtimeConfig' dictionary + // of the plugin's stdin data. libcni will ensure that only keys + // in this map which match the capabilities of the plugin are passed + // to the plugin + CapabilityArgs map[string]interface{} } type NetworkConfig struct { @@ -34,8 +41,18 @@ type NetworkConfig struct { Bytes []byte } +type NetworkConfigList struct { + Name string + CNIVersion string + Plugins []*NetworkConfig + Bytes []byte +} + type CNI interface { - AddNetwork(net *NetworkConfig, rt *RuntimeConf) (*types.Result, error) + AddNetworkList(net *NetworkConfigList, rt *RuntimeConf) (types.Result, error) + DelNetworkList(net *NetworkConfigList, rt *RuntimeConf) error + + AddNetwork(net *NetworkConfig, rt *RuntimeConf) (types.Result, error) DelNetwork(net *NetworkConfig, rt *RuntimeConf) error } @@ -46,13 +63,120 @@ type CNIConfig struct { // CNIConfig implements the CNI interface var _ CNI = &CNIConfig{} +func buildOneConfig(list *NetworkConfigList, orig *NetworkConfig, prevResult types.Result, rt *RuntimeConf) (*NetworkConfig, error) { + var err error + + inject := map[string]interface{}{ + "name": list.Name, + "cniVersion": list.CNIVersion, + } + // Add previous plugin result + if prevResult != nil { + inject["prevResult"] = prevResult + } + + // Ensure every config uses the same name and version + orig, err = InjectConf(orig, inject) + if err != nil { + return nil, err + } + + return injectRuntimeConfig(orig, rt) +} + +// This function takes a libcni RuntimeConf structure and injects values into +// a "runtimeConfig" dictionary in the CNI network configuration JSON that +// will be passed to the plugin on stdin. +// +// Only "capabilities arguments" passed by the runtime are currently injected. +// 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 +// 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. +func injectRuntimeConfig(orig *NetworkConfig, rt *RuntimeConf) (*NetworkConfig, error) { + var err error + + rc := make(map[string]interface{}) + for capability, supported := range orig.Network.Capabilities { + if !supported { + continue + } + if data, ok := rt.CapabilityArgs[capability]; ok { + rc[capability] = data + } + } + + if len(rc) > 0 { + orig, err = InjectConf(orig, map[string]interface{}{"runtimeConfig": rc}) + if err != nil { + return nil, err + } + } + + 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 + } + } + + return prevResult, nil +} + +// 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] + + pluginPath, err := invoke.FindInPath(net.Network.Type, c.Path) + if err != nil { + return err + } + + newConf, err := buildOneConfig(list, net, nil, rt) + if err != nil { + return err + } + + if err := invoke.ExecPluginWithoutResult(pluginPath, newConf.Bytes, c.args("DEL", rt)); err != nil { + return err + } + } + + return nil +} + // AddNetwork executes the plugin with the ADD command -func (c *CNIConfig) AddNetwork(net *NetworkConfig, rt *RuntimeConf) (*types.Result, error) { +func (c *CNIConfig) AddNetwork(net *NetworkConfig, rt *RuntimeConf) (types.Result, error) { pluginPath, err := invoke.FindInPath(net.Network.Type, c.Path) if err != nil { return nil, err } + net, err = injectRuntimeConfig(net, rt) + if err != nil { + return nil, err + } + return invoke.ExecPluginWithResult(pluginPath, net.Bytes, c.args("ADD", rt)) } @@ -63,6 +187,11 @@ func (c *CNIConfig) DelNetwork(net *NetworkConfig, rt *RuntimeConf) error { return err } + net, err = injectRuntimeConfig(net, rt) + if err != nil { + return err + } + return invoke.ExecPluginWithoutResult(pluginPath, net.Bytes, c.args("DEL", rt)) } @@ -85,6 +214,6 @@ func (c *CNIConfig) args(action string, rt *RuntimeConf) *invoke.Args { NetNS: rt.NetNS, PluginArgs: rt.Args, IfName: rt.IfName, - Path: strings.Join(c.Path, ":"), + Path: strings.Join(c.Path, string(os.PathListSeparator)), } } diff --git a/vendor/github.com/containernetworking/cni/libcni/conf.go b/vendor/github.com/containernetworking/cni/libcni/conf.go index 708686e69..c7738c665 100644 --- a/vendor/github.com/containernetworking/cni/libcni/conf.go +++ b/vendor/github.com/containernetworking/cni/libcni/conf.go @@ -23,6 +23,23 @@ import ( "sort" ) +type NotFoundError struct { + Dir string + Name string +} + +func (e NotFoundError) Error() string { + return fmt.Sprintf(`no net configuration with name "%s" in %s`, e.Name, e.Dir) +} + +type NoConfigsFoundError struct { + Dir string +} + +func (e NoConfigsFoundError) Error() string { + return fmt.Sprintf(`no net configurations found in %s`, e.Dir) +} + func ConfFromBytes(bytes []byte) (*NetworkConfig, error) { conf := &NetworkConfig{Bytes: bytes} if err := json.Unmarshal(bytes, &conf.Network); err != nil { @@ -39,7 +56,73 @@ func ConfFromFile(filename string) (*NetworkConfig, error) { return ConfFromBytes(bytes) } -func ConfFiles(dir string) ([]string, error) { +func ConfListFromBytes(bytes []byte) (*NetworkConfigList, error) { + rawList := make(map[string]interface{}) + if err := json.Unmarshal(bytes, &rawList); err != nil { + return nil, fmt.Errorf("error parsing configuration list: %s", err) + } + + rawName, ok := rawList["name"] + if !ok { + return nil, fmt.Errorf("error parsing configuration list: no name") + } + name, ok := rawName.(string) + if !ok { + return nil, fmt.Errorf("error parsing configuration list: invalid name type %T", rawName) + } + + var cniVersion string + rawVersion, ok := rawList["cniVersion"] + if ok { + cniVersion, ok = rawVersion.(string) + if !ok { + return nil, fmt.Errorf("error parsing configuration list: invalid cniVersion type %T", rawVersion) + } + } + + list := &NetworkConfigList{ + Name: name, + CNIVersion: cniVersion, + Bytes: bytes, + } + + var plugins []interface{} + plug, ok := rawList["plugins"] + if !ok { + return nil, fmt.Errorf("error parsing configuration list: no 'plugins' key") + } + plugins, ok = plug.([]interface{}) + if !ok { + return nil, fmt.Errorf("error parsing configuration list: invalid 'plugins' type %T", plug) + } + if len(plugins) == 0 { + return nil, fmt.Errorf("error parsing configuration list: no plugins in list") + } + + for i, conf := range plugins { + newBytes, err := json.Marshal(conf) + if err != nil { + return nil, fmt.Errorf("Failed to marshal plugin config %d: %v", i, err) + } + netConf, err := ConfFromBytes(newBytes) + if err != nil { + return nil, fmt.Errorf("Failed to parse plugin config %d: %v", i, err) + } + list.Plugins = append(list.Plugins, netConf) + } + + return list, nil +} + +func ConfListFromFile(filename string) (*NetworkConfigList, error) { + bytes, err := ioutil.ReadFile(filename) + if err != nil { + return nil, fmt.Errorf("error reading %s: %s", filename, err) + } + return ConfListFromBytes(bytes) +} + +func ConfFiles(dir string, extensions []string) ([]string, error) { // In part, adapted from rkt/networking/podenv.go#listFiles files, err := ioutil.ReadDir(dir) switch { @@ -56,20 +139,22 @@ func ConfFiles(dir string) ([]string, error) { continue } fileExt := filepath.Ext(f.Name()) - if fileExt == ".conf" || fileExt == ".json" { - confFiles = append(confFiles, filepath.Join(dir, f.Name())) + for _, ext := range extensions { + if fileExt == ext { + confFiles = append(confFiles, filepath.Join(dir, f.Name())) + } } } return confFiles, nil } func LoadConf(dir, name string) (*NetworkConfig, error) { - files, err := ConfFiles(dir) + files, err := ConfFiles(dir, []string{".conf", ".json"}) switch { case err != nil: return nil, err case len(files) == 0: - return nil, fmt.Errorf("no net configurations found") + return nil, NoConfigsFoundError{Dir: dir} } sort.Strings(files) @@ -82,25 +167,59 @@ func LoadConf(dir, name string) (*NetworkConfig, error) { return conf, nil } } - return nil, fmt.Errorf(`no net configuration with name "%s" in %s`, name, dir) + return nil, NotFoundError{dir, name} } -func InjectConf(original *NetworkConfig, key string, newValue interface{}) (*NetworkConfig, error) { +func LoadConfList(dir, name string) (*NetworkConfigList, error) { + files, err := ConfFiles(dir, []string{".conflist"}) + if err != nil { + return nil, err + } + sort.Strings(files) + + for _, confFile := range files { + conf, err := ConfListFromFile(confFile) + if err != nil { + return nil, err + } + if conf.Name == name { + return conf, nil + } + } + + // Try and load a network configuration file (instead of list) + // from the same name, then upconvert. + singleConf, err := LoadConf(dir, name) + if err != nil { + // A little extra logic so the error makes sense + if _, ok := err.(NoConfigsFoundError); len(files) != 0 && ok { + // Config lists found but no config files found + return nil, NotFoundError{dir, name} + } + + return nil, err + } + return ConfListFromConf(singleConf) +} + +func InjectConf(original *NetworkConfig, newValues map[string]interface{}) (*NetworkConfig, error) { config := make(map[string]interface{}) err := json.Unmarshal(original.Bytes, &config) if err != nil { return nil, fmt.Errorf("unmarshal existing network bytes: %s", err) } - if key == "" { - return nil, fmt.Errorf("key value can not be empty") - } + for key, value := range newValues { + if key == "" { + return nil, fmt.Errorf("keys cannot be empty") + } - if newValue == nil { - return nil, fmt.Errorf("newValue must be specified") - } + if value == nil { + return nil, fmt.Errorf("key '%s' value must not be nil", key) + } - config[key] = newValue + config[key] = value + } newBytes, err := json.Marshal(config) if err != nil { @@ -109,3 +228,29 @@ func InjectConf(original *NetworkConfig, key string, newValue interface{}) (*Net return ConfFromBytes(newBytes) } + +// ConfListFromConf "upconverts" a network config in to a NetworkConfigList, +// with the single network as the only entry in the list. +func ConfListFromConf(original *NetworkConfig) (*NetworkConfigList, error) { + // Re-deserialize the config's json, then make a raw map configlist. + // This may seem a bit strange, but it's to make the Bytes fields + // actually make sense. Otherwise, the generated json is littered with + // golang default values. + + rawConfig := make(map[string]interface{}) + if err := json.Unmarshal(original.Bytes, &rawConfig); err != nil { + return nil, err + } + + rawConfigList := map[string]interface{}{ + "name": original.Network.Name, + "cniVersion": original.Network.CNIVersion, + "plugins": []interface{}{rawConfig}, + } + + b, err := json.Marshal(rawConfigList) + if err != nil { + return nil, err + } + return ConfListFromBytes(b) +} diff --git a/vendor/github.com/containernetworking/cni/pkg/invoke/args.go b/vendor/github.com/containernetworking/cni/pkg/invoke/args.go index ba9d0c3b8..39b639723 100644 --- a/vendor/github.com/containernetworking/cni/pkg/invoke/args.go +++ b/vendor/github.com/containernetworking/cni/pkg/invoke/args.go @@ -57,13 +57,16 @@ func (args *Args) AsEnv() []string { pluginArgsStr = stringify(args.PluginArgs) } - 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) + // 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 } diff --git a/vendor/github.com/containernetworking/cni/pkg/invoke/delegate.go b/vendor/github.com/containernetworking/cni/pkg/invoke/delegate.go index ddf1d1727..c78a69eeb 100644 --- a/vendor/github.com/containernetworking/cni/pkg/invoke/delegate.go +++ b/vendor/github.com/containernetworking/cni/pkg/invoke/delegate.go @@ -17,17 +17,17 @@ package invoke import ( "fmt" "os" - "strings" + "path/filepath" "github.com/containernetworking/cni/pkg/types" ) -func DelegateAdd(delegatePlugin string, netconf []byte) (*types.Result, error) { +func DelegateAdd(delegatePlugin string, netconf []byte) (types.Result, error) { if os.Getenv("CNI_COMMAND") != "ADD" { return nil, fmt.Errorf("CNI_COMMAND is not ADD") } - paths := strings.Split(os.Getenv("CNI_PATH"), ":") + paths := filepath.SplitList(os.Getenv("CNI_PATH")) pluginPath, err := FindInPath(delegatePlugin, paths) if err != nil { @@ -42,7 +42,7 @@ func DelegateDel(delegatePlugin string, netconf []byte) error { return fmt.Errorf("CNI_COMMAND is not DEL") } - paths := strings.Split(os.Getenv("CNI_PATH"), ":") + paths := filepath.SplitList(os.Getenv("CNI_PATH")) pluginPath, err := FindInPath(delegatePlugin, paths) if err != nil { diff --git a/vendor/github.com/containernetworking/cni/pkg/invoke/exec.go b/vendor/github.com/containernetworking/cni/pkg/invoke/exec.go index 167d38f5a..fc47e7c82 100644 --- a/vendor/github.com/containernetworking/cni/pkg/invoke/exec.go +++ b/vendor/github.com/containernetworking/cni/pkg/invoke/exec.go @@ -15,7 +15,6 @@ package invoke import ( - "encoding/json" "fmt" "os" @@ -23,7 +22,7 @@ import ( "github.com/containernetworking/cni/pkg/version" ) -func ExecPluginWithResult(pluginPath string, netconf []byte, args CNIArgs) (*types.Result, error) { +func ExecPluginWithResult(pluginPath string, netconf []byte, args CNIArgs) (types.Result, error) { return defaultPluginExec.WithResult(pluginPath, netconf, args) } @@ -49,15 +48,20 @@ type PluginExec struct { } } -func (e *PluginExec) WithResult(pluginPath string, netconf []byte, args CNIArgs) (*types.Result, error) { +func (e *PluginExec) WithResult(pluginPath string, netconf []byte, args CNIArgs) (types.Result, error) { stdoutBytes, err := e.RawExec.ExecPlugin(pluginPath, netconf, args.AsEnv()) if err != nil { return nil, err } - res := &types.Result{} - err = json.Unmarshal(stdoutBytes, res) - return res, err + // Plugin must return result in same version as specified in netconf + versionDecoder := &version.ConfigDecoder{} + confVersion, err := versionDecoder.Decode(netconf) + if err != nil { + return nil, err + } + + return version.NewResult(confVersion, stdoutBytes) } func (e *PluginExec) WithoutResult(pluginPath string, netconf []byte, args CNIArgs) error { diff --git a/vendor/github.com/containernetworking/cni/pkg/invoke/find.go b/vendor/github.com/containernetworking/cni/pkg/invoke/find.go index 3b0379071..e815404c8 100644 --- a/vendor/github.com/containernetworking/cni/pkg/invoke/find.go +++ b/vendor/github.com/containernetworking/cni/pkg/invoke/find.go @@ -30,18 +30,14 @@ func FindInPath(plugin string, paths []string) (string, error) { return "", fmt.Errorf("no paths provided") } - var fullpath string for _, path := range paths { - full := filepath.Join(path, plugin) - if fi, err := os.Stat(full); err == nil && fi.Mode().IsRegular() { - fullpath = full - break + for _, fe := range ExecutableFileExtensions { + fullpath := filepath.Join(path, plugin) + fe + if fi, err := os.Stat(fullpath); err == nil && fi.Mode().IsRegular() { + return fullpath, nil + } } } - if fullpath == "" { - return "", fmt.Errorf("failed to find plugin %q in path %s", plugin, paths) - } - - return fullpath, nil + return "", fmt.Errorf("failed to find plugin %q in path %s", plugin, paths) } diff --git a/vendor/github.com/containernetworking/cni/pkg/invoke/os_unix.go b/vendor/github.com/containernetworking/cni/pkg/invoke/os_unix.go new file mode 100644 index 000000000..bab5737a9 --- /dev/null +++ b/vendor/github.com/containernetworking/cni/pkg/invoke/os_unix.go @@ -0,0 +1,20 @@ +// Copyright 2016 CNI authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build darwin dragonfly freebsd linux netbsd opensbd solaris + +package invoke + +// Valid file extensions for plugin executables. +var ExecutableFileExtensions = []string{""} diff --git a/vendor/github.com/containernetworking/cni/pkg/invoke/os_windows.go b/vendor/github.com/containernetworking/cni/pkg/invoke/os_windows.go new file mode 100644 index 000000000..7665125b1 --- /dev/null +++ b/vendor/github.com/containernetworking/cni/pkg/invoke/os_windows.go @@ -0,0 +1,18 @@ +// Copyright 2016 CNI authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package invoke + +// Valid file extensions for plugin executables. +var ExecutableFileExtensions = []string{".exe", ""} diff --git a/vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go b/vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go index d1bd860d3..93f1e75d9 100644 --- a/vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go +++ b/vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go @@ -50,13 +50,9 @@ func pluginErr(err error, output []byte) error { if _, ok := err.(*exec.ExitError); ok { emsg := types.Error{} if perr := json.Unmarshal(output, &emsg); perr != nil { - return fmt.Errorf("netplugin failed but error parsing its diagnostic message %q: %v", string(output), perr) + emsg.Msg = fmt.Sprintf("netplugin failed but error parsing its diagnostic message %q: %v", string(output), perr) } - details := "" - if emsg.Details != "" { - details = fmt.Sprintf("; %v", emsg.Details) - } - return fmt.Errorf("%v%v", emsg.Msg, details) + return &emsg } return err diff --git a/vendor/github.com/containernetworking/cni/pkg/types/020/types.go b/vendor/github.com/containernetworking/cni/pkg/types/020/types.go new file mode 100644 index 000000000..2833aba78 --- /dev/null +++ b/vendor/github.com/containernetworking/cni/pkg/types/020/types.go @@ -0,0 +1,135 @@ +// Copyright 2016 CNI authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types020 + +import ( + "encoding/json" + "fmt" + "net" + "os" + + "github.com/containernetworking/cni/pkg/types" +) + +const ImplementedSpecVersion string = "0.2.0" + +var SupportedVersions = []string{"", "0.1.0", ImplementedSpecVersion} + +// Compatibility types for CNI version 0.1.0 and 0.2.0 + +func NewResult(data []byte) (types.Result, error) { + result := &Result{} + if err := json.Unmarshal(data, result); err != nil { + return nil, err + } + return result, nil +} + +func GetResult(r types.Result) (*Result, error) { + // We expect version 0.1.0/0.2.0 results + result020, err := r.GetAsVersion(ImplementedSpecVersion) + if err != nil { + return nil, err + } + result, ok := result020.(*Result) + if !ok { + return nil, fmt.Errorf("failed to convert result") + } + return result, nil +} + +// Result is what gets returned from the plugin (via stdout) to the caller +type Result struct { + CNIVersion string `json:"cniVersion,omitempty"` + IP4 *IPConfig `json:"ip4,omitempty"` + IP6 *IPConfig `json:"ip6,omitempty"` + DNS types.DNS `json:"dns,omitempty"` +} + +func (r *Result) Version() string { + return ImplementedSpecVersion +} + +func (r *Result) GetAsVersion(version string) (types.Result, error) { + for _, supportedVersion := range SupportedVersions { + if version == supportedVersion { + r.CNIVersion = version + return r, nil + } + } + return nil, fmt.Errorf("cannot convert version %q to %s", SupportedVersions, version) +} + +func (r *Result) Print() error { + data, err := json.MarshalIndent(r, "", " ") + if err != nil { + return err + } + _, err = os.Stdout.Write(data) + return err +} + +// String returns a formatted string in the form of "[IP4: $1,][ IP6: $2,] DNS: $3" where +// $1 represents the receiver's IPv4, $2 represents the receiver's IPv6 and $3 the +// receiver's DNS. If $1 or $2 are nil, they won't be present in the returned string. +func (r *Result) String() string { + var str string + if r.IP4 != nil { + str = fmt.Sprintf("IP4:%+v, ", *r.IP4) + } + if r.IP6 != nil { + str += fmt.Sprintf("IP6:%+v, ", *r.IP6) + } + return fmt.Sprintf("%sDNS:%+v", str, r.DNS) +} + +// IPConfig contains values necessary to configure an interface +type IPConfig struct { + IP net.IPNet + Gateway net.IP + Routes []types.Route +} + +// net.IPNet is not JSON (un)marshallable so this duality is needed +// for our custom IPNet type + +// JSON (un)marshallable types +type ipConfig struct { + IP types.IPNet `json:"ip"` + Gateway net.IP `json:"gateway,omitempty"` + Routes []types.Route `json:"routes,omitempty"` +} + +func (c *IPConfig) MarshalJSON() ([]byte, error) { + ipc := ipConfig{ + IP: types.IPNet(c.IP), + Gateway: c.Gateway, + Routes: c.Routes, + } + + return json.Marshal(ipc) +} + +func (c *IPConfig) UnmarshalJSON(data []byte) error { + ipc := ipConfig{} + if err := json.Unmarshal(data, &ipc); err != nil { + return err + } + + c.IP = net.IPNet(ipc.IP) + c.Gateway = ipc.Gateway + c.Routes = ipc.Routes + return nil +} diff --git a/vendor/github.com/containernetworking/cni/pkg/types/args.go b/vendor/github.com/containernetworking/cni/pkg/types/args.go index 66dcf9eae..bd8640fc9 100644 --- a/vendor/github.com/containernetworking/cni/pkg/types/args.go +++ b/vendor/github.com/containernetworking/cni/pkg/types/args.go @@ -63,6 +63,12 @@ func GetKeyField(keyString string, v reflect.Value) reflect.Value { return v.Elem().FieldByName(keyString) } +// UnmarshalableArgsError is used to indicate error unmarshalling args +// from the args-string in the form "K=V;K2=V2;..." +type UnmarshalableArgsError struct { + error +} + // LoadArgs parses args from a string in the form "K=V;K2=V2;..." func LoadArgs(args string, container interface{}) error { if args == "" { @@ -85,8 +91,13 @@ func LoadArgs(args string, container interface{}) error { unknownArgs = append(unknownArgs, pair) continue } - - u := keyField.Addr().Interface().(encoding.TextUnmarshaler) + keyFieldIface := keyField.Addr().Interface() + u, ok := keyFieldIface.(encoding.TextUnmarshaler) + if !ok { + return UnmarshalableArgsError{fmt.Errorf( + "ARGS: cannot unmarshal into field '%s' - type '%s' does not implement encoding.TextUnmarshaler", + keyString, reflect.TypeOf(keyFieldIface))} + } err := u.UnmarshalText([]byte(valueString)) if err != nil { return fmt.Errorf("ARGS: error parsing value of pair %q: %v)", pair, err) diff --git a/vendor/github.com/containernetworking/cni/pkg/types/current/types.go b/vendor/github.com/containernetworking/cni/pkg/types/current/types.go new file mode 100644 index 000000000..caac92ba7 --- /dev/null +++ b/vendor/github.com/containernetworking/cni/pkg/types/current/types.go @@ -0,0 +1,300 @@ +// Copyright 2016 CNI authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package current + +import ( + "encoding/json" + "fmt" + "net" + "os" + + "github.com/containernetworking/cni/pkg/types" + "github.com/containernetworking/cni/pkg/types/020" +) + +const ImplementedSpecVersion string = "0.3.1" + +var SupportedVersions = []string{"0.3.0", ImplementedSpecVersion} + +func NewResult(data []byte) (types.Result, error) { + result := &Result{} + if err := json.Unmarshal(data, result); err != nil { + return nil, err + } + return result, nil +} + +func GetResult(r types.Result) (*Result, error) { + resultCurrent, err := r.GetAsVersion(ImplementedSpecVersion) + if err != nil { + return nil, err + } + result, ok := resultCurrent.(*Result) + if !ok { + return nil, fmt.Errorf("failed to convert result") + } + return result, nil +} + +var resultConverters = []struct { + versions []string + convert func(types.Result) (*Result, error) +}{ + {types020.SupportedVersions, convertFrom020}, + {SupportedVersions, convertFrom030}, +} + +func convertFrom020(result types.Result) (*Result, error) { + oldResult, err := types020.GetResult(result) + if err != nil { + return nil, err + } + + newResult := &Result{ + CNIVersion: ImplementedSpecVersion, + DNS: oldResult.DNS, + Routes: []*types.Route{}, + } + + if oldResult.IP4 != nil { + newResult.IPs = append(newResult.IPs, &IPConfig{ + Version: "4", + Address: oldResult.IP4.IP, + 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, + }) + } + } + + if oldResult.IP6 != nil { + newResult.IPs = append(newResult.IPs, &IPConfig{ + Version: "6", + Address: oldResult.IP6.IP, + 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, + }) + } + } + + if len(newResult.IPs) == 0 { + return nil, fmt.Errorf("cannot convert: no valid IP addresses") + } + + return newResult, nil +} + +func convertFrom030(result types.Result) (*Result, error) { + newResult, ok := result.(*Result) + if !ok { + return nil, fmt.Errorf("failed to convert result") + } + newResult.CNIVersion = ImplementedSpecVersion + return newResult, nil +} + +func NewResultFromResult(result types.Result) (*Result, error) { + version := result.Version() + for _, converter := range resultConverters { + for _, supportedVersion := range converter.versions { + if version == supportedVersion { + return converter.convert(result) + } + } + } + return nil, fmt.Errorf("unsupported CNI result22 version %q", version) +} + +// Result is what gets returned from the plugin (via stdout) to the caller +type Result struct { + CNIVersion string `json:"cniVersion,omitempty"` + Interfaces []*Interface `json:"interfaces,omitempty"` + IPs []*IPConfig `json:"ips,omitempty"` + Routes []*types.Route `json:"routes,omitempty"` + DNS types.DNS `json:"dns,omitempty"` +} + +// Convert to the older 0.2.0 CNI spec Result type +func (r *Result) convertTo020() (*types020.Result, error) { + oldResult := &types020.Result{ + CNIVersion: types020.ImplementedSpecVersion, + DNS: r.DNS, + } + + for _, ip := range r.IPs { + // Only convert the first IP address of each version as 0.2.0 + // and earlier cannot handle multiple IP addresses + if ip.Version == "4" && oldResult.IP4 == nil { + oldResult.IP4 = &types020.IPConfig{ + IP: ip.Address, + Gateway: ip.Gateway, + } + } else if ip.Version == "6" && oldResult.IP6 == nil { + oldResult.IP6 = &types020.IPConfig{ + IP: ip.Address, + Gateway: ip.Gateway, + } + } + + if oldResult.IP4 != nil && oldResult.IP6 != nil { + break + } + } + + for _, route := range r.Routes { + is4 := route.Dst.IP.To4() != nil + if is4 && oldResult.IP4 != nil { + oldResult.IP4.Routes = append(oldResult.IP4.Routes, types.Route{ + Dst: route.Dst, + GW: route.GW, + }) + } else if !is4 && oldResult.IP6 != nil { + oldResult.IP6.Routes = append(oldResult.IP6.Routes, types.Route{ + Dst: route.Dst, + GW: route.GW, + }) + } + } + + if oldResult.IP4 == nil && oldResult.IP6 == nil { + return nil, fmt.Errorf("cannot convert: no valid IP addresses") + } + + return oldResult, nil +} + +func (r *Result) Version() string { + return ImplementedSpecVersion +} + +func (r *Result) GetAsVersion(version string) (types.Result, error) { + switch version { + case "0.3.0", ImplementedSpecVersion: + r.CNIVersion = version + return r, nil + case types020.SupportedVersions[0], types020.SupportedVersions[1], types020.SupportedVersions[2]: + return r.convertTo020() + } + return nil, fmt.Errorf("cannot convert version 0.3.x to %q", version) +} + +func (r *Result) Print() error { + data, err := json.MarshalIndent(r, "", " ") + if err != nil { + return err + } + _, err = os.Stdout.Write(data) + return err +} + +// String returns a formatted string in the form of "[Interfaces: $1,][ IP: $2,] DNS: $3" where +// $1 represents the receiver's Interfaces, $2 represents the receiver's IP addresses and $3 the +// receiver's DNS. If $1 or $2 are nil, they won't be present in the returned string. +func (r *Result) String() string { + var str string + if len(r.Interfaces) > 0 { + str += fmt.Sprintf("Interfaces:%+v, ", r.Interfaces) + } + if len(r.IPs) > 0 { + str += fmt.Sprintf("IP:%+v, ", r.IPs) + } + if len(r.Routes) > 0 { + str += fmt.Sprintf("Routes:%+v, ", r.Routes) + } + return fmt.Sprintf("%sDNS:%+v", str, r.DNS) +} + +// Convert this old version result to the current CNI version result +func (r *Result) Convert() (*Result, error) { + return r, nil +} + +// Interface contains values about the created interfaces +type Interface struct { + Name string `json:"name"` + Mac string `json:"mac,omitempty"` + Sandbox string `json:"sandbox,omitempty"` +} + +func (i *Interface) String() string { + return fmt.Sprintf("%+v", *i) +} + +// Int returns a pointer to the int value passed in. Used to +// set the IPConfig.Interface field. +func Int(v int) *int { + return &v +} + +// IPConfig contains values necessary to configure an IP address on an interface +type IPConfig struct { + // IP version, either "4" or "6" + Version string + // Index into Result structs Interfaces list + Interface *int + Address net.IPNet + Gateway net.IP +} + +func (i *IPConfig) String() string { + return fmt.Sprintf("%+v", *i) +} + +// JSON (un)marshallable types +type ipConfig struct { + Version string `json:"version"` + Interface *int `json:"interface,omitempty"` + Address types.IPNet `json:"address"` + Gateway net.IP `json:"gateway,omitempty"` +} + +func (c *IPConfig) MarshalJSON() ([]byte, error) { + ipc := ipConfig{ + Version: c.Version, + Interface: c.Interface, + Address: types.IPNet(c.Address), + Gateway: c.Gateway, + } + + return json.Marshal(ipc) +} + +func (c *IPConfig) UnmarshalJSON(data []byte) error { + ipc := ipConfig{} + if err := json.Unmarshal(data, &ipc); err != nil { + return err + } + + c.Version = ipc.Version + c.Interface = ipc.Interface + c.Address = net.IPNet(ipc.Address) + c.Gateway = ipc.Gateway + return nil +} diff --git a/vendor/github.com/containernetworking/cni/pkg/types/types.go b/vendor/github.com/containernetworking/cni/pkg/types/types.go index 17caa49bb..641275600 100644 --- a/vendor/github.com/containernetworking/cni/pkg/types/types.go +++ b/vendor/github.com/containernetworking/cni/pkg/types/types.go @@ -16,6 +16,7 @@ package types import ( "encoding/json" + "errors" "fmt" "net" "os" @@ -59,44 +60,48 @@ func (n *IPNet) UnmarshalJSON(data []byte) error { type NetConf struct { CNIVersion string `json:"cniVersion,omitempty"` - Name string `json:"name,omitempty"` - Type string `json:"type,omitempty"` - IPAM 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"` DNS DNS `json:"dns"` } -// Result is what gets returned from the plugin (via stdout) to the caller -type Result struct { - IP4 *IPConfig `json:"ip4,omitempty"` - IP6 *IPConfig `json:"ip6,omitempty"` - DNS DNS `json:"dns,omitempty"` +// NetConfList describes an ordered list of networks. +type NetConfList struct { + CNIVersion string `json:"cniVersion,omitempty"` + + Name string `json:"name,omitempty"` + Plugins []*NetConf `json:"plugins,omitempty"` } -func (r *Result) Print() error { - return prettyPrint(r) +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 + // without having to convert + Version() string + + // Returns the result converted into the requested CNI specification + // result version, or an error if conversion failed + GetAsVersion(version string) (Result, error) + + // Prints the result in JSON format to stdout + Print() error + + // Returns a JSON string representation of the result + String() string } -// String returns a formatted string in the form of "[IP4: $1,][ IP6: $2,] DNS: $3" where -// $1 represents the receiver's IPv4, $2 represents the receiver's IPv6 and $3 the -// receiver's DNS. If $1 or $2 are nil, they won't be present in the returned string. -func (r *Result) String() string { - var str string - if r.IP4 != nil { - str = fmt.Sprintf("IP4:%+v, ", *r.IP4) +func PrintResult(result Result, version string) error { + newResult, err := result.GetAsVersion(version) + if err != nil { + return err } - if r.IP6 != nil { - str += fmt.Sprintf("IP6:%+v, ", *r.IP6) - } - return fmt.Sprintf("%sDNS:%+v", str, r.DNS) -} - -// IPConfig contains values necessary to configure an interface -type IPConfig struct { - IP net.IPNet - Gateway net.IP - Routes []Route + return newResult.Print() } // DNS contains values interesting for DNS resolvers @@ -112,6 +117,10 @@ type Route struct { GW net.IP } +func (r *Route) String() string { + return fmt.Sprintf("%+v", *r) +} + // Well known error codes // see https://github.com/containernetworking/cni/blob/master/SPEC.md#well-known-error-codes const ( @@ -127,7 +136,11 @@ type Error struct { } func (e *Error) Error() string { - return e.Msg + details := "" + if e.Details != "" { + details = fmt.Sprintf("; %v", e.Details) + } + return fmt.Sprintf("%v%v", e.Msg, details) } func (e *Error) Print() error { @@ -138,39 +151,11 @@ func (e *Error) Print() error { // for our custom IPNet type // JSON (un)marshallable types -type ipConfig struct { - IP IPNet `json:"ip"` - Gateway net.IP `json:"gateway,omitempty"` - Routes []Route `json:"routes,omitempty"` -} - type route struct { Dst IPNet `json:"dst"` GW net.IP `json:"gw,omitempty"` } -func (c *IPConfig) MarshalJSON() ([]byte, error) { - ipc := ipConfig{ - IP: IPNet(c.IP), - Gateway: c.Gateway, - Routes: c.Routes, - } - - return json.Marshal(ipc) -} - -func (c *IPConfig) UnmarshalJSON(data []byte) error { - ipc := ipConfig{} - if err := json.Unmarshal(data, &ipc); err != nil { - return err - } - - c.IP = net.IPNet(ipc.IP) - c.Gateway = ipc.Gateway - c.Routes = ipc.Routes - return nil -} - func (r *Route) UnmarshalJSON(data []byte) error { rt := route{} if err := json.Unmarshal(data, &rt); err != nil { @@ -199,3 +184,6 @@ func prettyPrint(obj interface{}) error { _, err = os.Stdout.Write(data) return err } + +// NotImplementedError is used to indicate that a method is not implemented for the given platform +var NotImplementedError = errors.New("Not Implemented") diff --git a/vendor/github.com/containernetworking/cni/pkg/version/reconcile.go b/vendor/github.com/containernetworking/cni/pkg/version/reconcile.go index f61ef6533..25c3810b2 100644 --- a/vendor/github.com/containernetworking/cni/pkg/version/reconcile.go +++ b/vendor/github.com/containernetworking/cni/pkg/version/reconcile.go @@ -17,12 +17,12 @@ package version import "fmt" type ErrorIncompatible struct { - Config string - Plugin []string + Config string + Supported []string } func (e *ErrorIncompatible) Details() string { - return fmt.Sprintf("config is %q, plugin supports %q", e.Config, e.Plugin) + return fmt.Sprintf("config is %q, plugin supports %q", e.Config, e.Supported) } func (e *ErrorIncompatible) Error() string { @@ -31,17 +31,19 @@ func (e *ErrorIncompatible) Error() string { type Reconciler struct{} -func (*Reconciler) Check(configVersion string, pluginInfo PluginInfo) *ErrorIncompatible { - pluginVersions := pluginInfo.SupportedVersions() +func (r *Reconciler) Check(configVersion string, pluginInfo PluginInfo) *ErrorIncompatible { + return r.CheckRaw(configVersion, pluginInfo.SupportedVersions()) +} - for _, pluginVersion := range pluginVersions { - if configVersion == pluginVersion { +func (*Reconciler) CheckRaw(configVersion string, supportedVersions []string) *ErrorIncompatible { + for _, supportedVersion := range supportedVersions { + if configVersion == supportedVersion { return nil } } return &ErrorIncompatible{ - Config: configVersion, - Plugin: pluginVersions, + Config: configVersion, + Supported: supportedVersions, } } diff --git a/vendor/github.com/containernetworking/cni/pkg/version/version.go b/vendor/github.com/containernetworking/cni/pkg/version/version.go index e39c3b553..efe8ea871 100644 --- a/vendor/github.com/containernetworking/cni/pkg/version/version.go +++ b/vendor/github.com/containernetworking/cni/pkg/version/version.go @@ -14,9 +14,17 @@ package version +import ( + "fmt" + + "github.com/containernetworking/cni/pkg/types" + "github.com/containernetworking/cni/pkg/types/020" + "github.com/containernetworking/cni/pkg/types/current" +) + // Current reports the version of the CNI spec implemented by this library func Current() string { - return "0.2.0" + return "0.3.1" } // Legacy PluginInfo describes a plugin that is backwards compatible with the @@ -27,3 +35,27 @@ 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 resultFactories = []struct { + supportedVersions []string + newResult types.ResultFactoryFunc +}{ + {current.SupportedVersions, current.NewResult}, + {types020.SupportedVersions, types020.NewResult}, +} + +// Finds a Result object matching the requested version (if any) and asks +// that object to parse the plugin result, returning an error if parsing failed. +func NewResult(version string, resultBytes []byte) (types.Result, error) { + reconciler := &Reconciler{} + for _, resultFactory := range resultFactories { + err := reconciler.CheckRaw(version, resultFactory.supportedVersions) + if err == nil { + // Result supports this version + return resultFactory.newResult(resultBytes) + } + } + + return nil, fmt.Errorf("unsupported CNI result version %q", version) +} From 8f898cb3b8a58a82ee0f35596c7ab8a1b175f5a7 Mon Sep 17 00:00:00 2001 From: Lantao Liu Date: Wed, 23 Aug 2017 01:24:19 +0000 Subject: [PATCH 2/3] Import ocicni update from https://github.com/Random-Liu/ocicni Signed-off-by: Lantao Liu --- pkg/server/testing/fake_cni_plugin.go | 46 +- vendor.conf | 4 +- .../cri-o/pkg => cri-o}/ocicni/LICENSE | 0 .../cri-o/pkg => cri-o}/ocicni/README.md | 0 vendor/github.com/cri-o/ocicni/noop.go | 24 + .../cri-o/pkg => cri-o}/ocicni/ocicni.go | 99 +- vendor/github.com/cri-o/ocicni/types.go | 62 + .../cri-o/pkg => cri-o}/ocicni/util.go | 0 .../kubernetes-incubator/cri-o/LICENSE | 201 --- .../kubernetes-incubator/cri-o/README.md | 217 --- .../kubernetes-incubator/cri-o/conmon/cmsg.c | 149 -- .../kubernetes-incubator/cri-o/conmon/cmsg.h | 38 - .../cri-o/conmon/conmon.c | 1400 ----------------- .../cri-o/pkg/ocicni/noop.go | 24 - .../cri-o/pkg/ocicni/types.go | 35 - .../kubernetes-incubator/cri-o/vendor.conf | 73 - 16 files changed, 169 insertions(+), 2203 deletions(-) rename vendor/github.com/{kubernetes-incubator/cri-o/pkg => cri-o}/ocicni/LICENSE (100%) rename vendor/github.com/{kubernetes-incubator/cri-o/pkg => cri-o}/ocicni/README.md (100%) create mode 100644 vendor/github.com/cri-o/ocicni/noop.go rename vendor/github.com/{kubernetes-incubator/cri-o/pkg => cri-o}/ocicni/ocicni.go (70%) create mode 100644 vendor/github.com/cri-o/ocicni/types.go rename vendor/github.com/{kubernetes-incubator/cri-o/pkg => cri-o}/ocicni/util.go (100%) delete mode 100644 vendor/github.com/kubernetes-incubator/cri-o/LICENSE delete mode 100644 vendor/github.com/kubernetes-incubator/cri-o/README.md delete mode 100644 vendor/github.com/kubernetes-incubator/cri-o/conmon/cmsg.c delete mode 100644 vendor/github.com/kubernetes-incubator/cri-o/conmon/cmsg.h delete mode 100644 vendor/github.com/kubernetes-incubator/cri-o/conmon/conmon.c delete mode 100644 vendor/github.com/kubernetes-incubator/cri-o/pkg/ocicni/noop.go delete mode 100644 vendor/github.com/kubernetes-incubator/cri-o/pkg/ocicni/types.go delete mode 100644 vendor/github.com/kubernetes-incubator/cri-o/vendor.conf diff --git a/pkg/server/testing/fake_cni_plugin.go b/pkg/server/testing/fake_cni_plugin.go index e9bad3917..c3f212032 100644 --- a/pkg/server/testing/fake_cni_plugin.go +++ b/pkg/server/testing/fake_cni_plugin.go @@ -23,7 +23,7 @@ import ( "sync" "time" - "github.com/kubernetes-incubator/cri-o/pkg/ocicni" + "github.com/cri-o/ocicni" ) // CalledDetail is the struct contains called function name and arguments. @@ -34,20 +34,12 @@ type CalledDetail struct { Argument interface{} } -// CNIPluginArgument is arguments used to call CNI related functions. -type CNIPluginArgument struct { - NetnsPath string - Namespace string - Name string - ContainerID string -} - // FakeCNIPlugin is a fake plugin used for test. type FakeCNIPlugin struct { sync.Mutex called []CalledDetail errors map[string]error - IPMap map[CNIPluginArgument]string + IPMap map[string]string } // getError get error for call @@ -108,18 +100,17 @@ func (f *FakeCNIPlugin) GetCalledDetails() []CalledDetail { } // SetFakePodNetwork sets the given IP for given arguments. -func (f *FakeCNIPlugin) SetFakePodNetwork(netnsPath string, namespace string, name string, containerID string, ip string) { +func (f *FakeCNIPlugin) SetFakePodNetwork(podNetwork ocicni.PodNetwork, ip string) { f.Lock() defer f.Unlock() - arg := CNIPluginArgument{netnsPath, namespace, name, containerID} - f.IPMap[arg] = ip + f.IPMap[podNetwork.NetNS] = ip } // NewFakeCNIPlugin create a FakeCNIPlugin. func NewFakeCNIPlugin() ocicni.CNIPlugin { return &FakeCNIPlugin{ errors: make(map[string]error), - IPMap: make(map[CNIPluginArgument]string), + IPMap: make(map[string]string), } } @@ -129,45 +120,42 @@ func (f *FakeCNIPlugin) Name() string { } // SetUpPod setup the network of PodSandbox. -func (f *FakeCNIPlugin) SetUpPod(netnsPath string, namespace string, name string, containerID string) error { +func (f *FakeCNIPlugin) SetUpPod(podNetwork ocicni.PodNetwork) error { f.Lock() defer f.Unlock() - arg := CNIPluginArgument{netnsPath, namespace, name, containerID} - f.appendCalled("SetUpPod", arg) + f.appendCalled("SetUpPod", podNetwork) if err := f.getError("SetUpPod"); err != nil { return err } - f.IPMap[arg] = generateIP() + f.IPMap[podNetwork.NetNS] = generateIP() return nil } // TearDownPod teardown the network of PodSandbox. -func (f *FakeCNIPlugin) TearDownPod(netnsPath string, namespace string, name string, containerID string) error { +func (f *FakeCNIPlugin) TearDownPod(podNetwork ocicni.PodNetwork) error { f.Lock() defer f.Unlock() - arg := CNIPluginArgument{netnsPath, namespace, name, containerID} - f.appendCalled("TearDownPod", arg) + f.appendCalled("TearDownPod", podNetwork) if err := f.getError("TearDownPod"); err != nil { return err } - _, ok := f.IPMap[arg] + _, ok := f.IPMap[podNetwork.NetNS] if !ok { return fmt.Errorf("failed to find the IP") } - delete(f.IPMap, arg) + delete(f.IPMap, podNetwork.NetNS) return nil } -// GetContainerNetworkStatus get the status of network. -func (f *FakeCNIPlugin) GetContainerNetworkStatus(netnsPath string, namespace string, name string, containerID string) (string, error) { +// GetPodNetworkStatus get the status of network. +func (f *FakeCNIPlugin) GetPodNetworkStatus(netnsPath string) (string, error) { f.Lock() defer f.Unlock() - arg := CNIPluginArgument{netnsPath, namespace, name, containerID} - f.appendCalled("GetContainerNetworkStatus", arg) - if err := f.getError("GetContainerNetworkStatus"); err != nil { + f.appendCalled("GetPodNetworkStatus", netnsPath) + if err := f.getError("GetPodNetworkStatus"); err != nil { return "", err } - ip, ok := f.IPMap[arg] + ip, ok := f.IPMap[netnsPath] if !ok { return "", fmt.Errorf("failed to find the IP") } diff --git a/vendor.conf b/vendor.conf index 10e87bddf..e9c6902eb 100644 --- a/vendor.conf +++ b/vendor.conf @@ -2,7 +2,8 @@ github.com/blang/semver v3.1.0 github.com/boltdb/bolt v1.3.0-58-ge9cf4fa github.com/containerd/containerd f79981c2dfe35c3bfcbdd2de9b682e8c3de904b2 github.com/containerd/fifo fbfb6a11ec671efbe94ad1c12c2e98773f19e1e6 -github.com/containernetworking/cni v0.4.0 +github.com/containernetworking/cni v0.6.0 +github.com/cri-o/ocicni 3bb422584a0755d73718085e0edc355619b5973e https://github.com/Random-Liu/ocicni.git github.com/davecgh/go-spew v1.1.0 github.com/docker/distribution b38e5838b7b2f2ad48e06ec4b500011976080621 github.com/docker/docker cc4da8112814cdbb00dbf23370f9ed764383de1f @@ -21,7 +22,6 @@ github.com/go-openapi/spec 6aced65f8501fe1217321abf0749d354824ba2ff github.com/go-openapi/swag 1d0bd113de87027671077d3c71eb3ac5d7dbba72 github.com/jpillora/backoff 06c7a16c845dc8e0bf575fafeeca0f5462f5eb4d github.com/juju/ratelimit 5b9ff866471762aa2ab2dced63c9fb6f53921342 -github.com/kubernetes-incubator/cri-o 63a218a45844fd912f482dc85f9cc149e68e0e57 github.com/mailru/easyjson d5b7844b561a7bc640052f1b935f7b800330d7e0 github.com/Microsoft/go-winio v0.4.4 github.com/opencontainers/go-digest 21dfd564fd89c944783d00d069f33e3e7123c448 diff --git a/vendor/github.com/kubernetes-incubator/cri-o/pkg/ocicni/LICENSE b/vendor/github.com/cri-o/ocicni/LICENSE similarity index 100% rename from vendor/github.com/kubernetes-incubator/cri-o/pkg/ocicni/LICENSE rename to vendor/github.com/cri-o/ocicni/LICENSE diff --git a/vendor/github.com/kubernetes-incubator/cri-o/pkg/ocicni/README.md b/vendor/github.com/cri-o/ocicni/README.md similarity index 100% rename from vendor/github.com/kubernetes-incubator/cri-o/pkg/ocicni/README.md rename to vendor/github.com/cri-o/ocicni/README.md diff --git a/vendor/github.com/cri-o/ocicni/noop.go b/vendor/github.com/cri-o/ocicni/noop.go new file mode 100644 index 000000000..fa2e0ee43 --- /dev/null +++ b/vendor/github.com/cri-o/ocicni/noop.go @@ -0,0 +1,24 @@ +package ocicni + +type cniNoOp struct { +} + +func (noop *cniNoOp) Name() string { + return "CNINoOp" +} + +func (noop *cniNoOp) SetUpPod(network PodNetwork) error { + return nil +} + +func (noop *cniNoOp) TearDownPod(network PodNetwork) error { + return nil +} + +func (noop *cniNoOp) GetPodNetworkStatus(netnsPath string) (string, error) { + return "", nil +} + +func (noop *cniNoOp) Status() error { + return nil +} diff --git a/vendor/github.com/kubernetes-incubator/cri-o/pkg/ocicni/ocicni.go b/vendor/github.com/cri-o/ocicni/ocicni.go similarity index 70% rename from vendor/github.com/kubernetes-incubator/cri-o/pkg/ocicni/ocicni.go rename to vendor/github.com/cri-o/ocicni/ocicni.go index 0204cc2f4..8dd12cec1 100644 --- a/vendor/github.com/kubernetes-incubator/cri-o/pkg/ocicni/ocicni.go +++ b/vendor/github.com/cri-o/ocicni/ocicni.go @@ -5,6 +5,7 @@ import ( "fmt" "os/exec" "sort" + "strings" "sync" "github.com/containernetworking/cni/libcni" @@ -29,7 +30,7 @@ type cniNetworkPlugin struct { type cniNetwork struct { name string - NetworkConfig *libcni.NetworkConfig + NetworkConfig *libcni.NetworkConfigList CNIConfig libcni.CNI } @@ -128,7 +129,7 @@ func getDefaultCNINetwork(pluginDir string, cniDirs []string, vendorCNIDirPrefix cniDirs = []string{DefaultCNIDir} } - files, err := libcni.ConfFiles(pluginDir) + files, err := libcni.ConfFiles(pluginDir, []string{".conf", ".conflist", ".json"}) switch { case err != nil: return nil, err @@ -138,19 +139,39 @@ func getDefaultCNINetwork(pluginDir string, cniDirs []string, vendorCNIDirPrefix sort.Strings(files) for _, confFile := range files { - conf, err := libcni.ConfFromFile(confFile) - if err != nil { - logrus.Warningf("Error loading CNI config file %s: %v", confFile, err) + var confList *libcni.NetworkConfigList + if strings.HasSuffix(confFile, ".conflist") { + confList, err = libcni.ConfListFromFile(confFile) + if err != nil { + logrus.Warningf("Error loading CNI config list file %s: %v", confFile, err) + continue + } + } else { + conf, err := libcni.ConfFromFile(confFile) + if err != nil { + logrus.Warningf("Error loading CNI config file %s: %v", confFile, err) + continue + } + if conf.Network.Type == "" { + logrus.Warningf("Error loading CNI config file %s: no 'type'; perhaps this is a .conflist?", confFile) + continue + } + confList, err = libcni.ConfListFromConf(conf) + if err != nil { + logrus.Warningf("Error converting CNI config file %s to list: %v", confFile, err) + continue + } + } + if len(confList.Plugins) == 0 { + logrus.Warningf("CNI config list %s has no networks, skipping", confFile) continue } - // Search for vendor-specific plugins as well as default plugins in the CNI codebase. - vendorDir := vendorCNIDir(vendorCNIDirPrefix, conf.Network.Type) + vendorDir := vendorCNIDir(vendorCNIDirPrefix, confList.Plugins[0].Network.Type) cninet := &libcni.CNIConfig{ Path: append(cniDirs, vendorDir), } - - network := &cniNetwork{name: conf.Network.Name, NetworkConfig: conf, CNIConfig: cninet} + network := &cniNetwork{name: confList.Name, NetworkConfig: confList, CNIConfig: cninet} return network, nil } return nil, fmt.Errorf("No valid networks found in %s", pluginDir) @@ -165,17 +186,19 @@ func getLoNetwork(cniDirs []string, vendorDirPrefix string) *cniNetwork { cniDirs = []string{DefaultCNIDir} } - loConfig, err := libcni.ConfFromBytes([]byte(`{ - "cniVersion": "0.1.0", + loConfig, err := libcni.ConfListFromBytes([]byte(`{ + "cniVersion": "0.2.0", "name": "cni-loopback", - "type": "loopback" + "plugins": [{ + "type": "loopback" + }] }`)) if err != nil { // The hardcoded config above should always be valid and unit tests will // catch this panic(err) } - vendorDir := vendorCNIDir(vendorDirPrefix, loConfig.Network.Type) + vendorDir := vendorCNIDir(vendorDirPrefix, loConfig.Plugins[0].Network.Type) cninet := &libcni.CNIConfig{ Path: append(cniDirs, vendorDir), } @@ -222,18 +245,18 @@ func (plugin *cniNetworkPlugin) Name() string { return CNIPluginName } -func (plugin *cniNetworkPlugin) SetUpPod(netnsPath string, namespace string, name string, id string) error { +func (plugin *cniNetworkPlugin) SetUpPod(podNetwork PodNetwork) error { if err := plugin.checkInitialized(); err != nil { return err } - _, err := plugin.loNetwork.addToNetwork(name, namespace, id, netnsPath) + _, err := plugin.loNetwork.addToNetwork(podNetwork) if err != nil { logrus.Errorf("Error while adding to cni lo network: %s", err) return err } - _, err = plugin.getDefaultNetwork().addToNetwork(name, namespace, id, netnsPath) + _, err = plugin.getDefaultNetwork().addToNetwork(podNetwork) if err != nil { logrus.Errorf("Error while adding to cni network: %s", err) return err @@ -242,17 +265,17 @@ func (plugin *cniNetworkPlugin) SetUpPod(netnsPath string, namespace string, nam return err } -func (plugin *cniNetworkPlugin) TearDownPod(netnsPath string, namespace string, name string, id string) error { +func (plugin *cniNetworkPlugin) TearDownPod(podNetwork PodNetwork) error { if err := plugin.checkInitialized(); err != nil { return err } - return plugin.getDefaultNetwork().deleteFromNetwork(name, namespace, id, netnsPath) + return plugin.getDefaultNetwork().deleteFromNetwork(podNetwork) } // TODO: Use the addToNetwork function to obtain the IP of the Pod. That will assume idempotent ADD call to the plugin. // Also fix the runtime's call to Status function to be done only in the case that the IP is lost, no need to do periodic calls -func (plugin *cniNetworkPlugin) GetContainerNetworkStatus(netnsPath string, namespace string, name string, id string) (string, error) { +func (plugin *cniNetworkPlugin) GetPodNetworkStatus(netnsPath string) (string, error) { ip, err := getContainerIP(plugin.nsenterPath, netnsPath, DefaultInterfaceName, "-4") if err != nil { return "", err @@ -261,16 +284,16 @@ func (plugin *cniNetworkPlugin) GetContainerNetworkStatus(netnsPath string, name return ip.String(), nil } -func (network *cniNetwork) addToNetwork(podName string, podNamespace string, podInfraContainerID string, podNetnsPath string) (*cnitypes.Result, error) { - rt, err := buildCNIRuntimeConf(podName, podNamespace, podInfraContainerID, podNetnsPath) +func (network *cniNetwork) addToNetwork(podNetwork PodNetwork) (cnitypes.Result, error) { + rt, err := buildCNIRuntimeConf(podNetwork) if err != nil { logrus.Errorf("Error adding network: %v", err) return nil, err } netconf, cninet := network.NetworkConfig, network.CNIConfig - logrus.Infof("About to run with conf.Network.Type=%v", netconf.Network.Type) - res, err := cninet.AddNetwork(netconf, rt) + logrus.Infof("About to add CNI network %v (type=%v)", netconf.Name, netconf.Plugins[0].Network.Type) + res, err := cninet.AddNetworkList(netconf, rt) if err != nil { logrus.Errorf("Error adding network: %v", err) return nil, err @@ -279,16 +302,16 @@ func (network *cniNetwork) addToNetwork(podName string, podNamespace string, pod return res, nil } -func (network *cniNetwork) deleteFromNetwork(podName string, podNamespace string, podInfraContainerID string, podNetnsPath string) error { - rt, err := buildCNIRuntimeConf(podName, podNamespace, podInfraContainerID, podNetnsPath) +func (network *cniNetwork) deleteFromNetwork(podNetwork PodNetwork) error { + rt, err := buildCNIRuntimeConf(podNetwork) if err != nil { logrus.Errorf("Error deleting network: %v", err) return err } netconf, cninet := network.NetworkConfig, network.CNIConfig - logrus.Infof("About to run with conf.Network.Type=%v", netconf.Network.Type) - err = cninet.DelNetwork(netconf, rt) + logrus.Infof("About to del CNI network %v (type=%v)", netconf.Name, netconf.Plugins[0].Network.Type) + err = cninet.DelNetworkList(netconf, rt) if err != nil { logrus.Errorf("Error deleting network: %v", err) return err @@ -296,22 +319,28 @@ func (network *cniNetwork) deleteFromNetwork(podName string, podNamespace string return nil } -func buildCNIRuntimeConf(podName string, podNs string, podInfraContainerID string, podNetnsPath string) (*libcni.RuntimeConf, error) { - logrus.Infof("Got netns path %v", podNetnsPath) - logrus.Infof("Using netns path %v", podNs) +func buildCNIRuntimeConf(podNetwork PodNetwork) (*libcni.RuntimeConf, error) { + logrus.Infof("Got pod network %+v", podNetwork) rt := &libcni.RuntimeConf{ - ContainerID: podInfraContainerID, - NetNS: podNetnsPath, + ContainerID: podNetwork.ID, + NetNS: podNetwork.NetNS, IfName: DefaultInterfaceName, Args: [][2]string{ {"IgnoreUnknown", "1"}, - {"K8S_POD_NAMESPACE", podNs}, - {"K8S_POD_NAME", podName}, - {"K8S_POD_INFRA_CONTAINER_ID", podInfraContainerID}, + {"K8S_POD_NAMESPACE", podNetwork.Namespace}, + {"K8S_POD_NAME", podNetwork.Name}, + {"K8S_POD_INFRA_CONTAINER_ID", podNetwork.ID}, }, } + if len(podNetwork.PortMappings) == 0 { + return rt, nil + } + + rt.CapabilityArgs = map[string]interface{}{ + "portMappings": podNetwork.PortMappings, + } return rt, nil } diff --git a/vendor/github.com/cri-o/ocicni/types.go b/vendor/github.com/cri-o/ocicni/types.go new file mode 100644 index 000000000..00ad00ff9 --- /dev/null +++ b/vendor/github.com/cri-o/ocicni/types.go @@ -0,0 +1,62 @@ +package ocicni + +const ( + // DefaultInterfaceName is the string to be used for the interface name inside the net namespace + DefaultInterfaceName = "eth0" + // CNIPluginName is the default name of the plugin + CNIPluginName = "cni" + // DefaultNetDir is the place to look for CNI Network + DefaultNetDir = "/etc/cni/net.d" + // DefaultCNIDir is the place to look for cni config files + DefaultCNIDir = "/opt/cni/bin" + // VendorCNIDirTemplate is the template for looking up vendor specific cni config/executable files + VendorCNIDirTemplate = "%s/opt/%s/bin" +) + +// PortMapping maps to the standard CNI portmapping Capability +// see: https://github.com/containernetworking/cni/blob/master/CONVENTIONS.md +type PortMapping struct { + // HostPort is the port number on the host. + HostPort int32 `json:"hostPort"` + // ContainerPort is the port number inside the sandbox. + ContainerPort int32 `json:"containerPort"` + // Protocol is the protocol of the port mapping. + Protocol string `json:"protocol"` + // HostIP is the host ip to use. + HostIP string `json:"hostIP"` +} + +// PodNetwork configures the network of a pod sandbox. +type PodNetwork struct { + // Name is the name of the sandbox. + Name string + // Namespace is the namespace of the sandbox. + Namespace string + // ID is the id of the sandbox container. + ID string + // NetNS is the network namespace path of the sandbox. + NetNS string + // PortMappings is the port mapping of the sandbox. + PortMappings []PortMapping +} + +// CNIPlugin is the interface that needs to be implemented by a plugin +type CNIPlugin interface { + // Name returns the plugin's name. This will be used when searching + // for a plugin by name, e.g. + Name() string + + // SetUpPod is the method called after the sandbox container of + // the pod has been created but before the other containers of the + // pod are launched. + SetUpPod(network PodNetwork) error + + // TearDownPod is the method called before a pod's sandbox container will be deleted + TearDownPod(network PodNetwork) error + + // Status is the method called to obtain the ipv4 or ipv6 addresses of the pod sandbox + GetPodNetworkStatus(netnsPath string) (string, error) + + // NetworkStatus returns error if the network plugin is in error state + Status() error +} diff --git a/vendor/github.com/kubernetes-incubator/cri-o/pkg/ocicni/util.go b/vendor/github.com/cri-o/ocicni/util.go similarity index 100% rename from vendor/github.com/kubernetes-incubator/cri-o/pkg/ocicni/util.go rename to vendor/github.com/cri-o/ocicni/util.go diff --git a/vendor/github.com/kubernetes-incubator/cri-o/LICENSE b/vendor/github.com/kubernetes-incubator/cri-o/LICENSE deleted file mode 100644 index 8dada3eda..000000000 --- a/vendor/github.com/kubernetes-incubator/cri-o/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/kubernetes-incubator/cri-o/README.md b/vendor/github.com/kubernetes-incubator/cri-o/README.md deleted file mode 100644 index a90fef5dc..000000000 --- a/vendor/github.com/kubernetes-incubator/cri-o/README.md +++ /dev/null @@ -1,217 +0,0 @@ -![cri-o logo](https://cdn.rawgit.com/kubernetes-incubator/cri-o/master/logo/crio-logo.svg) -# cri-o - OCI-based implementation of Kubernetes Container Runtime Interface - -[![Build Status](https://img.shields.io/travis/kubernetes-incubator/cri-o.svg?maxAge=2592000&style=flat-square)](https://travis-ci.org/kubernetes-incubator/cri-o) -[![Go Report Card](https://goreportcard.com/badge/github.com/kubernetes-incubator/cri-o?style=flat-square)](https://goreportcard.com/report/github.com/kubernetes-incubator/cri-o) - -### Status: alpha - -## What is the scope of this project? - -cri-o is meant to provide an integration path between OCI conformant runtimes and the kubelet. -Specifically, it implements the Kubelet Container Runtime Interface (CRI) using OCI conformant runtimes. -The scope of cri-o is tied to the scope of the CRI. - -At a high level, we expect the scope of cri-o to be restricted to the following functionalities: - -* Support multiple image formats including the existing Docker image format -* Support for multiple means to download images including trust & image verification -* Container image management (managing image layers, overlay filesystems, etc) -* Container process lifecycle management -* Monitoring and logging required to satisfy the CRI -* Resource isolation as required by the CRI - -## What is not in scope for this project? - -* Building, signing and pushing images to various image storages -* A CLI utility for interacting with cri-o. Any CLIs built as part of this project are only meant for testing this project and there will be no guarantees on the backwards compatibility with it. - -This is an implementation of the Kubernetes Container Runtime Interface (CRI) that will allow Kubernetes to directly launch and manage Open Container Initiative (OCI) containers. - -The plan is to use OCI projects and best of breed libraries for different aspects: -- Runtime: [runc](https://github.com/opencontainers/runc) (or any OCI runtime-spec implementation) and [oci runtime tools](https://github.com/opencontainers/runtime-tools) -- Images: Image management using [containers/image](https://github.com/containers/image) -- Storage: Storage and management of image layers using [containers/storage](https://github.com/containers/storage) -- Networking: Networking support through use of [CNI](https://github.com/containernetworking/cni) - -It is currently in active development in the Kubernetes community through the [design proposal](https://github.com/kubernetes/kubernetes/pull/26788). Questions and issues should be raised in the Kubernetes [sig-node Slack channel](https://kubernetes.slack.com/archives/sig-node). - -## Commands -| Command | Description | -| ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | -| [crio(8)](/docs/crio.8.md) | Enable OCI Kubernetes Container Runtime daemon | -| [kpod(1)](/docs/kpod.1.md) | Simple management tool for pods and images | -| [kpod-history(1)](/docs/kpod-history.1.md)] | Shows the history of an image | -| [kpod-images(1)](/docs/kpod-images.1.md) | List images in local storage | -| [kpod-inspect(1)](/docs/kpod-inspect.1.md) | Display the configuration of a container or image | -| [kpod-load(1)](/docs/kpod-load.1.md) | Load an image from docker archive or oci | -| [kpod-pull(1)](/docs/kpod-pull.1.md) | Pull an image from a registry | -| [kpod-push(1)](/docs/kpod-push.1.md) | Push an image to a specified destination | -| [kpod-rmi(1)](/docs/kpod-rmi.1.md) | Removes one or more images | -| [kpod-save(1)](/docs/kpod-save.1.md) | Saves an image to an archive | -| [kpod-tag(1)](/docs/kpod-tag.1.md) | Add an additional name to a local image | -| [kpod-version(1)](/docs/kpod-version.1.md) | Display the Kpod Version Information | - -## Configuration -| File | Description | -| ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | -| [crio.conf(5)](/docs/crio.conf.5.md) | CRI-O Configuation file | - -## Communication - -For async communication and long running discussions please use issues and pull requests on the github repo. This will be the best place to discuss design and implementation. - -For sync communication we have an IRC channel #cri-o, on chat.freenode.net, that everyone is welcome to join and chat about development. - -## Getting started - -### Prerequisites - -Latest verion of `runc` is expected to be installed on the system. It is picked up as the default runtime by crio. - -### Build Dependencies - -**Required** - -Fedora, CentOS, RHEL, and related distributions: - -```bash -yum install -y \ - btrfs-progs-devel \ - device-mapper-devel \ - glib2-devel \ - glibc-devel \ - glibc-static \ - gpgme-devel \ - libassuan-devel \ - libgpg-error-devel \ - libseccomp-devel \ - libselinux-devel \ - ostree-devel \ - pkgconfig \ - runc -``` - -Debian, Ubuntu, and related distributions: - -```bash -apt install -y \ - btrfs-tools \ - libassuan-dev \ - libdevmapper-dev \ - libglib2.0-dev \ - libc6-dev \ - libgpgme11-dev \ - libgpg-error-dev \ - libseccomp-dev \ - libselinux1-dev \ - pkg-config \ - runc -``` - -Debian, Ubuntu, and related distributions will also need a copy of the development libraries for `ostree`, either in the form of the `libostree-dev` package from the [flatpak](https://launchpad.net/~alexlarsson/+archive/ubuntu/flatpak) PPA, or built [from source](https://github.com/ostreedev/ostree) (more on that [here](https://ostree.readthedocs.io/en/latest/#building)). - -If using an older release or a long-term support release, be careful to double-check that the version of `runc` is new enough (running `runc --version` should produce `spec: 1.0.0`), or else build your own. - -**Optional** - -Fedora, CentOS, RHEL, and related distributions: - -(no optional packages) - -Debian, Ubuntu, and related distributions: - -```bash -apt install -y \ - libapparmor-dev -``` - -### Get Source Code - -As with other Go projects, cri-o must be cloned into a directory structure like: - -``` -GOPATH -└── src - └── github.com - └── kubernetes-incubator - └── cri-o -``` - -First, configure a `GOPATH` (if you are using go1.8 or later, this defaults to `~/go`). - -```bash -export GOPATH=~/go -mkdir -p $GOPATH -``` - -Next, clone the source code using: - -```bash -mkdir -p $GOPATH/src/github.com/kubernetes-incubator -cd $_ # or cd $GOPATH/src/github.com/kubernetes-incubator -git clone https://github.com/kubernetes-incubator/cri-o # or your fork -cd cri-o -``` - -### Build - -```bash -make install.tools -make -sudo make install -``` - -Otherwise, if you do not want to build `cri-o` with seccomp support you can add `BUILDTAGS=""` when running make. - -```bash -make BUILDTAGS="" -sudo make install -``` - -#### Build Tags - -`cri-o` supports optional build tags for compiling support of various features. -To add build tags to the make option the `BUILDTAGS` variable must be set. - -```bash -make BUILDTAGS='seccomp apparmor' -``` - -| Build Tag | Feature | Dependency | -|-----------|------------------------------------|-------------| -| seccomp | syscall filtering | libseccomp | -| selinux | selinux process and mount labeling | libselinux | -| apparmor | apparmor profile support | libapparmor | - -### Running pods and containers - -Follow this [tutorial](tutorial.md) to get started with CRI-O. - -### Setup CNI networking - -A proper description of setting up CNI networking is given in the -[`contrib/cni` README](contrib/cni/README.md). But the gist is that you need to -have some basic network configurations enabled and CNI plugins installed on -your system. - -### Running with kubernetes - -You can run a local version of kubernetes with cri-o using `local-up-cluster.sh`: - -1. Clone the [kubernetes repository](https://github.com/kubernetes/kubernetes) -1. Start the cri-o daemon (`crio`) -1. From the kubernetes project directory, run: `CONTAINER_RUNTIME=remote CONTAINER_RUNTIME_ENDPOINT='/var/run/crio.sock --runtime-request-timeout=15m' ./hack/local-up-cluster.sh` - -To run a full cluster, see [the instructions](kubernetes.md). - -### Current Roadmap - -1. Basic pod/container lifecycle, basic image pull (done) -1. Support for tty handling and state management (done) -1. Basic integration with kubelet once client side changes are ready (done) -1. Support for log management, networking integration using CNI, pluggable image/storage management (done) -1. Support for exec/attach (done) -1. Target fully automated kubernetes testing without failures [e2e status](https://github.com/kubernetes-incubator/cri-o/issues/533) -1. Release 1.0 -1. Track upstream k8s releases diff --git a/vendor/github.com/kubernetes-incubator/cri-o/conmon/cmsg.c b/vendor/github.com/kubernetes-incubator/cri-o/conmon/cmsg.c deleted file mode 100644 index c44db2ef1..000000000 --- a/vendor/github.com/kubernetes-incubator/cri-o/conmon/cmsg.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright 2016 SUSE LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* NOTE: This code comes directly from runc/libcontainer/utils/cmsg.c. */ - -#include -#include -#include -#include -#include -#include -#include - -#include "cmsg.h" - -#define error(fmt, ...) \ - ({ \ - fprintf(stderr, "nsenter: " fmt ": %m\n", ##__VA_ARGS__); \ - errno = ECOMM; \ - goto err; /* return value */ \ - }) - -/* - * Sends a file descriptor along the sockfd provided. Returns the return - * value of sendmsg(2). Any synchronisation and preparation of state - * should be done external to this (we expect the other side to be in - * recvfd() in the code). - */ -ssize_t sendfd(int sockfd, struct file_t file) -{ - struct msghdr msg = {0}; - struct iovec iov[1] = {0}; - struct cmsghdr *cmsg; - int *fdptr; - - union { - char buf[CMSG_SPACE(sizeof(file.fd))]; - struct cmsghdr align; - } u; - - /* - * We need to send some other data along with the ancillary data, - * otherwise the other side won't recieve any data. This is very - * well-hidden in the documentation (and only applies to - * SOCK_STREAM). See the bottom part of unix(7). - */ - iov[0].iov_base = file.name; - iov[0].iov_len = strlen(file.name) + 1; - - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = iov; - msg.msg_iovlen = 1; - msg.msg_control = u.buf; - msg.msg_controllen = sizeof(u.buf); - - cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN(sizeof(int)); - - fdptr = (int *) CMSG_DATA(cmsg); - memcpy(fdptr, &file.fd, sizeof(int)); - - return sendmsg(sockfd, &msg, 0); -} - -/* - * Receives a file descriptor from the sockfd provided. Returns the file - * descriptor as sent from sendfd(). It will return the file descriptor - * or die (literally) trying. Any synchronisation and preparation of - * state should be done external to this (we expect the other side to be - * in sendfd() in the code). - */ -struct file_t recvfd(int sockfd) -{ - struct msghdr msg = {0}; - struct iovec iov[1] = {0}; - struct cmsghdr *cmsg; - struct file_t file = {0}; - int *fdptr; - int olderrno; - - union { - char buf[CMSG_SPACE(sizeof(file.fd))]; - struct cmsghdr align; - } u; - - /* Allocate a buffer. */ - /* TODO: Make this dynamic with MSG_PEEK. */ - file.name = malloc(TAG_BUFFER); - if (!file.name) - error("recvfd: failed to allocate file.tag buffer\n"); - - /* - * We need to "recieve" the non-ancillary data even though we don't - * plan to use it at all. Otherwise, things won't work as expected. - * See unix(7) and other well-hidden documentation. - */ - iov[0].iov_base = file.name; - iov[0].iov_len = TAG_BUFFER; - - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = iov; - msg.msg_iovlen = 1; - msg.msg_control = u.buf; - msg.msg_controllen = sizeof(u.buf); - - ssize_t ret = recvmsg(sockfd, &msg, 0); - if (ret < 0) - goto err; - - cmsg = CMSG_FIRSTHDR(&msg); - if (!cmsg) - error("recvfd: got NULL from CMSG_FIRSTHDR"); - if (cmsg->cmsg_level != SOL_SOCKET) - error("recvfd: expected SOL_SOCKET in cmsg: %d", cmsg->cmsg_level); - if (cmsg->cmsg_type != SCM_RIGHTS) - error("recvfd: expected SCM_RIGHTS in cmsg: %d", cmsg->cmsg_type); - if (cmsg->cmsg_len != CMSG_LEN(sizeof(int))) - error("recvfd: expected correct CMSG_LEN in cmsg: %lu", cmsg->cmsg_len); - - fdptr = (int *) CMSG_DATA(cmsg); - if (!fdptr || *fdptr < 0) - error("recvfd: recieved invalid pointer"); - - file.fd = *fdptr; - return file; - -err: - olderrno = errno; - free(file.name); - errno = olderrno; - return (struct file_t){0}; -} diff --git a/vendor/github.com/kubernetes-incubator/cri-o/conmon/cmsg.h b/vendor/github.com/kubernetes-incubator/cri-o/conmon/cmsg.h deleted file mode 100644 index 7c7aefe6e..000000000 --- a/vendor/github.com/kubernetes-incubator/cri-o/conmon/cmsg.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2016 SUSE LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* NOTE: This code comes directly from runc/libcontainer/utils/cmsg.h. */ - -#pragma once - -#if !defined(CMSG_H) -#define CMSG_H - -#include - -/* TODO: Implement this properly with MSG_PEEK. */ -#define TAG_BUFFER 4096 - -/* This mirrors Go's (*os.File). */ -struct file_t { - char *name; - int fd; -}; - -struct file_t recvfd(int sockfd); -ssize_t sendfd(int sockfd, struct file_t file); - -#endif /* !defined(CMSG_H) */ diff --git a/vendor/github.com/kubernetes-incubator/cri-o/conmon/conmon.c b/vendor/github.com/kubernetes-incubator/cri-o/conmon/conmon.c deleted file mode 100644 index 2009bf490..000000000 --- a/vendor/github.com/kubernetes-incubator/cri-o/conmon/conmon.c +++ /dev/null @@ -1,1400 +0,0 @@ -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "cmsg.h" - -#define pexit(fmt, ...) \ - do { \ - fprintf(stderr, "[conmon:e]: " fmt " %m\n", ##__VA_ARGS__); \ - syslog(LOG_ERR, "conmon : " fmt ": %m\n", ##__VA_ARGS__); \ - exit(EXIT_FAILURE); \ - } while (0) - -#define nexit(fmt, ...) \ - do { \ - fprintf(stderr, "[conmon:e]: " fmt "\n", ##__VA_ARGS__); \ - syslog(LOG_ERR, "conmon : " fmt " \n", ##__VA_ARGS__); \ - exit(EXIT_FAILURE); \ - } while (0) - -#define nwarn(fmt, ...) \ - do { \ - fprintf(stderr, "[conmon:w]: " fmt "\n", ##__VA_ARGS__); \ - syslog(LOG_INFO, "conmon : " fmt " \n", ##__VA_ARGS__); \ - } while (0) - -#define ninfo(fmt, ...) \ - do { \ - fprintf(stderr, "[conmon:i]: " fmt "\n", ##__VA_ARGS__); \ - syslog(LOG_INFO, "conmon : " fmt " \n", ##__VA_ARGS__); \ - } while (0) - -#define _cleanup_(x) __attribute__((cleanup(x))) - -static inline void freep(void *p) -{ - free(*(void **)p); -} - -static inline void closep(int *fd) -{ - if (*fd >= 0) - close(*fd); - *fd = -1; -} - -static inline void fclosep(FILE **fp) { - if (*fp) - fclose(*fp); - *fp = NULL; -} - -static inline void gstring_free_cleanup(GString **string) -{ - if (*string) - g_string_free(*string, TRUE); -} - -static inline void strv_cleanup(char ***strv) -{ - if (strv) - g_strfreev (*strv); -} - -#define _cleanup_free_ _cleanup_(freep) -#define _cleanup_close_ _cleanup_(closep) -#define _cleanup_fclose_ _cleanup_(fclosep) -#define _cleanup_gstring_ _cleanup_(gstring_free_cleanup) -#define _cleanup_strv_ _cleanup_(strv_cleanup) - -#define BUF_SIZE 8192 -#define CMD_SIZE 1024 -#define MAX_EVENTS 10 - -static bool opt_terminal = false; -static bool opt_stdin = false; -static char *opt_cid = NULL; -static char *opt_cuuid = NULL; -static char *opt_runtime_path = NULL; -static char *opt_bundle_path = NULL; -static char *opt_pid_file = NULL; -static bool opt_systemd_cgroup = false; -static char *opt_exec_process_spec = NULL; -static bool opt_exec = false; -static char *opt_log_path = NULL; -static int opt_timeout = 0; -static GOptionEntry opt_entries[] = -{ - { "terminal", 't', 0, G_OPTION_ARG_NONE, &opt_terminal, "Terminal", NULL }, - { "stdin", 'i', 0, G_OPTION_ARG_NONE, &opt_stdin, "Stdin", NULL }, - { "cid", 'c', 0, G_OPTION_ARG_STRING, &opt_cid, "Container ID", NULL }, - { "cuuid", 'u', 0, G_OPTION_ARG_STRING, &opt_cuuid, "Container UUID", NULL }, - { "runtime", 'r', 0, G_OPTION_ARG_STRING, &opt_runtime_path, "Runtime path", NULL }, - { "bundle", 'b', 0, G_OPTION_ARG_STRING, &opt_bundle_path, "Bundle path", NULL }, - { "pidfile", 'p', 0, G_OPTION_ARG_STRING, &opt_pid_file, "PID file", NULL }, - { "systemd-cgroup", 's', 0, G_OPTION_ARG_NONE, &opt_systemd_cgroup, "Enable systemd cgroup manager", NULL }, - { "exec", 'e', 0, G_OPTION_ARG_NONE, &opt_exec, "Exec a command in a running container", NULL }, - { "exec-process-spec", 0, 0, G_OPTION_ARG_STRING, &opt_exec_process_spec, "Path to the process spec for exec", NULL }, - { "log-path", 'l', 0, G_OPTION_ARG_STRING, &opt_log_path, "Log file path", NULL }, - { "timeout", 'T', 0, G_OPTION_ARG_INT, &opt_timeout, "Timeout in seconds", NULL }, - { NULL } -}; - -/* strlen("1997-03-25T13:20:42.999999999+01:00 stdout ") + 1 */ -#define TSBUFLEN 44 - -#define CGROUP_ROOT "/sys/fs/cgroup" - -static ssize_t write_all(int fd, const void *buf, size_t count) -{ - size_t remaining = count; - const char *p = buf; - ssize_t res; - - while (remaining > 0) { - do { - res = write(fd, p, remaining); - } while (res == -1 && errno == EINTR); - - if (res <= 0) - return -1; - - remaining -= res; - p += res; - } - - return count; -} - -#define WRITEV_BUFFER_N_IOV 128 - -typedef struct { - int iovcnt; - struct iovec iov[WRITEV_BUFFER_N_IOV]; -} writev_buffer_t; - -static ssize_t writev_buffer_flush (int fd, writev_buffer_t *buf) -{ - size_t count = 0; - ssize_t res; - struct iovec *iov; - int iovcnt; - - iovcnt = buf->iovcnt; - iov = buf->iov; - - while (iovcnt > 0) { - do { - res = writev(fd, iov, iovcnt); - } while (res == -1 && errno == EINTR); - - if (res <= 0) - return -1; - - count += res; - - while (res > 0) { - size_t from_this = MIN((size_t)res, iov->iov_len); - iov->iov_len -= from_this; - res -= from_this; - - if (iov->iov_len == 0) { - iov++; - iovcnt--; - } - } - } - - buf->iovcnt = 0; - - return count; -} - -ssize_t writev_buffer_append_segment(int fd, writev_buffer_t *buf, const void *data, ssize_t len) -{ - if (data == NULL) - return 1; - - if (len < 0) - len = strlen ((char *)data); - - if (buf->iovcnt == WRITEV_BUFFER_N_IOV && - writev_buffer_flush (fd, buf) < 0) - return -1; - - if (len > 0) { - buf->iov[buf->iovcnt].iov_base = (void *)data; - buf->iov[buf->iovcnt].iov_len = (size_t)len; - buf->iovcnt++; - } - - return 1; -} - -int set_k8s_timestamp(char *buf, ssize_t buflen, const char *pipename) -{ - struct tm *tm; - struct timespec ts; - char off_sign = '+'; - int off, len, err = -1; - - if (clock_gettime(CLOCK_REALTIME, &ts) < 0) { - /* If CLOCK_REALTIME is not supported, we set nano seconds to 0 */ - if (errno == EINVAL) { - ts.tv_nsec = 0; - } else { - return err; - } - } - - if ((tm = localtime(&ts.tv_sec)) == NULL) - return err; - - - off = (int) tm->tm_gmtoff; - if (tm->tm_gmtoff < 0) { - off_sign = '-'; - off = -off; - } - - len = snprintf(buf, buflen, "%d-%02d-%02dT%02d:%02d:%02d.%09ld%c%02d:%02d %s ", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, - tm->tm_hour, tm->tm_min, tm->tm_sec, ts.tv_nsec, - off_sign, off / 3600, off % 3600, pipename); - - if (len < buflen) - err = 0; - return err; -} - -/* stdpipe_t represents one of the std pipes (or NONE). - * Sync with const in container_attach.go */ -typedef enum { - NO_PIPE, - STDIN_PIPE, /* unused */ - STDOUT_PIPE, - STDERR_PIPE, -} stdpipe_t; - -const char *stdpipe_name(stdpipe_t pipe) -{ - switch (pipe) { - case STDIN_PIPE: - return "stdin"; - case STDOUT_PIPE: - return "stdout"; - case STDERR_PIPE: - return "stderr"; - default: - return "NONE"; - } -} - -/* - * The CRI requires us to write logs with a (timestamp, stream, line) format - * for every newline-separated line. write_k8s_log writes said format for every - * line in buf, and will partially write the final line of the log if buf is - * not terminated by a newline. - */ -int write_k8s_log(int fd, stdpipe_t pipe, const char *buf, ssize_t buflen) -{ - char tsbuf[TSBUFLEN]; - static stdpipe_t trailing_line = NO_PIPE; - writev_buffer_t bufv = {0}; - - /* - * Use the same timestamp for every line of the log in this buffer. - * There is no practical difference in the output since write(2) is - * fast. - */ - if (set_k8s_timestamp(tsbuf, sizeof tsbuf, stdpipe_name(pipe))) - /* TODO: We should handle failures much more cleanly than this. */ - return -1; - - while (buflen > 0) { - const char *line_end = NULL; - ptrdiff_t line_len = 0; - - /* Find the end of the line, or alternatively the end of the buffer. */ - line_end = memchr(buf, '\n', buflen); - if (line_end == NULL) - line_end = &buf[buflen-1]; - line_len = line_end - buf + 1; - - /* - * Write the (timestamp, stream) tuple if there isn't any trailing - * output from the previous line (or if there is trailing output but - * the current buffer being printed is from a different pipe). - */ - if (trailing_line != pipe) { - /* - * If there was a trailing line from a different pipe, prepend a - * newline to split it properly. This technically breaks the flow - * of the previous line (adding a newline in the log where there - * wasn't one output) but without modifying the file in a - * non-append-only way there's not much we can do. - */ - if ((trailing_line != NO_PIPE && - writev_buffer_append_segment(fd, &bufv, "\n", -1) < 0) || - writev_buffer_append_segment(fd, &bufv, tsbuf, -1) < 0) { - nwarn("failed to write (timestamp, stream) to log"); - goto next; - } - } - - /* Output the actual contents. */ - if (writev_buffer_append_segment(fd, &bufv, buf, line_len) < 0) { - nwarn("failed to write buffer to log"); - goto next; - } - - /* If we did not output a full line, then we are a trailing_line. */ - trailing_line = (*line_end == '\n') ? NO_PIPE : pipe; - -next: - /* Update the head of the buffer remaining to output. */ - buf += line_len; - buflen -= line_len; - } - - if (writev_buffer_flush (fd, &bufv) < 0) { - nwarn("failed to flush buffer to log"); - } - - return 0; -} - -/* - * Returns the path for specified controller name for a pid. - * Returns NULL on error. - */ -static char *process_cgroup_subsystem_path(int pid, const char *subsystem) { - _cleanup_free_ char *cgroups_file_path = g_strdup_printf("/proc/%d/cgroup", pid); - _cleanup_fclose_ FILE *fp = NULL; - fp = fopen(cgroups_file_path, "re"); - if (fp == NULL) { - nwarn("Failed to open cgroups file: %s", cgroups_file_path); - return NULL; - } - - _cleanup_free_ char *line = NULL; - ssize_t read; - size_t len = 0; - char *ptr, *path; - char *subsystem_path = NULL; - int i; - while ((read = getline(&line, &len, fp)) != -1) { - _cleanup_strv_ char **subsystems = NULL; - ptr = strchr(line, ':'); - if (ptr == NULL) { - nwarn("Error parsing cgroup, ':' not found: %s", line); - return NULL; - } - ptr++; - path = strchr(ptr, ':'); - if (path == NULL) { - nwarn("Error parsing cgroup, second ':' not found: %s", line); - return NULL; - } - *path = 0; - path++; - subsystems = g_strsplit (ptr, ",", -1); - for (i = 0; subsystems[i] != NULL; i++) { - if (strcmp (subsystems[i], subsystem) == 0) { - char *subpath = strchr(subsystems[i], '='); - if (subpath == NULL) { - subpath = ptr; - } else { - *subpath = 0; - } - - subsystem_path = g_strdup_printf("%s/%s%s", CGROUP_ROOT, subpath, path); - subsystem_path[strlen(subsystem_path) - 1] = '\0'; - return subsystem_path; - } - } - } - - return NULL; -} - -static char *escape_json_string(const char *str) -{ - GString *escaped; - const char *p; - - p = str; - escaped = g_string_sized_new(strlen(str)); - - while (*p != 0) { - char c = *p++; - if (c == '\\' || c == '"') { - g_string_append_c(escaped, '\\'); - g_string_append_c(escaped, c); - } else if (c == '\n') { - g_string_append_printf (escaped, "\\n"); - } else if (c == '\t') { - g_string_append_printf (escaped, "\\t"); - } else if ((c > 0 && c < 0x1f) || c == 0x7f) { - g_string_append_printf (escaped, "\\u00%02x", (guint)c); - } else { - g_string_append_c (escaped, c); - } - } - - return g_string_free (escaped, FALSE); -} - -static int get_pipe_fd_from_env(const char *envname) -{ - char *pipe_str, *endptr; - int pipe_fd; - - pipe_str = getenv(envname); - if (pipe_str == NULL) - return -1; - - errno = 0; - pipe_fd = strtol(pipe_str, &endptr, 10); - if (errno != 0 || *endptr != '\0') - pexit("unable to parse %s", envname); - if (fcntl(pipe_fd, F_SETFD, FD_CLOEXEC) == -1) - pexit("unable to make %s CLOEXEC", envname); - - return pipe_fd; -} - -static void add_argv(GPtrArray *argv_array, ...) G_GNUC_NULL_TERMINATED; - -static void add_argv(GPtrArray *argv_array, ...) -{ - va_list args; - char *arg; - - va_start (args, argv_array); - while ((arg = va_arg (args, char *))) - g_ptr_array_add (argv_array, arg); - va_end (args); -} - -static void end_argv(GPtrArray *argv_array) -{ - g_ptr_array_add(argv_array, NULL); -} - -/* Global state */ - -static int runtime_status = -1; -static int container_status = -1; - -static int masterfd_stdin = -1; -static int masterfd_stdout = -1; -static int masterfd_stderr = -1; - -/* Used for attach */ -static int conn_sock = -1; -static int conn_sock_readable; -static int conn_sock_writable; - -static int log_fd = -1; -static int oom_event_fd = -1; -static int attach_socket_fd = -1; -static int console_socket_fd = -1; -static int terminal_ctrl_fd = -1; - -static bool timed_out = FALSE; - -static GMainLoop *main_loop = NULL; - -static void conn_sock_shutdown(int how) -{ - if (conn_sock == -1) - return; - shutdown(conn_sock, how); - if (how & SHUT_RD) - conn_sock_readable = false; - if (how & SHUT_WR) - conn_sock_writable = false; - if (!conn_sock_writable && !conn_sock_readable) { - close(conn_sock); - conn_sock = -1; - } -} - -static gboolean stdio_cb(int fd, GIOCondition condition, gpointer user_data); - -static gboolean tty_hup_timeout_scheduled = false; - -static gboolean tty_hup_timeout_cb (G_GNUC_UNUSED gpointer user_data) -{ - tty_hup_timeout_scheduled = false; - g_unix_fd_add (masterfd_stdout, G_IO_IN, stdio_cb, GINT_TO_POINTER(STDOUT_PIPE)); - return G_SOURCE_REMOVE; -} - -static bool read_stdio(int fd, stdpipe_t pipe, bool *eof) -{ - #define STDIO_BUF_SIZE 8192 /* Sync with redirectResponseToOutputStreams() */ - /* We use one extra byte at the start, which we don't read into, instead - we use that for marking the pipe when we write to the attached socket */ - char real_buf[STDIO_BUF_SIZE + 1]; - char *buf = real_buf + 1; - ssize_t num_read = 0; - - if (eof) - *eof = false; - - num_read = read(fd, buf, STDIO_BUF_SIZE); - if (num_read == 0) { - if (eof) - *eof = true; - return false; - } else if (num_read < 0) { - nwarn("stdio_input read failed %s", strerror(errno)); - return false; - } else { - if (write_k8s_log(log_fd, pipe, buf, num_read) < 0) { - nwarn("write_k8s_log failed"); - return G_SOURCE_CONTINUE; - } - - real_buf[0] = pipe; - if (conn_sock_writable && write_all(conn_sock, real_buf, num_read+1) < 0) { - nwarn("Failed to write to socket"); - conn_sock_shutdown(SHUT_WR); - } - return true; - } -} - -static void on_sigchld(G_GNUC_UNUSED int signal) -{ - raise (SIGUSR1); -} - -static void check_child_processes(GHashTable *pid_to_handler) -{ - void (*cb) (GPid, int, gpointer); - - for (;;) { - int status; - pid_t pid = waitpid(-1, &status, WNOHANG); - - if (pid < 0 && errno == EINTR) - continue; - if (pid < 0 && errno == ECHILD) { - g_main_loop_quit (main_loop); - return; - } - if (pid < 0) - pexit("Failed to read child process status"); - - if (pid == 0) - return; - - /* If we got here, pid > 0, so we have a valid pid to check. */ - cb = g_hash_table_lookup(pid_to_handler, &pid); - if (cb) - cb(pid, status, 0); - } -} - -static gboolean on_sigusr1_cb(gpointer user_data) -{ - GHashTable *pid_to_handler = (GHashTable *) user_data; - check_child_processes (pid_to_handler); - return G_SOURCE_CONTINUE; -} - -static gboolean stdio_cb(int fd, GIOCondition condition, gpointer user_data) -{ - stdpipe_t pipe = GPOINTER_TO_INT(user_data); - bool read_eof = false; - bool has_input = (condition & G_IO_IN) != 0; - bool has_hup = (condition & G_IO_HUP) != 0; - - /* When we get here, condition can be G_IO_IN and/or G_IO_HUP. - IN means there is some data to read. - HUP means the other side closed the fd. In the case of a pine - this in final, and we will never get more data. However, in the - terminal case this just means that nobody has the terminal - open at this point, and this can be change whenever someone - opens the tty */ - - /* Read any data before handling hup */ - if (has_input) { - read_stdio(fd, pipe, &read_eof); - } - - if (has_hup && opt_terminal && pipe == STDOUT_PIPE) { - /* We got a HUP from the terminal master this means there - are no open slaves ptys atm, and we will get a lot - of wakeups until we have one, switch to polling - mode. */ - - /* If we read some data this cycle, wait one more, maybe there - is more in the buffer before we handle the hup */ - if (has_input && !read_eof) { - return G_SOURCE_CONTINUE; - } - - if (!tty_hup_timeout_scheduled) { - g_timeout_add (100, tty_hup_timeout_cb, NULL); - } - tty_hup_timeout_scheduled = true; - return G_SOURCE_REMOVE; - } - - if (read_eof || (has_hup && !has_input)) { - /* End of input */ - if (pipe == STDOUT_PIPE) - masterfd_stdout = -1; - if (pipe == STDERR_PIPE) - masterfd_stderr = -1; - - close (fd); - return G_SOURCE_REMOVE; - } - - return G_SOURCE_CONTINUE; -} - -static gboolean timeout_cb (G_GNUC_UNUSED gpointer user_data) -{ - timed_out = TRUE; - ninfo ("Timed out, killing main loop"); - g_main_loop_quit (main_loop); - return G_SOURCE_REMOVE; -} - -static gboolean oom_cb(int fd, GIOCondition condition, G_GNUC_UNUSED gpointer user_data) -{ - uint64_t oom_event; - ssize_t num_read = 0; - - if ((condition & G_IO_IN) != 0) { - num_read = read(fd, &oom_event, sizeof(uint64_t)); - if (num_read < 0) { - nwarn("Failed to read oom event from eventfd"); - return G_SOURCE_CONTINUE; - } - - if (num_read > 0) { - if (num_read != sizeof(uint64_t)) - nwarn("Failed to read full oom event from eventfd"); - ninfo("OOM received"); - if (open("oom", O_CREAT, 0666) < 0) { - nwarn("Failed to write oom file"); - } - return G_SOURCE_CONTINUE; - } - } - - /* End of input */ - close (fd); - oom_event_fd = -1; - return G_SOURCE_REMOVE; -} - -static gboolean conn_sock_cb(int fd, GIOCondition condition, G_GNUC_UNUSED gpointer user_data) -{ - #define CONN_SOCK_BUF_SIZE 32*1024 /* Match the write size in CopyDetachable */ - char buf[CONN_SOCK_BUF_SIZE]; - ssize_t num_read = 0; - - if ((condition & G_IO_IN) != 0) { - num_read = read(fd, buf, CONN_SOCK_BUF_SIZE); - if (num_read < 0) - return G_SOURCE_CONTINUE; - - if (num_read > 0 && masterfd_stdin >= 0) { - if (write_all(masterfd_stdin, buf, num_read) < 0) { - nwarn("Failed to write to container stdin"); - } - return G_SOURCE_CONTINUE; - } - } - - /* End of input */ - conn_sock_shutdown(SHUT_RD); - if (masterfd_stdin >= 0 && opt_stdin) { - close(masterfd_stdin); - masterfd_stdin = -1; - } - return G_SOURCE_REMOVE; -} - -static gboolean attach_cb(int fd, G_GNUC_UNUSED GIOCondition condition, G_GNUC_UNUSED gpointer user_data) -{ - conn_sock = accept(fd, NULL, NULL); - if (conn_sock == -1) { - if (errno != EWOULDBLOCK) - nwarn("Failed to accept client connection on attach socket"); - } else { - conn_sock_readable = true; - conn_sock_writable = true; - g_unix_fd_add (conn_sock, G_IO_IN|G_IO_HUP|G_IO_ERR, conn_sock_cb, GINT_TO_POINTER(STDOUT_PIPE)); - ninfo("Accepted connection %d", conn_sock); - } - - return G_SOURCE_CONTINUE; -} - -static gboolean ctrl_cb(int fd, G_GNUC_UNUSED GIOCondition condition, G_GNUC_UNUSED gpointer user_data) -{ - #define CTLBUFSZ 200 - static char ctlbuf[CTLBUFSZ]; - static int readsz = CTLBUFSZ - 1; - static char *readptr = ctlbuf; - ssize_t num_read = 0; - int ctl_msg_type = -1; - int height = -1; - int width = -1; - struct winsize ws; - int ret; - - num_read = read(fd, readptr, readsz); - if (num_read <= 0) { - nwarn("Failed to read from control fd"); - return G_SOURCE_CONTINUE; - } - - readptr[num_read] = '\0'; - ninfo("Got ctl message: %s\n", ctlbuf); - - char *beg = ctlbuf; - char *newline = strchrnul(beg, '\n'); - /* Process each message which ends with a line */ - while (*newline != '\0') { - ret = sscanf(ctlbuf, "%d %d %d\n", &ctl_msg_type, &height, &width); - if (ret != 3) { - nwarn("Failed to sscanf message"); - return G_SOURCE_CONTINUE; - } - ninfo("Message type: %d, Height: %d, Width: %d", ctl_msg_type, height, width); - ret = ioctl(masterfd_stdout, TIOCGWINSZ, &ws); - ninfo("Existing size: %d %d", ws.ws_row, ws.ws_col); - ws.ws_row = height; - ws.ws_col = width; - ret = ioctl(masterfd_stdout, TIOCSWINSZ, &ws); - if (ret == -1) { - nwarn("Failed to set process pty terminal size"); - } - beg = newline + 1; - newline = strchrnul(beg, '\n'); - } - if (num_read == (CTLBUFSZ - 1) && beg == ctlbuf) { - /* - * We did not find a newline in the entire buffer. - * This shouldn't happen as our buffer is larger than - * the message that we expect to receive. - */ - nwarn("Could not find newline in entire buffer\n"); - } else if (*beg == '\0') { - /* We exhausted all messages that were complete */ - readptr = ctlbuf; - readsz = CTLBUFSZ - 1; - } else { - /* - * We copy remaining data to beginning of buffer - * and advance readptr after that. - */ - int cp_rem = 0; - do { - ctlbuf[cp_rem++] = *beg++; - } while (*beg != '\0'); - readptr = ctlbuf + cp_rem; - readsz = CTLBUFSZ - 1 - cp_rem; - } - - return G_SOURCE_CONTINUE; -} - -static gboolean terminal_accept_cb(int fd, G_GNUC_UNUSED GIOCondition condition, G_GNUC_UNUSED gpointer user_data) -{ - const char *csname = user_data; - struct file_t console; - int connfd = -1; - struct termios tset; - - ninfo("about to accept from console_socket_fd: %d", fd); - connfd = accept4(fd, NULL, NULL, SOCK_CLOEXEC); - if (connfd < 0) { - nwarn("Failed to accept console-socket connection"); - return G_SOURCE_CONTINUE; - } - - /* Not accepting anything else. */ - close(fd); - unlink(csname); - - /* We exit if this fails. */ - ninfo("about to recvfd from connfd: %d", connfd); - console = recvfd(connfd); - - ninfo("console = {.name = '%s'; .fd = %d}", console.name, console.fd); - free(console.name); - - /* We change the terminal settings to match kube settings */ - if (tcgetattr(console.fd, &tset) == -1) - pexit("Failed to get console terminal settings"); - - tset.c_oflag |= ONLCR; - - if (tcsetattr(console.fd, TCSANOW, &tset) == -1) - pexit("Failed to set console terminal settings"); - - /* We only have a single fd for both pipes, so we just treat it as - * stdout. stderr is ignored. */ - masterfd_stdin = console.fd; - masterfd_stdout = console.fd; - - /* Clean up everything */ - close(connfd); - - return G_SOURCE_CONTINUE; -} - -static void -runtime_exit_cb (G_GNUC_UNUSED GPid pid, int status, G_GNUC_UNUSED gpointer user_data) -{ - runtime_status = status; - g_main_loop_quit (main_loop); -} - -static void -container_exit_cb (G_GNUC_UNUSED GPid pid, int status, G_GNUC_UNUSED gpointer user_data) -{ - ninfo("container %d exited with status %d\n", pid, status); - container_status = status; - g_main_loop_quit (main_loop); -} - -static void write_sync_fd(int sync_pipe_fd, int res, const char *message) -{ - _cleanup_free_ char *escaped_message = NULL; - _cleanup_free_ char *json = NULL; - const char *res_key; - ssize_t len; - - if (sync_pipe_fd == -1) - return; - - if (opt_exec) - res_key = "exit_code"; - else - res_key = "pid"; - - if (message) { - escaped_message = escape_json_string(message); - json = g_strdup_printf ("{\"%s\": %d, \"message\": \"%s\"}\n", res_key, res, escaped_message); - } else { - json = g_strdup_printf ("{\"%s\": %d}\n", res_key, res); - } - - len = strlen(json); - if (write_all(sync_pipe_fd, json, len) != len) { - pexit("Unable to send container stderr message to parent"); - } -} - -static char *setup_console_socket(void) -{ - struct sockaddr_un addr = {0}; - _cleanup_free_ const char *tmpdir = g_get_tmp_dir(); - _cleanup_free_ char *csname = g_build_filename(tmpdir, "conmon-term.XXXXXX", NULL); - /* - * Generate a temporary name. Is this unsafe? Probably, but we can - * replace it with a rename(2) setup if necessary. - */ - - int unusedfd = g_mkstemp(csname); - if (unusedfd < 0) - pexit("Failed to generate random path for console-socket"); - close(unusedfd); - - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, csname, sizeof(addr.sun_path)-1); - - ninfo("addr{sun_family=AF_UNIX, sun_path=%s}", addr.sun_path); - - /* Bind to the console socket path. */ - console_socket_fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); - if (console_socket_fd < 0) - pexit("Failed to create console-socket"); - if (fchmod(console_socket_fd, 0700)) - pexit("Failed to change console-socket permissions"); - /* XXX: This should be handled with a rename(2). */ - if (unlink(csname) < 0) - pexit("Failed to unlink temporary random path"); - if (bind(console_socket_fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) - pexit("Failed to bind to console-socket"); - if (listen(console_socket_fd, 128) < 0) - pexit("Failed to listen on console-socket"); - - return g_strdup(csname); -} - -static char *setup_attach_socket(void) -{ - _cleanup_free_ char *attach_sock_path = NULL; - char *attach_symlink_dir_path; - struct sockaddr_un attach_addr = {0}; - attach_addr.sun_family = AF_UNIX; - - /* - * Create a symlink so we don't exceed unix domain socket - * path length limit. - */ - attach_symlink_dir_path = g_build_filename("/var/run/crio", opt_cuuid, NULL); - if (unlink(attach_symlink_dir_path) == -1 && errno != ENOENT) - pexit("Failed to remove existing symlink for attach socket directory"); - - if (symlink(opt_bundle_path, attach_symlink_dir_path) == -1) - pexit("Failed to create symlink for attach socket"); - - attach_sock_path = g_build_filename("/var/run/crio", opt_cuuid, "attach", NULL); - ninfo("attach sock path: %s", attach_sock_path); - - strncpy(attach_addr.sun_path, attach_sock_path, sizeof(attach_addr.sun_path) - 1); - ninfo("addr{sun_family=AF_UNIX, sun_path=%s}", attach_addr.sun_path); - - /* - * We make the socket non-blocking to avoid a race where client aborts connection - * before the server gets a chance to call accept. In that scenario, the server - * accept blocks till a new client connection comes in. - */ - attach_socket_fd = socket(AF_UNIX, SOCK_SEQPACKET|SOCK_NONBLOCK|SOCK_CLOEXEC, 0); - if (attach_socket_fd == -1) - pexit("Failed to create attach socket"); - - if (fchmod(attach_socket_fd, 0700)) - pexit("Failed to change attach socket permissions"); - - if (bind(attach_socket_fd, (struct sockaddr *)&attach_addr, sizeof(struct sockaddr_un)) == -1) - pexit("Failed to bind attach socket: %s", attach_sock_path); - - if (listen(attach_socket_fd, 10) == -1) - pexit("Failed to listen on attach socket: %s", attach_sock_path); - - g_unix_fd_add (attach_socket_fd, G_IO_IN, attach_cb, NULL); - - return attach_symlink_dir_path; -} - -static void setup_terminal_control_fifo() -{ - _cleanup_free_ char *ctl_fifo_path = g_build_filename(opt_bundle_path, "ctl", NULL); - ninfo("ctl fifo path: %s", ctl_fifo_path); - - /* Setup fifo for reading in terminal resize and other stdio control messages */ - - if (mkfifo(ctl_fifo_path, 0666) == -1) - pexit("Failed to mkfifo at %s", ctl_fifo_path); - - terminal_ctrl_fd = open(ctl_fifo_path, O_RDONLY|O_NONBLOCK|O_CLOEXEC); - if (terminal_ctrl_fd == -1) - pexit("Failed to open control fifo"); - - /* - * Open a dummy writer to prevent getting flood of POLLHUPs when - * last writer closes. - */ - int dummyfd = open(ctl_fifo_path, O_WRONLY|O_CLOEXEC); - if (dummyfd == -1) - pexit("Failed to open dummy writer for fifo"); - - g_unix_fd_add (terminal_ctrl_fd, G_IO_IN, ctrl_cb, NULL); - - ninfo("terminal_ctrl_fd: %d", terminal_ctrl_fd); -} - -static void setup_oom_handling(int container_pid) -{ - /* Setup OOM notification for container process */ - _cleanup_free_ char *memory_cgroup_path = process_cgroup_subsystem_path(container_pid, "memory"); - _cleanup_close_ int cfd = -1; - int ofd = -1; /* Not closed */ - if (!memory_cgroup_path) { - nexit("Failed to get memory cgroup path"); - } - - _cleanup_free_ char *memory_cgroup_file_path = g_build_filename(memory_cgroup_path, "cgroup.event_control", NULL); - - if ((cfd = open(memory_cgroup_file_path, O_WRONLY | O_CLOEXEC)) == -1) { - nwarn("Failed to open %s", memory_cgroup_file_path); - return; - } - - _cleanup_free_ char *memory_cgroup_file_oom_path = g_build_filename(memory_cgroup_path, "memory.oom_control", NULL); - if ((ofd = open(memory_cgroup_file_oom_path, O_RDONLY | O_CLOEXEC)) == -1) - pexit("Failed to open %s", memory_cgroup_file_oom_path); - - if ((oom_event_fd = eventfd(0, EFD_CLOEXEC)) == -1) - pexit("Failed to create eventfd"); - - _cleanup_free_ char *data = g_strdup_printf("%d %d", oom_event_fd, ofd); - if (write_all(cfd, data, strlen(data)) < 0) - pexit("Failed to write to cgroup.event_control"); - - g_unix_fd_add (oom_event_fd, G_IO_IN, oom_cb, NULL); -} - -int main(int argc, char *argv[]) -{ - int ret; - char cwd[PATH_MAX]; - _cleanup_free_ char *default_pid_file = NULL; - _cleanup_free_ char *csname = NULL; - GError *err = NULL; - _cleanup_free_ char *contents = NULL; - int container_pid = -1; - pid_t main_pid, create_pid; - /* Used for !terminal cases. */ - int slavefd_stdin = -1; - int slavefd_stdout = -1; - int slavefd_stderr = -1; - char buf[BUF_SIZE]; - int num_read; - int sync_pipe_fd = -1; - int start_pipe_fd = -1; - GError *error = NULL; - GOptionContext *context; - GPtrArray *runtime_argv = NULL; - _cleanup_close_ int dev_null_r = -1; - _cleanup_close_ int dev_null_w = -1; - int fds[2]; - - main_loop = g_main_loop_new (NULL, FALSE); - - /* Command line parameters */ - context = g_option_context_new("- conmon utility"); - g_option_context_add_main_entries(context, opt_entries, "conmon"); - if (!g_option_context_parse(context, &argc, &argv, &error)) { - g_print("option parsing failed: %s\n", error->message); - exit(1); - } - - if (opt_cid == NULL) - nexit("Container ID not provided. Use --cid"); - - if (!opt_exec && opt_cuuid == NULL) - nexit("Container UUID not provided. Use --cuuid"); - - if (opt_runtime_path == NULL) - nexit("Runtime path not provided. Use --runtime"); - - if (opt_bundle_path == NULL && !opt_exec) { - if (getcwd(cwd, sizeof(cwd)) == NULL) { - nexit("Failed to get working directory"); - } - opt_bundle_path = cwd; - } - - dev_null_r = open("/dev/null", O_RDONLY | O_CLOEXEC); - if (dev_null_r < 0) - pexit("Failed to open /dev/null"); - - dev_null_w = open("/dev/null", O_WRONLY | O_CLOEXEC); - if (dev_null_w < 0) - pexit("Failed to open /dev/null"); - - if (opt_exec && opt_exec_process_spec == NULL) { - nexit("Exec process spec path not provided. Use --exec-process-spec"); - } - - if (opt_pid_file == NULL) { - default_pid_file = g_strdup_printf ("%s/pidfile-%s", cwd, opt_cid); - opt_pid_file = default_pid_file; - } - - if (opt_log_path == NULL) - nexit("Log file path not provided. Use --log-path"); - - start_pipe_fd = get_pipe_fd_from_env("_OCI_STARTPIPE"); - if (start_pipe_fd >= 0) { - /* Block for an initial write to the start pipe before - spawning any childred or exiting, to ensure the - parent can put us in the right cgroup. */ - read(start_pipe_fd, buf, BUF_SIZE); - close(start_pipe_fd); - } - - /* In the create-container case we double-fork in - order to disconnect from the parent, as we want to - continue in a daemon-like way */ - main_pid = fork(); - if (main_pid < 0) { - pexit("Failed to fork the create command"); - } else if (main_pid != 0) { - exit(0); - } - - /* Disconnect stdio from parent. We need to do this, because - the parent is waiting for the stdout to end when the intermediate - child dies */ - if (dup2(dev_null_r, STDIN_FILENO) < 0) - pexit("Failed to dup over stdin"); - if (dup2(dev_null_w, STDOUT_FILENO) < 0) - pexit("Failed to dup over stdout"); - if (dup2(dev_null_w, STDERR_FILENO) < 0) - pexit("Failed to dup over stderr"); - - /* Create a new session group */ - setsid(); - - /* Environment variables */ - sync_pipe_fd = get_pipe_fd_from_env("_OCI_SYNCPIPE"); - - /* Open the log path file. */ - log_fd = open(opt_log_path, O_WRONLY | O_APPEND | O_CREAT | O_CLOEXEC, 0600); - if (log_fd < 0) - pexit("Failed to open log file"); - - /* - * Set self as subreaper so we can wait for container process - * and return its exit code. - */ - ret = prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0); - if (ret != 0) { - pexit("Failed to set as subreaper"); - } - - if (opt_terminal) { - csname = setup_console_socket(); - } else { - - /* - * Create a "fake" master fd so that we can use the same epoll code in - * both cases. The slavefd_*s will be closed after we dup over - * everything. - * - * We use pipes here because open(/dev/std{out,err}) will fail if we - * used anything else (and it wouldn't be a good idea to create a new - * pty pair in the host). - */ - - if (opt_stdin) { - if (pipe2(fds, O_CLOEXEC) < 0) - pexit("Failed to create !terminal stdin pipe"); - - masterfd_stdin = fds[1]; - slavefd_stdin = fds[0]; - } - - if (pipe2(fds, O_CLOEXEC) < 0) - pexit("Failed to create !terminal stdout pipe"); - - masterfd_stdout = fds[0]; - slavefd_stdout = fds[1]; - } - - /* We always create a stderr pipe, because that way we can capture - runc stderr messages before the tty is created */ - if (pipe2(fds, O_CLOEXEC) < 0) - pexit("Failed to create stderr pipe"); - - masterfd_stderr = fds[0]; - slavefd_stderr = fds[1]; - - runtime_argv = g_ptr_array_new(); - add_argv(runtime_argv, - opt_runtime_path, - NULL); - - /* Generate the cmdline. */ - if (!opt_exec && opt_systemd_cgroup) - add_argv(runtime_argv, - "--systemd-cgroup", - NULL); - - if (opt_exec) { - add_argv(runtime_argv, - "exec", "-d", - "--pid-file", opt_pid_file, - NULL); - } else { - add_argv(runtime_argv, - "create", - "--bundle", opt_bundle_path, - "--pid-file", opt_pid_file, - NULL); - } - - if (csname != NULL) { - add_argv(runtime_argv, - "--console-socket", csname, - NULL); - } - - /* Set the exec arguments. */ - if (opt_exec) { - add_argv(runtime_argv, - "--process", opt_exec_process_spec, - NULL); - } - - /* Container name comes last. */ - add_argv(runtime_argv, opt_cid, NULL); - end_argv(runtime_argv); - - /* - * We have to fork here because the current runC API dups the stdio of the - * calling process over the container's fds. This is actually *very bad* - * but is currently being discussed for change in - * https://github.com/opencontainers/runtime-spec/pull/513. Hopefully this - * won't be the case for very long. - */ - - /* Create our container. */ - create_pid = fork(); - if (create_pid < 0) { - pexit("Failed to fork the create command"); - } else if (!create_pid) { - /* FIXME: This results in us not outputting runc error messages to crio's log. */ - if (slavefd_stdin < 0) - slavefd_stdin = dev_null_r; - if (dup2(slavefd_stdin, STDIN_FILENO) < 0) - pexit("Failed to dup over stdout"); - - if (slavefd_stdout < 0) - slavefd_stdout = dev_null_w; - if (dup2(slavefd_stdout, STDOUT_FILENO) < 0) - pexit("Failed to dup over stdout"); - - if (slavefd_stderr < 0) - slavefd_stderr = slavefd_stdout; - if (dup2(slavefd_stderr, STDERR_FILENO) < 0) - pexit("Failed to dup over stderr"); - - execv(g_ptr_array_index(runtime_argv,0), (char **)runtime_argv->pdata); - exit(127); - } - - g_ptr_array_free (runtime_argv, TRUE); - - /* The runtime has that fd now. We don't need to touch it anymore. */ - close(slavefd_stdin); - close(slavefd_stdout); - close(slavefd_stderr); - - /* Map pid to its handler. */ - GHashTable *pid_to_handler = g_hash_table_new (g_int_hash, g_int_equal); - g_hash_table_insert (pid_to_handler, &create_pid, runtime_exit_cb); - - /* - * Glib does not support SIGCHLD so use SIGUSR1 with the same semantic. We will - * catch SIGCHLD and raise(SIGUSR1) in the signal handler. - */ - g_unix_signal_add (SIGUSR1, on_sigusr1_cb, pid_to_handler); - - if (signal(SIGCHLD, on_sigchld) == SIG_ERR) - pexit("Failed to set handler for SIGCHLD"); - - ninfo("about to waitpid: %d", create_pid); - if (csname != NULL) { - guint terminal_watch = g_unix_fd_add (console_socket_fd, G_IO_IN, terminal_accept_cb, csname); - /* Process any SIGCHLD we may have missed before the signal handler was in place. */ - check_child_processes (pid_to_handler); - g_main_loop_run (main_loop); - g_source_remove (terminal_watch); - } else { - int ret; - /* Wait for our create child to exit with the return code. */ - do - ret = waitpid(create_pid, &runtime_status, 0); - while (ret < 0 && errno == EINTR); - if (ret < 0) { - int old_errno = errno; - kill(create_pid, SIGKILL); - errno = old_errno; - pexit("Failed to wait for `runtime %s`", opt_exec ? "exec" : "create"); - } - - } - - if (!WIFEXITED(runtime_status) || WEXITSTATUS(runtime_status) != 0) { - if (sync_pipe_fd > 0) { - /* - * Read from container stderr for any error and send it to parent - * We send -1 as pid to signal to parent that create container has failed. - */ - num_read = read(masterfd_stderr, buf, BUF_SIZE); - if (num_read > 0) { - buf[num_read] = '\0'; - write_sync_fd(sync_pipe_fd, -1, buf); - } - } - nexit("Failed to create container: exit status %d", WEXITSTATUS(runtime_status)); - } - - if (opt_terminal && masterfd_stdout == -1) - nexit("Runtime did not set up terminal"); - - /* Read the pid so we can wait for the process to exit */ - g_file_get_contents(opt_pid_file, &contents, NULL, &err); - if (err) { - nwarn("Failed to read pidfile: %s", err->message); - g_error_free(err); - exit(1); - } - - container_pid = atoi(contents); - ninfo("container PID: %d", container_pid); - - g_hash_table_insert (pid_to_handler, &container_pid, container_exit_cb); - - /* Setup endpoint for attach */ - _cleanup_free_ char *attach_symlink_dir_path = NULL; - if (!opt_exec) { - attach_symlink_dir_path = setup_attach_socket(); - } - - if (!opt_exec) { - setup_terminal_control_fifo(); - } - - /* Send the container pid back to parent */ - if (!opt_exec) { - write_sync_fd(sync_pipe_fd, container_pid, NULL); - } - - setup_oom_handling(container_pid); - - if (masterfd_stdout >= 0) { - g_unix_fd_add (masterfd_stdout, G_IO_IN, stdio_cb, GINT_TO_POINTER(STDOUT_PIPE)); - } - if (masterfd_stderr >= 0) { - g_unix_fd_add (masterfd_stderr, G_IO_IN, stdio_cb, GINT_TO_POINTER(STDERR_PIPE)); - } - - if (opt_timeout > 0) { - g_timeout_add_seconds (opt_timeout, timeout_cb, NULL); - } - - check_child_processes(pid_to_handler); - - g_main_loop_run (main_loop); - - /* Drain stdout and stderr */ - if (masterfd_stdout != -1) { - g_unix_set_fd_nonblocking(masterfd_stdout, TRUE, NULL); - while (read_stdio(masterfd_stdout, STDOUT_PIPE, NULL)) - ; - } - if (masterfd_stderr != -1) { - g_unix_set_fd_nonblocking(masterfd_stderr, TRUE, NULL); - while (read_stdio(masterfd_stderr, STDERR_PIPE, NULL)) - ; - } - - int exit_status = -1; - const char *exit_message = NULL; - - if (timed_out) { - kill(container_pid, SIGKILL); - exit_message = "command timed out"; - } else { - exit_status = WEXITSTATUS(container_status); - } - - if (!opt_exec) { - _cleanup_free_ char *status_str = g_strdup_printf("%d", exit_status); - if (!g_file_set_contents("exit", status_str, -1, &err)) - nexit("Failed to write %s to exit file: %s\n", - status_str, err->message); - } else { - /* Send the command exec exit code back to the parent */ - write_sync_fd(sync_pipe_fd, exit_status, exit_message); - } - - if (attach_symlink_dir_path != NULL && - unlink(attach_symlink_dir_path) == -1 && errno != ENOENT) { - pexit("Failed to remove symlink for attach socket directory"); - } - - return EXIT_SUCCESS; -} diff --git a/vendor/github.com/kubernetes-incubator/cri-o/pkg/ocicni/noop.go b/vendor/github.com/kubernetes-incubator/cri-o/pkg/ocicni/noop.go deleted file mode 100644 index 954474388..000000000 --- a/vendor/github.com/kubernetes-incubator/cri-o/pkg/ocicni/noop.go +++ /dev/null @@ -1,24 +0,0 @@ -package ocicni - -type cniNoOp struct { -} - -func (noop *cniNoOp) Name() string { - return "CNINoOp" -} - -func (noop *cniNoOp) SetUpPod(netnsPath string, namespace string, name string, containerID string) error { - return nil -} - -func (noop *cniNoOp) TearDownPod(netnsPath string, namespace string, name string, containerID string) error { - return nil -} - -func (noop *cniNoOp) GetContainerNetworkStatus(netnsPath string, namespace string, name string, containerID string) (string, error) { - return "", nil -} - -func (noop *cniNoOp) Status() error { - return nil -} diff --git a/vendor/github.com/kubernetes-incubator/cri-o/pkg/ocicni/types.go b/vendor/github.com/kubernetes-incubator/cri-o/pkg/ocicni/types.go deleted file mode 100644 index 4483a203b..000000000 --- a/vendor/github.com/kubernetes-incubator/cri-o/pkg/ocicni/types.go +++ /dev/null @@ -1,35 +0,0 @@ -package ocicni - -const ( - // DefaultInterfaceName is the string to be used for the interface name inside the net namespace - DefaultInterfaceName = "eth0" - // CNIPluginName is the default name of the plugin - CNIPluginName = "cni" - // DefaultNetDir is the place to look for CNI Network - DefaultNetDir = "/etc/cni/net.d" - // DefaultCNIDir is the place to look for cni config files - DefaultCNIDir = "/opt/cni/bin" - // VendorCNIDirTemplate is the template for looking up vendor specific cni config/executable files - VendorCNIDirTemplate = "%s/opt/%s/bin" -) - -// CNIPlugin is the interface that needs to be implemented by a plugin -type CNIPlugin interface { - // Name returns the plugin's name. This will be used when searching - // for a plugin by name, e.g. - Name() string - - // SetUpPod is the method called after the infra container of - // the pod has been created but before the other containers of the - // pod are launched. - SetUpPod(netnsPath string, namespace string, name string, containerID string) error - - // TearDownPod is the method called before a pod's infra container will be deleted - TearDownPod(netnsPath string, namespace string, name string, containerID string) error - - // Status is the method called to obtain the ipv4 or ipv6 addresses of the container - GetContainerNetworkStatus(netnsPath string, namespace string, name string, containerID string) (string, error) - - // NetworkStatus returns error if the network plugin is in error state - Status() error -} diff --git a/vendor/github.com/kubernetes-incubator/cri-o/vendor.conf b/vendor/github.com/kubernetes-incubator/cri-o/vendor.conf deleted file mode 100644 index 813f08484..000000000 --- a/vendor/github.com/kubernetes-incubator/cri-o/vendor.conf +++ /dev/null @@ -1,73 +0,0 @@ -k8s.io/kubernetes v1.6.5 https://github.com/kubernetes/kubernetes -# https://github.com/kubernetes/client-go#compatibility-matrix -k8s.io/client-go v3.0.0-beta.0 https://github.com/kubernetes/client-go -k8s.io/apimachinery release-1.6 https://github.com/kubernetes/apimachinery -k8s.io/apiserver release-1.6 https://github.com/kubernetes/apiserver -# -github.com/sirupsen/logrus v1.0.0 -github.com/containers/image 74e359348c7ce9e0caf4fa75aa8de3809cf41c46 -github.com/ostreedev/ostree-go master -github.com/containers/storage f8cff0727cf0802f0752ca58d2c05ec5270a47d5 -github.com/containernetworking/cni v0.4.0 -google.golang.org/grpc v1.0.1-GA https://github.com/grpc/grpc-go -github.com/opencontainers/selinux v1.0.0-rc1 -github.com/opencontainers/go-digest v1.0.0-rc0 -github.com/opencontainers/runtime-tools 6bcd3b417fd6962ea04dafdbc2c07444e750572d -github.com/opencontainers/runc 45bde006ca8c90e089894508708bcf0e2cdf9e13 -github.com/opencontainers/image-spec v1.0.0 -github.com/opencontainers/runtime-spec v1.0.0 -github.com/juju/ratelimit acf38b000a03e4ab89e40f20f1e548f4e6ac7f72 -github.com/tchap/go-patricia v2.2.6 -gopkg.in/cheggaaa/pb.v1 v1.0.7 -gopkg.in/inf.v0 v0.9.0 -gopkg.in/yaml.v2 v2 -github.com/docker/docker d4f6db83c21cfc6af54fffb1f13e8acb7199f96a -github.com/docker/spdystream ed496381df8283605c435b86d4fdd6f4f20b8c6e -github.com/docker/distribution 7a8efe719e55bbfaff7bc5718cdf0ed51ca821df -github.com/docker/go-units v0.3.1 -github.com/docker/go-connections 3ede32e2033de7505e6500d6c868c2b9ed9f169d -github.com/docker/libtrust aabc10ec26b754e797f9028f4589c5b7bd90dc20 -github.com/mistifyio/go-zfs v2.1.1 -github.com/ghodss/yaml 04f313413ffd65ce25f2541bfd2b2ceec5c0908c -github.com/imdario/mergo 0.2.2 -github.com/gorilla/mux v1.3.0 -github.com/gorilla/context v1.1 -github.com/mtrmac/gpgme b2432428689ca58c2b8e8dea9449d3295cf96fc9 -github.com/mattn/go-runewidth v0.0.1 -github.com/seccomp/libseccomp-golang v0.9.0 -github.com/syndtr/gocapability e7cb7fa329f456b3855136a2642b197bad7366ba -github.com/blang/semver v3.5.0 -github.com/BurntSushi/toml v0.2.0 -github.com/mitchellh/go-wordwrap ad45545899c7b13c020ea92b2072220eefad42b8 -github.com/golang/glog 23def4e6c14b4da8ac2ed8007337bc5eb5007998 -github.com/davecgh/go-spew v1.1.0 -github.com/go-openapi/spec 02fb9cd3430ed0581e0ceb4804d5d4b3cc702694 -github.com/go-openapi/jsonpointer 779f45308c19820f1a69e9a4cd965f496e0da10f -github.com/go-openapi/jsonreference 36d33bfe519efae5632669801b180bf1a245da3b -github.com/go-openapi/swag d5f8ebc3b1c55a4cf6489eeae7354f338cfe299e -github.com/google/gofuzz 44d81051d367757e1c7c6a5a86423ece9afcf63c -github.com/mailru/easyjson 99e922cf9de1bc0ab38310c277cff32c2147e747 -github.com/PuerkitoBio/purell v1.1.0 -github.com/PuerkitoBio/urlesc 5bd2802263f21d8788851d5305584c82a5c75d7e -github.com/ugorji/go d23841a297e5489e787e72fceffabf9d2994b52a -github.com/spf13/pflag 9ff6c6923cfffbcd502984b8e0c80539a94968b7 -golang.org/x/crypto 3fbbcd23f1cb824e69491a5930cfeff09b12f4d2 -golang.org/x/net c427ad74c6d7a814201695e9ffde0c5d400a7674 -golang.org/x/sys 4cd6d1a821c7175768725b55ca82f14683a29ea4 -golang.org/x/text f72d8390a633d5dfb0cc84043294db9f6c935756 -github.com/kr/pty v1.0.0 -github.com/gogo/protobuf v0.3 -github.com/golang/protobuf 8ee79997227bf9b34611aee7946ae64735e6fd93 -github.com/coreos/go-systemd v14 -github.com/coreos/pkg v3 -github.com/golang/groupcache b710c8433bd175204919eb38776e944233235d03 -github.com/fsnotify/fsnotify 7d7316ed6e1ed2de075aab8dfc76de5d158d66e1 -github.com/emicklei/go-restful 09691a3b6378b740595c1002f40c34dd5f218a22 -github.com/Azure/go-ansiterm 19f72df4d05d31cbe1c56bfc8045c96babff6c7e -github.com/Microsoft/go-winio 78439966b38d69bf38227fbf57ac8a6fee70f69a -github.com/Microsoft/hcsshim 43f9725307998e09f2e3816c2c0c36dc98f0c982 -github.com/pkg/errors v0.8.0 -github.com/godbus/dbus v4.0.0 -github.com/urfave/cli v1.19.1 -github.com/vbatts/tar-split v0.10.1 -github.com/renstrom/dedent v1.0.0 From f6d99abcf4235b85f42a644634cd468f75624935 Mon Sep 17 00:00:00 2001 From: Lantao Liu Date: Wed, 23 Aug 2017 01:25:00 +0000 Subject: [PATCH 3/3] Add hostport support Signed-off-by: Lantao Liu --- hack/install-deps.sh | 36 ++++++++++--------- hack/test-cri.sh | 2 +- pkg/server/sandbox_run.go | 30 ++++++++++++++-- pkg/server/sandbox_run_test.go | 66 ++++++++++++++++++++++++++++++++++ pkg/server/sandbox_status.go | 4 +-- pkg/server/sandbox_stop.go | 10 ++++-- pkg/server/service.go | 2 +- 7 files changed, 124 insertions(+), 26 deletions(-) diff --git a/hack/install-deps.sh b/hack/install-deps.sh index d046acf54..9fd99efd2 100755 --- a/hack/install-deps.sh +++ b/hack/install-deps.sh @@ -32,7 +32,7 @@ ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"/.. BUILD_IMAGE=golang:1.8 RUNC_PKG=github.com/opencontainers/runc -CNI_PKG=github.com/containernetworking/cni +CNI_PKG=github.com/containernetworking/plugins CNI_DIR=/opt/cni CNI_CONFIG_DIR=/etc/cni/net.d CONTAINERD_PKG=github.com/containerd/containerd @@ -51,31 +51,33 @@ go get -d ${CNI_PKG}/... cd ${GOPATH}/src/${CNI_PKG} git fetch --all git checkout ${CNI_VERSION} -./build +./build.sh sudo mkdir -p ${CNI_DIR} sudo cp -r ./bin ${CNI_DIR} sudo mkdir -p ${CNI_CONFIG_DIR} -sudo bash -c 'cat >'${CNI_CONFIG_DIR}'/10-containerd-bridge.conf <'${CNI_CONFIG_DIR}'/10-containerd-net.conflist <'${CNI_CONFIG_DIR}'/99-loopback.conf <