Browse code

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 <dt@docker.com>

Dave Tucker authored on 2015/05/21 04:28:58
Showing 9 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1 @@
0
+*
... ...
@@ -2,6 +2,7 @@
2 2
 *.o
3 3
 *.a
4 4
 *.so
5
+bin/
5 6
 
6 7
 # Folders
7 8
 integration-tmp/
... ...
@@ -33,4 +34,4 @@ cmd/dnet/dnet
33 33
 .project
34 34
 .settings/
35 35
 
36
-libnetwork-build.created
36
+libnetworkbuild.created
37 37
new file mode 100644
... ...
@@ -0,0 +1,8 @@
0
+FROM golang:1.4-cross
1
+RUN apt-get update && apt-get -y install iptables
2
+RUN go get github.com/tools/godep \
3
+		github.com/golang/lint/golint \
4
+		golang.org/x/tools/cmd/vet \
5
+		golang.org/x/tools/cmd/goimports \
6
+		golang.org/x/tools/cmd/cover\
7
+		github.com/mattn/goveralls
... ...
@@ -1,42 +1,46 @@
1
-.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
1
+.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
2 2
 SHELL=/bin/bash
3 3
 build_image=libnetworkbuild
4 4
 dockerargs = --privileged -v $(shell pwd):/go/src/github.com/docker/libnetwork -w /go/src/github.com/docker/libnetwork
5 5
 container_env = -e "INSIDECONTAINER=-incontainer=true"
6
-docker = docker run --rm -it ${dockerargs} ${container_env} ${build_image}
6
+docker = docker run --rm -it ${dockerargs} $$EXTRA_ARGS ${container_env} ${build_image}
7 7
 ciargs = -e "COVERALLS_TOKEN=$$COVERALLS_TOKEN" -e "INSIDECONTAINER=-incontainer=true"
8
-cidocker = docker run ${ciargs} ${dockerargs} golang:1.4
9
-
10
-all: ${build_image}.created build check integration-tests clean
11
-
12
-integration-tests: ./cmd/dnet/dnet
13
-	@./test/integration/dnet/run-integration-tests.sh
14
-
15
-./cmd/dnet/dnet:
16
-	make build
17
-
18
-clean:
19
-	@if [ -e ./cmd/dnet/dnet ]; then \
20
-		echo "Removing dnet binary"; \
21
-		rm -rf ./cmd/dnet/dnet; \
22
-	fi
23
-
24
-all-local: check-local build-local
8
+cidocker = docker run ${dockerargs} ${ciargs} ${container_env} ${build_image}
9
+CROSS_PLATFORMS = linux/amd64 linux/386 linux/arm windows/amd64 windows/386
25 10
 
26 11
 ${build_image}.created:
27
-	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
28
-	docker commit libnetworkbuild ${build_image}
29
-	docker rm libnetworkbuild
12
+	docker build -f Dockerfile.build -t ${build_image} .
30 13
 	touch ${build_image}.created
31 14
 
15
+all: ${build_image}.created build check integration-tests clean
16
+
17
+all-local: build-local check-local integration-tests-local clean
18
+
32 19
 build: ${build_image}.created
33 20
 	@echo "Building code... "
34 21
 	@${docker} ./wrapmake.sh build-local
35 22
 	@echo "Done building code"
36 23
 
37 24
 build-local:
38
-	@$(shell which godep) go build  ./...
39
-	@$(shell which godep) go build -o ./cmd/dnet/dnet ./cmd/dnet
25
+	@mkdir -p "bin"
26
+	$(shell which godep) go build -o "bin/dnet" ./cmd/dnet
27
+
28
+clean:
29
+	@if [ -d bin ]; then \
30
+		echo "Removing dnet binaries"; \
31
+		rm -rf bin; \
32
+	fi
33
+
34
+cross: ${build_image}.created
35
+	@mkdir -p "bin"
36
+	@for platform in ${CROSS_PLATFORMS}; do \
37
+	        EXTRA_ARGS="-e GOOS=$${platform%/*} -e GOARCH=$${platform##*/}" ; \
38
+		echo "$${platform}..." ; \
39
+	        ${docker} make cross-local ; \
40
+	done
41
+
42
+cross-local:
43
+	$(shell which godep) go build -o "bin/dnet-$$GOOS-$$GOARCH" ./cmd/dnet
40 44
 
41 45
 check: ${build_image}.created
42 46
 	@${docker} ./wrapmake.sh check-local
... ...
@@ -71,27 +75,31 @@ run-tests:
71 71
 	done
72 72
 	@echo "Done running tests"
73 73
 
74
-check-local:	check-format check-code start-services run-tests
74
+check-local:	check-format check-code run-tests
75
+
76
+integration-tests: ./bin/dnet
77
+	@./test/integration/dnet/run-integration-tests.sh
75 78
 
