Skip to content

Commit f9574cf

Browse files
committed
feat: suspend feature
Signed-off-by: peefy <[email protected]>
1 parent 4287dc7 commit f9574cf

File tree

3 files changed

+94
-5
lines changed

3 files changed

+94
-5
lines changed

api/v1alpha1/kclrun_types.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,15 @@ type ConfigSpec struct {
191191

192192
// KCLRunStatus defines the observed state of KCLRun
193193
type KCLRunStatus struct {
194+
meta.ReconcileRequestStatus `json:",inline"`
195+
196+
// ObservedGeneration is the last reconciled generation.
197+
// +optional
198+
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
199+
200+
// +optional
201+
Conditions []metav1.Condition `json:"conditions,omitempty"`
202+
194203
// The last successfully applied revision.
195204
// Equals the Revision of the applied Artifact from the referenced Source.
196205
// +optional
@@ -208,9 +217,6 @@ type KCLRunStatus struct {
208217
// +optional
209218
LastAttemptedRevisionDigest string `json:"lastAttemptedRevisionDigest,omitempty"`
210219

211-
// +optional
212-
Conditions []metav1.Condition `json:"conditions,omitempty"`
213-
214220
// Inventory contains the list of Kubernetes resource object references that
215221
// have been successfully applied.
216222
// +optional

config/crd/bases/krm.kcl.dev.fluxcd_kclruns.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,16 @@ spec:
384384
LastAttemptedRevisionDigest is the digest of the last reconciliation attempt.
385385
This is only set for OCIRepository sources.
386386
type: string
387+
lastHandledReconcileAt:
388+
description: |-
389+
LastHandledReconcileAt holds the value of the most recent
390+
reconcile request value, so a change of the annotation value
391+
can be detected.
392+
type: string
393+
observedGeneration:
394+
description: ObservedGeneration is the last reconciled generation.
395+
format: int64
396+
type: integer
387397
type: object
388398
type: object
389399
served: true

internal/controller/kclrun_controller.go

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,9 @@ func (r *KCLRunReconciler) SetupWithManager(mgr ctrl.Manager, opts KCLRunReconci
138138
//
139139
// For more details, check Reconcile and its Result here:
140140
// - https://pkg.go.dev/sigs.k8s.io/[email protected]/pkg/reconcile
141-
func (r *KCLRunReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
141+
func (r *KCLRunReconciler) Reconcile(ctx context.Context, req ctrl.Request) (result ctrl.Result, retErr error) {
142142
log := ctrl.LoggerFrom(ctx)
143-
143+
reconcileStart := time.Now()
144144
// Get KCL source object
145145
var obj v1alpha1.KCLRun
146146
if err := r.Get(ctx, req.NamespacedName, &obj); err != nil {
@@ -150,6 +150,51 @@ func (r *KCLRunReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctr
150150
// Initialize the runtime patcher with the current version of the object.
151151
patcher := patch.NewSerialPatcher(&obj, r.Client)
152152

153+
// Finalise the reconciliation and report the results.
154+
defer func() {
155+
// Patch finalizers, status and conditions.
156+
if err := r.finalizeStatus(ctx, &obj, patcher); err != nil {
157+
retErr = kerrors.NewAggregate([]error{retErr, err})
158+
}
159+
160+
// Record Prometheus metrics.
161+
r.Metrics.RecordReadiness(ctx, &obj)
162+
r.Metrics.RecordDuration(ctx, &obj, reconcileStart)
163+
r.Metrics.RecordSuspend(ctx, &obj, obj.Spec.Suspend)
164+
165+
// Log and emit success event.
166+
if conditions.IsReady(&obj) {
167+
msg := fmt.Sprintf("Reconciliation finished in %s, next run in %s",
168+
time.Since(reconcileStart).String(),
169+
obj.Spec.Interval.Duration.String())
170+
log.Info(msg, "revision", obj.Status.LastAttemptedRevision)
171+
r.event(&obj, obj.Status.LastAppliedRevision, eventv1.EventSeverityInfo, msg,
172+
map[string]string{
173+
v1alpha1.GroupVersion.Group + "/" + eventv1.MetaCommitStatusKey: eventv1.MetaCommitStatusUpdateValue,
174+
})
175+
}
176+
}()
177+
178+
// Prune managed resources if the object is under deletion.
179+
if !obj.ObjectMeta.DeletionTimestamp.IsZero() {
180+
return r.finalize(ctx, &obj)
181+
}
182+
183+
// Add finalizer first if it doesn't exist to avoid the race condition
184+
// between init and delete.
185+
// Note: Finalizers in general can only be added when the deletionTimestamp
186+
// is not set.
187+
if !controllerutil.ContainsFinalizer(&obj, v1alpha1.KCLRunFinalizer) {
188+
controllerutil.AddFinalizer(&obj, v1alpha1.KCLRunFinalizer)
189+
return ctrl.Result{Requeue: true}, nil
190+
}
191+
192+
// Skip reconciliation if the object is suspended.
193+
if obj.Spec.Suspend {
194+
log.Info("Reconciliation is suspended for this object")
195+
return ctrl.Result{}, nil
196+
}
197+
153198
source, err := r.getSource(ctx, &obj)
154199
if err != nil {
155200
conditions.MarkFalse(&obj, meta.ReadyCondition, meta.ArtifactFailedReason, "%s", err)
@@ -833,6 +878,34 @@ func (r *KCLRunReconciler) apply(ctx context.Context,
833878
return applyLog != "", resultSet, nil
834879
}
835880

881+
func (r *KCLRunReconciler) finalizeStatus(ctx context.Context,
882+
obj *v1alpha1.KCLRun,
883+
patcher *patch.SerialPatcher) error {
884+
// Set the value of the reconciliation request in status.
885+
if v, ok := meta.ReconcileAnnotationValue(obj.GetAnnotations()); ok {
886+
obj.Status.LastHandledReconcileAt = v
887+
}
888+
889+
// Remove the Reconciling condition and update the observed generation
890+
// if the reconciliation was successful.
891+
if conditions.IsTrue(obj, meta.ReadyCondition) {
892+
conditions.Delete(obj, meta.ReconcilingCondition)
893+
obj.Status.ObservedGeneration = obj.Generation
894+
}
895+
896+
// Set the Reconciling reason to ProgressingWithRetry if the
897+
// reconciliation has failed.
898+
if conditions.IsFalse(obj, meta.ReadyCondition) &&
899+
conditions.Has(obj, meta.ReconcilingCondition) {
900+
rc := conditions.Get(obj, meta.ReconcilingCondition)
901+
rc.Reason = meta.ProgressingWithRetryReason
902+
conditions.Set(obj, rc)
903+
}
904+
905+
// Patch finalizers, status and conditions.
906+
return r.patch(ctx, obj, patcher)
907+
}
908+
836909
func (r *KCLRunReconciler) patch(ctx context.Context,
837910
obj *v1alpha1.KCLRun,
838911
patcher *patch.SerialPatcher) (retErr error) {

0 commit comments

Comments
 (0)