Skip to content
Snippets Groups Projects
Select Git revision
  • bf07753b97ec67284f39c5bc34c9671305547419
  • master default protected
  • Legacy_Php7
3 results

act_build.php

Blame
  • confighandler.sh 9.55 KiB
    #!/bin/bash
    # ======================================================================
    #
    # VARIABLE STORAGE written in Bash
    #
    # ----------------------------------------------------------------------
    # 2020-01-25  v0.1  <axel.hahn@iml.unibe.ch>
    # 2020-01-26  v0.2  <axel.hahn@iml.unibe.ch> added --get, --add
    # 2020-01-27  v0.3  <axel.hahn@iml.unibe.ch> added storages handling
    # 2020-01-30  v0.5  <axel.hahn@iml.unibe.ch> added --setfile
    # ======================================================================
    
    _product="VARIABLE STORAGE"
    _version=0.5
    
    # _storagedir=/var/tmp/confighandler
    _storagedir=/dev/shm/confighandler
    
    _storageprefix='flat-variable-store-'
    _storagename='default'
    tmpfile=/tmp/cfgmover.tmp
    
    _markFile='::FILE-CONTENT::'
    
    # ----------------------------------------------------------------------
    # FUNCTIONS
    # ----------------------------------------------------------------------
    
    # write a debug message to STDERR
    function _wd(){
    	echo -e "\e[33m# $*\e[0m" >&2
    }
    
    # write error message in red to STDERR
    function _we(){
    	echo -e "\e[31m# $*\e[0m" >&2
    }
    
    # ----------------------------------------------------------------------
    # storage functions
    # ----------------------------------------------------------------------
    
    # set a variable storage
    # param  string  name of the storage; allowed chars are a-z and 0-9
    function storageset(){
    	_storagename=`echo $1 | sed "s#[^a-z0-9]##g"`
    
    	mkdir $_storagedir 2>/dev/null
            chmod 777 $_storagedir
    	_wd "set storage [${_storagename}]"
    	# cfgfile=`dirname $0`/${_storageprefix}${_storagename}.cfg
    	cfgfile=$_storagedir/${_storageprefix}${_storagename}.cfg
    }
    
    # list existing storages
    function storagelist(){
    	ls -1 ${_storagedir}/${_storageprefix}*.cfg | sed "s#${_storagedir}/${_storageprefix}##g" | sed "s#.cfg\$##g"
    }
    
    # delete current storage data
    function storagedelete(){
    	rm -f "$cfgfile"
    }
    
    
    # ----------------------------------------------------------------------
    # variable functions
    # ----------------------------------------------------------------------
    
    function _removeprefix(){
    	local _var=$1
    	_wd "removing ${_var} ..."
    	cat $cfgfile 2>/dev/null | grep -v "^${_var}" > $tmpfile
    	mv $tmpfile $cfgfile
    }
    
    function vargetvalue(){
    	local _var=$1
    	grep "^${_var}=" $cfgfile | cut -f 2 -d '='
    }
    
    
    function varaddvalue(){
    	local _var=$1
            shift 1
    	local _val=$*
    	local _value=`vargetvalue $_var`
    	echo $_value | grep '^\[' >/dev/null
    	if [ $? -ne 0 ]; then
    		# echo ERROR: you can add a value to an array only - not on [$_value]
    		_we "ERROR: you can add a value to an array only - not on [$_value]"
    	else
    		_wd "OK, array detected: $_value"
    		_value=`echo $_value | sed "s#]##"`,$_val"]"
    		varset $_var "$_value"
    	fi
    }
    
    function varremove(){
    	local _var=$1
    	# _removeprefix "${_var}="
    	cat $cfgfile 2>/dev/null | grep -v "^${_var}=" > $tmpfile
    	mv $tmpfile $cfgfile
    }
    
    
    function varset(){
    	local _var=$1
            shift 1
    	local _val=$*
    
    	varremove "${_var}"
    	_wd "setting ${_var} = ${_val} ..."
    	(echo ${_var}=${_val} ; cat $cfgfile 2>/dev/null ) >$tmpfile
    	sort $tmpfile > $cfgfile
    	rm -f $tmpfile
    }
    function varsetfile(){
    	local _var=$1
            shift 1
    	local _val=$*
    	varset $_var "${_markFile}${_val}"
    }
    function showstorage(){
    	if [ -f $cfgfile ]; then
    		_wd "content of storage [${_storagename}]"
    		cat $cfgfile
    	else
    		_wd "storage [${_storagename}] is emtpy"
    	fi
    }
    
    # ----------------------------------------------------------------------
    # export functions
    # ----------------------------------------------------------------------
    
    function _showFileAsJson(){
    	local _file=$1
    	which jq >/dev/null
    	if [ $? -eq 0 ]; then
    		jq -nR --arg data "`cat $_file`" '$data'
    	else
    		_we "ERROR: Json export of files ${_markFile} requires [jq]"
    	fi
    }
    
    function _jsonloop(){
    	local var=$1
    	typeset -i iFollow=$2
    
    	# _wd "_jsonloop $1 $2"
    
    	typeset -i level=`echo $var | grep -o '\.' | wc -l`+2
    
    	typeset -i local iChilds=0
    	typeset -i local iCount=0
    	typeset -i local iLeft=0
    
    	typeset -i lastlevel=$level-1
    	local sLastvar=`echo ${var} | cut -f $lastlevel -d "."`
    	local space=`printf %${lastlevel}s |tr " " "\t"`
    
    	# --- handle existing subkeys
    	grep "^${var}\." $cfgfile >/dev/null && (
    		iCount=0
    		iChilds=`grep "^${var}" $cfgfile | wc -l`
    		echo "${space}\"$sLastvar\": {"
    		for myhash in `grep "^${var}[\.=]" $cfgfile | cut -f 1 -d "=" | cut -f $level -d "." | sort -u`
    		do
    			iCount=$iCount+1
    			iLeft=$iChilds-$iCount
    			_jsonloop "$var.$myhash" $iLeft
    		done
    		echo -n "${space}}"
    	)
    
    	# --- show values
    
    	grep "^${var}=" $cfgfile >/dev/null && (
    		value=`grep "^${var}=" $cfgfile | cut -f 2- -d "="`
    		echo -n "${space}\"$sLastvar\": "
    		echo ${value}| grep "${_markFile}" >/dev/null
    		if [ $? -eq 0 ]; then
    			_showFileAsJson `echo ${value} | sed "s#^${_markFile}##"`
    		else	
    			echo -n "${value}"
    		fi
    	)
    	if [ $iFollow -gt 0 ]; then
    		echo ","
    	else
    		echo
    	fi
    }
    
    function exportJson(){
    	# _wd "exportJson - init: find first level of vars"
    	typeset -i local iCount=0
    	typeset -i local iLeft=0
    	typeset -i local iChilds=`grep "^[a-zA-Z]" $cfgfile | cut -f 1 -d "=" | cut -f 1 -d '.' | sort -u | wc -l`
    
    	echo "{"
    
    	# first level names
    	for lev1var in `cat $cfgfile | grep "^.*\=" | cut -f 1 -d "=" | grep -v "\." | sort -u`
    	do
    		#_wd "exportJson - start run with var [$lev1var]"
    		iCount=$iCount+1
    		iLeft=$iChilds-$iCount
    		_jsonloop "$lev1var" $iLeft
    	done
    
    	# _wd "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    	# first level hashes
    	for lev1var in `cat $cfgfile | cut -f 1 -d "=" | grep  "\." | cut -f 1 -d "." | sort -u`
    	do
    		#_wd "exportJson - start run with hash [$lev1var]"
    		iCount=$iCount+1
    		iLeft=$iChilds-$iCount
    		_jsonloop "$lev1var" $iLeft
    	done
    	echo "}"
    
    }
    
    
    # W.I.P
    # JSON export with processing line by line
    #
    function exportJson2(){
    	typeset -i local iSublevel=0
    	typeset -i local iLast=0
    
    	typeset -i local lastlevel
    	local sLastvar
    
    	grep '^[a-zA-Z]' $cfgfile | while read line
    	do
    		fullvar=`echo $line | cut -f 1 -d "="`
    		iSublevel=`echo $fullvar | grep -o '\.' | wc -l`+2
    		lastlevel=$iSublevel-1
    		sLastvar=`echo ${fullvar} | cut -f $lastlevel -d "."`
    
    		local space=`printf %${lastlevel}s |tr " " "\t"`
    
    		echo "${space} $line .. level $iSublevel .. $sLastvar"
    	done
    }
    
    # ----------------------------------------------------------------------
    # help
    # ----------------------------------------------------------------------
    
    # show help text
    function showHelp(){
    self=`basename $0`
    cat <<EOH
    
    $_product v$_version
    
    This script handles variables and nested values (hashes and arrays).
    You can create several configuration sets (storages) to isolate them.
    
    Help
    
    	--help or -h or -?
    		show this help and abort.
    
    	--version or -v
    		show the version.
    
    Storage parameters
    
    	--storage NAME
    		Set a storage to use. Allowed chars are a-z and 0-9.
    		Default is a storage named "default".
    		You can set an evironment variable CFGSTORAGE to override
    		the default (= to skip --storage NAME).
    
    	--list
    		List existing storages.
    
    	--flush
    		delete current storage data
    
    	--show
    		show the current config entries as plain text
    
    	--json
    		show config entries as json.
    		Warning: it is implemented in Bash - can be slow on more data
    
    Create | read | update | delete variables
    
    	--set VARNAME VALUE
    		Set a variable and its value.
    		If it does not exist then it will be created.
    		If it exist then it will be overwritten with the new value.
    
    		For the values you can force the type:
    			* Use single and double quotes to set a string, i.e.
    				\$ $self --set my_string '"hello world"'
    
    			* Quote the doublequotes to expand variables, i.e.
    				\$ $self --set my_string2 \"\${my_string2}\"
    
    			* use no quoting vor integers and values
    				\$ $self --set number_cpu 8
    
    			* use barackets in quotes to set an array
    				\$ $self --set my_array '[8, 12, 16]'
    
    		Use a "." (dot) in varname to create a hierarchy, i.e.
    			\$ $self --set host.os '"linux"'
    
    	--setfile VARNAME FILENAME
    		Set an input file to show its content
    
    	--add VARNAME VALUE
    		Add VALUE as array element to VARNAME.
    		It fails if VARNAME does not exist or isn't an array.
    			 $ confighandler.sh --add my_array 20
    
    	--get VARNAME
    		Show value of the given variable.
    
    	--delete VARNAME
    		delete a variable.
    
    You can concatenate all parameters. So you can use --show before
    and after an --set action to see the differences.
    \$ $self --show --set hello '"world"' --show
    
    You get additional infos on STDERR. To get plain data send STDERR
    to /dev/null
    \$ $self --show 2>/dev/null
    
    EOH
    }
    
    # ----------------------------------------------------------------------
    #
    # MAIN
    #
    # ----------------------------------------------------------------------
    
    
    if [ ! -z $CFGSTORAGE ]; then
    	storageset "$CFGSTORAGE"
    else
    	storageset "default"
    fi
    
    if [ $# -eq 0 ]; then
    	showHelp
    	exit 0
    fi
    
    while [ $# -gt 0 ];
    do
    	case "$1" in
    		'--help' | '-h' | '-?')
    			_wd ">>> $1"
    			showHelp
    			exit 0
    			;;
    		'--version' | '-v')
    			_wd ">>> $1"
    			echo $_product v$_version
    			;;
    
    		# ----- storage
    
    		'--storage')
    			_wd ">>> $1 $2"
    			storageset "$2"
    			shift 1
    			;;
    		'--list')
    			_wd ">>> $1"
    			storagelist
    			;;
    		'--flush')
    			_wd ">>> $1"
    			storagedelete
    			;;
    
    		# ----- variables
    
    		'--set')
    			_wd ">>> $1 $2 $3"
    			varset $2 "$3"
    			shift 2
    			;;
    		'--setfile')
    			_wd ">>> $1 $2 $3"
    			varsetfile $2 "$3"
    			shift 2
    			;;
    		'--add')
    			_wd ">>> $1 $2 $3"
    			varaddvalue $2 "$3"
    			shift 2
    			;;
    		'--get')
    			_wd ">>> $1 $2"
    			vargetvalue $2
    			shift 1
    			;;
    		'--delete')
    			_wd ">>> $1 $2"
    			varremove $2
    			shift 1
    			;;
    		'--show')
    			_wd ">>> $1"
    			showstorage
    			;;
    
    		# ----- export
    
    		'--json')
    			_wd ">>> $1"
    			exportJson
    			# time exportJson
    			# time exportJson2
    			;;
    		*)
    			_we "ERROR: unknown param detected: [$1]"
    			showHelp
    			echo "Aborting ..."
    			exit 1
    	esac
    	_wd ""
    	shift 1
    
    done
    _wd "DONE"