diff --git a/check_haproxy_health b/check_haproxy_health index 0a208cd47d3452cec24d8ade662422b859384d09..d10a02bbb109ffa0149bab6282f813b5a978fc48 100755 --- a/check_haproxy_health +++ b/check_haproxy_health @@ -9,9 +9,11 @@ # 2020-04-27 v1.0 <axel.hahn@iml.unibe.ch> # 2020-05-04 v1.1 <axel.hahn@iml.unibe.ch> show message if monitor-uri was not set # 2020-12-03 v1.2 <axel.hahn@iml.unibe.ch> loop over multiple frontend status urls +# 2021-12-14 v1.3 <axel.hahn@iml.unibe.ch> use updated haproxy paser in sourced file # ====================================================================== . `dirname $0`/inc_pluginfunctions +. `dirname $0`/inc_haproxy_cfg.sh cfgfile=/etc/haproxy/haproxy.cfg tmpfile=/tmp/check_haproxy_healthcheck_$$ @@ -34,54 +36,27 @@ if [ $? -ne 0 ]; then fi -# ---------------------------------------------------------------------- -# build url # ---------------------------------------------------------------------- -proto=http -auth= -host=localhost -port=80 -uri= -uri=` cat $cfgfile | grep "\ monitor-uri\ " | awk '{ print $2 }'` +url=$( getHealthUri ) -if [ -z "$uri" ]; then - ph.abort "UNKNOWN: no monitor-uri setting was found in the config $cfgfile." +# --- get status page +wget --no-check-certificate -O $tmpfile $url 2>/dev/null +if [ $? -ne 0 ]; then + rm -f $tmpfile + ph.abort "UNKNOWN: url $url did not respond. `wget --no-check-certificate -O - -S $url`" fi -cat $cfgfile | grep "bind\ .*\ ssl\ " >/dev/null && proto=https - -# fix #4176 - take first found frontend ip only -# port=`cat $cfgfile | grep "\ bind\ " | awk '{ print $2 }' | head -1 | cut -f 2 -d ':'` - - -# ---------------------------------------------------------------------- -# loop over found bind ports -# ---------------------------------------------------------------------- - -for myport in `cat $cfgfile | grep "\ bind\ " | awk '{ print $2 }' | cut -f 2 -d ':'` -do - url="$proto://${host}:${myport}${uri}" - - # --- get status page - wget --no-check-certificate -O $tmpfile $url 2>/dev/null - if [ $? -ne 0 ]; then - rm -f $tmpfile - ph.abort "UNKNOWN: url $url did not respond. `wget --no-check-certificate -O - -S $url`" - fi - - grep "200 OK" $tmpfile >/dev/null - if [ $? -ne 0 ]; then - ph.setStatus "error" - ph.status "url $url did not contain 200 OK. `wget --no-check-certificate -O - -S $url`" - else - ph.status "HA Proxy $url is up and running." - fi - - rm -f $tmpfile +grep "200 OK" $tmpfile >/dev/null +if [ $? -ne 0 ]; then + ph.setStatus "error" + ph.status "url $url did not contain 200 OK. `wget --no-check-certificate -O - -S $url`" +else + ph.status "HA Proxy $url is up and running." +fi -done +rm -f $tmpfile ph.exit diff --git a/inc_haproxy_cfg.sh b/inc_haproxy_cfg.sh new file mode 100644 index 0000000000000000000000000000000000000000..6e1a735a7c9746791ae0913ce1bc0a5b997f7e8b --- /dev/null +++ b/inc_haproxy_cfg.sh @@ -0,0 +1,171 @@ +#!/bin/bash +# ====================================================================== +# +# haproxy functions +# parse haproxy.cfg - as good I can do with bash +# +# ---------------------------------------------------------------------- +# 2021-12-14 v1.0 <axel.hahn@iml.unibe.ch> init +# ====================================================================== + +# full path to haproxy.cfg +HAPROXYcfgfile=/etc/haproxy/haproxy.cfg + +# rewritten config as tmp file to parse data +HAPROXYdumpfile=/tmp/haproxy.config + +# enable caching; value 0 = off - it recreates tmp file on each run +HAPROXYdoCache=0 + + +# TESTING ONLY +# HAPROXYcfgfile=./haproxy-ldap01.cfg +# /TESTING + + +# ---------------------------------------------------------------------- +# +# functions +# +# ---------------------------------------------------------------------- + + +# ---------------------------------------------------------------------- +# CONFIG REWRITER +# ---------------------------------------------------------------------- + + +# rewrite the ha proxy config file to parse it by section +# it creates output with +# +# section + ":" + variable + "=" + value + +# i.e.: +# # new section: global +# global:chroot=/var/lib/haproxy +# global:daemon= +# global:user=haproxy +# global:group=haproxy +# global:maxconn=4000 +# global:pidfile=/var/run/haproxy.pid +# ... +function cfgrewriter(){ + local _section= + IFS='' + while read line + do + echo $line | grep "^[a-z]" >/dev/null + if [ $? -eq 0 ]; then + _section=$line + echo "# new section: $_section" + fi + echo $line | grep "^\ \ [a-z]*" >/dev/null + if [ $? -eq 0 ]; then + echo -n "$_section:" + echo $line | sed -e "s#^\ *\([a-z\-]*\)\ *#\1=#g" + fi + done < $HAPROXYcfgfile +} + +# ------------------------------------------------------------ +# dump Cfg data +# ------------------------------------------------------------ + +# dump rewritten config +function _dumpCfg(){ + cat $HAPROXYdumpfile +} + +# dump rewritten config and filter by a given section +# param string name of section +function _dumpSection(){ + local _section=$1 + _dumpCfg | grep "^${_section}:" +} + +# ------------------------------------------------------------ +# parsing functions +# ------------------------------------------------------------ + +# get a value from a given section +# param string name of variable +# param string name of section +function _getCfgVarFromSection(){ + local _var=$1 + local _section=$2 + _dumpSection "${_section}" | grep ":${_var}=" | cut -f 2 -d "=" +} + +# get sections where a given var exists +# param string name of variable +function getCfgSectionsOfVar(){ + local _var="$1" + _dumpCfg | grep ":${_var}=" | cut -f 1 -d ":" | sort -u +} + +# get a value from config - with autoscan of sections defaults and globals +# param string name of variable +# param string name of section +function getCfgVar(){ + local _var=$1 + local _section=$2 + test -z "$_section" && _section='.*' + + _getCfgVarFromSection "${_var}" "${_section}" \ + || _getCfgVarFromSection "${_var}" "defaults" \ + || _getCfgVarFromSection "${_var}" "global" + +} + +# ---------------------------------------------------------------------- +# High level functions +# ---------------------------------------------------------------------- + +# detect the section where variables named "stats" are defined +# to generate urls for health check and status +# WARNING: this function is UNSAFE ... it is heavy to parse +# haproxy.cfg with a bash script :-/ +function detectStatsSection(){ + getCfgSectionsOfVar "stats" | tail -1 +} + +# get a string with base url for stats and health check +function getStatsBaseUrl(){ + # default url parts + local proto=http + local auth= + local host=localhost + local port=80 + local mysection=$( detectStatsSection ) + + # read config + port=$( getCfgVar "bind" "${mysection}" | cut -f 2 -d ":") + auth=$( getCfgVar "stats" "${mysection}" | grep "^auth" | cut -f 2- -d " " ) + + # build url + url="$proto://" + test -z "$auth" || url="${url}${auth}@" + url="${url}${host}:${port}" + + echo $url +} + +# get a string with a health url +function getHealthUri(){ + local uri=$( getCfgVar "monitor-uri" ) + test -z "$uri" || echo $( getStatsBaseUrl )${uri} +} + +# get a string with a status page +function getStatusUri(){ + local mysection=$( detectStatsSection ) + local uri=$( getCfgVar "stats" "${mysection}" | grep "^uri " | cut -f 2- -d " " ) + test -z "$uri" || echo $( getStatsBaseUrl )${uri} +} + +# ---------------------------------------------------------------------- + +# INIT +if [ $HAPROXYdoCache = 0 -o $HAPROXYcfgfile -nt $HAPROXYdumpfile ]; then + cfgrewriter >$HAPROXYdumpfile +fi \ No newline at end of file