Skip to content

Commit f2ca062

Browse files
IlyesbdlalaJ12934
authored andcommitted
#150 added schedule and cronjob logic to scheduledscan controller
Signed-off-by: Ilyes Ben Dlala <ilyes.bendlala@iteratec.com>
1 parent 8a4f0ab commit f2ca062

2 files changed

Lines changed: 45 additions & 5 deletions

File tree

operator/apis/execution/v1/scheduledscan_types.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,14 @@ type ScheduledScanSpec struct {
1818

1919
// Interval describes how often the scan should be repeated
2020
// Examples: '12h', '30m'
21+
// +kubebuilder:validation:Optional
2122
Interval metav1.Duration `json:"interval"`
2223

24+
// +kubebuilder:validation:MinLength=0
25+
// +kubebuilder:validation:Optional
26+
// The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron.
27+
Schedule string `json:"schedule"`
28+
2329
// SuccessfulJobsHistoryLimit determines how many past Scans will be kept until the oldest one will be deleted, defaults to 3. When set to 0, Scans will be deleted directly after completion
2430
// +kubebuilder:validation:Optional
2531
// +kubebuilder:validation:Minimum=0

operator/controllers/execution/scheduledscan_controller.go

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"time"
1414

1515
"github.com/go-logr/logr"
16+
"github.com/robfig/cron"
1617
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1718
"k8s.io/apimachinery/pkg/runtime"
1819
"k8s.io/apimachinery/pkg/types"
@@ -100,11 +101,10 @@ func (r *ScheduledScanReconciler) Reconcile(ctx context.Context, req ctrl.Reques
100101
}
101102

102103
// Calculate the next schedule
103-
var nextSchedule time.Time
104-
if scheduledScan.Status.LastScheduleTime != nil {
105-
nextSchedule = scheduledScan.Status.LastScheduleTime.Add(scheduledScan.Spec.Interval.Duration)
106-
} else {
107-
nextSchedule = time.Now().Add(-1 * time.Second)
104+
nextSchedule, err := getNextSchedule(scheduledScan, time.Now())
105+
if err != nil {
106+
log.Error(err, "Unable to calculate next schedule")
107+
return ctrl.Result{}, err
108108
}
109109

110110
// check if it is time to start the next Scan
@@ -162,6 +162,40 @@ func (r *ScheduledScanReconciler) Reconcile(ctx context.Context, req ctrl.Reques
162162
return ctrl.Result{RequeueAfter: nextSchedule.Sub(time.Now())}, nil
163163
}
164164

165+
func getNextSchedule(scheduledScan executionv1.ScheduledScan, now time.Time) (next time.Time, err error) {
166+
// check if the Cron schedule is set
167+
if scheduledScan.Spec.Schedule != "" {
168+
sched, err := cron.ParseStandard(scheduledScan.Spec.Schedule)
169+
if err != nil {
170+
return time.Time{}, fmt.Errorf("Unparseable schedule %q: %v", scheduledScan.Spec.Schedule, err)
171+
}
172+
173+
// for optimization purposes, cheat a bit and start from our last observed run time
174+
// we could reconstitute this here, but there's not much point, since we've
175+
// just updated it.
176+
var earliestTime time.Time
177+
if scheduledScan.Status.LastScheduleTime != nil {
178+
earliestTime = scheduledScan.Status.LastScheduleTime.Time
179+
} else {
180+
earliestTime = scheduledScan.ObjectMeta.CreationTimestamp.Time
181+
}
182+
if earliestTime.After(now) {
183+
tmp := sched.Next(now)
184+
return tmp, nil
185+
}
186+
}
187+
if scheduledScan.Spec.Interval.Duration > 0 {
188+
var nextSchedule time.Time
189+
if scheduledScan.Status.LastScheduleTime != nil {
190+
nextSchedule = scheduledScan.Status.LastScheduleTime.Add(scheduledScan.Spec.Interval.Duration)
191+
} else {
192+
nextSchedule = time.Now().Add(-1 * time.Second)
193+
}
194+
return nextSchedule, nil
195+
}
196+
return time.Time{}, fmt.Errorf("No schedule or interval found")
197+
}
198+
165199
// Copy over securecodebox.io annotations from the scheduledScan to the created scan
166200
func getAnnotationsForScan(scheduledScan executionv1.ScheduledScan) map[string]string {
167201
annotations := map[string]string{}

0 commit comments

Comments
 (0)