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() {