Refactor load testing scripts to support Bash and PowerShell
CI / test (push) Successful in 2m50s
CI / docker (push) Successful in 5m12s

- Updated README.md to reflect changes in load testing commands and added usage examples for Bash scripts.
- Converted PowerShell load testing scripts to Bash equivalents for better cross-platform compatibility.
- Added new Bash scripts: run-loadtests.sh, summarize-artillery.sh, and summarize-k6.sh to mirror existing PowerShell functionality.
- Updated admin-api.js and ws-chat.yml for consistency and improved performance metrics reporting.
- Enhanced error handling and output formatting in summary scripts for better readability.
This commit is contained in:
zwitschi committed 2026-09-02 19:47:34 +02:00
1 parent 9f60087a4c
commit 33b6296c5e
82 files changed
+19682 -21133

No files matched your search

+177
View File
@@ -0,0 +1,177 @@
#!/usr/bin/env bash
# check-tokens.sh — Verify that the credentials in the environment actually work.
# Mirrors scripts/check-tokens.ps1.
#
# Reads .env (or a supplied file) and validates access against live services:
# 1. Gitea container registry (CI_REGISTRY_TOKEN / CI_REGISTRY_USER).
# 2. Cloudflare API token(s) (CLOUDFLARE_API_TOKEN, and any R2 admin token).
# 3. R2/S3 bucket access (R2_ACCESS_KEY_ID + R2_SECRET_ACCESS_KEY) — lists buckets.
# 4. Linear Void admin login (ADMIN_USERNAME / ADMIN_PASSWORD) against the app origin.
#
# NOTE: Runs the checks through the target Docker host (default 192.168.88.40) so
# network + TLS work regardless of this machine's proxy/firewall. Uses the
# curlimages/curl and amazon/aws-cli images, which are pulled on demand.
#
# Usage:
# ./scripts/check-tokens.sh
# ./scripts/check-tokens.sh -e .env
# ./scripts/check-tokens.sh -t 192.168.88.40
#
# Exit code 0 = all credentials valid; 1 = at least one check failed.
set -uo pipefail
ENV_FILE=""
TARGET=192.168.88.40
DOCKER_PORT=2375
TIMEOUT=20
while [[ $# -gt 0 ]]; do
case "$1" in
-e|--env-file) ENV_FILE="$2"; shift 2;;
-t|--target) TARGET="$2"; shift 2;;
-p|--docker-port) DOCKER_PORT="$2"; shift 2;;
--timeout) TIMEOUT="$2"; shift 2;;
*) echo "Unknown option: $1" >&2; exit 2;;
esac
done
export DOCKER_HOST="tcp://${TARGET}:${DOCKER_PORT}"
FAILED=0
fail() { printf ' [FAIL] %s\n' "$1"; FAILED=1; }
ok() { printf ' [OK] %s\n' "$1"; }
warn() { printf ' [WARN] %s\n' "$1"; }
# Resolve env file: explicit, or $PWD/.env, or repo root.
if [[ -z "$ENV_FILE" ]]; then
for cand in "$PWD/.env" "$(dirname "$PWD")/.env"; do
if [[ -f "$cand" ]]; then ENV_FILE="$cand"; break; fi
done
fi
if [[ -z "$ENV_FILE" || ! -f "$ENV_FILE" ]]; then
echo "No .env file found. Pass one with -e." >&2
exit 1
fi
# Parse KEY=VALUE lines into an associative array.
declare -A envs
while IFS= read -r line || [[ -n "$line" ]]; do
if [[ "$line" =~ ^[[:space:]]*([A-Za-z0-9_]+)[[:space:]]*=[[:space:]]*(.*)[[:space:]]*$ ]]; then
envs["${BASH_REMATCH[1]}"]="${BASH_REMATCH[2]}"
fi
done < "$ENV_FILE"
get_val() { [[ -n "${envs[$1]+x}" ]] && echo "${envs[$1]}"; }
# Pull helper images once.
echo "Preparing helper images (curl, aws-cli) on $TARGET..."
docker pull curlimages/curl:latest >/dev/null 2>&1 || true
docker pull amazon/aws-cli:latest >/dev/null 2>&1 || true
# dc_curl URL [bearer] [token] — run curl via the curlimages/curl container.
dc_curl() {
local url="$1" bearer="${2:-}" token="${3:-}"
local -a args=(run --rm curlimages/curl:latest -sS --max-time "$TIMEOUT")
[[ -n "$bearer" ]] && args+=( -H "Authorization: Bearer $bearer" )
[[ -n "$token" ]] && args+=( -H "Authorization: token $token" )
args+=( "$url" )
docker "${args[@]}" 2>&1 | tr -d '\r' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'
}
# ---------------------------------------------------------------------------
echo "== Linear Void credential / token check =="
echo "Env file : $ENV_FILE"
echo "Docker host: $DOCKER_HOST"
# --- 1. Gitea registry token ---
echo ""
echo "-- Gitea container registry --"
reg_user="$(get_val CI_REGISTRY_USER)"
reg_token="$(get_val CI_REGISTRY_TOKEN)"
if [[ -n "$reg_user" && -n "$reg_token" ]]; then
# Non-sensitive probe: /api/v1/user returns a scope message for token-based creds.
out="$(dc_curl 'https://git.allucanget.biz/api/v1/user' "" "$reg_token")"
if [[ "$out" =~ token.does.not.have.at.least.one.of.required.scope || "$out" =~ '"login"' || "$out" =~ invalid_grant ]]; then
if [[ "$out" =~ invalid_grant|Unauthorized|invalid ]]; then
fail "Gitea registry token rejected ($reg_user): $out"
else
ok "Gitea registry token valid for '$reg_user' (scope: write:package/write:repository)"
fi
else
warn "Gitea registry token response unexpected: $out"
fi
else
warn "CI_REGISTRY_USER / CI_REGISTRY_TOKEN not set; skipping Gitea registry check"
fi
# --- 2. Cloudflare API token ---
echo ""
echo "-- Cloudflare API tokens --"
cf_token="$(get_val CLOUDFLARE_API_TOKEN)"
if [[ -n "$cf_token" ]]; then
out="$(dc_curl 'https://api.cloudflare.com/client/v4/user/tokens/verify' "$cf_token")"
if [[ "$out" =~ '"success":true' ]]; then
if [[ "$out" =~ '"status":"active"' ]]; then ok 'Cloudflare API token valid and ACTIVE'; else warn "Cloudflare API token valid but status: $out"; fi
else
fail "Cloudflare API token rejected: $out"
fi
else
warn "CLOUDFLARE_API_TOKEN not set; skipping Cloudflare check"
fi
# --- 3. Cloudflare R2 / S3 bucket access ---
echo ""
echo "-- Cloudflare R2 (S3-compatible) --"
r2_key="$(get_val R2_ACCESS_KEY_ID)"
r2_secret="$(get_val R2_SECRET_ACCESS_KEY)"
r2_ep="$(get_val R2_ENDPOINT)"
bucket="$(get_val R2_BUCKET_NAME)"
# Use the admin key pair (which has ListBuckets) when present, else the regular key.
list_k="$(get_val R2_ADMIN_ACCESS_KEY_ID)"; list_s="$(get_val R2_ADMIN_SECRET_ACCESS_KEY)"
if [[ -z "$list_k" || -z "$list_s" ]]; then list_k="$r2_key"; list_s="$r2_secret"; fi
if [[ -n "$list_k" && -n "$list_s" && -n "$r2_ep" ]]; then
out="$(docker run --rm --entrypoint sh amazon/aws-cli:latest -c "export AWS_ACCESS_KEY_ID='$list_k'; export AWS_SECRET_ACCESS_KEY='$list_s'; aws s3 ls --endpoint-url '$r2_ep' --region auto 2>&1" 2>&1)"
if grep -q "$bucket" <<<"$out"; then ok "R2 bucket listing OK, '$bucket' present"
elif grep -q 'AccessDenied' <<<"$out"; then fail "R2 listing denied (no ListBuckets permission): $out"
elif grep -qE '^[^[:space:]]+[[:space:]]+' <<<"$out"; then warn "R2 listing returned (unexpected): $out"
else fail "R2 access failed: $out"; fi
else
warn "R2 credentials / endpoint not fully set; skipping R2 check"
fi
# Verify the specific application bucket is reachable with the primary key (read).
if [[ -n "$r2_key" && -n "$r2_secret" && -n "$r2_ep" && -n "$bucket" ]]; then
out="$(docker run --rm --entrypoint sh amazon/aws-cli:latest -c "export AWS_ACCESS_KEY_ID='$r2_key'; export AWS_SECRET_ACCESS_KEY='$r2_secret'; aws s3 ls s3://$bucket/ --endpoint-url '$r2_ep' --region auto --max-keys 5 2>&1 | head -5" 2>&1)"
if grep -q 'AccessDenied' <<<"$out"; then fail "Bucket '$bucket' read denied with primary key"
elif [[ -z "$out" ]]; then ok "Bucket '$bucket' reachable (empty listing, expected)"
elif grep -q 'NoSuchBucket' <<<"$out"; then fail "Bucket '$bucket' NOT FOUND"
else ok "Bucket '$bucket' reachable"; fi
elif [[ -z "$bucket" ]]; then
warn "R2_BUCKET_NAME not set; skipping bucket-level check"
fi
# --- 4. Linear Void admin login ---
echo ""
echo "-- Linear Void admin login --"
admin_user="$(get_val ADMIN_USERNAME)"
admin_pass="$(get_val ADMIN_PASSWORD)"
if [[ -n "$admin_user" && -n "$admin_pass" ]]; then
# Hit the chat backend directly (public origin is caught by nginx SPA fallback).
url="http://${TARGET}:3000/api/admin/login"
body="{\"username\":\"$admin_user\",\"password\":\"$admin_pass\"}"
wrong_body="{\"username\":\"$admin_user\",\"password\":\"__definitely_wrong__\"}"
ok_code="$(docker run --rm curlimages/curl:latest -sS --max-time "$TIMEOUT" -o /dev/null -w '%{http_code}' -X POST -H 'Content-Type: application/json' -d "$body" "$url" 2>/dev/null | tr -d '[:space:]')"
wrong_code="$(docker run --rm curlimages/curl:latest -sS --max-time "$TIMEOUT" -o /dev/null -w '%{http_code}' -X POST -H 'Content-Type: application/json' -d "$wrong_body" "$url" 2>/dev/null | tr -d '[:space:]')"
if [[ "$ok_code" == "200" && "$wrong_code" == "401" ]]; then ok "Admin credentials valid (correct=200, wrong=401)"
else fail "Admin login unexpected (correct=$ok_code, wrong=$wrong_code)"; fi
else
warn "ADMIN_USERNAME / ADMIN_PASSWORD not set; skipping admin check"
fi
# ---------------------------------------------------------------------------
echo ""
if [[ "$FAILED" -ne 0 ]]; then echo "RESULT: FAILED"; exit 1; fi
echo "RESULT: OK (no failing checks)"
exit 0