From d704ba175f4184d0a6b91d6a4c01e44eed0392c6 Mon Sep 17 00:00:00 2001 From: Paul Bellamy Date: Fri, 25 Sep 2015 16:33:10 +0100 Subject: [PATCH 1/2] [proxy] use a container-local unix socket to get the address, instead of logs --- prog/weaveproxy/main.go | 1 + proxy/proxy.go | 24 +++++++++++++++++++++--- weave | 41 +++++++++++++++++++++++++++-------------- 3 files changed, 49 insertions(+), 17 deletions(-) diff --git a/prog/weaveproxy/main.go b/prog/weaveproxy/main.go index f474a9e5..a0a247df 100644 --- a/prog/weaveproxy/main.go +++ b/prog/weaveproxy/main.go @@ -64,5 +64,6 @@ func main() { listeners := p.Listen() p.AttachExistingContainers() go p.Serve(listeners) + go p.ListenAndServeStatus("/home/weave/status.sock") SignalHandlerLoop() } diff --git a/proxy/proxy.go b/proxy/proxy.go index e6ca9599..dd441f3f 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -69,6 +69,7 @@ type Proxy struct { dockerBridgeIP string hostnameMatchRegexp *regexp.Regexp weaveWaitVolume string + normalisedAddrs []string waiters map[*http.Request]*wait } @@ -168,17 +169,17 @@ func (proxy *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (proxy *Proxy) Listen() []net.Listener { listeners := []net.Listener{} - addrs := []string{} + proxy.normalisedAddrs = []string{} for _, addr := range proxy.ListenAddrs { listener, normalisedAddr, err := proxy.listen(addr) if err != nil { Log.Fatalf("Cannot listen on %s: %s", addr, err) } listeners = append(listeners, listener) - addrs = append(addrs, normalisedAddr) + proxy.normalisedAddrs = append(proxy.normalisedAddrs, normalisedAddr) } - for _, addr := range addrs { + for _, addr := range proxy.normalisedAddrs { Log.Infoln("proxy listening on", addr) } return listeners @@ -199,6 +200,23 @@ func (proxy *Proxy) Serve(listeners []net.Listener) { } } +func (proxy *Proxy) ListenAndServeStatus(socket string) { + listener, err := net.Listen("unix", socket) + if err != nil { + Log.Fatalf("ListenAndServeStatus failed: %s", err) + } + handler := http.HandlerFunc(proxy.StatusHTTP) + if err := (&http.Server{Handler: handler}).Serve(listener); err != nil { + Log.Fatalf("ListenAndServeStatus failed: %s", err) + } +} + +func (proxy *Proxy) StatusHTTP(w http.ResponseWriter, r *http.Request) { + for _, addr := range proxy.normalisedAddrs { + fmt.Fprintln(w, addr) + } +} + func copyOwnerAndPermissions(from, to string) error { stat, err := os.Stat(from) if err != nil { diff --git a/weave b/weave index f7ecbe81..925d8ca5 100755 --- a/weave +++ b/weave @@ -662,6 +662,17 @@ http_call() { curl --connect-timeout 3 -s -S -X $http_verb "$@" http://$addr$url } +http_call_unix() { + container="$1" + socket="$2" + http_verb="$3" + url="$4" + shift 4 + output=$(docker exec $container curl -s -S -X $http_verb --unix-socket $socket "$@" http:$url) + [ -n "$output" ] || return 1 + echo $output +} + call_weave() { container_ip $CONTAINER_NAME \ "$CONTAINER_NAME container is not present. Have you launched it?" \ @@ -692,17 +703,19 @@ wait_for_status() { done } -# Wait until container $1 outputs a line containing $2 in its log -wait_for_log() { - fifo=/tmp/tmpfifo.$$ - mkfifo $fifo || exit 1 - docker logs -f $1 >$fifo 2>&1 & - res=0 - grep -q "$2" $fifo || res=1 - kill $! 2>/dev/null || true - rm $fifo - [ $res -eq 1 ] && echo "$(death_msg $1)" >&2 - return $res +# Wait until container $1 is alive enough to respond to "GET /status" +# http request is to unix socket "status.sock", we assume the container +# has curl >= 7.40 +wait_for_status_unix() { + err_msg=$(death_msg $1) + while true ; do + http_call_unix $1 status.sock GET /status >/dev/null 2>&1 && return 0 + if ! container_id $1 >/dev/null 2>&1 ; then + echo "$err_msg" >&2 + return 1 + fi + fractional_sleep 3.1 + done } # Call $1 for all containers, passing container ID, all MACs and all IPs @@ -1051,8 +1064,8 @@ proxy_args() { } proxy_addr() { - if addr=$(docker logs $PROXY_CONTAINER_NAME 2>&1 | head -n4 | grep -oE "proxy listening on .*") ; then - echo "${addr##* }" | sed "s/0.0.0.0/$PROXY_HOST/g" + if addr=$(http_call_unix $PROXY_CONTAINER_NAME status.sock GET /status 2>&1) ; then + echo "$addr" | head -n1 | sed "s/0.0.0.0/$PROXY_HOST/g" else echo "$PROXY_CONTAINER_NAME container is not present. Have you launched it?" >&2 return 1 @@ -1209,7 +1222,7 @@ launch_proxy() { -e DOCKER_BRIDGE \ --entrypoint=/home/weave/weaveproxy \ $WEAVEPROXY_DOCKER_ARGS $EXEC_IMAGE $COVERAGE_ARGS $PROXY_ARGS) - wait_for_log $PROXY_CONTAINER_NAME "proxy listening" + wait_for_status_unix $PROXY_CONTAINER_NAME } ########################################################################################## From 47c97e8191e667f30f4f5152515ff36c5df648b3 Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Mon, 28 Sep 2015 15:37:17 +0100 Subject: [PATCH 2/2] refactor: remove some code duplication --- weave | 35 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/weave b/weave index 925d8ca5..6d90b85b 100755 --- a/weave +++ b/weave @@ -668,7 +668,9 @@ http_call_unix() { http_verb="$3" url="$4" shift 4 + # NB: requires curl >= 7.40 output=$(docker exec $container curl -s -S -X $http_verb --unix-socket $socket "$@" http:$url) + # in some docker versions, `docker exec` does not fail when the executed command fails [ -n "$output" ] || return 1 echo $output } @@ -689,35 +691,20 @@ death_msg() { } # Wait until container $1 is alive enough to respond to "GET /status" -# http request on its docker-assigned IP +# http request wait_for_status() { - err_msg=$(death_msg $1) - container_ip $1 "$err_msg" "$err_msg" || return 1 + container="$1" + shift while true ; do - http_call $CONTAINER_IP:$HTTP_PORT GET /status >/dev/null 2>&1 && return 0 - if ! container_id $1 >/dev/null 2>&1 ; then - echo "$err_msg" >&2 + "$@" GET /status >/dev/null 2>&1 && return 0 + if ! container_id $container >/dev/null 2>&1 ; then + echo $(death_msg $container) >&2 return 1 fi fractional_sleep 0.1 done } -# Wait until container $1 is alive enough to respond to "GET /status" -# http request is to unix socket "status.sock", we assume the container -# has curl >= 7.40 -wait_for_status_unix() { - err_msg=$(death_msg $1) - while true ; do - http_call_unix $1 status.sock GET /status >/dev/null 2>&1 && return 0 - if ! container_id $1 >/dev/null 2>&1 ; then - echo "$err_msg" >&2 - return 1 - fi - fractional_sleep 3.1 - done -} - # Call $1 for all containers, passing container ID, all MACs and all IPs with_container_addresses() { COMMAND=$1 @@ -1186,7 +1173,9 @@ launch_router() { -e WEAVE_CIDR=none \ $WEAVE_DOCKER_ARGS $IMAGE $COVERAGE_ARGS --iface $CONTAINER_IFNAME --port $CONTAINER_PORT --name "$PEERNAME" --nickname "$(hostname)" --ipalloc-range "$IPRANGE" --dns-effective-listen-address "$DOCKER_BRIDGE_IP" "$@") with_container_netns_or_die $ROUTER_CONTAINER launch - wait_for_status $CONTAINER_NAME + err_msg=$(death_msg $CONTAINER_NAME) + container_ip $CONTAINER_NAME "$err_msg" "$err_msg" || return 1 + wait_for_status $CONTAINER_NAME http_call $CONTAINER_IP:$HTTP_PORT if [ -n "$IPRANGE" ] ; then # Tell the newly-started weave IP allocator about existing weave IPs with_container_addresses ipam_reclaim weave:expose $(docker ps -q --no-trunc) @@ -1222,7 +1211,7 @@ launch_proxy() { -e DOCKER_BRIDGE \ --entrypoint=/home/weave/weaveproxy \ $WEAVEPROXY_DOCKER_ARGS $EXEC_IMAGE $COVERAGE_ARGS $PROXY_ARGS) - wait_for_status_unix $PROXY_CONTAINER_NAME + wait_for_status $PROXY_CONTAINER_NAME http_call_unix $PROXY_CONTAINER_NAME status.sock } ##########################################################################################