-
Notifications
You must be signed in to change notification settings - Fork 67
/
schedule_controller.go
100 lines (86 loc) · 3.72 KB
/
schedule_controller.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package controllers
import (
"context"
"time"
"github.com/go-logr/logr"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/predicate"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
k8upv1 "github.com/k8up-io/k8up/api/v1"
"github.com/k8up-io/k8up/operator/cfg"
"github.com/k8up-io/k8up/operator/handler"
"github.com/k8up-io/k8up/operator/job"
)
// ScheduleReconciler reconciles a Schedule object
type ScheduleReconciler struct {
client.Client
Log logr.Logger
Scheme *runtime.Scheme
}
// +kubebuilder:rbac:groups=k8up.io,resources=schedules,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=k8up.io,resources=schedules/status;schedules/finalizers,verbs=get;update;patch
// +kubebuilder:rbac:groups=k8up.io,resources=effectiveschedules,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=k8up.io,resources=effectiveschedules/finalizers,verbs=update
// Reconcile is the entrypoint to manage the given resource.
func (r *ScheduleReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
log := r.Log.WithValues("schedule", req.NamespacedName)
schedule := &k8upv1.Schedule{}
err := r.Client.Get(ctx, req.NamespacedName, schedule)
if err != nil {
if errors.IsNotFound(err) {
return reconcile.Result{}, nil
}
return reconcile.Result{}, err
}
effectiveSchedules, err := r.fetchEffectiveSchedules(ctx, schedule)
if err != nil {
requeueAfter := 60 * time.Second
r.Log.Info("could not retrieve list of effective schedules", "error", err.Error(), "retry_after", requeueAfter)
return ctrl.Result{Requeue: true, RequeueAfter: requeueAfter}, err
}
repository := cfg.Config.GetGlobalRepository()
if schedule.Spec.Backend != nil {
repository = schedule.Spec.Backend.String()
}
config := job.NewConfig(ctx, r.Client, log, schedule, r.Scheme, repository)
return ctrl.Result{}, handler.NewScheduleHandler(config, schedule, effectiveSchedules).Handle()
}
// SetupWithManager configures the reconciler.
func (r *ScheduleReconciler) SetupWithManager(mgr ctrl.Manager, l logr.Logger) error {
r.Client = mgr.GetClient()
r.Scheme = mgr.GetScheme()
r.Log = l
return ctrl.NewControllerManagedBy(mgr).
For(&k8upv1.Schedule{}).
WithEventFilter(predicate.GenerationChangedPredicate{}).
Complete(r)
}
// fetchEffectiveSchedules retrieves a list of EffectiveSchedules and filter the one that matches the given schedule.
// Returns an error if the listing failed, but empty map when no matching EffectiveSchedule object was found.
func (r *ScheduleReconciler) fetchEffectiveSchedules(ctx context.Context, schedule *k8upv1.Schedule) (map[k8upv1.JobType]k8upv1.EffectiveSchedule, error) {
list := k8upv1.EffectiveScheduleList{}
err := r.Client.List(ctx, &list, client.InNamespace(cfg.Config.OperatorNamespace))
if err != nil {
return map[k8upv1.JobType]k8upv1.EffectiveSchedule{}, err
}
return filterEffectiveSchedulesForReferencesOfSchedule(list, schedule), nil
}
// filterEffectiveSchedulesForReferencesOfSchedule iterates over the given list of EffectiveSchedules and returns results that reference the given schedule in their spec.
// It returns an empty map if no element matches.
func filterEffectiveSchedulesForReferencesOfSchedule(list k8upv1.EffectiveScheduleList, schedule *k8upv1.Schedule) map[k8upv1.JobType]k8upv1.EffectiveSchedule {
filtered := map[k8upv1.JobType]k8upv1.EffectiveSchedule{}
for _, es := range list.Items {
if es.GetDeletionTimestamp() != nil {
continue
}
for _, jobRef := range es.Spec.ScheduleRefs {
if schedule.IsReferencedBy(jobRef) {
filtered[es.Spec.JobType] = es
}
}
}
return filtered
}