76
-install-deps:
77
-	apt-get update && apt-get -y install iptables zookeeperd
78
-	git clone https://github.com/golang/tools /go/src/golang.org/x/tools
79
-	go install golang.org/x/tools/cmd/vet
80
-	go install golang.org/x/tools/cmd/goimports
81
-	go install golang.org/x/tools/cmd/cover
82
-	go get github.com/tools/godep
83
-	go get github.com/golang/lint/golint
84
-	go get github.com/mattn/goveralls
79
+./bin/dnet:
80
+	make build
85 81
 
86 82
 coveralls:
87 83
 	-@goveralls -service circleci -coverprofile=coverage.coverprofile -repotoken $$COVERALLS_TOKEN
88 84
 
89 85
 # CircleCI's Docker fails when cleaning up using the --rm flag
90
-# The following target is a workaround for this
86
+# The following targets are a workaround for this
87
+circle-ci-cross: ${build_image}.created
88
+	@mkdir -p "bin"
89
+	@for platform in ${CROSS_PLATFORMS}; do \
90
+	        EXTRA_ARGS="-e GOOS=$${platform%/*} -e GOARCH=$${platform##*/}" ; \
91
+		echo "$${platform}..." ; \
92
+	        ${cidocker} make cross-local ; \
93
+	done
94
+
95
+circle-ci-check: ${build_image}.created
96
+	@${cidocker} make check-local coveralls
91 97
 
92
-circle-ci:
93
-	@${cidocker} make install-deps build-local check-local coveralls
94
-	make integration-tests
98
+circle-ci-build: ${build_image}.created
99
+	@${cidocker} make build-local
95 100
 
96
-start-services:
97
-	service zookeeper start
101
+circle-ci: circle-ci-check circle-ci-build integration-tests
... ...
@@ -1,12 +1,18 @@
1 1
 machine:
2
-    services:
3
-        - docker
2
+  services:
3
+    - docker
4 4
 
5 5
 dependencies:
6
-    override:
7
-        - echo "Nothing to install"
6
+  override:
7
+    - sudo apt-get update; sudo apt-get install -y iptables zookeeperd 
8
+    - go get golang.org/x/tools/cmd/vet
9
+    - go get golang.org/x/tools/cmd/goimports
10
+    - go get golang.org/x/tools/cmd/cover
11
+    - go get github.com/tools/godep
12
+    - go get github.com/golang/lint/golint
13
+    - go get github.com/mattn/goveralls
8 14
 
9 15
 test:
10
-    override:
11
-        - make circle-ci
16
+  override:
17
+    - make circle-ci
12 18
 
... ...
@@ -9,10 +9,8 @@ import (
9 9
 	"fmt"
10 10
 	"io"
11 11
 	"net"
12
-	"strings"
13 12
 
14 13
 	"github.com/docker/libnetwork/types"
15
-	"github.com/vishvananda/netlink"
16 14
 )
17 15
 
