Commit 332200c1 authored by 陈子龙's avatar 陈子龙

自动化运维 立即执行 fix

parent eb2db1eb
...@@ -10,3 +10,14 @@ type TaskInfoListReq struct { ...@@ -10,3 +10,14 @@ type TaskInfoListReq struct {
Search string `json:"search" form:"search"` // 关键词 Search string `json:"search" form:"search"` // 关键词
Pagination Pagination
} }
type AddExecHistory struct {
TaskId int `json:"task_id"` // 任务ID
CreateUser string `json:"create_user"` // 操作人
}
type UpdateExecHistory struct {
TaskHistoryId int `json:"task_history_id"` // 任务历史ID
ExecLog string `json:"exec_log"` // 执行日志
State int `json:"state"` // 状态(0执行中 1成功 2失败)
}
...@@ -33,9 +33,10 @@ type ListTaskManageReq struct { ...@@ -33,9 +33,10 @@ type ListTaskManageReq struct {
} }
type ExecScriptReq struct { type ExecScriptReq struct {
HostGroupId int `form:"host_group_id" vd:"$>0;msg:'请输入主机分组id'"` //主机分组id TaskId int `json:"task_id" binding:"required"` //主机分组id
Type int `form:"type"` //脚本额外变量类型1yaml 2json HostGroupId int `form:"host_group_id" binding:"required"` //主机分组id
Value string `form:"value"` //脚本额外变量值 Type int `json:"type" binding:"oneof=1 2"` //脚本额外变量类型1yaml 2json
Script string `form:"script"` //执行脚本 Value string `json:"value"` //脚本额外变量值
ScriptUrl string `form:"script_url"` //执行脚本url Script string `json:"script"` //执行脚本
YmlFileName string `json:"yml_file_name"` //执行脚本url
} }
...@@ -3,11 +3,15 @@ package controller ...@@ -3,11 +3,15 @@ package controller
import ( import (
"errors" "errors"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/minio/minio-go/v7"
"github.com/spf13/cast" "github.com/spf13/cast"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/request" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/request"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/client"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/resp" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/resp"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/service" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/service"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/util" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/util"
"io"
) )
// AddTaskManage 新增任务 // AddTaskManage 新增任务
...@@ -24,12 +28,12 @@ func AddTaskManage(c *gin.Context) { ...@@ -24,12 +28,12 @@ func AddTaskManage(c *gin.Context) {
} }
taskManageSvc := service.TaskManageSvc{} taskManageSvc := service.TaskManageSvc{}
err := taskManageSvc.AddTaskManage(req) id, err := taskManageSvc.AddTaskManage(req)
if err != nil { if err != nil {
SendJsonResponse(c, err, nil) SendJsonResponse(c, err, nil)
return return
} }
SendJsonResponse(c, resp.OK, nil) SendJsonResponse(c, resp.OK, id)
} }
// EditTaskManage 编辑任务 // EditTaskManage 编辑任务
...@@ -46,12 +50,12 @@ func EditTaskManage(c *gin.Context) { ...@@ -46,12 +50,12 @@ func EditTaskManage(c *gin.Context) {
} }
taskManageSvc := service.TaskManageSvc{} taskManageSvc := service.TaskManageSvc{}
err := taskManageSvc.EditTaskManage(req) id, err := taskManageSvc.EditTaskManage(req)
if err != nil { if err != nil {
SendJsonResponse(c, err, nil) SendJsonResponse(c, err, nil)
return return
} }
SendJsonResponse(c, resp.OK, nil) SendJsonResponse(c, resp.OK, id)
} }
// DelTaskManage 删除任务 // DelTaskManage 删除任务
...@@ -119,11 +123,36 @@ func ListTaskManage(c *gin.Context) { ...@@ -119,11 +123,36 @@ func ListTaskManage(c *gin.Context) {
func ExecScript(c *gin.Context) { func ExecScript(c *gin.Context) {
var req request.ExecScriptReq var req request.ExecScriptReq
if err := c.ShouldBind(&req); err != nil { if err := c.ShouldBindJSON(&req); err != nil {
SendJsonResponse(c, resp.InvalidParam.WithError(err), nil) SendJsonResponse(c, resp.InvalidParam.WithError(err), nil)
return return
} }
if req.YmlFileName == "" && req.Script == "" {
SendJsonResponse(c, resp.InvalidParam.WithError(errors.New("执行脚本为空")), nil)
return
}
//解析yml文件
if req.YmlFileName != "" && req.Value == "" {
minioClient, err := client.GetMinioConnect()
if err != nil {
SendJsonResponse(c, resp.InvalidParam.WithError(errors.New("执行脚本为空")), nil)
return
}
object, err := minioClient.GetObject(c, conf.Options.MinioBucket, req.YmlFileName, minio.GetObjectOptions{})
if err != nil {
SendJsonResponse(c, resp.GetFileStreamError.WithError(err), nil)
return
}
obj, err := io.ReadAll(object)
if err != nil {
SendJsonResponse(c, resp.ReadFileError.WithError(err), nil)
return
}
req.Script = string(obj)
}
taskManageSvc := service.TaskManageSvc{} taskManageSvc := service.TaskManageSvc{}
err := taskManageSvc.ExecScript(req) err := taskManageSvc.ExecScript(req)
if err != nil { if err != nil {
......
package service package service
import ( import (
"fmt"
"github.com/pkg/errors" "github.com/pkg/errors"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/entity" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/entity"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/request" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/request"
...@@ -145,3 +146,52 @@ func (t *TaskHistorySvc) TaskExecLog(id int) (taskExecLogRes response.TaskExecLo ...@@ -145,3 +146,52 @@ func (t *TaskHistorySvc) TaskExecLog(id int) (taskExecLogRes response.TaskExecLo
return return
} }
// AddExecHistory 新增执行历史
func AddExecHistory(req request.AddExecHistory) (id int, err error) {
db, err := client.GetDbClient()
if err != nil {
err = resp.DbConnectError.WithError(err)
return
}
count, err := db.Table("task_history").Where("id = ?", req.TaskId).Count(&entity.TaskHistory{})
if err != nil {
err = resp.DbSelectError.WithError(err)
return
}
//新增
taskHistory := entity.TaskHistory{
TaskId: req.TaskId,
ExecStartTime: time.Now(),
CreateUser: req.CreateUser,
ExecDesc: "执行说明" + fmt.Sprintf("%v", count+1),
State: 0,
}
_, err = db.Table("task_history").Insert(&taskHistory)
if err != nil {
err = resp.DbInsertError.WithError(err)
return
}
return taskHistory.Id, nil
}
// UpdateExecHistory 修改执行历史
func UpdateExecHistory(req request.UpdateExecHistory) (err error) {
db, err := client.GetDbClient()
if err != nil {
err = resp.DbConnectError.WithError(err)
return
}
_, err = db.Table("task_history").Where("id = ?", req.TaskHistoryId).Cols("state,exec_end_time,exec_log").
Update(&entity.TaskHistory{
State: req.State,
ExecEndTime: time.Now(),
ExecLog: req.ExecLog,
})
if err != nil {
err = resp.DbUpdateError.WithError(err)
return
}
return
}
...@@ -2,15 +2,12 @@ package service ...@@ -2,15 +2,12 @@ package service
import ( import (
"bufio" "bufio"
"context"
"errors" "errors"
"fmt" "fmt"
"github.com/minio/minio-go/v7"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/entity" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/entity"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/request" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/request"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/response" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/response"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/client" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/client"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/resp" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/resp"
"io" "io"
"os" "os"
...@@ -23,7 +20,7 @@ type TaskManageSvc struct { ...@@ -23,7 +20,7 @@ type TaskManageSvc struct {
} }
// AddTaskManage 新增任务 // AddTaskManage 新增任务
func (t *TaskManageSvc) AddTaskManage(req request.AddTaskManageReq) (err error) { func (t *TaskManageSvc) AddTaskManage(req request.AddTaskManageReq) (id int, err error) {
db, err := client.GetDbClient() db, err := client.GetDbClient()
if err != nil { if err != nil {
err = resp.DbConnectError.WithError(err) err = resp.DbConnectError.WithError(err)
...@@ -57,11 +54,11 @@ func (t *TaskManageSvc) AddTaskManage(req request.AddTaskManageReq) (err error) ...@@ -57,11 +54,11 @@ func (t *TaskManageSvc) AddTaskManage(req request.AddTaskManageReq) (err error)
err = resp.DbInsertError.WithError(err) err = resp.DbInsertError.WithError(err)
return return
} }
return return taskManage.Id, nil
} }
// EditTaskManage 编辑任务 // EditTaskManage 编辑任务
func (t *TaskManageSvc) EditTaskManage(req request.EditTaskManageReq) (err error) { func (t *TaskManageSvc) EditTaskManage(req request.EditTaskManageReq) (id int, err error) {
db, err := client.GetDbClient() db, err := client.GetDbClient()
if err != nil { if err != nil {
err = resp.DbConnectError.WithError(err) err = resp.DbConnectError.WithError(err)
...@@ -83,7 +80,7 @@ func (t *TaskManageSvc) EditTaskManage(req request.EditTaskManageReq) (err error ...@@ -83,7 +80,7 @@ func (t *TaskManageSvc) EditTaskManage(req request.EditTaskManageReq) (err error
err = resp.DbUpdateError.WithError(err) err = resp.DbUpdateError.WithError(err)
return return
} }
return return req.Id, nil
} }
// DelTaskManage 删除任务 // DelTaskManage 删除任务
...@@ -186,21 +183,6 @@ func (t *TaskManageSvc) ListTaskManage(req request.ListTaskManageReq) (total int ...@@ -186,21 +183,6 @@ func (t *TaskManageSvc) ListTaskManage(req request.ListTaskManageReq) (total int
} }
func (t *TaskManageSvc) ExecScript(req request.ExecScriptReq) (err error) { func (t *TaskManageSvc) ExecScript(req request.ExecScriptReq) (err error) {
if req.ScriptUrl != "" {
minioClient, err := client.GetMinioConnect()
if err != nil {
return resp.DbConnectError.WithError(err)
}
object, err := minioClient.GetObject(context.Background(), conf.Options.MinioBucket, req.ScriptUrl, minio.GetObjectOptions{})
if err != nil {
return resp.FileExecError.WithError(err)
}
obj, err := io.ReadAll(object)
if err != nil {
return resp.FileExecError.WithError(err)
}
req.Script = string(obj)
}
//var scripts []map[string]interface{} //var scripts []map[string]interface{}
//var script map[string]interface{} //var script map[string]interface{}
//j2, err := yaml.YAMLToJSON([]byte(req.Script)) //j2, err := yaml.YAMLToJSON([]byte(req.Script))
...@@ -223,7 +205,6 @@ func (t *TaskManageSvc) ExecScript(req request.ExecScriptReq) (err error) { ...@@ -223,7 +205,6 @@ func (t *TaskManageSvc) ExecScript(req request.ExecScriptReq) (err error) {
//} //}
//req.Script = string(y) //req.Script = string(y)
//写入执行脚本 //写入执行脚本
fmt.Println("1111111111111111111111")
f2, err := os.Create("/etc/ansible/ansible.yml") f2, err := os.Create("/etc/ansible/ansible.yml")
if err != nil { if err != nil {
return resp.FileExecError.WithError(err) return resp.FileExecError.WithError(err)
...@@ -233,7 +214,6 @@ func (t *TaskManageSvc) ExecScript(req request.ExecScriptReq) (err error) { ...@@ -233,7 +214,6 @@ func (t *TaskManageSvc) ExecScript(req request.ExecScriptReq) (err error) {
if err != nil { if err != nil {
return resp.FileExecError.WithError(err) return resp.FileExecError.WithError(err)
} }
fmt.Println("2222222222222")
//写入额外yml参数 //写入额外yml参数
if req.Type == 1 { if req.Type == 1 {
//写入执行脚本 //写入执行脚本
...@@ -248,13 +228,23 @@ func (t *TaskManageSvc) ExecScript(req request.ExecScriptReq) (err error) { ...@@ -248,13 +228,23 @@ func (t *TaskManageSvc) ExecScript(req request.ExecScriptReq) (err error) {
} }
req.Value = fmt.Sprintf("@/etc/ansible/ansible_extra.yml") req.Value = fmt.Sprintf("@/etc/ansible/ansible_extra.yml")
} }
//新增任务历史
id, err := AddExecHistory(request.AddExecHistory{
TaskId: req.TaskId,
CreateUser: t.User.SystemAccount,
})
if err != nil {
return
}
//执行ansible命令
var cmd *exec.Cmd var cmd *exec.Cmd
if req.Value != "" { if req.Value != "" {
cmd = exec.Command("ansible-playbook", "/etc/ansible/ansible.yml", "--extra-vars", req.Value) cmd = exec.Command("ansible-playbook", "/etc/ansible/ansible.yml", "--extra-vars", req.Value)
} else { } else {
cmd = exec.Command("ansible-playbook", "/etc/ansible/ansible.yml") cmd = exec.Command("ansible-playbook", "/etc/ansible/ansible.yml")
} }
fmt.Println("333333333333333")
//捕获正常日志 //捕获正常日志
stdout, err := cmd.StdoutPipe() stdout, err := cmd.StdoutPipe()
if err != nil { if err != nil {
...@@ -269,41 +259,61 @@ func (t *TaskManageSvc) ExecScript(req request.ExecScriptReq) (err error) { ...@@ -269,41 +259,61 @@ func (t *TaskManageSvc) ExecScript(req request.ExecScriptReq) (err error) {
if err = cmd.Start(); err != nil { if err = cmd.Start(); err != nil {
return resp.CmdExecError.WithError(err) return resp.CmdExecError.WithError(err)
} }
fmt.Println("4444444444444444444") //获取 正常/异常 输出流
//获取正常/异常 输出流
outputBuf := bufio.NewReader(stdout) outputBuf := bufio.NewReader(stdout)
readerr := bufio.NewReader(stderr) readerr := bufio.NewReader(stderr)
var out, outErr int var out, outErr, errFlag int
var execLog string
for { for {
fmt.Println("666666666666666")
//逐行打印日志 //逐行输出日志
lineOut, err1 := outputBuf.ReadString('\n') lineOut, err1 := outputBuf.ReadString('\n')
if (err1 != nil || io.EOF == err1) && out == 0 { if (err1 != nil || io.EOF == err1) && out == 0 {
fmt.Println("捕获标准输出line:", lineOut)
fmt.Println("捕获标准输出err:", err1)
out = 1 out = 1
//break
} else if out == 0 { } else if out == 0 {
fmt.Println("输出正常日志:", lineOut) //存储执行日志
execLog = execLog + lineOut + " \n "
UpdateExecHistory(request.UpdateExecHistory{
TaskHistoryId: id,
ExecLog: execLog,
})
} }
lineErr, err2 := readerr.ReadString('\n') lineErr, err2 := readerr.ReadString('\n')
if (err2 != nil || io.EOF == err2) && outErr == 0 { if (err2 != nil || io.EOF == err2) && outErr == 0 {
fmt.Println("捕获标准错误line:", lineErr)
fmt.Println("捕获标准错误err:", err)
outErr = 1 outErr = 1
//break
} else if outErr == 0 { } else if outErr == 0 {
fmt.Println("输出错误日志:", lineErr) //存储异常执行日志
errFlag = 1
execLog = execLog + lineErr + " \n "
UpdateExecHistory(request.UpdateExecHistory{
TaskHistoryId: id,
ExecLog: execLog,
})
} }
if out == 1 && outErr == 1 { if out == 1 && outErr == 1 {
if errFlag == 1 {
//任务执行失败
UpdateExecHistory(request.UpdateExecHistory{
TaskHistoryId: id,
ExecLog: execLog,
State: 2,
})
} else {
//任务执行成功
UpdateExecHistory(request.UpdateExecHistory{
TaskHistoryId: id,
ExecLog: execLog,
State: 1,
})
}
break break
} }
} }
fmt.Println("55555555555555")
cmd.Wait() cmd.Wait()
fmt.Println("执行结束") return
return nil
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment