d5d7e45ded
- 后端: FastAPI + kubectl 9大检查项(Pod/Node/Event/Deploy/Service/PVC/资源/网络) - AI Agent: OpenAI兼容接口自动分析故障根因+多轮追问对话 - 前端: Vue3 + Element Plus 仪表盘, 健康评分, 问题列表, 资源监控 - 一键启动脚本 start.sh
109 lines
2.9 KiB
Python
109 lines
2.9 KiB
Python
"""K8S 智能诊断平台 - FastAPI 主应用"""
|
|
import os
|
|
from datetime import datetime
|
|
from fastapi import FastAPI, HTTPException
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from fastapi.staticfiles import StaticFiles
|
|
from pydantic import BaseModel
|
|
from typing import Optional
|
|
|
|
from backend.config import PORT
|
|
from backend.diagnosis import run_full_diagnosis, build_diagnosis_report, ALL_CHECKS
|
|
from backend.ai_agent import analyze_with_ai, chat_with_ai
|
|
|
|
app = FastAPI(title="K8S 智能诊断平台", version="1.0.0")
|
|
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=["*"],
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
# 存储最近诊断结果 (内存)
|
|
_last_diagnosis: Optional[dict] = None
|
|
_last_report: str = ""
|
|
|
|
|
|
class DiagnoseRequest(BaseModel):
|
|
namespace: str = ""
|
|
checks: Optional[list[str]] = None
|
|
|
|
|
|
class AnalyzeRequest(BaseModel):
|
|
question: str = ""
|
|
|
|
|
|
class ChatRequest(BaseModel):
|
|
messages: list[dict]
|
|
|
|
|
|
@app.get("/api/health")
|
|
async def health():
|
|
return {"status": "ok", "time": datetime.now().isoformat()}
|
|
|
|
|
|
@app.get("/api/checks")
|
|
async def list_checks():
|
|
"""列出所有可用诊断项"""
|
|
return {
|
|
"checks": [
|
|
{"name": name, "title": fn.__doc__ or name}
|
|
for name, fn in ALL_CHECKS.items()
|
|
]
|
|
}
|
|
|
|
|
|
@app.post("/api/diagnose")
|
|
async def diagnose(req: DiagnoseRequest):
|
|
"""执行一键诊断"""
|
|
global _last_diagnosis, _last_report
|
|
_last_diagnosis = await run_full_diagnosis(namespace=req.namespace, checks=req.checks)
|
|
_last_report = build_diagnosis_report(_last_diagnosis)
|
|
return _last_diagnosis
|
|
|
|
|
|
@app.get("/api/diagnosis/latest")
|
|
async def get_latest():
|
|
"""获取最近一次诊断结果"""
|
|
if _last_diagnosis is None:
|
|
raise HTTPException(status_code=404, detail="暂无诊断记录,请先执行诊断")
|
|
return _last_diagnosis
|
|
|
|
|
|
@app.post("/api/analyze")
|
|
async def analyze(req: AnalyzeRequest):
|
|
"""AI 分析诊断结果"""
|
|
global _last_diagnosis, _last_report
|
|
if _last_diagnosis is None:
|
|
_last_diagnosis = await run_full_diagnosis()
|
|
_last_report = build_diagnosis_report(_last_diagnosis)
|
|
result = await analyze_with_ai(_last_report, question=req.question)
|
|
return result
|
|
|
|
|
|
@app.post("/api/chat")
|
|
async def chat(req: ChatRequest):
|
|
"""AI 多轮对话 (基于诊断上下文追问)"""
|
|
result = await chat_with_ai(req.messages, context=_last_report)
|
|
return result
|
|
|
|
|
|
@app.get("/api/report")
|
|
async def get_report():
|
|
"""获取诊断报告文本"""
|
|
if not _last_report:
|
|
raise HTTPException(status_code=404, detail="暂无诊断报告")
|
|
return {"report": _last_report}
|
|
|
|
|
|
# 静态文件服务 (前端)
|
|
static_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), "frontend", "dist")
|
|
if os.path.isdir(static_dir):
|
|
app.mount("/", StaticFiles(directory=static_dir, html=True), name="static")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
import uvicorn
|
|
uvicorn.run(app, host="0.0.0.0", port=PORT)
|