admin-dashboard-backend/grouptasks/grouptasks.go

245 lines
6.2 KiB
Go

package grouptasks
import (
"encoding/json"
"fmt"
"janex/admin-dashboard-backend/modules/cache"
"janex/admin-dashboard-backend/modules/database"
"janex/admin-dashboard-backend/modules/structs"
"janex/admin-dashboard-backend/modules/utils"
"janex/admin-dashboard-backend/socketclients"
"os"
"os/exec"
"time"
"github.com/google/uuid"
"github.com/rs/zerolog/log"
)
var root = "./groupTasks/groups/"
func ReadGroups() {
entries, err := os.ReadDir(root)
if err != nil {
log.Error().Msg("Failed to read groups directory, error: " + err.Error())
return
}
for _, entry := range entries {
log.Info().Msgf("Entry: %s", entry.Name())
files, err := os.ReadDir(root + entry.Name())
if err != nil {
log.Error().Msg("Failed to read groups directory files, error: " + err.Error())
return
}
for _, file := range files {
log.Info().Msgf("File: %s", file.Name())
if file.Name() == "index.json" {
content, err := os.ReadFile(root + entry.Name() + "/index.json")
if err != nil {
log.Error().Msg("Failed to read file content, error: " + err.Error())
return
}
var group structs.Group
json.Unmarshal(content, &group)
group.Id = entry.Name()
log.Info().Msgf("Group: %s", group)
cache.AddCategoryGroup(group)
}
}
}
}
const (
RunGroupTaskStartTypeNormal = 0
RunGroupTaskStartTypeTryAgain = 1
)
type RunGroupTaskArgs struct {
StartType uint8
GroupTaskId string
Category string
GroupId string
Step uint8
TaskStepId string
GlobalInputs []interface{}
}
func RunGroupTask(args RunGroupTaskArgs) {
log.Debug().Msgf("global input: %v", args.GlobalInputs)
categoryGroup := GetCategoryGroupTaskByCategoryAndGroupId(args.Category, args.GroupId)
log.Debug().Msgf("RunGroupTask %s", categoryGroup)
log.Debug().Msgf("script path %s", root+categoryGroup.Id+"/"+categoryGroup.Tasks[args.Step-1].ScriptPath)
groupTaskStep := structs.GroupTaskSteps{
GroupTasksId: args.GroupTaskId,
Step: args.Step,
Status: structs.GroupTasksStatusRunning,
StartedAt: time.Now(),
}
if args.StartType == RunGroupTaskStartTypeNormal {
groupTaskStep.Id = uuid.New().String()
database.DB.Create(&groupTaskStep)
socketclients.BroadcastMessage(structs.SendSocketMessage{
Cmd: utils.SentCmdNewGroupTaskStep,
Body: groupTaskStep,
})
} else if args.StartType == RunGroupTaskStartTypeTryAgain {
groupTaskStep.Id = args.TaskStepId
database.DB.Model(&structs.GroupTaskSteps{}).Where("id = ?", groupTaskStep.Id).Updates(groupTaskStep)
socketclients.BroadcastMessage(structs.SendSocketMessage{
Cmd: utils.SentCmdUpdateGroupTaskStep,
Body: groupTaskStep,
})
}
// set group task to running
database.DB.Model(&structs.GroupTasks{}).Where("id = ?", groupTaskStep.GroupTasksId).Updates(structs.GroupTasks{
Status: structs.GroupTasksStatusRunning,
})
var dbGroupTask structs.GroupTasks
database.DB.First(&dbGroupTask, "id = ?", groupTaskStep.GroupTasksId)
socketclients.BroadcastMessage(structs.SendSocketMessage{
Cmd: utils.SentCmdUpdateGroupTask,
Body: dbGroupTask,
})
// execute script
cmd, err := exec.Command("python3", root+categoryGroup.Id+"/"+categoryGroup.Tasks[args.Step-1].ScriptPath).Output()
cmdLog := string(cmd)
if err != nil {
if exitErr, ok := err.(*exec.ExitError); ok {
exitCode := exitErr.ExitCode()
log.Error().Msgf("exit code %d", exitCode)
cmdLog += fmt.Sprintf("\nExit code: %v", exitCode)
}
log.Error().Msgf("error exec command %s", err.Error())
groupTaskStep.Status = structs.GroupTasksStatusFailed
} else {
groupTaskStep.Status = structs.GroupTasksStatusFinished
}
fmt.Println(cmdLog)
groupTaskStep.Log = cmdLog
groupTaskStep.EndedAt = time.Now()
database.DB.Model(&structs.GroupTaskSteps{}).Where("id = ?", groupTaskStep.Id).Updates(groupTaskStep)
socketclients.BroadcastMessage(structs.SendSocketMessage{
Cmd: utils.SentCmdUpdateGroupTaskStep,
Body: groupTaskStep,
})
log.Info().Msgf("run next task")
if int(args.Step) < len(categoryGroup.Tasks) {
if groupTaskStep.Status == structs.GroupTasksStatusFailed {
// set group task to failed
database.DB.Model(&structs.GroupTasks{}).Where("id = ?", groupTaskStep.GroupTasksId).Updates(structs.GroupTasks{
Status: structs.GroupTasksStatusFailed,
})
var dbGroupTask structs.GroupTasks
database.DB.First(&dbGroupTask, "id = ?", groupTaskStep.GroupTasksId)
socketclients.BroadcastMessage(structs.SendSocketMessage{
Cmd: utils.SentCmdUpdateGroupTask,
Body: dbGroupTask,
})
} else {
args.StartType = RunGroupTaskStartTypeNormal
args.Step = args.Step + 1
database.DB.Model(&structs.GroupTasks{}).Where("id = ?", groupTaskStep.GroupTasksId).Updates(structs.GroupTasks{
CurrentTasksStep: args.Step,
})
var dbGroupTask structs.GroupTasks
database.DB.First(&dbGroupTask, "id = ?", groupTaskStep.GroupTasksId)
socketclients.BroadcastMessage(structs.SendSocketMessage{
Cmd: utils.SentCmdUpdateGroupTask,
Body: dbGroupTask,
})
log.Debug().Msgf("RUN NEXT TASK %s", groupTaskStep)
RunGroupTask(args)
}
} else {
// set group task to finished
database.DB.Model(&structs.GroupTasks{}).Where("id = ?", groupTaskStep.GroupTasksId).Updates(structs.GroupTasks{
Status: structs.GroupTasksStatusFinished,
EndedAt: time.Now(),
})
var dbGroupTask structs.GroupTasks
database.DB.First(&dbGroupTask, "id = ?", groupTaskStep.GroupTasksId)
socketclients.BroadcastMessage(structs.SendSocketMessage{
Cmd: utils.SentCmdUpdateGroupTask,
Body: dbGroupTask,
})
log.Info().Msg("SET TO FINISHED")
}
}
func GetAllGroupTasks() []structs.GroupTasks {
var groupTasks []structs.GroupTasks
database.DB.Find(&groupTasks)
return groupTasks
}
func GetAllGroupTasksSteps() []structs.GroupTaskSteps {
var groupTaskStepsLogs []structs.GroupTaskSteps
database.DB.Find(&groupTaskStepsLogs)
return groupTaskStepsLogs
}
func GetCategoryGroupTaskByCategoryAndGroupId(category string, groupId string) structs.Group {
for _, categoryGroup := range cache.GetCategoryGroups() {
if categoryGroup.Category == category {
for _, group := range categoryGroup.Groups {
if group.Id == groupId {
return group
}
}
}
}
return structs.Group{}
}