diff --git a/proxy/common.go b/proxy/common.go index ddfa85e6..1198ef1b 100644 --- a/proxy/common.go +++ b/proxy/common.go @@ -31,8 +31,7 @@ func callWeave(args ...string) ([]byte, error) { func weaveCIDRsFromConfig(config *docker.Config) ([]string, bool) { for _, e := range config.Env { if strings.HasPrefix(e, "WEAVE_CIDR=") { - result := strings.Trim(e[11:], " ") - return strings.Split(strings.TrimSpace(result), " "), result != "" + return strings.Fields(e[11:]), true } } return nil, false diff --git a/proxy/proxy.go b/proxy/proxy.go index de565f6b..03ba90eb 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -22,9 +22,10 @@ type Proxy struct { client *docker.Client withDNS bool dockerBridgeIP string + withIPAM bool } -func NewProxy(targetURL string, withDNS bool) (*Proxy, error) { +func NewProxy(targetURL string, withDNS, withIPAM bool) (*Proxy, error) { u, err := url.Parse(targetURL) if err != nil { return nil, err @@ -58,6 +59,7 @@ func NewProxy(targetURL string, withDNS bool) (*Proxy, error) { client: client, withDNS: withDNS, dockerBridgeIP: string(dockerBridgeIP), + withIPAM: withIPAM, }, nil } @@ -68,7 +70,7 @@ func (proxy *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { case containerCreateRegexp.MatchString(path): proxy.serveWithInterceptor(&createContainerInterceptor{proxy.client, proxy.withDNS, proxy.dockerBridgeIP}, w, r) case containerStartRegexp.MatchString(path): - proxy.serveWithInterceptor(&startContainerInterceptor{proxy.client, proxy.withDNS}, w, r) + proxy.serveWithInterceptor(&startContainerInterceptor{proxy.client, proxy.withDNS, proxy.withIPAM}, w, r) case execCreateRegexp.MatchString(path): proxy.serveWithInterceptor(&createExecInterceptor{proxy.client}, w, r) case strings.HasPrefix(path, "/weave"): diff --git a/proxy/start_container_interceptor.go b/proxy/start_container_interceptor.go index d35c3afd..bce86074 100644 --- a/proxy/start_container_interceptor.go +++ b/proxy/start_container_interceptor.go @@ -9,8 +9,9 @@ import ( ) type startContainerInterceptor struct { - client *docker.Client - withDNS bool + client *docker.Client + withDNS bool + withIPAM bool } func (i *startContainerInterceptor) InterceptRequest(r *http.Request) error { @@ -24,7 +25,7 @@ func (i *startContainerInterceptor) InterceptResponse(r *http.Response) error { } cidrs, ok := weaveCIDRsFromConfig(container.Config) - if !ok { + if !ok && !i.withIPAM { Debug.Print("No Weave CIDR, ignoring") return nil } @@ -34,7 +35,6 @@ func (i *startContainerInterceptor) InterceptResponse(r *http.Response) error { args = append(args, container.ID) if _, err := callWeave(args...); err != nil { Warning.Printf("Attaching container %s to weave network failed: %v", container.ID, err) - return nil } return nil } diff --git a/site/proxy.md b/site/proxy.md index c1d0daa0..9643b236 100644 --- a/site/proxy.md +++ b/site/proxy.md @@ -22,7 +22,7 @@ and listen on port 12375. However, we can adjust the connection to docker via the `-H` argument. All docker commands can be run via the proxy, so it is safe to globally adjust your `DOCKER_HOST`. - host1$ export DOCKER_HOST="tcp://host1:12375" + host1$ export DOCKER_HOST=tcp://host1:12375 host1$ docker ps ## Usage @@ -53,6 +53,24 @@ Containers started via the proxy can be automatically configured to use WeaveDNS With this done, any containers launched through the proxy will use weaveDNS for name resolution. WeaveDNS is used in addition to any dns servers specified via the `--dns` option. More details on weaveDNS can be found in the [weaveDNS documentation](weavedns.html). +## Usage with IPAM + +To automatically assign a unique IP address to a container, weave must be told on startup what range of addresses to allocate from. For example: + + host1# weave launch -iprange 10.2.3.0/24 + host1$ weave launch-proxy + host1$ export DOCKER_HOST=tcp://host1:12375 + +With this done, we can automtaically assign an address to a container by providing a blank `WEAVE_CIDR` value, as in + + host1$ docker run -e WEAVE_CIDR= -ti ubuntu /bin/sh + +Alternatively, to enable automatic allocation of all containers without a `WEAVE_CIDR`, we can launch the proxy with the `--with-ipam` option. For example: + + host1$ weave launch-proxy --with-ipam + +More details on IPAM can be found in the [IPAM documentation](ipam.html). + ## Limitations * The proxy does not currently support TLS. diff --git a/test/140_weave_local_test.sh b/test/140_weave_local_test.sh index bf6d88f4..f3c74de2 100755 --- a/test/140_weave_local_test.sh +++ b/test/140_weave_local_test.sh @@ -9,10 +9,10 @@ run_on $HOST1 sudo ./weave --local reset run_on $HOST1 sudo ./weave --local launch -iprange 10.2.5.0/24 assert_raises "docker_on $HOST1 ps | grep weave" -run_on $HOST1 sudo ./weave --local run 10.2.6.5/24 -ti --name=c1 gliderlabs/alpine /bin/sh +run_on $HOST1 sudo ./weave --local run 10.2.6.5/24 -ti --name=c1 $SMALL_IMAGE /bin/sh assert_raises "exec_on $HOST1 c1 $CHECK_ETHWE_UP" -run_on $HOST1 sudo ./weave --local run -ti --name=c2 gliderlabs/alpine /bin/sh +run_on $HOST1 sudo ./weave --local run -ti --name=c2 $SMALL_IMAGE /bin/sh assert_raises "exec_on $HOST1 c2 $CHECK_ETHWE_UP" end_suite diff --git a/test/610_proxy_wait_for_weave_test.sh b/test/610_proxy_wait_for_weave_test.sh index 189795e9..ff339293 100755 --- a/test/610_proxy_wait_for_weave_test.sh +++ b/test/610_proxy_wait_for_weave_test.sh @@ -10,6 +10,6 @@ if (docker_on $HOST1 images $BASE_IMAGE | grep $BASE_IMAGE); then docker_on $HOST1 rmi $BASE_IMAGE fi -assert_raises "docker_proxy_on $HOST1 run -e 'WEAVE_CIDR=10.2.1.1/24' $BASE_IMAGE $CHECK_ETHWE_UP" +assert_raises "proxy docker_on $HOST1 run -e 'WEAVE_CIDR=10.2.1.1/24' $BASE_IMAGE $CHECK_ETHWE_UP" end_suite diff --git a/test/620_proxy_entrypoint_inheritance_test.sh b/test/620_proxy_entrypoint_inheritance_test.sh index 2bb2fce6..0629d7c0 100755 --- a/test/620_proxy_entrypoint_inheritance_test.sh +++ b/test/620_proxy_entrypoint_inheritance_test.sh @@ -5,10 +5,10 @@ start_suite "Proxy uses entrypoint from the image with weavewait" weave_on $HOST1 launch-proxy docker_on $HOST1 build -t inspect-ethwe - <<- EOF - FROM gliderlabs/alpine + FROM $SMALL_IMAGE ENTRYPOINT ["ip", "link", "show", "ethwe"] EOF -assert_raises "docker_proxy_on $HOST1 run -e 'WEAVE_CIDR=10.2.1.1/24' inspect-ethwe | grep 'state UP'" +assert_raises "proxy docker_on $HOST1 run -e 'WEAVE_CIDR=10.2.1.1/24' inspect-ethwe | grep 'state UP'" end_suite diff --git a/test/630_proxy_dns_test.sh b/test/630_proxy_dns_test.sh index e4b94fee..fa6fba8f 100755 --- a/test/630_proxy_dns_test.sh +++ b/test/630_proxy_dns_test.sh @@ -10,8 +10,8 @@ start_suite "Proxy registers containers with dns" weave_on $HOST1 launch-dns 10.2.254.1/24 weave_on $HOST1 launch-proxy --with-dns -docker_proxy_on $HOST1 run -e WEAVE_CIDR=$C2/24 -dt --name=c2 -h $NAME gliderlabs/alpine /bin/sh -docker_proxy_on $HOST1 run -e WEAVE_CIDR=$C1/24 -dt --name=c1 aanand/docker-dnsutils /bin/sh +proxy docker_on $HOST1 run -e WEAVE_CIDR=$C2/24 -dt --name=c2 -h $NAME $SMALL_IMAGE /bin/sh +proxy docker_on $HOST1 run -e WEAVE_CIDR=$C1/24 -dt --name=c1 $DNS_IMAGE /bin/sh assert_dns_record $HOST1 c1 $NAME $C2 diff --git a/test/640_proxy_restart_reattaches_test.sh b/test/640_proxy_restart_reattaches_test.sh index 2e8e332a..13a193e4 100755 --- a/test/640_proxy_restart_reattaches_test.sh +++ b/test/640_proxy_restart_reattaches_test.sh @@ -10,11 +10,11 @@ start_suite "Proxy restart reattaches networking to containers" weave_on $HOST1 launch-dns 10.2.254.1/24 weave_on $HOST1 launch-proxy --with-dns -docker_proxy_on $HOST1 run -e WEAVE_CIDR=$C2/24 -dt --name=c2 -h $NAME gliderlabs/alpine /bin/sh -docker_proxy_on $HOST1 run -e WEAVE_CIDR=$C1/24 -dt --name=c1 aanand/docker-dnsutils /bin/sh +proxy docker_on $HOST1 run -e WEAVE_CIDR=$C2/24 -dt --name=c2 -h $NAME $SMALL_IMAGE /bin/sh +proxy docker_on $HOST1 run -e WEAVE_CIDR=$C1/24 -dt --name=c1 $DNS_IMAGE /bin/sh -docker_proxy_on $HOST1 restart c2 -assert_raises "proxy_exec_on $HOST1 c2 $CHECK_ETHWE_UP" +proxy docker_on $HOST1 restart c2 +assert_raises "proxy exec_on $HOST1 c2 $CHECK_ETHWE_UP" assert_dns_record $HOST1 c1 $NAME $C2 end_suite diff --git a/test/650_proxy_entrypoint_override_test.sh b/test/650_proxy_entrypoint_override_test.sh index 4f826408..bd45bdcd 100755 --- a/test/650_proxy_entrypoint_override_test.sh +++ b/test/650_proxy_entrypoint_override_test.sh @@ -5,10 +5,10 @@ start_suite "Proxy allows overridden entrypoint from the container with weavewait" weave_on $HOST1 launch-proxy docker_on $HOST1 build -t false - <<- EOF - FROM gliderlabs/alpine + FROM $SMALL_IMAGE ENTRYPOINT ["/bin/false"] EOF -assert_raises "docker_proxy_on $HOST1 run -e 'WEAVE_CIDR=10.2.1.1/24' --entrypoint '/sbin/ip' false link show ethwe | grep 'state UP'" +assert_raises "proxy docker_on $HOST1 run -e 'WEAVE_CIDR=10.2.1.1/24' --entrypoint '/sbin/ip' false link show ethwe | grep 'state UP'" end_suite diff --git a/test/660_proxy_ipam_test.sh b/test/660_proxy_ipam_test.sh new file mode 100755 index 00000000..601b2fd3 --- /dev/null +++ b/test/660_proxy_ipam_test.sh @@ -0,0 +1,22 @@ +#! /bin/bash + +. ./config.sh + +UNIVERSE=10.2.2.0/24 + +start_suite "Ping proxied containers over cross-host weave network (with IPAM)" + +weave_on $HOST1 launch -iprange $UNIVERSE +weave_on $HOST1 launch-proxy +weave_on $HOST2 launch -iprange $UNIVERSE $HOST1 +weave_on $HOST2 launch-proxy --with-ipam + +proxy docker_on $HOST1 run -e WEAVE_CIDR= --name=c1 -dt $SMALL_IMAGE /bin/sh +proxy docker_on $HOST2 run --name=c2 -dt $SMALL_IMAGE /bin/sh + +C1=$(container_ip $HOST1 c1) +C2=$(container_ip $HOST2 c2) +assert_raises "proxy exec_on $HOST1 c1 $PING $C2" +assert_raises "proxy exec_on $HOST2 c2 $PING $C1" + +end_suite diff --git a/test/config.sh b/test/config.sh index b8c657a1..8e74c5ab 100644 --- a/test/config.sh +++ b/test/config.sh @@ -29,9 +29,13 @@ HOST2=$(echo $HOSTS | cut -f 2 -d ' ') SSH=${SSH:-ssh -l vagrant -i ./insecure_private_key -o UserKnownHostsFile=./.ssh_known_hosts -o CheckHostIP=no -o StrictHostKeyChecking=no} +SMALL_IMAGE="gliderlabs/alpine" +DNS_IMAGE="aanand/docker-dnsutils" PING="ping -nq -W 1 -c 1" CHECK_ETHWE_UP="grep ^1$ /sys/class/net/ethwe/carrier" +DOCKER_PORT=2375 + remote() { rem=$1 shift 1 @@ -73,49 +77,38 @@ run_on() { docker_on() { host=$1 shift 1 - greyly echo "Docker on $host: $@" >&2 - docker -H tcp://$host:2375 "$@" + greyly echo "Docker on $host:$DOCKER_PORT: $@" >&2 + docker -H tcp://$host:$DOCKER_PORT "$@" } -docker_proxy_on() { - host=$1 - shift 1 - greyly echo "Docker (with proxy) on $host: $@" >&2 - docker -H tcp://$host:12375 "$@" +proxy() { + DOCKER_PORT=12375 "$@" } weave_on() { host=$1 shift 1 - greyly echo "Weave on $host: $@" >&2 - DOCKER_HOST=tcp://$host:2375 $WEAVE "$@" + greyly echo "Weave on $host:$DOCKER_PORT: $@" >&2 + DOCKER_HOST=tcp://$host:$DOCKER_PORT $WEAVE "$@" } exec_on() { host=$1 container=$2 shift 2 - docker -H tcp://$host:2375 exec $container "$@" + docker -H tcp://$host:$DOCKER_PORT exec $container "$@" } -proxy_exec_on() { - host=$1 - container=$2 - shift 2 - docker -H tcp://$host:12375 exec $container "$@" -} - - start_container() { host=$1 shift 1 - weave_on $host run "$@" -t gliderlabs/alpine /bin/sh + weave_on $host run "$@" -t $SMALL_IMAGE /bin/sh } start_container_with_dns() { host=$1 shift 1 - weave_on $host run --with-dns "$@" -t aanand/docker-dnsutils /bin/sh + weave_on $host run --with-dns "$@" -t $DNS_IMAGE /bin/sh } container_ip() { diff --git a/weave b/weave index 45295f52..87965cee 100755 --- a/weave +++ b/weave @@ -25,26 +25,26 @@ CIDR_REGEXP="$IP_REGEXP/[0-9]{1,2}" usage() { echo "Usage:" echo "weave setup" - echo "weave launch [-password ] [-nickname ] [-iprange ] ..." - echo "weave launch-dns " - echo "weave launch-proxy [-H ] [--with-dns]" - echo "weave connect " - echo "weave forget " - echo "weave run [--with-dns] [ ...] ..." - echo "weave start [ ...] " - echo "weave attach [ ...] " - echo "weave detach [ ...] " - echo "weave dns-add [ ...] [-h ]" - echo "weave dns-remove [ ...] " - echo "weave expose [ ...] [-h ]" - echo "weave hide [ ...]" - echo "weave ps [ ...]" + echo "weave launch [-password ] [-nickname ] [-iprange ] ..." + echo "weave launch-dns " + echo "weave launch-proxy [-H ] [--with-dns] [--with-ipam]" + echo "weave connect " + echo "weave forget " + echo "weave run [--with-dns] [ ...] ..." + echo "weave start [ ...] " + echo "weave attach [ ...] " + echo "weave detach [ ...] " + echo "weave dns-add [ ...] [-h ]" + echo "weave dns-remove [ ...] " + echo "weave expose [ ...] [-h ]" + echo "weave hide [ ...]" + echo "weave ps [ ...]" echo "weave status" echo "weave version" echo "weave stop" echo "weave stop-dns" echo "weave reset" - echo "weave rmpeer " + echo "weave rmpeer " echo echo "where is of the form [:], and" echo " is of the form /" diff --git a/weaveproxy/main.go b/weaveproxy/main.go index 2a395ae1..2d0baf93 100644 --- a/weaveproxy/main.go +++ b/weaveproxy/main.go @@ -16,12 +16,13 @@ var ( func main() { var target, listen string - var withDNS, debug bool + var withDNS, withIPAM, debug bool getopt.BoolVarLong(&debug, "debug", 'd', "log debugging information") getopt.StringVar(&target, 'H', fmt.Sprintf("docker daemon URL to proxy (default %s)", defaultTarget)) getopt.StringVar(&listen, 'L', fmt.Sprintf("address on which to listen (default %s)", defaultListen)) getopt.BoolVarLong(&withDNS, "with-dns", 'w', "instruct created containers to use weaveDNS as their nameserver") + getopt.BoolVarLong(&withIPAM, "with-ipam", 'i', "automatically allocate addresses for containers without a WEAVE_CIDR") getopt.Parse() if target == "" { @@ -36,7 +37,7 @@ func main() { InitDefaultLogging(true) } - p, err := proxy.NewProxy(target, withDNS) + p, err := proxy.NewProxy(target, withDNS, withIPAM) if err != nil { Error.Fatalf("Could not start proxy: %s", err) }