149 lines
5.9 KiB
Bash
Executable File
149 lines
5.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
SERVICE_URL="${RENDEZVOUS_SMOKE_HTTP_URL:-http://127.0.0.1:8080/}"
|
|
MEDIATOR="${RENDEZVOUS_SMOKE_UDP_ENDPOINT:-127.0.0.1:9050}"
|
|
TIMEOUT_SECONDS="${RENDEZVOUS_SMOKE_TIMEOUT_SECONDS:-30}"
|
|
LOCAL_KEY="${RENDEZVOUS_SMOKE_LOCAL_KEY:-$ROOT/deploy/compose/secrets/signing-key}"
|
|
PROJECT="$ROOT/src/FinalFactory.Rendezvous.TestClient/FinalFactory.Rendezvous.TestClient.csproj"
|
|
BUILD_CONFIGURATION="${RENDEZVOUS_SMOKE_CONFIGURATION:-Release}"
|
|
GAME_ID="${RENDEZVOUS_SMOKE_GAME_ID:-space-game}"
|
|
ENVIRONMENT_ID="${RENDEZVOUS_SMOKE_ENVIRONMENT_ID:-smoke}"
|
|
REGION="${RENDEZVOUS_SMOKE_REGION:-local}"
|
|
PROTOCOL_VERSION="${RENDEZVOUS_SMOKE_PROTOCOL_VERSION:-1}"
|
|
|
|
for command in curl date dotnet jq mktemp od openssl tail tr wc; do
|
|
command -v "$command" >/dev/null || {
|
|
printf 'Missing required command: %s\n' "$command" >&2
|
|
exit 2
|
|
}
|
|
done
|
|
|
|
if [[ ! "$TIMEOUT_SECONDS" =~ ^[0-9]+$ ]] || (( TIMEOUT_SECONDS < 1 || TIMEOUT_SECONDS > 300 )); then
|
|
printf 'RENDEZVOUS_SMOKE_TIMEOUT_SECONDS must be an integer from 1 through 300.\n' >&2
|
|
exit 2
|
|
fi
|
|
if [[ ! "$PROTOCOL_VERSION" =~ ^[0-9]+$ ]] || (( PROTOCOL_VERSION < 1 )); then
|
|
printf 'RENDEZVOUS_SMOKE_PROTOCOL_VERSION must be a positive integer.\n' >&2
|
|
exit 2
|
|
fi
|
|
for scoped_value in "$GAME_ID" "$ENVIRONMENT_ID" "$REGION"; do
|
|
if [[ -z "$scoped_value" ]]; then
|
|
printf 'Smoke game, environment, and region values must not be empty.\n' >&2
|
|
exit 2
|
|
fi
|
|
done
|
|
|
|
base64url() {
|
|
openssl base64 -A | tr '+/' '-_' | tr -d '='
|
|
}
|
|
|
|
local_credential() {
|
|
if [[ ! -f "$LOCAL_KEY" ]] || [[ "$(wc -c < "$LOCAL_KEY")" -ne 32 ]]; then
|
|
printf 'Local Compose smoke key must be exactly 32 bytes: %s\n' "$LOCAL_KEY" >&2
|
|
exit 2
|
|
fi
|
|
|
|
local now expires nonce payload encoded signed hex signature
|
|
now="$(date +%s)"
|
|
expires="$((now + 600))"
|
|
nonce="$(openssl rand -hex 16)"
|
|
payload="$(jq -cn \
|
|
--arg issuer final-factory-rendezvous-smoke \
|
|
--arg audience rendezvous-service \
|
|
--arg subject local-smoke-host \
|
|
--arg kind dedicatedPublisher \
|
|
--arg gameId "$GAME_ID" \
|
|
--arg environmentId "$ENVIRONMENT_ID" \
|
|
--arg region "$REGION" \
|
|
--arg nonce "$nonce" \
|
|
--argjson now "$now" \
|
|
--argjson expires "$expires" \
|
|
'{version:1,issuer:$issuer,audience:$audience,subject:$subject,kind:$kind,gameId:$gameId,environmentId:$environmentId,regions:[$region],permissions:[],issuedAtUnixSeconds:$now,notBeforeUnixSeconds:$now,expiresAtUnixSeconds:$expires,nonce:$nonce}')"
|
|
encoded="$(printf '%s' "$payload" | base64url)"
|
|
signed="rv1.local-smoke-1.$encoded"
|
|
hex="$(od -An -v -tx1 "$LOCAL_KEY" | tr -d ' \n')"
|
|
signature="$(printf '%s' "$signed" \
|
|
| openssl dgst -sha256 -mac HMAC -macopt "hexkey:$hex" -binary \
|
|
| base64url)"
|
|
printf '%s.%s' "$signed" "$signature"
|
|
}
|
|
|
|
credential="${RENDEZVOUS_PUBLISHER_CREDENTIAL:-}"
|
|
if [[ -z "$credential" ]]; then
|
|
credential="$(local_credential)"
|
|
fi
|
|
export RENDEZVOUS_PUBLISHER_CREDENTIAL="$credential"
|
|
|
|
curl --fail --silent --show-error --max-time 5 "${SERVICE_URL%/}/health/live" >/dev/null
|
|
curl --fail --silent --show-error --max-time 5 "${SERVICE_URL%/}/health/ready" >/dev/null
|
|
|
|
temp_dir="$(mktemp -d)"
|
|
host_log="$temp_dir/host.jsonl"
|
|
join_log="$temp_dir/join.jsonl"
|
|
host_pid=''
|
|
cleanup() {
|
|
local status="$?"
|
|
if [[ -n "$host_pid" ]] && kill -0 "$host_pid" 2>/dev/null; then
|
|
kill -TERM "$host_pid" 2>/dev/null || true
|
|
wait "$host_pid" 2>/dev/null || true
|
|
fi
|
|
if [[ "$status" -ne 0 ]]; then
|
|
printf 'Deployment smoke failed; sanitized diagnostic events follow.\n' >&2
|
|
[[ -f "$host_log" ]] && jq -c . "$host_log" >&2 || true
|
|
[[ -f "$join_log" ]] && jq -c . "$join_log" >&2 || true
|
|
fi
|
|
rm -rf "$temp_dir"
|
|
return "$status"
|
|
}
|
|
trap cleanup EXIT
|
|
trap 'exit 130' INT
|
|
trap 'exit 143' TERM
|
|
|
|
dotnet run --project "$PROJECT" --configuration "$BUILD_CONFIGURATION" --no-build -- \
|
|
host --service "$SERVICE_URL" --mediator "$MEDIATOR" \
|
|
--game "$GAME_ID" --environment "$ENVIRONMENT_ID" --region "$REGION" --protocol "$PROTOCOL_VERSION" \
|
|
--script --json --exit-after-echo --timeout-seconds "$TIMEOUT_SECONDS" \
|
|
>"$host_log" 2>&1 &
|
|
host_pid="$!"
|
|
|
|
ready=false
|
|
for ((iteration = 0; iteration < TIMEOUT_SECONDS * 4; iteration++)); do
|
|
if jq -e 'select(.event == "host.ready")' "$host_log" >/dev/null 2>&1; then
|
|
ready=true
|
|
break
|
|
fi
|
|
if ! kill -0 "$host_pid" 2>/dev/null; then
|
|
printf 'Host diagnostic stopped before it became ready.\n' >&2
|
|
jq -c . "$host_log" >&2 || true
|
|
exit 1
|
|
fi
|
|
sleep 0.25
|
|
done
|
|
if [[ "$ready" != true ]]; then
|
|
printf 'Host diagnostic did not become ready within %s seconds.\n' "$TIMEOUT_SECONDS" >&2
|
|
exit 1
|
|
fi
|
|
|
|
listing_id="$(jq -r 'select(.event == "host.registered") | .listingId' "$host_log" | tail -n 1)"
|
|
if [[ -z "$listing_id" || "$listing_id" == null ]]; then
|
|
printf 'Host diagnostic did not report a listing ID.\n' >&2
|
|
exit 1
|
|
fi
|
|
|
|
dotnet run --project "$PROJECT" --configuration "$BUILD_CONFIGURATION" --no-build -- \
|
|
join --service "$SERVICE_URL" --mediator "$MEDIATOR" \
|
|
--game "$GAME_ID" --environment "$ENVIRONMENT_ID" --region "$REGION" --protocol "$PROTOCOL_VERSION" \
|
|
--listing "$listing_id" --script --json --timeout-seconds "$TIMEOUT_SECONDS" \
|
|
>"$join_log" 2>&1
|
|
wait "$host_pid"
|
|
host_pid=''
|
|
|
|
jq -e 'select(.event == "host.direct-traffic" and .status == "verified")' "$host_log" >/dev/null
|
|
jq -e 'select(.event == "host.deregistered" and .status == "complete")' "$host_log" >/dev/null
|
|
jq -e 'select(.event == "join.direct-traffic" and .status == "verified")' "$join_log" >/dev/null
|
|
jq -e 'select(.event == "join.outcome-report" and .status == "accepted")' "$join_log" >/dev/null
|
|
|
|
printf 'Rendezvous deployment smoke passed: HTTP live/ready and authenticated UDP mediation/direct traffic.\n'
|