18 16
 var (
... ...
@@ -22,8 +20,6 @@ var (
22 22
 	ErrNetworkOverlaps = errors.New("requested network overlaps with existing network")
23 23
 	// ErrNoDefaultRoute preformatted error
24 24
 	ErrNoDefaultRoute = errors.New("no default route")
25
-
26
-	networkGetRoutesFct = netlink.RouteList
27 25
 )
28 26
 
29 27
 // CheckNameserverOverlaps checks whether the passed network overlaps with any of the nameservers
... ...
@@ -42,21 +38,6 @@ func CheckNameserverOverlaps(nameservers []string, toCheck *net.IPNet) error {
42 42
 	return nil
43 43
 }
44 44
 
45
-// CheckRouteOverlaps checks whether the passed network overlaps with any existing routes
46
-func CheckRouteOverlaps(toCheck *net.IPNet) error {
47
-	networks, err := networkGetRoutesFct(nil, netlink.FAMILY_V4)
48
-	if err != nil {
49
-		return err
50
-	}
51
-
52
-	for _, network := range networks {
53
-		if network.Dst != nil && NetworkOverlaps(toCheck, network.Dst) {
54
-			return ErrNetworkOverlaps
55
-		}
56
-	}
57
-	return nil
58
-}
59
-
60 45
 // NetworkOverlaps detects overlap between one IPNet and another
61 46
 func NetworkOverlaps(netX *net.IPNet, netY *net.IPNet) bool {
62 47
 	return netX.Contains(netY.IP) || netY.Contains(netX.IP)
... ...
@@ -151,22 +132,3 @@ func GenerateRandomName(prefix string, size int) (string, error) {
151 151
 	}
152 152
 	return prefix + hex.EncodeToString(id)[:size], nil
153 153
 }
154
-
155
-// GenerateIfaceName returns an interface name using the passed in
156
-// prefix and the length of random bytes. The api ensures that the
157
-// there are is no interface which exists with that name.
158
-func GenerateIfaceName(prefix string, len int) (string, error) {
159
-	for i := 0; i < 3; i++ {
160
-		name, err := GenerateRandomName(prefix, len)
161
-		if err != nil {
162
-			continue
163
-		}
164
-		if _, err := netlink.LinkByName(name); err != nil {
165
-			if strings.Contains(err.Error(), "not found") {
166
-				return name, nil
167
-			}
168
-			return "", err
169
-		}
170
-	}
171
-	return "", types.InternalErrorf("could not generate interface name")
172
-}
173 154
new file mode 100644
... ...
@@ -0,0 +1,50 @@
0
+// +build linux
1
+// Network utility functions.
2
+
3
+package netutils
4
+
5
+import (
6
+	"net"
7
+	"strings"
8
+
9
+	"github.com/docker/libnetwork/types"
10
+	"github.com/vishvananda/netlink"
11
+)
12
+
13
+var (
14
+	networkGetRoutesFct = netlink.RouteList
15
+)
16
+
17
+// CheckRouteOverlaps checks whether the passed network overlaps with any existing routes
18
+func CheckRouteOverlaps(toCheck *net.IPNet) error {
19
+	networks, err := networkGetRoutesFct(nil, netlink.FAMILY_V4)
20
+	if err != nil {
21
+		return err
22
+	}
23
+
24
+	for _, network := range networks {
25
+		if network.Dst != nil && NetworkOverlaps(toCheck, network.Dst) {
26
+			return ErrNetworkOverlaps
27
+		}
28
+	}
29
+	return nil
30
+}
31
+
32
+// GenerateIfaceName returns an interface name using the passed in
33
+// prefix and the length of random bytes. The api ensures that the
34
+// there are is no interface which exists with that name.
35
+func GenerateIfaceName(prefix string, len int) (string, error) {
36
+	for i := 0; i < 3; i++ {
37
+		name, err := GenerateRandomName(prefix, len)
38
+		if err != nil {
39
+			continue
40
+		}
41
+		if _, err := netlink.LinkByName(name); err != nil {
42
+			if strings.Contains(err.Error(), "not found") {
43
+				return name, nil
44
+			}
45
+			return "", err
46
+		}
47
+	}
48
+	return "", types.InternalErrorf("could not generate interface name")
49
+}
... ...
@@ -21,10 +21,10 @@ load helpers
21 21
     run dnet_cmd 8080 network ls
22 22
     echo ${output}
23 23
     [ "$status" -ne 0 ]
24
-    run ./cmd/dnet/dnet -H=unix://var/run/dnet.sock network ls
24
+    run ./bin/dnet -H=unix://var/run/dnet.sock network ls
25 25
     echo ${output}
26 26
     [ "$status" -ne 0 ]
27
-    run ./cmd/dnet/dnet -H= -l=invalid network ls
27
+    run ./bin/dnet -H= -l=invalid network ls
28 28
     echo ${output}
29 29
     [ "$status" -ne 0 ]
30 30
     stop_dnet 1 c
... ...
@@ -73,7 +73,7 @@ function wait_for_dnet() {
73 73
     echo "waiting on dnet to come up ..."
74 74
     for i in `seq 1 10`;
75 75
     do
76
-	hrun ./cmd/dnet/dnet -H tcp://127.0.0.1:${hport} network ls
76
+	hrun ./bin/dnet -H tcp://127.0.0.1:${hport} network ls
77 77
 	echo ${output}
78 78
 	if [ "$status" -eq 0 ]; then
79 79
 	    return
... ...
@@ -168,7 +168,7 @@ EOF
168 168
 	   -v $(pwd)/${TMPC_ROOT}:/scratch \
169 169
 	   -v /usr/local/bin/runc:/usr/local/bin/runc \
170 170
 	   -w /go/src/github.com/docker/libnetwork \
171
-	   mrjana/golang ./cmd/dnet/dnet -d -D ${hopt} -c ${tomlfile}
171
+	   mrjana/golang ./bin/dnet -d -D ${hopt} -c ${tomlfile}
172 172
 
173 173
     wait_for_dnet $(inst_id2port ${inst}) ${name}
174 174
 }
... ...
@@ -196,7 +196,7 @@ function dnet_cmd() {
196 196
 
197 197
     hport=$1
198 198
     shift
199
-    ./cmd/dnet/dnet -H tcp://127.0.0.1:${hport} $*
199
+    ./bin/dnet -H tcp://127.0.0.1:${hport} $*
200 200
 }
201 201
 
202 202
 function dnet_exec() {