diff --git a/automation/agent/exec/controller/action.go b/automation/agent/exec/controller/action.go index e465a2a00c90bea30c5a91ce770ecedb1b76aa85..275901a7354ad9a2ea4e0ed7383edea5f3933bdb 100644 --- a/automation/agent/exec/controller/action.go +++ b/automation/agent/exec/controller/action.go @@ -73,3 +73,22 @@ func GetActionStatus(c *gin.Context) { } response.Fail(c, nil, "任务不存在") } + +func GetActionResult(c *gin.Context) { + var jobParam struct { + JobId string `json:"job_id"` + ScriptId string `json:"script_id"` + } + if err := c.ShouldBindJSON(&jobParam); err != nil { + response.Fail(c, nil, "参数错误") + return + } + + result, err := service.GetActionResult(jobParam.JobId, jobParam.ScriptId) + if err != nil { + response.Fail(c, nil, "获取任务结果失败: "+err.Error()) + return + } + + response.Success(c, result, "获取任务结果成功") +} diff --git a/automation/agent/exec/model/action.go b/automation/agent/exec/model/action.go index eab1a1d542122349a6f133cc063f12de0450ef5c..55fb154a3de1909ab5e65dc63c52d943589ad277 100644 --- a/automation/agent/exec/model/action.go +++ b/automation/agent/exec/model/action.go @@ -11,10 +11,11 @@ type ActionTask struct { } type ActionResultResponse struct { - JobId string - ScriptId string - Status string - StartTime string - EndTime string - Result *CmdResult + JobId string `json:"job_id"` + ScriptId string `json:"script_id"` + Status string `json:"status"` + StartTime string `json:"start_time"` + EndTime string `json:"end_time"` + IP string `json:"ip"` + Result *CmdResult `json:"result"` } diff --git a/automation/agent/exec/router.go b/automation/agent/exec/router.go index 2f2a823c9b98de5bd19ee8d90fab3e5610de4923..fb9478deafd84570506599b64770ca546ad5abde 100644 --- a/automation/agent/exec/router.go +++ b/automation/agent/exec/router.go @@ -12,5 +12,6 @@ func ExecHandler(router *gin.RouterGroup) { api.POST("/action", controller.ActionExec) api.POST("/action/cancel", controller.CancelAction) api.POST("/action/status", controller.GetActionStatus) + api.POST("/action/result", controller.GetActionResult) } } diff --git a/automation/agent/exec/service/action.go b/automation/agent/exec/service/action.go index 989db2004388f553ecd6d9689f497182bd6bf734..af162412e5471a1e317ddee424b25ff900dc0428 100644 --- a/automation/agent/exec/service/action.go +++ b/automation/agent/exec/service/action.go @@ -2,7 +2,9 @@ package service import ( "ant-agent/exec/model" + "ant-agent/pkg/global" "encoding/json" + "fmt" "os" "time" @@ -43,9 +45,11 @@ func ActionExecWithStatus(task *model.ActionTask, taskStatus *TaskStatus) { } result := &model.CmdResult{ - Stdout: stdout, - Stderr: stderr, - RetCode: execCode, + Stdout: stdout, + Stderr: stderr, + RetCode: execCode, + StartTime: startTime, + EndTime: time.Now().Format("2006-01-02 15:04:05"), } resultResponse := &model.ActionResultResponse{ JobId: task.JobId, @@ -53,6 +57,7 @@ func ActionExecWithStatus(task *model.ActionTask, taskStatus *TaskStatus) { Status: taskStatus.Status, StartTime: startTime, EndTime: time.Now().Format("2006-01-02 15:04:05"), + IP: global.HttpAddr, Result: result, } logger.Debug("script execution result: %+v", resultResponse) @@ -71,3 +76,16 @@ func ActionExecWithStatus(task *model.ActionTask, taskStatus *TaskStatus) { TaskManager.Tasks.Delete(task.JobId + "_" + task.ScriptId) logger.Info("脚本执行结果已写入文件: %s", resultFilePath) } + +func GetActionResult(jobId, scriptId string) (*model.ActionResultResponse, error) { + data, err := getResult(jobId, scriptId) + if err != nil { + return nil, err + } + + var result model.ActionResultResponse + if err := json.Unmarshal(data, &result); err != nil { + return nil, fmt.Errorf("解析任务结果失败: %s", err.Error()) + } + return &result, nil +} diff --git a/automation/agent/exec/service/common.go b/automation/agent/exec/service/common.go index e5184b16968eb9c93ef80084f1062baaff076fe0..e0d9ab23f15e2baf731c97d32bce73763d3a2310 100644 --- a/automation/agent/exec/service/common.go +++ b/automation/agent/exec/service/common.go @@ -10,6 +10,9 @@ import ( "time" ) +var JobsBaseDir = "./srv/jobs" +var ScriptsBaseDir = "./srv/scripts" + func getScriptInfo(scriptType string) (suffix string, interpreter string, err error) { switch scriptType { case "Shell": @@ -40,7 +43,6 @@ func parseEscapeSequences(s string) string { } func createScriptFile(tag, scriptId, suffix, encodedScript string) (string, error) { - var baseDir = "./srv/scripts" decodedScript, err := base64.StdEncoding.DecodeString(encodedScript) if err != nil { return "", fmt.Errorf("脚本内容base64解码失败: %s", err.Error()) @@ -49,7 +51,7 @@ func createScriptFile(tag, scriptId, suffix, encodedScript string) (string, erro // 解析转义字符 parsedScript := parseEscapeSequences(string(decodedScript)) - scriptDir := fmt.Sprintf("%s/%s", baseDir, tag) + scriptDir := fmt.Sprintf("%s/%s", ScriptsBaseDir, tag) if _, err := os.Stat(scriptDir); os.IsNotExist(err) { if err := os.MkdirAll(scriptDir, 0755); err != nil { return "", fmt.Errorf("创建脚本存储目录失败: %s", err.Error()) @@ -70,9 +72,7 @@ func createScriptFile(tag, scriptId, suffix, encodedScript string) (string, erro } func createJobResultPath(jobId, scriptId string) (string, error) { - var baseDir = "./srv/jobs" - - resultDir := fmt.Sprintf("%s/jobId_%s", baseDir, jobId) + resultDir := fmt.Sprintf("%s/jobId_%s", JobsBaseDir, jobId) if _, err := os.Stat(resultDir); os.IsNotExist(err) { if err := os.MkdirAll(resultDir, 0755); err != nil { return "", fmt.Errorf("创建执行结果存储目录失败: %s", err.Error()) @@ -126,3 +126,17 @@ func runScriptWithCancel(interpreter, scriptPath string, params string, timeoutS return strings.TrimSpace(stdout.String()), strings.TrimSpace(stderr.String()), cmd.ProcessState.ExitCode(), err } } + +func getResult(jobId string, scriptId string) ([]byte, error) { + resultFilePath := fmt.Sprintf("%s/jobId_%s/result_%s.json", JobsBaseDir, jobId, scriptId) + if _, err := os.Stat(resultFilePath); os.IsNotExist(err) { + return nil, fmt.Errorf("任务结果不存在") + } + + data, err := os.ReadFile(resultFilePath) + if err != nil { + return nil, fmt.Errorf("读取任务结果失败: %s", err.Error()) + } + return data, nil + +} diff --git a/automation/server/internal/module/common/exec/action.go b/automation/server/internal/module/common/exec/action.go index d247eef271606e5ce3290b494c773f7f154af253..3f6e8dea2b0f555636bad22571a4f624eb1b5329 100644 --- a/automation/server/internal/module/common/exec/action.go +++ b/automation/server/internal/module/common/exec/action.go @@ -61,3 +61,52 @@ func ExecAction(ip string, sr ActionTask) error { } return nil } + +func GetActionResult(ip string, jobId, scriptId string) (interface{}, error) { + addr := fmt.Sprintf("http://%s:8277/plugin/automation/exec/action/result", ip) + dataMarshed, err := json.Marshal(struct { + JobId string `json:"job_id"` + ScriptId string `json:"script_id"` + }{ + JobId: jobId, + ScriptId: scriptId, + }) + if err != nil { + return nil, err + } + request, err := http.NewRequest("POST", addr, bytes.NewBuffer(dataMarshed)) + if err != nil { + return nil, err + } + request.Header.Set("Content-Type", "application/json") + client := &http.Client{ + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: true, + }, + }, + } + response, err := client.Do(request) + if err != nil { + return nil, err + } + defer response.Body.Close() + + body, err := io.ReadAll(response.Body) + if err != nil { + return nil, err + } + + var result struct { + Message string `json:"message"` + Code int `json:"code"` + Data interface{} `json:"data"` + } + if err := json.Unmarshal(body, &result); err != nil { + return nil, fmt.Errorf("解析响应体失败: %s", err.Error()) + } + if result.Code != http.StatusOK { + return nil, fmt.Errorf("操作任务结果获取失败, 报错: %s", result.Message) + } + return result.Data, nil +} diff --git a/automation/server/internal/module/job_action/controller/exec.go b/automation/server/internal/module/job_action/controller/exec.go index 5e3597ee7f8fd81ac9bfe0f1acf9f90adbc1a6d7..7519656d104f91066f2eae47f2ea136e6d13e8ba 100644 --- a/automation/server/internal/module/job_action/controller/exec.go +++ b/automation/server/internal/module/job_action/controller/exec.go @@ -10,10 +10,10 @@ import ( func ExecScriptHandler(c *gin.Context) { var sr struct { - IPs []string `json:"IPs"` - ScriptID string `json:"script_id"` - Params string `json:"params"` - TimeOutSec int `json:"timeoutSec"` + IPs string `json:"IPs"` + ScriptID string `json:"scriptId"` + Params string `json:"params"` + TimeOutSec int `json:"timeoutSec"` } if err := c.ShouldBindJSON(&sr); err != nil { response.Fail(c, nil, err.Error()) @@ -22,8 +22,28 @@ func ExecScriptHandler(c *gin.Context) { jobId, err := service.ExecScript(sr.IPs, sr.ScriptID, sr.Params, sr.TimeOutSec) if err != nil { - response.Fail(c, gin.H{"job_id": jobId}, fmt.Sprintf("下发脚本任务失败: %s", err.Error())) + response.Fail(c, gin.H{"jobId": jobId}, fmt.Sprintf("下发脚本任务失败: %s", err.Error())) return } - response.Success(c, gin.H{"job_id": jobId}, "success") + response.Success(c, gin.H{"jobId": jobId}, "success") +} + +func GetActionResultHandler(c *gin.Context) { + var actionResult struct { + IPs string `json:"IPs"` + JobId string `json:"jobId"` + ScriptId string `json:"scriptId"` + } + if err := c.ShouldBindJSON(&actionResult); err != nil { + response.Fail(c, nil, "参数错误") + return + } + + result, err := service.GetActionResult(actionResult.IPs, actionResult.JobId, actionResult.ScriptId) + if err != nil { + response.Fail(c, nil, "获取任务结果失败: "+err.Error()) + return + } + + response.Success(c, result, "获取任务结果成功") } diff --git a/automation/server/internal/module/job_action/router.go b/automation/server/internal/module/job_action/router.go index e77982de74e8b9b27704399429c10d79d51f8d1c..49af4f9ae6cc8adec5b6996291b7ff44c329db96 100644 --- a/automation/server/internal/module/job_action/router.go +++ b/automation/server/internal/module/job_action/router.go @@ -9,5 +9,6 @@ func JobActionHandler(router *gin.RouterGroup) { api := router.Group("/action") { api.POST("/exec", controller.ExecScriptHandler) + api.POST("/result", controller.GetActionResultHandler) } } diff --git a/automation/server/internal/module/job_action/service/exec.go b/automation/server/internal/module/job_action/service/exec.go index c5c39237a3fd923b88e9e6e3ed655c6bf8b380b3..3ec21f3c464e49189063eea7e5584e768decd434 100644 --- a/automation/server/internal/module/job_action/service/exec.go +++ b/automation/server/internal/module/job_action/service/exec.go @@ -1,6 +1,8 @@ package service import ( + "strings" + "github.com/google/uuid" "openeuler.org/PilotGo/PilotGo-plugin-automation/internal/module/common/exec" "openeuler.org/PilotGo/PilotGo-plugin-automation/internal/module/script_library/dao" @@ -10,7 +12,7 @@ func generateJobId() string { return uuid.New().String() } -func ExecScript(ips []string, scriptID, params string, timeoutSec int) (string, error) { +func ExecScript(ips string, scriptID, params string, timeoutSec int) (string, error) { jobId := generateJobId() scriptType, scriptTag, encodeScriptContent, err := dao.GetPublishedScriptByScriptId(scriptID) @@ -18,7 +20,7 @@ func ExecScript(ips []string, scriptID, params string, timeoutSec int) (string, return "", err } - for _, ip := range ips { + for _, ip := range strings.Split(ips, ",") { sr := exec.ActionTask{ JobId: jobId, ScriptId: scriptID, @@ -35,3 +37,15 @@ func ExecScript(ips []string, scriptID, params string, timeoutSec int) (string, } return jobId, nil } + +func GetActionResult(ips string, jobId, scriptId string) (interface{}, error) { + var results []interface{} + for _, ip := range strings.Split(ips, ",") { + result, err := exec.GetActionResult(ip, jobId, scriptId) + if err != nil { + return nil, err + } + results = append(results, result) + } + return results, nil +}