#!/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 # 2022-10-21 v1.1 <axel.hahn@unibe.ch> remove grep: warning: stray \ before white space # 2023-06-09 v1.2 <axel.hahn@unibe.ch> take first haproxy stats port on multiple binds # 2023-07-28 v1.3 <axel.hahn@unibe.ch> check existance of file $HAPROXYcfgfile # 2025-02-20 v1.4 <axel.hahn@unibe.ch> cfgrewriter returns exitcode 0 - haproxy check do not abort when sourcing on non haproxy systems # ====================================================================== # 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-01.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='' test -f $HAPROXYcfgfile && 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 return 0 } # ------------------------------------------------------------ # 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 ":" | head -1 ) auth=$( getCfgVar "stats" "${mysection}" | grep "^auth" | cut -f 2- -d " " | head -1 ) # 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