package service import ( "bufio" "encoding/json" "errors" "fmt" "gadmin/config" "gadmin/internal/admin/consts" "gadmin/internal/admin/forms" "gadmin/internal/admin/library/docker" "gadmin/internal/admin/ws" "gadmin/internal/gorm/model" "gadmin/internal/gorm/query" "gadmin/utility" "gadmin/utility/character" "gadmin/utility/serializer" "gadmin/utility/token" "os" "strconv" "strings" "time" "github.com/docker/docker/api/types" "github.com/gin-gonic/gin" "github.com/sirupsen/logrus" "gorm.io/gorm" ) var Deploy = new(sDeploy) type sDeploy struct{} // 一个容器部署完成后的消息上报 func (s *sDeploy) Notify(ctx *gin.Context, req forms.DeployNotifyReq) serializer.Response { var ( q = query.Use(config.DB).ServerDeploy ql = query.Use(config.DB).ServerDeployLog qs = query.Use(config.DB).ServerDeployStat stat *model.ServerDeployStat err error status = consts.DeployStatusSuc ) // 本次部署针对的容器 及相关配置 taskItem, err := ql.Where(ql.TraceID.Eq(req.TraceID)).First() if err != nil { logrus.Warnf("first err:%+v", err) return serializer.DBErr(err.Error(), err) } if taskItem == nil { return serializer.DBErr("操作记录不存在", nil) } // 取出容器配置 deploy, err := q.Where(q.ID.Eq(taskItem.DeployID)).First() if err != nil { logrus.Warnf("deploy err:%+v", err) return serializer.DBErr(err.Error(), err) } if deploy == nil { return serializer.DBErr("服务器不存在", nil) } // 取本次部署统计信息 一次部署可能是多个容器 if taskItem.PublishType == consts.DeployPublishTypeVersion { stat, err = qs.Where(qs.BatchID.Eq(taskItem.BatchID)).First() if err != nil { logrus.Warnf("stat err:%+v", err) return serializer.DBErr(err.Error(), err) } if stat == nil { return serializer.DBErr("批量记录不存在", nil) } // 解析一个容器上报数据 parsingError := func(log *forms.DeployLogViewModel) { if log == nil { return } logrus.Warnf("parsingError log:%+v\n", log) if strings.Contains(log.LogContent, `level=error`) { req.Code = 1 req.Msg = fmt.Sprintf("拉取json配置异常,请检查") return } // 提取本次启动的进程 ProcessFlag := "要开始的进程内容:" line, err1 := extractFromFlagToEnd(log.LogContent, ProcessFlag) if err1 != nil { req.Code = 1 req.Msg = fmt.Sprintf("未找到本次需要启动的进程信息,请检查") return } logrus.Infof("本次启动进程: %v\n", line) extra := make(map[string]interface{}) err := json.Unmarshal([]byte(taskItem.Extra), &extra) if err != nil { logrus.Infof("parsingError 1: %v\n", err) return } deployServer, ok := extra["deployServ"] if !ok { logrus.Infof("parsingError 2: %v\n", extra) return } var ds []string ds1, ok := deployServer.([]interface{}) if !ok { logrus.Infof("parsingError 3: %v %T\n", deployServer, deployServer) return } for _, v := range ds1 { ds = append(ds, v.(string)) } // err = json.Unmarshal([]byte(ds1), &ds) // if err != nil { // logrus.Infof("parsingError 32: %v\n", err) // return // } logrus.Infof("parsingError 4: %v\n", ds) // 检查进程数量是否正常 var monitor = make(map[string]bool) // _, startServ, _ := docker.ParseDeployServArgs(deploy.ServerType, ds, deploy.IsMproom) var serverList []string if len(ds) == 1 && ds[0] == "all" { serverList = strings.Split(line, ",") } else { serverList = ds } for _, v := range serverList { if v == consts.DeployPackJsonConvert { continue } // if v == consts.DeployPackMPRoom { // if deploy.IsMproom != consts.INTTRUE { // continue // } // } n := "./" + v monitor[n] = false } // if consts.DeployTypeGrave == deploy.ServerType { // if deploy.IsMproom == consts.INTTRUE { // monitor = map[string]bool{ // "./archive": false, // // "./chapter": false, // "./chapterd": false, // //"./gate": false, // "./store": false, // "./world": false, // "./mproom": false, // } // } else { // monitor = map[string]bool{ // "./archive": false, // // "./chapter": false, // "./chapterd": false, // "./store": false, // "./world": false, // } // } // } // if consts.DeployTypeLogin == deploy.ServerType { // monitor = map[string]bool{ // "./login": false, // } // } // if consts.DeployTypeGate == deploy.ServerType { // monitor = map[string]bool{ // "./gate": false, // } // } logrus.Infof("parsingError 5: %v\n", monitor) if len(monitor) == 0 { logrus.Warn("GameAlarm monitor is not set") return } process, err := docker.GetGraveProcess(docker.GraveProcessInput{Ctx: ctx, Deploy: deploy}) if err != nil { req.Code = 2 req.Msg = fmt.Sprintf("docker通讯异常:[%v]", err.Error()) return } logrus.Infof("parsingError 7: %v\n", string(process)) for _, line := range strings.Split(string(process), "\n") { // logrus.Infof("line:%s\n", line) awk := strings.Split(line, " ") awk2 := awk[len(awk)-1] if _, ok := monitor[awk2]; ok { monitor[awk2] = true } } logrus.WithField("method", "Notify").Infof("monitor: %+v\n", monitor) for s, b := range monitor { if !b { ps := strings.ReplaceAll(s, "./", "") req.Code = 2 req.Msg = fmt.Sprintf("服务启动异常,未监测进程到:[%v]", ps) return } } } // 解析日志中是否存在错误 log, err := s.getDeployLog(ctx, forms.DeployLogViewReq{Id: taskItem.ID, LogFile: req.LogFile}) if err != nil { logrus.Warnf("解析日志失败:%+v", err.Error()) } parsingError(log) } if req.Code != 0 { status = consts.DeployStatusErr } _, err = query.Use(config.DB).ServerDeploy.WithContext(ctx).Where(q.ID.Eq(taskItem.DeployID)).Updates(model.ServerDeploy{ DeployStatus: status, }) if err != nil { logrus.Warnf("Updates ServerDeploy err:%+v", err) return serializer.DBErr(err.Error(), err) } _, err = query.Use(config.DB).ServerDeployLog.WithContext(ctx).Where(ql.ID.Eq(taskItem.ID)).Updates(model.ServerDeployLog{ LogFile: req.LogFile, ErrorMsg: req.Msg, Status: status, EndAt: time.Now(), }) if err != nil { logrus.Warnf("Updates ServerDeployLog err:%+v", err) return serializer.DBErr(err.Error(), err) } msg := fmt.Sprintf("应用[%v]部署成功。远程服务器提示:%v", taskItem.Name, req.Msg) code := consts.CodeSuccess if req.Code != 0 { msg = fmt.Sprintf("应用[%v]部署失败。远程服务器提示:%v", taskItem.Name, req.Msg) code = consts.CodeParamErr } if taskItem.AdminID > 0 { msgData := ws.Msg{ Id: taskItem.ID, Type: consts.SocketDeployNotify, Code: code, Msg: msg, } go ws.SendToAdmin(taskItem.AdminID, msgData) } if taskItem.PublishType != consts.DeployPublishTypeVersion { return serializer.Suc(nil) } // 更新统计 if req.Code != 0 { tx := config.DB.Exec("UPDATE server_deploy_stat SET fail=fail+? WHERE batch_id=?", 1, stat.BatchID) if tx.Error != nil { logrus.Warnf("Notify Updates server_deploy_stat fail err:%+v", err) } stat.Fail += 1 } else { tx := config.DB.Exec("UPDATE server_deploy_stat SET success=success+? WHERE batch_id=?", 1, stat.BatchID) if tx.Error != nil { logrus.Warnf("Notify Updates server_deploy_stat success err:%+v", err) } stat.Success += 1 } // 满足通知条件 if stat.Success+stat.Fail+stat.Timeout >= stat.Total { msgData := ws.Msg{ Id: taskItem.ID, Type: consts.SocketDeployNotify, Code: consts.CodeSuccess, Msg: fmt.Sprintf("批量部署任务全部执行完毕,成功:%v,失败:%v,超时:%v", stat.Success, stat.Fail, stat.Timeout), } go ws.SendToAdmin(taskItem.AdminID, msgData) // 更新通知状态 _, err = query.Use(config.DB).ServerDeployStat.WithContext(ctx).Where(qs.ID.Eq(stat.ID)).Updates(model.ServerDeployStat{ IsNotify: consts.DeployNotifyOk, NotifyAt: time.Now(), }) if err != nil { logrus.Warnf("Updates ServerDeployStat err:%+v", err) return serializer.DBErr(err.Error(), err) } } return serializer.Suc(nil) } func extractFromFlagToEnd(input string, startFlag string) (string, error) { // 使用bufio.NewScanner模拟逐行读取 scanner := bufio.NewScanner(strings.NewReader(input)) var line string found := false for scanner.Scan() { line = scanner.Text() if strings.Contains(line, startFlag) { // 找到标记,提取整行 found = true break } } if err := scanner.Err(); err != nil { return "", err } if !found { return "", fmt.Errorf("startFlag not found") } startIndex := strings.Index(line, startFlag) if startIndex == -1 { return "", errors.New("未找到指定的字符串") } // 计算截取的开始位置(即"要开始的进程内容:"之后的位置) // 注意:由于我们要跳过"要开始的进程内容:"这个字符串,所以需要加上它的长度 start := startIndex + len(startFlag) // 截取字符串 // 这里我们没有指定end,所以它会截取到originalString的末尾 result := line[start:] return result, nil } func (s *sDeploy) getDeployLog(ctx *gin.Context, req forms.DeployLogViewReq) (taskItem *forms.DeployLogViewModel, err error) { var ( q = query.Use(config.DB).ServerDeploy ql = query.Use(config.DB).ServerDeployLog ) if err = ql.Where(ql.ID.Eq(req.Id)).Scan(&taskItem); err != nil { return } if taskItem == nil { err = errors.New("操作记录不存在") return } deploy, err := q.Where(q.ID.Eq(taskItem.DeployID)).First() if err != nil { return } if deploy == nil { err = errors.New("操作记录不存在") return } if taskItem.LogFile == "" && req.LogFile != "" { taskItem.LogFile = req.LogFile } log, err := docker.ReadDeployLog(docker.ReadDeployLogInput{ Ctx: ctx, Deploy: deploy, LogFile: taskItem.LogFile, }) if err != nil { return } taskItem.LogContent = string(log) taskItem.LogContent = utility.Rmu0000(taskItem.LogContent) taskItem.LogContent = strings.Replace(taskItem.LogContent, ``, "", -1) taskItem.LogContent = strings.Replace(taskItem.LogContent, `INFO`, "", -1) return } func (s *sDeploy) LogView(ctx *gin.Context, req forms.DeployLogViewReq) serializer.Response { taskItem, err := s.getDeployLog(ctx, req) if err != nil { return serializer.ParamErr(err.Error(), err) } return serializer.Suc(taskItem) } func (s *sDeploy) LogList(ctx *gin.Context, req forms.DeployLogListReq) serializer.Response { var ( q = query.Use(config.DB).ServerDeployLog m = q.WithContext(ctx).Where(q.DeployID.Eq(req.DeployId)) offset int64 = 0 models forms.UserAccountListRes lists []forms.DeployLogListModel ) m = m.Order(q.ID.Desc()) req.Page, req.PerPage, offset = forms.CalculatePage(req.Page, req.PerPage) count, err := m.Count() if err != nil { return serializer.Err(consts.CodeParamErr, "查询出错 count", err) } if count > 0 { if err = m.Limit(int(req.PerPage)).Offset(int(offset)).Scan(&lists); err != nil { return serializer.Err(consts.CodeParamErr, "查询出错 lists", err) } } for k, v := range lists { if v.AdminID > 0 { user, err := User.GetUser(v.AdminID) if err != nil { logrus.Warnf("Deploy LogList GetUser err:%+v", err) continue } if user != nil { lists[k].AdminName = fmt.Sprintf("%v(%v)", user.UserName, v.AdminID) } } } models.List = lists models.Page = req.Page models.PerPage = req.PerPage models.PageCount = (count + req.PerPage - 1) / req.PerPage return serializer.Suc(models) } // 获取部署的服务器列表 func (s *sDeploy) List(ctx *gin.Context, req forms.DeployListReq) serializer.Response { var ( q = query.Use(config.DB).ServerDeploy m = q.WithContext(ctx).Where(q.Environment.Eq(os.Getenv("GIN_MODE"))) offset int64 = 0 models forms.UserAccountListRes lists []forms.DeployListData ) if req.Name != "" { m = m.Where(q.Name.Like(req.Name)) } if req.ContainerName != "" { m = m.Where(q.ContainerName.Like(req.ContainerName)) } if len(req.ServerType) > 0 { m = m.Where(q.ServerType.In(req.ServerType...)) } m = m.Order(q.ServerType, q.ID.Desc()) req.Page, req.PerPage, offset = forms.CalculatePage(req.Page, req.PerPage) count, err := m.Count() if err != nil { return serializer.Err(consts.CodeParamErr, "查询出错 count", err) } if count > 0 { //if err = m.Limit(int(req.PerPage)).Offset(int(offset)).Scan(&lists); err != nil { if err = m.Scan(&lists); err != nil { return serializer.Err(consts.CodeParamErr, "查询出错 lists", err) } } //区分多少docker地址 dockerMap := make(map[string]map[string]string) for _, item := range lists { if _, ok := dockerMap[item.DockerAddr]; ok { continue } dockerInfoMap := make(map[string]string) dockerInfoMap["addr"] = item.DockerAddr dockerInfoMap["caPem"] = item.CaPem dockerInfoMap["certPem"] = item.CertPem dockerInfoMap["keyPem"] = item.KeyPem dockerMap[item.DockerAddr] = dockerInfoMap } logrus.Infof("dockerMap:%+v", dockerMap) //获取docker列表 containerMap := make(map[string]types.Container) for addr, info := range dockerMap { logrus.Infof("info:%+v", info) containerList, err := docker.GetContainerList(ctx, info["addr"], info["caPem"], info["certPem"], info["keyPem"]) if err != nil { logrus.Errorf("获取%s docker列表失败:%v", addr, err) // return serializer.Response{} } for _, item := range containerList { containerMap[item.Names[0]] = item } } nt := time.Now() for k, v := range lists { if v.AdminID > 0 { user, err := User.GetUser(v.AdminID) if err != nil { logrus.Warnf("Deploy LogList GetUser err:%+v", err) continue } if user != nil { lists[k].AdminName = fmt.Sprintf("%v(%v)", user.UserName, v.AdminID) } } if v.LastSyncAt.Add(consts.DeployRunSyncTime).Before(nt) { runStatus := consts.DeployRunStart container := containerMap["/"+v.ContainerName] if container.State != "running" { runStatus = consts.DeployRunStop } if container.ID == "" { runStatus = consts.DeployRunNoFound } _, err = query.Use(config.DB).ServerDeploy.WithContext(ctx).Where(q.ID.Eq(v.ID)).Updates(model.ServerDeploy{ RunStatus: runStatus, LastSyncAt: time.Now(), }) if err != nil { logrus.Warnf("ServerDeploy Updates LastSyncAt err:%+v", err) } } lists[k].DeployStatus = s.getLastDeployStatus(ctx, v.ID) } //for k, v := range lists { // if v.AdminID > 0 { // user, err := User.GetUser(v.AdminID) // if err != nil { // logrus.Warnf("Deploy LogList GetUser err:%+v", err) // continue // } // if user != nil { // lists[k].AdminName = fmt.Sprintf("%v(%v)", user.UserName, v.AdminID) // } // } // if v.LastSyncAt.Add(consts.DeployRunSyncTime).Before(nt) { // runStatus := consts.DeployRunStart // container, err := docker.GetContainer(ctx, v.DockerAddr, v.CaPem, v.CertPem, v.KeyPem, v.ContainerName) // if err != nil { // logrus.Warnf("ContainerErr: %+v", err) // } // // if container != nil { // if container.State != "running" { // runStatus = consts.DeployRunStop // } // } else { // runStatus = consts.DeployRunNoFound // logrus.Warnf("ContainerInfo: %+v;\n", container) // } // // _, err = query.Use(config.DB).ServerDeploy.WithContext(ctx).Where(q.ID.Eq(v.ID)).Updates(model.ServerDeploy{ // RunStatus: runStatus, // LastSyncAt: time.Now(), // }) // // if err != nil { // logrus.Warnf("ServerDeploy Updates LastSyncAt err:%+v", err) // } // // } // // lists[k].DeployStatus = s.getLastDeployStatus(ctx, v.ID) //} newList1 := make([]forms.DeployListData, 0) if len(req.RunStatus) > 0 { for _, item := range lists { if character.InSlice(req.RunStatus, strconv.Itoa(int(item.RunStatus))) { newList1 = append(newList1, item) } } } else { newList1 = lists } newList2 := make([]forms.DeployListData, 0) if len(req.DeployStatus) > 0 { for _, item := range newList1 { if character.InSlice(req.DeployStatus, strconv.Itoa(int(item.DeployStatus))) { newList2 = append(newList2, item) } } } else { newList2 = newList1 } pageCount := int64(len(newList2)) pageList := make([]forms.DeployListData, 0) if offset+req.PerPage <= pageCount-1 { pageList = newList2[offset : req.PerPage+offset] } else if offset+req.PerPage > pageCount-1 && offset <= pageCount-1 { pageList = newList2[offset:] } models.List = pageList //models.List = lists models.Page = req.Page models.PerPage = req.PerPage // todo 分页逻辑处理 models.PageCount = (pageCount + req.PerPage - 1) / req.PerPage return serializer.Suc(models) } // getLastDeployStatus 获取最后的部署状态 func (s *sDeploy) getLastDeployStatus(ctx *gin.Context, deployId int64) int32 { var ql = query.Use(config.DB).ServerDeployLog log, _ := ql.WithContext(ctx).Where(ql.DeployID.Eq(deployId)).Order(ql.ID.Desc()).First() if log == nil { return consts.DeployStatusWait } return log.Status } // 下发一键重启等部署任务 func (s *sDeploy) Task(ctx *gin.Context, req forms.DeployTaskReq) serializer.Response { var ( batchId = character.Md5Content([]byte(character.RandStringRunes(32))) taskList = make(map[string]docker.PushDeployTaskInput, len(req.Ids)) ) err := config.DB.Transaction(func(tx *gorm.DB) error { for _, id := range req.Ids { var ( q = query.Use(config.DB).ServerDeploy ql = query.Use(config.DB).ServerDeployLog err error ) first, err := q.Where(q.ID.Eq(id)).First() if err != nil { return err } if first == nil { return errors.New(fmt.Sprintf("服务器不存在 id:%v", id)) } log, _ := ql.Where(ql.DeployID.Eq(first.ID)).Order(ql.CreatedAt.Desc()).First() // 只要正式服验证时间 if os.Getenv("GIN_MODE") == "release" && log != nil && log.CreatedAt.Unix()+30 > time.Now().Unix() { return errors.New(fmt.Sprintf("距离上次部署时间过近,请稍后%v秒后再试 id:%v", log.CreatedAt.Unix()+30-time.Now().Unix(), id)) } extra := make(map[string]interface{}) extra["deployServ"] = req.DeployServ strExtra, err := json.Marshal(extra) if err != nil { return err } // 新建部署任务记录 createData := &model.ServerDeployLog{ AdminID: token.GetUID(ctx), DeployID: first.ID, BatchID: batchId, TraceID: character.Md5Content([]byte(character.RandStringRunes(32))), ContainerName: first.ContainerName, Name: first.Name, PublishType: consts.DeployPublishTypeVersion, Version: req.Version, Extra: string(strExtra), LogFile: "", Status: consts.DeployStatusIng, EndAt: time.Now().AddDate(-20, 0, 0), CreatedAt: time.Now(), } if err = query.Use(config.DB).ServerDeployLog.WithContext(ctx).Create(createData); err != nil { return err } if createData.ID < 1 { return errors.New(fmt.Sprintf("创建失败,请稍后重试! id:%v", id)) } logrus.Warnf("DeployTask createData:%+v", createData) taskList[createData.TraceID] = docker.PushDeployTaskInput{ Ctx: ctx, Deploy: first, Log: createData, DeployServ: req.DeployServ, } } // 插入批量记录 if err := query.Use(config.DB).ServerDeployStat.WithContext(ctx).Create(&model.ServerDeployStat{ AdminID: token.GetUID(ctx), BatchID: batchId, Total: int64(len(req.Ids)), Success: 0, Fail: 0, Timeout: 0, NotifyAt: time.Now().AddDate(-20, 0, 0), IsNotify: consts.DeployNotifyNo, CreatedAt: time.Now(), }); err != nil { return err } return nil }) if err != nil { return serializer.DBErr(err.Error(), err) } for _, task := range taskList { err = docker.PushDeployTask(task) if err != nil { logrus.Infof("task.PushDeployTask return err:%+v", err) var ( q = query.Use(config.DB).ServerDeploy ql = query.Use(config.DB).ServerDeployLog ) _, err = query.Use(config.DB).ServerDeploy.WithContext(ctx).Where(q.ID.Eq(task.Deploy.ID)).Updates(model.ServerDeploy{ RunStatus: consts.DeployStatusErr, LastSyncAt: time.Now(), }) if err != nil { logrus.Warnf("task.ServerDeploy Updates LastSyncAt err:%+v", err) } errorMsg := fmt.Sprintf("创建远程任务失败:%v ", err.Error()) _, err = query.Use(config.DB).ServerDeployLog.WithContext(ctx).Where(ql.ID.Eq(task.Log.ID)).Updates(model.ServerDeployLog{ ErrorMsg: errorMsg, Status: consts.DeployStatusErr, EndAt: time.Now(), }) if err != nil { logrus.Warnf("task.ServerDeployLog Updates LastSyncAt err:%+v", err) } tx := config.DB.Exec("UPDATE server_deploy_stat SET fail=fail+? WHERE batch_id=?", 1, batchId) if tx.Error != nil { logrus.Warnf("task.ServerDeployLog Updates server_deploy_stat err:%+v", err) } // 推送失败通知 if task.Log.AdminID > 0 { msgData := ws.Msg{ Id: task.Deploy.ID, Type: consts.SocketDeployNotify, Code: consts.CodeParamErr, Msg: fmt.Sprintf("应用[%v]部署失败。远程服务器提示:%v", task.Deploy.Name, errorMsg), } go ws.SendToAdmin(task.Log.AdminID, msgData) } } } return serializer.Suc(nil) } func (s *sDeploy) Stop(ctx *gin.Context, req forms.DeployStopReq) serializer.Response { for _, id := range req.Ids { var ( q = query.Use(config.DB).ServerDeploy ql = query.Use(config.DB).ServerDeployLog err error ) first, err := q.Where(q.ID.Eq(id)).First() if err != nil { return serializer.DBErr(err.Error(), err) } if first == nil { return serializer.DBErr(fmt.Sprintf("Stop 服务器不存在 id:%v", id), nil) } log, _ := ql.Where(ql.DeployID.Eq(first.ID)).Order(ql.CreatedAt.Desc()).First() if log != nil && log.CreatedAt.Unix()+30 > time.Now().Unix() { return serializer.DBErr(fmt.Sprintf("Stop 距离上次部署时间过近,请稍后%v秒后再试 id:%v", log.CreatedAt.Unix()+30-time.Now().Unix(), id), nil) } // 新建部署任务记录 createData := &model.ServerDeployLog{ AdminID: token.GetUID(ctx), DeployID: first.ID, TraceID: character.Md5Content([]byte(character.RandStringRunes(32))), ContainerName: first.ContainerName, Name: first.Name, PublishType: consts.DeployPublishTypeStop, Extra: fmt.Sprintf(`{"stopType":%v}`, req.StopType), LogFile: "", Status: consts.DeployStatusIng, EndAt: time.Now(), CreatedAt: time.Now(), } if err = query.Use(config.DB).ServerDeployLog.WithContext(ctx).Create(createData); err != nil { return serializer.DBErr(err.Error(), err) } if createData.ID < 1 { return serializer.ParamErr(fmt.Sprintf("Stop 创建失败,请稍后重试! id:%v", id), nil) } err = docker.PushDeployStop(docker.PushDeployStopInput{ Ctx: ctx, Deploy: first, Log: createData, StopType: req.StopType, }) if err != nil { return serializer.ParamErr(fmt.Sprintf("Stop 创建远程任务失败:%v id:%v", err.Error(), id), nil) } } return serializer.Suc(nil) } // 编辑某服的配置 func (s *sDeploy) Edit(ctx *gin.Context, req forms.DeployEditReq) serializer.Response { var ( q = query.Use(config.DB).ServerDeploy err error ) // 编辑 if req.ID > 0 { _, err = query.Use(config.DB).ServerDeploy.WithContext(ctx).Where(q.ID.Eq(req.ID)).Updates(model.ServerDeploy{ GroupID: req.GroupID, ServerType: req.ServerType, ContainerName: req.ContainerName, Name: req.Name, DockerAddr: req.DockerAddr, CaPem: req.CaPem, CertPem: req.CertPem, KeyPem: req.KeyPem, Remark: req.Remark, IsMproom: req.IsMproom, LastSyncAt: time.Time{}, CreatedAt: time.Now(), }) if err != nil { return serializer.DBErr(err.Error(), err) } return serializer.Suc(nil) } // 新增 createData := model.ServerDeploy{ Environment: os.Getenv("GIN_MODE"), AdminID: token.GetUID(ctx), GroupID: req.GroupID, ContainerName: req.ContainerName, Name: req.Name, ServerType: req.ServerType, DockerAddr: req.DockerAddr, CaPem: req.CaPem, CertPem: req.CertPem, KeyPem: req.KeyPem, Remark: req.Remark, RunStatus: consts.DeployRunStop, DeployStatus: consts.DeployStatusWait, CreatedAt: time.Now(), } if err = query.Use(config.DB).ServerDeploy.WithContext(ctx).Omit(q.LastSyncAt.Desc()).Create(&createData); err != nil { return serializer.DBErr(err.Error(), err) } if createData.ID < 1 { return serializer.ParamErr("创建失败,请稍后重试!", nil) } return serializer.Suc(nil) } func (s *sDeploy) Delete(ctx *gin.Context, req forms.DeployDeleteReq) serializer.Response { // 编辑 if req.ID <= 0 { return serializer.ParamErr("ID不能空,删除失败!", nil) } if _, err := query.Use(config.DB).ServerDeploy.WithContext(ctx).Where(query.Use(config.DB).ServerDeploy.ID.Eq(req.ID)).Delete(); err != nil { return serializer.DBErr(err.Error(), err) } return serializer.Suc(nil) }