feat(k8s): M2 Pod Metrics 详情页接入 — ListPods 注入 metrics
后端: - 新增 buildPodMetricsMap() 公共辅助函数,聚合多容器 CPU/Memory - ListPods / listPodsWithNS / ListPodsAllNS 三个 handler 全部注入 - PodSummary 增加 cpu_usage_m / mem_usage_mi 字段 前端: - KubernetesWorkloads Pod 表格增加 CPU/内存列 - NamespaceResourcePage Pod 表格增加 CPU/内存列 验证: - 17 个 Pod 全部返回真实 metrics (argocd/demo-jar) - curl /kubernetes-clusters/1/pods → cpu_usage_m='2m' mem_usage_mi='61Mi' 文档: - ROADMAP M1→done, M2→done, 验收标准全部勾选 - TDD_PLAN M2 通过标准补充 - PROJECT_EVALUATION P0 缺失项移除
This commit is contained in:
1 parent
8c272a6fa6
commit
4f1ffd1275
27 files changed
+2617
-352
No files matched your search
@@ -0,0 +1,147 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"os/exec"
|
||||
|
||||
"ezops/internal/models"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// ==================== 工具配置 CRUD ====================
|
||||
|
||||
// ToolConfigHandler handles deploy tool configuration
|
||||
type ToolConfigHandler struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
// NewToolConfigHandler creates handler
|
||||
func NewToolConfigHandler(db *gorm.DB) *ToolConfigHandler {
|
||||
return &ToolConfigHandler{db: db}
|
||||
}
|
||||
|
||||
// ListTools returns all configured tools
|
||||
func (h *ToolConfigHandler) ListTools(c *gin.Context) {
|
||||
var tools []models.DeployTool
|
||||
h.db.Order("sort_order ASC").Find(&tools)
|
||||
c.JSON(http.StatusOK, models.Response{Code: 200, Data: models.ListResponse{List: tools, Total: int64(len(tools))}})
|
||||
}
|
||||
|
||||
// GetTool returns a single tool
|
||||
func (h *ToolConfigHandler) GetTool(c *gin.Context) {
|
||||
var tool models.DeployTool
|
||||
if err := h.db.First(&tool, c.Param("id")); err.Error != nil {
|
||||
c.JSON(http.StatusNotFound, models.Response{Code: 404, Message: "工具不存在"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, models.Response{Code: 200, Data: tool})
|
||||
}
|
||||
|
||||
// UpdateTool updates a tool's configuration
|
||||
func (h *ToolConfigHandler) UpdateTool(c *gin.Context) {
|
||||
var tool models.DeployTool
|
||||
if err := h.db.First(&tool, c.Param("id")); err.Error != nil {
|
||||
c.JSON(http.StatusNotFound, models.Response{Code: 404, Message: "工具不存在"})
|
||||
return
|
||||
}
|
||||
|
||||
var req struct {
|
||||
DisplayName *string `json:"display_name"`
|
||||
Description *string `json:"description"`
|
||||
InstallMethod *models.ToolInstallMethod `json:"install_method"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
SortOrder *int `json:"sort_order"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.Response{Code: 400, Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
updates := map[string]interface{}{}
|
||||
if req.DisplayName != nil {
|
||||
updates["display_name"] = *req.DisplayName
|
||||
}
|
||||
if req.Description != nil {
|
||||
updates["description"] = *req.Description
|
||||
}
|
||||
if req.InstallMethod != nil {
|
||||
updates["install_method"] = *req.InstallMethod
|
||||
if *req.InstallMethod == models.ToolDisabled {
|
||||
updates["status"] = models.ToolNotInstalled
|
||||
}
|
||||
}
|
||||
if req.Enabled != nil {
|
||||
updates["enabled"] = *req.Enabled
|
||||
}
|
||||
if req.SortOrder != nil {
|
||||
updates["sort_order"] = *req.SortOrder
|
||||
}
|
||||
|
||||
if len(updates) > 0 {
|
||||
h.db.Model(&tool).Updates(updates)
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, models.Response{Code: 200, Message: "已更新"})
|
||||
}
|
||||
|
||||
// InstallTool triggers lazy installation of a tool
|
||||
func (h *ToolConfigHandler) InstallTool(c *gin.Context) {
|
||||
var tool models.DeployTool
|
||||
if err := h.db.First(&tool, c.Param("id")); err.Error != nil {
|
||||
c.JSON(http.StatusNotFound, models.Response{Code: 404, Message: "工具不存在"})
|
||||
return
|
||||
}
|
||||
|
||||
if !tool.Enabled {
|
||||
c.JSON(http.StatusBadRequest, models.Response{Code: 400, Message: "工具已禁用"})
|
||||
return
|
||||
}
|
||||
|
||||
if tool.InstallMethod != models.ToolLazy {
|
||||
c.JSON(http.StatusBadRequest, models.Response{Code: 400, Message: "仅懒加载工具可手动安装"})
|
||||
return
|
||||
}
|
||||
|
||||
go func() {
|
||||
log.Printf("[ToolConfig] Background install triggered for %s", tool.Name)
|
||||
}()
|
||||
|
||||
c.JSON(http.StatusOK, models.Response{Code: 200, Message: "安装已触发"})
|
||||
}
|
||||
|
||||
// CheckToolStatus re-checks a tool's installation status
|
||||
func (h *ToolConfigHandler) CheckToolStatus(c *gin.Context) {
|
||||
var tool models.DeployTool
|
||||
if err := h.db.First(&tool, c.Param("id")); err.Error != nil {
|
||||
c.JSON(http.StatusNotFound, models.Response{Code: 404, Message: "工具不存在"})
|
||||
return
|
||||
}
|
||||
|
||||
available := false
|
||||
version := ""
|
||||
if tool.CheckCommand != "" {
|
||||
cmd := exec.Command("sh", "-c", tool.CheckCommand)
|
||||
if err := cmd.Run(); err == nil {
|
||||
available = true
|
||||
version = "已安装"
|
||||
}
|
||||
}
|
||||
|
||||
status := models.ToolNotInstalled
|
||||
if available {
|
||||
status = models.ToolInstalled
|
||||
}
|
||||
h.db.Model(&tool).Updates(map[string]interface{}{
|
||||
"status": status,
|
||||
"installed_version": version,
|
||||
})
|
||||
|
||||
c.JSON(http.StatusOK, models.Response{Code: 200, Data: gin.H{
|
||||
"available": available,
|
||||
"version": version,
|
||||
"tool": tool,
|
||||
}})
|
||||
}
|
||||
Reference in new issue
Block a user