2021-09-06 13:05:10 +02:00
|
|
|
package schedules
|
|
|
|
|
|
|
|
import (
|
2021-09-06 14:01:38 +02:00
|
|
|
log "github.com/Sirupsen/logrus"
|
2021-09-06 13:05:10 +02:00
|
|
|
"github.com/ansible-semaphore/semaphore/db"
|
2022-01-30 18:43:15 +01:00
|
|
|
"github.com/ansible-semaphore/semaphore/lib"
|
2022-01-29 19:00:21 +01:00
|
|
|
"github.com/ansible-semaphore/semaphore/services/tasks"
|
2021-09-06 13:05:10 +02:00
|
|
|
"github.com/robfig/cron/v3"
|
2021-09-06 17:45:43 +02:00
|
|
|
"sync"
|
2021-09-06 13:05:10 +02:00
|
|
|
)
|
|
|
|
|
2021-09-06 14:01:38 +02:00
|
|
|
type ScheduleRunner struct {
|
2022-01-29 19:00:21 +01:00
|
|
|
schedule db.Schedule
|
|
|
|
pool *SchedulePool
|
2021-09-06 13:05:10 +02:00
|
|
|
}
|
|
|
|
|
2021-09-06 14:01:38 +02:00
|
|
|
func (r ScheduleRunner) Run() {
|
2022-01-31 05:22:08 +01:00
|
|
|
if r.schedule.RepositoryID != nil {
|
2022-01-30 18:43:15 +01:00
|
|
|
repo, err := r.pool.store.GetRepository(r.schedule.ProjectID, *r.schedule.RepositoryID)
|
|
|
|
if err != nil {
|
|
|
|
log.Error(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
remoteHash, err := lib.GitRepository{
|
|
|
|
Logger: nil,
|
|
|
|
TemplateID: r.schedule.TemplateID,
|
|
|
|
Repository: repo,
|
|
|
|
}.GetLastRemoteCommitHash()
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
log.Error(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-01-31 05:22:08 +01:00
|
|
|
if r.schedule.LastCommitHash != nil && remoteHash == *r.schedule.LastCommitHash {
|
2022-01-30 18:43:15 +01:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
err = r.pool.store.SetScheduleCommitHash(r.schedule.ProjectID, r.schedule.ID, remoteHash)
|
|
|
|
if err != nil {
|
|
|
|
log.Error(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-29 19:00:21 +01:00
|
|
|
_, err := r.pool.taskPool.AddTask(db.Task{
|
|
|
|
TemplateID: r.schedule.TemplateID,
|
|
|
|
ProjectID: r.schedule.ProjectID,
|
|
|
|
}, nil, r.schedule.ProjectID)
|
2022-01-30 18:43:15 +01:00
|
|
|
|
2021-09-06 14:01:38 +02:00
|
|
|
if err != nil {
|
|
|
|
log.Error(err)
|
|
|
|
}
|
2021-09-06 13:05:10 +02:00
|
|
|
}
|
|
|
|
|
2021-09-06 14:01:38 +02:00
|
|
|
type SchedulePool struct {
|
2022-01-29 19:00:21 +01:00
|
|
|
cron *cron.Cron
|
|
|
|
locker sync.Locker
|
|
|
|
store db.Store
|
|
|
|
taskPool *tasks.TaskPool
|
2021-09-06 13:05:10 +02:00
|
|
|
}
|
|
|
|
|
2021-09-06 17:45:43 +02:00
|
|
|
func (p *SchedulePool) init() {
|
2021-09-06 13:05:10 +02:00
|
|
|
p.cron = cron.New()
|
2021-09-06 17:45:43 +02:00
|
|
|
p.locker = &sync.Mutex{}
|
|
|
|
}
|
2021-09-06 13:05:10 +02:00
|
|
|
|
2022-01-29 19:00:21 +01:00
|
|
|
func (p *SchedulePool) Refresh() {
|
2021-09-07 10:42:06 +02:00
|
|
|
defer p.locker.Unlock()
|
|
|
|
|
2022-01-29 19:00:21 +01:00
|
|
|
schedules, err := p.store.GetSchedules()
|
2021-09-06 13:05:10 +02:00
|
|
|
|
|
|
|
if err != nil {
|
2021-09-06 14:01:38 +02:00
|
|
|
log.Error(err)
|
2021-09-06 13:05:10 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-09-06 17:45:43 +02:00
|
|
|
p.locker.Lock()
|
|
|
|
p.clear()
|
2021-09-06 13:05:10 +02:00
|
|
|
for _, schedule := range schedules {
|
2021-09-06 17:45:43 +02:00
|
|
|
_, err := p.addRunner(ScheduleRunner{
|
2022-01-29 19:00:21 +01:00
|
|
|
schedule: schedule,
|
|
|
|
pool: p,
|
2021-09-06 14:01:38 +02:00
|
|
|
})
|
2021-09-06 13:05:10 +02:00
|
|
|
if err != nil {
|
2021-09-06 14:01:38 +02:00
|
|
|
log.Error(err)
|
2021-09-06 13:05:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-06 17:45:43 +02:00
|
|
|
func (p *SchedulePool) addRunner(runner ScheduleRunner) (int, error) {
|
2022-01-29 19:00:21 +01:00
|
|
|
id, err := p.cron.AddJob(runner.schedule.CronFormat, runner)
|
2021-09-06 17:45:43 +02:00
|
|
|
|
2021-09-06 13:05:10 +02:00
|
|
|
if err != nil {
|
2021-09-06 17:45:43 +02:00
|
|
|
return 0, err
|
2021-09-06 13:05:10 +02:00
|
|
|
}
|
2021-09-06 17:45:43 +02:00
|
|
|
|
|
|
|
return int(id), nil
|
2021-09-06 13:05:10 +02:00
|
|
|
}
|
|
|
|
|
2021-09-06 14:01:38 +02:00
|
|
|
func (p *SchedulePool) Run() {
|
2021-09-06 13:05:10 +02:00
|
|
|
p.cron.Run()
|
|
|
|
}
|
|
|
|
|
2021-09-06 17:45:43 +02:00
|
|
|
func (p *SchedulePool) clear() {
|
2021-09-06 14:01:38 +02:00
|
|
|
runners := p.cron.Entries()
|
|
|
|
for _, r := range runners {
|
|
|
|
p.cron.Remove(r.ID)
|
|
|
|
}
|
2021-09-06 17:45:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (p *SchedulePool) Destroy() {
|
2021-09-07 10:42:06 +02:00
|
|
|
defer p.locker.Unlock()
|
2021-09-06 17:45:43 +02:00
|
|
|
p.locker.Lock()
|
|
|
|
p.cron.Stop()
|
|
|
|
p.clear()
|
2021-09-06 14:01:38 +02:00
|
|
|
p.cron = nil
|
|
|
|
}
|
2021-09-06 13:05:10 +02:00
|
|
|
|
2022-01-29 19:00:21 +01:00
|
|
|
func CreateSchedulePool(store db.Store, taskPool *tasks.TaskPool) SchedulePool {
|
|
|
|
pool := SchedulePool{
|
|
|
|
store: store,
|
|
|
|
taskPool: taskPool,
|
|
|
|
}
|
2021-09-06 17:45:43 +02:00
|
|
|
pool.init()
|
2022-01-29 19:00:21 +01:00
|
|
|
pool.Refresh()
|
|
|
|
return pool
|
2021-09-06 13:05:10 +02:00
|
|
|
}
|
2021-09-06 17:45:43 +02:00
|
|
|
|
|
|
|
func ValidateCronFormat(cronFormat string) error {
|
|
|
|
_, err := cron.ParseStandard(cronFormat)
|
|
|
|
return err
|
2022-01-29 19:00:21 +01:00
|
|
|
}
|