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 }