From 3d8249b4c396738abebec6cd31f5f223673b7adc Mon Sep 17 00:00:00 2001 From: Michael Bridgen Date: Tue, 18 Nov 2014 14:24:44 +0000 Subject: [PATCH 1/3] Populate DNS when starting the weaveDNS container --- weave | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/weave b/weave index 6b63d348..5b8d35f2 100755 --- a/weave +++ b/weave @@ -308,6 +308,19 @@ tell_dns() { http_call $1 $DNS_CONTAINER_NAME $DNS_HTTP_PORT /name/$CONTAINER/$WEAVE_ADDR_IP $MORE_ARGS } +# Tell the newly-started weaveDNS about existing weave IPs +populate_dns() { + for CONTAINER in $(docker ps -q); do + MORE_ARGS=$(docker inspect --format '--data-urlencode local_ip={{ .NetworkSettings.IPAddress }} --data-urlencode fqdn={{ .Config.Hostname }}.{{ .Config.Domainname }}.' $CONTAINER 2>/dev/null) && true + if CONTAINER_ADDRS=$(with_container_netns $CONTAINER container_weave_addrs 2>&1) ; then + CONTAINER_IPS=$(echo "$CONTAINER_ADDRS" | grep -o 'inet .*' | sed -e 's/inet \([^/]*\)\/\(.*\)/\1/') + for IP in $CONTAINER_IPS; do + http_call PUT $DNS_CONTAINER_NAME $DNS_HTTP_PORT /name/$CONTAINER/$IP $MORE_ARGS + done + fi + done +} + # Check that a container named $1 with image $2 is not running check_not_running() { case $(docker inspect --format '{{ .State.Running }} {{ .Config.Image }}' $1 2>/dev/null) in @@ -379,9 +392,10 @@ case "$COMMAND" in check_not_running $DNS_CONTAINER_NAME $DNS_IMAGE create_bridge docker_bridge_ip - CONTAINER=$(docker run --privileged -d --name=$DNS_CONTAINER_NAME -p $DOCKER_BRIDGE_IP:53:53/udp -v /var/run/docker.sock:/var/run/docker.sock $DNS_IMAGE "$@" | tail -n 1) - with_container_netns $CONTAINER attach $CIDR >/dev/null - echo $CONTAINER + DNS_CONTAINER=$(docker run --privileged -d --name=$DNS_CONTAINER_NAME -p $DOCKER_BRIDGE_IP:53:53/udp -v /var/run/docker.sock:/var/run/docker.sock $DNS_IMAGE "$@" | tail -n 1) + with_container_netns $DNS_CONTAINER attach $CIDR >/dev/null + populate_dns + echo $DNS_CONTAINER ;; connect) [ $# -eq 1 ] || usage From 6a076d05b051f50478c70a52fd62e6d1ebe5a6dd Mon Sep 17 00:00:00 2001 From: Michael Bridgen Date: Thu, 20 Nov 2014 14:21:01 +0000 Subject: [PATCH 2/3] Only get the DNS container IP once `populate_dns` previously used http_call, which looks up the IP for a container each time. I've factored the HTTP bit after the IP look-up in http_call out, so it can be used directly. This involved switching arguments around to make the tail call easier. --- weave | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/weave b/weave index 5b8d35f2..d3c00b2b 100755 --- a/weave +++ b/weave @@ -262,27 +262,33 @@ detach() { ip link del $LOCAL_IFNAME type veth } -# Call url $4 on container $2 at port $3 with http verb $1 +# Call url $4 with http verb $3 on container $1 at port $2 http_call() { - http_verb="$1" - if ! status=$(docker inspect --format='{{ .State.Running }} {{ .NetworkSettings.IPAddress }}' $2 2>/dev/null); then - echo "$2 container is not present; have you launched it?" >&2 + if ! status=$(docker inspect --format='{{ .State.Running }} {{ .NetworkSettings.IPAddress }}' $1 2>/dev/null); then + echo "$1 container is not present; have you launched it?" >&2 exit 1 fi case "$status" in "true ") - echo "$2 container has no IP address; is Docker networking enabled?" >&2 + echo "$1 container has no IP address; is Docker networking enabled?" >&2 exit 1 ;; true*) ip="${status#true }" ;; *) - echo "$2 container is not running." >&2 + echo "$1 container is not running." >&2 exit 1 ;; esac - port="$3" + shift 1 + http_call_ip $ip $@ +} + +http_call_ip() { + ip="$1" + port="$2" + http_verb="$3" url="$4" shift 4 if command_exists curl ; then @@ -305,17 +311,18 @@ tell_dns() { # extract IP address and routing prefix from CIDR WEAVE_ADDR_IP=$(echo $3 | sed -e 's/\([^/]*\)\/\(.*\)/\1/') MORE_ARGS=$(docker inspect --format '--data-urlencode local_ip={{ .NetworkSettings.IPAddress }} --data-urlencode fqdn={{ .Config.Hostname }}.{{ .Config.Domainname }}.' $CONTAINER 2>/dev/null) && true - http_call $1 $DNS_CONTAINER_NAME $DNS_HTTP_PORT /name/$CONTAINER/$WEAVE_ADDR_IP $MORE_ARGS + http_call $DNS_CONTAINER_NAME $DNS_HTTP_PORT $1 /name/$CONTAINER/$WEAVE_ADDR_IP $MORE_ARGS } # Tell the newly-started weaveDNS about existing weave IPs populate_dns() { + DNS_IP=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' $DNS_CONTAINER_NAME) for CONTAINER in $(docker ps -q); do MORE_ARGS=$(docker inspect --format '--data-urlencode local_ip={{ .NetworkSettings.IPAddress }} --data-urlencode fqdn={{ .Config.Hostname }}.{{ .Config.Domainname }}.' $CONTAINER 2>/dev/null) && true if CONTAINER_ADDRS=$(with_container_netns $CONTAINER container_weave_addrs 2>&1) ; then CONTAINER_IPS=$(echo "$CONTAINER_ADDRS" | grep -o 'inet .*' | sed -e 's/inet \([^/]*\)\/\(.*\)/\1/') for IP in $CONTAINER_IPS; do - http_call PUT $DNS_CONTAINER_NAME $DNS_HTTP_PORT /name/$CONTAINER/$IP $MORE_ARGS + http_call_ip $DNS_IP $DNS_HTTP_PORT PUT /name/$CONTAINER/$IP $MORE_ARGS done fi done @@ -399,10 +406,10 @@ case "$COMMAND" in ;; connect) [ $# -eq 1 ] || usage - http_call POST $CONTAINER_NAME $HTTP_PORT /connect -d "peer=$1" + http_call $CONTAINER_NAME $HTTP_PORT POST /connect -d "peer=$1" ;; status) - http_call GET $CONTAINER_NAME $HTTP_PORT /status + http_call $CONTAINER_NAME $HTTP_PORT GET /status ;; ps) [ $# -eq 0 ] || usage From b3d19d6e9db7d5785452fbcf9b696e483d7f9538 Mon Sep 17 00:00:00 2001 From: Michael Bridgen Date: Tue, 25 Nov 2014 12:14:40 +0000 Subject: [PATCH 3/3] Wait for weaveDNS HTTP to be running before sending it names This adds a no-op endpoint to the HTTP API at `/status`. The script simply tries this until it succeeds or gets bored. --- nameserver/http.go | 10 ++++++++++ weave | 11 +++++++++++ 2 files changed, 21 insertions(+) diff --git a/nameserver/http.go b/nameserver/http.go index b25b9204..d6895d7d 100644 --- a/nameserver/http.go +++ b/nameserver/http.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "github.com/miekg/dns" + "io" "log" "net" "net/http" @@ -26,6 +27,15 @@ func httpErrorAndLog(level *log.Logger, w http.ResponseWriter, msg string, } func ListenHttp(domain string, db Zone, port int) { + + http.HandleFunc("/status", func(w http.ResponseWriter, r *http.Request) { + if r.Method != "GET" { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + } else { + io.WriteString(w, "ok") + } + }) + http.HandleFunc("/name/", func(w http.ResponseWriter, r *http.Request) { reqError := func(msg string, logmsg string, logargs ...interface{}) { diff --git a/weave b/weave index d3c00b2b..b044a7cc 100755 --- a/weave +++ b/weave @@ -317,6 +317,17 @@ tell_dns() { # Tell the newly-started weaveDNS about existing weave IPs populate_dns() { DNS_IP=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' $DNS_CONTAINER_NAME) + WAIT_TIME=1 + while ! http_call_ip $DNS_IP $DNS_HTTP_PORT GET /status >/dev/null && [ $WAIT_TIME -lt 4 ]; do + echo "Waiting for weaveDNS container to start" >&2 + sleep $WAIT_TIME + WAIT_TIME=$((WAIT_TIME+1)) + done + if [ $WAIT_TIME = 4 ]; then + echo "Timed out waiting for weaveDNS container to start." >&2 + echo "If running, it will not be pre-populated." >&2 + fi + for CONTAINER in $(docker ps -q); do MORE_ARGS=$(docker inspect --format '--data-urlencode local_ip={{ .NetworkSettings.IPAddress }} --data-urlencode fqdn={{ .Config.Hostname }}.{{ .Config.Domainname }}.' $CONTAINER 2>/dev/null) && true if CONTAINER_ADDRS=$(with_container_netns $CONTAINER container_weave_addrs 2>&1) ; then