mirror of https://github.com/goharbor/harbor.git
152 lines
4.4 KiB
Go
152 lines
4.4 KiB
Go
package systemartifact
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/goharbor/harbor/src/jobservice/job"
|
|
"github.com/goharbor/harbor/src/jobservice/logger"
|
|
"github.com/goharbor/harbor/src/lib/log"
|
|
"github.com/goharbor/harbor/src/lib/orm"
|
|
"github.com/goharbor/harbor/src/lib/q"
|
|
"github.com/goharbor/harbor/src/lib/retry"
|
|
"github.com/goharbor/harbor/src/pkg/scheduler"
|
|
"github.com/goharbor/harbor/src/pkg/systemartifact"
|
|
"github.com/goharbor/harbor/src/pkg/task"
|
|
)
|
|
|
|
const (
|
|
cronTypeDaily = "Daily"
|
|
cronSpec = "0 0 0 * * *"
|
|
)
|
|
|
|
var (
|
|
sched = scheduler.Sched
|
|
)
|
|
|
|
var Ctl = NewController()
|
|
|
|
type Controller interface {
|
|
Start(ctx context.Context, async bool, trigger string) error
|
|
}
|
|
|
|
func NewController() Controller {
|
|
return &controller{
|
|
execMgr: task.ExecMgr,
|
|
taskMgr: task.Mgr,
|
|
systemArtifactMgr: systemartifact.Mgr,
|
|
makeCtx: orm.Context,
|
|
}
|
|
}
|
|
|
|
type controller struct {
|
|
execMgr task.ExecutionManager
|
|
taskMgr task.Manager
|
|
systemArtifactMgr systemartifact.Manager
|
|
makeCtx func() context.Context
|
|
}
|
|
|
|
func (c *controller) Start(ctx context.Context, async bool, trigger string) error {
|
|
execID, err := c.execMgr.Create(ctx, job.SystemArtifactCleanupVendorType, 0, trigger)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// cleanup job would always be scheduled in async mode in production
|
|
// allowing for sync mode execution only for test mode purposes
|
|
// if there are any trigger settings then pass them to the cleanup manager first
|
|
jobParams := job.Parameters{}
|
|
|
|
if !async {
|
|
err := c.createCleanupTask(ctx, jobParams, execID)
|
|
if err != nil {
|
|
log.Errorf("failed to create system artifact clean-up task: %v", err)
|
|
return err
|
|
}
|
|
|
|
logger.Info("Created job for scan data export successfully")
|
|
return nil
|
|
}
|
|
go func(ctx context.Context) {
|
|
err := retry.Retry(func() error {
|
|
_, err := c.execMgr.Get(ctx, execID)
|
|
return err
|
|
})
|
|
if err != nil {
|
|
log.Errorf("failed to get the execution %d for the export data cleanup job", execID)
|
|
return
|
|
}
|
|
err = c.createCleanupTask(ctx, jobParams, execID)
|
|
if err != nil {
|
|
logger.Errorf("Encountered error in scan data artifact cleanup : %v", err)
|
|
return
|
|
}
|
|
}(c.makeCtx())
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c *controller) createCleanupTask(ctx context.Context, jobParams job.Parameters, execID int64) error {
|
|
j := &task.Job{
|
|
Name: job.SystemArtifactCleanupVendorType,
|
|
Metadata: &job.Metadata{
|
|
JobKind: job.KindGeneric,
|
|
},
|
|
Parameters: jobParams,
|
|
}
|
|
|
|
_, err := c.taskMgr.Create(ctx, execID, j)
|
|
|
|
if err != nil {
|
|
logger.Errorf("Unable to create a scan data export job in clean-up mode : %v", err)
|
|
c.markError(ctx, execID, err)
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (c *controller) markError(ctx context.Context, executionID int64, err error) {
|
|
// try to stop the execution first in case that some tasks are already created
|
|
if err := c.execMgr.StopAndWait(ctx, executionID, 10*time.Second); err != nil {
|
|
logger.Errorf("failed to stop the execution %d: %v", executionID, err)
|
|
}
|
|
if err := c.execMgr.MarkError(ctx, executionID, err.Error()); err != nil {
|
|
logger.Errorf("failed to mark error for the execution %d: %v", executionID, err)
|
|
}
|
|
}
|
|
|
|
// ScheduleCleanupTask schedules a system artifact cleanup task
|
|
func ScheduleCleanupTask(ctx context.Context) {
|
|
scheduleSystemArtifactCleanJob(ctx)
|
|
}
|
|
|
|
func scheduleSystemArtifactCleanJob(ctx context.Context) {
|
|
schedule, err := getSystemArtifactCleanupSchedule(ctx)
|
|
if err != nil {
|
|
return
|
|
}
|
|
if schedule != nil {
|
|
logger.Debugf(" Export data cleanup job already scheduled with ID : %v.", schedule.ID)
|
|
return
|
|
}
|
|
scheduleID, err := sched.Schedule(ctx, job.SystemArtifactCleanupVendorType, 0, cronTypeDaily, cronSpec, SystemArtifactCleanupCallback, nil, nil)
|
|
if err != nil {
|
|
log.Errorf("Encountered error when scheduling scan data export cleanup job : %v", err)
|
|
return
|
|
}
|
|
log.Infof("Scheduled scan data export cleanup job with ID : %v", scheduleID)
|
|
}
|
|
|
|
func getSystemArtifactCleanupSchedule(ctx context.Context) (*scheduler.Schedule, error) {
|
|
query := q.New(map[string]interface{}{"vendor_type": job.SystemArtifactCleanupVendorType})
|
|
schedules, err := sched.ListSchedules(ctx, query)
|
|
if err != nil {
|
|
logger.Errorf("Unable to check if export data cleanup job is already scheduled : %v", err)
|
|
return nil, err
|
|
}
|
|
if len(schedules) > 0 {
|
|
logger.Infof("Found export data cleanup job with schedule id : %v", schedules[0].ID)
|
|
return schedules[0], nil
|
|
}
|
|
return nil, nil
|
|
}
|