forked from bird-house/birdhouse-deploy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
post-docker-compose-up
executable file
·357 lines (329 loc) · 14.4 KB
/
post-docker-compose-up
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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
#!/bin/sh
# Operations:
# 1. Registers WPS providers into Weaver to provide their OGC-API interface.
# 2. Validate that Weaver workers are ready to receive tasks.
#
# 1. WPS provider registration
# -----------------------------
#
# The script first authenticates in Magpie to obtain authorization for requests, as everything could be protected.
# Afterwards, there is a quick validation that Weaver is up and ready to receive WPS providers registration requests.
# Then, each provider defined in 'WEAVER_WPS_PROVIDERS' is registered iteratively.
# All requests have a timeout to avoid hanging indefinitely.
# Also, maximum total timeout configured by 'WEAVER_WPS_PROVIDERS_MAX_TIME' will break out if nothing responds.
#
# This script is executed after 'docker-compose up' of the full bird-house stack.
# The reason why WPS providers must be registered after starting everything is because Weaver attempts to query
# them (with GetCapabilities requests) to obtain their metadata.
# Because some WPS containers could take longer to start, it is otherwise not guaranteed that they would be ready
# to receive those requests before Weaver starts querying them.
#
# Parameters:
#
# WEAVER_WPS_PROVIDERS:
# list of provider names (comma or space delimited), all are assumed to be available at
# "https://${PAVICS_FQDN_PUBLIC}${TWITCHER_PROTECTED_PATH}/<provider-name>"
# WEAVER_WPS_PROVIDERS_MAX_TIME:
# limit script execution up to a maximum of this number of seconds
# WEAVER_WPS_PROVIDERS_RETRY_COUNT:
# number of permitted retries to register a given WPS provider
# WEAVER_WPS_PROVIDERS_RETRY_AFTER:
# number of seconds between each retry request as needed
#
# Following configurations are expected to be inherited from bird-house/weaver-component env.local/default.env:
# - MAGPIE_ADMIN_USERNAME
# - MAGPIE_ADMIN_PASSWORD
# - PAVICS_FQDN_PUBLIC
# - TWITCHER_PROTECTED_PATH
# - WEAVER_MANAGER_NAME
#
# 2. Worker tasks validation
# -----------------------------
#
# When Weaver and its Celery workers are started, tasks often fail to properly register themselves at startup.
# In order to ensure everything is properly configured and ready to receive jobs, Celery checks are employed to
# validate that tasks are known by each component (webapp and workers), and ready to submit/receive them.
# If any of the webapp/worker is not ready, restart them to retry detecting tasks. At that point, it is expected
# that one of the two should have finished registering tasks, and it is just a matter of synchronizing them.
#
# See also the 'celery-healthcheck' script that does the same periodic verification while the images are running,
# but it will not automatically restart them.
#
# Parameters:
#
# PAVICS_LOG_DIR (optional, default=/tmp/pavics-compose):
# Location to log results from celery healthcheck outputs.
#
# in case parent script called with debug (sh -x <script>), hide output for this script and reset on exit
# this is important, otherwise curl logs will leak tokens!
old_state="$(set +o)"
# if this script needs live debugging, comment out following line and call the script with (sh -x <script>)
set +x
reset_state() {
set +vx; eval "${old_state}"
}
# logging
if [ ! -z "$TERM" ]; then
YELLOW=${YELLOW:-$(tput setaf 3)}
RED=${RED:-$(tput setaf 1)}
NORMAL=${NORMAL:-$(tput sgr0)}
else
YELLOW=""
RED=""
NORMAL=""
fi
PREFIX="[Weaver] "
ERROR="${PREFIX}${RED}ERROR${NORMAL}: "
WARN="${PREFIX}${YELLOW}WARNING${NORMAL}: "
echo "${PREFIX}Running: $0"
MAGPIE_URL="https://${PAVICS_FQDN_PUBLIC}/magpie"
WEAVER_URL="https://${PAVICS_FQDN_PUBLIC}${TWITCHER_PROTECTED_PATH}/${WEAVER_MANAGER_NAME}"
WEAVER_WPS_PROVIDERS_MAX_TIME=${WEAVER_WPS_PROVIDERS_MAX_TIME:-120}
WEAVER_WPS_PROVIDERS_RETRY_AFTER=${WEAVER_WPS_PROVIDERS_RETRY_AFTER:-5}
WEAVER_WPS_PROVIDERS_RETRY_COUNT=${WEAVER_WPS_PROVIDERS_RETRY_COUNT:-5}
# double echo and no quotes used on purpose to remove empty/extra newlines/spaces
WEAVER_WPS_PROVIDERS=$(echo $(echo "${WEAVER_WPS_PROVIDERS}" | tr ',' ' '))
REQUEST_TIMEOUT=2
if [ -z "${WEAVER_WPS_PROVIDERS}" ]; then
echo "${WARN}Nothing specified in WEAVER_WPS_PROVIDERS to register WPS remote providers."
reset_state
exit 0
fi
if [ "${WEAVER_WPS_PROVIDERS_RETRY_COUNT}" -lt 0 ]; then
WEAVER_WPS_PROVIDERS_RETRY_AFTER=0
WEAVER_WPS_PROVIDERS_RETRY_COUNT=0
fi
if [ "${WEAVER_WPS_PROVIDERS_RETRY_AFTER}" -lt 0 ]; then
WEAVER_WPS_PROVIDERS_RETRY_AFTER=0
fi
echo "${PREFIX}Requested Weaver WPS providers: [${WEAVER_WPS_PROVIDERS}]"
echo "${PREFIX}Will retry requests at most for ${WEAVER_WPS_PROVIDERS_MAX_TIME}s"
echo "${PREFIX}Will retry registration of each provider up to ${WEAVER_WPS_PROVIDERS_RETRY_COUNT} times"
echo "${PREFIX}Will retry registration of each provider with ${WEAVER_WPS_PROVIDERS_RETRY_AFTER}s intervals"
if [ -z "$WEAVER_CURL_IMAGE" ]; then
WEAVER_CURL_IMAGE="curlimages/curl:7.87.0"
fi
# POSIX portable RNG if RANDOM does not exist on the current shell
RANDOM_NUMBER=${RANDOM:-$(tr -dc 0-9 < /dev/urandom 2>/dev/null | head -c 5)}
# To know when a docker run was started in case it hangs.
DOCKER_RUN_TAG="weaver_post_curl_$(date -Isecond | sed 's/:/_/g' | sed 's/+/p/g')_${RANDOM_NUMBER}"
curl_cmd() {
docker run --rm --name "${DOCKER_RUN_TAG}" "${WEAVER_CURL_IMAGE}" "$@"
}
# pull image if missing to avoid mangling output messages on first call
docker pull "${WEAVER_CURL_IMAGE}"
start_time="$(date -u +%s)"
# ------ PHASE 1 ------
# Magpie Authentication
# registration of WPS providers require authenticated access, obtain login from Magpie
printf "%s" "${PREFIX}Wait for response from Magpie to login [${MAGPIE_URL}]."
while true; do
# login (output null + cookie-jar '-' redirects output cookie to variable)
cookie_jar=$( \
curl_cmd --insecure --silent --location \
-m ${REQUEST_TIMEOUT} \
-o /dev/null \
-X POST \
-H "Content-Type: application/json" \
-d "{\"user_name\": \"${MAGPIE_ADMIN_USERNAME}\", \"password\": \"${MAGPIE_ADMIN_PASSWORD}\"}" \
--cookie-jar - \
"${MAGPIE_URL}/signin" \
)
# trim excess stuff in cookie_jar pseudo-file (comments, empty lines)
# also trim duplicate cookies ".<host>" and "<host>" returned by Magpie behind proxy
cookie_jar=$(echo "${cookie_jar}" | grep -v '# ' | grep -v -e '^$' | grep -v '_\.')
# validate exactly 1 cookie retrieved (empty if bad-auth or invalid endpoint)
if [ ! -z "${cookie_jar}" ] && [ "$(echo "${cookie_jar}" | wc -l)" -eq 1 ]; then
fields="$(echo "${cookie_jar}" | wc -w)"
cookie_name="$(echo "${cookie_jar}" | cut -f $(( fields - 1 )) )"
cookie_value="$(echo "${cookie_jar}" | cut -f "${fields}")"
cookie="${cookie_name}=${cookie_value}"
printf " %s\n" "OK!"
break;
fi
# interrupt if max time reached
next_time=$(date -u +%s)
delta_time=$(( next_time - start_time ))
if [ ${delta_time} -ge "${WEAVER_WPS_PROVIDERS_MAX_TIME}" ]; then
msg="Failed to register all providers specified in WEAVER_WPS_PROVIDERS. Magpie is not responding."
printf "\n%s\n" "${ERROR}Timeout (${WEAVER_WPS_PROVIDERS_MAX_TIME}s)! ${msg}"
reset_state
exit 11
fi
# wait and retry
sleep 1
printf "."
done
if [ -z "${cookie}" ]; then
echo "${ERROR}Failed to retrieve authentication token from Magpie for Weaver WPS providers registration."
reset_state
exit 12
fi
# validate that Magpie token retrieved is adequate
printf "%s" "${PREFIX}Validate Magpie token..."
resp=$( \
curl_cmd --insecure --silent --location \
-m ${REQUEST_TIMEOUT} \
-w "\n%{http_code}" \
-b "${cookie}" \
-H "Accept: application/json" \
-X GET \
"${MAGPIE_URL}/session" \
)
ret=$? # in case proxy not up yet to receive any request
code=$(echo "${resp}" | tail -n -1)
body=$(echo "${resp}" | head -n -1)
auth=$(echo "${body}" | grep -c '"authenticated": true')
admin=$(echo "${body}" | grep -c '"administrators"')
if [ ${ret} -eq 0 ] && [ "${code}" -eq 200 ] && [ "${auth}" -eq 1 ] && [ "${admin}" -eq 1 ]; then
printf " %s\n" "OK!"
else
printf "\n%s\n" "${ERROR}Failed administrative validation of Magpie token for Weaver WPS providers registration."
reset_state
exit 13
fi
# ------ PHASE 2 ------
# Weaver WPS Providers
# validate that Weaver is ready to receive requests
printf "%s" "${PREFIX}Wait for response from Weaver [${WEAVER_URL}]."
while true; do
resp=$( \
curl_cmd --insecure --silent --location \
-m ${REQUEST_TIMEOUT} \
-w "\n%{http_code}" \
-b "${cookie}" \
-H "Accept: application/json" \
-X GET \
"${WEAVER_URL}/" \
)
ret=$? # in case proxy not up yet to receive any request
code=$(echo "${resp}" | tail -n -1)
body=$(echo "${resp}" | head -n -1)
info=$(echo "${body}" | grep -c '"Weaver Information"')
if [ ${ret} -eq 0 ] && [ "${code}" -eq 200 ] && [ "${info}" -ne 0 ]; then
printf " %s\n" "OK!"
break;
fi
# interrupt if max time reached
next_time=$(date -u +%s)
delta_time=$(( next_time - start_time ))
if [ ${delta_time} -ge "${WEAVER_WPS_PROVIDERS_MAX_TIME}" ]; then
msg="Failed to register all providers specified in WEAVER_WPS_PROVIDERS. Weaver is not responding."
printf "\n%s\n" "${ERROR}Timeout (${WEAVER_WPS_PROVIDERS_MAX_TIME}s)! ${msg}"
reset_state
exit 21
fi
# wait and retry
sleep 1
printf "."
done
# move on to actual registration of WPS providers
echo "${PREFIX}Using URL: [${WEAVER_URL}]"
start_time="$(date -u +%s)"
ret=1
for prov in ${WEAVER_WPS_PROVIDERS}; do
if [ -z "${prov}" ]; then
continue
fi
prov_url="https://${PAVICS_FQDN_PUBLIC}${TWITCHER_PROTECTED_PATH}/${prov}"
prov_cap="${prov_url}?service=WPS&request=GetCapabilities"
# wait for WPS provider to respond
printf "%s" "${PREFIX}Wait for response from remote WPS provider [${prov}] on [${prov_url}]."
while true; do
# request the URL and obtain the body+http code, then split them for verification
resp=$( \
curl_cmd --insecure --silent --location \
-m ${REQUEST_TIMEOUT} \
-w "\n%{http_code}" \
-b "${cookie}" \
"${prov_cap}"
)
ret=$? # in case proxy not up yet to receive any request
code=$(echo "${resp}" | tail -n -1)
body=$(echo "${resp}" | head -n -1)
caps=$(echo "${body}" | grep -c "wps:Capabilities")
if [ ${ret} -eq 0 ] && [ "${code}" -eq 200 ] && [ "${caps}" -ne 0 ]; then
printf "\n%s\n" "${PREFIX}Got valid response from remote WPS provider [${prov}]."
break;
fi
# interrupt if max time reached
next_time=$(date -u +%s)
delta_time=$(( next_time - start_time ))
if [ ${delta_time} -ge "${WEAVER_WPS_PROVIDERS_MAX_TIME}" ]; then
msg="Failed to register all providers specified in WEAVER_WPS_PROVIDERS: [${prov}] is not responding."
printf "\n%s\n" "${ERROR}Timeout (${WEAVER_WPS_PROVIDERS_MAX_TIME}s)! ${msg}"
reset_state
exit 22
fi
# wait and retry
sleep 1
printf "."
done
retry=0
retry_msg=""
total=${WEAVER_WPS_PROVIDERS_RETRY_COUNT}
while true; do
if [ ${retry} -ne 0 ]; then
retry_msg=" (retry: ${retry}/${total})"
fi
# unregister in case of multiple up/down to regenerate from scratch, don't care if NotFound returned
echo "${PREFIX}Unregistering any remote WPS provider matching [${prov}]${retry_msg}."
curl_cmd --insecure --silent --location \
-m ${REQUEST_TIMEOUT} \
-w "${PREFIX}Delete [${prov}] response: %{http_code}${retry_msg}" -o /dev/null \
-b "${cookie}" \
-X DELETE \
"${WEAVER_URL}/providers/${prov}"
# register the new provider and validate
printf "\n%s" "${PREFIX}Registering remote WPS provider [${prov}] on [${prov_url}]${retry_msg}... "
resp=$( \
curl_cmd --insecure --silent --location \
-m ${REQUEST_TIMEOUT} \
-w "\n%{http_code}" \
-b "${cookie}" \
-H "Content-Type: application/json" \
-X POST \
-d "{\"id\": \"${prov}\", \"url\": \"${prov_url}\"}" \
"${WEAVER_URL}/providers" \
)
ret=$?
code=$(echo "${resp}" | tail -n -1)
body=$(echo "${resp}" | head -n -1)
if [ ${ret} -ne 0 ] || [ "${code}" -ne 201 ]; then
printf "\n%s\n" "${WARN}Failed registration of remote WPS provider [${prov}] on [${prov_url}]${retry_msg}."
printf "Error:\n%s\n" "${body}"
if [ ${retry} -gt ${total} ]; then
echo "${ERROR}Maximum retry attempts ${total} reached for WPS provider [${prov}]. Aborting."
reset_state
exit 23
fi
echo "${WARN}Will retry after ${WEAVER_WPS_PROVIDERS_RETRY_AFTER}s..."
sleep ${WEAVER_WPS_PROVIDERS_RETRY_AFTER}
retry=$((retry+1))
else
echo "OK!" # displayed on same line after first registration printf
break
fi
done
done
echo "${PREFIX}All Weaver remote WPS providers registered successfully!"
echo "${PREFIX}Starting Weaver WebApp/Worker Celery tasks validation..."
CUR_SCRIPT_DIR="$(dirname "$(realpath "$0")")"
PAVICS_COMPOSE="$(realpath "${CUR_SCRIPT_DIR}/../../pavics-compose.sh")"
PAVICS_LOG_DIR="${PAVICS_LOG_DIR:-/tmp/pavics-compose}"
CELERY_HEALTHCHECK="/opt/local/bin/weaver/celery-healthcheck"
mkdir -p "${PAVICS_LOG_DIR}"
# note: use 'tee' instead of capturing in variable to allow displaying results directly when running command
${PAVICS_COMPOSE} exec weaver bash "${CELERY_HEALTHCHECK}" | tee "${PAVICS_LOG_DIR}/weaver.log"
ret_weaver=$?
out_weaver=$(cat "${PAVICS_LOG_DIR}/weaver.log" | tail -n 1 | grep -c "ERROR")
${PAVICS_COMPOSE} exec weaver-worker bash "${CELERY_HEALTHCHECK}" | tee "${PAVICS_LOG_DIR}/weaver-worker.log"
ret_worker=$?
out_worker=$(cat "${PAVICS_LOG_DIR}/weaver-worker.log" | tail -n 1 | grep -c "ERROR")
if [ ${ret_weaver} -ne 0 ] || [ ${ret_worker} -ne 0 ] || [ "${out_weaver}" -ne 0 ] || [ "${out_worker}" -ne 0 ]; then
echo "${PREFIX}Weaver WebApp and/or Worker Celery tasks were not ready. Restarting both..."
${PAVICS_COMPOSE} restart weaver weaver-worker
else
echo "${PREFIX}Weaver WebApp and/or Worker Celery tasks are both ready."
fi
reset_state