func (r *CronJobReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
	log := r.Log.WithValues("cronjob", req.NamespacedName)
	var cronJob *batchv1.CronJob
	if err := r.Get(ctx, req.NamespacedName, cronJob); err != nil {
		log.Error(err, "unable to fetch CronJob")
		return ctrl.Result{}, client.IgnoreNotFound(err)
	}
	myFinalizerName := "batch.tutorial.kubebuilder.io/finalizer"
	if cronJob.ObjectMeta.DeletionTimestamp.IsZero() {
		if !containsString(cronJob.GetFinalizers(), myFinalizerName) {
			controllerutil.AddFinalizer(cronJob, myFinalizerName)
			if err := r.Update(ctx, cronJob); err != nil {
				return ctrl.Result{}, err
			}
		}
	} else {
		if containsString(cronJob.GetFinalizers(), myFinalizerName) {
			if err := r.deleteExternalResources(cronJob); err != nil {
				return ctrl.Result{}, err
			}
			controllerutil.RemoveFinalizer(cronJob, myFinalizerName)
			if err := r.Update(ctx, cronJob); err != nil {
				return ctrl.Result{}, err
			}
		}
		return ctrl.Result{}, nil
	}
	return ctrl.Result{}, nil
}
+kubebuilder:docs-gen:collapse=Imports
/*
By default, kubebuilder will include the RBAC rules necessary to update finalizers for CronJobs.

+kubebuilder:rbac:groups=batch.tutorial.kubebuilder.io,resources=cronjobs,verbs=get;list;watch;create;update;patch;delete
+kubebuilder:rbac:groups=batch.tutorial.kubebuilder.io,resources=cronjobs/status,verbs=get;update;patch
+kubebuilder:rbac:groups=batch.tutorial.kubebuilder.io,resources=cronjobs/finalizers,verbs=update
/*
The code snippet below shows skeleton code for implementing a finalizer.
package controllers
import (
	"context"
	"k8s.io/kubernetes/pkg/apis/batch"
	ctrl "sigs.k8s.io/controller-runtime"
	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
	batchv1 "tutorial.kubebuilder.io/project/api/v1"
)