package handler import ( "bytes" "encoding/json" "fmt" "github.com/gin-gonic/gin" "os/exec" "strconv" "strings" "videoplayer/dao" "videoplayer/proto" "videoplayer/worker" ) type CIDCreateReq struct { Name string `json:"name" form:"name"` Url string `json:"url" form:"url"` Time int `json:"time" form:"time"` // 定时任务,单位秒,大于0表示定时任务 Script string `json:"script" form:"script"` } type CIDDeleteReq struct { ID int `json:"id" form:"id"` } type CIDRunReq struct { ID int `json:"id" form:"id"` } type CIDLogReq struct { ID int `json:"id" form:"id"` } type CIDUpdateReq struct { ID int `json:"id" form:"id"` Name string `json:"name" form:"name"` Url string `json:"url" form:"url"` Time int `json:"time" form:"time"` // 定时任务,单位秒,大于0表示定时任务 Script string `json:"script" form:"script"` Token string `json:"cidtoken" form:"cidtoken"` } func SetUpCIDGroup(router *gin.Engine) { cidGroup := router.Group("/cid") //持续集成、部署 cidGroup.POST("/create", CreateCID) cidGroup.POST("/delete", DeleteCID) cidGroup.POST("/update", UpdateCID) cidGroup.POST("/list", GetCIDList) cidGroup.POST("/run", RunCID) cidGroup.POST("/log", GetCIDLogList) //获取执行日志 cidGroup.POST("/log/detail", GetCIDLog) //获取执行日志详情 cidGroup.POST("/callback", CIDCallback) } func RunCID(c *gin.Context) { var req CIDRunReq id, _ := c.Get("id") authID := int(id.(float64)) //获取权限 user := dao.FindUserByUserID(authID) if user.Run == false { c.JSON(200, gin.H{"error": "no run Permissions", "code": proto.NoRunPermissions, "message": "no run Permissions"}) return } if err := c.ShouldBind(&req); err == nil { // 获取用户ID username, _ := c.Get("username") cid := dao.FindCIDByID(req.ID, authID) if cid.ID == 0 { c.JSON(200, gin.H{"error": "CID not found", "code": proto.OperationFailed, "message": "failed"}) return } else { go RunShell(username.(string), cid.Url, cid.Script, req.ID, authID) c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success", "data": "success"}) } } else { c.JSON(200, gin.H{"error": err.Error(), "code": proto.ParameterError, "message": "failed"}) } } func CreateCID(c *gin.Context) { var req CIDCreateReq if err := c.ShouldBind(&req); err == nil { // 获取用户ID id, _ := c.Get("id") authID := int(id.(float64)) token, _ := generateRandomHexString(32) res := dao.CreateCID(req.Name, req.Url, req.Script, token, req.Time, authID) if res != 0 { c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success", "data": res}) } else { c.JSON(200, gin.H{"error": "CreateCID failed", "code": proto.OperationFailed, "message": "failed"}) } } else { c.JSON(200, gin.H{"error": err.Error(), "code": proto.ParameterError, "message": "failed"}) } } func DeleteCID(c *gin.Context) { var req CIDDeleteReq if err := c.ShouldBind(&req); err == nil { // 获取用户ID id, _ := c.Get("id") authID := int(id.(float64)) cid := dao.DeleteCIDByID(req.ID, authID) if cid == false { c.JSON(200, gin.H{"error": "CID not found", "code": proto.OperationFailed, "message": "failed"}) return } else { c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success", "data": "success"}) } } else { c.JSON(200, gin.H{"error": err.Error(), "code": proto.ParameterError, "message": "failed"}) } } func UpdateCID(c *gin.Context) { var req CIDUpdateReq if err := c.ShouldBind(&req); err == nil { // 获取用户ID id, _ := c.Get("id") authID := int(id.(float64)) cid := dao.UpdateCIDByID(req.ID, authID, req.Time, req.Name, req.Url, req.Script, req.Token) if cid == false { c.JSON(200, gin.H{"error": "CID not found", "code": proto.OperationFailed, "message": "failed"}) return } else { c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success", "data": "success"}) } } else { c.JSON(200, gin.H{"error": err.Error(), "code": proto.ParameterError, "message": "failed"}) } } func GetCIDList(c *gin.Context) { // 获取用户ID id, _ := c.Get("id") authID := int(id.(float64)) cids := dao.FindCIDByAuthID(authID) c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success", "data": cids}) } func GetCIDLog(c *gin.Context) { var req CIDRunReq if err := c.ShouldBind(&req); err == nil { // 获取用户ID id, _ := c.Get("id") authID := int(id.(float64)) cidLogs := dao.FindRunLogByCIDLogID(req.ID, authID) c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success", "data": cidLogs}) } else { c.JSON(200, gin.H{"error": err.Error(), "code": proto.ParameterError, "message": "failed"}) } } func GetCIDLogList(c *gin.Context) { // 获取用户ID id, _ := c.Get("id") authID := int(id.(float64)) var req CIDLogReq if err := c.ShouldBind(&req); err == nil { cidLogs := dao.FindRunLogByID(authID, req.ID) c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success", "data": cidLogs}) } else { c.JSON(200, gin.H{"error": err.Error(), "code": proto.ParameterError, "message": "failed"}) } } func CIDCallback(c *gin.Context) { // 获取用户ID token := c.Query("token") cid_id := c.Query("id") fmt.Println("token:", token, "cid_id:", cid_id) //将cid转换为int cid, _ := strconv.Atoi(cid_id) if token == "" || cid == 0 { c.JSON(200, gin.H{"error": "parameter error", "code": proto.ParameterError, "message": "failed"}) return } res := dao.FindCIDByIDAndToken(cid, token) if res.ID == 0 { c.JSON(200, gin.H{"error": "CID not found by id and token", "code": proto.OperationFailed, "message": "failed"}) return } user := dao.FindUserByUserID(res.Auth_id) if user.Run == false { c.JSON(200, gin.H{"error": "no run Permissions", "code": proto.NoRunPermissions, "message": "the user has no run Permissions"}) return } if res.ID != 0 { user := dao.FindUserByID(res.Auth_id) go RunShell(user[0].Name, res.Url, res.Script, int(res.ID), res.Auth_id) c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success", "data": "success"}) } else { c.JSON(200, gin.H{"error": "CID not found by id and token", "code": proto.OperationFailed, "message": "failed"}) return } } func RunShell(username, url, script string, id, authID int) { strs := strings.Split(url, "/") name := strs[len(strs)-1] names := strings.Split(name, ".") name = names[0] //脚本内容,不同用户的持续集成、部署目录不同 scriptContent := ` echo "start" ` + script + ` echo "end"` //执行脚本 cmd := exec.Command("/bin/bash", "-c", scriptContent) // 使用bytes.Buffer捕获输出 var out bytes.Buffer cmd.Stdout = &out err3 := cmd.Run() err3_info := "" if err3 != nil { err3_info = err3.Error() } //fmt.Println("bash content:", scriptContent) dao.CreateRunLog(id, authID, scriptContent, out.String(), err3_info) //添加执行日志 } // 定时任务处理逻辑 func RunCron() { //从redis查看是否有定时任务 //如果有定时任务,执行定时任务 //如果没有定时任务,查找数据库是否有定时任务,如果有,则加入redis,如果没有,则不做任何操作 key := "cron_cid_runs" res := worker.GetRedis(key) if res == "" { cids := dao.FindCIDByTime() cid_workers := make([]proto.CIDRUN, 0) for _, v := range cids { cid_worker := proto.CIDRUN{CID: v.ID, Curr: v.Time, Every: v.Time} cid_workers = append(cid_workers, cid_worker) } if len(cid_workers) > 0 { //将定时任务加入redis json_data, err := json.Marshal(cid_workers) if err != nil { fmt.Println("json marshal failed") } worker.SetRedis(key, string(json_data)) } } else { var cid_workers []proto.CIDRUN cid_redis_workers := worker.GetRedis(key) err := json.Unmarshal([]byte(cid_redis_workers), &cid_workers) if err != nil { fmt.Println("json unmarshal failed") } for _, v := range cid_workers { //查找定时任务 if v.Curr-10 <= 0 { cid := dao.FindCIDByCID(v.CID) if cid.ID != 0 { go RunShell("cron", cid.Url, cid.Script, int(cid.ID), cid.Auth_id) } } else { v.Curr = v.Curr - 10 } } //将定时任务加入redis json_data, err := json.Marshal(cid_workers) if err != nil { fmt.Println("json marshal failed") } worker.SetRedis(key, string(json_data)) } }