#!/bin/bash configfile="<%= scope.lookupvar('puppi::params::basedir') %>/puppi.conf" # This is the actual command used to run the different scripts # Use cat for debugging noop purposes # runcommand="cat" runcommand="" # Define defaults verbosity="max" show="yes" # Define action tag export tag=$(date +%Y%m%d-%H%M%S) counter=0 # Load general configurations if [ ! -f $configfile ] ; then echo "Config file: $configfile not found" exit 1 else . $configfile . $scriptsdir/functions fi # Main functions check_host () { for command in $(ls -1 $checksdir) ; do title="$HOSTNAME check: $command" code=$(cat "$checksdir/$command") ask_interactive output=$($runcommand "$checksdir/$command" 2>&1) handle_result done } check () { for command in $(ls -1 $projectsdir/$project/check) ; do title="$HOSTNAME check: $command" code=$(cat "$projectsdir/$project/check/$command") ask_interactive output=$($runcommand "$projectsdir/$project/check/$command" 2>&1) handle_result done check_host # show_report } log () { tailcommand="tail" which colortail >/dev/null 2>&1 && tailcommand="colortail" if [ "x$project" != "xdefault" ] ; then if [ $logsdir/$project ] ; then alllog="$alllog $(cat $logsdir/$project)" else echo "WARNING: $logsdir/$project does not exist!" exit 1 fi else if [ "$interactive" = "yes" ] ; then echo "Choose one or more log topics to show. Select the last number (done) to end selection" PS3="Type one number to add a log topic to the show list." all_choices="" select choice in $( ls $logsdir ) done do echo "You selected $choice [$REPLY]" [[ $choice == "done" ]] && break all_choices="$all_choices $choice" echo "Your choices: $all_choices" done for log in $all_choices ; do alllog="$alllog $(cat $logsdir/$log)" done else for log in $(ls $logsdir) ; do alllog="$alllog $(cat $logsdir/$log)" done fi fi # So, show something if [ ! -z "$counts" ] ; then if [ ! -z "$greppattern" ] ; then $tailcommand -n $counts $alllog | grep $greppattern else $tailcommand -n $counts $alllog fi else if [ ! -z "$greppattern" ] ; then $tailcommand -f $alllog | grep $greppattern else $tailcommand -f $alllog fi fi } info () { if [ "x$project" != "xdefault" ] ; then if [ $infodir/$project ] ; then $infodir/$project else echo "WARNING: $infodir/$project does not exist!" exit 1 fi else if [ "$interactive" = "yes" ] ; then echo "Choose one or more topics to show. Select the last number (done) to end selection" PS3="Type one number to add an info topic to the show list." all_choices="" select choice in $( ls $infodir ) done do echo "You selected $choice [$REPLY]" [[ $choice == "done" ]] && break all_choices="$all_choices $choice" echo "Your choices: $all_choices" done for info in $all_choices ; do if [ ! -z "$greppattern" ] ; then $infodir/$info | grep $greppattern else $infodir/$info fi done else for info in $(ls $infodir) ; do if [ ! -z "$greppattern" ] ; then $infodir/$info | grep $greppattern else $infodir/$info fi done fi fi } todo () { for todo in $(ls $tododir) ; do $tododir/$todo done } rollback () { if [ ! -z $rollbackversion ] ; then save_runtime_config "rollbackversion=$rollbackversion" || initerr=1 else echo "Choose deploy to rollback:" ls -1 $archivedir/$project read rollbackversion save_runtime_config "rollbackversion=$rollbackversion" || initerr=1 fi for command in $(ls -1 $projectsdir/$project/rollback) ; do title="$HOSTNAME Rollback: $command" code=$(cat "$projectsdir/$project/rollback/$command") ask_interactive output=$($runcommand "$projectsdir/$project/rollback/$command" 2>&1) handle_result done send_reports show_report [ "$result" = "OK" ] && exit 0 } deploy () { for command in $(ls -1 $projectsdir/$project/deploy) ; do title="$HOSTNAME Deploy: $command" code=$(cat "$projectsdir/$project/deploy/$command") ask_interactive output=$($runcommand "$projectsdir/$project/deploy/$command" 2>&1) handle_result [ "$EXITCRIT" = "1" ] && [ "$force" != "yes" ] && break if [ "$DONTDEPLOY" = "1" ] ; then echo "No need to deploy: source file has not changed" echo "Type 'rm $archivedir/$project/md5sum' and run puppi again to force deployment" exit 0 fi done send_reports show_report [ "$result" = "OK" ] && exit 0 } initialize () { for command in $(ls -1 $projectsdir/$project/initialize) ; do title="$HOSTNAME Init: $command" code=$(cat "$projectsdir/$project/initialize/$command") ask_interactive output=$($runcommand "$projectsdir/$project/initialize/$command" 2>&1) handle_result [ "$EXITCRIT" = "1" ] && [ "$force" != "yes" ] && break done send_reports show_report [ "$result" = "OK" ] && exit 0 } configure () { for command in $(ls -1 $projectsdir/$project/configure) ; do title="$HOSTNAME Init: $command" code=$(cat "$projectsdir/$project/configure/$command") ask_interactive output=$($runcommand "$projectsdir/$project/configure/$command" 2>&1) handle_result [ "$EXITCRIT" = "1" ] && [ "$force" != "yes" ] && break done send_reports show_report [ "$result" = "OK" ] && exit 0 } save_summary () { tagend=$(date +%Y%m%d-%H%M%S) result="OK" if [ "$EXITWARN" = "1" ] ; then result="WARNING" fi if [ "$EXITCRIT" = "1" ] ; then result="ERROR" fi echo "Report for $action on $project" > $logdir/$project/$tag/summary echo "Job start: $tag" >> $logdir/$project/$tag/summary echo "Job end: $tagend" >> $logdir/$project/$tag/summary echo "Job result: $result" >> $logdir/$project/$tag/summary echo "Actions executed:" >> $logdir/$project/$tag/summary cd $logdir/$project/$tag/ for message in $(ls -1 $logdir/$project/$tag/ | grep -v summary ) ; do msg_title=$(head -1 $message) msg_code=$(head -2 $message | tail -1) msg_result=$(head -3 $message | tail -1) echo "[$msg_result] $msg_title : $msg_code" >> $logdir/$project/$tag/summary done # Copy runtime config in archive cp $workdir/$project/config $logdir/$project/$tag/ # Write runtime config on Summary echo >> $logdir/$project/$tag/summary echo "RUNTIME CONFIGURATION" >> $logdir/$project/$tag/summary cat $workdir/$project/config | grep -vE "^#|^$" >> $logdir/$project/$tag/summary } send_reports () { if [[ "x$report" == "xyes" ]] ; then save_summary for command in $(ls -1 $projectsdir/$project/report) ; do title="Reporting: $command" code=$(cat "$projectsdir/$project/report/$command") echo -n $title output=$($runcommand "$projectsdir/$project/report/$command" 2>&1) # handle_result # This breaks the overall exit code when deploy fails done fi } show_report () { echo echo "REPORT FOR PUPPI - STATUS $result" echo "Summary of operations is: $logdir/$project/$tag/summary " echo "Details are in: $logdir/$project/$tag/" echo "Temporary workdir has been: $workdir/$project/ (Will be rewritten at the next puppi run)" echo "Runtime config file is: $workdir/$project/config" echo "Files have been archived in: $archivedir/$project/$tag" test "$testmode" = "yes" && echo "This was a TEST RUN! Nothing has been done for real." } create_runtime_conf () { if [[ ( ! -e $projectsdir/$project ) && ( ! -e $infodir/$project ) && ( ! -e $logsdir/$project ) ]] ; then showhelp exit 1 fi initerr=0 # When project is unset we set it to default [ ! -z "$project" ] || export project="default" # Clean up and Create runtime configuration file # command="00-$project-RuntimeConfig-Initialization" # title="Puppi setup: $command" # code="rm -rf $workdir/$project && touch $workdir/$project/config [...]" # echo -n $title echo $workdir | grep tmp >/dev/null 2>&1 || ( echo "Workdir must contain string tmp" ; exit 1 ) rm -rf $workdir/$project || initerr=1 mkdir -p $workdir/$project || initerr=1 touch $workdir/$project/config || initerr=1 test -r "$projectsdir/$project/config" && cp $projectsdir/$project/config $workdir/$project/ chmod 644 $workdir/$project/config || initerr=1 save_runtime_config "project=$project" || initerr=1 save_runtime_config "tag=$tag" || initerr=1 save_runtime_config "action=$action" || initerr=1 storedir=$workdir/$project/store || initerr=1 mkdir -p $storedir || initerr=1 save_runtime_config "storedir=$storedir" || initerr=1 predeploydir=$workdir/$project/deploy || initerr=1 mkdir -p $predeploydir || initerr=1 save_runtime_config "predeploydir=$predeploydir" || initerr=1 save_runtime_config "force=$force" || initerr=1 save_runtime_config "testmode=$testmode" || initerr=1 save_runtime_config "interactive=$interactive" || initerr=1 save_runtime_config "debug=$debug" || initerr=1 save_runtime_config "report=$report" || initerr=1 save_runtime_config "show=$show" || initerr=1 save_runtime_config "counts=$counts" || initerr=1 save_runtime_config "greppattern=$greppattern" || initerr=1 for oopt in $(echo $options) ; do save_runtime_config "$(echo $oopt)" || initerr=1 done echo $initerr | grep "0" 2>&1 > /dev/null # handle_result } showhelp () { echo "Usage: puppi [project|topic] [options]" echo " " echo "Available commands:" echo "check [project] [-s ] - Run puppi checks host or project wide" echo "log [topic] [-i] [-g ] - Show system and application specific logs" echo "info [topic] [-i] [-g ] - Show informations about the system" echo "todo - Show todo's checklist of the system" echo "init [-i] [-f] [-t] - First time project initialization and setup" echo "configure [-i] [-f] [-t] - Project configuration deployment." echo "deploy [-i] [-f] [-t] [-o ...] - Deploy the specified project" echo "rollback [state] [-i] [-f] [-t] - Rollback the specified project. " echo " " echo "Available options:" echo "-f - Force puppi commands execution flow also on CRITICAL errors" echo "-i - Interactively ask confirmation for every step" echo "-t - Test mode. Just show the commands that should be executed" echo "-d - Debug mode. Show debug of what is done." echo "-r - Enable reporting: yes/no/only on failures. Default depends on action" echo "-s - Show output: yes/no/only for failures. Default: yes" echo "-g - Grep command output with the selected pattern" echo "-o \"parameter=value parameter2=value2\" - Set manual options to override defaults" echo " " echo "Available deploy projects:" ls -1 $projectsdir echo echo "Available info topics:" ls $infodir echo echo "Available log topics:" ls $logsdir } # Check Input if [ "$#" = "0" ] ; then showhelp exit fi while [ $# -gt 0 ]; do case "$1" in deploy|init|configure) report="yes" export action=$1 if [ -n "$2" ] ; then echo "$2" | egrep -q "^-.$" if [ "$?" != "0" ] ; then export project=$(shell_filter_strict $2) shift 2 else shift fi else showhelp exit shift fi ;; rollback) report="yes" export action=$1 if [ -n "$3" ] ; then echo "$3" | egrep -q "^-.$" if [ "$?" != "0" ] ; then export project=$(shell_filter_strict $2) export rollbackversion=$(shell_filter_strict $3) shift 3 else shift 2 fi elif [ -n "$2" ] ; then echo "$2" | egrep -q "^-.$" if [ "$?" != "0" ] ; then export project=$(shell_filter_strict $2) shift 2 else shift fi else showhelp exit shift fi ;; check) report="no" export action="checkhost" if [ -n "$2" ] ; then echo "$2" | egrep -q "^-.$" if [ "$?" != "0" ] ; then export project=$(shell_filter_strict $2) export action="check" shift 2 else shift fi else shift fi ;; log) report="no" export action="log" if [ -n "$2" ] ; then echo "$2" | egrep -q "^-.$" if [ "$?" != "0" ] ; then export project=$(shell_filter_strict $2) shift 2 else shift fi else shift fi ;; info) report="no" export action="info" if [ -n "$2" ] ; then echo "$2" | egrep -q "^-.$" if [ "$?" != "0" ] ; then export project=$(shell_filter_strict $2) shift 2 else shift fi else shift fi ;; todo) report="no" export action="todo" shift ;; -i) interactive="yes" shift ;; -f) force="yes" shift ;; -t) testmode="yes" runcommand="cat" shift ;; -o) options="$2" shift 2;; -d) debug="$(shell_filter_strict $2)" shift 2;; -r) report="$(shell_filter_strict $2)" shift 2;; -s) show="$(shell_filter_strict $2)" shift 2;; -c) counts="$(shell_filter_strict $2)" shift 2;; -g) greppattern="$(shell_filter_strict $2)" # greppattern="$(shell_filter $2)" # This allows partial regexp usage # greppattern="$2" # This allows full regexp usage but is highly insecure if you sudo puppi shift 2;; *) showhelp exit ;; esac done # Action! case $action in check) check ;; checkhost) check_host ;; log) create_runtime_conf ; log ;; info) create_runtime_conf ; info ;; todo) create_runtime_conf ; todo ;; rollback) create_runtime_conf ; rollback ;; deploy) create_runtime_conf ; deploy ;; init) create_runtime_conf ; initialize ;; configure) create_runtime_conf ; configure ;; esac