[Agent] [Executor] 优化Functional Executor

This commit is contained in:
zeaslity
2023-10-13 17:22:21 +08:00
parent 0a294fa81b
commit 020fc76e05
8 changed files with 215 additions and 150 deletions

View File

@@ -1,7 +1,6 @@
package executor
import (
"os/exec"
"time"
)
@@ -81,60 +80,6 @@ func (op *AgentOsOperator) Deploy(appFuncName string, funcArgs ...string) (bool,
return resultOK, result
}
// 通用命令脚本
// BaseCommandExists 判定命令是否存在
func BaseCommandExists(commandName string) bool {
cmd := exec.Command("command", "-v", commandName)
err := cmd.Run()
if err != nil {
log.DebugF("指令 %s 不存在", commandName)
return false
} else {
return true
}
}
// BaseCommandExistsBatch 判定批量命令是否存在
func BaseCommandExistsBatch(commandNameList []string) (bool, string) {
for _, commandName := range commandNameList {
if !BaseCommandExists(commandName) {
return false, commandName
}
}
return true, ""
}
// BaseReplace 基础替换命令
func BaseReplace(filename string, origin string, replace string) bool {
cmd := exec.Command("sed", "-i", "s/"+origin+"/"+replace+"/g", filename)
err := cmd.Run()
if err != nil {
log.DebugF("文件 %s [%s] => [%s] 错误!", filename, origin, replace)
return false
} else {
return true
}
}
func BaseFileExists(filename string) bool {
cmd := exec.Command("test", "-f", filename)
err := cmd.Run()
if err != nil {
log.DebugF("文件 %s 不存在!", filename)
return false
} else {
return true
}
}
// 通用命令脚本
func (op *AgentOsOperator) deployMinio(funcArgs []string) (bool, []string) {
minioTemplateFileName := "minio-docker-compose.yaml"
result := append(AppExecuteErrorLogPrefix, "部署MINIO")
@@ -142,7 +87,7 @@ func (op *AgentOsOperator) deployMinio(funcArgs []string) (bool, []string) {
// 逻辑为接收执行,但是会报错
// 环境判定
commandExist, commandName := BaseCommandExistsBatch([]string{
commandExist, commandName := BasicCommandExistsBatch([]string{
"docker-compose",
})
if !commandExist {
@@ -162,7 +107,7 @@ func (op *AgentOsOperator) deployMinio(funcArgs []string) (bool, []string) {
return false, result
}
// 根据参数 A1C2IP 替换
if !BaseReplace(minioTemplateFileName, "A1C2IP", funcArgs[0]) {
if !BasicReplace(minioTemplateFileName, "A1C2IP", funcArgs[0]) {
result = append(result, "替换IP信息")
return false, result
}
@@ -194,7 +139,7 @@ func (op *AgentOsOperator) deployNFS(funcArgs []string) (bool, []string) {
nfsDataPath := "/nfsdata"
// 环境判定
commandExist, commandName := BaseCommandExistsBatch([]string{
commandExist, commandName := BasicCommandExistsBatch([]string{
"kubectl",
})
if !commandExist {
@@ -220,7 +165,7 @@ func (op *AgentOsOperator) deployNFS(funcArgs []string) (bool, []string) {
return false, result
}
// 根据参数 A1C2IP 替换
if !BaseReplace(nfsTemplateFile, "N1C2IP", funcArgs[0]) {
if !BasicReplace(nfsTemplateFile, "N1C2IP", funcArgs[0]) {
result = append(result, "替换IP信息")
return false, result
}
@@ -248,7 +193,7 @@ func (op *AgentOsOperator) testNFS(funcArgs []string) (bool, []string) {
result := append(AppExecuteErrorLogPrefix, "测试NFS部署")
// 环境判定
commandExist, commandName := BaseCommandExistsBatch([]string{
commandExist, commandName := BasicCommandExistsBatch([]string{
"kubectl",
})
if !commandExist {
@@ -266,7 +211,7 @@ func (op *AgentOsOperator) testNFS(funcArgs []string) (bool, []string) {
return false, result
}
// 根据参数 A1C2IP 替换
if !BaseReplace(nfsTemplateFile, "N1C2IP", funcArgs[0]) {
if !BasicReplace(nfsTemplateFile, "N1C2IP", funcArgs[0]) {
result = append(result, "替换IP信息")
return false, result
}
@@ -283,7 +228,7 @@ func (op *AgentOsOperator) testNFS(funcArgs []string) (bool, []string) {
}
// 测试文件是否存在
if !BaseFileExists("/nfsdata/test-pod*/NFS-CREATE-SUCCESS") {
if !BasicFileExists("/nfsdata/test-pod*/NFS-CREATE-SUCCESS") {
result = append(result, "NFS 测试功能 异常!!")
return false, result
}
@@ -300,7 +245,7 @@ func (op *AgentOsOperator) deployPVC(funcArgs []string) (bool, []string) {
result := append(AppExecuteErrorLogPrefix, "部署PVC")
// 环境判定
commandExist, commandName := BaseCommandExistsBatch([]string{
commandExist, commandName := BasicCommandExistsBatch([]string{
"kubectl",
})
if !commandExist {
@@ -318,7 +263,7 @@ func (op *AgentOsOperator) deployPVC(funcArgs []string) (bool, []string) {
return false, result
}
// 根据参数 A1C2IP 替换
if !BaseReplace(pvcTemplateFile, "SUPREME", funcArgs[0]) {
if !BasicReplace(pvcTemplateFile, "SUPREME", funcArgs[0]) {
result = append(result, "替换SUPREME信息")
return false, result
}
@@ -346,7 +291,7 @@ func (op *AgentOsOperator) deployMySQL(funcArgs []string) (bool, []string) {
result := append(AppExecuteErrorLogPrefix, "部署 MySQL !")
// 环境判定
commandExist, commandName := BaseCommandExistsBatch([]string{
commandExist, commandName := BasicCommandExistsBatch([]string{
"kubectl",
})
if !commandExist {
@@ -364,11 +309,11 @@ func (op *AgentOsOperator) deployMySQL(funcArgs []string) (bool, []string) {
return false, result
}
// 根据参数 A1C2IP 替换
if !BaseReplace(mysqlTemplate, "SUPREME", funcArgs[0]) {
if !BasicReplace(mysqlTemplate, "SUPREME", funcArgs[0]) {
result = append(result, "替换SUPREME信息")
return false, result
}
if !BaseReplace(mysqlTemplate, "A1C2IP", funcArgs[1]) {
if !BasicReplace(mysqlTemplate, "A1C2IP", funcArgs[1]) {
result = append(result, "替换A1C2IP信息")
return false, result
}
@@ -421,7 +366,7 @@ func (op *AgentOsOperator) deployMiddlewares(funcArgs []string) (bool, []string)
result := append(AppExecuteErrorLogPrefix, "部署 所有的中间件 !")
// 环境判定
commandExist, commandName := BaseCommandExistsBatch([]string{
commandExist, commandName := BasicCommandExistsBatch([]string{
"kubectl",
})
if !commandExist {
@@ -439,11 +384,11 @@ func (op *AgentOsOperator) deployMiddlewares(funcArgs []string) (bool, []string)
return false, result
}
// 根据参数 A1C2IP 替换
if !BaseReplace(middlewaresTemplate, "SUPREME", funcArgs[0]) {
if !BasicReplace(middlewaresTemplate, "SUPREME", funcArgs[0]) {
result = append(result, "替换SUPREME信息")
return false, result
}
if !BaseReplace(middlewaresTemplate, "A1C2IP", funcArgs[1]) {
if !BasicReplace(middlewaresTemplate, "A1C2IP", funcArgs[1]) {
result = append(result, "替换A1C2IP信息")
return false, result
}
@@ -472,7 +417,7 @@ func (op *AgentOsOperator) deployRedis(funcArgs []string) (bool, []string) {
result := append(AppExecuteErrorLogPrefix, "部署 redis !")
// 环境判定
commandExist, commandName := BaseCommandExistsBatch([]string{
commandExist, commandName := BasicCommandExistsBatch([]string{
"kubectl",
})
if !commandExist {
@@ -490,11 +435,11 @@ func (op *AgentOsOperator) deployRedis(funcArgs []string) (bool, []string) {
return false, result
}
// 根据参数 A1C2IP 替换
if !BaseReplace(redisTemplate, "SUPREME", funcArgs[0]) {
if !BasicReplace(redisTemplate, "SUPREME", funcArgs[0]) {
result = append(result, "替换SUPREME信息")
return false, result
}
if !BaseReplace(redisTemplate, "A1C2IP", funcArgs[1]) {
if !BasicReplace(redisTemplate, "A1C2IP", funcArgs[1]) {
result = append(result, "替换A1C2IP信息")
return false, result
}
@@ -523,7 +468,7 @@ func (op *AgentOsOperator) deployIngress(funcArgs []string) (bool, []string) {
result := append(AppExecuteErrorLogPrefix, "部署 Ingress !")
// 环境判定
commandExist, commandName := BaseCommandExistsBatch([]string{
commandExist, commandName := BasicCommandExistsBatch([]string{
"kubectl",
})
if !commandExist {
@@ -541,15 +486,15 @@ func (op *AgentOsOperator) deployIngress(funcArgs []string) (bool, []string) {
return false, result
}
// 根据参数 A1C2IP 替换
if !BaseReplace(ingressTemplate, "SUPREME", funcArgs[0]) {
if !BasicReplace(ingressTemplate, "SUPREME", funcArgs[0]) {
result = append(result, "替换SUPREME信息")
return false, result
}
if !BaseReplace(ingressTemplate, "A1C2IP", funcArgs[1]) {
if !BasicReplace(ingressTemplate, "A1C2IP", funcArgs[1]) {
result = append(result, "替换A1C2IP信息")
return false, result
}
if !BaseReplace(ingressTemplate, "A1C1JS", funcArgs[1]) {
if !BasicReplace(ingressTemplate, "A1C1JS", funcArgs[1]) {
result = append(result, "替换A1C1JS信息")
return false, result
}
@@ -577,7 +522,7 @@ func (op *AgentOsOperator) deployFront(funcArgs []string) (bool, []string) {
result := append(AppExecuteErrorLogPrefix, "部署 前端服务 !")
// 环境判定
commandExist, commandName := BaseCommandExistsBatch([]string{
commandExist, commandName := BasicCommandExistsBatch([]string{
"kubectl",
})
if !commandExist {
@@ -595,11 +540,11 @@ func (op *AgentOsOperator) deployFront(funcArgs []string) (bool, []string) {
return false, result
}
// 根据参数 A1C2IP 替换
if !BaseReplace(fontTemplate, "SUPREME", funcArgs[0]) {
if !BasicReplace(fontTemplate, "SUPREME", funcArgs[0]) {
result = append(result, "替换SUPREME信息")
return false, result
}
if !BaseReplace(fontTemplate, "A1C2IP", funcArgs[1]) {
if !BasicReplace(fontTemplate, "A1C2IP", funcArgs[1]) {
result = append(result, "替换A1C2IP信息")
return false, result
}
@@ -628,7 +573,7 @@ func (op *AgentOsOperator) initMinio(funcArgs []string) (bool, []string) {
result := append(AppExecuteErrorLogPrefix, "进行MINIO初始化服务 !")
// 环境判定
commandExist, commandName := BaseCommandExistsBatch([]string{
commandExist, commandName := BasicCommandExistsBatch([]string{
"kubectl",
})
if !commandExist {
@@ -646,15 +591,15 @@ func (op *AgentOsOperator) initMinio(funcArgs []string) (bool, []string) {
return false, result
}
// 根据参数 A1C2IP 替换
if !BaseReplace(initMinioTemplate, "SUPREME", funcArgs[0]) {
if !BasicReplace(initMinioTemplate, "SUPREME", funcArgs[0]) {
result = append(result, "替换SUPREME信息")
return false, result
}
if !BaseReplace(initMinioTemplate, "A1C2IP", funcArgs[1]) {
if !BasicReplace(initMinioTemplate, "A1C2IP", funcArgs[1]) {
result = append(result, "替换A1C2IP信息")
return false, result
}
if !BaseReplace(initMinioTemplate, "M2D2IP", funcArgs[1]) {
if !BasicReplace(initMinioTemplate, "M2D2IP", funcArgs[1]) {
result = append(result, "替换A1C2IP信息")
return false, result
}
@@ -683,7 +628,7 @@ func (op *AgentOsOperator) deploySRS(funcArgs []string) (bool, []string) {
result := append(AppExecuteErrorLogPrefix, "开始部署SRS服务")
// 环境判定
commandExist, commandName := BaseCommandExistsBatch([]string{
commandExist, commandName := BasicCommandExistsBatch([]string{
"kubectl",
})
if !commandExist {
@@ -701,19 +646,19 @@ func (op *AgentOsOperator) deploySRS(funcArgs []string) (bool, []string) {
return false, result
}
// 根据参数 A1C2IP 替换
if !BaseReplace(srsTemplate, "SUPREME", funcArgs[0]) {
if !BasicReplace(srsTemplate, "SUPREME", funcArgs[0]) {
result = append(result, "替换SUPREME信息")
return false, result
}
if !BaseReplace(srsTemplate, "A1C2IP", funcArgs[1]) {
if !BasicReplace(srsTemplate, "A1C2IP", funcArgs[1]) {
result = append(result, "替换A1C2IP信息")
return false, result
}
if !BaseReplace(srsTemplate, "A1C1JS", funcArgs[1]) {
if !BasicReplace(srsTemplate, "A1C1JS", funcArgs[1]) {
result = append(result, "替换A1C1JS信息")
return false, result
}
if !BaseReplace(srsTemplate, "M2D2IP", funcArgs[1]) {
if !BasicReplace(srsTemplate, "M2D2IP", funcArgs[1]) {
result = append(result, "替换M2D2IP信息")
return false, result
}
@@ -765,7 +710,7 @@ func (op *AgentOsOperator) deployBackend(funcArgs []string) (bool, []string) {
result := append(AppExecuteErrorLogPrefix, "部署 后端 服务 !")
// 环境判定
commandExist, commandName := BaseCommandExistsBatch([]string{
commandExist, commandName := BasicCommandExistsBatch([]string{
"kubectl",
})
if !commandExist {
@@ -783,11 +728,11 @@ func (op *AgentOsOperator) deployBackend(funcArgs []string) (bool, []string) {
return false, result
}
// 根据参数 A1C2IP 替换
if !BaseReplace(backendTemplate, "SUPREME", funcArgs[0]) {
if !BasicReplace(backendTemplate, "SUPREME", funcArgs[0]) {
result = append(result, "替换SUPREME信息")
return false, result
}
if !BaseReplace(backendTemplate, "A1C2IP", funcArgs[1]) {
if !BasicReplace(backendTemplate, "A1C2IP", funcArgs[1]) {
result = append(result, "替换A1C2IP信息")
return false, result
}

View File

@@ -203,9 +203,19 @@ func (op *AgentOsOperator) shutdownFirewall() [][]string {
func (op *AgentOsOperator) shutdownFirewallExec() (bool, []string) {
// quick sort
shutdownFunc := [][]string{
{"systemctl", "stop", "firewalld"},
{"systemctl", "disable", "firewalld"},
{"systemctl", "stop", "ufw"},
{"systemctl", "disable", "ufw"},
{"iptables", "-F"},
}
// 忽略错误
_, resultLog := AllCompleteExecutor(shutdownFunc)
return false, nil
// centos
return true, resultLog
}
func (op *AgentOsOperator) modifyHostname(args []string) [][]string {
@@ -265,7 +275,11 @@ func (op *AgentOsOperator) disableSwap() [][]string {
}
func (op *AgentOsOperator) disableSwapExec() (bool, []string) {
return false, nil
resultOK := true
var resultLog []string
return resultOK, resultLog
}
func (op *AgentOsOperator) removeDocker() [][]string {

View File

@@ -0,0 +1,65 @@
package executor
import "os/exec"
// BasicCommandExists 判定命令是否存在
func BasicCommandExists(commandName string) bool {
cmd := exec.Command("command", "-v", commandName)
err := cmd.Run()
if err != nil {
log.DebugF("指令 %s 不存在", commandName)
return false
} else {
return true
}
}
// BasicCommandExistsBatch 判定批量命令是否存在
func BasicCommandExistsBatch(commandNameList []string) (bool, string) {
for _, commandName := range commandNameList {
if !BasicCommandExists(commandName) {
return false, commandName
}
}
return true, ""
}
// BasicReplace 基础替换命令
func BasicReplace(filename string, origin string, replace string) bool {
cmd := exec.Command("sed", "-i", "s/"+origin+"/"+replace+"/g", filename)
err := cmd.Run()
if err != nil {
log.DebugF("文件 %s [%s] => [%s] 错误!", filename, origin, replace)
return false
} else {
return true
}
}
func BasicFileExists(filename string) bool {
cmd := exec.Command("test", "-f", filename)
err := cmd.Run()
if err != nil {
log.DebugF("文件 %s 不存在!", filename)
return false
} else {
return true
}
}
func BasicFileExistAndNotNull(filename string) bool {
cmd := exec.Command("test", "-z", filename)
err := cmd.Run()
if err != nil {
log.DebugF("文件 %s 不存在!", filename)
return false
} else {
return true
}
}

View File

@@ -0,0 +1,16 @@
package executor
import (
"github.com/magiconair/properties/assert"
"testing"
)
var emptyFilePath = "/home/wdd/IdeaProjects/ProjectOctopus/agent-go/executor/script"
func TestBasicFileExistAndNotNull(t *testing.T) {
resultOK := BasicFileExistAndNotNull(emptyFilePath)
assert.Equal(t, resultOK, false, "判定为空文件返回false")
}

View File

@@ -7,36 +7,11 @@ import (
"os/exec"
)
// ReadTimeCommandExecutor 执行命令,并且实时返回结果
func ReadTimeCommandExecutor(singleLineCommand []string) {
cmd := exec.Command(singleLineCommand[0], singleLineCommand[1:]...)
stdout, err := cmd.StdoutPipe()
if err != nil {
log.ErrorF("command %v stdout error => %v", singleLineCommand, err)
}
stderr, err := cmd.StderrPipe()
if err != nil {
log.ErrorF("command %v stderr error => %v", singleLineCommand, err)
}
if err := cmd.Start(); err != nil {
log.ErrorF("command %v runtime error => %v", singleLineCommand, err)
}
go realTimeOutput(stdout)
go realTimeOutput(stderr)
if err := cmd.Wait(); err != nil {
log.ErrorF("command %v result error => %v", singleLineCommand, err)
}
}
// AllCommandExecutor 正确或者错误的信息全部收集,共同返回
func AllCommandExecutor(singleLineCommand []string) (bool, []string) {
func AllCommandExecutor(singleLineCommand []string) (resultOk bool, resultLog []string) {
// result
var resultSlice []string
resultOk := true
resultOk = true
cmd := exec.Command(singleLineCommand[0], singleLineCommand[1:]...)
stdout, err := cmd.StdoutPipe()
@@ -69,6 +44,24 @@ func AllCommandExecutor(singleLineCommand []string) (bool, []string) {
return resultOk, resultSlice
}
// AllCompleteExecutor 多行命令的执行函数,返回执行正确与否和执行结果
func AllCompleteExecutor(multiCommand [][]string) (resultOk bool, resultLog []string) {
var result []string
resultOk = true
for _, singleLineCommand := range multiCommand {
ok, resultLog := AllCommandExecutor(singleLineCommand)
if !ok {
// 执行出错
resultOk = false
}
result = append(result, resultLog...)
}
return resultOk, result
}
// FormatAllCommandExecutor 收集全部执行结果、错误并且返回
func FormatAllCommandExecutor(singleLineCommand []string) ([]string, error) {
@@ -107,6 +100,59 @@ func FormatAllCommandExecutor(singleLineCommand []string) ([]string, error) {
return resultSlice, resultError
}
// PureResultSingleExecute 执行单行命令,忽略输出,只对执行成功与否负责
func PureResultSingleExecute(singleCommand []string) (resultOK bool) {
cmd := exec.Command(singleCommand[0], singleCommand[1:]...)
err := cmd.Run()
if err != nil {
log.ErrorF("指令 %s 执行 错误, 错误内容为 %s", singleCommand, err.Error())
return false
} else {
log.DebugF("指令 %s 执行 成功", singleCommand)
return true
}
}
// PureResultSingleExecuteBatch 批量 执行单行命令,忽略输出,只对执行成功与否负责
func PureResultSingleExecuteBatch(singleCommandList [][]string) (resultOK bool) {
result := true
for _, singleCommand := range singleCommandList {
if !PureResultSingleExecute(singleCommand) {
result = false
}
}
return result
}
// ReadTimeCommandExecutor 执行命令,并且实时返回结果
func ReadTimeCommandExecutor(singleLineCommand []string) {
cmd := exec.Command(singleLineCommand[0], singleLineCommand[1:]...)
stdout, err := cmd.StdoutPipe()
if err != nil {
log.ErrorF("command %v stdout error => %v", singleLineCommand, err)
}
stderr, err := cmd.StderrPipe()
if err != nil {
log.ErrorF("command %v stderr error => %v", singleLineCommand, err)
}
if err := cmd.Start(); err != nil {
log.ErrorF("command %v runtime error => %v", singleLineCommand, err)
}
go realTimeOutput(stdout)
go realTimeOutput(stderr)
if err := cmd.Wait(); err != nil {
log.ErrorF("command %v result error => %v", singleLineCommand, err)
}
}
func realTimeOutput(r io.Reader) {
scanner := bufio.NewScanner(r)
for scanner.Scan() {
@@ -126,29 +172,3 @@ func collectOutput(r io.Reader, resultSlice []string) []string {
return resultSlice
}
// PureResultSingleExecute 执行单行命令,忽略输出,只对执行成功与否负责
func PureResultSingleExecute(singleCommand []string) bool {
cmd := exec.Command(singleCommand[0], singleCommand[1:]...)
err := cmd.Run()
if err != nil {
log.ErrorF("指令 %s 执行 错误, 错误内容为 %s", singleCommand, err.Error())
return false
} else {
log.DebugF("指令 %s 执行 成功", singleCommand)
return true
}
}
// PureResultSingleExecuteBatch 批量 执行单行命令,忽略输出,只对执行成功与否负责
func PureResultSingleExecuteBatch(singleCommandList [][]string) bool {
for _, singleCommand := range singleCommandList {
if !PureResultSingleExecute(singleCommand) {
return false
}
}
return true
}

View File

@@ -14,6 +14,11 @@ var callShellScript = []string{
"/root/IdeaProjects/ProjectOctopus/agent-go/tmp/simple.sh",
}
var shutdownFirewalld = []string{
// wrong usage of &&
"systemctl", "stop", "firewalld", "&&", "systemctl", "disable", "firewalld",
}
var ifconfigCommand = []string{"ifconfig"}
func TestReadTimeOutput(t *testing.T) {
@@ -23,7 +28,7 @@ func TestReadTimeOutput(t *testing.T) {
}
func TestAllCommandExecutor(t *testing.T) {
ok, result := AllCommandExecutor(ifconfigCommand)
ok, result := AllCommandExecutor(shutdownFirewalld)
t.Logf("执行结果为 => %#v", ok)
t.Logf("执行日志为 => %#v", result)

View File

@@ -6,7 +6,7 @@ var configFilePath = "/root/.kube/config"
func CheckPodStatus(specific string, supreme string) bool {
if !BaseCommandExists("kubectl") {
if !BasicCommandExists("kubectl") {
log.Error("kubectl命令不存在无法查看Pod状态请查看")
}

View File