mirror of
https://github.com/iflytek/skillhub.git
synced 2026-08-27 11:14:59 +00:00
fix(smoke): support separate actuator target (#689)
Signed-off-by: ShinyHero666 <160204855+ShinyHero666@users.noreply.github.com>
This commit is contained in:
parent
7599dd0ca9
commit
470e79d6d2
3 changed files with 115 additions and 11 deletions
12
README.md
12
README.md
|
|
@ -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:
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue