Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
executable file 256 lines (219 sloc) 8.68 KB
#!/bin/sh
set -e
[ -n "$WEAVE_DEBUG" ] && set -x
usage() {
cat <<-EOF
Weave Discovery
Usage:
# joins a discovery URL
$ discovery join [--advertise=ADDR]
[--advertise-external]
[--advertise-router]
[--weave=ADDR[:PORT]] <URL>
where <URL> = backend://path
<ADDR> = host|IP
# leaves current discovery URL
$ discovery leave
Example:
$ discovery join etcd://some/path
EOF
}
DOCKER_BRIDGE=${DOCKER_BRIDGE:-docker0}
DOCKERHUB_USER=${DOCKERHUB_USER:-weaveworks}
BASE_DISCOVERY_IMAGE=$DOCKERHUB_USER/weavediscovery
DISCOVERY_IMAGE=$BASE_DISCOVERY_IMAGE:$IMAGE_VERSION
DISCOVERY_CONTAINER_NAME=${WEAVE_DISCOVERY_NAME:-weavediscovery}
DISCOVERY_HTTP_PORT=6789
DISCOVERY_HTTP_IFNAME=eth0
WEAVER_CONTAINER_NAME=${WEAVE_CONTAINER_NAME:-weave}
DEFAULT_WEAVER_ADDR=
DEFAULT_WEAVER_HTTP_PORT=6784
WEAVER_ADDR=
WEAVER_PORT=6783 # we can only use the standard port
WEAVER_LOCAL_IP=
ADVERTISE_EXTERNAL=
ADVERTISE_ROUTER=
ADVERTISED_ADDR=
DISCOVERED_PORT=
######################################################################
# auxiliary functions
######################################################################
VALID_HOSTNAME_RE="^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$"
VALID_IP_RE="(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"
VALID_PORT_NUM_RE="^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$"
log() { echo "$1" >&2 ; }
warning() { log "WARNING: $1" ; }
error() { log "ERROR: $1" ; }
fatal() { log "FATAL: $1" ; exit 1 ; }
usage_and_abort() { [ -n "$1" ] && log "FATAL: $1" ; usage ; exit 1 ; }
command_exists() { command -v $1 >/dev/null 2>&1 ; }
parse_addr() { echo $1 | cut -d':' -f1 ; }
parse_port() { echo $1 | cut -d':' -f2 -s ; }
# Some auxiliary functions for names, IPs, ports...
valid_ip() { echo $1 | grep -E -q $VALID_IP_RE ; }
valid_hostname() { echo $1 | grep -E -q $VALID_HOSTNAME_RE ; }
valid_port_num() { echo $1 | grep -E -q $VALID_PORT_NUM_RE ; }
valid_addr() { valid_hostname $1 || valid_ip $1 ; }
valid_addr_or_die() { valid_addr $1 || fatal "'$1' does not seem a valid $2 address" ; }
valid_addr_and_port() { valid_addr $(parse_addr $1) && valid_port_num $(parse_port $1) ; }
valid_addr_and_port_or_die() { valid_addr_and_port $1 || fatal "'$1' does not seem a valid $2 address and port" ; }
docker_bridge_ip() {
DOCKER_BRIDGE_IP=$(ip -4 addr show dev $DOCKER_BRIDGE | grep -m1 -o 'inet [.0-9]*')
DOCKER_BRIDGE_IP=${DOCKER_BRIDGE_IP#inet }
echo $DOCKER_BRIDGE_IP
}
default_route_ip() { /sbin/ip route | awk '/default/ { print $3 }' ; }
guess_external_ip_or_die() {
fatal_guess() { fatal "could not determine external IP address: $1" ; }
command_exists dig || fatal_guess "'dig' command not found"
ADVERTISED_ADDR=$(dig +short myip.opendns.com @resolver1.opendns.com)
[ -n "$ADVERTISED_ADDR" ] || fatal_guess "got '$ADVERTISED_ADDR'"
echo $ADVERTISED_ADDR
}
url_proto() {
echo $1 | grep :// | sed -e's,^\(.*\)://.*,\1,g'
}
# Print an error to stderr and return with an indicative exit status
# if the container $1 does not exist or isn't running.
check_running() {
if ! STATUS=$(docker inspect --format='{{.State.Running}}' $1 2>/dev/null); then
echo "$1 container is not present. Have you launched it?" >&2
return 1
elif [ "$STATUS" != "true" ] ; then
echo "$1 container is not running." >&2
return 2
fi
}
# 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
"true $2") fatal "$1 is already running." ;;
"true $2:"*) fatal "$1 is already running." ;;
"false $2") docker rm $1 >/dev/null ;;
"false $2:"*) docker rm $1 >/dev/null ;;
true*) fatal "Found another running container named '$1'. Aborting." ;;
false*) fatal "Found another container named '$1'. Aborting." ;;
esac
}
stop() {
if ! docker stop $1 >/dev/null 2>&1 ; then
echo "$2 is not running." >&2
fi
docker rm -f $1 >/dev/null 2>&1 || true
}
launch_discovery() {
docker_args=$1
endpoint=$2
discovery_args="-http-iface $DISCOVERY_HTTP_IFNAME"
# check there is router we can talk to
if [ -z "$WEAVER_ADDR" ] ; then
# use the local docker0 address (eg, 172.17.42.1) for sending API request
WEAVER_API_IP=$(docker_bridge_ip)
else
WEAVER_API_IP=$WEAVER_ADDR
fi
valid_addr_or_die $WEAVER_ADDR "router"
weaver_http_url="http://$WEAVER_API_IP:$DEFAULT_WEAVER_HTTP_PORT"
if [ -n "$ADVERTISED_ADDR" ] ; then
:
elif [ -n "$ADVERTISE_EXTERNAL" ] ; then
ADVERTISED_ADDR=$(guess_external_ip_or_die):$WEAVER_PORT
elif [ -n "$ADVERTISE_ROUTER" ] ; then
if [ -n "$WEAVER_ADDR" ] ; then
# we are using a remote router, so it could (/should) be advertised
ADVERTISED_ADDR=$WEAVER_ADDR:$WEAVER_PORT
else
check_running $WEAVER_CONTAINER_NAME || \
fatal "trying to advertise local router, but it is not running"
# we are using a local router: we will advertise the default route IP
ADVERTISED_ADDR=$(default_route_ip):$WEAVER_PORT
fi
else
warning "nothing will be advertised"
fi
# when advertising, check there is a valid port in the $ADVERTISED_ADDR
if [ -n "$ADVERTISED_ADDR" ] ; then
valid_addr_and_port_or_die $ADVERTISED_ADDR "advertised"
log "Discovery will advertise $ADVERTISED_ADDR"
discovery_args="$discovery_args -local $ADVERTISED_ADDR"
fi
# we want to force a specific port for discovered peers in some cases (eg, when using swarm)
if [ -n "$DISCOVERED_PORT" ] ; then
discovery_args="$discovery_args -discovered-port $DISCOVERED_PORT"
fi
# process file:// endpoints by mounting the files and rewritting the URL
proto=$(url_proto $endpoint)
[ -z "$proto" ] && fatal "'$endpoint' does not seem valid discovery endpoint"
docker_mount_args=
if [ "$proto" = "file" ] ; then
host_path="$(echo $endpoint | grep / | cut -d/ -f2- | tr -s '/')"
[ -f $host_path ] || fatal "file '$host_path' not found"
container_path=/tmp/$(basename $host_path)
endpoint=file://$container_path
docker_mount_args="-v $host_path:$container_path"
fi
# Set WEAVEDISCOVERY_DOCKER_ARGS in the environment in order to supply
# additional parameters, such as resource limits, to docker
# when launching the weave container.
DISCOVERY_CONTAINER=$(docker run -d \
--name=$DISCOVERY_CONTAINER_NAME \
-e WEAVE_CIDR=none \
$WEAVEDISCOVERY_DOCKER_ARGS \
$docker_args \
$DISCOVERY_IMAGE \
$discovery_args \
-weave "$weaver_http_url" \
$endpoint )
}
##########################################################################################
[ $# -gt 0 ] || usage_and_abort
COMMAND=$1
shift 1
case "$COMMAND" in
join)
check_not_running $DISCOVERY_CONTAINER_NAME $BASE_DISCOVERY_IMAGE
while [ $# -gt 0 ] ; do
case "$1" in
--advertise=*)
ADVERTISED_ADDR="${1#*=}"
;;
--advertise-router)
ADVERTISE_ROUTER=1
;;
--advertise-external)
ADVERTISE_EXTERNAL=1
;;
--discovered-port=*)
DISCOVERED_PORT="${1#*=}"
;;
--weave=*)
WEAVER_ADDR=$(echo ${1#*=} | cut -d':' -f1)
#WEAVER_PORT=$(echo ${1#*=} | cut -d':' -f2 -s)
;;
*)
break
;;
esac
shift
done
docker_args=
while [ $# -gt 1 ] ; do docker_args="$docker_args $1" ; shift ; done
[ $# -ge 1 ] || fatal "endpoint not provided"
endpoint=$1
launch_discovery "$docker_args" $endpoint
echo $DISCOVERY_CONTAINER
;;
leave)
check_running $DISCOVERY_CONTAINER_NAME
stop $DISCOVERY_CONTAINER_NAME "Weave Discovery"
;;
help|--help)
usage
exit 0
;;
*)
echo "Unknown Discovery command '$COMMAND'" >&2
usage_and_abort
;;
esac
exit 0
You can’t perform that action at this time.