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, }}) }