Skip to content

Commit c36d1ba

Browse files
committed
Added get_info_extrainfo.sh recipe
Get App/Nodes via ACTstandard commands Then uses controller call to call a restui call for extra node info
1 parent a04325e commit c36d1ba

File tree

2 files changed

+375
-0
lines changed

2 files changed

+375
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
*.swp
2+
~scratch

recipes/get_node_extrainfo.sh

Lines changed: 374 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,374 @@
1+
#!/usr/bin/env bash
2+
3+
################################################################################
4+
# Gets extra node info from an applications node list
5+
#
6+
# NB; review SOURCE_API_NODEINFO setup, for version of controller
7+
#
8+
# Useful output lines for debug;
9+
# echo "lines: ${#app_list_array[@]} | entries: ${#app_array[@]}"
10+
# for key in "${!app_array[@]}"; do echo "key : $key"; echo "value : ${app_array[$key]}"; done
11+
################################################################################
12+
13+
usage () {
14+
echo "
15+
Usage:
16+
$0 [params]
17+
18+
Params;
19+
-E [name] The ACT environment name (Mandatory)
20+
-L [0|1] Whether to run for a single app (0) or
21+
whole controller (1)
22+
-A [999] Application ID you want to run for
23+
only required if LEVEL is set to 0
24+
-S [0|1] Input type, controller (0) or file (1)
25+
-D [0|1] Output type, stdout (0) or file (1)
26+
-O [path] Where source and dest files reside
27+
Required if SOURCE or DEST is 1
28+
29+
Defaults;
30+
L=0
31+
S=0
32+
D=0
33+
O=(recipes folder)
34+
35+
Examples;
36+
./get_node_extrainfo.sh -E prod -A 123
37+
./get_node_extrainfo.sh -E prod -L 1
38+
./get_node_extrainfo.sh -E prod -L 1 -D 1"
39+
40+
}
41+
42+
################################################################################
43+
# Setup Variables, etc
44+
################################################################################
45+
# RESTUI API call
46+
# TODO: Find exact version api calls changed
47+
# NB; this api call is valid on > mid-4.5 controller...
48+
SOURCE_API_NODEINFO="/controller/restui/v1/nodes/list/health/ids"
49+
# ...before which it was
50+
#SOURCE_API_NODEINFO="/controller/restui/nodes/list/health/ids"
51+
52+
# Set default input params
53+
LEVEL="0" #This means -A is mandatory unless -L is changed
54+
SOURCE="0"
55+
DEST="0"
56+
IO_FILE_PATH=$(dirname "${BASH_SOURCE[0]}")
57+
58+
# Declare the global variables
59+
declare APP_IDS
60+
declare NODE_IDS
61+
declare APP_SOURCE
62+
declare NODE_SOURCE
63+
declare NODEINFO_SOURCE
64+
# ...and global arrays
65+
declare -a app_list_array
66+
declare -A app_array
67+
declare -a node_list_array
68+
declare -A node_array
69+
declare -a nodeinfo_list_array
70+
declare -A nodeinfo_array
71+
declare -A output_array
72+
73+
# Set up some time variables, to use for time ranged calls
74+
# Default to last 1 hour with these values
75+
TIME_ZERO="$(date +%s)"
76+
TIME_END="${TIME_ZERO}000"
77+
TIME_START="$((${TIME_ZERO}-3600))000"
78+
79+
# Read input params
80+
while getopts ":E:L:A:S:D:O:" opt "$@"; do
81+
case "${opt}" in
82+
E)
83+
ENVIRONMENT="${OPTARG}"
84+
;;
85+
L)
86+
LEVEL="${OPTARG}"
87+
;;
88+
A)
89+
APP_ID="${OPTARG}"
90+
;;
91+
S)
92+
SOURCE="${OPTARG}"
93+
;;
94+
D)
95+
DEST="${OPTARG}"
96+
;;
97+
O)
98+
IO_FILE_PATH="${OPTARG}"
99+
;;
100+
:)
101+
usage
102+
exit 1
103+
;;
104+
*)
105+
echo "Invalid flag ${OPTARG}, exiting..."
106+
exit 1
107+
;;
108+
esac
109+
done
110+
111+
# Override params
112+
#ENVIRONMENT="prod"
113+
#LEVEL="1"
114+
#APP_ID="100"
115+
#SOURCE="1"
116+
#DEST="1"
117+
#IO_FILE_PATH="${IO_FILE_PATH}/../~scratch"
118+
119+
120+
################################################################################
121+
# Start of functions
122+
################################################################################
123+
124+
# Checks
125+
runChecks () {
126+
# If we didnt get an ENVIRONMENT, we cant continue
127+
if [[ -z ${ENVIRONMENT} ]]; then echo "No -E param passed."; usage; exit 1; fi
128+
# If we have an app LEVEL, but no APP_ID, we cant continue
129+
if [[ ${LEVEL} == "0" && -z ${APP_ID} ]]; then echo "No -A param passed for -L=0."; usage; exit 1; fi
130+
}
131+
132+
# Setup our data sources
133+
setupSources () {
134+
# Filenames for input, if SOURCE=1
135+
# APP0/APP1 is for LEVEL (app/controller) variances
136+
SOURCE_FILE_APP0="app.txt"
137+
SOURCE_FILE_APP1="app_list.txt"
138+
SOURCE_FILE_NODE="node_list.txt"
139+
SOURCE_FILE_NODEINFO="node_info.txt"
140+
# File for output if DEST=1
141+
OUTPUT_FILE="${TIME_ZERO}-E${ENVIRONMENT}-L${LEVEL}-S${SOURCE}.csv"
142+
143+
# Where are we getting the data from, either...
144+
# ...controller, via calls
145+
# ...exported file, from previous controller run
146+
# Managed by the SOURCE & LEVEL param
147+
if [[ ${SOURCE} == "0" && ${LEVEL} == "0" ]]; then
148+
APP_SOURCE="../act.sh -E ${ENVIRONMENT} application get -a ${APP_ID}"
149+
elif [[ ${SOURCE} == "1" && ${LEVEL} == "0" ]]; then
150+
APP_SOURCE="cat ${IO_FILE_PATH}/${SOURCE_FILE_APP0}"
151+
elif [[ ${SOURCE} == "0" && ${LEVEL} == "1" ]]; then
152+
APP_SOURCE="../act.sh -E ${ENVIRONMENT} application list"
153+
elif [[ ${SOURCE} == "1" && ${LEVEL} == "1" ]]; then
154+
APP_SOURCE="cat ${IO_FILE_PATH}/${SOURCE_FILE_APP1}"
155+
fi
156+
157+
if [[ ${SOURCE} == "1" ]]; then NODE_SOURCE="cat ${IO_FILE_PATH}/${SOURCE_FILE_NODE}"; fi
158+
}
159+
160+
# Setup some sources that require data not available at start
161+
setInFlightSources () {
162+
if [[ ${SOURCE} == "0" ]]; then NODE_SOURCE="../act.sh -E ${ENVIRONMENT} node list -a ${APP_ID}"; fi
163+
164+
if [[ ${SOURCE} == "0" ]]; then
165+
NODEINFO_SOURCE="../act.sh -E ${ENVIRONMENT} controller call -X POST -d {\"requestFilter\":[${NODE_IDS}],\"resultColumns\":[\"VM_RUNTIME_VERSION\"],\"timeRangeStart\":${TIME_START},\"timeRangeEnd\":${TIME_END}} ${SOURCE_API_NODEINFO}"
166+
elif [[ ${SOURCE} == "1" ]]; then
167+
NODEINFO_SOURCE="cat ${IO_FILE_PATH}/${SOURCE_FILE_NODEINFO}"
168+
fi
169+
}
170+
171+
# Clear down node related info
172+
resetVars () {
173+
NODE_IDS=""
174+
NODE_LIST=""
175+
unset node_list_array
176+
unset node_array
177+
178+
NODEINFO_LIST=""
179+
unset nodeinfo_list_array
180+
unset nodeinfo_array
181+
}
182+
183+
184+
################################################################################
185+
# XML and JSON parsing functions
186+
################################################################################
187+
188+
# Function to read XML and pull tags (ENTITY) and values (CONTENT)
189+
# Using this to remove dependancy on non-standard utils
190+
read_xml () {
191+
local IFS=\>
192+
read -d \< ENTITY CONTENT
193+
}
194+
195+
# Parse the APP XML, just for IDs
196+
parse_xml_app_ids () {
197+
while read_xml; do
198+
if [[ ${ENTITY} == "id" ]]; then echo "${CONTENT}"; fi
199+
done <<< "$(${APP_SOURCE})"
200+
}
201+
202+
# Parse the APP XML
203+
parse_xml_app_list () {
204+
while read_xml; do
205+
if [[ ${ENTITY} == "id" ]]; then echo "${CONTENT}"; fi
206+
if [[ ${ENTITY} == "name" ]]; then echo "${CONTENT}"; fi
207+
done <<< "$(${APP_SOURCE})"
208+
}
209+
210+
# Parse the NODE XML, just for IDs
211+
parse_xml_node_ids () {
212+
while read_xml; do
213+
if [[ ${ENTITY} == "id" ]]; then echo "${CONTENT},"; fi
214+
done <<< "$(${NODE_SOURCE})"
215+
}
216+
217+
# Parse the NODE XML
218+
parse_xml_node_list () {
219+
while read_xml; do
220+
if [[ ${ENTITY} == "id" ]]; then echo "${CONTENT}"; fi
221+
if [[ ${ENTITY} == "name" ]]; then echo "${CONTENT}"; fi
222+
if [[ ${ENTITY} == "tierName" ]]; then echo "${CONTENT}"; fi
223+
if [[ ${ENTITY} == "machineName" ]]; then echo "${CONTENT}"; fi
224+
if [[ ${ENTITY} == "machineOSType" ]]; then echo "${CONTENT}"; fi
225+
if [[ ${ENTITY} == "machineAgentPresent" && ${CONTENT} = "false" ]]; then echo "${CONTENT}"; fi
226+
if [[ ${ENTITY} == "appAgentPresent" && ${CONTENT} = "false" ]]; then echo "${CONTENT}"; fi
227+
if [[ ${ENTITY} == "machineAgentVersion" ]]; then echo "${CONTENT}"; fi
228+
if [[ ${ENTITY} == "appAgentVersion" ]]; then echo "${CONTENT}"; fi
229+
if [[ ${ENTITY} == "agentType" ]]; then echo "${CONTENT}"; fi
230+
done <<< "$(${NODE_SOURCE})"
231+
}
232+
233+
# Parse the NODEINFO JSON
234+
parse_json_nodeinfo_list () {
235+
while read line; do
236+
if [[ ${line} =~ \"nodeId\"[[:space:]]*:[[:space:]]*(.*),$ ]]; then echo "${BASH_REMATCH[1]}"; fi
237+
if [[ ${line} =~ \"jvmVersion\"[[:space:]]*:[[:space:]]*(.*),$ ]]; then echo "${BASH_REMATCH[1]}"; fi
238+
if [[ ${line} =~ \"appServerRestartDate\"[[:space:]]*:[[:space:]]*(.*),$ ]]; then echo "${BASH_REMATCH[1]}"; fi
239+
done <<< "$(${NODEINFO_SOURCE})"
240+
}
241+
242+
243+
################################################################################
244+
# Output functions
245+
################################################################################
246+
247+
outputHeader () {
248+
# Output variables used
249+
echo "ENVIRONMENT: ${ENVIRONMENT} | LEVEL: ${LEVEL} | APP_ID: ${APP_ID} | SOURCE: ${SOURCE} | DEST: ${DEST}"
250+
# Output header line
251+
if [[ ${DEST} == "0" ]]; then
252+
echo "appId,appName,nodeId,nodeName,tierName,machineName,machineOSType,machineAgentVersion,appAgentVersion,agentType,jvmVersion,appServerRestartDate"
253+
elif [[ ${DEST} == "1" ]]; then
254+
echo "appId,appName,nodeId,nodeName,tierName,machineName,machineOSType,machineAgentVersion,appAgentVersion,agentType,jvmVersion,appServerRestartDate" >> "${IO_FILE_PATH}/${OUTPUT_FILE}"
255+
fi
256+
257+
}
258+
259+
# Output the data to stdout or file
260+
outputData () {
261+
for node in "${!node_array[@]}"; do
262+
if [[ ${DEST} == "0" ]]; then
263+
echo "${APP_ID},${app_array[${APP_ID}]},${node},${node_array[${node}]},${nodeinfo_array[${node}]}"
264+
elif [[ ${DEST} == "1" ]]; then
265+
echo "${APP_ID},${app_array[${APP_ID}]},${node},${node_array[${node}]},${nodeinfo_array[${node}]}" >> ${IO_FILE_PATH}/${OUTPUT_FILE}
266+
fi
267+
done
268+
269+
# And reset node data for next run
270+
resetVars
271+
}
272+
273+
274+
################################################################################
275+
# GetData functions
276+
################################################################################
277+
278+
# Get application data
279+
getAppData () {
280+
# Produce list of App IDs - to use for calling getNodeIDs
281+
APP_IDS=$(parse_xml_app_ids)
282+
283+
# Produce list of App data fields (id and name) - to build output file
284+
APP_LIST=$(parse_xml_app_list)
285+
286+
# Import APP_LIST into app_list_array using IFS
287+
IFS=$'\r\n' GLOBIGNORE='*' command eval 'app_list_array=(${APP_LIST})'
288+
289+
# Loop through the list array
290+
app_count=0
291+
while [ ${app_count} -lt ${#app_list_array[@]} ] ; do
292+
# Add new array entry
293+
app_array+=([${app_list_array[${app_count}]}]=${app_list_array[${app_count} + 1]})
294+
# Jump the number of fields we have in each 'row'
295+
app_count=$(($app_count + 2))
296+
done
297+
}
298+
299+
# Get all node ids for an application id
300+
getNodeIDs () {
301+
setInFlightSources
302+
303+
# Produce csv list of Node IDs - for use for calling getNodeInfo
304+
NODE_IDS=$(parse_xml_node_ids | tr -d '\n' | sed -e "s/,$//")
305+
306+
# Produce list of Node data fields (8 currently) - to build output file
307+
NODE_LIST=$(parse_xml_node_list)
308+
309+
# Import NODE_LIST into node_list_array using IFS
310+
IFS=$'\r\n' GLOBIGNORE='*' command eval 'node_list_array=(${NODE_LIST})'
311+
312+
# Loop through the list array
313+
node_count=0
314+
while [ ${node_count} -lt ${#node_list_array[@]} ] ; do
315+
# Add new array entry
316+
node_array+=([${node_list_array[${node_count}]}]=${node_list_array[${node_count} + 1]},${node_list_array[${node_count} + 2]},${node_list_array[${node_count} + 3]},${node_list_array[${node_count} + 4]},${node_list_array[${node_count} + 5]},${node_list_array[${node_count} + 6]},${node_list_array[${node_count} + 7]})
317+
# Jump the number of fields we have in each 'row'
318+
node_count=$(($node_count + 8))
319+
done
320+
}
321+
322+
# Get all node extra info for a list of node ids
323+
getNodeInfo () {
324+
setInFlightSources
325+
326+
# Produce list of NodeInfo data fields (3 currently) - to build output file
327+
NODEINFO_LIST=$(parse_json_nodeinfo_list)
328+
329+
# Import NODEINFO_LIST into nodeinfo_list_array using IFS
330+
IFS=$'\r\n' GLOBIGNORE='*' command eval 'nodeinfo_list_array=(${NODEINFO_LIST})'
331+
332+
# Loop through the list array
333+
nodeinfo_count=0
334+
while [ ${nodeinfo_count} -lt ${#nodeinfo_list_array[@]} ] ; do
335+
# Add new array entry
336+
nodeinfo_array+=([${nodeinfo_list_array[${nodeinfo_count}]}]=${nodeinfo_list_array[${nodeinfo_count} + 1]},${nodeinfo_list_array[${nodeinfo_count} + 2]})
337+
# Jump the number of fields we have in each 'row'
338+
nodeinfo_count=$(($nodeinfo_count + 3))
339+
done
340+
}
341+
342+
343+
################################################################################
344+
################################################################################
345+
# MAIN CODE
346+
################################################################################
347+
################################################################################
348+
349+
# Lets get ready
350+
runChecks
351+
setupSources
352+
353+
# Output header line
354+
outputHeader
355+
356+
# Run based on whether we are APP or CONTROLLER level
357+
case $LEVEL in
358+
0) # Run at APP Level
359+
getAppData
360+
getNodeIDs
361+
getNodeInfo
362+
outputData
363+
;;
364+
1) # Run at CONTROLLER level
365+
getAppData
366+
# Iterate through the apps obtained
367+
for app in "${!app_array[@]}"; do
368+
APP_ID=${app}
369+
getNodeIDs
370+
getNodeInfo
371+
outputData
372+
done
373+
;;
374+
esac

0 commit comments

Comments
 (0)