2018-07-11 08:39:20 +00:00
|
|
|
package cron
|
|
|
|
|
|
|
|
import (
|
2019-03-21 01:20:14 +00:00
|
|
|
"github.com/portainer/portainer/api"
|
2019-12-05 04:02:27 +00:00
|
|
|
"github.com/robfig/cron/v3"
|
2018-07-11 08:39:20 +00:00
|
|
|
)
|
|
|
|
|
2018-11-06 09:49:48 +00:00
|
|
|
// JobScheduler represents a service for managing crons
|
2018-07-11 08:39:20 +00:00
|
|
|
type JobScheduler struct {
|
2018-11-05 20:58:15 +00:00
|
|
|
cron *cron.Cron
|
2018-07-11 08:39:20 +00:00
|
|
|
}
|
|
|
|
|
2018-11-06 09:49:48 +00:00
|
|
|
// NewJobScheduler initializes a new service
|
2018-11-05 20:58:15 +00:00
|
|
|
func NewJobScheduler() *JobScheduler {
|
2018-07-11 08:39:20 +00:00
|
|
|
return &JobScheduler{
|
2019-10-08 01:39:37 +00:00
|
|
|
cron: cron.New(),
|
2018-07-11 08:39:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-13 01:39:26 +00:00
|
|
|
// ScheduleJob schedules the execution of a job via a runner
|
|
|
|
func (scheduler *JobScheduler) ScheduleJob(runner portainer.JobRunner) error {
|
2019-09-14 22:47:44 +00:00
|
|
|
_, err := scheduler.cron.AddJob(runner.GetSchedule().CronExpression, runner)
|
|
|
|
return err
|
2018-11-06 09:49:48 +00:00
|
|
|
}
|
|
|
|
|
2018-11-13 01:39:26 +00:00
|
|
|
// UpdateSystemJobSchedule updates the first occurence of the specified
|
|
|
|
// scheduled job based on the specified job type.
|
|
|
|
// It does so by re-creating a new cron
|
|
|
|
// and adding all the existing jobs. It will then re-schedule the new job
|
|
|
|
// with the update cron expression passed in parameter.
|
|
|
|
// NOTE: the cron library do not support updating schedules directly
|
|
|
|
// hence the work-around
|
|
|
|
func (scheduler *JobScheduler) UpdateSystemJobSchedule(jobType portainer.JobType, newCronExpression string) error {
|
|
|
|
cronEntries := scheduler.cron.Entries()
|
|
|
|
newCron := cron.New()
|
|
|
|
|
|
|
|
for _, entry := range cronEntries {
|
|
|
|
if entry.Job.(portainer.JobRunner).GetSchedule().JobType == jobType {
|
2019-09-14 22:47:44 +00:00
|
|
|
_, err := newCron.AddJob(newCronExpression, entry.Job)
|
2018-11-13 01:39:26 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2018-12-12 01:11:40 +00:00
|
|
|
continue
|
2018-11-13 01:39:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
newCron.Schedule(entry.Schedule, entry.Job)
|
|
|
|
}
|
|
|
|
|
|
|
|
scheduler.cron.Stop()
|
|
|
|
scheduler.cron = newCron
|
|
|
|
scheduler.cron.Start()
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// UpdateJobSchedule updates a specific scheduled job by re-creating a new cron
|
2018-11-06 09:49:48 +00:00
|
|
|
// and adding all the existing jobs. It will then re-schedule the new job
|
|
|
|
// via the specified JobRunner parameter.
|
2018-11-05 20:58:15 +00:00
|
|
|
// NOTE: the cron library do not support updating schedules directly
|
2018-11-06 09:49:48 +00:00
|
|
|
// hence the work-around
|
2018-11-13 01:39:26 +00:00
|
|
|
func (scheduler *JobScheduler) UpdateJobSchedule(runner portainer.JobRunner) error {
|
2018-11-06 09:49:48 +00:00
|
|
|
cronEntries := scheduler.cron.Entries()
|
2018-11-05 20:58:15 +00:00
|
|
|
newCron := cron.New()
|
2018-07-11 08:39:20 +00:00
|
|
|
|
2018-11-06 09:49:48 +00:00
|
|
|
for _, entry := range cronEntries {
|
2018-07-11 08:39:20 +00:00
|
|
|
|
2018-11-13 01:39:26 +00:00
|
|
|
if entry.Job.(portainer.JobRunner).GetSchedule().ID == runner.GetSchedule().ID {
|
2018-11-05 20:58:15 +00:00
|
|
|
|
2018-11-06 09:49:48 +00:00
|
|
|
var jobRunner cron.Job = runner
|
2018-11-13 01:39:26 +00:00
|
|
|
if entry.Job.(portainer.JobRunner).GetSchedule().JobType == portainer.SnapshotJobType {
|
2018-11-06 09:49:48 +00:00
|
|
|
jobRunner = entry.Job
|
2018-11-05 20:58:15 +00:00
|
|
|
}
|
2018-11-06 09:49:48 +00:00
|
|
|
|
2019-09-14 22:47:44 +00:00
|
|
|
_, err := newCron.AddJob(runner.GetSchedule().CronExpression, jobRunner)
|
2018-11-06 09:49:48 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
2018-11-05 20:58:15 +00:00
|
|
|
}
|
2018-12-12 01:11:40 +00:00
|
|
|
continue
|
2018-11-05 20:58:15 +00:00
|
|
|
}
|
2018-07-11 08:39:20 +00:00
|
|
|
|
2018-11-06 09:49:48 +00:00
|
|
|
newCron.Schedule(entry.Schedule, entry.Job)
|
2018-07-11 08:39:20 +00:00
|
|
|
}
|
|
|
|
|
2018-11-05 20:58:15 +00:00
|
|
|
scheduler.cron.Stop()
|
|
|
|
scheduler.cron = newCron
|
|
|
|
scheduler.cron.Start()
|
|
|
|
return nil
|
2018-07-11 08:39:20 +00:00
|
|
|
}
|
|
|
|
|
2018-11-13 01:39:26 +00:00
|
|
|
// UnscheduleJob remove a scheduled job by re-creating a new cron
|
2018-11-05 20:58:15 +00:00
|
|
|
// and adding all the existing jobs except for the one specified via scheduleID.
|
|
|
|
// NOTE: the cron library do not support removing schedules directly
|
2018-11-06 09:49:48 +00:00
|
|
|
// hence the work-around
|
2018-11-13 01:39:26 +00:00
|
|
|
func (scheduler *JobScheduler) UnscheduleJob(scheduleID portainer.ScheduleID) {
|
2018-11-06 09:49:48 +00:00
|
|
|
cronEntries := scheduler.cron.Entries()
|
2018-11-05 20:58:15 +00:00
|
|
|
newCron := cron.New()
|
2018-07-11 08:39:20 +00:00
|
|
|
|
2018-11-06 09:49:48 +00:00
|
|
|
for _, entry := range cronEntries {
|
2018-11-05 20:58:15 +00:00
|
|
|
|
2018-11-13 01:39:26 +00:00
|
|
|
if entry.Job.(portainer.JobRunner).GetSchedule().ID == scheduleID {
|
2018-11-06 09:49:48 +00:00
|
|
|
continue
|
2018-07-11 08:39:20 +00:00
|
|
|
}
|
2018-11-05 20:58:15 +00:00
|
|
|
|
2018-11-06 09:49:48 +00:00
|
|
|
newCron.Schedule(entry.Schedule, entry.Job)
|
2018-07-11 08:39:20 +00:00
|
|
|
}
|
|
|
|
|
2018-11-05 20:58:15 +00:00
|
|
|
scheduler.cron.Stop()
|
|
|
|
scheduler.cron = newCron
|
2018-07-11 08:39:20 +00:00
|
|
|
scheduler.cron.Start()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Start starts the scheduled jobs
|
|
|
|
func (scheduler *JobScheduler) Start() {
|
|
|
|
if len(scheduler.cron.Entries()) > 0 {
|
|
|
|
scheduler.cron.Start()
|
|
|
|
}
|
|
|
|
}
|