162 lines
4.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package taskdebug
import (
"context"
"devops/agent/script"
"devops/agent/tasks"
"devops/server/apps/task"
"fmt"
"strings"
"time"
)
const (
TASK_NAME = "task_debug"
)
func init() {
tasks.RegisterTaskRunner(TASK_NAME, &TaskDebugRunner{})
}
// 实现一个 task_debug 任务
type TaskDebugRunner struct{}
func (t *TaskDebugRunner) Run(ctx context.Context, spec *task.TaskSpec) (*task.Task, error) {
// 直接使用单元测试的上下文, 方便取消
req := script.NewExecuteScriptRequest("task_debug.sh", []string{})
req.SetWorkDir(spec.GetWorkDir())
req.SetTimeout(spec.GetTimeout())
req.SetDebugScript(true)
req.SetLogFile("stdout.txt")
// Task的日志后面会通过Websocket 实时上报给Api Server 右API Server进行日志的实时展示
req.SetLogCallback(func(s string) {
fmt.Print(s)
})
// 添加输入参数
for k, v := range spec.InputParams {
req.SetEnv(k, v)
}
resp, err := script.ExecuteScript(ctx, req)
if err != nil {
return nil, err
}
// 将resp 转化为 TaskStatus
taskIns := task.NewTask(spec)
MapExecutionResultToTask(taskIns, resp)
// 使用脚本执行
return taskIns, nil
}
// MapExecutionResultToTask updates a Task with execution results
func MapExecutionResultToTask(task *task.Task, result *script.ExecutionResult) {
if task == nil || result == nil {
return
}
// Update TaskStatus fields from ExecutionResult
task.TaskStatus = convertExecutionResultToStatus(result)
// Optionally update some TaskSpec fields if needed
// For example, if you want to store output params in the task spec extras
if len(result.OutputParams) > 0 && task.TaskSpec.Extras == nil {
task.TaskSpec.Extras = make(map[string]string)
}
for k, v := range result.OutputParams {
task.TaskSpec.Extras["output_"+k] = v
}
}
// convertExecutionResultToStatus converts ExecutionResult to TaskStatus
func convertExecutionResultToStatus(result *script.ExecutionResult) *task.TaskStatus {
status := &task.TaskStatus{
Status: mapSuccessToStatus(result.Success, result.Skipped),
Message: getMessage(result),
Detail: getDetail(result),
StartAt: &result.StartTime,
EndAt: getEndTime(result),
UpdateAt: time.Now(),
Output: result.OutputParams,
Extras: make(map[string]string),
}
// Add file contents to extras if present
if len(result.FileContents) > 0 {
for k, v := range result.FileContents {
status.Extras["file_"+k] = v
}
}
// Add command execution details
if result.Command != "" {
status.Extras["executed_command"] = result.Command
}
if result.ExitCode != 0 {
status.Extras["exit_code"] = fmt.Sprintf("%d", result.ExitCode)
}
if result.Duration > 0 {
status.Extras["duration"] = result.Duration.String()
}
return status
}
// mapSuccessToStatus maps execution result success/skipped to task status
func mapSuccessToStatus(success bool, skipped bool) task.STATUS {
if skipped {
return task.STATUS_SKIP
}
if success {
return task.STATUS_SUCCESS
}
return task.STATUS_FAILED
}
// getMessage combines error and message from execution result
func getMessage(result *script.ExecutionResult) string {
if result.Error != "" {
return result.Error
}
return result.Message
}
// getDetail creates a detailed message from execution result
func getDetail(result *script.ExecutionResult) string {
var details []string
if result.Command != "" {
details = append(details, fmt.Sprintf("Command: %s", result.Command))
}
if result.ExitCode != 0 {
details = append(details, fmt.Sprintf("Exit Code: %d", result.ExitCode))
}
if result.Duration > 0 {
details = append(details, fmt.Sprintf("Duration: %v", result.Duration))
}
if result.Error != "" && result.Error != result.Message {
details = append(details, fmt.Sprintf("Error: %s", result.Error))
}
if result.Message != "" && result.Message != result.Error {
details = append(details, fmt.Sprintf("Message: %s", result.Message))
}
return strings.Join(details, "\n")
}
// getEndTime returns the end time or current time if nil
func getEndTime(result *script.ExecutionResult) time.Time {
if result.EndTime != nil {
return *result.EndTime
}
return time.Now()
}