#!/bin/bash

# Adds a gear to the haproxy configuration.

# Exit on any errors
set -e

source /etc/openshift/node.conf

function print_help {
    echo "Usage: $0 app-name namespace uuid"
    echo "Start a running application"

    echo "$0 $@" | logger -p local0.notice -t openshift_origin_haproxy_set_proxy
    exit 1
}

while getopts 'd' OPTION
do
    case $OPTION in
        d) set -x
        ;;
        ?) print_help
        ;;
    esac
done


[ $# -gt 3 ] || print_help

exitcode=0

declare -A curr_server_gears

haproxy_cfg=$OPENSHIFT_HAPROXY_DIR/conf/haproxy.cfg

# Establish locking file descriptor
exec 200>${haproxy_cfg}.lock

# Remove the first 3 args and process all the remaining args of the form k=v.
# The values are the gear endpoints.
kvargs=$(echo "${@:4}" | tr -d "\n" )
for arg in $kvargs; do
    zinfo=$(echo "$arg" | cut -f 2 -d '=' | tr -d "'")
    zarr=(${zinfo//|/ })
    ep="${zarr[1]}"
    #  Add gear to the proxy configuration if not already in there.
    #  Gear end-point is the form: $gear-ipaddress:$gear-port
    gear_name=$(echo "${zarr[0]}" | cut -f 1 -d '.')

    # Ensure endpoint is valid.
    [ -z "$ep" ]  &&  continue

    # And of the form: $ipv4-address:$port-number
    if [[ ! $ep =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}:[0-9]{4,5} ]]; then
       # write/log error, set exit code but continue/process remaining entries.
       echo "${@:1:3} - Invalid endpoint '$ep' passed in input - $zinfo" 1>&2
       exitcode=22
       continue
    fi

	# If this is the local gear, we are NOT creating an entry for it
	# The local gear entry is made separately later below
    if [ "$OPENSHIFT_GEAR_DNS" != "${zarr[0]}" ]; then 
        flock 200
        curr_server_gears[$gear_name]="$ep"
        if grep "server gear-$gear_name" "$haproxy_cfg" > /dev/null 2>&1; then
            sed -i "/\s*server\s*gear-${gear_name}\s.*/d" $haproxy_cfg
        fi

        echo "    server gear-$gear_name $ep check fall 2 rise 3 inter 2000 cookie $gear_name" >> "$haproxy_cfg"
        flock -u 200
    fi
done

# Now remove all the gears from the haproxy configuration which are not in the
# current set. No recreate permissions on haproxy.cfg, so need to use a temp
# file to operate on and then overlay the contents of haproxy.cfg
srvgears=$(grep -E "server\s*gear" "$haproxy_cfg" |  \
           sed "s/\s*server\s*gear-\([A-Za-z0-9\-]*\)\s.*/\\1/g" | tr "\n" " ")
flock 200
cp -f "$haproxy_cfg" /tmp/haproxy.cfg.$$
for sg in $srvgears; do
    if [ -z "${curr_server_gears[$sg]}" ]; then
        sed -i "/\s*server\s*gear-$sg\s.*/d" /tmp/haproxy.cfg.$$
    fi
done

# Get the local app server endpoint.
# TODO: SDK should provide a better way to get this value
prim_cart=$(grep "Cartridge-Short-Name" $OPENSHIFT_PRIMARY_CARTRIDGE_DIR/metadata/manifest.yml | cut -d: -f2 | xargs)
prim_cart_ip="OPENSHIFT_${prim_cart}_IP"
prim_cart_port="OPENSHIFT_${prim_cart}_PORT"
eval local_ip=\$${prim_cart_ip}
if [ -z "$local_ip" ]; then
    first_ip_in_manifest=$(grep Endpoints: $OPENSHIFT_PRIMARY_CARTRIDGE_DIR/metadata/manifest.yml -A 5 | grep Private-IP-Name | cut -d":" -f2  | xargs)
    prim_cart_ip="OPENSHIFT_${prim_cart}_${first_ip_in_manifest}"
    eval local_ip=\$${prim_cart_ip}
fi
eval local_port=\$${prim_cart_port}
if [ -z "$local_port" ]; then
    first_port_in_manifest=$(grep Endpoints: $OPENSHIFT_PRIMARY_CARTRIDGE_DIR/metadata/manifest.yml -A 5 | grep Private-Port-Name | cut -d":" -f2  | xargs)
    prim_cart_port="OPENSHIFT_${prim_cart}_${first_port_in_manifest}"
    eval local_port=\$${prim_cart_port}
fi
local_ep=$local_ip:$local_port

# Enable local endpoint based on number of serving gears.
if [ $(grep -E "server\s*gear" /tmp/haproxy.cfg.$$ | wc -l) -le 1 ]; then
    # re-add local-gear with maxconn 2.
    sed -i "/\s*server\s*local-gear\s.*/d" /tmp/haproxy.cfg.$$
    echo "    server local-gear $local_ep maxconn 2 check fall 2 rise 3 inter 2000 cookie local-$OPENSHIFT_GEAR_UUID" >> /tmp/haproxy.cfg.$$
fi

cat /tmp/haproxy.cfg.$$ > "$haproxy_cfg"
rm -f /tmp/haproxy.cfg.$$
flock -u 200

uuid=$3
/usr/bin/gear reload --cart haproxy-$OPENSHIFT_HAPROXY_VERSION
appctl_exitcode=$?

# Pass the appropriate exit code back.
[ $exitcode -ne 0 ]  &&  exit $exitcode
exit $appctl_exitcode
