459 lines
14 KiB
Go
459 lines
14 KiB
Go
package outgiving
|
||
|
||
import (
|
||
"encoding/json"
|
||
err1 "errors"
|
||
"fmt"
|
||
"git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/controller"
|
||
"git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/controller/v1/app_manage"
|
||
"git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/middleware"
|
||
"git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/model/app_manage/node"
|
||
"git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/model/app_manage/out_giving"
|
||
"git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/model/app_manage/server_white_list"
|
||
"git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/model/app_manage/system_parameters"
|
||
"git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/model/user"
|
||
"git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/pkg/errors"
|
||
"git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/pkg/request"
|
||
"git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/pkg/response"
|
||
"git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/service/app_manage/common"
|
||
node2 "git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/service/app_manage/node"
|
||
"git.inspur.com/sbg-jszt/cfn/cfn-schedule/pkg/log"
|
||
"github.com/gin-gonic/gin"
|
||
"strings"
|
||
"time"
|
||
)
|
||
|
||
// 创建分发项目
|
||
func SavePorject(c *gin.Context) {
|
||
bodyToMap := request.GetBodyToMap(c)
|
||
typeStr, _ := bodyToMap["type"].(string)
|
||
id, _ := bodyToMap["id"].(string)
|
||
|
||
workspaceId := app_manage.GetWorkspaceId(c)
|
||
bodyToMap["workspace_id"] = workspaceId
|
||
|
||
userObject, _ := c.Get(middleware.LoginUserKey)
|
||
userModel := userObject.(*user.UserObj)
|
||
|
||
if "add" == typeStr {
|
||
checkId := strings.ReplaceAll(id, "-", "")
|
||
checkId = strings.ReplaceAll(checkId, "_", "")
|
||
err := validateID(checkId)
|
||
if err != nil {
|
||
controller.FailCode(c, errors.ServerError, err, err.Error())
|
||
return
|
||
}
|
||
addOutGiving(c, id, bodyToMap, userModel)
|
||
} else {
|
||
updateGiving(c, id, bodyToMap, userModel)
|
||
}
|
||
|
||
}
|
||
func DeletePorject(c *gin.Context) {
|
||
bodyToMap := request.GetBodyToMap(c)
|
||
id, ok := bodyToMap["id"]
|
||
if !ok {
|
||
controller.Fail(c, errors.ServerError, "id不能为空")
|
||
return
|
||
}
|
||
|
||
thorough, ok := bodyToMap["thorough"]
|
||
if !ok {
|
||
controller.Fail(c, errors.ServerError, "id不能为空")
|
||
return
|
||
}
|
||
|
||
outGivingModel := out_giving.GetOutGivingModelById(id.(string))
|
||
if outGivingModel == nil {
|
||
controller.Fail(c, errors.ServerError, "没有找到对应的分发项目")
|
||
return
|
||
}
|
||
|
||
// 该项目不是节点分发项目,不能在此次删除
|
||
if !outGivingModel.OutGivingProject {
|
||
controller.Fail(c, errors.ServerError, "该项目不是节点分发项目,不能在此处删除")
|
||
return
|
||
}
|
||
|
||
outGivingNodeProjectList := outGivingModel.GetOutGivingNodeProjectList()
|
||
|
||
for _, outGivingNodeProject := range outGivingNodeProjectList {
|
||
nodeModel := node.GetNodeById(outGivingNodeProject.NodeId)
|
||
if nodeModel.Id == "" {
|
||
controller.Fail(c, errors.ServerError, "没有找到对应的节点")
|
||
return
|
||
}
|
||
|
||
resp := deleteNodeProject(nodeModel, outGivingModel.Id, thorough.(string))
|
||
|
||
if resp.Result.Code != errors.SUCCESS {
|
||
controller.FailCode(c, errors.ServerError, err1.New(resp.Result.Msg), nodeModel.Name+"节点失败: "+resp.Result.Msg)
|
||
return
|
||
}
|
||
}
|
||
|
||
rows, err := out_giving.DeleteOutGivingModelById(id.(string))
|
||
if err != nil {
|
||
controller.FailCode(c, errors.ServerError, err, "删除分发失败")
|
||
return
|
||
}
|
||
if rows >= 0 {
|
||
out_giving.DeleteOutGivingLogByOutGivingId(id.(string))
|
||
}
|
||
|
||
controller.Success(c, "删除成功")
|
||
}
|
||
|
||
func addOutGiving(c *gin.Context, id string, body map[string]interface{}, userObj *user.UserObj) {
|
||
byId := out_giving.GetOutGivingModelById(id)
|
||
if byId.Id != "" {
|
||
controller.FailCode(c, errors.ServerError, nil, "项目id已存在")
|
||
return
|
||
}
|
||
outGivingModel := out_giving.NewOutGivingModel()
|
||
outGivingModel.Id = id
|
||
outGivingModel.OutGivingProject = true
|
||
outGivingModel.CreateUser = userObj.UserID
|
||
outGivingModel.ModifyUser = userObj.UserID
|
||
|
||
tuples, err := doData(outGivingModel, body, false)
|
||
if err != nil {
|
||
controller.FailCode(c, errors.ServerError, err, err.Error())
|
||
return
|
||
}
|
||
|
||
_, err = outGivingModel.Create(outGivingModel)
|
||
if err != nil {
|
||
controller.FailCode(c, errors.ServerError, nil, "项目id已存在")
|
||
return
|
||
}
|
||
|
||
// saveNodeData
|
||
res := saveNodeData(outGivingModel, tuples, false)
|
||
if res != nil {
|
||
controller.Fail(c, errors.ServerError, res.Result.Msg)
|
||
return
|
||
}
|
||
|
||
controller.Success(c, "添加成功")
|
||
}
|
||
|
||
func updateGiving(c *gin.Context, id string, body map[string]interface{}, userObj *user.UserObj) {
|
||
outGivingModel := out_giving.GetOutGivingModelById(id)
|
||
if outGivingModel == nil {
|
||
controller.Fail(c, errors.ServerError, "没有找到对应的分发id")
|
||
return
|
||
}
|
||
|
||
tuples, err := doData(outGivingModel, body, true)
|
||
if err != nil {
|
||
controller.FailCode(c, errors.ServerError, err, err.Error())
|
||
return
|
||
}
|
||
|
||
outGivingModel.ModifyUser = userObj.UserID
|
||
outGivingModel.ModifyTimeMillis = time.Now().UnixMilli()
|
||
err = out_giving.UpdateOutGivingModel(outGivingModel, []string{"name", "group", "workspace_id", "after_opt", "secondary_directory",
|
||
"out_giving_node_project_list", "clear_old", "upload_close_first", "secondary_directory", "modify_user", "modify_time_millis"})
|
||
|
||
if err != nil {
|
||
controller.FailCode(c, errors.ServerError, err, "修改失败")
|
||
return
|
||
}
|
||
// saveNodeData 保存节点项目数据
|
||
res := saveNodeData(outGivingModel, tuples, true)
|
||
if res != nil {
|
||
controller.Fail(c, errors.ServerError, res.Result.Msg)
|
||
return
|
||
}
|
||
|
||
controller.Success(c, "修改成功")
|
||
}
|
||
|
||
// 保存节点项目数据
|
||
func saveNodeData(outGivingModel *out_giving.OutGivingModel, tuples map[string]map[string]interface{}, edit bool) *response.Response {
|
||
successTuples := map[string]interface{}{}
|
||
fail := false
|
||
|
||
for key, value := range tuples {
|
||
nodeModelId := key
|
||
n, _ := app_manage.TryGetNode(map[string]interface{}{"nodeId": nodeModelId})
|
||
|
||
dataJSON := value
|
||
jsonMessage := sendData(n, dataJSON, true)
|
||
if jsonMessage.Result.Code != errors.SUCCESS {
|
||
if !edit {
|
||
out_giving.DeleteOutGivingModelById(outGivingModel.Id)
|
||
fail = true
|
||
}
|
||
|
||
if fail {
|
||
for nodeModelId, _ = range successTuples {
|
||
resp := deleteNodeProject(n, outGivingModel.Id, "")
|
||
if resp.Result.Code != errors.SUCCESS {
|
||
log.Errorf("还原项目失败:" + resp.Result.Msg)
|
||
}
|
||
}
|
||
}
|
||
|
||
jsonMessage.Result.Msg = n.Name + "节点失败:" + jsonMessage.Result.Msg
|
||
return jsonMessage
|
||
}
|
||
|
||
successTuples[key] = value
|
||
// 同步项目信息
|
||
node2.SyncNodeProjectInfo(n, outGivingModel.Id)
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// 创建项目管理的默认数据
|
||
func getDefData(outGivingModel *out_giving.OutGivingModel, body map[string]interface{}, edit bool) (map[string]interface{}, error) {
|
||
defData := make(map[string]interface{})
|
||
defData["id"] = outGivingModel.Id
|
||
defData["name"] = outGivingModel.Name
|
||
defData["group"] = outGivingModel.Group
|
||
|
||
runMode := body["runMode"]
|
||
defData["runMode"] = runMode
|
||
|
||
if runMode == "Dsl" {
|
||
dslContent := body["dslContent"]
|
||
defData["dslContent"] = dslContent
|
||
}
|
||
|
||
whitelistDirectory := body["whitelistDirectory"]
|
||
// 获取白名单
|
||
s := &system_parameters.SystemParameters{}
|
||
s.Id = server_white_list.GetId(outGivingModel.WorkspaceId)
|
||
_ = s.GetById(s)
|
||
serverWhitelist := &server_white_list.ServerWhitelist{}
|
||
if s.Value != "" {
|
||
err := json.Unmarshal([]byte(s.Value), serverWhitelist)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
}
|
||
|
||
var outGivingArray []string
|
||
if strings.Contains(serverWhitelist.OutGiving, "\r\n") == true {
|
||
outGivingArray = strings.Split(serverWhitelist.OutGiving, "\r\n")
|
||
} else {
|
||
outGivingArray = strings.Split(serverWhitelist.OutGiving, "\n")
|
||
}
|
||
|
||
checkPath := server_white_list.CheckPath(outGivingArray, whitelistDirectory.(string))
|
||
if !checkPath {
|
||
return nil, fmt.Errorf("请选择正确的项目路径,或者还没有配置白名单")
|
||
}
|
||
defData["whitelistDirectory"] = whitelistDirectory
|
||
|
||
logPath := body["logPath"]
|
||
if logPath != nil && strings.TrimSpace(logPath.(string)) != "" {
|
||
checkPath = server_white_list.CheckPath(outGivingArray, whitelistDirectory.(string))
|
||
if !checkPath {
|
||
return nil, fmt.Errorf("请选择正确的日志路径,或者还没有配置白名单")
|
||
}
|
||
defData["logPath"] = logPath
|
||
}
|
||
lib := body["lib"]
|
||
defData["lib"] = lib
|
||
|
||
if edit {
|
||
defData["edit"] = "on"
|
||
}
|
||
defData["previewData"] = true
|
||
|
||
return defData, nil
|
||
}
|
||
|
||
// 参考outGivingProjectEditController.example.json
|
||
func doData(outGivingModel *out_giving.OutGivingModel, body map[string]interface{}, edit bool) (map[string]map[string]interface{}, error) {
|
||
tuples := make(map[string]map[string]interface{})
|
||
|
||
outGivingModel.Name = body["name"].(string)
|
||
if outGivingModel.Name == "" {
|
||
return tuples, fmt.Errorf("分发名称不能为空")
|
||
}
|
||
outGivingModel.WorkspaceId = body["workspace_id"].(string)
|
||
|
||
if groupStr, ok := body["group"]; ok {
|
||
if groupStr != nil {
|
||
s := groupStr.(string)
|
||
outGivingModel.Group = &s
|
||
}
|
||
|
||
}
|
||
|
||
if afterOpt, ok := body["afterOpt"]; ok {
|
||
afterOptInt, err := afterOpt.(float64)
|
||
if err != true {
|
||
return tuples, fmt.Errorf("参数有误:afterOpt")
|
||
}
|
||
outGivingModel.AfterOpt = int(afterOptInt)
|
||
} else {
|
||
return tuples, fmt.Errorf("请选择分发后的操作")
|
||
}
|
||
|
||
outGivingModel.IntervalTime = 10
|
||
|
||
if clearOld, ok := body["clearOld"]; ok {
|
||
//toBool := utils.StringToBool(clearOld.(string))
|
||
outGivingModel.ClearOld = clearOld.(bool)
|
||
}
|
||
|
||
if secondaryDirectory, ok := body["secondaryDirectory"]; ok {
|
||
if secondaryDirectory != nil {
|
||
s := secondaryDirectory.(string)
|
||
outGivingModel.SecondaryDirectory = &s
|
||
}
|
||
}
|
||
|
||
if uploadCloseFirst, ok := body["uploadCloseFirst"]; ok {
|
||
//toBool := utils.StringToBool(uploadCloseFirst.(string))
|
||
outGivingModel.UploadCloseFirst = uploadCloseFirst.(bool)
|
||
}
|
||
|
||
// 填充其他数据
|
||
defData, err := getDefData(outGivingModel, body, edit)
|
||
if err != nil {
|
||
return tuples, err
|
||
}
|
||
|
||
//
|
||
nodeIdsStr := body["nodeIds"]
|
||
nodeIds := strings.Split(nodeIdsStr.(string), ",")
|
||
if len(nodeIds) == 0 {
|
||
return tuples, fmt.Errorf("没有任何节点信息")
|
||
}
|
||
|
||
outGivingModels := out_giving.ListOutGivingModel()
|
||
outGivingNodeProjects := make([]out_giving.OutGivingNodeProject, 0)
|
||
var outGivingNodeProject *out_giving.OutGivingNodeProject
|
||
|
||
for _, nodeId := range nodeIds {
|
||
nodeModel, err := app_manage.TryGetNode(map[string]interface{}{"nodeId": nodeId})
|
||
if err != nil {
|
||
return tuples, fmt.Errorf("对应的节点不存在")
|
||
}
|
||
|
||
// 判断项目是否已被使用,还要兼容新增和编辑两种场景!
|
||
if outGivingModels != nil {
|
||
for _, model := range outGivingModels {
|
||
if strings.EqualFold(model.Id, outGivingModel.Id) {
|
||
continue
|
||
}
|
||
contains := model.CheckContains(nodeId, outGivingModel.Id)
|
||
if contains {
|
||
return tuples, fmt.Errorf("已经存在相同的分发项目: %s", outGivingModel.Id)
|
||
}
|
||
}
|
||
}
|
||
|
||
nodeProjectList := outGivingModel.GetOutGivingNodeProjectList()
|
||
// 分发 ID 等同于项目 ID
|
||
outGivingNodeProject = outGivingModel.GetNodeProject(nodeProjectList, nodeModel.Id, outGivingModel.Id)
|
||
if outGivingNodeProject == nil {
|
||
outGivingNodeProject = &out_giving.OutGivingNodeProject{}
|
||
}
|
||
outGivingNodeProject.NodeId = nodeModel.Id
|
||
// 分发id为项目id
|
||
outGivingNodeProject.ProjectId = outGivingModel.Id
|
||
outGivingNodeProjects = append(outGivingNodeProjects, *outGivingNodeProject)
|
||
|
||
// 准备并检查数据
|
||
allData := cloneMap(defData)
|
||
token := body[(fmt.Sprintf("%s_token", nodeModel.Id))]
|
||
allData["token"] = token
|
||
jvm := body[fmt.Sprintf("%s_jvm", nodeModel.Id)]
|
||
allData["jvm"] = jvm
|
||
args := body[fmt.Sprintf("%s_args", nodeModel.Id)]
|
||
allData["args"] = args
|
||
autoStart := body[fmt.Sprintf("%s_autoStart", nodeModel.Id)]
|
||
//allData["autoStart"] = autoStart.(bool)
|
||
if _, ok := autoStart.(bool); ok {
|
||
allData["autoStart"] = autoStart.(bool)
|
||
}
|
||
dslEnv := body[fmt.Sprintf("%s_dslEnv", nodeModel.Id)]
|
||
allData["dslEnv"] = dslEnv
|
||
|
||
jsonMessage := sendData(nodeModel, allData, false)
|
||
if jsonMessage.Result.Code != errors.SUCCESS {
|
||
return tuples, fmt.Errorf("%s节点失败:%s", nodeModel.Name, jsonMessage.Result.Msg)
|
||
}
|
||
|
||
tuples[nodeModel.Id] = allData
|
||
}
|
||
|
||
if len(outGivingNodeProjects) == 0 {
|
||
return tuples, fmt.Errorf("至少选择1个节点项目")
|
||
}
|
||
// 删除已经删除的项目
|
||
err = deleteProject(outGivingModel, outGivingNodeProjects)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("删除项目失败: %s", err.Error())
|
||
}
|
||
|
||
outGivingModel.SetOutGivingNodeProjectList(outGivingNodeProjects)
|
||
|
||
return tuples, nil
|
||
}
|
||
|
||
// 删除已经删除过的项目
|
||
func deleteProject(outGivingModel *out_giving.OutGivingModel, outGivingNodeProjects []out_giving.OutGivingNodeProject) error {
|
||
// 获取需要删除的节点项目
|
||
deleteNodeProjects := outGivingModel.GetDelete(outGivingNodeProjects)
|
||
if deleteNodeProjects != nil {
|
||
for _, outGivingNodeProject := range deleteNodeProjects {
|
||
nodeModel, err := app_manage.TryGetNode(map[string]interface{}{"nodeId": outGivingNodeProject.NodeId})
|
||
if err != nil {
|
||
return fmt.Errorf("节点不存在")
|
||
}
|
||
//outGivingNodeProject.GetNodeData(true) // 假设这是获取某些数据的操作,需根据实际情况实现或忽略
|
||
|
||
// 彻底删除节点项目
|
||
jsonMessage := deleteNodeProject(nodeModel, outGivingNodeProject.ProjectId, "thorough")
|
||
if jsonMessage.Result.Code != errors.SUCCESS {
|
||
return fmt.Errorf("%s节点失败:%s", nodeModel.Name, jsonMessage.Result.Msg)
|
||
}
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// 删除项目
|
||
func deleteNodeProject(nodeModel *node.Node, projectId, thorough string) *response.Response {
|
||
data := make(map[string]interface{})
|
||
data["id"] = projectId
|
||
data["thorough"] = thorough
|
||
data["nodeId"] = nodeModel.Id
|
||
|
||
resp := app_manage.TryRequestNode("", data, common.Manage_DeleteProject)
|
||
if resp.Result.Code == errors.SUCCESS {
|
||
node2.SyncNodeProjectInfo(nodeModel, projectId)
|
||
}
|
||
|
||
return resp
|
||
}
|
||
|
||
func sendData(nodeModel *node.Node, data map[string]interface{}, save bool) *response.Response {
|
||
if save {
|
||
delete(data, "previewData")
|
||
}
|
||
data["outGivingProject"] = true
|
||
data["nodeId"] = nodeModel.Id
|
||
return app_manage.TryRequestNode("", data, common.Manage_SaveProject)
|
||
}
|
||
|
||
func cloneMap(body map[string]interface{}) map[string]interface{} {
|
||
clone := make(map[string]interface{})
|
||
for k, v := range body {
|
||
// 注意:这里仅实现了浅拷贝,如果value本身是复杂的数据结构(如嵌套的map或slice),
|
||
// 那么这个拷贝过程不会递归拷贝内部结构,它们仍然会被共享。
|
||
clone[k] = v
|
||
}
|
||
return clone
|
||
}
|