Merge pull request #154 from Random-Liu/add-host-port
Add host port support.
This commit is contained in:
commit
b291ec0fa2
@ -32,7 +32,7 @@ ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"/..
|
|||||||
|
|
||||||
BUILD_IMAGE=golang:1.8
|
BUILD_IMAGE=golang:1.8
|
||||||
RUNC_PKG=github.com/opencontainers/runc
|
RUNC_PKG=github.com/opencontainers/runc
|
||||||
CNI_PKG=github.com/containernetworking/cni
|
CNI_PKG=github.com/containernetworking/plugins
|
||||||
CNI_DIR=/opt/cni
|
CNI_DIR=/opt/cni
|
||||||
CNI_CONFIG_DIR=/etc/cni/net.d
|
CNI_CONFIG_DIR=/etc/cni/net.d
|
||||||
CONTAINERD_PKG=github.com/containerd/containerd
|
CONTAINERD_PKG=github.com/containerd/containerd
|
||||||
@ -51,31 +51,33 @@ go get -d ${CNI_PKG}/...
|
|||||||
cd ${GOPATH}/src/${CNI_PKG}
|
cd ${GOPATH}/src/${CNI_PKG}
|
||||||
git fetch --all
|
git fetch --all
|
||||||
git checkout ${CNI_VERSION}
|
git checkout ${CNI_VERSION}
|
||||||
./build
|
./build.sh
|
||||||
sudo mkdir -p ${CNI_DIR}
|
sudo mkdir -p ${CNI_DIR}
|
||||||
sudo cp -r ./bin ${CNI_DIR}
|
sudo cp -r ./bin ${CNI_DIR}
|
||||||
sudo mkdir -p ${CNI_CONFIG_DIR}
|
sudo mkdir -p ${CNI_CONFIG_DIR}
|
||||||
sudo bash -c 'cat >'${CNI_CONFIG_DIR}'/10-containerd-bridge.conf <<EOF
|
sudo bash -c 'cat >'${CNI_CONFIG_DIR}'/10-containerd-net.conflist <<EOF
|
||||||
{
|
{
|
||||||
"cniVersion": "0.2.0",
|
"cniVersion": "0.3.1",
|
||||||
"name": "containerd-bridge",
|
"name": "containerd-net",
|
||||||
"type": "bridge",
|
"plugins": [
|
||||||
"bridge": "cni0",
|
{
|
||||||
"isGateway": true,
|
"type": "bridge",
|
||||||
"ipMasq": true,
|
"bridge": "cni0",
|
||||||
"ipam": {
|
"isGateway": true,
|
||||||
|
"ipMasq": true,
|
||||||
|
"ipam": {
|
||||||
"type": "host-local",
|
"type": "host-local",
|
||||||
"subnet": "10.88.0.0/16",
|
"subnet": "10.88.0.0/16",
|
||||||
"routes": [
|
"routes": [
|
||||||
{ "dst": "0.0.0.0/0" }
|
{ "dst": "0.0.0.0/0" }
|
||||||
]
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "portmap",
|
||||||
|
"capabilities": {"portMappings": true}
|
||||||
}
|
}
|
||||||
}
|
]
|
||||||
EOF'
|
|
||||||
sudo bash -c 'cat >'${CNI_CONFIG_DIR}'/99-loopback.conf <<EOF
|
|
||||||
{
|
|
||||||
"cniVersion": "0.2.0",
|
|
||||||
"type": "loopback"
|
|
||||||
}
|
}
|
||||||
EOF'
|
EOF'
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ source $(dirname "${BASH_SOURCE[0]}")/test-utils.sh
|
|||||||
# FOCUS focuses the test to run.
|
# FOCUS focuses the test to run.
|
||||||
FOCUS=${FOCUS:-}
|
FOCUS=${FOCUS:-}
|
||||||
# SKIP skips the test to skip.
|
# SKIP skips the test to skip.
|
||||||
SKIP=${SKIP:-"attach|RunAsUser|host port"}
|
SKIP=${SKIP:-"attach|RunAsUser"}
|
||||||
REPORT_DIR=${REPORT_DIR:-"/tmp/test-cri"}
|
REPORT_DIR=${REPORT_DIR:-"/tmp/test-cri"}
|
||||||
|
|
||||||
if [[ -z "${GOPATH}" ]]; then
|
if [[ -z "${GOPATH}" ]]; then
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
RUNC_VERSION=e775f0fba3ea329b8b766451c892c41a3d49594d
|
RUNC_VERSION=e775f0fba3ea329b8b766451c892c41a3d49594d
|
||||||
CNI_VERSION=v0.4.0
|
CNI_VERSION=v0.6.0
|
||||||
CONTAINERD_VERSION=938810e706bbcdbcb937ce63ba3e7c9ca329af64
|
CONTAINERD_VERSION=938810e706bbcdbcb937ce63ba3e7c9ca329af64
|
||||||
CRITEST_VERSION=74bbd4e142f752f13c648d9dde23defed3e472a2
|
CRITEST_VERSION=74bbd4e142f752f13c648d9dde23defed3e472a2
|
||||||
KUBERNETES_VERSION=493ee8b28560c118cebd2165ba9ef0959cfa2bc3
|
KUBERNETES_VERSION=493ee8b28560c118cebd2165ba9ef0959cfa2bc3
|
||||||
|
@ -25,6 +25,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
|
"github.com/cri-o/ocicni"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
runtimespec "github.com/opencontainers/runtime-spec/specs-go"
|
runtimespec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
@ -169,14 +170,20 @@ func (c *criContainerdService) RunPodSandbox(ctx context.Context, r *runtime.Run
|
|||||||
if !config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetHostNetwork() {
|
if !config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetHostNetwork() {
|
||||||
// Setup network for sandbox.
|
// Setup network for sandbox.
|
||||||
// TODO(random-liu): [P2] Replace with permanent network namespace.
|
// TODO(random-liu): [P2] Replace with permanent network namespace.
|
||||||
podName := config.GetMetadata().GetName()
|
podNetwork := ocicni.PodNetwork{
|
||||||
if err = c.netPlugin.SetUpPod(sandbox.NetNS, config.GetMetadata().GetNamespace(), podName, id); err != nil {
|
Name: config.GetMetadata().GetName(),
|
||||||
|
Namespace: config.GetMetadata().GetNamespace(),
|
||||||
|
ID: id,
|
||||||
|
NetNS: sandbox.NetNS,
|
||||||
|
PortMappings: toCNIPortMappings(config.GetPortMappings()),
|
||||||
|
}
|
||||||
|
if err = c.netPlugin.SetUpPod(podNetwork); err != nil {
|
||||||
return nil, fmt.Errorf("failed to setup network for sandbox %q: %v", id, err)
|
return nil, fmt.Errorf("failed to setup network for sandbox %q: %v", id, err)
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if retErr != nil {
|
if retErr != nil {
|
||||||
// Teardown network if an error is returned.
|
// Teardown network if an error is returned.
|
||||||
if err := c.netPlugin.TearDownPod(sandbox.NetNS, config.GetMetadata().GetNamespace(), podName, id); err != nil {
|
if err := c.netPlugin.TearDownPod(podNetwork); err != nil {
|
||||||
glog.Errorf("failed to destroy network for sandbox %q: %v", id, err)
|
glog.Errorf("failed to destroy network for sandbox %q: %v", id, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -372,3 +379,20 @@ func (c *criContainerdService) unmountSandboxFiles(rootDir string, config *runti
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// toCNIPortMappings converts CRI port mappings to CNI.
|
||||||
|
func toCNIPortMappings(criPortMappings []*runtime.PortMapping) []ocicni.PortMapping {
|
||||||
|
var portMappings []ocicni.PortMapping
|
||||||
|
for _, mapping := range criPortMappings {
|
||||||
|
if mapping.HostPort <= 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
portMappings = append(portMappings, ocicni.PortMapping{
|
||||||
|
HostPort: mapping.HostPort,
|
||||||
|
ContainerPort: mapping.ContainerPort,
|
||||||
|
Protocol: strings.ToLower(mapping.Protocol.String()),
|
||||||
|
HostIP: mapping.HostIp,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return portMappings
|
||||||
|
}
|
||||||
|
@ -20,6 +20,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/cri-o/ocicni"
|
||||||
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
runtimespec "github.com/opencontainers/runtime-spec/specs-go"
|
runtimespec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@ -303,5 +304,70 @@ options timeout:1
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestToCNIPortMappings(t *testing.T) {
|
||||||
|
for desc, test := range map[string]struct {
|
||||||
|
criPortMappings []*runtime.PortMapping
|
||||||
|
cniPortMappings []ocicni.PortMapping
|
||||||
|
}{
|
||||||
|
"empty CRI port mapping should map to empty CNI port mapping": {},
|
||||||
|
"CRI port mapping should be converted to CNI port mapping properly": {
|
||||||
|
criPortMappings: []*runtime.PortMapping{
|
||||||
|
{
|
||||||
|
Protocol: runtime.Protocol_UDP,
|
||||||
|
ContainerPort: 1234,
|
||||||
|
HostPort: 5678,
|
||||||
|
HostIp: "123.124.125.126",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Protocol: runtime.Protocol_TCP,
|
||||||
|
ContainerPort: 4321,
|
||||||
|
HostPort: 8765,
|
||||||
|
HostIp: "126.125.124.123",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
cniPortMappings: []ocicni.PortMapping{
|
||||||
|
{
|
||||||
|
HostPort: 5678,
|
||||||
|
ContainerPort: 1234,
|
||||||
|
Protocol: "udp",
|
||||||
|
HostIP: "123.124.125.126",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
HostPort: 8765,
|
||||||
|
ContainerPort: 4321,
|
||||||
|
Protocol: "tcp",
|
||||||
|
HostIP: "126.125.124.123",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"CRI port mapping without host port should be skipped": {
|
||||||
|
criPortMappings: []*runtime.PortMapping{
|
||||||
|
{
|
||||||
|
Protocol: runtime.Protocol_UDP,
|
||||||
|
ContainerPort: 1234,
|
||||||
|
HostIp: "123.124.125.126",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Protocol: runtime.Protocol_TCP,
|
||||||
|
ContainerPort: 4321,
|
||||||
|
HostPort: 8765,
|
||||||
|
HostIp: "126.125.124.123",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
cniPortMappings: []ocicni.PortMapping{
|
||||||
|
{
|
||||||
|
HostPort: 8765,
|
||||||
|
ContainerPort: 4321,
|
||||||
|
Protocol: "tcp",
|
||||||
|
HostIP: "126.125.124.123",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Logf("TestCase %q", desc)
|
||||||
|
assert.Equal(t, test.cniPortMappings, toCNIPortMappings(test.criPortMappings))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(random-liu): [P1] Add unit test for different error cases to make sure
|
// TODO(random-liu): [P1] Add unit test for different error cases to make sure
|
||||||
// the function cleans up on error properly.
|
// the function cleans up on error properly.
|
||||||
|
@ -64,11 +64,11 @@ func (c *criContainerdService) PodSandboxStatus(ctx context.Context, r *runtime.
|
|||||||
state = runtime.PodSandboxState_SANDBOX_READY
|
state = runtime.PodSandboxState_SANDBOX_READY
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ip, err := c.netPlugin.GetContainerNetworkStatus(sandbox.NetNS, sandbox.Config.GetMetadata().GetNamespace(), sandbox.Config.GetMetadata().GetName(), id)
|
ip, err := c.netPlugin.GetPodNetworkStatus(sandbox.NetNS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Ignore the error on network status
|
// Ignore the error on network status
|
||||||
ip = ""
|
ip = ""
|
||||||
glog.V(4).Infof("GetContainerNetworkStatus returns error: %v", err)
|
glog.V(4).Infof("GetPodNetworkStatus returns error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &runtime.PodSandboxStatusResponse{Status: toCRISandboxStatus(sandbox.Metadata, state, ip)}, nil
|
return &runtime.PodSandboxStatusResponse{Status: toCRISandboxStatus(sandbox.Metadata, state, ip)}, nil
|
||||||
|
@ -22,6 +22,7 @@ import (
|
|||||||
|
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
"github.com/containerd/containerd/errdefs"
|
"github.com/containerd/containerd/errdefs"
|
||||||
|
"github.com/cri-o/ocicni"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
|
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
|
||||||
@ -65,8 +66,13 @@ func (c *criContainerdService) StopPodSandbox(ctx context.Context, r *runtime.St
|
|||||||
_, err = c.os.Stat(sandbox.NetNS)
|
_, err = c.os.Stat(sandbox.NetNS)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if !sandbox.Config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetHostNetwork() {
|
if !sandbox.Config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetHostNetwork() {
|
||||||
if teardownErr := c.netPlugin.TearDownPod(sandbox.NetNS, sandbox.Config.GetMetadata().GetNamespace(),
|
if teardownErr := c.netPlugin.TearDownPod(ocicni.PodNetwork{
|
||||||
sandbox.Config.GetMetadata().GetName(), id); teardownErr != nil {
|
Name: sandbox.Config.GetMetadata().GetName(),
|
||||||
|
Namespace: sandbox.Config.GetMetadata().GetNamespace(),
|
||||||
|
ID: id,
|
||||||
|
NetNS: sandbox.NetNS,
|
||||||
|
PortMappings: toCNIPortMappings(sandbox.Config.GetPortMappings()),
|
||||||
|
}); teardownErr != nil {
|
||||||
return nil, fmt.Errorf("failed to destroy network for sandbox %q: %v", id, teardownErr)
|
return nil, fmt.Errorf("failed to destroy network for sandbox %q: %v", id, teardownErr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,8 +24,8 @@ import (
|
|||||||
"github.com/containerd/containerd/api/services/tasks/v1"
|
"github.com/containerd/containerd/api/services/tasks/v1"
|
||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/content"
|
||||||
"github.com/containerd/containerd/images"
|
"github.com/containerd/containerd/images"
|
||||||
|
"github.com/cri-o/ocicni"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"github.com/kubernetes-incubator/cri-o/pkg/ocicni"
|
|
||||||
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
|
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/server/streaming"
|
"k8s.io/kubernetes/pkg/kubelet/server/streaming"
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/kubernetes-incubator/cri-o/pkg/ocicni"
|
"github.com/cri-o/ocicni"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CalledDetail is the struct contains called function name and arguments.
|
// CalledDetail is the struct contains called function name and arguments.
|
||||||
@ -34,20 +34,12 @@ type CalledDetail struct {
|
|||||||
Argument interface{}
|
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.
|
// FakeCNIPlugin is a fake plugin used for test.
|
||||||
type FakeCNIPlugin struct {
|
type FakeCNIPlugin struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
called []CalledDetail
|
called []CalledDetail
|
||||||
errors map[string]error
|
errors map[string]error
|
||||||
IPMap map[CNIPluginArgument]string
|
IPMap map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
// getError get error for call
|
// getError get error for call
|
||||||
@ -108,18 +100,17 @@ func (f *FakeCNIPlugin) GetCalledDetails() []CalledDetail {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetFakePodNetwork sets the given IP for given arguments.
|
// 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()
|
f.Lock()
|
||||||
defer f.Unlock()
|
defer f.Unlock()
|
||||||
arg := CNIPluginArgument{netnsPath, namespace, name, containerID}
|
f.IPMap[podNetwork.NetNS] = ip
|
||||||
f.IPMap[arg] = ip
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFakeCNIPlugin create a FakeCNIPlugin.
|
// NewFakeCNIPlugin create a FakeCNIPlugin.
|
||||||
func NewFakeCNIPlugin() ocicni.CNIPlugin {
|
func NewFakeCNIPlugin() ocicni.CNIPlugin {
|
||||||
return &FakeCNIPlugin{
|
return &FakeCNIPlugin{
|
||||||
errors: make(map[string]error),
|
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.
|
// 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()
|
f.Lock()
|
||||||
defer f.Unlock()
|
defer f.Unlock()
|
||||||
arg := CNIPluginArgument{netnsPath, namespace, name, containerID}
|
f.appendCalled("SetUpPod", podNetwork)
|
||||||
f.appendCalled("SetUpPod", arg)
|
|
||||||
if err := f.getError("SetUpPod"); err != nil {
|
if err := f.getError("SetUpPod"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
f.IPMap[arg] = generateIP()
|
f.IPMap[podNetwork.NetNS] = generateIP()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TearDownPod teardown the network of PodSandbox.
|
// 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()
|
f.Lock()
|
||||||
defer f.Unlock()
|
defer f.Unlock()
|
||||||
arg := CNIPluginArgument{netnsPath, namespace, name, containerID}
|
f.appendCalled("TearDownPod", podNetwork)
|
||||||
f.appendCalled("TearDownPod", arg)
|
|
||||||
if err := f.getError("TearDownPod"); err != nil {
|
if err := f.getError("TearDownPod"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, ok := f.IPMap[arg]
|
_, ok := f.IPMap[podNetwork.NetNS]
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("failed to find the IP")
|
return fmt.Errorf("failed to find the IP")
|
||||||
}
|
}
|
||||||
delete(f.IPMap, arg)
|
delete(f.IPMap, podNetwork.NetNS)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetContainerNetworkStatus get the status of network.
|
// GetPodNetworkStatus get the status of network.
|
||||||
func (f *FakeCNIPlugin) GetContainerNetworkStatus(netnsPath string, namespace string, name string, containerID string) (string, error) {
|
func (f *FakeCNIPlugin) GetPodNetworkStatus(netnsPath string) (string, error) {
|
||||||
f.Lock()
|
f.Lock()
|
||||||
defer f.Unlock()
|
defer f.Unlock()
|
||||||
arg := CNIPluginArgument{netnsPath, namespace, name, containerID}
|
f.appendCalled("GetPodNetworkStatus", netnsPath)
|
||||||
f.appendCalled("GetContainerNetworkStatus", arg)
|
if err := f.getError("GetPodNetworkStatus"); err != nil {
|
||||||
if err := f.getError("GetContainerNetworkStatus"); err != nil {
|
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
ip, ok := f.IPMap[arg]
|
ip, ok := f.IPMap[netnsPath]
|
||||||
if !ok {
|
if !ok {
|
||||||
return "", fmt.Errorf("failed to find the IP")
|
return "", fmt.Errorf("failed to find the IP")
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,8 @@ github.com/blang/semver v3.1.0
|
|||||||
github.com/boltdb/bolt v1.3.0-58-ge9cf4fa
|
github.com/boltdb/bolt v1.3.0-58-ge9cf4fa
|
||||||
github.com/containerd/containerd f79981c2dfe35c3bfcbdd2de9b682e8c3de904b2
|
github.com/containerd/containerd f79981c2dfe35c3bfcbdd2de9b682e8c3de904b2
|
||||||
github.com/containerd/fifo fbfb6a11ec671efbe94ad1c12c2e98773f19e1e6
|
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/davecgh/go-spew v1.1.0
|
||||||
github.com/docker/distribution b38e5838b7b2f2ad48e06ec4b500011976080621
|
github.com/docker/distribution b38e5838b7b2f2ad48e06ec4b500011976080621
|
||||||
github.com/docker/docker cc4da8112814cdbb00dbf23370f9ed764383de1f
|
github.com/docker/docker cc4da8112814cdbb00dbf23370f9ed764383de1f
|
||||||
@ -21,7 +22,6 @@ github.com/go-openapi/spec 6aced65f8501fe1217321abf0749d354824ba2ff
|
|||||||
github.com/go-openapi/swag 1d0bd113de87027671077d3c71eb3ac5d7dbba72
|
github.com/go-openapi/swag 1d0bd113de87027671077d3c71eb3ac5d7dbba72
|
||||||
github.com/jpillora/backoff 06c7a16c845dc8e0bf575fafeeca0f5462f5eb4d
|
github.com/jpillora/backoff 06c7a16c845dc8e0bf575fafeeca0f5462f5eb4d
|
||||||
github.com/juju/ratelimit 5b9ff866471762aa2ab2dced63c9fb6f53921342
|
github.com/juju/ratelimit 5b9ff866471762aa2ab2dced63c9fb6f53921342
|
||||||
github.com/kubernetes-incubator/cri-o 63a218a45844fd912f482dc85f9cc149e68e0e57
|
|
||||||
github.com/mailru/easyjson d5b7844b561a7bc640052f1b935f7b800330d7e0
|
github.com/mailru/easyjson d5b7844b561a7bc640052f1b935f7b800330d7e0
|
||||||
github.com/Microsoft/go-winio v0.4.4
|
github.com/Microsoft/go-winio v0.4.4
|
||||||
github.com/opencontainers/go-digest 21dfd564fd89c944783d00d069f33e3e7123c448
|
github.com/opencontainers/go-digest 21dfd564fd89c944783d00d069f33e3e7123c448
|
||||||
|
57
vendor/github.com/containernetworking/cni/README.md
generated
vendored
57
vendor/github.com/containernetworking/cni/README.md
generated
vendored
@ -2,15 +2,25 @@
|
|||||||
[](https://coveralls.io/github/containernetworking/cni?branch=master)
|
[](https://coveralls.io/github/containernetworking/cni?branch=master)
|
||||||
[](https://cryptic-tundra-43194.herokuapp.com/)
|
[](https://cryptic-tundra-43194.herokuapp.com/)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 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
|
# CNI - the Container Network Interface
|
||||||
|
|
||||||
## What is CNI?
|
## 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.
|
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.
|
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.
|
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.
|
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)
|
- [rkt - container engine](https://coreos.com/blog/rkt-cni-networking.html)
|
||||||
- [Kurma - container runtime](http://kurma.io/)
|
- [Kurma - container runtime](http://kurma.io/)
|
||||||
- [Kubernetes - a system to simplify container operations](http://kubernetes.io/docs/admin/network-plugins/)
|
- [Kubernetes - a system to simplify container operations](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)
|
- [Mesos - a distributed systems kernel](https://github.com/apache/mesos/blob/master/docs/cni.md)
|
||||||
|
|
||||||
### 3rd party plugins
|
### 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)
|
- [SR-IOV](https://github.com/hustcat/sriov-cni)
|
||||||
- [Cilium - BPF & XDP for containers](https://github.com/cilium/cilium)
|
- [Cilium - BPF & XDP for containers](https://github.com/cilium/cilium)
|
||||||
- [Infoblox - enterprise IP address management for containers](https://github.com/infobloxopen/cni-infoblox)
|
- [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
|
## Contributing to CNI
|
||||||
@ -50,19 +67,16 @@ If you intend to contribute to code or documentation, please read [CONTRIBUTING.
|
|||||||
|
|
||||||
### Requirements
|
### 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
|
### Reference Plugins
|
||||||
dependencies. This flag is set by default in 1.6.
|
|
||||||
|
|
||||||
### Included 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.
|
||||||
This repository includes a number of common plugins in the `plugins/` directory.
|
|
||||||
Please see the [Documentation/](Documentation/) directory for documentation about particular plugins.
|
|
||||||
|
|
||||||
### Running the plugins
|
### 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`**
|
**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:
|
Next, build the plugins:
|
||||||
|
|
||||||
```bash
|
```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:
|
Finally, execute a command (`ifconfig` in this example) in a private network namespace that has joined the `mynet` network:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ CNI_PATH=`pwd`/bin
|
$ CNI_PATH=$GOPATH/src/github.com/containernetworking/plugins/bin
|
||||||
$ cd scripts
|
$ cd $GOPATH/src/github.com/containernetworking/cni/scripts
|
||||||
$ sudo CNI_PATH=$CNI_PATH ./priv-net-run.sh ifconfig
|
$ sudo CNI_PATH=$CNI_PATH ./priv-net-run.sh ifconfig
|
||||||
eth0 Link encap:Ethernet HWaddr f2:c2:6f:54:b8:2b
|
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
|
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
|
UP BROADCAST MULTICAST MTU:1500 Metric:1
|
||||||
RX packets:1 errors:0 dropped:0 overruns:0 frame:0
|
RX packets:1 errors:0 dropped:0 overruns:0 frame:0
|
||||||
TX packets:0 errors:0 dropped:1 overruns:0 carrier: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)
|
RX bytes:90 (90.0 B) TX bytes:0 (0.0 B)
|
||||||
|
|
||||||
lo Link encap:Local Loopback
|
lo Link encap:Local Loopback
|
||||||
@ -124,7 +139,7 @@ lo Link encap:Local Loopback
|
|||||||
UP LOOPBACK RUNNING MTU:65536 Metric:1
|
UP LOOPBACK RUNNING MTU:65536 Metric:1
|
||||||
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
|
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
|
||||||
TX packets:0 errors:0 dropped:0 overruns:0 carrier: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)
|
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:
|
Next, docker-run.sh script wraps `docker run`, to execute the plugins prior to entering the container:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ CNI_PATH=`pwd`/bin
|
$ CNI_PATH=$GOPATH/src/github.com/containernetworking/plugins/bin
|
||||||
$ cd scripts
|
$ cd $GOPATH/src/github.com/containernetworking/cni/scripts
|
||||||
$ sudo CNI_PATH=$CNI_PATH ./docker-run.sh --rm busybox:latest ifconfig
|
$ sudo CNI_PATH=$CNI_PATH ./docker-run.sh --rm busybox:latest ifconfig
|
||||||
eth0 Link encap:Ethernet HWaddr fa:60:70:aa:07:d1
|
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
|
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
|
UP BROADCAST MULTICAST MTU:1500 Metric:1
|
||||||
RX packets:1 errors:0 dropped:0 overruns:0 frame:0
|
RX packets:1 errors:0 dropped:0 overruns:0 frame:0
|
||||||
TX packets:0 errors:0 dropped:1 overruns:0 carrier: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)
|
RX bytes:90 (90.0 B) TX bytes:0 (0.0 B)
|
||||||
|
|
||||||
lo Link encap:Local Loopback
|
lo Link encap:Local Loopback
|
||||||
@ -154,7 +169,7 @@ lo Link encap:Local Loopback
|
|||||||
UP LOOPBACK RUNNING MTU:65536 Metric:1
|
UP LOOPBACK RUNNING MTU:65536 Metric:1
|
||||||
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
|
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
|
||||||
TX packets:0 errors:0 dropped:0 overruns:0 carrier: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)
|
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
135
vendor/github.com/containernetworking/cni/libcni/api.go
generated
vendored
135
vendor/github.com/containernetworking/cni/libcni/api.go
generated
vendored
@ -15,6 +15,7 @@
|
|||||||
package libcni
|
package libcni
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/containernetworking/cni/pkg/invoke"
|
"github.com/containernetworking/cni/pkg/invoke"
|
||||||
@ -27,6 +28,12 @@ type RuntimeConf struct {
|
|||||||
NetNS string
|
NetNS string
|
||||||
IfName string
|
IfName string
|
||||||
Args [][2]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 {
|
type NetworkConfig struct {
|
||||||
@ -34,8 +41,18 @@ type NetworkConfig struct {
|
|||||||
Bytes []byte
|
Bytes []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type NetworkConfigList struct {
|
||||||
|
Name string
|
||||||
|
CNIVersion string
|
||||||
|
Plugins []*NetworkConfig
|
||||||
|
Bytes []byte
|
||||||
|
}
|
||||||
|
|
||||||
type CNI interface {
|
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
|
DelNetwork(net *NetworkConfig, rt *RuntimeConf) error
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,13 +63,120 @@ type CNIConfig struct {
|
|||||||
// CNIConfig implements the CNI interface
|
// CNIConfig implements the CNI interface
|
||||||
var _ CNI = &CNIConfig{}
|
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
|
// 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)
|
pluginPath, err := invoke.FindInPath(net.Network.Type, c.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
net, err = injectRuntimeConfig(net, rt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return invoke.ExecPluginWithResult(pluginPath, net.Bytes, c.args("ADD", rt))
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
net, err = injectRuntimeConfig(net, rt)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return invoke.ExecPluginWithoutResult(pluginPath, net.Bytes, c.args("DEL", rt))
|
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,
|
NetNS: rt.NetNS,
|
||||||
PluginArgs: rt.Args,
|
PluginArgs: rt.Args,
|
||||||
IfName: rt.IfName,
|
IfName: rt.IfName,
|
||||||
Path: strings.Join(c.Path, ":"),
|
Path: strings.Join(c.Path, string(os.PathListSeparator)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
173
vendor/github.com/containernetworking/cni/libcni/conf.go
generated
vendored
173
vendor/github.com/containernetworking/cni/libcni/conf.go
generated
vendored
@ -23,6 +23,23 @@ import (
|
|||||||
"sort"
|
"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) {
|
func ConfFromBytes(bytes []byte) (*NetworkConfig, error) {
|
||||||
conf := &NetworkConfig{Bytes: bytes}
|
conf := &NetworkConfig{Bytes: bytes}
|
||||||
if err := json.Unmarshal(bytes, &conf.Network); err != nil {
|
if err := json.Unmarshal(bytes, &conf.Network); err != nil {
|
||||||
@ -39,7 +56,73 @@ func ConfFromFile(filename string) (*NetworkConfig, error) {
|
|||||||
return ConfFromBytes(bytes)
|
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
|
// In part, adapted from rkt/networking/podenv.go#listFiles
|
||||||
files, err := ioutil.ReadDir(dir)
|
files, err := ioutil.ReadDir(dir)
|
||||||
switch {
|
switch {
|
||||||
@ -56,20 +139,22 @@ func ConfFiles(dir string) ([]string, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
fileExt := filepath.Ext(f.Name())
|
fileExt := filepath.Ext(f.Name())
|
||||||
if fileExt == ".conf" || fileExt == ".json" {
|
for _, ext := range extensions {
|
||||||
confFiles = append(confFiles, filepath.Join(dir, f.Name()))
|
if fileExt == ext {
|
||||||
|
confFiles = append(confFiles, filepath.Join(dir, f.Name()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return confFiles, nil
|
return confFiles, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadConf(dir, name string) (*NetworkConfig, error) {
|
func LoadConf(dir, name string) (*NetworkConfig, error) {
|
||||||
files, err := ConfFiles(dir)
|
files, err := ConfFiles(dir, []string{".conf", ".json"})
|
||||||
switch {
|
switch {
|
||||||
case err != nil:
|
case err != nil:
|
||||||
return nil, err
|
return nil, err
|
||||||
case len(files) == 0:
|
case len(files) == 0:
|
||||||
return nil, fmt.Errorf("no net configurations found")
|
return nil, NoConfigsFoundError{Dir: dir}
|
||||||
}
|
}
|
||||||
sort.Strings(files)
|
sort.Strings(files)
|
||||||
|
|
||||||
@ -82,25 +167,59 @@ func LoadConf(dir, name string) (*NetworkConfig, error) {
|
|||||||
return conf, nil
|
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{})
|
config := make(map[string]interface{})
|
||||||
err := json.Unmarshal(original.Bytes, &config)
|
err := json.Unmarshal(original.Bytes, &config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unmarshal existing network bytes: %s", err)
|
return nil, fmt.Errorf("unmarshal existing network bytes: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if key == "" {
|
for key, value := range newValues {
|
||||||
return nil, fmt.Errorf("key value can not be empty")
|
if key == "" {
|
||||||
}
|
return nil, fmt.Errorf("keys cannot be empty")
|
||||||
|
}
|
||||||
|
|
||||||
if newValue == nil {
|
if value == nil {
|
||||||
return nil, fmt.Errorf("newValue must be specified")
|
return nil, fmt.Errorf("key '%s' value must not be nil", key)
|
||||||
}
|
}
|
||||||
|
|
||||||
config[key] = newValue
|
config[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
newBytes, err := json.Marshal(config)
|
newBytes, err := json.Marshal(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -109,3 +228,29 @@ func InjectConf(original *NetworkConfig, key string, newValue interface{}) (*Net
|
|||||||
|
|
||||||
return ConfFromBytes(newBytes)
|
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)
|
||||||
|
}
|
||||||
|
17
vendor/github.com/containernetworking/cni/pkg/invoke/args.go
generated
vendored
17
vendor/github.com/containernetworking/cni/pkg/invoke/args.go
generated
vendored
@ -57,13 +57,16 @@ func (args *Args) AsEnv() []string {
|
|||||||
pluginArgsStr = stringify(args.PluginArgs)
|
pluginArgsStr = stringify(args.PluginArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
env = append(env,
|
// Ensure that the custom values are first, so any value present in
|
||||||
"CNI_COMMAND="+args.Command,
|
// the process environment won't override them.
|
||||||
"CNI_CONTAINERID="+args.ContainerID,
|
env = append([]string{
|
||||||
"CNI_NETNS="+args.NetNS,
|
"CNI_COMMAND=" + args.Command,
|
||||||
"CNI_ARGS="+pluginArgsStr,
|
"CNI_CONTAINERID=" + args.ContainerID,
|
||||||
"CNI_IFNAME="+args.IfName,
|
"CNI_NETNS=" + args.NetNS,
|
||||||
"CNI_PATH="+args.Path)
|
"CNI_ARGS=" + pluginArgsStr,
|
||||||
|
"CNI_IFNAME=" + args.IfName,
|
||||||
|
"CNI_PATH=" + args.Path,
|
||||||
|
}, env...)
|
||||||
return env
|
return env
|
||||||
}
|
}
|
||||||
|
|
||||||
|
8
vendor/github.com/containernetworking/cni/pkg/invoke/delegate.go
generated
vendored
8
vendor/github.com/containernetworking/cni/pkg/invoke/delegate.go
generated
vendored
@ -17,17 +17,17 @@ package invoke
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/containernetworking/cni/pkg/types"
|
"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" {
|
if os.Getenv("CNI_COMMAND") != "ADD" {
|
||||||
return nil, fmt.Errorf("CNI_COMMAND is not 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)
|
pluginPath, err := FindInPath(delegatePlugin, paths)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -42,7 +42,7 @@ func DelegateDel(delegatePlugin string, netconf []byte) error {
|
|||||||
return fmt.Errorf("CNI_COMMAND is not DEL")
|
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)
|
pluginPath, err := FindInPath(delegatePlugin, paths)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
16
vendor/github.com/containernetworking/cni/pkg/invoke/exec.go
generated
vendored
16
vendor/github.com/containernetworking/cni/pkg/invoke/exec.go
generated
vendored
@ -15,7 +15,6 @@
|
|||||||
package invoke
|
package invoke
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
@ -23,7 +22,7 @@ import (
|
|||||||
"github.com/containernetworking/cni/pkg/version"
|
"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)
|
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())
|
stdoutBytes, err := e.RawExec.ExecPlugin(pluginPath, netconf, args.AsEnv())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
res := &types.Result{}
|
// Plugin must return result in same version as specified in netconf
|
||||||
err = json.Unmarshal(stdoutBytes, res)
|
versionDecoder := &version.ConfigDecoder{}
|
||||||
return res, err
|
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 {
|
func (e *PluginExec) WithoutResult(pluginPath string, netconf []byte, args CNIArgs) error {
|
||||||
|
16
vendor/github.com/containernetworking/cni/pkg/invoke/find.go
generated
vendored
16
vendor/github.com/containernetworking/cni/pkg/invoke/find.go
generated
vendored
@ -30,18 +30,14 @@ func FindInPath(plugin string, paths []string) (string, error) {
|
|||||||
return "", fmt.Errorf("no paths provided")
|
return "", fmt.Errorf("no paths provided")
|
||||||
}
|
}
|
||||||
|
|
||||||
var fullpath string
|
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
full := filepath.Join(path, plugin)
|
for _, fe := range ExecutableFileExtensions {
|
||||||
if fi, err := os.Stat(full); err == nil && fi.Mode().IsRegular() {
|
fullpath := filepath.Join(path, plugin) + fe
|
||||||
fullpath = full
|
if fi, err := os.Stat(fullpath); err == nil && fi.Mode().IsRegular() {
|
||||||
break
|
return fullpath, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if fullpath == "" {
|
return "", fmt.Errorf("failed to find plugin %q in path %s", plugin, paths)
|
||||||
return "", fmt.Errorf("failed to find plugin %q in path %s", plugin, paths)
|
|
||||||
}
|
|
||||||
|
|
||||||
return fullpath, nil
|
|
||||||
}
|
}
|
||||||
|
20
vendor/github.com/containernetworking/cni/pkg/invoke/os_unix.go
generated
vendored
Normal file
20
vendor/github.com/containernetworking/cni/pkg/invoke/os_unix.go
generated
vendored
Normal file
@ -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{""}
|
18
vendor/github.com/containernetworking/cni/pkg/invoke/os_windows.go
generated
vendored
Normal file
18
vendor/github.com/containernetworking/cni/pkg/invoke/os_windows.go
generated
vendored
Normal file
@ -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", ""}
|
8
vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go
generated
vendored
8
vendor/github.com/containernetworking/cni/pkg/invoke/raw_exec.go
generated
vendored
@ -50,13 +50,9 @@ func pluginErr(err error, output []byte) error {
|
|||||||
if _, ok := err.(*exec.ExitError); ok {
|
if _, ok := err.(*exec.ExitError); ok {
|
||||||
emsg := types.Error{}
|
emsg := types.Error{}
|
||||||
if perr := json.Unmarshal(output, &emsg); perr != nil {
|
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 := ""
|
return &emsg
|
||||||
if emsg.Details != "" {
|
|
||||||
details = fmt.Sprintf("; %v", emsg.Details)
|
|
||||||
}
|
|
||||||
return fmt.Errorf("%v%v", emsg.Msg, details)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
|
135
vendor/github.com/containernetworking/cni/pkg/types/020/types.go
generated
vendored
Normal file
135
vendor/github.com/containernetworking/cni/pkg/types/020/types.go
generated
vendored
Normal file
@ -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
|
||||||
|
}
|
15
vendor/github.com/containernetworking/cni/pkg/types/args.go
generated
vendored
15
vendor/github.com/containernetworking/cni/pkg/types/args.go
generated
vendored
@ -63,6 +63,12 @@ func GetKeyField(keyString string, v reflect.Value) reflect.Value {
|
|||||||
return v.Elem().FieldByName(keyString)
|
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;..."
|
// LoadArgs parses args from a string in the form "K=V;K2=V2;..."
|
||||||
func LoadArgs(args string, container interface{}) error {
|
func LoadArgs(args string, container interface{}) error {
|
||||||
if args == "" {
|
if args == "" {
|
||||||
@ -85,8 +91,13 @@ func LoadArgs(args string, container interface{}) error {
|
|||||||
unknownArgs = append(unknownArgs, pair)
|
unknownArgs = append(unknownArgs, pair)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
keyFieldIface := keyField.Addr().Interface()
|
||||||
u := keyField.Addr().Interface().(encoding.TextUnmarshaler)
|
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))
|
err := u.UnmarshalText([]byte(valueString))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("ARGS: error parsing value of pair %q: %v)", pair, err)
|
return fmt.Errorf("ARGS: error parsing value of pair %q: %v)", pair, err)
|
||||||
|
300
vendor/github.com/containernetworking/cni/pkg/types/current/types.go
generated
vendored
Normal file
300
vendor/github.com/containernetworking/cni/pkg/types/current/types.go
generated
vendored
Normal file
@ -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
|
||||||
|
}
|
102
vendor/github.com/containernetworking/cni/pkg/types/types.go
generated
vendored
102
vendor/github.com/containernetworking/cni/pkg/types/types.go
generated
vendored
@ -16,6 +16,7 @@ package types
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
@ -59,44 +60,48 @@ func (n *IPNet) UnmarshalJSON(data []byte) error {
|
|||||||
type NetConf struct {
|
type NetConf struct {
|
||||||
CNIVersion string `json:"cniVersion,omitempty"`
|
CNIVersion string `json:"cniVersion,omitempty"`
|
||||||
|
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
Type string `json:"type,omitempty"`
|
Type string `json:"type,omitempty"`
|
||||||
IPAM struct {
|
Capabilities map[string]bool `json:"capabilities,omitempty"`
|
||||||
|
IPAM struct {
|
||||||
Type string `json:"type,omitempty"`
|
Type string `json:"type,omitempty"`
|
||||||
} `json:"ipam,omitempty"`
|
} `json:"ipam,omitempty"`
|
||||||
DNS DNS `json:"dns"`
|
DNS DNS `json:"dns"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Result is what gets returned from the plugin (via stdout) to the caller
|
// NetConfList describes an ordered list of networks.
|
||||||
type Result struct {
|
type NetConfList struct {
|
||||||
IP4 *IPConfig `json:"ip4,omitempty"`
|
CNIVersion string `json:"cniVersion,omitempty"`
|
||||||
IP6 *IPConfig `json:"ip6,omitempty"`
|
|
||||||
DNS DNS `json:"dns,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
|
Plugins []*NetConf `json:"plugins,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Result) Print() error {
|
type ResultFactoryFunc func([]byte) (Result, error)
|
||||||
return prettyPrint(r)
|
|
||||||
|
// 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
|
func PrintResult(result Result, version string) error {
|
||||||
// $1 represents the receiver's IPv4, $2 represents the receiver's IPv6 and $3 the
|
newResult, err := result.GetAsVersion(version)
|
||||||
// receiver's DNS. If $1 or $2 are nil, they won't be present in the returned string.
|
if err != nil {
|
||||||
func (r *Result) String() string {
|
return err
|
||||||
var str string
|
|
||||||
if r.IP4 != nil {
|
|
||||||
str = fmt.Sprintf("IP4:%+v, ", *r.IP4)
|
|
||||||
}
|
}
|
||||||
if r.IP6 != nil {
|
return newResult.Print()
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DNS contains values interesting for DNS resolvers
|
// DNS contains values interesting for DNS resolvers
|
||||||
@ -112,6 +117,10 @@ type Route struct {
|
|||||||
GW net.IP
|
GW net.IP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Route) String() string {
|
||||||
|
return fmt.Sprintf("%+v", *r)
|
||||||
|
}
|
||||||
|
|
||||||
// Well known error codes
|
// Well known error codes
|
||||||
// see https://github.com/containernetworking/cni/blob/master/SPEC.md#well-known-error-codes
|
// see https://github.com/containernetworking/cni/blob/master/SPEC.md#well-known-error-codes
|
||||||
const (
|
const (
|
||||||
@ -127,7 +136,11 @@ type Error struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *Error) Error() string {
|
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 {
|
func (e *Error) Print() error {
|
||||||
@ -138,39 +151,11 @@ func (e *Error) Print() error {
|
|||||||
// for our custom IPNet type
|
// for our custom IPNet type
|
||||||
|
|
||||||
// JSON (un)marshallable types
|
// 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 {
|
type route struct {
|
||||||
Dst IPNet `json:"dst"`
|
Dst IPNet `json:"dst"`
|
||||||
GW net.IP `json:"gw,omitempty"`
|
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 {
|
func (r *Route) UnmarshalJSON(data []byte) error {
|
||||||
rt := route{}
|
rt := route{}
|
||||||
if err := json.Unmarshal(data, &rt); err != nil {
|
if err := json.Unmarshal(data, &rt); err != nil {
|
||||||
@ -199,3 +184,6 @@ func prettyPrint(obj interface{}) error {
|
|||||||
_, err = os.Stdout.Write(data)
|
_, err = os.Stdout.Write(data)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NotImplementedError is used to indicate that a method is not implemented for the given platform
|
||||||
|
var NotImplementedError = errors.New("Not Implemented")
|
||||||
|
20
vendor/github.com/containernetworking/cni/pkg/version/reconcile.go
generated
vendored
20
vendor/github.com/containernetworking/cni/pkg/version/reconcile.go
generated
vendored
@ -17,12 +17,12 @@ package version
|
|||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
type ErrorIncompatible struct {
|
type ErrorIncompatible struct {
|
||||||
Config string
|
Config string
|
||||||
Plugin []string
|
Supported []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *ErrorIncompatible) Details() 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 {
|
func (e *ErrorIncompatible) Error() string {
|
||||||
@ -31,17 +31,19 @@ func (e *ErrorIncompatible) Error() string {
|
|||||||
|
|
||||||
type Reconciler struct{}
|
type Reconciler struct{}
|
||||||
|
|
||||||
func (*Reconciler) Check(configVersion string, pluginInfo PluginInfo) *ErrorIncompatible {
|
func (r *Reconciler) Check(configVersion string, pluginInfo PluginInfo) *ErrorIncompatible {
|
||||||
pluginVersions := pluginInfo.SupportedVersions()
|
return r.CheckRaw(configVersion, pluginInfo.SupportedVersions())
|
||||||
|
}
|
||||||
|
|
||||||
for _, pluginVersion := range pluginVersions {
|
func (*Reconciler) CheckRaw(configVersion string, supportedVersions []string) *ErrorIncompatible {
|
||||||
if configVersion == pluginVersion {
|
for _, supportedVersion := range supportedVersions {
|
||||||
|
if configVersion == supportedVersion {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ErrorIncompatible{
|
return &ErrorIncompatible{
|
||||||
Config: configVersion,
|
Config: configVersion,
|
||||||
Plugin: pluginVersions,
|
Supported: supportedVersions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
34
vendor/github.com/containernetworking/cni/pkg/version/version.go
generated
vendored
34
vendor/github.com/containernetworking/cni/pkg/version/version.go
generated
vendored
@ -14,9 +14,17 @@
|
|||||||
|
|
||||||
package version
|
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
|
// Current reports the version of the CNI spec implemented by this library
|
||||||
func Current() string {
|
func Current() string {
|
||||||
return "0.2.0"
|
return "0.3.1"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Legacy PluginInfo describes a plugin that is backwards compatible with the
|
// 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
|
// Any future CNI spec versions which meet this definition should be added to
|
||||||
// this list.
|
// this list.
|
||||||
var Legacy = PluginSupports("0.1.0", "0.2.0")
|
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)
|
||||||
|
}
|
||||||
|
24
vendor/github.com/cri-o/ocicni/noop.go
generated
vendored
Normal file
24
vendor/github.com/cri-o/ocicni/noop.go
generated
vendored
Normal file
@ -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
|
||||||
|
}
|
@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/containernetworking/cni/libcni"
|
"github.com/containernetworking/cni/libcni"
|
||||||
@ -29,7 +30,7 @@ type cniNetworkPlugin struct {
|
|||||||
|
|
||||||
type cniNetwork struct {
|
type cniNetwork struct {
|
||||||
name string
|
name string
|
||||||
NetworkConfig *libcni.NetworkConfig
|
NetworkConfig *libcni.NetworkConfigList
|
||||||
CNIConfig libcni.CNI
|
CNIConfig libcni.CNI
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,7 +129,7 @@ func getDefaultCNINetwork(pluginDir string, cniDirs []string, vendorCNIDirPrefix
|
|||||||
cniDirs = []string{DefaultCNIDir}
|
cniDirs = []string{DefaultCNIDir}
|
||||||
}
|
}
|
||||||
|
|
||||||
files, err := libcni.ConfFiles(pluginDir)
|
files, err := libcni.ConfFiles(pluginDir, []string{".conf", ".conflist", ".json"})
|
||||||
switch {
|
switch {
|
||||||
case err != nil:
|
case err != nil:
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -138,19 +139,39 @@ func getDefaultCNINetwork(pluginDir string, cniDirs []string, vendorCNIDirPrefix
|
|||||||
|
|
||||||
sort.Strings(files)
|
sort.Strings(files)
|
||||||
for _, confFile := range files {
|
for _, confFile := range files {
|
||||||
conf, err := libcni.ConfFromFile(confFile)
|
var confList *libcni.NetworkConfigList
|
||||||
if err != nil {
|
if strings.HasSuffix(confFile, ".conflist") {
|
||||||
logrus.Warningf("Error loading CNI config file %s: %v", confFile, err)
|
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
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search for vendor-specific plugins as well as default plugins in the CNI codebase.
|
// 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{
|
cninet := &libcni.CNIConfig{
|
||||||
Path: append(cniDirs, vendorDir),
|
Path: append(cniDirs, vendorDir),
|
||||||
}
|
}
|
||||||
|
network := &cniNetwork{name: confList.Name, NetworkConfig: confList, CNIConfig: cninet}
|
||||||
network := &cniNetwork{name: conf.Network.Name, NetworkConfig: conf, CNIConfig: cninet}
|
|
||||||
return network, nil
|
return network, nil
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("No valid networks found in %s", pluginDir)
|
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}
|
cniDirs = []string{DefaultCNIDir}
|
||||||
}
|
}
|
||||||
|
|
||||||
loConfig, err := libcni.ConfFromBytes([]byte(`{
|
loConfig, err := libcni.ConfListFromBytes([]byte(`{
|
||||||
"cniVersion": "0.1.0",
|
"cniVersion": "0.2.0",
|
||||||
"name": "cni-loopback",
|
"name": "cni-loopback",
|
||||||
"type": "loopback"
|
"plugins": [{
|
||||||
|
"type": "loopback"
|
||||||
|
}]
|
||||||
}`))
|
}`))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// The hardcoded config above should always be valid and unit tests will
|
// The hardcoded config above should always be valid and unit tests will
|
||||||
// catch this
|
// catch this
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
vendorDir := vendorCNIDir(vendorDirPrefix, loConfig.Network.Type)
|
vendorDir := vendorCNIDir(vendorDirPrefix, loConfig.Plugins[0].Network.Type)
|
||||||
cninet := &libcni.CNIConfig{
|
cninet := &libcni.CNIConfig{
|
||||||
Path: append(cniDirs, vendorDir),
|
Path: append(cniDirs, vendorDir),
|
||||||
}
|
}
|
||||||
@ -222,18 +245,18 @@ func (plugin *cniNetworkPlugin) Name() string {
|
|||||||
return CNIPluginName
|
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 {
|
if err := plugin.checkInitialized(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := plugin.loNetwork.addToNetwork(name, namespace, id, netnsPath)
|
_, err := plugin.loNetwork.addToNetwork(podNetwork)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("Error while adding to cni lo network: %s", err)
|
logrus.Errorf("Error while adding to cni lo network: %s", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = plugin.getDefaultNetwork().addToNetwork(name, namespace, id, netnsPath)
|
_, err = plugin.getDefaultNetwork().addToNetwork(podNetwork)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("Error while adding to cni network: %s", err)
|
logrus.Errorf("Error while adding to cni network: %s", err)
|
||||||
return err
|
return err
|
||||||
@ -242,17 +265,17 @@ func (plugin *cniNetworkPlugin) SetUpPod(netnsPath string, namespace string, nam
|
|||||||
return err
|
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 {
|
if err := plugin.checkInitialized(); err != nil {
|
||||||
return err
|
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.
|
// 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
|
// 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")
|
ip, err := getContainerIP(plugin.nsenterPath, netnsPath, DefaultInterfaceName, "-4")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@ -261,16 +284,16 @@ func (plugin *cniNetworkPlugin) GetContainerNetworkStatus(netnsPath string, name
|
|||||||
return ip.String(), nil
|
return ip.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (network *cniNetwork) addToNetwork(podName string, podNamespace string, podInfraContainerID string, podNetnsPath string) (*cnitypes.Result, error) {
|
func (network *cniNetwork) addToNetwork(podNetwork PodNetwork) (cnitypes.Result, error) {
|
||||||
rt, err := buildCNIRuntimeConf(podName, podNamespace, podInfraContainerID, podNetnsPath)
|
rt, err := buildCNIRuntimeConf(podNetwork)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("Error adding network: %v", err)
|
logrus.Errorf("Error adding network: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
netconf, cninet := network.NetworkConfig, network.CNIConfig
|
netconf, cninet := network.NetworkConfig, network.CNIConfig
|
||||||
logrus.Infof("About to run with conf.Network.Type=%v", netconf.Network.Type)
|
logrus.Infof("About to add CNI network %v (type=%v)", netconf.Name, netconf.Plugins[0].Network.Type)
|
||||||
res, err := cninet.AddNetwork(netconf, rt)
|
res, err := cninet.AddNetworkList(netconf, rt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("Error adding network: %v", err)
|
logrus.Errorf("Error adding network: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -279,16 +302,16 @@ func (network *cniNetwork) addToNetwork(podName string, podNamespace string, pod
|
|||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (network *cniNetwork) deleteFromNetwork(podName string, podNamespace string, podInfraContainerID string, podNetnsPath string) error {
|
func (network *cniNetwork) deleteFromNetwork(podNetwork PodNetwork) error {
|
||||||
rt, err := buildCNIRuntimeConf(podName, podNamespace, podInfraContainerID, podNetnsPath)
|
rt, err := buildCNIRuntimeConf(podNetwork)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("Error deleting network: %v", err)
|
logrus.Errorf("Error deleting network: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
netconf, cninet := network.NetworkConfig, network.CNIConfig
|
netconf, cninet := network.NetworkConfig, network.CNIConfig
|
||||||
logrus.Infof("About to run with conf.Network.Type=%v", netconf.Network.Type)
|
logrus.Infof("About to del CNI network %v (type=%v)", netconf.Name, netconf.Plugins[0].Network.Type)
|
||||||
err = cninet.DelNetwork(netconf, rt)
|
err = cninet.DelNetworkList(netconf, rt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("Error deleting network: %v", err)
|
logrus.Errorf("Error deleting network: %v", err)
|
||||||
return err
|
return err
|
||||||
@ -296,22 +319,28 @@ func (network *cniNetwork) deleteFromNetwork(podName string, podNamespace string
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildCNIRuntimeConf(podName string, podNs string, podInfraContainerID string, podNetnsPath string) (*libcni.RuntimeConf, error) {
|
func buildCNIRuntimeConf(podNetwork PodNetwork) (*libcni.RuntimeConf, error) {
|
||||||
logrus.Infof("Got netns path %v", podNetnsPath)
|
logrus.Infof("Got pod network %+v", podNetwork)
|
||||||
logrus.Infof("Using netns path %v", podNs)
|
|
||||||
|
|
||||||
rt := &libcni.RuntimeConf{
|
rt := &libcni.RuntimeConf{
|
||||||
ContainerID: podInfraContainerID,
|
ContainerID: podNetwork.ID,
|
||||||
NetNS: podNetnsPath,
|
NetNS: podNetwork.NetNS,
|
||||||
IfName: DefaultInterfaceName,
|
IfName: DefaultInterfaceName,
|
||||||
Args: [][2]string{
|
Args: [][2]string{
|
||||||
{"IgnoreUnknown", "1"},
|
{"IgnoreUnknown", "1"},
|
||||||
{"K8S_POD_NAMESPACE", podNs},
|
{"K8S_POD_NAMESPACE", podNetwork.Namespace},
|
||||||
{"K8S_POD_NAME", podName},
|
{"K8S_POD_NAME", podNetwork.Name},
|
||||||
{"K8S_POD_INFRA_CONTAINER_ID", podInfraContainerID},
|
{"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
|
return rt, nil
|
||||||
}
|
}
|
||||||
|
|
62
vendor/github.com/cri-o/ocicni/types.go
generated
vendored
Normal file
62
vendor/github.com/cri-o/ocicni/types.go
generated
vendored
Normal file
@ -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
|
||||||
|
}
|
201
vendor/github.com/kubernetes-incubator/cri-o/LICENSE
generated
vendored
201
vendor/github.com/kubernetes-incubator/cri-o/LICENSE
generated
vendored
@ -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.
|
|
217
vendor/github.com/kubernetes-incubator/cri-o/README.md
generated
vendored
217
vendor/github.com/kubernetes-incubator/cri-o/README.md
generated
vendored
@ -1,217 +0,0 @@
|
|||||||

|
|
||||||
# cri-o - OCI-based implementation of Kubernetes Container Runtime Interface
|
|
||||||
|
|
||||||
[](https://travis-ci.org/kubernetes-incubator/cri-o)
|
|
||||||
[](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
|
|
149
vendor/github.com/kubernetes-incubator/cri-o/conmon/cmsg.c
generated
vendored
149
vendor/github.com/kubernetes-incubator/cri-o/conmon/cmsg.c
generated
vendored
@ -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 <errno.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#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};
|
|
||||||
}
|
|
38
vendor/github.com/kubernetes-incubator/cri-o/conmon/cmsg.h
generated
vendored
38
vendor/github.com/kubernetes-incubator/cri-o/conmon/cmsg.h
generated
vendored
@ -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 <sys/types.h>
|
|
||||||
|
|
||||||
/* 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) */
|
|
1400
vendor/github.com/kubernetes-incubator/cri-o/conmon/conmon.c
generated
vendored
1400
vendor/github.com/kubernetes-incubator/cri-o/conmon/conmon.c
generated
vendored
File diff suppressed because it is too large
Load Diff
24
vendor/github.com/kubernetes-incubator/cri-o/pkg/ocicni/noop.go
generated
vendored
24
vendor/github.com/kubernetes-incubator/cri-o/pkg/ocicni/noop.go
generated
vendored
@ -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
|
|
||||||
}
|
|
35
vendor/github.com/kubernetes-incubator/cri-o/pkg/ocicni/types.go
generated
vendored
35
vendor/github.com/kubernetes-incubator/cri-o/pkg/ocicni/types.go
generated
vendored
@ -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
|
|
||||||
}
|
|
73
vendor/github.com/kubernetes-incubator/cri-o/vendor.conf
generated
vendored
73
vendor/github.com/kubernetes-incubator/cri-o/vendor.conf
generated
vendored
@ -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
|
|
Loading…
Reference in New Issue
Block a user