tests: тестовые ресурсы с префиксом test-/t-, ns fission-test-*, guard в cleanup
This commit is contained in:
@@ -25,10 +25,14 @@ type UserIdentity struct {
|
|||||||
Email string // email — опционально, для отображения в UI
|
Email string // email — опционально, для отображения в UI
|
||||||
}
|
}
|
||||||
|
|
||||||
// NamespaceForSub вычисляет детерминированный K8s namespace из Sub:
|
// NamespaceForSub вычисляет детерминированный K8s namespace из Sub.
|
||||||
// "fission-" + hex(SHA256(sub)[:8])
|
// Если sub начинается с "test-" → "fission-test-" + hex(SHA256(sub)[:8])
|
||||||
|
// Иначе → "fission-" + hex(SHA256(sub)[:8])
|
||||||
func NamespaceForSub(sub string) string {
|
func NamespaceForSub(sub string) string {
|
||||||
h := sha256.Sum256([]byte(sub))
|
h := sha256.Sum256([]byte(sub))
|
||||||
|
if strings.HasPrefix(sub, "test-") {
|
||||||
|
return "fission-test-" + hex.EncodeToString(h[:8])
|
||||||
|
}
|
||||||
return "fission-" + hex.EncodeToString(h[:8])
|
return "fission-" + hex.EncodeToString(h[:8])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
@@ -37,16 +38,20 @@ import (
|
|||||||
// (не ClusterRoleBinding) безопасен — даёт полный доступ только внутри NS.
|
// (не ClusterRoleBinding) безопасен — даёт полный доступ только внутри NS.
|
||||||
func SetupFissionNamespace(ctx context.Context, dyn dynamic.Interface, ns string) error {
|
func SetupFissionNamespace(ctx context.Context, dyn dynamic.Interface, ns string) error {
|
||||||
// 1. Namespace
|
// 1. Namespace
|
||||||
|
labels := map[string]any{
|
||||||
|
"managed-by": "fission-console",
|
||||||
|
"fission.io/managed": "true", // Layer 1: executor NSWatcher auto-discovers this NS
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(ns, "fission-test-") {
|
||||||
|
labels["fission-console/env"] = "test"
|
||||||
|
}
|
||||||
nsObj := &unstructured.Unstructured{
|
nsObj := &unstructured.Unstructured{
|
||||||
Object: map[string]any{
|
Object: map[string]any{
|
||||||
"apiVersion": "v1",
|
"apiVersion": "v1",
|
||||||
"kind": "Namespace",
|
"kind": "Namespace",
|
||||||
"metadata": map[string]any{
|
"metadata": map[string]any{
|
||||||
"name": ns,
|
"name": ns,
|
||||||
"labels": map[string]any{
|
"labels": labels,
|
||||||
"managed-by": "fission-console",
|
|
||||||
"fission.io/managed": "true", // Layer 1: executor NSWatcher auto-discovers this NS
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,13 +16,32 @@ kube_exec() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Зеркало логики Go NamespaceForSub:
|
||||||
|
# sub начинается с "test-" → "fission-test-" + sha256[:8*2]
|
||||||
|
# иначе → "fission-" + sha256[:8*2]
|
||||||
namespace_for_sub() {
|
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() {
|
delete_ns() {
|
||||||
local ns="$1"
|
local ns="$1"
|
||||||
[ -n "$ns" ] || return 0
|
[ -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
|
if [ "${KUBECTL_DIRECT:-0}" = "1" ]; then
|
||||||
kubectl delete namespace "$ns" --wait=false >/dev/null 2>&1 || true
|
kubectl delete namespace "$ns" --wait=false >/dev/null 2>&1 || true
|
||||||
else
|
else
|
||||||
@@ -31,15 +50,16 @@ delete_ns() {
|
|||||||
echo "cleanup namespace: ${ns}"
|
echo "cleanup namespace: ${ns}"
|
||||||
}
|
}
|
||||||
|
|
||||||
delete_all_console_managed() {
|
# --all-test: удалить все namespace-ы с лейблом fission-console/env=test
|
||||||
|
# (только fission-test-* по определению)
|
||||||
|
delete_all_test() {
|
||||||
local ns_list
|
local ns_list
|
||||||
if [ "${KUBECTL_DIRECT:-0}" = "1" ]; then
|
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
|
else
|
||||||
ns_list=$(ssh "${SSH_ARGS[@]}" '
|
ns_list=$(ssh "${SSH_ARGS[@]}" \
|
||||||
set -e
|
'kubectl get ns -l "fission-console/env=test" --no-headers -o custom-columns=":metadata.name" 2>/dev/null || true')
|
||||||
kubectl get ns -l managed-by=fission-console -o jsonpath="{range .items[*]}{.metadata.name}{"\n"}{end}" 2>/dev/null || true
|
|
||||||
' )
|
|
||||||
fi
|
fi
|
||||||
printf '%s\n' "$ns_list" | while IFS= read -r ns; do
|
printf '%s\n' "$ns_list" | while IFS= read -r ns; do
|
||||||
[ -n "$ns" ] || continue
|
[ -n "$ns" ] || continue
|
||||||
@@ -48,12 +68,12 @@ kubectl get ns -l managed-by=fission-console -o jsonpath="{range .items[*]}{.met
|
|||||||
}
|
}
|
||||||
|
|
||||||
if [ "$#" -eq 0 ]; then
|
if [ "$#" -eq 0 ]; then
|
||||||
echo "usage: $0 SUB [SUB ...] | --all-console-managed" >&2
|
echo "usage: $0 SUB [SUB ...] | --all-test" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$1" = "--all-console-managed" ]; then
|
if [ "$1" = "--all-test" ]; then
|
||||||
delete_all_console_managed
|
delete_all_test
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ source "${ROOT_DIR}/lib.sh"
|
|||||||
|
|
||||||
NS_CLEANUP_SCRIPT="${ROOT_DIR}/cleanup_test_namespaces.sh"
|
NS_CLEANUP_SCRIPT="${ROOT_DIR}/cleanup_test_namespaces.sh"
|
||||||
RUN_ID=$(mk_run_id)
|
RUN_ID=$(mk_run_id)
|
||||||
SUB="auth-test-${RUN_ID}@test.local"
|
SUB="test-auth-${RUN_ID}@test.local"
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
if [ -x "$NS_CLEANUP_SCRIPT" ]; then
|
if [ -x "$NS_CLEANUP_SCRIPT" ]; then
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ source "${ROOT_DIR}/lib.sh"
|
|||||||
|
|
||||||
NS_CLEANUP_SCRIPT="${ROOT_DIR}/cleanup_test_namespaces.sh"
|
NS_CLEANUP_SCRIPT="${ROOT_DIR}/cleanup_test_namespaces.sh"
|
||||||
RUN_ID=$(mk_run_id)
|
RUN_ID=$(mk_run_id)
|
||||||
SUB="crud-${RUN_ID}@test.local"
|
SUB="test-crud-${RUN_ID}@test.local"
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
if [ -x "$NS_CLEANUP_SCRIPT" ]; then
|
if [ -x "$NS_CLEANUP_SCRIPT" ]; then
|
||||||
@@ -31,14 +31,14 @@ echo ""
|
|||||||
echo ">>> CREATE: базовый nodejs → 201"
|
echo ">>> CREATE: базовый nodejs → 201"
|
||||||
R=$(curl -s -w "\n%{http_code}" -X POST "${BASE}/functions" \
|
R=$(curl -s -w "\n%{http_code}" -X POST "${BASE}/functions" \
|
||||||
-H "X-Auth-Token: ${SUB}" -H "Content-Type: application/json" \
|
-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)
|
CODE=$(echo "$R" | tail -1)
|
||||||
BODY=$(echo "$R" | sed '$d')
|
BODY=$(echo "$R" | sed '$d')
|
||||||
check_http "$CODE" "201" "CREATE nodejs → 201"
|
check_http "$CODE" "201" "CREATE nodejs → 201"
|
||||||
FN_NAME=$(json_field "$BODY" name)
|
FN_NAME=$(json_field "$BODY" name)
|
||||||
FN_ROUTE=$(json_field "$BODY" route)
|
FN_ROUTE=$(json_field "$BODY" route)
|
||||||
FN_PKG=$(json_field "$BODY" package)
|
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'"
|
printf '%s' "$FN_ROUTE" | grep -q '/' && pass "CREATE: route непустой" || fail "CREATE: route='$FN_ROUTE'"
|
||||||
[ -n "$FN_PKG" ] && pass "CREATE: package непустой" || fail "CREATE: package пустой"
|
[ -n "$FN_PKG" ] && pass "CREATE: package непустой" || fail "CREATE: package пустой"
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ echo ""
|
|||||||
echo ">>> CREATE: дубликат → 409"
|
echo ">>> CREATE: дубликат → 409"
|
||||||
R=$(curl -s -w "\n%{http_code}" -X POST "${BASE}/functions" \
|
R=$(curl -s -w "\n%{http_code}" -X POST "${BASE}/functions" \
|
||||||
-H "X-Auth-Token: ${SUB}" -H "Content-Type: application/json" \
|
-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"
|
check_http "$(echo "$R" | tail -1)" "409" "CREATE дубликат → 409"
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
@@ -158,13 +158,13 @@ COUNT=$(json_len "$BODY")
|
|||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo ">>> GET: /functions/{name} → 200"
|
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}")
|
-H "X-Auth-Token: ${SUB}")
|
||||||
CODE=$(echo "$R" | tail -1)
|
CODE=$(echo "$R" | tail -1)
|
||||||
BODY=$(echo "$R" | sed '$d')
|
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=$(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)
|
GOT_ENV=$(json_field "$BODY" environment)
|
||||||
[ -n "$GOT_ENV" ] && pass "GET: environment непустой ($GOT_ENV)" || fail "GET: 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 ""
|
||||||
echo ">>> DELETE: /functions/{name} → 200"
|
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}")
|
-H "X-Auth-Token: ${SUB}")
|
||||||
CODE=$(echo "$R" | tail -1)
|
CODE=$(echo "$R" | tail -1)
|
||||||
BODY=$(echo "$R" | sed '$d')
|
BODY=$(echo "$R" | sed '$d')
|
||||||
@@ -188,13 +188,13 @@ DELETED=$(json_field "$BODY" deleted)
|
|||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo ">>> DELETE: повторное удаление → 404"
|
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}")
|
-H "X-Auth-Token: ${SUB}")
|
||||||
check_http "$(echo "$R" | tail -1)" "404" "DELETE повторное → 404"
|
check_http "$(echo "$R" | tail -1)" "404" "DELETE повторное → 404"
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo ">>> GET: после DELETE → 404"
|
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}")
|
-H "X-Auth-Token: ${SUB}")
|
||||||
check_http "$(echo "$R" | tail -1)" "404" "GET после DELETE → 404"
|
check_http "$(echo "$R" | tail -1)" "404" "GET после DELETE → 404"
|
||||||
|
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ source "${ROOT_DIR}/lib.sh"
|
|||||||
|
|
||||||
RUN_ID=$(mk_run_id)
|
RUN_ID=$(mk_run_id)
|
||||||
# Используем прогретый namespace — fission router его знает.
|
# Используем прогретый namespace — fission router его знает.
|
||||||
SUB="livetest@test.local"
|
SUB="test-livetest@test.local"
|
||||||
FN_NODE="node-fn-${RUN_ID}"
|
FN_NODE="t-node-fn-${RUN_ID}"
|
||||||
FN_PY="py-fn-${RUN_ID}"
|
FN_PY="t-py-fn-${RUN_ID}"
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
# Удаляем только конкретные функции через API, не весь namespace.
|
# Удаляем только конкретные функции через API, не весь namespace.
|
||||||
|
|||||||
+34
-34
@@ -9,8 +9,8 @@ source "${ROOT_DIR}/lib.sh"
|
|||||||
|
|
||||||
NS_CLEANUP_SCRIPT="${ROOT_DIR}/cleanup_test_namespaces.sh"
|
NS_CLEANUP_SCRIPT="${ROOT_DIR}/cleanup_test_namespaces.sh"
|
||||||
RUN_ID=$(mk_run_id)
|
RUN_ID=$(mk_run_id)
|
||||||
ALICE="alice-${RUN_ID}@test.local"
|
ALICE="test-alice-${RUN_ID}@test.local"
|
||||||
BOB="bob-${RUN_ID}@test.local"
|
BOB="test-bob-${RUN_ID}@test.local"
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
if [ -x "$NS_CLEANUP_SCRIPT" ]; then
|
if [ -x "$NS_CLEANUP_SCRIPT" ]; then
|
||||||
@@ -32,43 +32,43 @@ echo ""
|
|||||||
echo ">>> Alice создаёт функцию"
|
echo ">>> Alice создаёт функцию"
|
||||||
R=$(curl -s -w "\n%{http_code}" -X POST "${BASE}/functions" \
|
R=$(curl -s -w "\n%{http_code}" -X POST "${BASE}/functions" \
|
||||||
-H "X-Auth-Token: ${ALICE}" -H "Content-Type: application/json" \
|
-H "X-Auth-Token: ${ALICE}" -H "Content-Type: application/json" \
|
||||||
-d "{\"name\":\"alice-fn\",\"language\":\"nodejs\",\"code\":$(printf '%s' "$JS_CODE" | json_escape)}")
|
-d "{\"name\":\"t-alice-fn\",\"language\":\"nodejs\",\"code\":$(printf '%s' "$JS_CODE" | json_escape)}")
|
||||||
check_http "$(echo "$R" | tail -1)" "201" "Alice CREATE alice-fn → 201"
|
check_http "$(echo "$R" | tail -1)" "201" "Alice CREATE t-alice-fn → 201"
|
||||||
|
|
||||||
# ── Bob не может получить функцию Alice ──────────────────────────────────────
|
# ── Bob не может получить функцию Alice ──────────────────────────────────────
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo ">>> Bob GET alice-fn → 404"
|
echo ">>> Bob GET t-alice-fn → 404"
|
||||||
R=$(curl -s -w "\n%{http_code}" "${BASE}/functions/alice-fn" \
|
R=$(curl -s -w "\n%{http_code}" "${BASE}/functions/t-alice-fn" \
|
||||||
-H "X-Auth-Token: ${BOB}")
|
-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 ""
|
||||||
echo ">>> Bob DELETE alice-fn → 404"
|
echo ">>> Bob DELETE t-alice-fn → 404"
|
||||||
R=$(curl -s -w "\n%{http_code}" -X DELETE "${BASE}/functions/alice-fn" \
|
R=$(curl -s -w "\n%{http_code}" -X DELETE "${BASE}/functions/t-alice-fn" \
|
||||||
-H "X-Auth-Token: ${BOB}")
|
-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 ""
|
||||||
echo ">>> Bob PUT alice-fn/code → 404"
|
echo ">>> Bob PUT t-alice-fn/code → 404"
|
||||||
R=$(curl -s -w "\n%{http_code}" -X PUT "${BASE}/functions/alice-fn/code" \
|
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" \
|
-H "X-Auth-Token: ${BOB}" -H "Content-Type: application/json" \
|
||||||
-d '{"code":"module.exports = async () => ({ body: \"hacked\" });"}')
|
-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 ""
|
||||||
echo ">>> Bob INVOKE alice-fn → 404"
|
echo ">>> Bob INVOKE t-alice-fn → 404"
|
||||||
R=$(curl -s -w "\n%{http_code}" -X POST "${BASE}/functions/alice-fn/invoke" \
|
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 '{}')
|
-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 убеждается что её функция цела ────────────────────────────────────
|
# ── Alice убеждается что её функция цела ────────────────────────────────────
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo ">>> Alice GET alice-fn → 200 (не повреждена)"
|
echo ">>> Alice GET t-alice-fn → 200 (не повреждена)"
|
||||||
R=$(curl -s -w "\n%{http_code}" "${BASE}/functions/alice-fn" \
|
R=$(curl -s -w "\n%{http_code}" "${BASE}/functions/t-alice-fn" \
|
||||||
-H "X-Auth-Token: ${ALICE}")
|
-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 изоляция ────────────────────────────────────────────────────────────
|
# ── LIST изоляция ────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -78,51 +78,51 @@ echo ">>> LIST изоляция: Alice и Bob видят только свои
|
|||||||
# Bob создаёт свою функцию
|
# Bob создаёт свою функцию
|
||||||
curl -s -X POST "${BASE}/functions" \
|
curl -s -X POST "${BASE}/functions" \
|
||||||
-H "X-Auth-Token: ${BOB}" -H "Content-Type: application/json" \
|
-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
|
sleep 1
|
||||||
|
|
||||||
ALICE_LIST=$(curl -s "${BASE}/functions" -H "X-Auth-Token: ${ALICE}")
|
ALICE_LIST=$(curl -s "${BASE}/functions" -H "X-Auth-Token: ${ALICE}")
|
||||||
BOB_LIST=$(curl -s "${BASE}/functions" -H "X-Auth-Token: ${BOB}")
|
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_COUNT=$(json_len "$ALICE_LIST")
|
||||||
ALICE_HAS_OWN=$(printf '%s' "$ALICE_LIST" | python3 -c "
|
ALICE_HAS_OWN=$(printf '%s' "$ALICE_LIST" | python3 -c "
|
||||||
import json, sys
|
import json, sys
|
||||||
try:
|
try:
|
||||||
fns = json.load(sys.stdin)
|
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:
|
except:
|
||||||
print(0)" 2>/dev/null)
|
print(0)" 2>/dev/null)
|
||||||
ALICE_HAS_BOB=$(printf '%s' "$ALICE_LIST" | python3 -c "
|
ALICE_HAS_BOB=$(printf '%s' "$ALICE_LIST" | python3 -c "
|
||||||
import json, sys
|
import json, sys
|
||||||
try:
|
try:
|
||||||
fns = json.load(sys.stdin)
|
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:
|
except:
|
||||||
print(0)" 2>/dev/null)
|
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_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 не содержит bob-fn" || fail "Alice LIST содержит bob-fn — УТЕЧКА ДАННЫХ!"
|
[ "${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 "
|
BOB_HAS_OWN=$(printf '%s' "$BOB_LIST" | python3 -c "
|
||||||
import json, sys
|
import json, sys
|
||||||
try:
|
try:
|
||||||
fns = json.load(sys.stdin)
|
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:
|
except:
|
||||||
print(0)" 2>/dev/null)
|
print(0)" 2>/dev/null)
|
||||||
BOB_HAS_ALICE=$(printf '%s' "$BOB_LIST" | python3 -c "
|
BOB_HAS_ALICE=$(printf '%s' "$BOB_LIST" | python3 -c "
|
||||||
import json, sys
|
import json, sys
|
||||||
try:
|
try:
|
||||||
fns = json.load(sys.stdin)
|
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:
|
except:
|
||||||
print(0)" 2>/dev/null)
|
print(0)" 2>/dev/null)
|
||||||
|
|
||||||
[ "${BOB_HAS_OWN:-0}" -ge 1 ] && pass "Bob LIST содержит bob-fn" || fail "Bob LIST не содержит bob-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 не содержит alice-fn" || fail "Bob LIST содержит alice-fn — УТЕЧКА ДАННЫХ!"
|
[ "${BOB_HAS_ALICE:-0}" -eq 0 ] && pass "Bob LIST не содержит t-alice-fn" || fail "Bob LIST содержит t-alice-fn — УТЕЧКА ДАННЫХ!"
|
||||||
|
|
||||||
# ── Route изоляция ───────────────────────────────────────────────────────────
|
# ── Route изоляция ───────────────────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -133,7 +133,7 @@ import json, sys
|
|||||||
try:
|
try:
|
||||||
fns = json.load(sys.stdin)
|
fns = json.load(sys.stdin)
|
||||||
for f in fns:
|
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',''))
|
print(f.get('spec',{}).get('relativeurl',''))
|
||||||
break
|
break
|
||||||
except:
|
except:
|
||||||
@@ -144,15 +144,15 @@ import json, sys
|
|||||||
try:
|
try:
|
||||||
fns = json.load(sys.stdin)
|
fns = json.load(sys.stdin)
|
||||||
for f in fns:
|
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',''))
|
print(f.get('spec',{}).get('relativeurl',''))
|
||||||
break
|
break
|
||||||
except:
|
except:
|
||||||
print('')" 2>/dev/null)
|
print('')" 2>/dev/null)
|
||||||
|
|
||||||
# Проверяем через GET (возвращает route)
|
# Проверяем через GET (возвращает route)
|
||||||
ALICE_GET=$(curl -s "${BASE}/functions/alice-fn" -H "X-Auth-Token: ${ALICE}")
|
ALICE_GET=$(curl -s "${BASE}/functions/t-alice-fn" -H "X-Auth-Token: ${ALICE}")
|
||||||
BOB_GET=$(curl -s "${BASE}/functions/bob-fn" -H "X-Auth-Token: ${BOB}")
|
BOB_GET=$(curl -s "${BASE}/functions/t-bob-fn" -H "X-Auth-Token: ${BOB}")
|
||||||
ROUTE_A=$(json_field "$ALICE_GET" route)
|
ROUTE_A=$(json_field "$ALICE_GET" route)
|
||||||
ROUTE_B=$(json_field "$BOB_GET" route)
|
ROUTE_B=$(json_field "$BOB_GET" route)
|
||||||
[ "$ROUTE_A" != "$ROUTE_B" ] && [ -n "$ROUTE_A" ] && [ -n "$ROUTE_B" ] \
|
[ "$ROUTE_A" != "$ROUTE_B" ] && [ -n "$ROUTE_A" ] && [ -n "$ROUTE_B" ] \
|
||||||
|
|||||||
@@ -13,17 +13,17 @@ NS_CLEANUP_SCRIPT="${ROOT_DIR}/cleanup_test_namespaces.sh"
|
|||||||
RUN_ID=$(mk_run_id)
|
RUN_ID=$(mk_run_id)
|
||||||
COUNT="${1:-8}"
|
COUNT="${1:-8}"
|
||||||
TMP=$(mktemp -d)
|
TMP=$(mktemp -d)
|
||||||
INVOKE_SUB="livetest@test.local"
|
INVOKE_SUB="test-livetest@test.local"
|
||||||
INVOKE_COUNT=8
|
INVOKE_COUNT=8
|
||||||
|
|
||||||
declare -a SUBS=()
|
declare -a SUBS=()
|
||||||
for i in $(seq 1 "$COUNT"); do
|
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
|
done
|
||||||
|
|
||||||
declare -a INVOKE_FNS=()
|
declare -a INVOKE_FNS=()
|
||||||
for i in $(seq 1 "$INVOKE_COUNT"); do
|
for i in $(seq 1 "$INVOKE_COUNT"); do
|
||||||
INVOKE_FNS+=("sinv-${RUN_ID}-${i}")
|
INVOKE_FNS+=("t-sinv-${RUN_ID}-${i}")
|
||||||
done
|
done
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
|
|||||||
+3
-3
@@ -10,7 +10,7 @@ source "${ROOT_DIR}/lib.sh"
|
|||||||
|
|
||||||
NS_CLEANUP_SCRIPT="${ROOT_DIR}/cleanup_test_namespaces.sh"
|
NS_CLEANUP_SCRIPT="${ROOT_DIR}/cleanup_test_namespaces.sh"
|
||||||
RUN_ID=$(mk_run_id)
|
RUN_ID=$(mk_run_id)
|
||||||
SUB="ttl-${RUN_ID}@test.local"
|
SUB="test-ttl-${RUN_ID}@test.local"
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
if [ -x "$NS_CLEANUP_SCRIPT" ]; then
|
if [ -x "$NS_CLEANUP_SCRIPT" ]; then
|
||||||
@@ -32,7 +32,7 @@ echo ""
|
|||||||
echo ">>> CREATE без TTL → expires_at отсутствует"
|
echo ">>> CREATE без TTL → expires_at отсутствует"
|
||||||
R=$(curl -s -X POST "${BASE}/functions" \
|
R=$(curl -s -X POST "${BASE}/functions" \
|
||||||
-H "X-Auth-Token: ${SUB}" -H "Content-Type: application/json" \
|
-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 "?")
|
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)
|
EXPIRES=$(json_field "$R" expires_at)
|
||||||
[ -z "$EXPIRES" ] && pass "CREATE без TTL: expires_at отсутствует" || fail "CREATE без TTL: expires_at='$EXPIRES'"
|
[ -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
|
if [ -z "$badttl" ]; then continue; fi
|
||||||
R=$(curl -s -w "\n%{http_code}" -X POST "${BASE}/functions" \
|
R=$(curl -s -w "\n%{http_code}" -X POST "${BASE}/functions" \
|
||||||
-H "X-Auth-Token: ${SUB}" -H "Content-Type: application/json" \
|
-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=$(echo "$R" | tail -1)
|
||||||
[ "$CODE" = "400" ] && pass "TTL='$badttl' → 400" || fail "TTL='$badttl' → got $CODE"
|
[ "$CODE" = "400" ] && pass "TTL='$badttl' → 400" || fail "TTL='$badttl' → got $CODE"
|
||||||
done
|
done
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ ROOT_DIR=$(cd "$(dirname "$0")" && pwd)
|
|||||||
source "${ROOT_DIR}/lib.sh"
|
source "${ROOT_DIR}/lib.sh"
|
||||||
|
|
||||||
RUN_ID=$(mk_run_id)
|
RUN_ID=$(mk_run_id)
|
||||||
SUB="livetest@test.local"
|
SUB="test-livetest@test.local"
|
||||||
FN="upd-fn-${RUN_ID}"
|
FN="t-upd-fn-${RUN_ID}"
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
curl -s -X DELETE "${BASE}/functions/${FN}" -H "X-Auth-Token: ${SUB}" > /dev/null 2>&1 || true
|
curl -s -X DELETE "${BASE}/functions/${FN}" -H "X-Auth-Token: ${SUB}" > /dev/null 2>&1 || true
|
||||||
|
|||||||
Reference in New Issue
Block a user