package scheduler import ( "bytes" "encoding/gob" "fmt" "local/firestormy/config" "local/firestormy/config/ns" "local/firestormy/logger" "os/exec" "strings" "time" "github.com/google/uuid" ) type Job struct { Title string Name string Schedule string Raw string Runner Runner foo func() LastStatus int LastOutput string LastRuntime time.Duration LastRun time.Time Disabled bool } func NewJob(runner Runner, schedule, raw string) (*Job, error) { switch runner { case Bash: return newBashJob(schedule, raw) default: return nil, ErrBadRunner } } func newBashJob(schedule, sh string, title ...string) (*Job, error) { if !validCron(schedule) { return nil, ErrBadCron } j := &Job{ Name: uuid.New().String(), Schedule: schedule, Raw: sh, Runner: Bash, } if len(title) == 0 || len(title[0]) == 0 { j.Title = j.Name } else { j.Title = title[0] } j.foo = func() { cmd := exec.Command("bash", "-c", sh) j.LastRun = time.Now() start := time.Now() out, err := cmd.CombinedOutput() j.LastRuntime = time.Since(start) if err != nil { out = []byte(fmt.Sprintf("error running command: %v: %v", err, out)) } j.LastOutput = strings.TrimSpace(string(out)) if cmd != nil && cmd.ProcessState != nil { j.LastStatus = cmd.ProcessState.ExitCode() } b, err := j.Encode() if err == nil { // TODO webpage doenst load post SET despite this returning nil config.Store.Set(j.Name, b, ns.Jobs...) } logger.New().Info("result", fmt.Sprintf("%+v", j)) } return j, nil } func (j *Job) Run() { j.foo() } func (j *Job) Encode() ([]byte, error) { buff := bytes.NewBuffer(nil) encoder := gob.NewEncoder(buff) err := encoder.Encode(*j) return buff.Bytes(), err } func (j *Job) Decode(b []byte) error { buff := bytes.NewReader(b) decoder := gob.NewDecoder(buff) err := decoder.Decode(j) if err != nil { return err } k, err := NewJob(j.Runner, j.Schedule, j.Raw) if err == nil { k.Name = j.Name k.Title = j.Title k.LastStatus = j.LastStatus k.LastOutput = j.LastOutput k.LastRuntime = j.LastRuntime k.LastRun = j.LastRun k.Disabled = j.Disabled *j = *k } return err }