Repository: containernetworking/cni
Pull request #774 (2020-06-29 13:04:27)

Switch to go modules
- rejigger some the test build infrastructure
- add go.mod
- bump travis go versions, because why not.

coveralls: 
[![Coverage Status](https://coveralls.io/builds/31746401/badge)](https://coveralls.io/builds/31746401)

Coverage increased (+0.2%) to 75.223% when pulling **8e20dcb6bfeb6a740973e9d4e4837ada88f2b9c8 on squeed:go-mod** into **11db36c11b015c1d84fa6f46496796d193fa8d43 on containernetworking:master**.


Patch:
diff --git a/.travis.yml b/.travis.yml
index a240bce..461a7fe 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,9 +2,8 @@ language: go
 dist: bionic
 
 go:
-  - 1.11.x
-  - 1.12.x
   - 1.13.x
+  - 1.14.x
 
 env:
   matrix:
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..f0be88a
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,8 @@
+module github.com/containernetworking/cni
+
+go 1.14
+
+require (
+	github.com/onsi/ginkgo v1.13.0
+	github.com/onsi/gomega v1.10.1
+)
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..5276e40
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,60 @@
+github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
+github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
+github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
+github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
+github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
+github.com/onsi/ginkgo v1.13.0 h1:M76yO2HkZASFjXL0HSoZJ1AYEmQxNJmY41Jx1zNUq1Y=
+github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0=
+github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
+github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
+github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
+github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 h1:AeiKBIuRw3UomYXSbLy0Mc2dDLfdtbT/IVn4keq83P0=
+golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7NkNAQs+6Q8b9WEB/F4=
+golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
+gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
+gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=


Test patch:
diff --git a/pkg/version/testhelpers/testhelpers.go b/pkg/version/testhelpers/testhelpers.go
index 773d012..6e9fd16 100644
--- a/pkg/version/testhelpers/testhelpers.go
+++ b/pkg/version/testhelpers/testhelpers.go
@@ -23,12 +23,10 @@ package testhelpers
 import (
 	"fmt"
 	"io/ioutil"
-	"math/rand"
 	"os"
 	"os/exec"
 	"path/filepath"
 	"strings"
-	"time"
 )
 
 const packageBaseName = "github.com/containernetworking/cni"
@@ -42,114 +40,63 @@ func run(cmd *exec.Cmd) error {
 	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
+// unset GOPATH if it's set, so we use modules
+func goBuildEnviron() []string {
+	out := []string{}
+	for _, kvp := range os.Environ() {
+		if !strings.HasPrefix(kvp, "GOPATH=") {
+			out = append(out, kvp)
 		}
 	}
-	environ = append(environ, "GOPATH="+gopath)
-	return environ
+	return out
 }
 
-func buildGoProgram(gopath, packageName, outputFilePath string) error {
-	cmd := exec.Command("go", "build", "-o", outputFilePath, packageName)
-	cmd.Env = goBuildEnviron(gopath)
+func buildGoProgram(modPath, outputFilePath string) error {
+	cmd := exec.Command("go", "build", "-o", outputFilePath, ".")
+	cmd.Dir = modPath
+	cmd.Env = goBuildEnviron()
 	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 modInit(path, name string) error {
+	cmd := exec.Command("go", "mod", "init", name)
+	cmd.Dir = path
+	return run(cmd)
 }
 
-func gitCheckout(localRepo string, gitRef string) error {
-	return run(exec.Command("git", "-C", localRepo, "checkout", gitRef))
+func addLibcni(path, gitRef string) error {
+	cmd := exec.Command("go", "get", "github.com/containernetworking/cni@"+gitRef)
+	cmd.Dir = path
+	return run(cmd)
 }
 
 // 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-")
+	tempDir, err := ioutil.TempDir(os.Getenv("GOTMPDIR"), "cni-test-")
 	if err != nil {
 		return err
 	}
-	defer os.RemoveAll(tempGoPath)
+	defer os.RemoveAll(tempDir)
 
-	cloneDestination := filepath.Join(tempGoPath, "src", packageBaseName)
-	err = gitCloneThisRepo(cloneDestination)
-	if err != nil {
+	modName := filepath.Base(tempDir)
+
+	if err := modInit(tempDir, modName); err != nil {
 		return err
 	}
 
-	err = gitCheckout(cloneDestination, gitRef)
-	if err != nil {
+	// go get
+	if err := addLibcni(tempDir, gitRef); 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 {
+	if err := ioutil.WriteFile(filepath.Join(tempDir, "main.go"), programSource, 0600); err != nil {
 		return err
 	}
-	defer removePackage(tempGoPath, testPackageName)
 
-	err = buildGoProgram(tempGoPath, testPackageName, outputFilePath)
+	err = buildGoProgram(tempDir, outputFilePath)
 	if err != nil {
-		return err
+		return fmt.Errorf("failed to build: %w", err)
 	}
 
 	return nil
diff --git a/pkg/version/testhelpers/testhelpers_test.go b/pkg/version/testhelpers/testhelpers_test.go
index 4fe070f..3a19d62 100644
--- a/pkg/version/testhelpers/testhelpers_test.go
+++ b/pkg/version/testhelpers/testhelpers_test.go
@@ -11,7 +11,7 @@
 // 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
+package testhelpers
 
 import (
 	"io/ioutil"
@@ -20,7 +20,6 @@ import (
 	"path/filepath"
 	"runtime"
 
-	"github.com/containernetworking/cni/pkg/version/testhelpers"
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
 )
@@ -59,7 +58,7 @@ func main() { skel.PluginMain(c, c) }
 	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)
+		err := BuildAt(programSource, gitRef, outputFilePath)
 		Expect(err).NotTo(HaveOccurred())
 
 		Expect(outputFilePath).To(BeAnExistingFile())
@@ -71,40 +70,3 @@ func main() { skel.PluginMain(c, c) }
 		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"))
-}