tests: тестовые ресурсы с префиксом test-/t-, ns fission-test-*, guard в cleanup

This commit is contained in:
“Naeel”
2026-05-03 17:59:12 +04:00
parent 47759b5231
commit cf475d0d2d
10 changed files with 102 additions and 73 deletions
+30 -10
View File
@@ -16,13 +16,32 @@ kube_exec() {
fi
}
# Зеркало логики Go NamespaceForSub:
# sub начинается с "test-" → "fission-test-" + sha256[:8*2]
# иначе → "fission-" + sha256[:8*2]
namespace_for_sub() {
printf '%s' "$1" | sha256sum | awk '{print "fission-" substr($1, 1, 16)}'
local sub="$1"
local hash
hash=$(printf '%s' "$sub" | sha256sum | awk '{print substr($1, 1, 16)}')
if [[ "$sub" == test-* ]]; then
echo "fission-test-${hash}"
else
echo "fission-${hash}"
fi
}
# ⛔ АБСОЛЮТНЫЙ GUARD: удалять ТОЛЬКО namespace-ы вида fission-test-*
# Всё остальное — немедленный выход с ошибкой
delete_ns() {
local ns="$1"
[ -n "$ns" ] || return 0
# ЖЁСТКАЯ ЗАЩИТА: только fission-test-* разрешено удалять
if [[ "$ns" != fission-test-* ]]; then
echo "⛔ ОТКАЗ: '$ns' не является тестовым namespace (должно начинаться с 'fission-test-')" >&2
return 1
fi
if [ "${KUBECTL_DIRECT:-0}" = "1" ]; then
kubectl delete namespace "$ns" --wait=false >/dev/null 2>&1 || true
else
@@ -31,15 +50,16 @@ delete_ns() {
echo "cleanup namespace: ${ns}"
}
delete_all_console_managed() {
# --all-test: удалить все namespace-ы с лейблом fission-console/env=test
# (только fission-test-* по определению)
delete_all_test() {
local ns_list
if [ "${KUBECTL_DIRECT:-0}" = "1" ]; then
ns_list=$(kubectl get ns -l managed-by=fission-console -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' 2>/dev/null || true)
ns_list=$(kubectl get ns -l 'fission-console/env=test' --no-headers \
-o custom-columns=":metadata.name" 2>/dev/null || true)
else
ns_list=$(ssh "${SSH_ARGS[@]}" '
set -e
kubectl get ns -l managed-by=fission-console -o jsonpath="{range .items[*]}{.metadata.name}{"\n"}{end}" 2>/dev/null || true
' )
ns_list=$(ssh "${SSH_ARGS[@]}" \
'kubectl get ns -l "fission-console/env=test" --no-headers -o custom-columns=":metadata.name" 2>/dev/null || true')
fi
printf '%s\n' "$ns_list" | while IFS= read -r ns; do
[ -n "$ns" ] || continue
@@ -48,12 +68,12 @@ kubectl get ns -l managed-by=fission-console -o jsonpath="{range .items[*]}{.met
}
if [ "$#" -eq 0 ]; then
echo "usage: $0 SUB [SUB ...] | --all-console-managed" >&2
echo "usage: $0 SUB [SUB ...] | --all-test" >&2
exit 1
fi
if [ "$1" = "--all-console-managed" ]; then
delete_all_console_managed
if [ "$1" = "--all-test" ]; then
delete_all_test
exit 0
fi
+1 -1
View File
@@ -11,7 +11,7 @@ source "${ROOT_DIR}/lib.sh"
NS_CLEANUP_SCRIPT="${ROOT_DIR}/cleanup_test_namespaces.sh"
RUN_ID=$(mk_run_id)
SUB="auth-test-${RUN_ID}@test.local"
SUB="test-auth-${RUN_ID}@test.local"
cleanup() {
if [ -x "$NS_CLEANUP_SCRIPT" ]; then
+10 -10
View File
@@ -9,7 +9,7 @@ source "${ROOT_DIR}/lib.sh"
NS_CLEANUP_SCRIPT="${ROOT_DIR}/cleanup_test_namespaces.sh"
RUN_ID=$(mk_run_id)
SUB="crud-${RUN_ID}@test.local"
SUB="test-crud-${RUN_ID}@test.local"
cleanup() {
if [ -x "$NS_CLEANUP_SCRIPT" ]; then
@@ -31,14 +31,14 @@ echo ""
echo ">>> CREATE: базовый nodejs → 201"
R=$(curl -s -w "\n%{http_code}" -X POST "${BASE}/functions" \
-H "X-Auth-Token: ${SUB}" -H "Content-Type: application/json" \
-d "{\"name\":\"crud-fn-${RUN_ID}\",\"language\":\"nodejs\",\"code\":$(printf '%s' "$JS_CODE" | json_escape)}")
-d "{\"name\":\"t-crud-fn-${RUN_ID}\",\"language\":\"nodejs\",\"code\":$(printf '%s' "$JS_CODE" | json_escape)}")
CODE=$(echo "$R" | tail -1)
BODY=$(echo "$R" | sed '$d')
check_http "$CODE" "201" "CREATE nodejs → 201"
FN_NAME=$(json_field "$BODY" name)
FN_ROUTE=$(json_field "$BODY" route)
FN_PKG=$(json_field "$BODY" package)
[ "$FN_NAME" = "crud-fn-${RUN_ID}" ] && pass "CREATE: name в ответе" || fail "CREATE: name='$FN_NAME'"
[ "$FN_NAME" = "t-crud-fn-${RUN_ID}" ] && pass "CREATE: name в ответе" || fail "CREATE: name='$FN_NAME'"
printf '%s' "$FN_ROUTE" | grep -q '/' && pass "CREATE: route непустой" || fail "CREATE: route='$FN_ROUTE'"
[ -n "$FN_PKG" ] && pass "CREATE: package непустой" || fail "CREATE: package пустой"
@@ -46,7 +46,7 @@ echo ""
echo ">>> CREATE: дубликат → 409"
R=$(curl -s -w "\n%{http_code}" -X POST "${BASE}/functions" \
-H "X-Auth-Token: ${SUB}" -H "Content-Type: application/json" \
-d "{\"name\":\"crud-fn-${RUN_ID}\",\"language\":\"nodejs\",\"code\":$(printf '%s' "$JS_CODE" | json_escape)}")
-d "{\"name\":\"t-crud-fn-${RUN_ID}\",\"language\":\"nodejs\",\"code\":$(printf '%s' "$JS_CODE" | json_escape)}")
check_http "$(echo "$R" | tail -1)" "409" "CREATE дубликат → 409"
echo ""
@@ -158,13 +158,13 @@ COUNT=$(json_len "$BODY")
echo ""
echo ">>> GET: /functions/{name} → 200"
R=$(curl -s -w "\n%{http_code}" "${BASE}/functions/crud-fn-${RUN_ID}" \
R=$(curl -s -w "\n%{http_code}" "${BASE}/functions/t-crud-fn-${RUN_ID}" \
-H "X-Auth-Token: ${SUB}")
CODE=$(echo "$R" | tail -1)
BODY=$(echo "$R" | sed '$d')
check_http "$CODE" "200" "GET /functions/crud-fn-${RUN_ID} → 200"
check_http "$CODE" "200" "GET /functions/t-crud-fn-${RUN_ID} → 200"
GOT_NAME=$(json_field "$BODY" name)
[ "$GOT_NAME" = "crud-fn-${RUN_ID}" ] && pass "GET: name совпадает" || fail "GET: name='$GOT_NAME'"
[ "$GOT_NAME" = "t-crud-fn-${RUN_ID}" ] && pass "GET: name совпадает" || fail "GET: name='$GOT_NAME'"
GOT_ENV=$(json_field "$BODY" environment)
[ -n "$GOT_ENV" ] && pass "GET: environment непустой ($GOT_ENV)" || fail "GET: environment пустой"
@@ -178,7 +178,7 @@ check_http "$(echo "$R" | tail -1)" "404" "GET несуществующая →
echo ""
echo ">>> DELETE: /functions/{name} → 200"
R=$(curl -s -w "\n%{http_code}" -X DELETE "${BASE}/functions/crud-fn-${RUN_ID}" \
R=$(curl -s -w "\n%{http_code}" -X DELETE "${BASE}/functions/t-crud-fn-${RUN_ID}" \
-H "X-Auth-Token: ${SUB}")
CODE=$(echo "$R" | tail -1)
BODY=$(echo "$R" | sed '$d')
@@ -188,13 +188,13 @@ DELETED=$(json_field "$BODY" deleted)
echo ""
echo ">>> DELETE: повторное удаление → 404"
R=$(curl -s -w "\n%{http_code}" -X DELETE "${BASE}/functions/crud-fn-${RUN_ID}" \
R=$(curl -s -w "\n%{http_code}" -X DELETE "${BASE}/functions/t-crud-fn-${RUN_ID}" \
-H "X-Auth-Token: ${SUB}")
check_http "$(echo "$R" | tail -1)" "404" "DELETE повторное → 404"
echo ""
echo ">>> GET: после DELETE → 404"
R=$(curl -s -w "\n%{http_code}" "${BASE}/functions/crud-fn-${RUN_ID}" \
R=$(curl -s -w "\n%{http_code}" "${BASE}/functions/t-crud-fn-${RUN_ID}" \
-H "X-Auth-Token: ${SUB}")
check_http "$(echo "$R" | tail -1)" "404" "GET после DELETE → 404"
+3 -3
View File
@@ -11,9 +11,9 @@ source "${ROOT_DIR}/lib.sh"
RUN_ID=$(mk_run_id)
# Используем прогретый namespace — fission router его знает.
SUB="livetest@test.local"
FN_NODE="node-fn-${RUN_ID}"
FN_PY="py-fn-${RUN_ID}"
SUB="test-livetest@test.local"
FN_NODE="t-node-fn-${RUN_ID}"
FN_PY="t-py-fn-${RUN_ID}"
cleanup() {
# Удаляем только конкретные функции через API, не весь namespace.
+34 -34
View File
@@ -9,8 +9,8 @@ source "${ROOT_DIR}/lib.sh"
NS_CLEANUP_SCRIPT="${ROOT_DIR}/cleanup_test_namespaces.sh"
RUN_ID=$(mk_run_id)
ALICE="alice-${RUN_ID}@test.local"
BOB="bob-${RUN_ID}@test.local"
ALICE="test-alice-${RUN_ID}@test.local"
BOB="test-bob-${RUN_ID}@test.local"
cleanup() {
if [ -x "$NS_CLEANUP_SCRIPT" ]; then
@@ -32,43 +32,43 @@ echo ""
echo ">>> Alice создаёт функцию"
R=$(curl -s -w "\n%{http_code}" -X POST "${BASE}/functions" \
-H "X-Auth-Token: ${ALICE}" -H "Content-Type: application/json" \
-d "{\"name\":\"alice-fn\",\"language\":\"nodejs\",\"code\":$(printf '%s' "$JS_CODE" | json_escape)}")
check_http "$(echo "$R" | tail -1)" "201" "Alice CREATE alice-fn → 201"
-d "{\"name\":\"t-alice-fn\",\"language\":\"nodejs\",\"code\":$(printf '%s' "$JS_CODE" | json_escape)}")
check_http "$(echo "$R" | tail -1)" "201" "Alice CREATE t-alice-fn → 201"
# ── Bob не может получить функцию Alice ──────────────────────────────────────
echo ""
echo ">>> Bob GET alice-fn → 404"
R=$(curl -s -w "\n%{http_code}" "${BASE}/functions/alice-fn" \
echo ">>> Bob GET t-alice-fn → 404"
R=$(curl -s -w "\n%{http_code}" "${BASE}/functions/t-alice-fn" \
-H "X-Auth-Token: ${BOB}")
check_http "$(echo "$R" | tail -1)" "404" "Bob GET alice-fn → 404"
check_http "$(echo "$R" | tail -1)" "404" "Bob GET t-alice-fn → 404"
echo ""
echo ">>> Bob DELETE alice-fn → 404"
R=$(curl -s -w "\n%{http_code}" -X DELETE "${BASE}/functions/alice-fn" \
echo ">>> Bob DELETE t-alice-fn → 404"
R=$(curl -s -w "\n%{http_code}" -X DELETE "${BASE}/functions/t-alice-fn" \
-H "X-Auth-Token: ${BOB}")
check_http "$(echo "$R" | tail -1)" "404" "Bob DELETE alice-fn → 404"
check_http "$(echo "$R" | tail -1)" "404" "Bob DELETE t-alice-fn → 404"
echo ""
echo ">>> Bob PUT alice-fn/code → 404"
R=$(curl -s -w "\n%{http_code}" -X PUT "${BASE}/functions/alice-fn/code" \
echo ">>> Bob PUT t-alice-fn/code → 404"
R=$(curl -s -w "\n%{http_code}" -X PUT "${BASE}/functions/t-alice-fn/code" \
-H "X-Auth-Token: ${BOB}" -H "Content-Type: application/json" \
-d '{"code":"module.exports = async () => ({ body: \"hacked\" });"}')
check_http "$(echo "$R" | tail -1)" "404" "Bob PUT alice-fn/code → 404"
check_http "$(echo "$R" | tail -1)" "404" "Bob PUT t-alice-fn/code → 404"
echo ""
echo ">>> Bob INVOKE alice-fn → 404"
R=$(curl -s -w "\n%{http_code}" -X POST "${BASE}/functions/alice-fn/invoke" \
echo ">>> Bob INVOKE t-alice-fn → 404"
R=$(curl -s -w "\n%{http_code}" -X POST "${BASE}/functions/t-alice-fn/invoke" \
-H "X-Auth-Token: ${BOB}" -H "Content-Type: application/json" -d '{}')
check_http "$(echo "$R" | tail -1)" "404" "Bob INVOKE alice-fn → 404"
check_http "$(echo "$R" | tail -1)" "404" "Bob INVOKE t-alice-fn → 404"
# ── Alice убеждается что её функция цела ────────────────────────────────────
echo ""
echo ">>> Alice GET alice-fn → 200 (не повреждена)"
R=$(curl -s -w "\n%{http_code}" "${BASE}/functions/alice-fn" \
echo ">>> Alice GET t-alice-fn → 200 (не повреждена)"
R=$(curl -s -w "\n%{http_code}" "${BASE}/functions/t-alice-fn" \
-H "X-Auth-Token: ${ALICE}")
check_http "$(echo "$R" | tail -1)" "200" "Alice GET alice-fn → 200"
check_http "$(echo "$R" | tail -1)" "200" "Alice GET t-alice-fn → 200"
# ── LIST изоляция ────────────────────────────────────────────────────────────
@@ -78,51 +78,51 @@ echo ">>> LIST изоляция: Alice и Bob видят только свои
# Bob создаёт свою функцию
curl -s -X POST "${BASE}/functions" \
-H "X-Auth-Token: ${BOB}" -H "Content-Type: application/json" \
-d "{\"name\":\"bob-fn\",\"language\":\"nodejs\",\"code\":$(printf '%s' "$JS_CODE" | json_escape)}" > /dev/null
-d "{\"name\":\"t-bob-fn\",\"language\":\"nodejs\",\"code\":$(printf '%s' "$JS_CODE" | json_escape)}" > /dev/null
sleep 1
ALICE_LIST=$(curl -s "${BASE}/functions" -H "X-Auth-Token: ${ALICE}")
BOB_LIST=$(curl -s "${BASE}/functions" -H "X-Auth-Token: ${BOB}")
# Alice видит alice-fn но не bob-fn
# Alice видит t-alice-fn но не t-bob-fn
ALICE_COUNT=$(json_len "$ALICE_LIST")
ALICE_HAS_OWN=$(printf '%s' "$ALICE_LIST" | python3 -c "
import json, sys
try:
fns = json.load(sys.stdin)
print(sum(1 for f in fns if f.get('metadata',{}).get('name','') == 'alice-fn'))
print(sum(1 for f in fns if f.get('metadata',{}).get('name','') == 't-t-alice-fn'))
except:
print(0)" 2>/dev/null)
ALICE_HAS_BOB=$(printf '%s' "$ALICE_LIST" | python3 -c "
import json, sys
try:
fns = json.load(sys.stdin)
print(sum(1 for f in fns if f.get('metadata',{}).get('name','') == 'bob-fn'))
print(sum(1 for f in fns if f.get('metadata',{}).get('name','') == 't-t-bob-fn'))
except:
print(0)" 2>/dev/null)
[ "${ALICE_HAS_OWN:-0}" -ge 1 ] && pass "Alice LIST содержит alice-fn" || fail "Alice LIST не содержит alice-fn (count=$ALICE_COUNT)"
[ "${ALICE_HAS_BOB:-0}" -eq 0 ] && pass "Alice LIST не содержит bob-fn" || fail "Alice LIST содержит bob-fn — УТЕЧКА ДАННЫХ!"
[ "${ALICE_HAS_OWN:-0}" -ge 1 ] && pass "Alice LIST содержит t-alice-fn" || fail "Alice LIST не содержит t-alice-fn (count=$ALICE_COUNT)"
[ "${ALICE_HAS_BOB:-0}" -eq 0 ] && pass "Alice LIST не содержит t-bob-fn" || fail "Alice LIST содержит t-bob-fn — УТЕЧКА ДАННЫХ!"
# Bob видит bob-fn но не alice-fn
# Bob видит t-bob-fn но не t-alice-fn
BOB_HAS_OWN=$(printf '%s' "$BOB_LIST" | python3 -c "
import json, sys
try:
fns = json.load(sys.stdin)
print(sum(1 for f in fns if f.get('metadata',{}).get('name','') == 'bob-fn'))
print(sum(1 for f in fns if f.get('metadata',{}).get('name','') == 't-t-bob-fn'))
except:
print(0)" 2>/dev/null)
BOB_HAS_ALICE=$(printf '%s' "$BOB_LIST" | python3 -c "
import json, sys
try:
fns = json.load(sys.stdin)
print(sum(1 for f in fns if f.get('metadata',{}).get('name','') == 'alice-fn'))
print(sum(1 for f in fns if f.get('metadata',{}).get('name','') == 't-t-alice-fn'))
except:
print(0)" 2>/dev/null)
[ "${BOB_HAS_OWN:-0}" -ge 1 ] && pass "Bob LIST содержит bob-fn" || fail "Bob LIST не содержит bob-fn"
[ "${BOB_HAS_ALICE:-0}" -eq 0 ] && pass "Bob LIST не содержит alice-fn" || fail "Bob LIST содержит alice-fn — УТЕЧКА ДАННЫХ!"
[ "${BOB_HAS_OWN:-0}" -ge 1 ] && pass "Bob LIST содержит t-bob-fn" || fail "Bob LIST не содержит t-bob-fn"
[ "${BOB_HAS_ALICE:-0}" -eq 0 ] && pass "Bob LIST не содержит t-alice-fn" || fail "Bob LIST содержит t-alice-fn — УТЕЧКА ДАННЫХ!"
# ── Route изоляция ───────────────────────────────────────────────────────────
@@ -133,7 +133,7 @@ import json, sys
try:
fns = json.load(sys.stdin)
for f in fns:
if f.get('metadata',{}).get('name','') == 'alice-fn':
if f.get('metadata',{}).get('name','') == 't-t-alice-fn':
print(f.get('spec',{}).get('relativeurl',''))
break
except:
@@ -144,15 +144,15 @@ import json, sys
try:
fns = json.load(sys.stdin)
for f in fns:
if f.get('metadata',{}).get('name','') == 'bob-fn':
if f.get('metadata',{}).get('name','') == 't-t-bob-fn':
print(f.get('spec',{}).get('relativeurl',''))
break
except:
print('')" 2>/dev/null)
# Проверяем через GET (возвращает route)
ALICE_GET=$(curl -s "${BASE}/functions/alice-fn" -H "X-Auth-Token: ${ALICE}")
BOB_GET=$(curl -s "${BASE}/functions/bob-fn" -H "X-Auth-Token: ${BOB}")
ALICE_GET=$(curl -s "${BASE}/functions/t-alice-fn" -H "X-Auth-Token: ${ALICE}")
BOB_GET=$(curl -s "${BASE}/functions/t-bob-fn" -H "X-Auth-Token: ${BOB}")
ROUTE_A=$(json_field "$ALICE_GET" route)
ROUTE_B=$(json_field "$BOB_GET" route)
[ "$ROUTE_A" != "$ROUTE_B" ] && [ -n "$ROUTE_A" ] && [ -n "$ROUTE_B" ] \
+3 -3
View File
@@ -13,17 +13,17 @@ NS_CLEANUP_SCRIPT="${ROOT_DIR}/cleanup_test_namespaces.sh"
RUN_ID=$(mk_run_id)
COUNT="${1:-8}"
TMP=$(mktemp -d)
INVOKE_SUB="livetest@test.local"
INVOKE_SUB="test-livetest@test.local"
INVOKE_COUNT=8
declare -a SUBS=()
for i in $(seq 1 "$COUNT"); do
SUBS+=("stress-${RUN_ID}-u${i}@test.local")
SUBS+=("test-stress-${RUN_ID}-u${i}@test.local")
done
declare -a INVOKE_FNS=()
for i in $(seq 1 "$INVOKE_COUNT"); do
INVOKE_FNS+=("sinv-${RUN_ID}-${i}")
INVOKE_FNS+=("t-sinv-${RUN_ID}-${i}")
done
cleanup() {
+3 -3
View File
@@ -10,7 +10,7 @@ source "${ROOT_DIR}/lib.sh"
NS_CLEANUP_SCRIPT="${ROOT_DIR}/cleanup_test_namespaces.sh"
RUN_ID=$(mk_run_id)
SUB="ttl-${RUN_ID}@test.local"
SUB="test-ttl-${RUN_ID}@test.local"
cleanup() {
if [ -x "$NS_CLEANUP_SCRIPT" ]; then
@@ -32,7 +32,7 @@ echo ""
echo ">>> CREATE без TTL → expires_at отсутствует"
R=$(curl -s -X POST "${BASE}/functions" \
-H "X-Auth-Token: ${SUB}" -H "Content-Type: application/json" \
-d "{\"name\":\"nttl-fn\",\"language\":\"nodejs\",\"code\":$(printf '%s' "$JS_CODE" | json_escape)}")
-d "{\"name\":\"t-nttl-fn\",\"language\":\"nodejs\",\"code\":$(printf '%s' "$JS_CODE" | json_escape)}")
CODE_HTTP=$(printf '%s' "$R" | python3 -c "import sys; lines=sys.stdin.read().split('\n'); print(lines[-1] if lines else '')" 2>/dev/null || echo "?")
EXPIRES=$(json_field "$R" expires_at)
[ -z "$EXPIRES" ] && pass "CREATE без TTL: expires_at отсутствует" || fail "CREATE без TTL: expires_at='$EXPIRES'"
@@ -77,7 +77,7 @@ for badttl in "99z" "abc" "0d" "-1h" ""; do
if [ -z "$badttl" ]; then continue; fi
R=$(curl -s -w "\n%{http_code}" -X POST "${BASE}/functions" \
-H "X-Auth-Token: ${SUB}" -H "Content-Type: application/json" \
-d "{\"name\":\"badttl-fn\",\"language\":\"nodejs\",\"code\":\"x\",\"ttl\":\"${badttl}\"}")
-d "{\"name\":\"t-badttl-fn\",\"language\":\"nodejs\",\"code\":\"x\",\"ttl\":\"${badttl}\"}")
CODE=$(echo "$R" | tail -1)
[ "$CODE" = "400" ] && pass "TTL='$badttl' → 400" || fail "TTL='$badttl' → got $CODE"
done
+2 -2
View File
@@ -11,8 +11,8 @@ ROOT_DIR=$(cd "$(dirname "$0")" && pwd)
source "${ROOT_DIR}/lib.sh"
RUN_ID=$(mk_run_id)
SUB="livetest@test.local"
FN="upd-fn-${RUN_ID}"
SUB="test-livetest@test.local"
FN="t-upd-fn-${RUN_ID}"
cleanup() {
curl -s -X DELETE "${BASE}/functions/${FN}" -H "X-Auth-Token: ${SUB}" > /dev/null 2>&1 || true