Skip to content

Commit ada2969

Browse files
committed
Fix streaming test request parsing
1 parent 9a39245 commit ada2969

File tree

1 file changed

+197
-30
lines changed

1 file changed

+197
-30
lines changed

scripts/test-int.sh

Lines changed: 197 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,46 @@ host_arch() {
1717

1818
wait_for_file() {
1919
file=$1
20-
waits=200
20+
waits=${2:-200}
2121
while [ ! -s "$file" ] && [ "$waits" -gt 0 ]; do
2222
sleep 0.1
2323
waits=$((waits - 1))
2424
done
2525
[ -s "$file" ]
2626
}
2727

28+
ensure_image() {
29+
image=$1
30+
if ! docker image inspect "$image" >/dev/null 2>&1; then
31+
if ! docker pull "$image" >/dev/null 2>&1; then
32+
printf '%s\n' "Failed to pull image: $image" >&2
33+
return 1
34+
fi
35+
fi
36+
return 0
37+
}
38+
39+
container_running() {
40+
docker inspect -f '{{.State.Running}}' "$1" 2>/dev/null | grep -q true
41+
}
42+
43+
wait_for_container_port() {
44+
container=$1
45+
port=$2
46+
waits=${3:-200}
47+
while [ "$waits" -gt 0 ]; do
48+
if docker exec "$container" sh -c "if command -v ncat >/dev/null 2>&1; then ncat -z 127.0.0.1 $port; elif command -v nc >/dev/null 2>&1; then nc -z 127.0.0.1 $port; else exit 1; fi" >/dev/null 2>&1; then
49+
return 0
50+
fi
51+
if ! container_running "$container"; then
52+
return 1
53+
fi
54+
sleep 0.2
55+
waits=$((waits - 1))
56+
done
57+
return 1
58+
}
59+
2860
arch=${ARCH:-}
2961
if [ -z "$arch" ]; then
3062
arch=$(host_arch) || {
@@ -137,7 +169,10 @@ template=$(mktemp)
137169
streaming_dir=""
138170
streaming_code_dir=""
139171
streaming_request=""
172+
streaming_next_request=""
140173
streaming_request_clean=""
174+
streaming_api_log=""
175+
streaming_runtime_log=""
141176
streaming_network=""
142177
streaming_api_container=""
143178
streaming_runtime_container=""
@@ -161,6 +196,12 @@ cleanup() {
161196
if [ -n "$streaming_request_clean" ]; then
162197
rm -f "$streaming_request_clean"
163198
fi
199+
if [ -n "$streaming_api_log" ]; then
200+
rm -f "$streaming_api_log"
201+
fi
202+
if [ -n "$streaming_runtime_log" ]; then
203+
rm -f "$streaming_runtime_log"
204+
fi
164205
}
165206
trap cleanup EXIT
166207

@@ -224,9 +265,12 @@ TEMPLATE
224265

225266
run_streaming() {
226267
platform="linux/$arch"
268+
api_image="public.ecr.aws/amazonlinux/amazonlinux:2023"
269+
runtime_image="public.ecr.aws/lambda/provided:al2023"
227270
streaming_dir=$(mktemp -d)
228271
streaming_code_dir=$(mktemp -d)
229272
streaming_request="$streaming_dir/response_request.txt"
273+
streaming_next_request="$streaming_dir/next_request.txt"
230274
streaming_event="$streaming_dir/event.json"
231275
streaming_script="$streaming_dir/runtime_api.sh"
232276
streaming_request_id="streaming-test-id"
@@ -245,7 +289,7 @@ exec /opt/bootstrap
245289
BOOT
246290
chmod +x "$streaming_code_dir/function.sh" "$streaming_code_dir/bootstrap"
247291

248-
cat <<'API' > "$streaming_script"
292+
cat <<'API' > "$streaming_script"
249293
#!/bin/sh
250294
set -eu
251295
@@ -254,45 +298,135 @@ event_file=${EVENT_FILE:-/data/event.json}
254298
next_file=${NEXT_FILE:-/data/next_request.txt}
255299
response_file=${RESPONSE_FILE:-/data/response_request.txt}
256300
request_id=${REQUEST_ID:-streaming-test-id}
301+
handler=${HANDLER_FILE:-/data/handle_request.sh}
302+
log_file=${LOG_FILE:-/data/api.log}
257303
258304
event=$(cat "$event_file")
259305
length=$(printf '%s' "$event" | wc -c | tr -d ' ')
260306
261-
{
262-
printf 'HTTP/1.1 200 OK\r\n'
263-
printf 'Lambda-Runtime-Aws-Request-Id: %s\r\n' "$request_id"
264-
printf 'Lambda-Runtime-Deadline-Ms: 0\r\n'
265-
printf 'Lambda-Runtime-Function-Response-Mode: streaming\r\n'
266-
printf 'Content-Type: application/json\r\n'
267-
printf 'Content-Length: %s\r\n' "$length"
268-
printf 'Connection: close\r\n'
269-
printf '\r\n'
270-
printf '%s' "$event"
271-
} | nc -l -p "$port" > "$next_file"
272-
273-
{
274-
printf 'HTTP/1.1 202 Accepted\r\n'
275-
printf 'Content-Length: 0\r\n'
276-
printf 'Connection: close\r\n'
277-
printf '\r\n'
278-
} | nc -l -p "$port" > "$response_file"
307+
cat <<'HANDLER' > "$handler"
308+
#!/bin/sh
309+
set -eu
310+
311+
request_line=""
312+
if IFS= read -r request_line; then
313+
:
314+
fi
315+
clean_request_line=$(printf '%s' "$request_line" | tr -d '\r')
316+
if [ -z "$clean_request_line" ]; then
317+
exit 0
318+
fi
319+
320+
printf '%s\n' "$clean_request_line" >> "$LOG_FILE"
321+
322+
path=$(printf '%s' "$clean_request_line" | awk '{print $2}')
323+
target=""
324+
case "$path" in
325+
/2018-06-01/runtime/invocation/next)
326+
target="$NEXT_FILE"
327+
;;
328+
/2018-06-01/runtime/invocation/*/response)
329+
target="$RESPONSE_FILE"
330+
;;
331+
*)
332+
target="$RESPONSE_FILE"
333+
;;
334+
esac
335+
336+
printf '%s\n' "$clean_request_line" > "$target"
337+
while IFS= read -r line; do
338+
clean_line=$(printf '%s' "$line" | tr -d '\r')
339+
printf '%s\n' "$clean_line" >> "$target"
340+
[ -z "$clean_line" ] && break
341+
done
342+
343+
case "$path" in
344+
/2018-06-01/runtime/invocation/next)
345+
{
346+
printf 'HTTP/1.1 200 OK\r\n'
347+
printf 'Lambda-Runtime-Aws-Request-Id: %s\r\n' "$REQUEST_ID"
348+
printf 'Lambda-Runtime-Deadline-Ms: 0\r\n'
349+
printf 'Lambda-Runtime-Function-Response-Mode: streaming\r\n'
350+
printf 'Content-Type: application/json\r\n'
351+
printf 'Content-Length: %s\r\n' "$EVENT_LENGTH"
352+
printf 'Connection: close\r\n'
353+
printf '\r\n'
354+
printf '%s' "$EVENT_PAYLOAD"
355+
}
356+
;;
357+
*)
358+
{
359+
printf 'HTTP/1.1 202 Accepted\r\n'
360+
printf 'Content-Length: 0\r\n'
361+
printf 'Connection: close\r\n'
362+
printf '\r\n'
363+
}
364+
;;
365+
esac
366+
367+
case "$path" in
368+
/2018-06-01/runtime/invocation/next)
369+
exit 0
370+
;;
371+
esac
372+
373+
while IFS= read -r line || [ -n "$line" ]; do
374+
clean_line=$(printf '%s' "$line" | tr -d '\r')
375+
printf '%s\n' "$clean_line" >> "$target"
376+
done
377+
HANDLER
378+
chmod +x "$handler"
379+
380+
if command -v ncat >/dev/null 2>&1; then
381+
NCHANDLER=$(command -v ncat)
382+
elif command -v nc >/dev/null 2>&1; then
383+
NCHANDLER=$(command -v nc)
384+
else
385+
printf '%s\n' "ncat/nc not available" >&2
386+
exit 1
387+
fi
388+
389+
export NEXT_FILE="$next_file"
390+
export RESPONSE_FILE="$response_file"
391+
export REQUEST_ID="$request_id"
392+
export EVENT_PAYLOAD="$event"
393+
export EVENT_LENGTH="$length"
394+
export LOG_FILE="$log_file"
395+
396+
while :; do
397+
"$NCHANDLER" -l -p "$port" -c "$handler"
398+
done
279399
API
280400
chmod +x "$streaming_script"
281401

282402
streaming_network="lambda-shell-runtime-streaming-$arch-$$"
283403
streaming_api_container="lambda-shell-runtime-streaming-api-$$"
284404
streaming_runtime_container="lambda-shell-runtime-streaming-runtime-$$"
405+
streaming_api_log=$(mktemp)
406+
streaming_runtime_log=$(mktemp)
407+
408+
ensure_image "$api_image"
409+
ensure_image "$runtime_image"
285410

286411
docker network create "$streaming_network" >/dev/null
287-
docker run -d --name "$streaming_api_container" \
412+
if ! docker run -d --name "$streaming_api_container" \
288413
--network "$streaming_network" \
289414
--platform "$platform" \
290415
-v "$streaming_dir:/data" \
291-
busybox sh /data/runtime_api.sh >/dev/null
416+
"$api_image" sh -c \
417+
'dnf -y install nmap-ncat >/dev/null 2>&1 || { echo "Failed to install nmap-ncat" >&2; exit 1; }; sh /data/runtime_api.sh' \
418+
>"$streaming_api_log" 2>&1; then
419+
cat "$streaming_api_log" >&2
420+
exit 1
421+
fi
292422

293-
sleep 0.2
423+
if ! wait_for_container_port "$streaming_api_container" 9001 600; then
424+
docker logs "$streaming_api_container" >&2 || true
425+
printf '%s\n' "Streaming API container did not become ready" >&2
426+
exit 1
427+
fi
294428

295-
docker run -d --name "$streaming_runtime_container" \
429+
if ! docker run -d --name "$streaming_runtime_container" \
296430
--network "$streaming_network" \
297431
--platform "$platform" \
298432
-v "$layer_root:/opt:ro" \
@@ -301,32 +435,65 @@ API
301435
-e _HANDLER="function.handler" \
302436
-e LAMBDA_TASK_ROOT="/var/task" \
303437
--entrypoint /bin/sh \
304-
public.ecr.aws/lambda/provided:al2023 \
305-
-c 'if ! rpm -q curl-minimal >/dev/null 2>&1; then echo "curl-minimal not installed" >&2; exit 1; fi; curl --version >&2; exec /opt/bootstrap' >/dev/null
438+
"$runtime_image" \
439+
-c 'if ! rpm -q curl-minimal >/dev/null 2>&1; then echo "curl-minimal not installed" >&2; exit 1; fi; exec /opt/bootstrap' \
440+
>"$streaming_runtime_log" 2>&1; then
441+
cat "$streaming_runtime_log" >&2
442+
exit 1
443+
fi
306444

307-
if ! wait_for_file "$streaming_request"; then
445+
if ! wait_for_file "$streaming_request" 600; then
308446
docker logs "$streaming_runtime_container" >&2 || true
447+
docker logs "$streaming_api_container" >&2 || true
448+
docker inspect -f 'runtime status: {{.State.Status}} exit={{.State.ExitCode}}' "$streaming_runtime_container" >&2 2>/dev/null || true
449+
docker inspect -f 'api status: {{.State.Status}} exit={{.State.ExitCode}}' "$streaming_api_container" >&2 2>/dev/null || true
450+
if [ -f "$streaming_next_request" ]; then
451+
printf '%s\n' "Captured next request:" >&2
452+
tr -d '\r' < "$streaming_next_request" >&2 || true
453+
fi
454+
if [ -f "$streaming_dir/api.log" ]; then
455+
printf '%s\n' "API request log:" >&2
456+
cat "$streaming_dir/api.log" >&2 || true
457+
fi
309458
printf '%s\n' "Streaming response request was not captured" >&2
310459
exit 1
311460
fi
312461

313462
streaming_request_clean=$(mktemp)
314-
tr -d '\r' < "$streaming_request" > "$streaming_request_clean"
463+
{
464+
if [ -f "$streaming_request" ]; then
465+
cat "$streaming_request"
466+
fi
467+
if [ -f "$streaming_next_request" ]; then
468+
cat "$streaming_next_request"
469+
fi
470+
} | tr -d '\r' > "$streaming_request_clean"
315471

316-
if ! grep -F "POST /2018-06-01/runtime/invocation/${streaming_request_id}/response" "$streaming_request_clean" >/dev/null 2>&1; then
317-
printf '%s\n' "Streaming response used unexpected endpoint" >&2
472+
if ! grep -F "/2018-06-01/runtime/invocation/${streaming_request_id}/response" "$streaming_request_clean" >/dev/null 2>&1; then
473+
request_line=$(head -n 1 "$streaming_request_clean" || true)
474+
printf '%s\n' "Streaming response used unexpected endpoint: $request_line" >&2
475+
printf '%s\n' "Captured requests:" >&2
476+
cat "$streaming_request_clean" >&2 || true
477+
docker logs "$streaming_runtime_container" >&2 || true
478+
docker logs "$streaming_api_container" >&2 || true
318479
exit 1
319480
fi
320481
if ! grep -i -F "Lambda-Runtime-Function-Response-Mode: streaming" "$streaming_request_clean" >/dev/null 2>&1; then
321482
printf '%s\n' "Streaming response header missing response mode" >&2
483+
printf '%s\n' "Captured requests:" >&2
484+
cat "$streaming_request_clean" >&2 || true
322485
exit 1
323486
fi
324487
if ! grep -i -F "Trailer: Lambda-Runtime-Function-Error-Type, Lambda-Runtime-Function-Error-Body" "$streaming_request_clean" >/dev/null 2>&1; then
325488
printf '%s\n' "Streaming response header missing error trailers" >&2
489+
printf '%s\n' "Captured requests:" >&2
490+
cat "$streaming_request_clean" >&2 || true
326491
exit 1
327492
fi
328493
if ! grep -F "$streaming_payload" "$streaming_request_clean" >/dev/null 2>&1; then
329494
printf '%s\n' "Streaming response payload not captured" >&2
495+
printf '%s\n' "Captured requests:" >&2
496+
cat "$streaming_request_clean" >&2 || true
330497
exit 1
331498
fi
332499
}

0 commit comments

Comments
 (0)