#!/usr/bin/env bash
#
# This script is designed to be run inside the container
#

# fail hard and fast even on pipelines
set -eo pipefail

# set debug based on envvar
[[ $DEBUG ]] && set -x

# configure etcd
export ETCD_PORT="${ETCD_PORT:-4001}"
export ETCD="$HOST:$ETCD_PORT"
export ETCD_PATH="${ETCD_PATH:-/deis/registry}"
export HOST_ETCD_PATH="${HOST_ETCD_PATH:-/deis/registry/hosts/$HOST}"
export ETCD_TTL="${ETCD_TTL:-20}"

# run.sh requires $REGISTRY_PORT
export REGISTRY_PORT="${PORT:-5000}"

export BUCKET_NAME="${BUCKET_NAME:-registry}"

# wait for etcd to be available
until etcdctl --no-sync -C "$ETCD" ls >/dev/null 2>&1; do
	echo "waiting for etcd at $ETCD..."
	sleep $((ETCD_TTL/2))  # sleep for half the TTL
done

# wait until etcd has discarded potentially stale values
sleep $((ETCD_TTL+1))

function etcd_set_default {
  set +e
  ERROR="$(etcdctl --no-sync -C "$ETCD" mk "$ETCD_PATH/$1" "$2" 2>&1 >/dev/null)"

  if [[ $? -ne 0 ]] && echo "$ERROR" | grep -iqve "key already exists"; then
    echo "etcd_set_default: an etcd error occurred ($ERROR)"
    echo "aborting..."
    exit 1
  fi
  set -e
}

# seed initial service configuration if necessary
etcd_set_default protocol http
etcd_set_default bucketName "${BUCKET_NAME}"

# wait for confd to run once and install initial templates
until confd -onetime -node "$ETCD" --confdir /app --log-level error; do
	echo "registry: waiting for confd to write initial templates..."
	sleep $((ETCD_TTL/2))  # sleep for half the TTL
done

# ensure registry bucket exists
/app/bin/create_bucket

# spawn the service in the background
cd /docker-registry
sudo -E -u registry docker-registry &
SERVICE_PID=$!

# smart shutdown on SIGINT and SIGTERM
function on_exit() {
	kill -TERM $SERVICE_PID
	wait $SERVICE_PID 2>/dev/null
	exit 0
}
trap on_exit INT TERM

# spawn confd in the background to update services based on etcd changes
confd -node "$ETCD" --confdir /app --log-level error --interval 5 &

echo deis-registry running...

# publish the service to etcd using the injected EXTERNAL_PORT
if [[ ! -z $EXTERNAL_PORT ]]; then

	# configure service discovery
	PORT=${PORT:-5000}
	PROTO=${PROTO:-tcp}

	set +e

	# wait for the service to become available on PORT
	sleep 1 && while [[ -z $(netstat -lnt | awk "\$6 == \"LISTEN\" && \$4 ~ \".$PORT\" && \$1 ~ \"$PROTO.?\"") ]] ; do sleep 1; done

	# while the port is listening, publish to etcd
	while [[ ! -z $(netstat -lnt | awk "\$6 == \"LISTEN\" && \$4 ~ \".$PORT\" && \$1 ~ \"$PROTO.?\"") ]] ; do
		if etcdctl --no-sync -C "$ETCD" mk "${ETCD_PATH}/masterLock" "$HOSTNAME" --ttl "$ETCD_TTL" >/dev/null 2>&1 \
		|| [[ $(etcdctl --no-sync -C "$ETCD" get "${ETCD_PATH}/masterLock") == "$HOSTNAME" ]] ; then
			etcdctl --no-sync -C "$ETCD" set "$ETCD_PATH/host" "$HOST" --ttl "$ETCD_TTL" >/dev/null
			etcdctl --no-sync -C "$ETCD" set "$ETCD_PATH/port" "$EXTERNAL_PORT" --ttl "$ETCD_TTL" >/dev/null
			etcdctl --no-sync -C "$ETCD" update "${ETCD_PATH}/masterLock" "$HOSTNAME" --ttl "$ETCD_TTL" >/dev/null
		fi
		etcdctl --no-sync -C "$ETCD" set "$HOST_ETCD_PATH/host" "$HOST" --ttl "$ETCD_TTL" >/dev/null
		etcdctl --no-sync -C "$ETCD" set "$HOST_ETCD_PATH/port" "$EXTERNAL_PORT" --ttl "$ETCD_TTL" >/dev/null

		sleep $((ETCD_TTL/2)) # sleep for half the TTL
	done

	# if the loop quits, something went wrong
	exit 1

fi

wait
