fix(smoke): support separate actuator target (#689)

Signed-off-by: ShinyHero666 <160204855+ShinyHero666@users.noreply.github.com>
This commit is contained in:
ShinyHero666 2026-08-26 10:23:31 +08:00 committed by GitHub
parent 7599dd0ca9
commit 470e79d6d2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 115 additions and 11 deletions

View file

@ -410,6 +410,18 @@ Run it against a local backend:
./scripts/smoke-test.sh http://localhost:8080
```
Local Compose and staging runs can keep using one backend URL. For an ingress
deployment where the public URL exposes application APIs but keeps Actuator on
the backend service, set a separate Actuator target:
```bash
ACTUATOR_BASE_URL=http://skillhub-server:8080 \
./scripts/smoke-test.sh https://skillhub.example.com
```
The health check requires an Actuator JSON response, so an HTML SPA fallback is
reported as a routing or target error instead of a successful health response.
Admin label-management smoke checks run only when current admin credentials are
supplied explicitly:

View file

@ -2,16 +2,18 @@
set -euo pipefail
BASE_URL="${1:-http://localhost:8080}"
ACTUATOR_BASE_URL="${ACTUATOR_BASE_URL:-$BASE_URL}"
PASS=0
FAIL=0
COOKIE_JAR="$(mktemp)"
TMP_DIR="$(mktemp -d)"
COOKIE_JAR="$TMP_DIR/cookies"
USERNAME="smoketest_$(date +%s)"
EMAIL="${USERNAME}@example.com"
PASSWORD="Smoke@2026"
NEW_PASSWORD="Smoke@2027"
cleanup() {
rm -f "$COOKIE_JAR"
rm -rf "$TMP_DIR"
}
trap cleanup EXIT
@ -31,6 +33,56 @@ check() {
fi
}
check_health() {
local desc="$1"
local url="$2"
local body_file="$TMP_DIR/health-body"
local result
local status
local content_type
result="$(curl --retry 3 --retry-delay 1 --max-time 10 -sS -o "$body_file" \
-w "%{http_code}|%{content_type}" "$url" || true)"
status="${result%%|*}"
content_type="${result#*|}"
if [[ "$content_type" == text/html* ]]; then
echo "FAIL: $desc (routing/target error: received $content_type from $url)"
FAIL=$((FAIL + 1))
elif [[ "$status" == "200" \
&& ( "$content_type" == application/json* || "$content_type" == application/*+json* ) \
&& -f "$body_file" \
&& "$(grep -Ec '"status"[[:space:]]*:' "$body_file" || true)" -gt 0 ]]; then
echo "PASS: $desc (HTTP $status, $content_type)"
PASS=$((PASS + 1))
else
echo "FAIL: $desc (expected HTTP 200 actuator JSON, got HTTP $status, ${content_type:-no content type})"
FAIL=$((FAIL + 1))
fi
}
check_protected_actuator() {
local desc="$1"
local url="$2"
local result
local status
local content_type
result="$(curl --retry 3 --retry-delay 1 --max-time 10 -sS -o /dev/null \
-w "%{http_code}|%{content_type}" "$url" || true)"
status="${result%%|*}"
content_type="${result#*|}"
if [[ "$content_type" == text/html* ]]; then
echo "FAIL: $desc (routing/target error: received $content_type from $url)"
FAIL=$((FAIL + 1))
elif [[ "$status" == "401" ]]; then
echo "PASS: $desc (HTTP $status)"
PASS=$((PASS + 1))
else
echo "FAIL: $desc (expected 401, got $status)"
FAIL=$((FAIL + 1))
fi
}
finish() {
echo
echo "Results: $PASS passed, $FAIL failed"
@ -38,11 +90,12 @@ finish() {
}
echo "=== SkillHub Smoke Test ==="
echo "Target: $BASE_URL"
echo "API target: $BASE_URL"
echo "Actuator target: $ACTUATOR_BASE_URL"
echo
check "Health endpoint" "$BASE_URL/actuator/health" "200"
check "Prometheus metrics requires auth" "$BASE_URL/actuator/prometheus" "401"
check_health "Health endpoint" "$ACTUATOR_BASE_URL/actuator/health"
check_protected_actuator "Prometheus metrics requires auth" "$ACTUATOR_BASE_URL/actuator/prometheus"
check "Namespaces API requires auth" "$BASE_URL/api/v1/namespaces" "401"
check "Auth required" "$BASE_URL/api/v1/auth/me" "401"

View file

@ -26,6 +26,7 @@ data=""
cookie_in=""
cookie_out=""
write_code=false
write_format=""
output_file=""
while (($#)); do
case "$1" in
@ -47,6 +48,7 @@ while (($#)); do
;;
-w)
write_code=true
write_format="$2"
shift 2
;;
-o)
@ -76,8 +78,16 @@ fi
printf '%s\n' "$method $url $data" >>"${SMOKE_CURL_LOG:?SMOKE_CURL_LOG is required}"
status=200
content_type="application/json"
body='{}'
case "$url" in
*/actuator/health) status=200 ;;
https://public.example/actuator/health|https://public.example/actuator/prometheus)
content_type="text/html"
body='<html>SkillHub</html>'
;;
*/actuator/health)
body='{"status":"UP"}'
;;
*/actuator/prometheus) status=401 ;;
*/api/v1/namespaces)
if [[ -n "$cookie_in" && -f "$cookie_in.session" ]]; then status=200; else status=401; fi
@ -108,24 +118,35 @@ case "$url" in
esac
if [[ "$output_file" != "/dev/null" && -n "$output_file" ]]; then
printf '{}\n' >"$output_file"
printf '%s\n' "$body" >"$output_file"
fi
if [[ "$write_code" == true ]]; then
printf '%s' "$status"
if [[ "$write_format" == *content_type* ]]; then
printf '%s|%s' "$status" "$content_type"
else
printf '%s' "$status"
fi
fi
EOF
chmod +x "$TMP_DIR/bin/curl"
run_smoke() {
run_smoke_at() {
local name="$1"
shift
local base_url="$2"
shift 2
local log="$TMP_DIR/$name.curl.log"
local out="$TMP_DIR/$name.out"
local status=0
env PATH="$TMP_DIR/bin:$PATH" SMOKE_CURL_LOG="$log" "$@" "$SMOKE_SCRIPT" http://skillhub.test >"$out" 2>&1 || status=$?
env PATH="$TMP_DIR/bin:$PATH" SMOKE_CURL_LOG="$log" "$@" "$SMOKE_SCRIPT" "$base_url" >"$out" 2>&1 || status=$?
printf '%s\n' "$status"
}
run_smoke() {
local name="$1"
shift
run_smoke_at "$name" http://skillhub.test "$@"
}
status="$(run_smoke skip-admin env)"
[[ "$status" == "0" ]] || fail "default smoke without admin credentials should pass"
grep -Fq "SKIP: Admin label management" "$TMP_DIR/skip-admin.out" \
@ -153,4 +174,22 @@ if grep -Fq 'ChangeMe!2026' "$TMP_DIR/explicit-admin.curl.log"; then
fail "admin login must not fall back to the bootstrap default password"
fi
status="$(run_smoke_at split-targets https://public.example env \
ACTUATOR_BASE_URL=http://actuator.internal:8080 SMOKE_ADMIN_CHECKS=false)"
[[ "$status" == "0" ]] || fail "split public and actuator targets should pass"
grep -Fq "GET http://actuator.internal:8080/actuator/health" "$TMP_DIR/split-targets.curl.log" \
|| fail "health check should use ACTUATOR_BASE_URL"
grep -Fq "GET http://actuator.internal:8080/actuator/prometheus" "$TMP_DIR/split-targets.curl.log" \
|| fail "Prometheus check should use ACTUATOR_BASE_URL"
if grep -Fq "https://public.example/actuator/" "$TMP_DIR/split-targets.curl.log"; then
fail "actuator checks must not use the public API target when ACTUATOR_BASE_URL is set"
fi
grep -Fq "GET https://public.example/api/v1/auth/me" "$TMP_DIR/split-targets.curl.log" \
|| fail "application API checks should continue using BASE_URL"
status="$(run_smoke_at html-fallback https://public.example env SMOKE_ADMIN_CHECKS=false)"
[[ "$status" != "0" ]] || fail "HTML SPA fallback must not pass as actuator health"
grep -Fq "routing/target error: received text/html" "$TMP_DIR/html-fallback.out" \
|| fail "HTML fallback should produce an actionable routing/target error"
echo "smoke-test-admin-mode-test passed"