package v1 import ( "fmt" "git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/controller" "git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/middleware" "git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/model" "git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/model/event" "git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/model/id" sc "git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/model/schedule" tk "git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/model/schedule" "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" excel "git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/pkg/utils" "git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/service/schedule_engine" "git.inspur.com/sbg-jszt/cfn/cfn-schedule/internal/validator" "git.inspur.com/sbg-jszt/cfn/cfn-schedule/pkg/log" "github.com/gin-gonic/gin" "time" ) func CreateSchedRule(c *gin.Context) { rule := &sc.SchedRule{} err := validator.CheckPostParams(c, rule) if err != nil { controller.FailCode(c, errors.InvalidParameter, err, "请检查参数!") return } if ur, bl := c.Get(middleware.LoginUserKey); bl { if u, b := ur.(*user.User); b { rule.CreateBy = u.Name } } if _, err = rule.Create(); err != nil { controller.FailCode(c, errors.ServerError, err, "内部错误!") return } controller.Success(c, "") } // 编辑调度规则 func EditSchedRule(c *gin.Context) { rule := &sc.SchedRule{} err := validator.CheckPostParams(c, rule) if err != nil { controller.FailCode(c, errors.InvalidParameter, err, "请检查参数!") return } fields := map[string]interface{}{} fields["id"] = rule.Id _, err = rule.Get(fields) if err != nil { controller.FailCode(c, errors.InvalidParameter, err, "无法查找到对象!") return } updateColumns := []string{} _, err = rule.Update(updateColumns) if err != nil { controller.FailCode(c, errors.ServerError, err, "数据库错误!") return } controller.Success(c, "") } // 根据ID获取规则 func GetSchedRule(c *gin.Context) { rule := &sc.SchedRule{} id := c.Param("id") fields := map[string]interface{}{} fields["id"] = id result, err := rule.Get(fields) if err != nil { controller.FailCode(c, errors.InvalidParameter, err, "请检查参数!") return } controller.Success(c, result) } func StatisticSchedRule(c *gin.Context) { rule := &sc.SchedRule{} total, err := rule.Count() if err != nil { controller.FailCode(c, errors.InvalidParameter, err, "数据库异常!") return } now := time.Now() lastYear := now.AddDate(-1, 1, 0) startDate := time.Date(lastYear.Year(), lastYear.Month(), 1, 0, 0, 0, 0, time.Local) tmp, err := rule.CountByMonth(startDate) if err != nil { controller.FailCode(c, errors.InvalidParameter, err, "数据库异常!") return } group := make(map[string]interface{}) for _, item := range tmp { dateStr := item["date"].(string) group[dateStr] = item["count"] } for startDate.Before(now) { dateStr := startDate.Format("2006-01") if _, exist := group[dateStr]; !exist { group[dateStr] = 0 } startDate = startDate.AddDate(0, 1, 0) } result := map[string]interface{}{ "total": total, "group": group, } controller.Success(c, result) } type PageBodySchedRule struct { PageInfo *request.PageInfo `json:"pageInfo" binding:"required"` Keyword string `json:"keyword"` Status string `json:"status"` } // 分页获取规则 func PageSchedRules(c *gin.Context) { var pageBody PageBodySchedRule err := c.ShouldBindJSON(&pageBody) if err != nil { controller.FailCode(c, errors.InvalidParameter, err, "请检查参数!") return } rule := &sc.SchedRule{} fields := map[string]interface{}{} fields["keyword"] = pageBody.Keyword if pageBody.Status != "" { fields["rule_status"] = pageBody.Status } page := &model.Page[sc.SchedRule]{} page.Covert(pageBody.PageInfo) err = rule.Page(page, fields) if err != nil { controller.FailCode(c, errors.ServerError, err, "内部错误!") return } controller.Success(c, page) } type DeleteBodySchedRule struct { Ids []int64 `json:"ids" binding:"required"` } // 批量删除规则 func DeleteSchedRules(c *gin.Context) { var deleteBody DeleteBodySchedRule err := c.ShouldBindJSON(&deleteBody) if err != nil { controller.FailCode(c, errors.InvalidParameter, err, "请检查参数!") return } rule := &sc.SchedRule{} _, err = rule.DeleteBatch(deleteBody.Ids) if err != nil { controller.FailCode(c, errors.InvalidParameter, err, "删除失败!") return } controller.Success(c, "删除成功!") } // 停用启用操作 func DoSchedRule(c *gin.Context) { rule := &sc.SchedRule{} id := c.Param("id") option := c.Param("option") fields := map[string]interface{}{} fields["id"] = id result, err := rule.Get(fields) if err != nil { controller.FailCode(c, errors.InvalidParameter, err, "请检查参数!") return } if option == "0" { //todo 开启任务 } else if option == "1" { //todo 停止任务 } else { controller.FailCode(c, errors.InvalidParameter, err, "请检查参数!") return } result.RuleStatus = option result.Update(nil) controller.Success(c, "执行成功!") } type PageBodySchedTask struct { PageInfo *request.PageInfo `json:"pageInfo" binding:"required"` ListBodySchedTask } type ListBodySchedTask struct { TaskName string `json:"taskName"` TaskStatus string `json:"taskStatus"` StartTime *time.Time `json:"startTime"` EndTime *time.Time `json:"endTime"` } // 分页获取规则 func PageSchedTasks(c *gin.Context) { var pageBody PageBodySchedTask err := c.ShouldBindJSON(&pageBody) if err != nil { controller.FailCode(c, errors.InvalidParameter, err, "请检查参数!") return } task := &sc.SchedTask{} fields := map[string]interface{}{} fields["task_name"] = pageBody.TaskName if pageBody.TaskStatus != "" { fields["task_status"] = pageBody.TaskStatus } if pageBody.StartTime == nil { fields["start_time"] = time.Now().Add(-30 * 24 * time.Hour) } else { fields["start_time"] = pageBody.StartTime } if pageBody.EndTime == nil { fields["end_time"] = time.Now() } else { fields["end_time"] = pageBody.EndTime } page := &model.Page[sc.SchedTask]{} page.Covert(pageBody.PageInfo) err = task.Page(page, fields) if err != nil { controller.FailCode(c, errors.ServerError, err, "内部错误!") return } controller.Success(c, page) } // 分页获取规则 func ExportSchedTasks(c *gin.Context) { var listBody ListBodySchedTask err := c.ShouldBindJSON(&listBody) if err != nil { controller.FailCode(c, errors.InvalidParameter, err, "请检查参数!") return } task := &sc.SchedTask{} fields := map[string]interface{}{} fields["task_name"] = listBody.TaskName if listBody.TaskStatus != "" { fields["task_status"] = listBody.TaskStatus } fields["start_time"] = listBody.StartTime fields["end_time"] = listBody.EndTime tasks, err := task.ListAll(fields) if err != nil { controller.FailCode(c, errors.ServerError, err, "未找到记录!") return } rows := [][]interface{}{} for _, t := range tasks { row := []interface{}{ t.TaskName, t.Id, t.StartTime, t.EndTime, tk.TriggerTypeMap[t.TriggerType], "", tk.TaskStatusMap[t.TaskStatus], } rows = append(rows, row) } header := []string{"任务名称", "任务编号", "开始时间", "结束时间", "触发方式", "触发事件", "状态"} f, err := excel.ExportExcel("调度任务", header, rows) if err != nil { controller.FailCode(c, errors.ServerError, err, "生成excel文件失败!") return } f.SetColWidth("调度任务", "A", "A", 40) f.SetColWidth("调度任务", "C", "D", 15) f.SetColWidth("调度任务", "F", "F", 40) defer func() { if err := f.Close(); err != nil { fmt.Println(err) } }() if err := f.SaveAs("/tmp/task.xlsx"); err != nil { fmt.Println(err) controller.FailCode(c, errors.ServerError, err, "生成下载文件失败!") return } c.Header("Content-Type", "application/octet-stream") c.Header("Content-Disposition", "attachment; filename=task.xlsx") c.Header("Content-Transfer-Encoding", "binary") c.File("/tmp/task.xlsx") return } // 根据ID获取调度任务 func GetSchedTask(c *gin.Context) { task := &sc.SchedTask{} id := c.Param("id") fields := map[string]interface{}{} fields["id"] = id result, err := task.Get(fields) if err != nil { controller.FailCode(c, errors.InvalidParameter, err, "请检查参数!") return } controller.Success(c, result) } // 根据EventId获取调度任务 func GetSchedTaskByEvent(c *gin.Context) { task := &sc.SchedTask{} eventId := c.Param("eventId") fields := map[string]interface{}{} fields["event_id"] = eventId result, err := task.Get(fields) if err != nil { controller.FailCode(c, errors.InvalidParameter, err, "请检查参数!") return } controller.Success(c, result) } type TriggerTaskBody struct { PlanId string `json:"planId" validate:"required"` HandleAdvice string `json:"handleAdvice"` // 资源Id ResourceID string `json:"resourceId"` // 资源名称(cpCode) ResourceName string `json:"resourceName"` // 资源节点 ResourceNode string `json:"resourceNode"` // 资源类型 ResourceType string `json:"resourceType"` // 方案参数 SchemeParams string `json:"schemeParams"` } // 手动触发调度任务 func TriggerSchedTask_UserManual(c *gin.Context) { var body TriggerTaskBody err := c.ShouldBindJSON(&body) if err != nil { controller.FailCode(c, errors.InvalidParameter, err, "请检查参数!") return } // 暂不入库 record := event.EventRecord{ ResourceType: body.ResourceType, ResourceNode: body.ResourceNode, ResourceName: body.ResourceName, ResourceId: body.ResourceID, Id: id.NewEventRecord(), } task := &sc.SchedTask{} t := time.Now() sno := fmt.Sprintf("%d-%d%d-%s", t.Year(), t.Month(), t.Day(), record.Id) task.Id = record.ResourceType + "-" + sno task.TaskName = "" task.EventId = record.Id task.StartTime = time.Now() task.PlanId = body.PlanId task.CreateTime = time.Now() task.HandleAdvice = body.HandleAdvice task.HandleTime = time.Now() err = schedule_engine.PlanHandle(task.PlanId, task.Id, body.SchemeParams, record) if err != nil { //log.Errorf("%v", err) controller.FailCode(c, errors.ServerError, err, "调度方案失败!") return } task.TaskStatus = sc.TASK_STATUS_ING task.TriggerType = sc.TRIGGER_TYPE_MANUAL _, err = task.Create() if err != nil { log.Errorf("生成调度任务失败:%v,事件ID:%s", err, record.Id) controller.FailCode(c, errors.ServerError, err, "生成调度任务失败!") return } controller.Success(c, "") } // 手动触发调度任务 func TriggerSchedTask(c *gin.Context) { eventId := c.Param("eventId") event := &event.EventRecord{} eventFields := map[string]interface{}{} eventFields["id"] = eventId record, err := event.Get(eventFields) if err != nil { controller.FailCode(c, errors.InvalidParameter, err, "请检查参数!") return } var body TriggerTaskBody err = c.ShouldBindJSON(&body) if err != nil { controller.FailCode(c, errors.InvalidParameter, err, "请检查参数!") return } task := &sc.SchedTask{} fields := map[string]interface{}{} fields["event_id"] = eventId taskRecord, err := task.Get(fields) if ur, bl := c.Get(middleware.LoginUserKey); bl { if u, b := ur.(*user.User); b { task.HandleUsername = u.Name taskRecord.HandleUsername = u.Name } } if err != nil { t := time.Now() sno := fmt.Sprintf("%d-%d%d-%s", t.Year(), t.Month(), t.Day(), eventId) task.Id = record.ResourceType + "-" + sno task.TaskName = "" task.EventId = eventId task.StartTime = time.Now() task.PlanId = body.PlanId task.CreateTime = time.Now() task.HandleAdvice = body.HandleAdvice task.HandleTime = time.Now() err = schedule_engine.PlanHandle(task.PlanId, task.Id, "", record) if err != nil { log.Errorf("%v", err) controller.FailCode(c, errors.ServerError, err, "调度方案失败!") return } task.TaskStatus = sc.TASK_STATUS_ING task.TriggerType = sc.TRIGGER_TYPE_MANUAL _, err = task.Create() if err != nil { log.Errorf("生成调度任务失败:%v,事件ID:%s", err, eventId) controller.FailCode(c, errors.ServerError, err, "生成调度任务失败!") return } } else { taskRecord.TriggerType = sc.TRIGGER_TYPE_MANUAL taskRecord.StartTime = time.Now() taskRecord.EventId = eventId taskRecord.PlanId = body.PlanId taskRecord.HandleAdvice = body.HandleAdvice taskRecord.HandleTime = time.Now() err = schedule_engine.PlanHandle(taskRecord.PlanId, taskRecord.Id, "", record) if err != nil { log.Errorf("%v", err) controller.FailCode(c, errors.ServerError, err, "调度失败!") return } taskRecord.TaskStatus = sc.TASK_STATUS_ING _, err = taskRecord.Update(nil) if err != nil { log.Errorf("生成调度任务失败:%v,事件ID:%s", err, eventId) controller.FailCode(c, errors.ServerError, err, "生成调度任务失败!") return } } controller.Success(c, "") } type TaskCallBackBody struct { Status string `json:"status" validate:"required"` // 1:成功,2:失败 EndTime int64 `json:"endTime"` //秒级时间戳 } // 调度任务回调 func TaskCallBack(c *gin.Context) { taskId := c.Param("taskId") var body TaskCallBackBody err := c.ShouldBindJSON(&body) if err != nil { controller.FailCode(c, errors.InvalidParameter, err, "请检查参数!") return } task := &sc.SchedTask{} fields := map[string]interface{}{} fields["id"] = taskId taskRecord, err := task.Get(fields) if err != nil { log.Errorf("回调任务失败:%v", err) controller.FailCode(c, errors.InvalidParameter, err, "未找到调度任务,请检查参数!") return } taskRecord.TaskStatus = body.Status if body.EndTime <= 0 { taskRecord.EndTime = time.Now() } else { taskRecord.EndTime = time.Unix(body.EndTime, 22) } _, err = taskRecord.Update(nil) // todo 将事件更新至事件历史表(一删一增) if err != nil { log.Errorf("更新回调任务失败:%v", err) controller.FailCode(c, errors.ServerError, err, "内部错误!") return } go func() { evt := &event.EventRecord{} f := map[string]interface{}{} f["id"] = taskRecord.EventId e, err := evt.Get(f) if err == nil { eh := &event.HistoryEventRecord{ Id: e.Id, EventName: e.EventName, EventKey: e.EventKey, Level: e.Level, ResourceId: e.ResourceId, ResourceName: e.ResourceName, ResourceType: e.ResourceType, ResourceNode: e.ResourceNode, EventTime: e.EventTime, EventInfo: e.EventInfo, OperatorUser: taskRecord.HandleUsername, OperatorFinishTime: taskRecord.EndTime, CreateTime: time.Now(), } rows, _ := eh.SaveOrUpdate() if rows > 0 { e.Delete() } } }() controller.Success(c, "回调成功") } // 任务状态数统计 func CountTaskStatus(c *gin.Context) { task := &sc.SchedTask{} result, err := task.CountStatusNum() if err != nil { controller.FailCode(c, errors.InvalidParameter, err, "请检查参数!") return } controller.Success(c, result) } // 调度任务自动化率 func AutoRatio(c *gin.Context) { task := &sc.SchedTask{} result, err := task.AutoRatio() if err != nil { controller.FailCode(c, errors.InvalidParameter, err, "数据库异常!") return } controller.Success(c, result) }