From 7ddd97684e786d8e4aa489c01d5c4a826e0d7db3 Mon Sep 17 00:00:00 2001
From: Dave Tucker
Date: Wed, 20 May 2015 20:28:58 +0100
Subject: [PATCH] Multi-Arch Support
Compile the dnet tool for Linux (x86, amd64 and arm)
and Windows (x86 and amd64)
- Moved installation of dependencies into `Dockerfile.build`
- Remove `start-services` from Makefile
- That's the responsibility of Docker or build environment
- Removed utils depending on `netlink` from `netutils/utils.go`
Unable to add `make cross` to CircleCI just yet as there are some
issues to solve that are unrelated to this PR
Also fix `.gitignore` which was not updated after changing the build
image name in #667
Signed-off-by: Dave Tucker
---
.dockerignore | 1 +
.gitignore | 3 +-
Dockerfile.build | 8 +++
Makefile | 88 ++++++++++++++++--------------
circle.yml | 18 ++++--
netutils/utils.go | 38 -------------
netutils/utils_linux.go | 50 +++++++++++++++++
test/integration/dnet/dnet.bats | 4 +-
test/integration/dnet/helpers.bash | 6 +-
9 files changed, 126 insertions(+), 90 deletions(-)
create mode 100644 .dockerignore
create mode 100644 Dockerfile.build
create mode 100644 netutils/utils_linux.go
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 00000000..72e8ffc0
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1 @@
+*
diff --git a/.gitignore b/.gitignore
index 0e0d4892..08e11d78 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
*.o
*.a
*.so
+bin/
# Folders
integration-tmp/
@@ -33,4 +34,4 @@ cmd/dnet/dnet
.project
.settings/
-libnetwork-build.created
+libnetworkbuild.created
diff --git a/Dockerfile.build b/Dockerfile.build
new file mode 100644
index 00000000..f43d4805
--- /dev/null
+++ b/Dockerfile.build
@@ -0,0 +1,8 @@
+FROM golang:1.4-cross
+RUN apt-get update && apt-get -y install iptables
+RUN go get github.com/tools/godep \
+ github.com/golang/lint/golint \
+ golang.org/x/tools/cmd/vet \
+ golang.org/x/tools/cmd/goimports \
+ golang.org/x/tools/cmd/cover\
+ github.com/mattn/goveralls
diff --git a/Makefile b/Makefile
index b1eabf52..73c58873 100644
--- a/Makefile
+++ b/Makefile
@@ -1,33 +1,20 @@
-.PHONY: all all-local build build-local check check-code check-format run-tests check-local integration-tests install-deps coveralls circle-ci start-services clean
+.PHONY: all all-local build build-local clean cross cross-local check check-code check-format run-tests integration-tests check-local coveralls circle-ci-cross circle-ci-build circle-ci-check circle-ci
SHELL=/bin/bash
build_image=libnetworkbuild
dockerargs = --privileged -v $(shell pwd):/go/src/github.com/docker/libnetwork -w /go/src/github.com/docker/libnetwork
container_env = -e "INSIDECONTAINER=-incontainer=true"
-docker = docker run --rm -it ${dockerargs} ${container_env} ${build_image}
+docker = docker run --rm -it ${dockerargs} $$EXTRA_ARGS ${container_env} ${build_image}
ciargs = -e "COVERALLS_TOKEN=$$COVERALLS_TOKEN" -e "INSIDECONTAINER=-incontainer=true"
-cidocker = docker run ${ciargs} ${dockerargs} golang:1.4
+cidocker = docker run ${dockerargs} ${ciargs} ${container_env} ${build_image}
+CROSS_PLATFORMS = linux/amd64 linux/386 linux/arm windows/amd64 windows/386
+
+${build_image}.created:
+ docker build -f Dockerfile.build -t ${build_image} .
+ touch ${build_image}.created
all: ${build_image}.created build check integration-tests clean
-integration-tests: ./cmd/dnet/dnet
- @./test/integration/dnet/run-integration-tests.sh
-
-./cmd/dnet/dnet:
- make build
-
-clean:
- @if [ -e ./cmd/dnet/dnet ]; then \
- echo "Removing dnet binary"; \
- rm -rf ./cmd/dnet/dnet; \
- fi
-
-all-local: check-local build-local
-
-${build_image}.created:
- docker run --name=libnetworkbuild -v $(shell pwd):/go/src/github.com/docker/libnetwork -w /go/src/github.com/docker/libnetwork golang:1.4 make install-deps
- docker commit libnetworkbuild ${build_image}
- docker rm libnetworkbuild
- touch ${build_image}.created
+all-local: build-local check-local integration-tests-local clean
build: ${build_image}.created
@echo "Building code... "
@@ -35,8 +22,25 @@ build: ${build_image}.created
@echo "Done building code"
build-local:
- @$(shell which godep) go build ./...
- @$(shell which godep) go build -o ./cmd/dnet/dnet ./cmd/dnet
+ @mkdir -p "bin"
+ $(shell which godep) go build -o "bin/dnet" ./cmd/dnet
+
+clean:
+ @if [ -d bin ]; then \
+ echo "Removing dnet binaries"; \
+ rm -rf bin; \
+ fi
+
+cross: ${build_image}.created
+ @mkdir -p "bin"
+ @for platform in ${CROSS_PLATFORMS}; do \
+ EXTRA_ARGS="-e GOOS=$${platform%/*} -e GOARCH=$${platform##*/}" ; \
+ echo "$${platform}..." ; \
+ ${docker} make cross-local ; \
+ done
+
+cross-local:
+ $(shell which godep) go build -o "bin/dnet-$$GOOS-$$GOARCH" ./cmd/dnet
check: ${build_image}.created
@${docker} ./wrapmake.sh check-local
@@ -71,27 +75,31 @@ run-tests:
done
@echo "Done running tests"
-check-local: check-format check-code start-services run-tests
+check-local: check-format check-code run-tests
-install-deps:
- apt-get update && apt-get -y install iptables zookeeperd
- git clone https://github.com/golang/tools /go/src/golang.org/x/tools
- go install golang.org/x/tools/cmd/vet
- go install golang.org/x/tools/cmd/goimports
- go install golang.org/x/tools/cmd/cover
- go get github.com/tools/godep
- go get github.com/golang/lint/golint
- go get github.com/mattn/goveralls
+integration-tests: ./bin/dnet
+ @./test/integration/dnet/run-integration-tests.sh
+
+./bin/dnet:
+ make build
coveralls:
-@goveralls -service circleci -coverprofile=coverage.coverprofile -repotoken $$COVERALLS_TOKEN
# CircleCI's Docker fails when cleaning up using the --rm flag
-# The following target is a workaround for this
+# The following targets are a workaround for this
+circle-ci-cross: ${build_image}.created
+ @mkdir -p "bin"
+ @for platform in ${CROSS_PLATFORMS}; do \
+ EXTRA_ARGS="-e GOOS=$${platform%/*} -e GOARCH=$${platform##*/}" ; \
+ echo "$${platform}..." ; \
+ ${cidocker} make cross-local ; \
+ done
-circle-ci:
- @${cidocker} make install-deps build-local check-local coveralls
- make integration-tests
+circle-ci-check: ${build_image}.created
+ @${cidocker} make check-local coveralls
-start-services:
- service zookeeper start
+circle-ci-build: ${build_image}.created
+ @${cidocker} make build-local
+
+circle-ci: circle-ci-check circle-ci-build integration-tests
diff --git a/circle.yml b/circle.yml
index d02f6a92..a454d212 100644
--- a/circle.yml
+++ b/circle.yml
@@ -1,12 +1,18 @@
machine:
- services:
- - docker
+ services:
+ - docker
dependencies:
- override:
- - echo "Nothing to install"
+ override:
+ - sudo apt-get update; sudo apt-get install -y iptables zookeeperd
+ - go get golang.org/x/tools/cmd/vet
+ - go get golang.org/x/tools/cmd/goimports
+ - go get golang.org/x/tools/cmd/cover
+ - go get github.com/tools/godep
+ - go get github.com/golang/lint/golint
+ - go get github.com/mattn/goveralls
test:
- override:
- - make circle-ci
+ override:
+ - make circle-ci
diff --git a/netutils/utils.go b/netutils/utils.go
index a1ead361..19ea2fdd 100644
--- a/netutils/utils.go
+++ b/netutils/utils.go
@@ -9,10 +9,8 @@ import (
"fmt"
"io"
"net"
- "strings"
"github.com/docker/libnetwork/types"
- "github.com/vishvananda/netlink"
)
var (
@@ -22,8 +20,6 @@ var (
ErrNetworkOverlaps = errors.New("requested network overlaps with existing network")
// ErrNoDefaultRoute preformatted error
ErrNoDefaultRoute = errors.New("no default route")
-
- networkGetRoutesFct = netlink.RouteList
)
// CheckNameserverOverlaps checks whether the passed network overlaps with any of the nameservers
@@ -42,21 +38,6 @@ func CheckNameserverOverlaps(nameservers []string, toCheck *net.IPNet) error {
return nil
}
-// CheckRouteOverlaps checks whether the passed network overlaps with any existing routes
-func CheckRouteOverlaps(toCheck *net.IPNet) error {
- networks, err := networkGetRoutesFct(nil, netlink.FAMILY_V4)
- if err != nil {
- return err
- }
-
- for _, network := range networks {
- if network.Dst != nil && NetworkOverlaps(toCheck, network.Dst) {
- return ErrNetworkOverlaps
- }
- }
- return nil
-}
-
// NetworkOverlaps detects overlap between one IPNet and another
func NetworkOverlaps(netX *net.IPNet, netY *net.IPNet) bool {
return netX.Contains(netY.IP) || netY.Contains(netX.IP)
@@ -151,22 +132,3 @@ func GenerateRandomName(prefix string, size int) (string, error) {
}
return prefix + hex.EncodeToString(id)[:size], nil
}
-
-// GenerateIfaceName returns an interface name using the passed in
-// prefix and the length of random bytes. The api ensures that the
-// there are is no interface which exists with that name.
-func GenerateIfaceName(prefix string, len int) (string, error) {
- for i := 0; i < 3; i++ {
- name, err := GenerateRandomName(prefix, len)
- if err != nil {
- continue
- }
- if _, err := netlink.LinkByName(name); err != nil {
- if strings.Contains(err.Error(), "not found") {
- return name, nil
- }
- return "", err
- }
- }
- return "", types.InternalErrorf("could not generate interface name")
-}
diff --git a/netutils/utils_linux.go b/netutils/utils_linux.go
new file mode 100644
index 00000000..782e542a
--- /dev/null
+++ b/netutils/utils_linux.go
@@ -0,0 +1,50 @@
+// +build linux
+// Network utility functions.
+
+package netutils
+
+import (
+ "net"
+ "strings"
+
+ "github.com/docker/libnetwork/types"
+ "github.com/vishvananda/netlink"
+)
+
+var (
+ networkGetRoutesFct = netlink.RouteList
+)
+
+// CheckRouteOverlaps checks whether the passed network overlaps with any existing routes
+func CheckRouteOverlaps(toCheck *net.IPNet) error {
+ networks, err := networkGetRoutesFct(nil, netlink.FAMILY_V4)
+ if err != nil {
+ return err
+ }
+
+ for _, network := range networks {
+ if network.Dst != nil && NetworkOverlaps(toCheck, network.Dst) {
+ return ErrNetworkOverlaps
+ }
+ }
+ return nil
+}
+
+// GenerateIfaceName returns an interface name using the passed in
+// prefix and the length of random bytes. The api ensures that the
+// there are is no interface which exists with that name.
+func GenerateIfaceName(prefix string, len int) (string, error) {
+ for i := 0; i < 3; i++ {
+ name, err := GenerateRandomName(prefix, len)
+ if err != nil {
+ continue
+ }
+ if _, err := netlink.LinkByName(name); err != nil {
+ if strings.Contains(err.Error(), "not found") {
+ return name, nil
+ }
+ return "", err
+ }
+ }
+ return "", types.InternalErrorf("could not generate interface name")
+}
diff --git a/test/integration/dnet/dnet.bats b/test/integration/dnet/dnet.bats
index e5c60dc0..cf73eab5 100644
--- a/test/integration/dnet/dnet.bats
+++ b/test/integration/dnet/dnet.bats
@@ -21,10 +21,10 @@ load helpers
run dnet_cmd 8080 network ls
echo ${output}
[ "$status" -ne 0 ]
- run ./cmd/dnet/dnet -H=unix://var/run/dnet.sock network ls
+ run ./bin/dnet -H=unix://var/run/dnet.sock network ls
echo ${output}
[ "$status" -ne 0 ]
- run ./cmd/dnet/dnet -H= -l=invalid network ls
+ run ./bin/dnet -H= -l=invalid network ls
echo ${output}
[ "$status" -ne 0 ]
stop_dnet 1 c
diff --git a/test/integration/dnet/helpers.bash b/test/integration/dnet/helpers.bash
index 7b507abf..5f85bd20 100644
--- a/test/integration/dnet/helpers.bash
+++ b/test/integration/dnet/helpers.bash
@@ -73,7 +73,7 @@ function wait_for_dnet() {
echo "waiting on dnet to come up ..."
for i in `seq 1 10`;
do
- hrun ./cmd/dnet/dnet -H tcp://127.0.0.1:${hport} network ls
+ hrun ./bin/dnet -H tcp://127.0.0.1:${hport} network ls
echo ${output}
if [ "$status" -eq 0 ]; then
return
@@ -168,7 +168,7 @@ EOF
-v $(pwd)/${TMPC_ROOT}:/scratch \
-v /usr/local/bin/runc:/usr/local/bin/runc \
-w /go/src/github.com/docker/libnetwork \
- mrjana/golang ./cmd/dnet/dnet -d -D ${hopt} -c ${tomlfile}
+ mrjana/golang ./bin/dnet -d -D ${hopt} -c ${tomlfile}
wait_for_dnet $(inst_id2port ${inst}) ${name}
}
@@ -196,7 +196,7 @@ function dnet_cmd() {
hport=$1
shift
- ./cmd/dnet/dnet -H tcp://127.0.0.1:${hport} $*
+ ./bin/dnet -H tcp://127.0.0.1:${hport} $*
}
function dnet_exec() {