docs: 全量重新评估 — PROJECT_EVALUATION/ROADMAP/TDD_PLAN 清空重写
基于全项目深度审计(96,102 行 / 374 文件),从 K8s 专项开发全面转向: PROJECT_EVALUATION.md: - 全量评估 8 大功能模块(资产/K8s/发布/监控/自动化/AIOps/审批/系统) - 技术债清单:前端 1026 处 any + 后端 4204 行 kubernetes.go + 1324 行 api.ts - Mock API 缺口:dashboardApi(6) / traceApi(3) / alertCenterApi.silence(1) - 综合评分 83/100 ROADMAP.md: - P0 工程质量:Q1 类型安全治理 / Q2 kubernetes.go 拆分 / Q3 api.ts 拆分 - P1 功能补全:F1 告警静默 / F2 审计导出 / F3 前端 RBAC - P2 架构优化:A1 K8s 路由统一 / A2 告警分布式 / A3 WebSocket 管理 - P3 用户体验:U1 虚拟滚动 / U2 DataTable / U3 i18n / U4 镜像优化 TDD_PLAN.md: - P0-P1 每个模块完整验证用例 - 回归测试基线(10 个核心 API 端点) - 全部改用 Python urllib(避免 shell 引号问题)
This commit is contained in:
1 parent
6e479f6df7
commit
e29dfb5868
4 files changed
+677
-1265
No files matched your search
+317
-494
@@ -1,550 +1,373 @@
|
||||
# TDD 验证计划 — K8s 管理功能
|
||||
# AIOps 验证计划 — 全模块回归测试
|
||||
|
||||
> 每个模块实现前先写验证用例,实现后必须跑通,不能只编译通过。
|
||||
> 基于 ROADMAP P0-P3 模块定义,每个模块开发前先写验证用例,实现后必须跑通。
|
||||
> 最后更新: 2026-06-25
|
||||
|
||||
## 通用验证流程
|
||||
|
||||
```bash
|
||||
# 1. 重建后端镜像
|
||||
cd /srv/aiops && docker-compose up -d --build backend
|
||||
# 0. 环境准备
|
||||
cd /srv/aiops
|
||||
|
||||
# 2. 等待 healthy
|
||||
# 1. 重建后端
|
||||
docker-compose up -d --build backend
|
||||
sleep 10 && docker ps --format '{{.Names}} {{.Status}}' | grep aiops-backend
|
||||
|
||||
# 3. 获取 JWT Token
|
||||
TOKEN=$(curl -s http://127.0.0.1:8080/api/v1/auth/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"username":"admin","password":"CHANGE_ME"}' | jq -r '.data.token')
|
||||
# 2. 获取 JWT Token(用 Python 避免 shell 引号问题)
|
||||
python3 -c "
|
||||
import urllib.request, json
|
||||
login_data = json.dumps({'username': 'admin', 'password': '123456'}).encode()
|
||||
req = urllib.request.Request('http://127.0.0.1:8080/api/v1/auth/login', data=login_data, method='POST')
|
||||
req.add_header('Content-Type', 'application/json')
|
||||
resp = urllib.request.urlopen(req)
|
||||
print(json.loads(resp.read())['data']['token'])
|
||||
" > /tmp/aiops_token
|
||||
TOKEN=$(cat /tmp/aiops_token)
|
||||
|
||||
# 4. 验证 API
|
||||
# 3. 验证后端健康
|
||||
curl -s http://127.0.0.1:8080/health | python3 -m json.tool
|
||||
|
||||
# 4. 前端构建
|
||||
cd frontend && npm run build 2>&1 | tail -3
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## P0-Q1: 前端类型安全治理
|
||||
|
||||
### 验证用例
|
||||
|
||||
```bash
|
||||
# U1: TypeScript 编译零错误
|
||||
cd /srv/aiops/frontend && npx tsc --noEmit 2>&1 | tail -5
|
||||
# 期望: 退出码 0, 无输出
|
||||
|
||||
# U2: ESLint any 类型数量
|
||||
npx eslint src/ --quiet --format json 2>/dev/null | python3 -c "
|
||||
import json, sys
|
||||
data = json.load(sys.stdin)
|
||||
any_count = sum(1 for r in data for m in r.get('messages', []) if m.get('ruleId') == '@typescript-eslint/no-explicit-any')
|
||||
print(f'any 类型: {any_count} 处')
|
||||
# 期望: < 50
|
||||
"
|
||||
|
||||
# U3: ESLint unused-vars 数量
|
||||
npx eslint src/ --quiet --format json 2>/dev/null | python3 -c "
|
||||
import json, sys
|
||||
data = json.load(sys.stdin)
|
||||
unused = sum(1 for r in data for m in r.get('messages', []) if m.get('ruleId') == '@typescript-eslint/no-unused-vars')
|
||||
print(f'未使用变量: {unused} 处')
|
||||
# 期望: < 20
|
||||
"
|
||||
|
||||
# U4: console.* 数量
|
||||
grep -rn 'console\.\(log\|debug\|info\)' src/ --include='*.ts' --include='*.tsx' | grep -v node_modules | wc -l
|
||||
# 期望: < 10
|
||||
|
||||
# U5: api.ts 中无泄露 token 的 console.log
|
||||
grep -n 'console.*token\|console.*Token' src/services/api.ts
|
||||
# 期望: 无输出
|
||||
|
||||
# U6: types/ 目录覆盖率
|
||||
wc -l src/types/*.ts
|
||||
# 期望: > 500 行(当前 375 行)
|
||||
|
||||
# U7: Vite 构建成功
|
||||
npm run build 2>&1 | tail -3
|
||||
# 期望: built in Ns
|
||||
```
|
||||
|
||||
### 通过标准
|
||||
- [ ] U1: `tsc --noEmit` 零错误
|
||||
- [ ] U2: `any` 类型 < 50 处
|
||||
- [ ] U3: 未使用变量 < 20 处
|
||||
- [ ] U4: `console.*` < 10 处
|
||||
- [ ] U5: api.ts 无 token 泄露
|
||||
- [ ] U6: types/ 覆盖率提升
|
||||
- [ ] U7: Vite 构建成功
|
||||
|
||||
---
|
||||
|
||||
## P0-Q2: 后端 kubernetes.go 模块化拆分
|
||||
|
||||
### 验证用例
|
||||
|
||||
```bash
|
||||
# U1: Go 编译
|
||||
cd /srv/aiops/backend && go build ./... 2>&1
|
||||
# 期望: 零错误
|
||||
|
||||
# U2: 拆分后文件行数
|
||||
for f in internal/api/handlers/k8s_*.go; do
|
||||
echo "$(wc -l < "$f") $f"
|
||||
done | sort -rn
|
||||
# 期望: 每个文件 < 800 行
|
||||
|
||||
# U3: 路由总数不变(拆分前后对比)
|
||||
grep -cE '^\s+(api\.|r\.|router\.|group\.|authorized\.)' internal/api/routes/routes.go
|
||||
# 期望: 路由数量与拆分前一致
|
||||
|
||||
# U4: API 回归测试 — 抽样核心端点
|
||||
TOKEN=$(cat /tmp/aiops_token)
|
||||
|
||||
# 集群列表
|
||||
curl -s http://127.0.0.1:8080/api/v1/kubernetes-clusters \
|
||||
-H "Authorization: Bearer $TOKEN" | jq '.'
|
||||
```
|
||||
-H "Authorization: Bearer $TOKEN" | python3 -c "import json,sys; d=json.load(sys.stdin); print(f'clusters: {len(d[\"data\"])}')"
|
||||
# 期望: 返回集群数组
|
||||
|
||||
---
|
||||
|
||||
## M1: SyncCluster metrics 采集
|
||||
|
||||
### 验证用例
|
||||
|
||||
```bash
|
||||
# U1: 同步前 — 确认 DB 里 cpu_usage 为 0
|
||||
docker exec aiops-mysql mysql -uroot -p"$MYSQL_ROOT_PASSWORD" aiops \
|
||||
-e "SELECT name, cpu_usage, memory_usage FROM kubernetes_nodes WHERE cluster_id=1"
|
||||
|
||||
# U2: 触发同步
|
||||
curl -X POST http://127.0.0.1:8080/api/v1/kubernetes-clusters/1/sync \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
|
||||
# U3: 同步后 — 确认 cpu_usage/memory_usage 非零
|
||||
docker exec aiops-mysql mysql -uroot -p"$MYSQL_ROOT_PASSWORD" aiops \
|
||||
-e "SELECT name, cpu_usage, memory_usage FROM kubernetes_nodes WHERE cluster_id=1"
|
||||
# 期望: cpu_usage > 0 AND memory_usage > 0
|
||||
|
||||
# U4: 集群详情页 API — 无硬编码
|
||||
curl -s http://127.0.0.1:8080/api/v1/kubernetes-clusters/1 \
|
||||
-H "Authorization: Bearer $TOKEN" | jq '.data.node_count, .data.pod_count'
|
||||
# 期望: node_count=2, pod_count>0
|
||||
|
||||
# U5: 前端构建无报错
|
||||
cd /srv/aiops/frontend && npm run build 2>&1 | tail -5
|
||||
# 期望: vite build 成功
|
||||
```
|
||||
|
||||
### 通过标准
|
||||
- [x] U1: 同步前 cpu_usage=0
|
||||
- [x] U2: 同步 API 200
|
||||
- [x] U3: 同步后 cpu_usage>0
|
||||
- [x] U4: 集群计数正确
|
||||
- [x] U5: 前端构建成功
|
||||
|
||||
---
|
||||
|
||||
## M2: Pod Metrics
|
||||
|
||||
### 验证用例
|
||||
```bash
|
||||
# 同步后 Pod 列表含 CPU/内存
|
||||
curl -s "http://127.0.0.1:8080/api/v1/kubernetes-clusters/1/pods" \
|
||||
-H "Authorization: Bearer ***" | jq '.data[0]'
|
||||
# 期望: 含 cpu_usage_m / mem_usage_mi 字段
|
||||
```
|
||||
|
||||
### 通过标准
|
||||
- [x] Pod 列表 API 返回 cpu_usage_m / mem_usage_mi 字段
|
||||
- [x] 前端 Pod 列表表格显示 CPU/内存列(KubernetesWorkloads + NamespaceResourcePage)
|
||||
- [x] 17 个 Pod 全部有真实 metrics 数据
|
||||
|
||||
---
|
||||
|
||||
## M3: Pod 文件上传
|
||||
|
||||
### 验证用例
|
||||
```bash
|
||||
# 上传文件
|
||||
echo "test content" > /tmp/test-upload.txt
|
||||
curl -X POST "http://127.0.0.1:8080/api/v1/kubernetes/1/namespace/devops/pods/aiops-xxx/files/upload?path=/tmp&container=aiops" \
|
||||
-H "Authorization: Bearer ***" \
|
||||
-F "file=@/tmp/test-upload.txt"
|
||||
# 期望: 200 + 文件出现在列表中
|
||||
```
|
||||
|
||||
### 通过标准
|
||||
- [x] 上传 API 返回 200 + verify 字段匹配文件大小
|
||||
- [x] 文件列表 (ls) 能看到上传的文件
|
||||
- [x] ExecInPod 使用 WebSocket channel.k8s.io 协议(不再用 SPDY raw HTTP)
|
||||
- [x] BusyBox ls 解析兼容(Mon DD HH:MM 格式)
|
||||
|
||||
---
|
||||
|
||||
## M5: Deployment 暂停更新 + CI/CD 集成
|
||||
|
||||
### 验证用例
|
||||
```bash
|
||||
# U1: 暂停前 — 确认 paused=false
|
||||
# Deployment 列表
|
||||
curl -s "http://127.0.0.1:8080/api/v1/kubernetes/prod-cluster/namespace/devops/deployments" \
|
||||
-H "Authorization: Bearer $TOKEN" | jq '.data[] | select(.name=="redis") | .paused'
|
||||
# 期望: false
|
||||
-H "Authorization: Bearer $TOKEN" | python3 -c "import json,sys; d=json.load(sys.stdin); print(f'deployments: {len(d[\"data\"])}')"
|
||||
# 期望: 返回 Deployment 数组
|
||||
|
||||
# U2: 暂停 Deployment
|
||||
curl -X POST "http://127.0.0.1:8080/api/v1/kubernetes/prod-cluster/namespace/devops/deployments/redis/pause" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
# 期望: code=200, msg="已暂停滚动更新"
|
||||
# Pod 列表
|
||||
curl -s "http://127.0.0.1:8080/api/v1/kubernetes/prod-cluster/namespace/devops/pods" \
|
||||
-H "Authorization: Bearer $TOKEN" | python3 -c "import json,sys; d=json.load(sys.stdin); print(f'pods: {len(d[\"data\"])}')"
|
||||
# 期望: 返回 Pod 数组
|
||||
|
||||
# U3: 暂停后 — 确认 paused=true
|
||||
curl -s "http://127.0.0.1:8080/api/v1/kubernetes/prod-cluster/namespace/devops/deployments" \
|
||||
-H "Authorization: Bearer $TOKEN" | jq '.data[] | select(.name=="redis") | .paused'
|
||||
# 期望: true
|
||||
|
||||
# U4: 恢复 Deployment
|
||||
curl -X POST "http://127.0.0.1:8080/api/v1/kubernetes/prod-cluster/namespace/devops/deployments/redis/resume" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
# 期望: code=200, msg="已恢复滚动更新"
|
||||
|
||||
# U5: 恢复后 — 确认 paused=false
|
||||
curl -s "http://127.0.0.1:8080/api/v1/kubernetes/prod-cluster/namespace/devops/deployments" \
|
||||
-H "Authorization: Bearer $TOKEN" | jq '.data[] | select(.name=="redis") | .paused'
|
||||
# 期望: false
|
||||
```
|
||||
|
||||
### 通过标准
|
||||
- [x] U1: 暂停前 paused=false
|
||||
- [x] U2: pause API 返回 200
|
||||
- [x] U3: 暂停后 paused=true
|
||||
- [x] U4: resume API 返回 200
|
||||
- [x] U5: 恢复后 paused=false
|
||||
- [x] ID 路由 + Kuboard code 路由均可用
|
||||
- [x] 前端操作菜单显示「暂停更新/恢复更新」动态切换
|
||||
- [x] CI/CD 发布按钮可跳转到流水线页面
|
||||
|
||||
---
|
||||
|
||||
## M6: 编辑器基础设施 + 基本信息 Tab + YAML编辑器
|
||||
|
||||
### 验证用例
|
||||
|
||||
```bash
|
||||
# U1: 三模式路由 SPA fallback 200(非 301/404)
|
||||
curl -s -o /dev/null -w "%{http_code}" \
|
||||
"http://127.0.0.1/kubernetes/prod-cluster/namespace/devops/workload/yaml/Deployment/redis"
|
||||
# 期望: 200
|
||||
|
||||
# U2: YAML GET API — CodeMirror 编辑器数据源
|
||||
# YAML 获取
|
||||
curl -s "http://127.0.0.1:8080/api/v1/kubernetes/prod-cluster/namespace/devops/deployments/redis/yaml" \
|
||||
-H "Authorization: Bearer *** | head -5
|
||||
# 期望: apiVersion: apps/v1 / kind: Deployment / metadata:
|
||||
|
||||
# U3: 前端构建含 CodeMirror 依赖
|
||||
curl -s http://127.0.0.1/ | grep -oP 'index-[A-Za-z0-9]+\.js'
|
||||
# 期望: 新 hash(每次构建变化)
|
||||
|
||||
# U4: TypeScript 编译无错误
|
||||
cd frontend && npx tsc --noEmit
|
||||
# 期望: 退出码 0
|
||||
|
||||
# U5: Vite 生产构建成功
|
||||
cd frontend && npm run build 2>&1 | tail -3
|
||||
# 期望: built in Ns
|
||||
```
|
||||
|
||||
### 通过标准
|
||||
- [x] U1: yaml 路由 SPA fallback 返回 200
|
||||
- [x] U2: YAML API 返回有效 K8s manifest(apiVersion/kind/metadata 齐全)
|
||||
- [x] U3: 前端 bundle 含 CodeMirror(codemirror 关键字在 JS chunk 中)
|
||||
- [x] U4: TypeScript 零编译错误
|
||||
- [x] U5: Vite 生产构建成功
|
||||
- [x] YamlViewer 支持弹窗模式 + 内联模式(inline prop)
|
||||
- [x] DeploymentEditBasic 可编辑 replicas/labels/annotations/selector
|
||||
- [x] 编辑模式 Tab 导航系统就绪(基本信息可用 + M7-M9 预留)
|
||||
|
||||
---
|
||||
|
||||
## M7: 容器信息 Tab(工作容器 + 初始化容器)
|
||||
|
||||
### 验证用例
|
||||
|
||||
```bash
|
||||
# U1: 登录获取 Token
|
||||
TOKEN=$(curl -s http://127.0.0.1:8080/api/v1/auth/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"username":"admin","password":"admin123"}' | jq -r '.data.token')
|
||||
# 期望: code=200
|
||||
|
||||
# U2: YAML GET — 容器编辑器数据源
|
||||
curl -s "http://127.0.0.1:8080/api/v1/kubernetes/test-k8s/namespace/devops/deployments/aiops/yaml" \
|
||||
-H "Authorization: Bearer $TOKEN" | head -5
|
||||
# 期望: apiVersion: apps/v1 / kind: Deployment / containers:
|
||||
|
||||
# U3: PUT YAML 保存(容器编辑器保存路径)
|
||||
curl -s -X PUT "http://127.0.0.1:8080/api/v1/kubernetes/test-k8s/namespace/devops/deployments/aiops/yaml" \
|
||||
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/yaml" \
|
||||
-d "$(curl -s .../aiops/yaml -H "Authorization: Bearer $TOKEN")"
|
||||
# 期望: code=200
|
||||
|
||||
# U4: SPA fallback — edit 路由 200(非 301)
|
||||
curl -s -o /dev/null -w "%{http_code}" \
|
||||
"http://127.0.0.1/kubernetes/test-k8s/namespace/devops/workload/edit/Deployment/aiops"
|
||||
# 期望: 200
|
||||
|
||||
# U5: TypeScript 编译 + Vite 构建无错误
|
||||
cd frontend && npm run build 2>&1 | tail -3
|
||||
# 期望: built in Ns
|
||||
|
||||
# U6: 前端 bundle 含 DeploymentEditContainers 组件(新 hash)
|
||||
curl -s http://127.0.0.1/ | grep -oP 'index-[A-Za-z0-9]+\.js'
|
||||
# 期望: 新 hash(每次构建变化)
|
||||
```
|
||||
|
||||
### 通过标准
|
||||
- [x] U1: 登录成功
|
||||
- [x] U2: YAML API 返回含 containers 的有效 K8s manifest
|
||||
- [x] U3: PUT 保存返回 code=200
|
||||
- [x] U4: 编辑模式 SPA 路由返回 200(非 301)
|
||||
- [x] U5: TypeScript 零编译错误 + Vite 构建成功
|
||||
- [x] U6: 前端 bundle 已更新(含新组件)
|
||||
- [x] DeploymentEditContainers 支持工作容器 + 初始化容器增删
|
||||
- [x] 每个容器可编辑:镜像/拉取策略/命令/参数/环境变量/端口/资源/健康检查/生命周期/安全上下文/卷挂载
|
||||
- [x] 镜像拉取凭证(imagePullSecrets) Pod 级别编辑
|
||||
- [x] 三种探针类型(httpGet/tcpSocket/exec)可切换
|
||||
|
||||
---
|
||||
|
||||
## M8: 存储挂载 + 高级设置 Tab
|
||||
|
||||
### 验证用例
|
||||
|
||||
```bash
|
||||
# U1: 登录获取 Token
|
||||
TOKEN=$(curl -s http://127.0.0.1:8080/api/v1/auth/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"username":"admin","password":"admin123"}' | jq -r '.data.token')
|
||||
|
||||
# U2: SPA fallback — edit 路由返回 200(非 301)
|
||||
curl -s -o /dev/null -w "%{http_code}" \
|
||||
"http://127.0.0.1/kubernetes/prod-cluster/namespace/devops/workload/edit/Deployment/redis"
|
||||
# 期望: 200
|
||||
|
||||
# U3: YAML GET API — Storage/Advanced Tab 数据源
|
||||
curl -s "http://127.0.0.1:8080/api/v1/kubernetes/prod-cluster/namespace/devops/deployments/redis/yaml" \
|
||||
-H "Authorization: Bearer $TOKEN" | head -5
|
||||
# 期望: apiVersion: apps/v1 / kind: Deployment / metadata:
|
||||
|
||||
# U4: TypeScript 编译 + Vite 构建
|
||||
cd frontend && npx tsc --noEmit && npm run build 2>&1 | tail -3
|
||||
# 期望: 零错误 + built in Ns
|
||||
|
||||
# U5: 前端 bundle 含 DeploymentEditStorage + DeploymentEditAdvanced 组件
|
||||
curl -s http://127.0.0.1/ | grep -oP 'index-[A-Za-z0-9]+\.js'
|
||||
# 期望: 新 hash(每次构建变化)
|
||||
```
|
||||
|
||||
### 通过标准
|
||||
- [x] U1: 登录成功
|
||||
- [x] U2: edit 路由 SPA fallback 返回 200
|
||||
- [x] U3: YAML API 返回含 spec.strategy/spec.template.spec 的有效 manifest
|
||||
- [x] U4: TypeScript 零编译错误 + Vite 构建成功
|
||||
- [x] U5: 前端 bundle 已更新
|
||||
- [x] DeploymentEditStorage 支持 6 种 volume 类型(EmptyDir/HostPath/ConfigMap/Secret/PVC/NFS)
|
||||
- [x] DeploymentEditAdvanced 支持更新策略/调度/nodeSelector/tolerations/DNS/安全上下文/主机设置/hostAliases/dnsConfig
|
||||
- [x] 各 Tab 独立保存(PUT application/yaml 直通 K8s API)
|
||||
|
||||
---
|
||||
|
||||
## M10: Node 详情页(PID/容器运行时/分配率)
|
||||
|
||||
### 验证用例
|
||||
|
||||
```bash
|
||||
# U1: 登录获取 Token
|
||||
TOKEN=$(curl -s http://127.0.0.1:8080/api/v1/auth/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"username":"admin","password":"admin123"}' | jq -r '.data.token')
|
||||
|
||||
# U2: Node detail API — Kuboard code route
|
||||
curl -s "http://127.0.0.1:8080/api/v1/kubernetes/test-k8s/nodes/k8s-master-01" \
|
||||
-H "Authorization: Bearer *** | jq '.data.container_runtime'
|
||||
# 期望: "containerd://2.1.4"
|
||||
|
||||
# U3: 资源分配率字段
|
||||
curl -s "http://127.0.0.1:8080/api/v1/kubernetes/test-k8s/nodes/k8s-master-01" \
|
||||
-H "Authorization: Bearer *** | jq '.data | {cpu_alloc_pct, mem_alloc_pct, pod_alloc_pct, pod_count}'
|
||||
# 期望: cpu_alloc_pct/mem_alloc_pct/pod_alloc_pct 均为数字 > 0
|
||||
|
||||
# U4: conditions + taints + pods 列表
|
||||
curl -s "http://127.0.0.1:8080/api/v1/kubernetes/test-k8s/nodes/k8s-master-01" \
|
||||
-H "Authorization: Bearer *** | jq '.data | {conditions: (.conditions|length), taints: (.taints|length), pods: (.pods|length)}'
|
||||
# 期望: conditions>=4, pods>=1
|
||||
|
||||
# U5: SPA fallback — node detail 路由 200
|
||||
curl -s -o /dev/null -w "%{http_code}" \
|
||||
"http://127.0.0.1/kubernetes/test-k8s/nodes/k8s-master-01"
|
||||
# 期望: 200
|
||||
|
||||
# U6: TypeScript + Vite 构建
|
||||
cd frontend && npx tsc --noEmit && npm run build 2>&1 | tail -3
|
||||
# 期望: 零错误 + built in Ns
|
||||
```
|
||||
|
||||
### 通过标准
|
||||
- [x] U1: 登录成功
|
||||
- [x] U2: Node detail API 返回 container_runtime/kubelet/os/kernel/architecture
|
||||
- [x] U3: 资源分配率正确(cpu_alloc_pct/mem_alloc_pct/pod_alloc_pct 数字)
|
||||
- [x] U4: conditions/taints/pods 列表非空
|
||||
- [x] U5: SPA 路由 200(非 301)
|
||||
- [x] U6: TypeScript 零错误 + Vite 构建成功
|
||||
- [x] 前端节点名称可点击跳转详情页
|
||||
|
||||
---
|
||||
|
||||
## M9: 服务/应用路由 Tab + 整体联调
|
||||
|
||||
### 验证用例
|
||||
|
||||
```bash
|
||||
# U1: 5 Tab 全部 available(检查 EditModeContainer)
|
||||
# 验证方式: 浏览器打开 edit 模式,5 个 Tab 均可点击切换
|
||||
|
||||
# U2: TypeScript 编译
|
||||
cd frontend && npx tsc --noEmit
|
||||
# 期望: 退出码 0
|
||||
|
||||
# U3: Vite 构建成功
|
||||
cd frontend && npm run build 2>&1 | tail -3
|
||||
# 期望: built in Ns
|
||||
```
|
||||
|
||||
### 通过标准
|
||||
- [x] DeploymentEditService.tsx 组件存在且编译通过
|
||||
- [x] DeploymentWorkload.tsx EditModeContainer 5 Tab 全部 available
|
||||
- [x] Service Tab selector 双路径兼容(spec.selector.matchLabels || selector)
|
||||
- [x] TypeScript 零编译错误 + Vite 构建成功
|
||||
- [x] 前端 bundle 已更新
|
||||
|
||||
---
|
||||
|
||||
## M11: StatefulSet/DaemonSet 详情页
|
||||
|
||||
### 验证用例
|
||||
|
||||
```bash
|
||||
# U1: 登录获取 Token
|
||||
TOKEN=$(curl -s http://127.0.0.1:8080/api/v1/auth/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"username":"admin","password":"admin123"}' | jq -r '.data.token')
|
||||
|
||||
# U2: DaemonSet YAML API(路由冲突修复验证)
|
||||
curl -s "http://127.0.0.1:8080/api/v1/kubernetes/prod-cluster/namespace/kube-system/daemonsets/calico-node/yaml" \
|
||||
-H "Authorization: Bearer *** | head -3
|
||||
# 期望: apiVersion: apps/v1 / kind: DaemonSet / metadata:
|
||||
|
||||
# U3: DaemonSet Detail API
|
||||
curl -s "http://127.0.0.1:8080/api/v1/kubernetes/prod-cluster/namespace/kube-system/daemonsets/calico-node" \
|
||||
-H "Authorization: Bearer *** | jq '.data | {name: .metadata.name, desired: .status.desiredNumberScheduled, ready: .status.numberReady}'
|
||||
# 期望: name="calico-node", desired=2, ready=2
|
||||
|
||||
# U4: Deployment YAML 仍正常(generic 路由未受影响)
|
||||
curl -s "http://127.0.0.1:8080/api/v1/kubernetes/prod-cluster/namespace/devops/deployments/redis/yaml" \
|
||||
-H "Authorization: Bearer *** | head -1
|
||||
-H "Authorization: Bearer $TOKEN" | head -3
|
||||
# 期望: apiVersion: apps/v1
|
||||
|
||||
# U5: SPA fallback — workload 路由 200
|
||||
curl -s -o /dev/null -w "%{http_code}" \
|
||||
"http://127.0.0.1/kubernetes/prod-cluster/namespace/kube-system/workload/view/DaemonSet/calico-node"
|
||||
# 期望: 200
|
||||
|
||||
# U6: TypeScript + Vite 构建
|
||||
cd frontend && npx tsc --noEmit && npm run build 2>&1 | tail -3
|
||||
# 期望: 零错误 + built in Ns
|
||||
```
|
||||
|
||||
### 通过标准
|
||||
- [x] U2: DS YAML API 返回 200 + apiVersion + kind=DaemonSet(Gin radix tree 路由冲突已修复)
|
||||
- [x] U3: DS Detail API 返回 name/desired/current/ready/containers
|
||||
- [x] U4: Deployment YAML API 仍正常(generic `/:resource/:name/yaml` 路由未受影响)
|
||||
- [x] U5: SPA 路由 view/yaml 两种模式均返回 200
|
||||
- [x] U6: TypeScript 零编译错误 + Vite 构建成功
|
||||
- [x] NamespaceResourcePage 点击 STS/DS 行可跳转详情页
|
||||
- [x] WorkloadViewPage 支持 view/yaml 双模式切换
|
||||
- [x] WorkloadViewPage kind 从 useLocation 正确提取(DaemonSet 不被误判为 StatefulSet)
|
||||
- [x] 更新策略/选择器/PVC模板/InitContainers 全部展示
|
||||
|
||||
---
|
||||
|
||||
## M12: 事件聚合 + 告警联动
|
||||
|
||||
### 验证用例
|
||||
|
||||
```bash
|
||||
# U1: 登录获取 Token
|
||||
TOKEN=*** -s http://127.0.0.1:8080/api/v1/auth/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"username":"admin","password":"admin123"}' | jq -r '.data.token')
|
||||
|
||||
# U2: Events Summary API(聚合统计)
|
||||
# 事件聚合
|
||||
curl -s "http://127.0.0.1:8080/api/v1/kubernetes/prod-cluster/events/summary" \
|
||||
-H "Authorization: Bearer $TOKEN" | jq '.data | {total, warning_count, normal_count, reasons: (.by_reason|length), namespaces: (.by_namespace|length), kinds: (.by_kind|length), recent: (.recent_warnings|length)}'
|
||||
# 期望: total/warning_count/normal_count 为数字,by_reason/by_namespace/by_kind/recent_warnings 为数组
|
||||
-H "Authorization: Bearer $TOKEN" | python3 -c "import json,sys; d=json.load(sys.stdin)['data']; print(f'events total: {d[\"total\"]}')"
|
||||
# 期望: total 为数字
|
||||
|
||||
# U3: Events Summary 时间窗口过滤
|
||||
curl -s "http://127.0.0.1:8080/api/v1/kubernetes/prod-cluster/events/summary?hours=24" \
|
||||
-H "Authorization: Bearer $TOKEN" | jq '.data.total'
|
||||
# 期望: 只返回近 24 小时事件计数
|
||||
# 多集群对比
|
||||
curl -s "http://127.0.0.1:8080/api/v1/kubernetes/compare" \
|
||||
-H "Authorization: Bearer $TOKEN" | python3 -c "import json,sys; d=json.load(sys.stdin)['data']; print(f'clusters compared: {len(d[\"clusters\"])}')"
|
||||
# 期望: clusters 数组
|
||||
|
||||
# U4: Events List 仍正常
|
||||
curl -s "http://127.0.0.1:8080/api/v1/kubernetes/prod-cluster/events" \
|
||||
-H "Authorization: Bearer $TOKEN" | jq '.data | length'
|
||||
# 期望: 返回事件数组
|
||||
# Namespace 详情
|
||||
curl -s "http://127.0.0.1:8080/api/v1/kubernetes/prod-cluster/namespaces/detail" \
|
||||
-H "Authorization: Bearer $TOKEN" | python3 -c "import json,sys; d=json.load(sys.stdin); print(f'namespaces: {len(d[\"data\"])}')"
|
||||
# 期望: 返回命名空间数组
|
||||
|
||||
# U5: SPA 路由
|
||||
curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:8080/kubernetes/prod-cluster/events
|
||||
# 期望: 200
|
||||
|
||||
# U6: TypeScript + Vite 构建
|
||||
cd frontend && npx tsc --noEmit && npm run build 2>&1 | tail -3
|
||||
# 期望: 零错误 + built in Ns
|
||||
# U5: 容器重新构建 + 启动
|
||||
docker-compose up -d --build backend
|
||||
sleep 10
|
||||
docker ps --format '{{.Names}} {{.Status}}' | grep aiops-backend
|
||||
# 期望: healthy
|
||||
```
|
||||
|
||||
### 通过标准
|
||||
- [x] U2: Events Summary API 返回完整聚合数据(total/warning_count/normal_count/by_reason/by_namespace/by_kind/recent_warnings)
|
||||
- [x] U3: 时间窗口过滤正常(hours=24 只统计近 24h)
|
||||
- [x] U4: Events List API 不受影响
|
||||
- [x] U5: SPA 路由返回 200
|
||||
- [x] U6: TypeScript 零编译错误 + Vite 构建成功
|
||||
- [x] 前端三维度柱状图正确渲染(recharts)
|
||||
- [x] 图表点击联动过滤事件列表
|
||||
- [x] 最新告警面板展示 Warning 事件
|
||||
- [ ] U1: `go build` 零错误
|
||||
- [ ] U2: 每个拆分文件 < 800 行
|
||||
- [ ] U3: 路由数量不变
|
||||
- [ ] U4: 7 个核心 API 端点全部返回正确数据
|
||||
- [ ] U5: 容器 healthy
|
||||
|
||||
---
|
||||
|
||||
## M13: 多集群资源对比看板
|
||||
## P0-Q3: 前端 api.ts 模块化拆分
|
||||
|
||||
### 验证用例
|
||||
|
||||
```bash
|
||||
# U1: 登录获取 Token
|
||||
TOKEN=$(python3 -c "
|
||||
# U1: 拆分后文件结构
|
||||
ls -la /srv/aiops/frontend/src/services/api/
|
||||
# 期望: kubernetes.ts, deploy.ts, agent.ts, alert.ts, server.ts, cloud.ts, index.ts
|
||||
|
||||
# U2: 单文件行数
|
||||
wc -l /srv/aiops/frontend/src/services/api/*.ts | sort -rn
|
||||
# 期望: 每个文件 < 300 行
|
||||
|
||||
# U3: API 方法总数不变
|
||||
grep -c 'export const\|async \|: Promise' /srv/aiops/frontend/src/services/api/index.ts
|
||||
# 期望: re-export 352 个方法
|
||||
|
||||
# U4: TypeScript 编译
|
||||
cd /srv/aiops/frontend && npx tsc --noEmit
|
||||
# 期望: 零错误
|
||||
|
||||
# U5: Vite 构建
|
||||
npm run build 2>&1 | tail -3
|
||||
# 期望: built in Ns
|
||||
|
||||
# U6: 所有 import 路径正确(无断链)
|
||||
grep -rn "from.*services/api" src/ | head -20
|
||||
# 期望: 所有引用正常解析
|
||||
```
|
||||
|
||||
### 通过标准
|
||||
- [ ] U1: api/ 目录结构正确
|
||||
- [ ] U2: 每个文件 < 300 行
|
||||
- [ ] U3: 352 个方法全部保留
|
||||
- [ ] U4: `tsc --noEmit` 零错误
|
||||
- [ ] U5: Vite 构建成功
|
||||
- [ ] U6: 所有 import 正常
|
||||
|
||||
---
|
||||
|
||||
## P1-F1: 告警静默规则
|
||||
|
||||
### 验证用例
|
||||
|
||||
```bash
|
||||
TOKEN=$(cat /tmp/aiops_token)
|
||||
|
||||
# U1: 创建静默规则
|
||||
curl -s -X POST "http://127.0.0.1:8080/api/v1/alerts/silences" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"name": "维护窗口静默",
|
||||
"matchers": [{"key": "namespace", "value": "devops"}],
|
||||
"starts_at": "2026-06-25T10:00:00Z",
|
||||
"ends_at": "2026-06-25T12:00:00Z"
|
||||
}' | python3 -m json.tool
|
||||
# 期望: code=200
|
||||
|
||||
# U2: 查询静默规则列表
|
||||
curl -s "http://127.0.0.1:8080/api/v1/alerts/silences" \
|
||||
-H "Authorization: Bearer $TOKEN" | python3 -c "import json,sys; d=json.load(sys.stdin); print(f'silences: {len(d[\"data\"])}')"
|
||||
# 期望: >= 1
|
||||
|
||||
# U3: 静默期间告警不触发通知(需要模拟告警条件)
|
||||
# 手动验证: 创建一个会匹配静默规则的告警规则,触发后检查飞书是否收到通知
|
||||
|
||||
# U4: 删除静默规则
|
||||
SILENCE_ID=$(curl -s "http://127.0.0.1:8080/api/v1/alerts/silences" -H "Authorization: Bearer $TOKEN" | python3 -c "import json,sys; print(json.load(sys.stdin)['data'][0]['id'])")
|
||||
curl -s -X DELETE "http://127.0.0.1:8080/api/v1/alerts/silences/$SILENCE_ID" \
|
||||
-H "Authorization: Bearer $TOKEN" | python3 -m json.tool
|
||||
# 期望: code=200
|
||||
```
|
||||
|
||||
### 通过标准
|
||||
- [ ] U1: 创建静默规则返回 200
|
||||
- [ ] U2: 列表包含创建的规则
|
||||
- [ ] U3: 静默期间不触发通知
|
||||
- [ ] U4: 删除返回 200
|
||||
- [ ] 前端 AlertCenter 有「静默规则」Tab
|
||||
|
||||
---
|
||||
|
||||
## P1-F2: 审计日志导出
|
||||
|
||||
### 验证用例
|
||||
|
||||
```bash
|
||||
TOKEN=$(cat /tmp/aiops_token)
|
||||
|
||||
# U1: 导出 CSV
|
||||
curl -s "http://127.0.0.1:8080/api/v1/audit/export?format=csv" \
|
||||
-H "Authorization: Bearer $TOKEN" -o /tmp/audit_export.csv
|
||||
file /tmp/audit_export.csv
|
||||
# 期望: CSV 文件
|
||||
|
||||
# U2: 导出 Excel
|
||||
curl -s "http://127.0.0.1:8080/api/v1/audit/export?format=xlsx" \
|
||||
-H "Authorization: Bearer $TOKEN" -o /tmp/audit_export.xlsx
|
||||
file /tmp/audit_export.xlsx
|
||||
# 期望: Microsoft Excel 2007+
|
||||
|
||||
# U3: 带筛选条件导出
|
||||
curl -s "http://127.0.0.1:8080/api/v1/audit/export?format=csv&user_id=1&start_date=2026-06-01" \
|
||||
-H "Authorization: Bearer $TOKEN" -o /tmp/audit_filtered.csv
|
||||
wc -l /tmp/audit_filtered.csv
|
||||
# 期望: 行数 > 1(有数据)
|
||||
```
|
||||
|
||||
### 通过标准
|
||||
- [ ] U1: CSV 导出文件有效
|
||||
- [ ] U2: Excel 导出文件有效
|
||||
- [ ] U3: 筛选条件正确工作
|
||||
- [ ] 前端有「导出」按钮
|
||||
|
||||
---
|
||||
|
||||
## P1-F3: 前端 RBAC 按钮级控制
|
||||
|
||||
### 验证用例
|
||||
|
||||
```bash
|
||||
# U1: 创建只读角色(无写入权限)
|
||||
TOKEN=$(cat /tmp/aiops_token)
|
||||
curl -s -X POST "http://127.0.0.1:8080/api/v1/admin/roles" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"name": "viewer", "permissions": ["read:servers", "read:k8s"]}' | python3 -m json.tool
|
||||
# 期望: code=200
|
||||
|
||||
# U2: 创建 viewer 用户
|
||||
curl -s -X POST "http://127.0.0.1:8080/api/v1/admin/users" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"username": "viewer_test", "password": "123456", "role_id": 2}' | python3 -m json.tool
|
||||
# 期望: code=200
|
||||
|
||||
# U3: 以 viewer 身份登录
|
||||
VIEWER_TOKEN=$(python3 -c "
|
||||
import urllib.request, json
|
||||
login_data = json.dumps({'username': 'admin', 'password': 'admin123'}).encode()
|
||||
login_data = json.dumps({'username': 'viewer_test', 'password': '123456'}).encode()
|
||||
req = urllib.request.Request('http://127.0.0.1:8080/api/v1/auth/login', data=login_data, method='POST')
|
||||
req.add_header('Content-Type', 'application/json')
|
||||
resp = urllib.request.urlopen(req)
|
||||
print(json.loads(resp.read())['data']['token'])
|
||||
")
|
||||
|
||||
# U2: 多集群对比 API
|
||||
curl -s "http://127.0.0.1:8080/api/v1/kubernetes/compare" \
|
||||
-H "Authorization: Bearer $TOKEN" | jq '.data | {totals, cluster_count: (.clusters|length)}'
|
||||
# 期望: totals 含 cluster_count/node_count/pod_count/deployment_count/service_count
|
||||
# U4: viewer 调用写接口应被拒绝
|
||||
curl -s -X POST "http://127.0.0.1:8080/api/v1/servers" \
|
||||
-H "Authorization: Bearer $VIEWER_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"hostname": "test", "ip": "10.0.0.1"}' | python3 -m json.tool
|
||||
# 期望: code=403
|
||||
|
||||
# U3: 验证每个集群包含完整字段
|
||||
curl -s "http://127.0.0.1:8080/api/v1/kubernetes/compare" \
|
||||
-H "Authorization: Bearer $TOKEN" | jq '.data.clusters[0] | keys'
|
||||
# 期望: 19 个字段 (id/name/code/status/node_count/pod_count/.../total_cpu_cores/total_memory_mb/master_count/worker_count)
|
||||
|
||||
# U4: SPA 路由
|
||||
curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:8080/kubernetes/compare
|
||||
# 期望: 200
|
||||
|
||||
# U5: TypeScript + Vite 构建
|
||||
cd frontend && npx tsc --noEmit && npm run build 2>&1 | tail -3
|
||||
# 期望: 零错误 + built in Ns
|
||||
# U5: 前端验证(手动)
|
||||
# 1. 用 viewer_test 登录前端
|
||||
# 2. 确认侧边栏无「删除」按钮
|
||||
# 3. 确认无权限的菜单不显示
|
||||
```
|
||||
|
||||
### 通过标准
|
||||
- [x] U2: Compare API 返回 clusters 数组 + totals 聚合数据
|
||||
- [x] U3: 每个集群包含 19 个字段(含 node 级别聚合数据)
|
||||
- [x] U4: SPA 路由返回 200
|
||||
- [x] U5: TypeScript 零编译错误 + Vite 构建成功
|
||||
- [x] 前端 4 类图表正确渲染(柱状图×2 + 雷达图 + 饼图)
|
||||
- [x] 详细对比表格可点击跳转集群概览
|
||||
- [x] totals 聚合正确(cluster_count/node_count/pod_count/deployment_count/service_count)
|
||||
- [ ] U1-U2: 创建角色和用户成功
|
||||
- [ ] U4: 写接口返回 403
|
||||
- [ ] U5: 前端按钮/菜单按权限显示
|
||||
|
||||
---
|
||||
|
||||
## M14: Namespace 管理看板(资源配额 + 命名空间 CRUD)
|
||||
|
||||
### 验证用例
|
||||
## 回归测试基线(每次改动后必跑)
|
||||
|
||||
```bash
|
||||
# U1: 登录获取 Token
|
||||
TOKEN=$(python3 -c "
|
||||
import urllib.request, json
|
||||
login_data = json.dumps({'username': 'admin', 'password': 'admin123'}).encode()
|
||||
req = urllib.request.Request('http://127.0.0.1:8080/api/v1/auth/login', data=login_data, method='POST')
|
||||
req.add_header('Content-Type', 'application/json')
|
||||
resp = urllib.request.urlopen(req)
|
||||
print(json.loads(resp.read())['data']['token'])
|
||||
")
|
||||
# === 后端回归 ===
|
||||
TOKEN=$(cat /tmp/aiops_token)
|
||||
|
||||
# U2: 命名空间详情 API(含资源计数+配额状态)
|
||||
curl -s "http://127.0.0.1:8080/api/v1/kubernetes/prod-cluster/namespaces/detail" \
|
||||
-H "Authorization: Bearer $TOKEN" | jq '.data | length'
|
||||
# 期望: 返回所有命名空间(含 status/age/labels/resource_counts)
|
||||
# 集群
|
||||
curl -sf http://127.0.0.1:8080/api/v1/kubernetes-clusters -H "Authorization: Bearer $TOKEN" > /dev/null && echo "✅ clusters" || echo "❌ clusters"
|
||||
|
||||
# U3: 字段完整性
|
||||
curl -s "http://127.0.0.1:8080/api/v1/kubernetes/prod-cluster/namespaces/detail" \
|
||||
-H "Authorization: Bearer $TOKEN" | jq '.data[0] | keys'
|
||||
# 期望: 含 name/status/age/labels/resource_counts/has_resource_quota/has_limit_range
|
||||
# Deployments
|
||||
curl -sf "http://127.0.0.1:8080/api/v1/kubernetes/prod-cluster/namespace/devops/deployments" -H "Authorization: Bearer $TOKEN" > /dev/null && echo "✅ deployments" || echo "❌ deployments"
|
||||
|
||||
# U4: 创建命名空间
|
||||
curl -s -X POST "http://127.0.0.1:8080/api/v1/kubernetes/prod-cluster/namespaces" \
|
||||
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
|
||||
-d '{"name":"test-ns-m14","labels":{"env":"test"}}'
|
||||
# 期望: code=200, message="命名空间创建成功"
|
||||
# Pods
|
||||
curl -sf "http://127.0.0.1:8080/api/v1/kubernetes/prod-cluster/namespace/devops/pods" -H "Authorization: Bearer $TOKEN" > /dev/null && echo "✅ pods" || echo "❌ pods"
|
||||
|
||||
# U5: 创建后验证存在于列表
|
||||
curl -s "http://127.0.0.1:8080/api/v1/kubernetes/prod-cluster/namespaces/detail" \
|
||||
-H "Authorization: Bearer $TOKEN" | jq '[.data[] | select(.name=="test-ns-m14")] | length'
|
||||
# 期望: 1
|
||||
# Events
|
||||
curl -sf "http://127.0.0.1:8080/api/v1/kubernetes/prod-cluster/events/summary" -H "Authorization: Bearer $TOKEN" > /dev/null && echo "✅ events" || echo "❌ events"
|
||||
|
||||
# U6: 删除命名空间
|
||||
curl -s -X DELETE "http://127.0.0.1:8080/api/v1/kubernetes/prod-cluster/namespaces/test-ns-m14" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
# 期望: code=200, message="命名空间已删除"
|
||||
# Namespace
|
||||
curl -sf "http://127.0.0.1:8080/api/v1/kubernetes/prod-cluster/namespaces/detail" -H "Authorization: Bearer $TOKEN" > /dev/null && echo "✅ namespaces" || echo "❌ namespaces"
|
||||
|
||||
# U7: 系统命名空间删除保护
|
||||
curl -s -X DELETE "http://127.0.0.1:8080/api/v1/kubernetes/prod-cluster/namespaces/kube-system" \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
# 期望: code=403, message="禁止删除系统命名空间: kube-system"
|
||||
# Servers
|
||||
curl -sf http://127.0.0.1:8080/api/v1/servers -H "Authorization: Bearer $TOKEN" > /dev/null && echo "✅ servers" || echo "❌ servers"
|
||||
|
||||
# U8: SPA 路由
|
||||
curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1/kubernetes/prod-cluster/namespaces
|
||||
# 期望: 200
|
||||
# Pipelines
|
||||
curl -sf http://127.0.0.1:8080/api/v1/pipelines -H "Authorization: Bearer $TOKEN" > /dev/null && echo "✅ pipelines" || echo "❌ pipelines"
|
||||
|
||||
# U9: TypeScript + Vite 构建
|
||||
cd frontend && npx tsc --noEmit && npm run build 2>&1 | tail -3
|
||||
# 期望: 零错误 + built in Ns
|
||||
# Alerts
|
||||
curl -sf http://127.0.0.1:8080/api/v1/alerts/rules -H "Authorization: Bearer $TOKEN" > /dev/null && echo "✅ alerts" || echo "❌ alerts"
|
||||
|
||||
# Agent
|
||||
curl -sf http://127.0.0.1:8080/api/v1/agent/latest -H "Authorization: Bearer $TOKEN" > /dev/null && echo "✅ agent" || echo "❌ agent"
|
||||
|
||||
# Dashboard
|
||||
curl -sf http://127.0.0.1:8080/api/v1/dashboard/stats -H "Authorization: Bearer $TOKEN" > /dev/null && echo "✅ dashboard" || echo "❌ dashboard"
|
||||
|
||||
# === 前端回归 ===
|
||||
cd /srv/aiops/frontend && npm run build 2>&1 | tail -1
|
||||
|
||||
# === 健康检查 ===
|
||||
curl -sf http://127.0.0.1:8080/health > /dev/null && echo "✅ health" || echo "❌ health"
|
||||
curl -sf http://127.0.0.1/ > /dev/null && echo "✅ frontend" || echo "❌ frontend"
|
||||
```
|
||||
|
||||
### 通过标准
|
||||
- [x] U2: Namespaces Detail API 返回完整命名空间列表(含 status/age/resource_counts)
|
||||
- [x] U3: 每个命名空间包含 7 个字段(name/status/age/labels/resource_counts/has_resource_quota/has_limit_range)
|
||||
- [x] U4: 创建命名空间 API 返回 200
|
||||
- [x] U5: 创建后命名空间出现在列表中
|
||||
- [x] U6: 删除命名空间 API 返回 200
|
||||
- [x] U7: 系统命名空间删除被拦截(403)
|
||||
- [x] U8: SPA 路由返回 200
|
||||
- [x] U9: TypeScript 零编译错误 + Vite 构建成功
|
||||
- [x] 前端命名空间管理页表格正确渲染(名称/状态/年龄/资源计数/配额/操作)
|
||||
- [x] 创建/删除弹框功能正常
|
||||
- [x] 集群概览页「管理全部」链接跳转正常
|
||||
Reference in new issue
Block a user