diff --git a/controllers/scaledjob_controller.go b/controllers/scaledjob_controller.go index 0f0059bf3ac..2d3e91ffe64 100644 --- a/controllers/scaledjob_controller.go +++ b/controllers/scaledjob_controller.go @@ -62,6 +62,17 @@ func (r *ScaledJobReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { reqLogger.Info("Reconciling ScaledJob") + // Check if the ScaledJob instance is marked to be deleted, which is + // indicated by the deletion timestamp being set. + if scaledJob.GetDeletionTimestamp() != nil { + return ctrl.Result{}, r.finalizeScaledJob(reqLogger, scaledJob) + } + + // ensure finalizer is set on this CR + if err := r.ensureFinalizer(reqLogger, scaledJob); err != nil { + return ctrl.Result{}, err + } + var errMsg string if scaledJob.Spec.JobTargetRef != nil { reqLogger.Info("Detected ScaleType = Job") @@ -132,3 +143,12 @@ func (r *ScaledJobReconciler) requestScaleLoop(logger logr.Logger, scaledJob *ke return r.scaleHandler.HandleScalableObject(scaledJob) } + +// stopScaleLoop stops ScaleLoop handler for the respective ScaledJob +func (r *ScaledJobReconciler) stopScaleLoop(scaledJob *kedav1alpha1.ScaledJob) error { + if err := r.scaleHandler.DeleteScalableObject(scaledJob); err != nil { + return err + } + + return nil +} diff --git a/controllers/scaledjob_finalizer.go b/controllers/scaledjob_finalizer.go new file mode 100644 index 00000000000..82aa68328e3 --- /dev/null +++ b/controllers/scaledjob_finalizer.go @@ -0,0 +1,53 @@ +package controllers + +import ( + "context" + + "github.com/go-logr/logr" + + kedav1alpha1 "github.com/kedacore/keda/api/v1alpha1" + "github.com/kedacore/keda/controllers/util" +) + +const ( + scaledJobFinalizer = "finalizer.keda.sh" +) + +// finalizeScaledJob runs finalization logic on ScaledJob if there's finalizer +func (r *ScaledJobReconciler) finalizeScaledJob(logger logr.Logger, scaledJob *kedav1alpha1.ScaledJob) error { + if util.Contains(scaledJob.GetFinalizers(), scaledJobFinalizer) { + // Run finalization logic for scaledJobFinalizer. If the + // finalization logic fails, don't remove the finalizer so + // that we can retry during the next reconciliation. + if err := r.stopScaleLoop(scaledJob); err != nil { + return err + } + + // Remove scaledJobFinalizer. Once all finalizers have been + // removed, the object will be deleted. + scaledJob.SetFinalizers(util.Remove(scaledJob.GetFinalizers(), scaledJobFinalizer)) + if err := r.Client.Update(context.TODO(), scaledJob); err != nil { + logger.Error(err, "Failed to update ScaledJob after removing a finalizer", "finalizer", scaledJobFinalizer) + return err + } + } + + logger.Info("Successfully finalized ScaledJob") + return nil +} + +// ensureFinalizer check there is finalizer present on the ScaledJob, if not it adds one +func (r *ScaledJobReconciler) ensureFinalizer(logger logr.Logger, scaledJob *kedav1alpha1.ScaledJob) error { + if !util.Contains(scaledJob.GetFinalizers(), scaledJobFinalizer) { + logger.Info("Adding Finalizer for the ScaledJob") + scaledJob.SetFinalizers(append(scaledJob.GetFinalizers(), scaledJobFinalizer)) + + // Update CR + err := r.Client.Update(context.TODO(), scaledJob) + if err != nil { + logger.Error(err, "Failed to update ScaledJob with a finalizer", "finalizer", scaledJobFinalizer) + return err + } + } + return nil +}