package server import ( "context" "fmt" "os" "strconv" "strings" "time" "github.com/mimecast/dtail/internal/clients" "github.com/mimecast/dtail/internal/config" "github.com/mimecast/dtail/internal/io/dlog" "github.com/mimecast/dtail/internal/omode" gossh "golang.org/x/crypto/ssh" ) type scheduler struct { cfg config.RuntimeConfig } func newScheduler(cfg config.RuntimeConfig) *scheduler { return &scheduler{cfg: cfg} } func (s *scheduler) start(ctx context.Context) { dlog.Server.Info("Starting scheduled job runner after 2s") // First run after just 10s! time.Sleep(time.Second * 2) s.runJobs(ctx) runTicker := time.NewTicker(time.Minute) defer runTicker.Stop() for { select { case <-runTicker.C: s.runJobs(ctx) case <-ctx.Done(): return } } } func (s *scheduler) runJobs(ctx context.Context) { for i := range s.cfg.Server.Schedule { job := &s.cfg.Server.Schedule[i] if !job.Enable { dlog.Server.Debug(job.Name, "Not running job as not enabled") continue } hour, err := strconv.Atoi(time.Now().Format("15")) if err != nil { dlog.Server.Error(job.Name, "Unable to create job", err) continue } if hour < job.TimeRange[0] || hour >= job.TimeRange[1] { dlog.Server.Debug(job.Name, "Not running job out of time range") continue } s.runJob(ctx, job) } } func (s *scheduler) runJob(ctx context.Context, job *config.Scheduled) { files := fillDates(job.Files) outfile := fillDates(job.Outfile) _, err := os.Stat(outfile) if !os.IsNotExist(err) { dlog.Server.Debug(job.Name, "Not running job as outfile already exists", outfile) return } servers := strings.Join(job.Servers, ",") if servers == "" { servers = s.cfg.Server.SSHBindAddress } args := config.Args{ ConnectionsPerCPU: config.DefaultConnectionsPerCPU, Discovery: job.Discovery, ServersStr: servers, What: files, Mode: omode.MapClient, UserName: config.ScheduleUser, } args.SSHAuthMethods = append(args.SSHAuthMethods, gossh.Password(job.Name)) args.QueryStr = fmt.Sprintf("%s outfile %s", job.Query, outfile) client, err := clients.NewMaprClient(args, clients.CumulativeMode) if err != nil { dlog.Server.Error(fmt.Sprintf("Unable to create job %s", job.Name), err) return } jobCtx, cancel := context.WithCancel(ctx) defer cancel() dlog.Server.Info(fmt.Sprintf("Starting job %s", job.Name)) status := client.Start(jobCtx, make(chan string)) logMessage := fmt.Sprintf("Job exited with status %d", status) if status != 0 { dlog.Server.Warn(logMessage) return } dlog.Server.Info(logMessage) }