@@ -36,6 +36,7 @@ import (
3636 ctrl "sigs.k8s.io/controller-runtime"
3737 "sigs.k8s.io/controller-runtime/pkg/client"
3838 "sigs.k8s.io/controller-runtime/pkg/controller"
39+ "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
3940 logf "sigs.k8s.io/controller-runtime/pkg/log"
4041 "sigs.k8s.io/controller-runtime/pkg/predicate"
4142
@@ -44,6 +45,8 @@ import (
4445 apierrors "k8s.io/apimachinery/pkg/api/errors"
4546)
4647
48+ const functionFinalizer = "function.functions.dev/finalizer"
49+
4750// FunctionReconciler reconciles a Function object
4851type FunctionReconciler struct {
4952 client.Client
@@ -82,8 +85,6 @@ func (r *FunctionReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
8285 return ctrl.Result {}, err
8386 }
8487
85- logger .Info ("Reconciling Function" , "function" , req .NamespacedName )
86-
8788 // checkout repo
8889 branchReference := "main"
8990 if function .Spec .Source .Reference != "" {
@@ -101,6 +102,45 @@ func (r *FunctionReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
101102 return ctrl.Result {}, fmt .Errorf ("failed to get function metadata: %w" , err )
102103 }
103104
105+ if ! controllerutil .ContainsFinalizer (function , functionFinalizer ) {
106+ logger .Info ("Adding Finalizer for Function" )
107+ if ok := controllerutil .AddFinalizer (function , functionFinalizer ); ! ok {
108+ return ctrl.Result {}, fmt .Errorf ("failed to add finalizer for function: %w" , err )
109+ }
110+
111+ if err = r .Update (ctx , function ); err != nil {
112+ return ctrl.Result {}, fmt .Errorf ("failed to add finalizer for function: %w" , err )
113+ }
114+ }
115+
116+ // Check if the Function instance is marked to be deleted, which is
117+ // indicated by the deletion timestamp being set.
118+ if function .GetDeletionTimestamp () != nil {
119+ if controllerutil .ContainsFinalizer (function , functionFinalizer ) {
120+ logger .Info ("Performing Finalizer Operations for Function before delete CR" )
121+
122+ // TODO: maybe set some status conditions marking the function as degraded
123+
124+ // Perform all operations required before removing the finalizer and allow
125+ // the Kubernetes API to remove the custom resource.
126+ if err := r .Finalize (ctx , metadata .Name , function .Namespace ); err != nil {
127+ return ctrl.Result {}, fmt .Errorf ("failed to perform finalizer for function: %w" , err )
128+ }
129+
130+ logger .Info ("Removing Finalizer for Function after successfully perform the operations" )
131+ if ok := controllerutil .RemoveFinalizer (function , functionFinalizer ); ! ok {
132+ return ctrl.Result {}, fmt .Errorf ("failed to remove finalizer for function" )
133+ }
134+
135+ if err := r .Update (ctx , function ); err != nil {
136+ return ctrl.Result {}, fmt .Errorf ("failed to remove finalizer for function: %w" , err )
137+ }
138+ }
139+ return ctrl.Result {}, nil
140+ }
141+
142+ logger .Info ("Reconciling Function" , "function" , req .NamespacedName )
143+
104144 // deploy if needed
105145 deployed , err := r .isDeployed (ctx , metadata .Name , function .Namespace )
106146 if err != nil {
@@ -336,3 +376,12 @@ func (r *FunctionReconciler) isMiddlewareLatest(ctx context.Context, metadata fu
336376
337377 return latestMiddleware == functionMiddleware , nil
338378}
379+
380+ func (r * FunctionReconciler ) Finalize (ctx context.Context , name , namespace string ) error {
381+ err := r .FuncCliManager .Delete (ctx , name , namespace )
382+ if err != nil {
383+ return fmt .Errorf ("failed to finalize function: %w" , err )
384+ }
385+
386+ return nil
387+ }
0 commit comments