mirror of
https://github.com/portainer/portainer.git
synced 2025-07-24 15:59:41 +02:00
feat(api): revamp scheduling to introduce system schedules (#2433)
* feat(api): revamp scheduling to introduce system schedules * fix(api): fix linting issues * fix(api): fix lint issues * refactor(api): fix lint issues
This commit is contained in:
parent
dbbea0a20f
commit
110fcc46a6
16 changed files with 475 additions and 297 deletions
|
@ -6,7 +6,6 @@ import (
|
|||
"github.com/gorilla/mux"
|
||||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/portainer"
|
||||
"github.com/portainer/portainer/cron"
|
||||
"github.com/portainer/portainer/http/security"
|
||||
)
|
||||
|
||||
|
@ -39,13 +38,3 @@ func NewHandler(bouncer *security.RequestBouncer) *Handler {
|
|||
|
||||
return h
|
||||
}
|
||||
|
||||
func (handler *Handler) createTaskExecutionContext(scheduleID portainer.ScheduleID, endpoints []portainer.EndpointID) *cron.ScriptTaskContext {
|
||||
return &cron.ScriptTaskContext{
|
||||
JobService: handler.JobService,
|
||||
EndpointService: handler.EndpointService,
|
||||
FileService: handler.FileService,
|
||||
ScheduleID: scheduleID,
|
||||
TargetEndpoints: endpoints,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -142,20 +142,27 @@ func (handler *Handler) createSchedule(name, image, cronExpression string, endpo
|
|||
return nil, err
|
||||
}
|
||||
|
||||
taskContext := handler.createTaskExecutionContext(scheduleIdentifier, endpoints)
|
||||
task := cron.NewScriptTask(image, scriptPath, taskContext)
|
||||
|
||||
err = handler.JobScheduler.ScheduleTask(cronExpression, task)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
job := &portainer.ScriptExecutionJob{
|
||||
Endpoints: endpoints,
|
||||
Image: image,
|
||||
ScriptPath: scriptPath,
|
||||
ScheduleID: scheduleIdentifier,
|
||||
}
|
||||
|
||||
schedule := &portainer.Schedule{
|
||||
ID: scheduleIdentifier,
|
||||
Name: name,
|
||||
Endpoints: endpoints,
|
||||
CronExpression: cronExpression,
|
||||
Task: task,
|
||||
ID: scheduleIdentifier,
|
||||
Name: name,
|
||||
CronExpression: cronExpression,
|
||||
JobType: portainer.ScriptExecutionJobType,
|
||||
ScriptExecutionJob: job,
|
||||
}
|
||||
|
||||
jobContext := cron.NewScriptExecutionJobContext(handler.JobService, handler.EndpointService, handler.FileService)
|
||||
jobRunner := cron.NewScriptExecutionJobRunner(job, jobContext)
|
||||
|
||||
err = handler.JobScheduler.CreateSchedule(schedule, jobRunner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = handler.ScheduleService.CreateSchedule(schedule)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package schedules
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
httperror "github.com/portainer/libhttp/error"
|
||||
|
@ -15,7 +16,16 @@ func (handler *Handler) scheduleDelete(w http.ResponseWriter, r *http.Request) *
|
|||
return &httperror.HandlerError{http.StatusBadRequest, "Invalid schedule identifier route variable", err}
|
||||
}
|
||||
|
||||
handler.JobScheduler.UnscheduleTask(portainer.ScheduleID(scheduleID))
|
||||
schedule, err := handler.ScheduleService.Schedule(portainer.ScheduleID(scheduleID))
|
||||
if err == portainer.ErrObjectNotFound {
|
||||
return &httperror.HandlerError{http.StatusNotFound, "Unable to find a schedule with the specified identifier inside the database", err}
|
||||
} else if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find a schedule with the specified identifier inside the database", err}
|
||||
}
|
||||
|
||||
if schedule.JobType == portainer.SnapshotJobType || schedule.JobType == portainer.EndpointSyncJobType {
|
||||
return &httperror.HandlerError{http.StatusBadRequest, "Cannot remove system schedules", errors.New("Cannot remove system schedule")}
|
||||
}
|
||||
|
||||
scheduleFolder := handler.FileService.GetScheduleFolder(portainer.ScheduleID(scheduleID))
|
||||
err = handler.FileService.RemoveDirectory(scheduleFolder)
|
||||
|
|
|
@ -40,14 +40,14 @@ func (handler *Handler) scheduleUpdate(w http.ResponseWriter, r *http.Request) *
|
|||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find a schedule with the specified identifier inside the database", err}
|
||||
}
|
||||
|
||||
updateTaskSchedule := updateSchedule(schedule, &payload)
|
||||
if updateTaskSchedule {
|
||||
taskContext := handler.createTaskExecutionContext(schedule.ID, schedule.Endpoints)
|
||||
schedule.Task.(cron.ScriptTask).SetContext(taskContext)
|
||||
updateJobSchedule := updateSchedule(schedule, &payload)
|
||||
if updateJobSchedule {
|
||||
|
||||
err := handler.JobScheduler.UpdateScheduledTask(schedule.ID, schedule.CronExpression, schedule.Task)
|
||||
jobContext := cron.NewScriptExecutionJobContext(handler.JobService, handler.EndpointService, handler.FileService)
|
||||
jobRunner := cron.NewScriptExecutionJobRunner(schedule.ScriptExecutionJob, jobContext)
|
||||
err := handler.JobScheduler.UpdateSchedule(schedule, jobRunner)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to update task scheduler", err}
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to update job scheduler", err}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,28 +60,26 @@ func (handler *Handler) scheduleUpdate(w http.ResponseWriter, r *http.Request) *
|
|||
}
|
||||
|
||||
func updateSchedule(schedule *portainer.Schedule, payload *scheduleUpdatePayload) bool {
|
||||
updateTaskSchedule := false
|
||||
updateJobSchedule := false
|
||||
|
||||
if payload.Name != nil {
|
||||
schedule.Name = *payload.Name
|
||||
}
|
||||
|
||||
if payload.Endpoints != nil {
|
||||
schedule.Endpoints = payload.Endpoints
|
||||
updateTaskSchedule = true
|
||||
schedule.ScriptExecutionJob.Endpoints = payload.Endpoints
|
||||
updateJobSchedule = true
|
||||
}
|
||||
|
||||
if payload.CronExpression != nil {
|
||||
schedule.CronExpression = *payload.CronExpression
|
||||
updateTaskSchedule = true
|
||||
updateJobSchedule = true
|
||||
}
|
||||
|
||||
if payload.Image != nil {
|
||||
t := schedule.Task.(cron.ScriptTask)
|
||||
t.Image = *payload.Image
|
||||
|
||||
updateTaskSchedule = true
|
||||
schedule.ScriptExecutionJob.Image = *payload.Image
|
||||
updateJobSchedule = true
|
||||
}
|
||||
|
||||
return updateTaskSchedule
|
||||
return updateJobSchedule
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ type Handler struct {
|
|||
LDAPService portainer.LDAPService
|
||||
FileService portainer.FileService
|
||||
JobScheduler portainer.JobScheduler
|
||||
ScheduleService portainer.ScheduleService
|
||||
}
|
||||
|
||||
// NewHandler creates a handler to manage settings operations.
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer"
|
||||
"github.com/portainer/portainer/cron"
|
||||
"github.com/portainer/portainer/filesystem"
|
||||
)
|
||||
|
||||
|
@ -78,11 +77,9 @@ func (handler *Handler) settingsUpdate(w http.ResponseWriter, r *http.Request) *
|
|||
}
|
||||
|
||||
if payload.SnapshotInterval != nil && *payload.SnapshotInterval != settings.SnapshotInterval {
|
||||
settings.SnapshotInterval = *payload.SnapshotInterval
|
||||
|
||||
err := handler.JobScheduler.UpdateScheduledTask(0, "@every "+*payload.SnapshotInterval, cron.NewSnapshotTask(nil))
|
||||
err := handler.updateSnapshotInterval(settings, *payload.SnapshotInterval)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to update task scheduler", err}
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to update snapshot interval", err}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,6 +96,27 @@ func (handler *Handler) settingsUpdate(w http.ResponseWriter, r *http.Request) *
|
|||
return response.JSON(w, settings)
|
||||
}
|
||||
|
||||
func (handler *Handler) updateSnapshotInterval(settings *portainer.Settings, snapshotInterval string) error {
|
||||
settings.SnapshotInterval = snapshotInterval
|
||||
|
||||
schedules, err := handler.ScheduleService.SchedulesByJobType(portainer.SnapshotJobType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(schedules) != 0 {
|
||||
snapshotSchedule := schedules[0]
|
||||
snapshotSchedule.CronExpression = "@every " + snapshotInterval
|
||||
|
||||
err := handler.JobScheduler.UpdateSchedule(&snapshotSchedule, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (handler *Handler) updateTLS(settings *portainer.Settings) *httperror.HandlerError {
|
||||
if (settings.LDAPSettings.TLSConfig.TLS || settings.LDAPSettings.StartTLS) && !settings.LDAPSettings.TLSConfig.TLSSkipVerify {
|
||||
caCertPath, _ := handler.FileService.GetPathForTLSFile(filesystem.LDAPStorePath, portainer.TLSFileCA)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue