Switch to github.com/golang/dep for vendoring

Signed-off-by: Mrunal Patel <mrunalp@gmail.com>
This commit is contained in:
Mrunal Patel 2017-01-31 16:45:59 -08:00
parent d6ab91be27
commit 8e5b17cf13
15431 changed files with 3971413 additions and 8881 deletions

View file

@ -0,0 +1,69 @@
// 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 version_test
import (
"github.com/containernetworking/cni/pkg/version"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("Decoding the version of network config", func() {
var (
decoder *version.ConfigDecoder
configBytes []byte
)
BeforeEach(func() {
decoder = &version.ConfigDecoder{}
configBytes = []byte(`{ "cniVersion": "4.3.2" }`)
})
Context("when the version is explict", func() {
It("returns the version", func() {
version, err := decoder.Decode(configBytes)
Expect(err).NotTo(HaveOccurred())
Expect(version).To(Equal("4.3.2"))
})
})
Context("when the version is not present in the config", func() {
BeforeEach(func() {
configBytes = []byte(`{ "not-a-version-field": "foo" }`)
})
It("assumes the config is version 0.1.0", func() {
version, err := decoder.Decode(configBytes)
Expect(err).NotTo(HaveOccurred())
Expect(version).To(Equal("0.1.0"))
})
})
Context("when the config data is malformed", func() {
BeforeEach(func() {
configBytes = []byte(`{{{`)
})
It("returns a useful error", func() {
_, err := decoder.Decode(configBytes)
Expect(err).To(MatchError(HavePrefix(
"decoding version from network config: invalid character",
)))
})
})
})

View file

@ -0,0 +1,167 @@
// 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 legacy_examples
// An ExampleRuntime is a small program that uses libcni to invoke a network plugin.
// It should call ADD and DELETE, verifying all intermediate steps
// and data structures.
type ExampleRuntime struct {
Example
NetConfs []string // The network configuration names to pass
}
// NetConfs are various versioned network configuration files. Examples should
// specify which version they expect
var NetConfs = map[string]string{
"unversioned": `{
"name": "default",
"type": "ptp",
"ipam": {
"type": "host-local",
"subnet": "10.1.2.0/24"
}
}`,
"0.1.0": `{
"cniVersion": "0.1.0",
"name": "default",
"type": "ptp",
"ipam": {
"type": "host-local",
"subnet": "10.1.2.0/24"
}
}`,
}
// V010_Runtime creates a simple ptp network configuration, then
// executes libcni against the currently-built plugins.
var V010_Runtime = ExampleRuntime{
NetConfs: []string{"unversioned", "0.1.0"},
Example: Example{
Name: "example_invoker_v010",
CNIRepoGitRef: "c0d34c69", //version with ns.Do
PluginSource: `package main
import (
"fmt"
"io/ioutil"
"net"
"os"
"github.com/containernetworking/cni/pkg/ns"
"github.com/containernetworking/cni/libcni"
)
func main(){
code := exec()
os.Exit(code)
}
func exec() int {
confBytes, err := ioutil.ReadAll(os.Stdin)
if err != nil {
fmt.Printf("could not read netconfig from stdin: %+v", err)
return 1
}
netConf, err := libcni.ConfFromBytes(confBytes)
if err != nil {
fmt.Printf("could not parse netconfig: %+v", err)
return 1
}
fmt.Printf("Parsed network configuration: %+v\n", netConf.Network)
if len(os.Args) == 1 {
fmt.Printf("Expect CNI plugin paths in argv")
return 1
}
targetNs, err := ns.NewNS()
if err != nil {
fmt.Printf("Could not create ns: %+v", err)
return 1
}
defer targetNs.Close()
ifName := "eth0"
runtimeConf := &libcni.RuntimeConf{
ContainerID: "some-container-id",
NetNS: targetNs.Path(),
IfName: ifName,
}
cniConfig := &libcni.CNIConfig{Path: os.Args[1:]}
result, err := cniConfig.AddNetwork(netConf, runtimeConf)
if err != nil {
fmt.Printf("AddNetwork failed: %+v", err)
return 2
}
fmt.Printf("AddNetwork result: %+v", result)
expectedIP := result.IP4.IP
err = targetNs.Do(func(ns.NetNS) error {
netif, err := net.InterfaceByName(ifName)
if err != nil {
return fmt.Errorf("could not retrieve interface: %v", err)
}
addrs, err := netif.Addrs()
if err != nil {
return fmt.Errorf("could not retrieve addresses, %+v", err)
}
found := false
for _, addr := range addrs {
if addr.String() == expectedIP.String() {
found = true
break
}
}
if !found {
return fmt.Errorf("Far-side link did not have expected address %s", expectedIP)
}
return nil
})
if err != nil {
fmt.Println(err)
return 4
}
err = cniConfig.DelNetwork(netConf, runtimeConf)
if err != nil {
fmt.Printf("DelNetwork failed: %v", err)
return 5
}
err = targetNs.Do(func(ns.NetNS) error {
_, err := net.InterfaceByName(ifName)
if err == nil {
return fmt.Errorf("interface was not deleted")
}
return nil
})
if err != nil {
fmt.Println(err)
return 6
}
return 0
}
`,
},
}

View file

@ -0,0 +1,138 @@
// 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 legacy_examples contains sample code from prior versions of
// the CNI library, for use in verifying backwards compatibility.
package legacy_examples
import (
"io/ioutil"
"net"
"path/filepath"
"sync"
"github.com/containernetworking/cni/pkg/types"
"github.com/containernetworking/cni/pkg/version/testhelpers"
)
// An Example is a Git reference to the CNI repo and a Golang CNI plugin that
// builds against that version of the repo.
//
// By convention, every Example plugin returns an ADD result that is
// semantically equivalent to the ExpectedResult.
type Example struct {
Name string
CNIRepoGitRef string
PluginSource string
}
var buildDir = ""
var buildDirLock sync.Mutex
func ensureBuildDirExists() error {
buildDirLock.Lock()
defer buildDirLock.Unlock()
if buildDir != "" {
return nil
}
var err error
buildDir, err = ioutil.TempDir("", "cni-example-plugins")
return err
}
// Build builds the example, returning the path to the binary
func (e Example) Build() (string, error) {
if err := ensureBuildDirExists(); err != nil {
return "", err
}
outBinPath := filepath.Join(buildDir, e.Name)
if err := testhelpers.BuildAt([]byte(e.PluginSource), e.CNIRepoGitRef, outBinPath); err != nil {
return "", err
}
return outBinPath, nil
}
// V010 acts like a CNI plugin from the v0.1.0 era
var V010 = Example{
Name: "example_v010",
CNIRepoGitRef: "2c482f4",
PluginSource: `package main
import (
"net"
"github.com/containernetworking/cni/pkg/skel"
"github.com/containernetworking/cni/pkg/types"
)
var result = types.Result{
IP4: &types.IPConfig{
IP: net.IPNet{
IP: net.ParseIP("10.1.2.3"),
Mask: net.CIDRMask(24, 32),
},
Gateway: net.ParseIP("10.1.2.1"),
Routes: []types.Route{
types.Route{
Dst: net.IPNet{
IP: net.ParseIP("0.0.0.0"),
Mask: net.CIDRMask(0, 32),
},
GW: net.ParseIP("10.1.0.1"),
},
},
},
DNS: types.DNS{
Nameservers: []string{"8.8.8.8"},
Domain: "example.com",
},
}
func c(_ *skel.CmdArgs) error { result.Print(); return nil }
func main() { skel.PluginMain(c, c) }
`,
}
// ExpectedResult is the current representation of the plugin result
// that is expected from each of the examples.
//
// As we change the CNI spec, the Result type and this value may change.
// The text of the example plugins should not.
var ExpectedResult = &types.Result{
IP4: &types.IPConfig{
IP: net.IPNet{
IP: net.ParseIP("10.1.2.3"),
Mask: net.CIDRMask(24, 32),
},
Gateway: net.ParseIP("10.1.2.1"),
Routes: []types.Route{
types.Route{
Dst: net.IPNet{
IP: net.ParseIP("0.0.0.0"),
Mask: net.CIDRMask(0, 32),
},
GW: net.ParseIP("10.1.0.1"),
},
},
},
DNS: types.DNS{
Nameservers: []string{"8.8.8.8"},
Domain: "example.com",
},
}

View file

@ -0,0 +1,27 @@
// 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 legacy_examples_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
)
func TestLegacyExamples(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "LegacyExamples Suite")
}

View file

@ -0,0 +1,36 @@
// 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 legacy_examples_test
import (
"os"
"path/filepath"
"github.com/containernetworking/cni/pkg/version/legacy_examples"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("The v0.1.0 Example", func() {
It("builds ok", func() {
example := legacy_examples.V010
pluginPath, err := example.Build()
Expect(err).NotTo(HaveOccurred())
Expect(filepath.Base(pluginPath)).To(Equal(example.Name))
Expect(os.RemoveAll(pluginPath)).To(Succeed())
})
})

View file

@ -0,0 +1,85 @@
// 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 version_test
import (
"github.com/containernetworking/cni/pkg/version"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("Decoding versions reported by a plugin", func() {
var (
decoder *version.PluginDecoder
versionStdout []byte
)
BeforeEach(func() {
decoder = &version.PluginDecoder{}
versionStdout = []byte(`{
"cniVersion": "some-library-version",
"supportedVersions": [ "some-version", "some-other-version" ]
}`)
})
It("returns a PluginInfo that represents the given json bytes", func() {
pluginInfo, err := decoder.Decode(versionStdout)
Expect(err).NotTo(HaveOccurred())
Expect(pluginInfo).NotTo(BeNil())
Expect(pluginInfo.SupportedVersions()).To(Equal([]string{
"some-version",
"some-other-version",
}))
})
Context("when the bytes cannot be decoded as json", func() {
BeforeEach(func() {
versionStdout = []byte(`{{{`)
})
It("returns a meaningful error", func() {
_, err := decoder.Decode(versionStdout)
Expect(err).To(MatchError("decoding version info: invalid character '{' looking for beginning of object key string"))
})
})
Context("when the json bytes are missing the required CNIVersion field", func() {
BeforeEach(func() {
versionStdout = []byte(`{ "supportedVersions": [ "foo" ] }`)
})
It("returns a meaningful error", func() {
_, err := decoder.Decode(versionStdout)
Expect(err).To(MatchError("decoding version info: missing field cniVersion"))
})
})
Context("when there are no supported versions", func() {
BeforeEach(func() {
versionStdout = []byte(`{ "cniVersion": "0.2.0" }`)
})
It("assumes that the supported versions are 0.1.0 and 0.2.0", func() {
pluginInfo, err := decoder.Decode(versionStdout)
Expect(err).NotTo(HaveOccurred())
Expect(pluginInfo).NotTo(BeNil())
Expect(pluginInfo.SupportedVersions()).To(Equal([]string{
"0.1.0",
"0.2.0",
}))
})
})
})

View file

@ -0,0 +1,51 @@
// 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 version_test
import (
"github.com/containernetworking/cni/pkg/version"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("Reconcile versions of net config with versions supported by plugins", func() {
var (
reconciler *version.Reconciler
pluginInfo version.PluginInfo
)
BeforeEach(func() {
reconciler = &version.Reconciler{}
pluginInfo = version.PluginSupports("1.2.3", "4.3.2")
})
It("succeeds if the config version is supported by the plugin", func() {
err := reconciler.Check("4.3.2", pluginInfo)
Expect(err).NotTo(HaveOccurred())
})
Context("when the config version is not supported by the plugin", func() {
It("returns a helpful error", func() {
err := reconciler.Check("0.1.0", pluginInfo)
Expect(err).To(Equal(&version.ErrorIncompatible{
Config: "0.1.0",
Plugin: []string{"1.2.3", "4.3.2"},
}))
Expect(err.Error()).To(Equal(`incompatible CNI versions: config is "0.1.0", plugin supports ["1.2.3" "4.3.2"]`))
})
})
})

View file

@ -0,0 +1,156 @@
// 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 testhelpers supports testing of CNI components of different versions
//
// For example, to build a plugin against an old version of the CNI library,
// we can pass the plugin's source and the old git commit reference to BuildAt.
// We could then test how the built binary responds when called by the latest
// version of this library.
package testhelpers
import (
"fmt"
"io/ioutil"
"math/rand"
"os"
"os/exec"
"path/filepath"
"strings"
"time"
)
const packageBaseName = "github.com/containernetworking/cni"
func run(cmd *exec.Cmd) error {
out, err := cmd.CombinedOutput()
if err != nil {
command := strings.Join(cmd.Args, " ")
return fmt.Errorf("running %q: %s", command, out)
}
return nil
}
func goBuildEnviron(gopath string) []string {
environ := os.Environ()
for i, kvp := range environ {
if strings.HasPrefix(kvp, "GOPATH=") {
environ[i] = "GOPATH=" + gopath
return environ
}
}
environ = append(environ, "GOPATH="+gopath)
return environ
}
func buildGoProgram(gopath, packageName, outputFilePath string) error {
cmd := exec.Command("go", "build", "-o", outputFilePath, packageName)
cmd.Env = goBuildEnviron(gopath)
return run(cmd)
}
func createSingleFilePackage(gopath, packageName string, fileContents []byte) error {
dirName := filepath.Join(gopath, "src", packageName)
err := os.MkdirAll(dirName, 0700)
if err != nil {
return err
}
return ioutil.WriteFile(filepath.Join(dirName, "main.go"), fileContents, 0600)
}
func removePackage(gopath, packageName string) error {
dirName := filepath.Join(gopath, "src", packageName)
return os.RemoveAll(dirName)
}
func isRepoRoot(path string) bool {
_, err := ioutil.ReadDir(filepath.Join(path, ".git"))
return (err == nil) && (filepath.Base(path) == "cni")
}
func LocateCurrentGitRepo() (string, error) {
dir, err := os.Getwd()
if err != nil {
return "", err
}
for i := 0; i < 5; i++ {
if isRepoRoot(dir) {
return dir, nil
}
dir, err = filepath.Abs(filepath.Dir(dir))
if err != nil {
return "", fmt.Errorf("abs(dir(%q)): %s", dir, err)
}
}
return "", fmt.Errorf("unable to find cni repo root, landed at %q", dir)
}
func gitCloneThisRepo(cloneDestination string) error {
err := os.MkdirAll(cloneDestination, 0700)
if err != nil {
return err
}
currentGitRepo, err := LocateCurrentGitRepo()
if err != nil {
return err
}
return run(exec.Command("git", "clone", currentGitRepo, cloneDestination))
}
func gitCheckout(localRepo string, gitRef string) error {
return run(exec.Command("git", "-C", localRepo, "checkout", gitRef))
}
// BuildAt builds the go programSource using the version of the CNI library
// at gitRef, and saves the resulting binary file at outputFilePath
func BuildAt(programSource []byte, gitRef string, outputFilePath string) error {
tempGoPath, err := ioutil.TempDir("", "cni-git-")
if err != nil {
return err
}
defer os.RemoveAll(tempGoPath)
cloneDestination := filepath.Join(tempGoPath, "src", packageBaseName)
err = gitCloneThisRepo(cloneDestination)
if err != nil {
return err
}
err = gitCheckout(cloneDestination, gitRef)
if err != nil {
return err
}
rand.Seed(time.Now().UnixNano())
testPackageName := fmt.Sprintf("test-package-%x", rand.Int31())
err = createSingleFilePackage(tempGoPath, testPackageName, programSource)
if err != nil {
return err
}
defer removePackage(tempGoPath, testPackageName)
err = buildGoProgram(tempGoPath, testPackageName, outputFilePath)
if err != nil {
return err
}
return nil
}

View file

@ -0,0 +1,27 @@
// 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 testhelpers_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
)
func TestTesthelpers(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Testhelpers Suite")
}

View file

@ -0,0 +1,106 @@
// 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 testhelpers_test
import (
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"github.com/containernetworking/cni/pkg/version/testhelpers"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("BuildAt", func() {
var (
gitRef string
outputFilePath string
outputDir string
programSource []byte
)
BeforeEach(func() {
programSource = []byte(`package main
import "github.com/containernetworking/cni/pkg/skel"
func c(_ *skel.CmdArgs) error { return nil }
func main() { skel.PluginMain(c, c) }
`)
gitRef = "f4364185253"
var err error
outputDir, err = ioutil.TempDir("", "bin")
Expect(err).NotTo(HaveOccurred())
outputFilePath = filepath.Join(outputDir, "some-binary")
})
AfterEach(func() {
Expect(os.RemoveAll(outputDir)).To(Succeed())
})
It("builds the provided source code using the CNI library at the given git ref", func() {
Expect(outputFilePath).NotTo(BeAnExistingFile())
err := testhelpers.BuildAt(programSource, gitRef, outputFilePath)
Expect(err).NotTo(HaveOccurred())
Expect(outputFilePath).To(BeAnExistingFile())
cmd := exec.Command(outputFilePath)
cmd.Env = []string{"CNI_COMMAND=VERSION"}
output, err := cmd.CombinedOutput()
Expect(err).To(BeAssignableToTypeOf(&exec.ExitError{}))
Expect(output).To(ContainSubstring("unknown CNI_COMMAND: VERSION"))
})
})
var _ = Describe("LocateCurrentGitRepo", func() {
It("returns the path to the root of the CNI git repo", func() {
path, err := testhelpers.LocateCurrentGitRepo()
Expect(err).NotTo(HaveOccurred())
AssertItIsTheCNIRepoRoot(path)
})
Context("when run from a different directory", func() {
BeforeEach(func() {
os.Chdir("..")
})
It("still finds the CNI repo root", func() {
path, err := testhelpers.LocateCurrentGitRepo()
Expect(err).NotTo(HaveOccurred())
AssertItIsTheCNIRepoRoot(path)
})
})
})
func AssertItIsTheCNIRepoRoot(path string) {
Expect(path).To(BeADirectory())
files, err := ioutil.ReadDir(path)
Expect(err).NotTo(HaveOccurred())
names := []string{}
for _, file := range files {
names = append(names, file.Name())
}
Expect(names).To(ContainElement("SPEC.md"))
Expect(names).To(ContainElement("libcni"))
Expect(names).To(ContainElement("cnitool"))
}

View file

@ -0,0 +1,27 @@
// 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 version_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
)
func TestVersion(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Version Suite")
}