Files
ProjectOctopus/agent-go/executor/CommandExecutor.go
2024-01-22 14:33:55 +08:00

168 lines
4.6 KiB
Go

package executor
import (
"bufio"
"bytes"
"fmt"
"os/exec"
"strconv"
"strings"
logger2 "wdd.io/agent-go/logger"
)
type ExecutionMessage struct {
NeedResultReplay bool `json:"needResultReplay"`
DurationTask bool `json:"durationTask,default:false"`
ExecutionType string `json:"executionType"`
FuncContent []string `json:"funcContent"`
SingleLineCommand []string `json:"singleLineCommand"`
MultiLineCommand [][]string `json:"multiLineCommand"`
PipeLineCommand [][]string `json:"pipeLineCommand"`
ResultKey string `json:"resultKey"`
}
var log = logger2.Log
var AgentOsOperatorCache = &AgentOsOperator{}
func Execute(em *ExecutionMessage) (bool, []string) {
var resultLog []string
var err error
ok := true
executionContent := em.ExecutionType + " == " + strings.Join(em.FuncContent, " - ")
log.DebugF("em message is => %#v", em)
if strings.HasPrefix(em.ExecutionType, "BASE") {
// base function
if len(em.FuncContent) > 1 {
ok, resultLog = AgentOsOperatorCache.Exec(em.FuncContent[0], em.FuncContent[1:]...)
} else {
ok, resultLog = AgentOsOperatorCache.Exec(em.FuncContent[0])
}
} else if strings.HasPrefix(em.ExecutionType, "APP") {
// app function
if len(em.FuncContent) > 1 {
ok, resultLog = AgentOsOperatorCache.Deploy(em.FuncContent[0], em.FuncContent[1:]...)
} else {
ok, resultLog = AgentOsOperatorCache.Deploy(em.FuncContent[0])
}
} else if strings.HasPrefix(em.ExecutionType, "HARBOR") {
if em.FuncContent == nil || len(em.FuncContent) <= 1 {
ok = false
resultLog = []string{
"[Harbor Execute] - functions args is wrong!",
}
}
// Harbor Execute
ok, resultLog = HarborOperatorCache.Exec(em.FuncContent[0], em.FuncContent[1:]...)
} else {
// shell command
if em.PipeLineCommand != nil && len(em.PipeLineCommand) != 0 {
// 管道命令
resultLog, err = PipeLineCommandExecutor(em.PipeLineCommand)
executionContent = fmt.Sprintf("%v", em.PipeLineCommand)
} else if em.MultiLineCommand != nil && len(em.MultiLineCommand) != 0 {
// 多行命令
resultLog, err = MultiLineCommandExecutor(em.MultiLineCommand)
executionContent = fmt.Sprintf("%v", em.MultiLineCommand)
} else {
// 单行命令
resultLog, err = FormatAllCommandExecutor(em.SingleLineCommand)
executionContent = fmt.Sprintf("%v", em.SingleLineCommand)
}
}
// 归一化错误和日志
if err != nil {
resultLog = append(resultLog, " 命令执行错误如下 ", err.Error())
}
resultLog = append(resultLog, fmt.Sprintf("命令 %v 执行结果为 %s", executionContent, strconv.FormatBool(ok)))
// debug
log.DebugF("%v", resultLog)
return ok, resultLog
}
func PipeLineCommandExecutor(pipeLineCommand [][]string) ([]string, error) {
var resultSlice []string
var output []byte
var err error
tmp := make([]string, len(pipeLineCommand))
for index, pipe := range pipeLineCommand {
tmp[index] = strings.Join(pipe, " ")
}
pipelineCommandString := strings.Join(tmp, " | ")
resultSlice = append(resultSlice, fmt.Sprintf(" ========= 命令为 ====> %s", pipelineCommandString))
for _, pipeCommand := range pipeLineCommand {
if len(pipeCommand) == 0 {
continue
}
command := exec.Command(pipeCommand[0], pipeCommand[1:]...)
if len(output) > 0 {
command.Stdin = bytes.NewBuffer(output)
}
output, err = command.CombinedOutput()
if err != nil {
log.ErrorF("Pipeline Command Command Error => %v", err.Error())
// 收集错误的信息
resultSlice = append(resultSlice, "↓↓↓ 命令 错误 如下 ↓↓↓", string(output))
return resultSlice, err
}
}
// 正常的输出
resultSlice = append(resultSlice, "↓↓↓ 命令 输出 如下 ↓↓↓", string(output))
return resultSlice, err
}
func MultiLineCommandExecutor(multiLineCommandExecutor [][]string) ([]string, error) {
var res []string
for _, singleLineCommand := range multiLineCommandExecutor {
singleLogs, err := FormatAllCommandExecutor(singleLineCommand)
res = append(res, singleLogs...)
if err != nil {
log.Error(fmt.Sprintf("Execution error ! command is %v, error is %v", singleLineCommand, err))
return res, err
}
}
return res, nil
}
// SingleLineCommandExecutor 执行单行命令
func SingleLineCommandExecutor(singleLineCommand []string) ([]string, error) {
cmd := exec.Command(singleLineCommand[0], singleLineCommand[1:]...)
var out bytes.Buffer
cmd.Stdout = &out
cmd.Stderr = &out
err := cmd.Run()
scanner := bufio.NewScanner(&out)
var result []string
for scanner.Scan() {
result = append(result, scanner.Text())
}
if err != nil {
return nil, err
}
return result, nil
}