-
Notifications
You must be signed in to change notification settings - Fork 1
/
QueryWebServers.sh
178 lines (161 loc) · 5.23 KB
/
QueryWebServers.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#!/bin/bash
#
# Defaults for parameters
#
region="ap-southeast-2"
pool="WebPool"
pool_tag="pup-WebServer"
#
# Variables
#
left_in="{\"node\":\""
right_in=":80\",\"priority\":1,\"state\":\"active\",\"weight\":1}"
work_dir="/root"
manifest="example.pp"
rand_str=$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-f0-9' | head -c 10)
export PATH=$PATH:/usr/local/bin
OPTIND=1
debug=0
function show_help {
printf "\nThis script will find out IPs of running EC2 instances tagged with the specified Tag\n"
printf "and update the specified ::pools in the Puppet manifest file $work_dir/$manifest accordingly.\n"
printf "\nThe script will indicate through an exit code whether changes were made - 0 for no, 10 for yes.\n"
printf "\nRequired parameters:\n\t-r <region> : Region where we're running\n"
printf "\t-p <pool name> : Name of the pool in the Manifest file (must exist)\n"
printf "\t-t <pool tag> : unique tag to find pool EC2 instances by\n\n"
printf "Instance running this script needs to have an IAM role with Policy allowing ec2:DescribeInstances\n\n"
}
while getopts "h?dr:p:t:" opt; do
case "$opt" in
h|\?)
show_help
exit 0
;;
d) debug=1
;;
r) region=$OPTARG
;;
p) pool=$OPTARG
;;
t) pool_tag=$OPTARG
;;
esac
done
shift $((OPTIND-1))
[ "$1" = "--" ] && shift
if [[ "$region" == "" || "$pool" == "" || "$pool_tag" == "" || "$rand_str" == "" ]]; then
echo "Error: One of the required parameters is empty"
echo "Region: \"$region\""
echo "Pool: \"$pool\""
echo "Pool Tag: \"$pool_tag\""
echo "Random Str: \"$rand_str\""
exit 1
fi
if [[ "$debug" == "0" ]]; then
if [[ ! -d "$work_dir" ]]; then
echo "Work directory \"$work_dir\" doesn't exist or inaccessible, exiting."
exit 1
fi
cd "$work_dir"
which jq >/dev/null 2>&1
if [[ "$?" != "0" ]]; then
echo "Looks like we don't have jq installed; quitting'"
exit 1
fi
which aws >/dev/null 2>&1
if [[ "$?" != "0" ]]; then
echo "Looks like we don't have AWS CLI installed; quitting'"
exit 1
fi
fi
if [[ ! -f "$manifest" ]]; then
echo "Can't find \"$manifest\"; exiting"
exit 1
fi
# Saving SHA checksum for later checking
oldsha=$(shasum "$manifest" | awk '{print $1}')
declare -a IPs
if [[ "$debug" == "0" ]]; then
# Look up running instances with the "Name" Tag matching $pool_tag, use jq to extract their IPs
# Sort at the end, in case AWS returns the same results in different order which shouldn't trigger update
errCode=1
backoff=1
multiplier=2
resFName="/tmp/aws-out.$rand_str"
while [[ "$errCode" != "0" ]]; do
if (( $backoff > 64 )); then
echo "Exceeded backoff budget of 64 seconds; giving up for now."
rm -f $resFName
exit 1
fi
rm -f $resFName
aws ec2 describe-instances --region $region \
--filters "Name=tag:Name,Values=$pool_tag" \
"Name=instance-state-name,Values=running" > $resFName 2>&1
errCode=$?
if [[ "$errCode" != "0" ]]; then
sleep $backoff
let "backoff =* multiplier"
fi
# Now let's validate that our result file is a valid JSON, and keep repeating if not.
if [[ "$errCode" == 0 ]]; then
jq '.' $resFName > /dev/null 2>&1
errCode=$?
fi
done
IPs=( $(cat $resFName \
| jq -r ".Reservations[] | .Instances[] | .NetworkInterfaces[] | .PrivateIpAddress" \
| sort -rn) )
rm -f $resFName
else
# We're in debug mode; just set the array to two dummy IPs
IPs=( $(printf "%s\n%s\n" "1.1.1.1" "2.2.2.2" ) )
fi
# After the above, the $IPs is the list of our backend pool servers' IPs
# Build up the list of pool servers in Puppet manifest format
nodes=""
pos1=$(( ${#IPs[*]} - 1 ))
for j in $(seq 0 $pos1); do
a="$left_in""${IPs[$j]}""$right_in"
if (( $j < $pos1 )); then
nodes="$nodes""$a"","
else
nodes="$nodes""$a"
fi
done
# Edit the current manifest:
# awk to change \n to |, then sed to search for our Pool name, replace
# everything in "[]" against brocadevtm::pools with what we've cooked up just above,
# and finally change | back to \n
#
tmpf="$manifest.$rand_str"
cat "$manifest" | awk 1 ORS="|" \
| sed -e "s/\(.*brocadevtm::pools { '$pool':.*basic__nodes_table => '\)\(\[[^]]*\]\)\(.*\)/\1\[$nodes\]\3/g" \
| tr '|' '\n' > "$tmpf"
# Some awk versions add an extra \n to the end of file.
# Let's deal with that:
#
man_len=$(wc -l "$manifest" | awk '{print $1}')
tmp_len=$(wc -l "$tmpf" | awk '{print $1}')
if (( tmp_len == man_len+1 )); then
# Yep, we're dealing with one of those; let's fix it.
sed -i -e '$d' "$tmpf"
fi
if [[ -s "$tmpf" ]]; then
cat "$tmpf" > "$manifest"
rm -f "$tmpf"
else
echo "Edit resulted in an empty file for some reason."
echo "nodes var was \"$nodes\". Leaving $manifest unchanged."
rm -f "$tmpf"
exit 1
fi
newsha=$(shasum "$manifest" | awk '{print $1}')
if [[ "$newsha" != "$oldsha" ]]; then
echo "File changed; need to update"
# Yeah, I know - error code "10" is arbitrary. Let me know if you have a better idea.
exit 10
else
echo "No changes needed"
exit 0
fi