From 828f2596472b62ac9b2afd4b1db499ae375ed2db Mon Sep 17 00:00:00 2001 From: Eric Loyd Date: Thu, 18 Jul 2024 12:44:48 -0400 Subject: [PATCH] Slowly converting to using arrays instead of variables --- api.sh | 338 +++++++++++++++++++++++++++------------------------------ 1 file changed, 159 insertions(+), 179 deletions(-) diff --git a/api.sh b/api.sh index 723b40f..ad88e7c 100755 --- a/api.sh +++ b/api.sh @@ -9,31 +9,19 @@ XI_URL="" curl="curl -k -s" # curl -XGET "https://192.168.1.19/nagiosxi/api/v1/objects/service?apikey=" -verbose="0" -testMode="" -doCreate="" - -myAck="" -myCG="" -myCommand="" -myConfigName="" -myFields="" -myFile="" -myHG="" -myHost="" -myOutput="" -mySave="" -myService="" -mySG="" -myState="" -myStateType="" -myQuick="" +# myThings are now too big for individual variables. We'll read them into an associative array instead +declare -A myThing + +# We need a separate thing for myOptions +declare -A myOptions +myOptions[API]="objects" +myOptions[APIep]="servicestatus" +myOptions[TestMode]="" +myOptions[Verbose]="0" +myOptions[Create]="" +myOptions[Options]="" tmpJSON="" -moreJQ="" -cmdOptions="" -myAPI="objects" -myAPIep="servicestatus" # Different API commands return different JSON datasets. So let's make a lookup table that figures out where to start the data extracts declare -A APIinfo @@ -72,31 +60,31 @@ APIinfo["objects/bpi"]="" get_myAPI() { case "$1" in - o*) myAPI="objects";; - c*) myAPI="config";; - s*) myAPI="system";; - *) myAPI="";; + o*) ${myOptions[API]}="objects";; + c*) ${myOptions[API]}="config";; + s*) ${myOptions[API]}="system";; + *) ${myOptions[API]}="";; esac } get_myAPIep() { case "$1" in - co|comment) myAPIep="comment";; - cg|contactgroup) myAPIep="contactgroup";; - c|contact) myAPIep="contact";; - dt|downtime) myAPIep="downtime";; - hgm|hostgroupmembers) myAPI="objects"; myAPIep="hostgroupmembers";; - hg|hostgroup) myAPIep="hostgroup";; - h|host) myAPIep="host";; - hs|hoststatus) myAPIep="hoststatus";; - le|logentries) myAPIep="logentries";; - sgm|servicegroupmembers) myAPI="objects"; myAPIep="servicegroupmembers";; - sg|servicegroup) myAPIep="servicegroup";; - s|service) myAPIep="service";; - ss|servicestatus) myAPIep="servicestatus";; - sh|statehistory) myAPIep="statehistory";; - tp|timeperiod) myAPIep="timeperiod";; - *) myAPIep="";; + co|comment) myOptions[APIep]="comment";; + cg|contactgroup) myOptions[APIep]="contactgroup";; + c|contact) myOptions[APIep]="contact";; + dt|downtime) myOptions[APIep]="downtime";; + hgm|hostgroupmembers) myOptions[API]="objects"; myOptions[APIep]="hostgroupmembers";; + hg|hostgroup) myOptions[APIep]="hostgroup";; + h|host) myOptions[APIep]="host";; + hs|hoststatus) myOptions[APIep]="hoststatus";; + le|logentries) myOptions[APIep]="logentries";; + sgm|servicegroupmembers) myOptions[API]="objects"; myOptions[APIep]="servicegroupmembers";; + sg|servicegroup) myOptions[APIep]="servicegroup";; + s|service) myOptions[APIep]="service";; + ss|servicestatus) myOptions[APIep]="servicestatus";; + sh|statehistory) myOptions[APIep]="statehistory";; + tp|timeperiod) myOptions[APIep]="timeperiod";; + *) myOptions[APIep]="";; esac } @@ -106,6 +94,9 @@ print_helpopt() { Options for different APIs: + all: + i Make all string comparisons case-insentitive + servicestatus: c Show fields selected by -f as quoted CSV @@ -119,37 +110,41 @@ HELPOPT_EOF print_help() { cat << HELP_EOF - --help This text + --ack problem_has_been_acknowledged=<0,1> + --ace active_checks_enabled=<0,1> + --api < o*bjects | c*onfig | s*ystem > + -c|--command check_command="\$2" + -cca current_check_attempt="\$2" + -cnn current_notification_number= + -cg|--contactgroup contact_groups="\$2" + -cn|--configname config_name="\$2" + ... comment | downtime | contact | host | service | hostgroup | ... + --create doCreate="true" + -f|--fields JQ-valid list of fields to show="\$2" + --file load JSON from="\$2" --helpopt Show help for command options + --help This text + -hg|--hostgroup hostgroup="\$2" + -h|--host host_name="\$2" + ... hostgroupmembers | servicegroupmembers > + -j|--jq additional valid JQ="\$2" + --key APIKEY="\$2" --keyfile APIkeyFile="\$2" + -o|--opt cmdOptions="\$2" (endpoint specific options. See --helpopt) + --output output text="\$2" -q|--quick Sets -f to .host_name,.service_description,.current_state,.state_type,.problem_has_been_acknowledged (assumes servicestatus) -Q Same as --quick but add -o c - -j|--jq moreJQ="\$2" - -v|--verbose verbose=\$((\$verbose + 1)) - --create doCreate="true" - --key APIKEY="\$2" - --url XI_URL="\$2" - --save mySave="\$2" - --file myFile="\$2" - -f|--fields myFields="\$2" - -h|--host myHost="\$2" - -s|--service myService="\$2" - -c|--command myCommand="\$2" - -cn|--configname myConfigName="\$2" - -cg|--contactgroup myCG="\$2" - -hg|--hostgroup myHG="\$2" - -sg|--servicegroup mySG="\$2" + --save save JSON to="\$2" + ... servicegroup | contactgroup | timeperiod | ... + -sg|--servicegroup servicegroup="\$2" + -s|--service service_description="\$2" --state 0, 1, or 2 (or other, I suppose) --stype 0, 1 (SOFT or HARD) - --output myOutput="\$2" - --ack 0, 1 - -o|--opt cmdOptions="\$2" (endpoint specific options. See --helpopt) - --api < o*bjects | c*onfig | s*ystem > - -t|--object < hoststatus | servicestatus | logentries | statehistory | ... - ... comment | downtime | contact | host | service | hostgroup | ... - ... servicegroup | contactgroup | timeperiod | ... - ... hostgroupmembers | servicegroupmembers > --test Don't call the API, just show what would happen + -t|--object < hoststatus | servicestatus | logentries | statehistory | ... + --url XI_URL="\$2" + -v|--verbose verbose=\$((\${myOptions[Verbose]} + 1)) + [...] [...]=<...> NOTE: This will take anything listed as a Nagios configuration directive and search for it HELP_EOF exit @@ -157,34 +152,37 @@ HELP_EOF while [ -n "$1" ]; do case "$1" in - --help) print_help;; + --ack) myThing[problem_has_been_acknowledged]="$2"; shift 2;; + --ace) myThing[active_checks_enabled]="$2"; shift 2;; + --api) get_myAPI "$2"; shift 2;; + -c|--command) myThing[check_command]="$2"; shift 2;; + -cca) myThing[current_check_attempt]="$2"; shift 2;; + -cnn) myThing[current_notification_number]="$2"; shift 2;; + -cg|--contactgroup) myThing[contact_groups]="$2"; shift 2;; + -cn|--configname) myThing[config_name]="$2"; shift 2;; + --create) myOptions[Create]="true"; shift 1;; + -f|--fields) myOptions[Fields]="$2"; shift 2;; + --file) myOptions[File]="$2"; shift 2;; --helpopt) print_helpopt;; - --keyfile) APIkeyFile="$2"; shift 2;; - --test) testMode="true"; shift 1;; - -q|--quick) myQuick="true"; shift 1;; - -Q) myQuick="true"; cmdOptions+="c,"; shift 1;; - -j|--jq) moreJQ="$2"; shift 2;; - -v|--verbose) verbose=$(($verbose + 1)); shift 1;; - --create) doCreate="true"; shift 1;; + --help) print_help;; + -hg|--hostgroup) myThing[HG]="$2"; shift 2;; + -h|--host) myThing[Host]="$2"; shift 2;; + -j|--jq) myOptions[MoreJQ]="$2"; shift 2;; --key) APIKEY="$2"; shift 2;; - --url) XI_URL="$2"; shift 2;; - --save) mySave="$2"; shift 2;; - --file) myFile="$2"; shift 2;; - -f|--fields) myFields="$2"; shift 2;; - -h|--host) myHost="$2"; shift 2;; - -s|--service) myService="$2"; shift 2;; - -c|--command) myCommand="$2"; shift 2;; - -cn|--configname) myConfigName="$2"; shift 2;; - -cg|--contactgroup) myCG="$2"; shift 2;; - -hg|--hostgroup) myHG="$2"; shift 2;; - -sg|--servicegroup) mySG="$2"; shift 2;; - --state) myState="$2"; shift 2;; - --stype) myStateType="$2"; shift 2;; - --output) myOutput="$2"; shift 2;; - --ack) myAck="$2"; shift 2;; - -o|--opt) cmdOptions+="$2,"; shift 2;; - --api) get_myAPI "$2"; shift 2;; + --keyfile) APIkeyFile="$2"; shift 2;; + -o|--opt) myOptions[Options]+="$2,"; shift 2;; + --output) myThing[Output]="$2"; shift 2;; + -Q) myOptions[Quick]="true"; myOptions[Options]+="c,"; shift 1;; + -q|--quick) myOptions[Quick]="true"; shift 1;; + --save) myOptions[Save]="$2"; shift 2;; + -sg|--servicegroup) myThing[SG]="$2"; shift 2;; + -s|--service) myThing[Service]="$2"; shift 2;; + --state) myThing[State]="$2"; shift 2;; + --stype) myThing[StateType]="$2"; shift 2;; + --test) myOptions[TestMode]="true"; shift 1;; -t|--object) get_myAPIep "$2"; shift 2;; + --url) XI_URL="$2"; shift 2;; + -v|--verbose) verbose=$((${myOptions[Verbose]} + 1)); shift 1;; *) shift 1;; esac done @@ -203,7 +201,7 @@ if [ -n "$APIkeyFile" -a -r "$APIkeyFile" ]; then fi do_debug() { - [ "$verbose" -ge "$1" ] && echo "$2" >&2 + [ "${myOptions[Verbose]}" -ge "$1" ] && echo "$2" >&2 } do_api() { @@ -222,7 +220,7 @@ do_api_post() { url="${XI_URL}/api/v1/${api_start}/${api_command}?apikey=${APIKEY}&pretty=0" do_debug 2 "start=$1 command=$2" do_debug 1 "Executing: $url" - $curl -XPOST -k "$url" -d "hostgroup_name=$myHG&alias=$myHG&applyconfig=0" + $curl -XPOST -k "$url" -d "hostgroup_name=${myThing[HG]}&alias=${myThing[HG]}&applyconfig=0" } # At this time, all we can create ia a hostgroup @@ -233,12 +231,12 @@ create_hostgroup() { do_create() { do_debug 1 "about to do a create_command" - [ -n "$myHG" ] && create_hostgroup + [ -n "${myThing[HG]}" ] && create_hostgroup exit } # If we said "--create" then we want to make something -if [ -n "$doCreate" ]; then +if [ -n "${myOptions[Create]}" ]; then do_create exit fi @@ -246,25 +244,26 @@ fi # Grab a copy of the JSON data so we don't have to keep making calls over and over # If we used an existing file, then just use that # If we're in test mode, then skip this part -if [ -z "$testMode" ]; then - if [ -z "$myFile" ]; then +if [ -z "${myOptions[TestMode]}" ]; then + if [ -z "${myOptions[File]}" ]; then tmpJSON=`mktemp` do_debug 1 "tmp file is $tmpJSON" - do_debug 2 "myAPI is $myAPI and myAPIep is $myAPIep" - do_api "$myAPI" "$myAPIep" > $tmpJSON + do_debug 2 "myAPI is ${myOptions[API]} and myAPIep is ${myOptions[APIep]}" + do_api "${myOptions[API]}" "${myOptions[APIep]}" > $tmpJSON else - do_debug 1 "myFile=$myFile" - tmpJSON="$myFile" + do_debug 1 "myFile=${myOptions[File]}" + tmpJSON="${myOptions[File]}" + do_debug 1 "tmpJSON=$tmpJSON" fi - # if mySave is not empty, then we're just saving it into the file called $mySave - if [ -n "$mySave" ]; then - mv $tmpJSON $mySave - do_debug 1 "JSON data saved to $mySave" + # if mySave is not empty, then we're just saving it into the file called ${myOptions[Save]} + if [ -n "${myOptions[Save]}" ]; then + mv $tmpJSON ${myOptions[Save]} + do_debug 1 "JSON data saved to ${myOptions[Save]}" exit fi else - echo "### TEST MODE - Skipping API call (testMode=${testMode}) ###" + echo "### TEST MODE - Skipping API call (testMode=${myOptions[TestMode]}) ###" fi # Helper functions for creating our jqString @@ -272,112 +271,93 @@ fi jq_check_case() { thing="$*" if [ -n "$thing" ]; then + do_debug 2 "### in JQ_CHECK_CASE cmdOptions=${myOptions[Options]}" val="| test(\"$thing\"" - [[ "$cmdOptions" =~ "i," ]] && val+="; \"i\"" + [[ "$myOptions[Options]" =~ "i," ]] && val+="; \"i\"" echo "$val)" else echo "" fi } -# Do we need to add host limits to the query? -jq_add_host() { - [ -n "$myHost" ] && jqString+="| select(.host_name $(jq_check_case $myHost))" -} -jq_add_service() { - [ -n "$myService" ] && jqString+="| select(.service_description $(jq_check_case $myService))" -} -jq_add_hostgroup() { - [ -n "$myHG" ] && jqString+="| select(.hostgroup_name==\"$myHG\")" -} -jq_add_servicegroup() { - [ -n "$mySG" ] && jqString+="| select(.servicegroup_name==\"$mySG\")" -} -jq_add_command() { - [ -n "$myCommand" ] && jqString+="| select(.check_command $(jq_check_case $myCommand))" -} -jq_add_output() { - [ -n "$myOutput" ] && jqString+="| select(.output $(jq_check_case $myOutput))" -} -jq_add_configname() { - [ -n "$myConfigName" ] && jqString+="| select(.check_command $(jq_check_case $myConfigName))" -} -jq_add_contactgroup() { - [ -n "$myCG" ] && jqString+="| select(.contactgroup_name $(jq_check_case $myCG))" -} -jq_add_state() { - [ -n "$myState" ] && jqString+="| select(.current_state | test(\"$myState\"))" -} -jq_add_statetype() { - [ -n "$myStateType" ] && jqString+="| select(.state_type | test(\"$myStateType\"))" -} -jq_add_ack() { - [ -n "$myAck" ] && jqString+="| select(.problem_has_been_acknowledged | test(\"$myAck\"))" +# Create the jQuery search string +jq_add_myThing() { + thing="$1" + if [ -z "$1" ]; then + return + else + [ -n "${myThing[$thing]}" ] && jqString+="| select(.$thing | test(\"${myThing[$thing]}\"))" + fi } + + jq_get_fields() { - if [[ "$cmdOptions" =~ "c," ]]; then - jqString+="| [$myFields] | @csv" + if [[ "$myOptions[Options]" =~ "c," ]]; then + jqString+="| [${myOptions[Fields]}] | @csv" else - jqString+="| $myFields" + jqString+="| ${myOptions[Fields]}" fi } # Otherwise, let's parse the JSON data here # Parse our string -do_debug 1 "APIinfo=${APIinfo[$myAPI/$myAPIep]}" -jqString=${APIinfo[$myAPI/$myAPIep]} -case "$myAPIep" in +do_debug 1 "APIinfo=${APIinfo[${myOptiosn[API]}/${myOptions[APIep]}]}" +jqString=${APIinfo[${myOptions[API]}/${myOptions[APIep]}]} +case "${myOptions[APIep]}" in servicestatus) - jq_add_host - jq_add_service - jq_add_hostgroup - jq_add_servicegroup - jq_add_command - jq_add_output - jq_add_state - jq_add_statetype - jq_add_ack + jq_add_myThing host_name + jq_add_myThing service_description + jq_add_myThing hostgroup_name + jq_add_myThing servicegroup_name + jq_add_myThing output + jq_add_myThing current_state + jq_add_myThing current_state_type + jq_add_myThing check_command + jq_add_myThing current_check_attempt + jq_add_myThing current_notification_number + jq_add_myThing active_checks_enabled + jq_add_myThing problem_has_been_acknowledged ;; hostgroup) - jq_add_host - jq_add_hostgroup + jq_add_myThing host_name + jq_add_myThing hostgroup_name ;; host) - jq_add_host + jq_add_myThing host_name ;; service) - jq_add_host - jq_add_service - jq_add_configname - jq_add_command + jq_add_myThing host_name + jq_add_myThing service_description + jq_add_myThing config_name + jq_add_myThing check_command ;; hostgroupmembers) - jq_add_host - jq_add_hostgroup - [[ $cmdOptions =~ "h," ]] && jqString+="| .members[] | .[] | .host_name" - [[ $cmdOptions =~ "o," ]] && jqString+="| .members[] | .[] | .host_object_id" + jq_add_myThing host_name + jq_add_myThing hostgroup_name + [[ $myOptions[Options] =~ "h," ]] && jqString+="| .members[] | .[] | .host_name" + [[ $myOptions[Options] =~ "o," ]] && jqString+="| .members[] | .[] | .host_object_id" ;; servicegroup) - jq_add_host - jq_add_servicegroup + jq_add_myThing host_name + jq_add_myThing servicegroup_name ;; contactgroup) - jq_add_contactgroup + jq_add_myThing contact_groups ;; esac -if [ -n "$myQuick" -a -n "$myFields" ]; then - myFields=".host_name,.service_description,.current_state,.state_type,.problem_has_been_acknowledged,${myFields}" -elif [ -n "$myQuick" ]; then - myFields=".host_name,.service_description,.current_state,.state_type,.problem_has_been_acknowledged" +if [ -n "${myOptions[Quick]}" -a -n "${myOptions[Fields]}" ]; then + myOptions[Fields]=".host_name,.service_description,.current_state,.state_type,.problem_has_been_acknowledged,${myOptions[Fields]}" +elif [ -n "${myOptions[Quick]}" ]; then + myOptions[Fields]=".host_name,.service_description,.current_state,.state_type,.problem_has_been_acknowledged" fi -[ -n "$myFields" ] && jq_get_fields -jqString+="$moreJQ" +[ -n "${myOptions[Fields]}" ] && jq_get_fields +jqString+="${myOptions[MoreJQ]}" do_debug 1 "jqString=$jqString" -if [ -n "$testMode" ]; then - echo "### TEST MODE - Here is what would have been done (testMode=${testMode}) ###" +if [ -n "${myOptions[TestMode]}" ]; then + echo "### TEST MODE - Here is what would have been done (testMode=${myOptions[TestMode]}) ###" echo "cat | jq -r \"$jqString\"" else cat $tmpJSON | jq -r "$jqString" - [ -z "$myFile" ] && rm $tmpJSON + [ -z "${myOptions[File]}" ] && rm $tmpJSON fi