108 lines
4.2 KiB
Bash
108 lines
4.2 KiB
Bash
|
|
#!/usr/bin/env bash
|
||
|
|
# test_nginx_cache.sh — verify the phase-1 edge cache actually caches.
|
||
|
|
#
|
||
|
|
# Sequence :
|
||
|
|
# 1. Pre-flight : nginx-cache reachable + /health returns 200.
|
||
|
|
# 2. Curl a fixed URL twice. First request must be MISS, second
|
||
|
|
# must be HIT. Surfaces via the X-Cache-Status response header.
|
||
|
|
# 3. Verify the cache directory has at least one entry on disk.
|
||
|
|
#
|
||
|
|
# Run on the Incus host that owns the nginx-cache container, OR
|
||
|
|
# from a workstation that can reach nginx-cache.lxd:80. The test
|
||
|
|
# uses a public bucket path so it doesn't need MinIO credentials.
|
||
|
|
#
|
||
|
|
# v1.0.9 — phase-1 edge cache acceptance.
|
||
|
|
#
|
||
|
|
# Usage:
|
||
|
|
# TEST_URL=http://nginx-cache.lxd/some-public-object.m4s \
|
||
|
|
# bash infra/ansible/tests/test_nginx_cache.sh
|
||
|
|
#
|
||
|
|
# Exit codes :
|
||
|
|
# 0 — cache is working (MISS then HIT)
|
||
|
|
# 1 — cache not reachable
|
||
|
|
# 2 — second request did not return HIT
|
||
|
|
# 3 — required tool missing
|
||
|
|
set -euo pipefail
|
||
|
|
|
||
|
|
CACHE_HOST=${CACHE_HOST:-nginx-cache.lxd}
|
||
|
|
CACHE_PORT=${CACHE_PORT:-80}
|
||
|
|
TEST_URL=${TEST_URL:-http://${CACHE_HOST}:${CACHE_PORT}/health}
|
||
|
|
RUN_VIA_INCUS=${RUN_VIA_INCUS:-0}
|
||
|
|
|
||
|
|
log() { printf '[%s] %s\n' "$(date +%H:%M:%S)" "$*" >&2; }
|
||
|
|
fail() { log "FAIL: $*"; exit "${2:-2}"; }
|
||
|
|
|
||
|
|
require() {
|
||
|
|
command -v "$1" >/dev/null 2>&1 || fail "required tool missing on host: $1" 3
|
||
|
|
}
|
||
|
|
|
||
|
|
require curl
|
||
|
|
require date
|
||
|
|
|
||
|
|
# helper : run curl in the right context. If RUN_VIA_INCUS=1 the
|
||
|
|
# command runs inside the host (which can resolve .lxd hostnames).
|
||
|
|
do_curl() {
|
||
|
|
if [ "$RUN_VIA_INCUS" = "1" ]; then
|
||
|
|
incus exec nginx-cache -- curl -sS "$@"
|
||
|
|
else
|
||
|
|
curl -sS "$@"
|
||
|
|
fi
|
||
|
|
}
|
||
|
|
|
||
|
|
# -----------------------------------------------------------------------------
|
||
|
|
# 1. Pre-flight — /health is alive.
|
||
|
|
# -----------------------------------------------------------------------------
|
||
|
|
log "step 0: pre-flight — GET ${CACHE_HOST}:${CACHE_PORT}/health"
|
||
|
|
health_url="http://${CACHE_HOST}:${CACHE_PORT}/health"
|
||
|
|
if ! body=$(do_curl --max-time 5 -o /dev/null -w "%{http_code}" "$health_url" 2>&1); then
|
||
|
|
fail "cache not reachable at $health_url" 1
|
||
|
|
fi
|
||
|
|
if [ "$body" != "200" ]; then
|
||
|
|
fail "cache /health returned HTTP $body, want 200" 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
# -----------------------------------------------------------------------------
|
||
|
|
# 2. The ${TEST_URL} dance — first MISS, second HIT.
|
||
|
|
# -----------------------------------------------------------------------------
|
||
|
|
log "step 1: first request to $TEST_URL — expect MISS"
|
||
|
|
status1=$(do_curl --max-time 10 -o /dev/null -D - "$TEST_URL" 2>&1 \
|
||
|
|
| tr -d '\r' | awk -F': ' 'tolower($1) == "x-cache-status" {print $2}' | tr -d ' ')
|
||
|
|
log " X-Cache-Status: $status1"
|
||
|
|
if [ -z "$status1" ]; then
|
||
|
|
fail "first response missing X-Cache-Status header — site config not applying ?" 2
|
||
|
|
fi
|
||
|
|
|
||
|
|
# A cacheable URL with no prior entry is MISS or EXPIRED. STALE means
|
||
|
|
# the upstream is unhealthy, which is a different bug — fail loud.
|
||
|
|
case "$status1" in
|
||
|
|
MISS|EXPIRED|REVALIDATED|BYPASS) ;;
|
||
|
|
HIT) log " WARN: first request already HIT (a previous run cached it)" ;;
|
||
|
|
STALE|UPDATING) fail "origin upstream unhealthy — got STALE on cold cache" 2 ;;
|
||
|
|
*) fail "unexpected cache status on first request: $status1" 2 ;;
|
||
|
|
esac
|
||
|
|
|
||
|
|
log "step 2: second request to $TEST_URL — expect HIT"
|
||
|
|
sleep 1 # give nginx a moment to flush the entry to disk
|
||
|
|
status2=$(do_curl --max-time 10 -o /dev/null -D - "$TEST_URL" 2>&1 \
|
||
|
|
| tr -d '\r' | awk -F': ' 'tolower($1) == "x-cache-status" {print $2}' | tr -d ' ')
|
||
|
|
log " X-Cache-Status: $status2"
|
||
|
|
|
||
|
|
if [ "$status2" != "HIT" ]; then
|
||
|
|
fail "second request returned X-Cache-Status=$status2, want HIT — cache config not effective" 2
|
||
|
|
fi
|
||
|
|
|
||
|
|
# -----------------------------------------------------------------------------
|
||
|
|
# 3. On-disk verification — at least one entry under the cache root.
|
||
|
|
# -----------------------------------------------------------------------------
|
||
|
|
log "step 3: verifying cache directory has on-disk entries"
|
||
|
|
if [ "$RUN_VIA_INCUS" = "1" ]; then
|
||
|
|
count=$(incus exec nginx-cache -- bash -c "find /var/cache/nginx/veza -type f 2>/dev/null | wc -l" || echo 0)
|
||
|
|
log " on-disk entries: $count"
|
||
|
|
if [ "$count" = "0" ]; then
|
||
|
|
fail "cache directory is empty after a HIT — unexpected" 2
|
||
|
|
fi
|
||
|
|
fi
|
||
|
|
|
||
|
|
log "PASS: edge cache MISS→HIT roundtrip OK (status1=$status1, status2=$status2)"
|
||
|
|
exit 0
|