Skip to content

Instantly share code, notes, and snippets.

@pozgo
Last active August 29, 2015 14:12
Show Gist options
  • Save pozgo/b05bd578ef51b55469f6 to your computer and use it in GitHub Desktop.
Save pozgo/b05bd578ef51b55469f6 to your computer and use it in GitHub Desktop.
haproxy-marathon-bridge
#!/bin/bash
set -o errexit -o nounset -o pipefail
function -h {
cat <<USAGE
USAGE: $name <marathon host:port>+
$name install_haproxy_system <marathon host:port>+
Generates a new configuration file for HAProxy from the specified Marathon
servers, replaces the file in /etc/haproxy and restarts the service.
In the second form, installs the script itself, HAProxy and a cronjob that
once a minute pings one of the Marathon servers specified and refreshes
HAProxy if anything has changed. The list of Marathons to ping is stored,
one per line, in:
$cronjob_conf_file
The script is installed as:
$script_path
The cronjob is installed as:
$cronjob
and run as root.
USAGE
}; function --help { -h ;}
export LC_ALL=en_US.UTF-8
name=haproxy-marathon-bridge
cronjob_conf_file=/etc/"$name"/marathons
cronjob=/etc/cron.d/"$name"
script_path=/usr/local/bin/"$name"
conf_file=haproxy.cfg
function main {
config "$@"
}
function refresh_system_haproxy {
config "$@" > /tmp/"$conf_file"
if ! diff -q /tmp/"$conf_file" /etc/haproxy/"$conf_file" >&2
then
msg "Found changes. Sending reload request to HAProxy..."
cat /tmp/"$conf_file" > /etc/haproxy/"$conf_file"
if [[ -f /etc/init/haproxy.conf ]]
then reload haproxy ## Upstart
elif [[ -f /usr/lib/systemd/system/haproxy.service ]]
then systemctl reload haproxy ## systemd
else /etc/init.d/haproxy reload
fi
fi
}
function install_haproxy_system {
os=$(lsb_release -si)
if [[ $os == "CentOS" ]] || [[ $os == "RHEL" ]]
then
yum install -y haproxy
chkconfig haproxy on
elif [[ $os == "Ubuntu" ]] || [[ $os == "Debian" ]]
then
env DEBIAN_FRONTEND=noninteractive aptitude install -y haproxy
sed -i 's/^ENABLED=0/ENABLED=1/' /etc/default/haproxy
else
echo "$os is not a supported OS for this feature."
exit 1
fi
install_cronjob "$@"
}
function install_cronjob {
mkdir -p "$(dirname "$cronjob_conf_file")"
[[ -f $cronjob_conf_file ]] || touch "$cronjob_conf_file"
if [[ $# -gt 0 ]]
then printf '%s\n' "$@" | dd of="$cronjob_conf_file"
fi
cat "$0" | dd of="$script_path"
chmod ug+rx "$script_path"
cronjob | dd of="$cronjob"
header | dd of=/etc/haproxy/"$conf_file"
}
function cronjob {
cat <<EOF
* * * * * root $script_path logged refresh_system_haproxy \$(cat $cronjob_conf_file)
EOF
}
function config {
header
apps "$@"
}
function header {
cat <<\EOF
global
log 127.0.0.1 local0
log 127.0.0.1 local1 notice
maxconn 4096
defaults
log global
retries 3
maxconn 2000
timeout connect 5000
timeout client 50000
timeout server 50000
listen stats
bind 0.0.0.0:80
balance
mode http
stats enable
stats hide-version
stats refresh 30s
stats realm Strictly\ Private
stats auth admin:admin
stats uri /
EOF
}
function apps {
(until curl -sSfLk -m 10 -H 'Accept: text/plain' "${1%/}"/v2/tasks; do [ $# -lt 2 ] && return 1 || shift; done) | while read -r txt
do
set -- $txt
local app_name="$1"
local app_port="$2"
shift 2
if [ "${app_port//[0-9]*}" = "" ]
then
cat <<EOF
frontend $app_name-$app_port
bind 0.0.0.0:$app_port
default_backend $app_name-$app_port
backend $app_name-$app_port
mode tcp
balance roundrobin
EOF
while [[ $# -ne 0 ]]
do
out " server ${app_name}-$# $1 check"
shift
done
fi
done
}
function logged {
exec 1> >(logger -p user.info -t "$name[$$]")
exec 2> >(logger -p user.notice -t "$name[$$]")
"$@"
}
function msg { out "$*" >&2 ;}
function err { local x=$? ; msg "$*" ; return $(( $x == 0 ? 1 : $x )) ;}
function out { printf '%s\n' "$*" ;}
# If less than 1 argument is provided, print usage and exit. At least one
# argument is required as described in the `USAGE` message.
[ $# -lt 1 ] && { -h; exit 1; }
if [[ ${1:-} ]] && declare -F | cut -d' ' -f3 | fgrep -qx -- "${1:-}"
then "$@"
else main "$@"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment