test(e2e): 第5刀b L4 gRPC 全链路(enroll→ReportUsage→统计真入库真读出)
在 HTTP 段基础上接 gRPC mTLS 全链路,真验证「统计准不准」: - 脚本:生成 Node CA + gRPC server 证书(镜像 deploy.sh)、起 server 带 gRPC、 nodectl 签 bootstrap token,传 E2E_GRPC_ADDR/CA/token/node 给 driver - driver:复用 agentd.EnsureEnrolled 真 TCP enroll → enroll 到的 client cert 建 mTLS → ReportUsage 注入 1GiB/100MiB(dp_uuid=用户) → 轮询 /v1/usage 断言 bytes_up=1GiB·bytes_down=100MiB 真入库真读回 - 本地全链路绿;go build ./... 不受影响(tag e2e) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+44
-19
@@ -1,16 +1,16 @@
|
||||
#!/usr/bin/env bash
|
||||
# e2e-smoke.sh — L4 后端进程级端到端冒烟。
|
||||
#
|
||||
# 真起打包好的 server 二进制(sqlite 临时库 + Redis),跑一条真 HTTP/gRPC over TCP/TLS
|
||||
# 的用户旅程,验证 in-process 测试给不了的信心:二进制能起、迁移能跑、路由/鉴权/DB
|
||||
# 端到端通、用量真入库真从 API 读出。
|
||||
# 真起打包好的 server 二进制(sqlite 临时库 + Redis + gRPC mTLS),跑一条真 HTTP/gRPC
|
||||
# over TCP/TLS 的全链路,验证 in-process 测试给不了的信心:二进制能起、迁移能跑、
|
||||
# 路由/鉴权/DB 通、用量经 gRPC enroll+ReportUsage 真入库、再经 HTTP /v1/usage 真读出。
|
||||
#
|
||||
# 用法: bash scripts/e2e-smoke.sh
|
||||
# 依赖: go · openssl · python3(取随机端口) · curl
|
||||
# 依赖: go · openssl · python3(随机端口+UUID) · curl
|
||||
# Redis 三选一:E2E_REDIS_ADDR(已有) > docker(redis:7-alpine) > 内嵌 miniredis
|
||||
#
|
||||
# 阶段: 5a = HTTP 段(登录→/v1/me→/v1/usage);5b 起 gRPC 全链路(enroll+ReportUsage)。
|
||||
# 全部断言在 Go driver: server/test/e2e/smoke_test.go(build tag e2e)。
|
||||
# 全部断言在 Go driver: server/test/e2e/smoke_test.go(build tag e2e):
|
||||
# HTTP 段(登录→/v1/me→/v1/usage) + gRPC 全链路(enroll→ReportUsage→/v1/usage bytes 断言)。
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
@@ -34,19 +34,14 @@ rand_port() {
|
||||
python3 -c 'import socket;s=socket.socket();s.bind(("",0));print(s.getsockname()[1]);s.close()'
|
||||
}
|
||||
|
||||
# start_redis — 按优先级落一个真 TCP Redis,地址写入 REDIS_ADDR_RESOLVED。
|
||||
start_redis() {
|
||||
if [ -n "${E2E_REDIS_ADDR:-}" ]; then
|
||||
REDIS_ADDR_RESOLVED="$E2E_REDIS_ADDR"
|
||||
echo "[e2e] 用已有 Redis $REDIS_ADDR_RESOLVED"
|
||||
return
|
||||
REDIS_ADDR_RESOLVED="$E2E_REDIS_ADDR"; echo "[e2e] 用已有 Redis $REDIS_ADDR_RESOLVED"; return
|
||||
fi
|
||||
if docker info >/dev/null 2>&1; then
|
||||
local p; p="$(rand_port)"
|
||||
REDIS_CID="$(docker run -d -p "$p:6379" redis:7-alpine)"
|
||||
REDIS_ADDR_RESOLVED="127.0.0.1:$p"
|
||||
echo "[e2e] docker Redis $REDIS_ADDR_RESOLVED"
|
||||
return
|
||||
REDIS_ADDR_RESOLVED="127.0.0.1:$p"; echo "[e2e] docker Redis $REDIS_ADDR_RESOLVED"; return
|
||||
fi
|
||||
echo "[e2e] 无 docker,用内嵌 miniredis 兜底 ..."
|
||||
( cd server && go run -tags e2e ./test/e2e/miniredis ) > "$TMP/mr.addr" 2>"$TMP/mr.log" &
|
||||
@@ -58,24 +53,46 @@ start_redis() {
|
||||
}
|
||||
|
||||
HTTP_PORT="$(rand_port)"
|
||||
GRPC_PORT="$(rand_port)"
|
||||
NODE_UUID="$(python3 -c 'import uuid;print(uuid.uuid4())')"
|
||||
|
||||
start_redis
|
||||
|
||||
echo "[e2e] 生成 JWT 密钥 ..."
|
||||
echo "[e2e] 生成 JWT 密钥 + Node CA + gRPC server 证书 ..."
|
||||
openssl genrsa -out "$TMP/jwt_private.pem" 2048 2>/dev/null
|
||||
openssl rsa -in "$TMP/jwt_private.pem" -pubout -out "$TMP/jwt_public.pem" 2>/dev/null
|
||||
# Node CA(ECDSA P-256,mtls.NewCA 读它)+ gRPC server 证书(CA 签,SAN localhost+127.0.0.1)
|
||||
# —— 镜像 deploy/single-node/deploy.sh L119-142。
|
||||
openssl ecparam -name prime256v1 -genkey -noout -out "$TMP/ca.key" 2>/dev/null
|
||||
openssl req -x509 -new -key "$TMP/ca.key" -days 3650 -out "$TMP/ca.crt" \
|
||||
-subj "/O=Pangolin/CN=Pangolin Node CA" \
|
||||
-addext "basicConstraints=critical,CA:TRUE" \
|
||||
-addext "keyUsage=critical,keyCertSign,cRLSign" 2>/dev/null
|
||||
openssl ecparam -name prime256v1 -genkey -noout -out "$TMP/grpc.key" 2>/dev/null
|
||||
openssl req -new -key "$TMP/grpc.key" -out "$TMP/grpc.csr" -subj "/CN=pangolin-control-plane" 2>/dev/null
|
||||
cat > "$TMP/grpc.ext" <<EXT
|
||||
subjectAltName=DNS:localhost,IP:127.0.0.1
|
||||
extendedKeyUsage=serverAuth
|
||||
EXT
|
||||
openssl x509 -req -in "$TMP/grpc.csr" -CA "$TMP/ca.crt" -CAkey "$TMP/ca.key" \
|
||||
-CAcreateserial -days 825 -out "$TMP/grpc.crt" -extfile "$TMP/grpc.ext" 2>/dev/null
|
||||
|
||||
echo "[e2e] go build server + migrate ..."
|
||||
( cd server && go build -o "$TMP/server" ./cmd/server && go build -o "$TMP/migrate" ./cmd/migrate )
|
||||
echo "[e2e] go build server + migrate + nodectl ..."
|
||||
( cd server && go build -o "$TMP/server" ./cmd/server \
|
||||
&& go build -o "$TMP/migrate" ./cmd/migrate \
|
||||
&& go build -o "$TMP/nodectl" ./cmd/nodectl )
|
||||
|
||||
DB_FILE="$TMP/e2e.db"
|
||||
echo "[e2e] migrate(sqlite) ..."
|
||||
DB_DRIVER=sqlite DB_DSN="$DB_FILE" "$TMP/migrate" up
|
||||
|
||||
echo "[e2e] 起 server :$HTTP_PORT ..."
|
||||
echo "[e2e] 起 server HTTP :$HTTP_PORT gRPC :$GRPC_PORT ..."
|
||||
DB_DRIVER=sqlite DB_DSN="$DB_FILE" \
|
||||
REDIS_ADDR="$REDIS_ADDR_RESOLVED" \
|
||||
ADDR=":$HTTP_PORT" \
|
||||
GRPC_ADDR=":$GRPC_PORT" \
|
||||
CA_KEY_PATH="$TMP/ca.key" CA_CERT_PATH="$TMP/ca.crt" \
|
||||
GRPC_CERT_PATH="$TMP/grpc.crt" GRPC_KEY_PATH="$TMP/grpc.key" \
|
||||
JWT_PRIVATE_KEY_PATH="$TMP/jwt_private.pem" \
|
||||
JWT_KEY_ID="e2e-key-1" \
|
||||
JWT_PUBLIC_KEYS="e2e-key-1:$TMP/jwt_public.pem" \
|
||||
@@ -96,14 +113,22 @@ done
|
||||
[ "$ok" = 1 ] || { echo "[e2e] ✗ /healthz 超时,日志:" >&2; cat "$TMP/server.log" >&2; exit 1; }
|
||||
echo "[e2e] 控制面健康。"
|
||||
|
||||
echo "[e2e] 跑 Go driver ..."
|
||||
echo "[e2e] 签发 agent bootstrap token(node=$NODE_UUID)..."
|
||||
TOKEN="$(REDIS_ADDR="$REDIS_ADDR_RESOLVED" "$TMP/nodectl" bootstrap-token -node="$NODE_UUID")"
|
||||
[ -n "$TOKEN" ] || { echo "[e2e] ✗ bootstrap token 签发失败" >&2; cat "$TMP/server.log" >&2; exit 1; }
|
||||
|
||||
echo "[e2e] 跑 Go driver(HTTP + gRPC 全链路)..."
|
||||
(
|
||||
cd server
|
||||
E2E_HTTP="http://127.0.0.1:$HTTP_PORT" \
|
||||
E2E_DB_DSN="$DB_FILE" \
|
||||
E2E_SERVER_LOG="$TMP/server.log" \
|
||||
E2E_GRPC_ADDR="127.0.0.1:$GRPC_PORT" \
|
||||
E2E_CA_CERT="$TMP/ca.crt" \
|
||||
E2E_BOOTSTRAP_TOKEN="$TOKEN" \
|
||||
E2E_NODE_UUID="$NODE_UUID" \
|
||||
DB_DRIVER=sqlite \
|
||||
go test -tags e2e ./test/e2e -run TestE2ESmoke -count=1 -v
|
||||
)
|
||||
|
||||
echo "[e2e] ✓ PASS — 进程级端到端冒烟通过"
|
||||
echo "[e2e] ✓ PASS — 进程级端到端冒烟通过(含 gRPC 全链路)"
|
||||
|
||||
Reference in New Issue
Block a user