fix: 修复集群不可达时误报100分的严重bug
- 新增 check_connectivity() 连通性预检: kubectl存在性/kubeconfig/API Server连接 - 连不上集群直接返回0分+明确错误信息+排查建议(不再静默跳过) - 每个检查项kubectl失败时必须报critical问题(不再忽略error) - 前端: 连接失败时显示红色错误页+错误详情+排查建议+重新诊断按钮 - 智能识别常见错误: connection refused/证书过期/超时/DNS解析失败等
This commit is contained in:
+44
-6
@@ -13,6 +13,7 @@ from typing import Optional
|
||||
from backend.config import PORT
|
||||
from backend.diagnosis import (
|
||||
run_full_diagnosis, build_diagnosis_report, ALL_CHECKS,
|
||||
check_connectivity,
|
||||
check_cluster_info, check_pods, check_nodes, check_events,
|
||||
check_deployments, check_services, check_pvc, check_resource_usage,
|
||||
check_network_policies,
|
||||
@@ -82,12 +83,46 @@ async def diagnose_stream(namespace: str = ""):
|
||||
|
||||
async def event_generator():
|
||||
start = datetime.now()
|
||||
|
||||
# ★ 第一步: 连通性检查
|
||||
yield f"data: {json.dumps({'type': 'progress', 'step': 0, 'total': len(CHECK_ORDER) + 1, 'name': 'connectivity', 'title': '集群连通性检查', 'status': 'running'}, ensure_ascii=False)}\n\n"
|
||||
|
||||
conn = await check_connectivity()
|
||||
if not conn["connected"]:
|
||||
yield f"data: {json.dumps({'type': 'progress', 'step': 0, 'total': len(CHECK_ORDER) + 1, 'name': 'connectivity', 'title': '集群连通性检查', 'status': 'done', 'issues': 1}, ensure_ascii=False)}\n\n"
|
||||
|
||||
diagnosis = {
|
||||
"timestamp": start.isoformat(),
|
||||
"elapsed_seconds": round((datetime.now() - start).total_seconds(), 2),
|
||||
"namespace": namespace or "all",
|
||||
"score": 0,
|
||||
"status": "critical",
|
||||
"connected": False,
|
||||
"connectivity_error": conn["error"],
|
||||
"connectivity_suggestion": conn.get("suggestion", ""),
|
||||
"critical_count": 1,
|
||||
"warning_count": 0,
|
||||
"issues": [{
|
||||
"level": "critical",
|
||||
"check": "集群连通性",
|
||||
"resource": "API Server",
|
||||
"message": f"无法连接到集群: {conn['error'][:300]}",
|
||||
}],
|
||||
"checks": {},
|
||||
}
|
||||
_last_diagnosis = diagnosis
|
||||
_last_report = build_diagnosis_report(diagnosis)
|
||||
yield f"data: {json.dumps({'type': 'complete', 'diagnosis': diagnosis}, ensure_ascii=False)}\n\n"
|
||||
return
|
||||
|
||||
yield f"data: {json.dumps({'type': 'progress', 'step': 0, 'total': len(CHECK_ORDER) + 1, 'name': 'connectivity', 'title': '集群连通性检查', 'status': 'done', 'issues': 0}, ensure_ascii=False)}\n\n"
|
||||
|
||||
# ★ 第二步: 执行各项检查
|
||||
results = {}
|
||||
all_issues = []
|
||||
total = len(CHECK_ORDER)
|
||||
total = len(CHECK_ORDER) + 1
|
||||
|
||||
for idx, (name, title, fn) in enumerate(CHECK_ORDER, 1):
|
||||
# 推送: 开始检查
|
||||
yield f"data: {json.dumps({'type': 'progress', 'step': idx, 'total': total, 'name': name, 'title': title, 'status': 'running'}, ensure_ascii=False)}\n\n"
|
||||
|
||||
try:
|
||||
@@ -101,10 +136,13 @@ async def diagnose_stream(namespace: str = ""):
|
||||
issue["check"] = title
|
||||
all_issues.append(issue)
|
||||
except Exception as e:
|
||||
results[name] = {"name": name, "title": title, "error": str(e), "issues": []}
|
||||
issue_count = -1
|
||||
results[name] = {
|
||||
"name": name, "title": title, "error": str(e),
|
||||
"issues": [{"level": "critical", "resource": name, "message": f"检查执行异常: {str(e)}"}],
|
||||
}
|
||||
issue_count = 1
|
||||
all_issues.append({"level": "critical", "check": title, "resource": name, "message": f"检查执行异常: {str(e)}"})
|
||||
|
||||
# 推送: 完成检查
|
||||
yield f"data: {json.dumps({'type': 'progress', 'step': idx, 'total': total, 'name': name, 'title': title, 'status': 'done', 'issues': issue_count}, ensure_ascii=False)}\n\n"
|
||||
|
||||
# 汇总
|
||||
@@ -120,6 +158,7 @@ async def diagnose_stream(namespace: str = ""):
|
||||
"namespace": namespace or "all",
|
||||
"score": score,
|
||||
"status": status,
|
||||
"connected": True,
|
||||
"critical_count": len(critical),
|
||||
"warning_count": len(warning),
|
||||
"issues": all_issues,
|
||||
@@ -129,7 +168,6 @@ async def diagnose_stream(namespace: str = ""):
|
||||
_last_diagnosis = diagnosis
|
||||
_last_report = build_diagnosis_report(diagnosis)
|
||||
|
||||
# 推送: 最终结果
|
||||
yield f"data: {json.dumps({'type': 'complete', 'diagnosis': diagnosis}, ensure_ascii=False)}\n\n"
|
||||
|
||||
return StreamingResponse(
|
||||
|
||||
Reference in New Issue
Block a user