feat: add cmd task call
This commit is contained in:
@@ -42,10 +42,17 @@ func InitBasic() *App {
|
||||
return app
|
||||
}
|
||||
|
||||
func (a *App) initConfig() {
|
||||
a.initConfigWithPath(constant.ConfigPath)
|
||||
// InitBasicForCmd 专为命令行工具定制的基础环境初始化入口
|
||||
// 内部会调高控制台日志过滤级别以自动静默屏蔽刷屏的底层系统与组件启动 Info 日志
|
||||
func InitBasicForCmd() *App {
|
||||
logger.SetLevel("warn")
|
||||
return InitBasic()
|
||||
}
|
||||
|
||||
// func (a *App) initConfig() {
|
||||
// a.initConfigWithPath(constant.ConfigPath)
|
||||
// }
|
||||
|
||||
func (a *App) initConfigWithPath(path string) {
|
||||
cfg, err := services.LoadConfig(path)
|
||||
if err != nil {
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package bootstrap
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/engigu/baihu-panel/internal/services"
|
||||
)
|
||||
|
||||
// SendInternalRequest 向常驻后台主服务安全发送内部通信请求
|
||||
// relPath 传入相对内部接口路径 (如: "/internal/tasks/execute/xxx"),方法内部会自动补充完整的协议、端口及 "/api/v1" 前缀,
|
||||
// 并自动获取 security.secret 密钥种入 X-Internal-Token 头部。
|
||||
func SendInternalRequest(method, relPath string, payload interface{}) ([]byte, int, error) {
|
||||
appCfg := services.GetConfig()
|
||||
if appCfg == nil {
|
||||
return nil, 0, fmt.Errorf("加载系统配置失败")
|
||||
}
|
||||
|
||||
relPath = strings.TrimPrefix(relPath, "/")
|
||||
url := fmt.Sprintf("http://127.0.0.1:%d/api/v1/%s", appCfg.Server.Port, relPath)
|
||||
|
||||
var bodyReader io.Reader
|
||||
if payload != nil {
|
||||
jsonData, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("序列化请求负载失败: %v", err)
|
||||
}
|
||||
bodyReader = bytes.NewBuffer(jsonData)
|
||||
}
|
||||
|
||||
settings := services.NewSettingsService()
|
||||
secret := settings.Get("security", "secret")
|
||||
|
||||
req, err := http.NewRequest(method, url, bodyReader)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("创建 HTTP 请求失败: %v", err)
|
||||
}
|
||||
|
||||
if payload != nil {
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
}
|
||||
req.Header.Set("X-Internal-Token", secret)
|
||||
|
||||
client := &http.Client{Timeout: 5 * time.Second}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("网络连接失败,请确保白虎面板常驻后台服务正在运行中: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
bodyBytes, err := io.ReadAll(resp.Body)
|
||||
return bodyBytes, resp.StatusCode, err
|
||||
}
|
||||
@@ -28,4 +28,8 @@ var Commands = []CommandInfo{
|
||||
Name: "builtininstall",
|
||||
Description: "为所有 mise 管理的 Node.js 和 Python 环境安装内建助手库",
|
||||
},
|
||||
{
|
||||
Name: "task",
|
||||
Description: "系统级任务的列表查询、触发运行、启停控制及状态查看",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -619,3 +619,80 @@ func (tc *TaskController) SyncRepoTasks(c *gin.Context) {
|
||||
tc.executorService.SyncRepoTasks(req.UpsertedIDs, req.DeletedIDs)
|
||||
utils.SuccessMsg(c, "增量同步成功")
|
||||
}
|
||||
|
||||
// ToggleTask 切换任务启用/禁用状态
|
||||
func (tc *TaskController) ToggleTask(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
if id == "" {
|
||||
utils.BadRequest(c, "无效的任务ID")
|
||||
return
|
||||
}
|
||||
|
||||
var req struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
utils.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
task := tc.taskService.GetTaskByID(id)
|
||||
if task == nil {
|
||||
utils.NotFound(c, "任务不存在")
|
||||
return
|
||||
}
|
||||
|
||||
// 获取旧 AgentID
|
||||
var oldAgentID *string
|
||||
oldAgentID = task.AgentID
|
||||
|
||||
// 构造更新参数,仅修改 Enabled
|
||||
param := tasks.TaskParam{
|
||||
Name: task.Name,
|
||||
Remark: task.Remark,
|
||||
Command: string(task.Command),
|
||||
PreCommand: string(task.PreCommand),
|
||||
PostCommand: string(task.PostCommand),
|
||||
Tags: task.Tags,
|
||||
Type: task.Type,
|
||||
Config: string(task.Config),
|
||||
Schedule: task.Schedule,
|
||||
Timeout: task.Timeout,
|
||||
WorkDir: task.WorkDir,
|
||||
CleanConfig: task.CleanConfig,
|
||||
Envs: string(task.Envs),
|
||||
Languages: task.Languages,
|
||||
AgentID: task.AgentID,
|
||||
TriggerType: task.TriggerType,
|
||||
RetryCount: task.RetryCount,
|
||||
RetryInterval: task.RetryInterval,
|
||||
RandomRange: task.RandomRange,
|
||||
SourceID: task.SourceID,
|
||||
PinType: task.PinType,
|
||||
Enabled: req.Enabled,
|
||||
}
|
||||
|
||||
updatedTask := tc.taskService.UpdateTask(id, ¶m)
|
||||
if updatedTask == nil {
|
||||
utils.NotFound(c, "任务不存在")
|
||||
return
|
||||
}
|
||||
|
||||
// 处理调度器更新
|
||||
if updatedTask.AgentID != nil && *updatedTask.AgentID != "" {
|
||||
tc.executorService.RemoveCronTask(updatedTask.ID)
|
||||
tc.agentWSManager.BroadcastTasks(*updatedTask.AgentID)
|
||||
} else {
|
||||
if req.Enabled {
|
||||
tc.executorService.AddCronTask(updatedTask)
|
||||
} else {
|
||||
tc.executorService.RemoveCronTask(updatedTask.ID)
|
||||
}
|
||||
if oldAgentID != nil && *oldAgentID != "" {
|
||||
tc.agentWSManager.BroadcastTasks(*oldAgentID)
|
||||
}
|
||||
}
|
||||
|
||||
utils.Success(c, vo.ToTaskVO(updatedTask))
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,8 @@ func initPublicAPIRoutes(api *gin.RouterGroup, c *Controllers) {
|
||||
internalAPI.Use(middleware.LocalhostOnly())
|
||||
{
|
||||
internalAPI.POST("/tasks/sync-repo-status", c.Task.SyncRepoTasks)
|
||||
internalAPI.POST("/tasks/execute/:id", c.Executor.ExecuteTask)
|
||||
internalAPI.POST("/tasks/toggle/:id", c.Task.ToggleTask)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user