Skip to content

Commit a5d727a

Browse files
committed
Add finalizer for CSV cleanup
Cleanup CRB/CR/MWC/VWC via finalizer. Signed-off-by: Todd Short <[email protected]>
1 parent 4d6d11b commit a5d727a

File tree

1 file changed

+106
-0
lines changed

1 file changed

+106
-0
lines changed

Diff for: pkg/controller/operators/operatorconditiongenerator_controller.go

+106
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,20 @@ package operators
22

33
import (
44
"context"
5+
"fmt"
56
"reflect"
67

78
"github.com/go-logr/logr"
9+
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
10+
rbacv1 "k8s.io/api/rbac/v1"
811
apierrors "k8s.io/apimachinery/pkg/api/errors"
912
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1013
"k8s.io/apimachinery/pkg/runtime"
14+
utilerrors "k8s.io/apimachinery/pkg/util/errors"
1115
ctrl "sigs.k8s.io/controller-runtime"
1216
"sigs.k8s.io/controller-runtime/pkg/builder"
1317
"sigs.k8s.io/controller-runtime/pkg/client"
18+
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
1419
"sigs.k8s.io/controller-runtime/pkg/event"
1520
"sigs.k8s.io/controller-runtime/pkg/handler"
1621
"sigs.k8s.io/controller-runtime/pkg/predicate"
@@ -95,6 +100,10 @@ func (r *OperatorConditionGeneratorReconciler) Reconcile(ctx context.Context, re
95100
return ctrl.Result{}, client.IgnoreNotFound(err)
96101
}
97102

103+
if err, ok := r.processFinalizer(ctx, in); !ok {
104+
return ctrl.Result{}, err
105+
}
106+
98107
operatorCondition := &operatorsv2.OperatorCondition{
99108
ObjectMeta: metav1.ObjectMeta{
100109
// For now, only generate an OperatorCondition with the same name as the csv.
@@ -170,3 +179,100 @@ func (r *OperatorConditionGeneratorReconciler) ensureOperatorCondition(operatorC
170179
existingOperatorCondition.Spec.ServiceAccounts = operatorCondition.Spec.ServiceAccounts
171180
return r.Client.Update(context.TODO(), existingOperatorCondition)
172181
}
182+
183+
// Return values, err, ok; ok == true: continue Reconcile, ok == false: exit Reconcile
184+
func (r *OperatorConditionGeneratorReconciler) processFinalizer(ctx context.Context, csv *operatorsv1alpha1.ClusterServiceVersion) (error, bool) {
185+
myFinalizerName := "operators.coreos.com/csv-cleanup"
186+
log := r.log.WithValues("name", csv.GetName()).WithValues("namespace", csv.GetNamespace())
187+
188+
if csv.ObjectMeta.DeletionTimestamp.IsZero() {
189+
// CSV is not being deleted, add finalizer if not present
190+
if !controllerutil.ContainsFinalizer(csv, myFinalizerName) {
191+
patch := client.MergeFrom(csv.DeepCopy())
192+
controllerutil.AddFinalizer(csv, myFinalizerName)
193+
if err := r.Client.Patch(ctx, csv, patch); err != nil {
194+
log.Error(err, "Adding finalizer")
195+
return err, false
196+
}
197+
}
198+
return nil, true
199+
}
200+
201+
if !controllerutil.ContainsFinalizer(csv, myFinalizerName) {
202+
// Finalizer has been removed; stop reconciliation as the CSV is being deleted
203+
return nil, false
204+
}
205+
206+
// CSV is being deleted and the finalizer still present; do any clean up
207+
ownerSelector := ownerutil.CSVOwnerSelector(csv)
208+
listOptions := client.ListOptions{
209+
LabelSelector: ownerSelector,
210+
}
211+
deleteOptions := client.DeleteAllOfOptions{
212+
ListOptions: listOptions,
213+
}
214+
// Look for resources owned by this CSV, and delete them.
215+
log.WithValues("selector", ownerSelector).Info("Cleaning up resources after CSV deletion")
216+
var errs []error
217+
218+
err := r.Client.DeleteAllOf(ctx, &rbacv1.ClusterRoleBinding{}, &deleteOptions)
219+
if client.IgnoreNotFound(err) != nil {
220+
log.Error(err, "Deleting ClusterRoleBindings on CSV delete")
221+
errs = append(errs, err)
222+
}
223+
224+
err = r.Client.DeleteAllOf(ctx, &rbacv1.ClusterRole{}, &deleteOptions)
225+
if client.IgnoreNotFound(err) != nil {
226+
log.Error(err, "Deleting ClusterRoles on CSV delete")
227+
errs = append(errs, err)
228+
}
229+
230+
err = r.Client.DeleteAllOf(ctx, &admissionregistrationv1.MutatingWebhookConfiguration{}, &deleteOptions)
231+
if client.IgnoreNotFound(err) != nil {
232+
log.Error(err, "Deleting MutatingWebhookConfigurations on CSV delete")
233+
errs = append(errs, err)
234+
}
235+
236+
err = r.Client.DeleteAllOf(ctx, &admissionregistrationv1.ValidatingWebhookConfiguration{}, &deleteOptions)
237+
if client.IgnoreNotFound(err) != nil {
238+
log.Error(err, "Deleting ValidatingWebhookConfigurations on CSV delete")
239+
errs = append(errs, err)
240+
}
241+
242+
// Make sure things are deleted
243+
crbList := &rbacv1.ClusterRoleBindingList{}
244+
if _ = r.Client.List(ctx, crbList, &listOptions); len(crbList.Items) != 0 {
245+
errs = append(errs, fmt.Errorf("Waiting for ClusterRoleBindings to delete"))
246+
}
247+
248+
crList := &rbacv1.ClusterRoleList{}
249+
if _ = r.Client.List(ctx, crList, &listOptions); len(crList.Items) != 0 {
250+
errs = append(errs, fmt.Errorf("Waiting for ClusterRoles to delete"))
251+
}
252+
253+
mwcList := &admissionregistrationv1.MutatingWebhookConfigurationList{}
254+
if _ = r.Client.List(ctx, mwcList, &listOptions); len(mwcList.Items) != 0 {
255+
errs = append(errs, fmt.Errorf("Waiting for MutatingWebhookConfigurations to delete"))
256+
}
257+
258+
vwcList := &admissionregistrationv1.ValidatingWebhookConfigurationList{}
259+
if _ = r.Client.List(ctx, vwcList, &listOptions); len(vwcList.Items) != 0 {
260+
errs = append(errs, fmt.Errorf("Waiting for ValidatingWebhookConfigurations to delete"))
261+
}
262+
263+
// Return any errors
264+
if err := utilerrors.NewAggregate(errs); err != nil {
265+
return err, false
266+
}
267+
268+
// If no errors, remove our finalizer from the CSV and update
269+
patch := client.MergeFrom(csv.DeepCopy())
270+
controllerutil.RemoveFinalizer(csv, myFinalizerName)
271+
if err := r.Client.Patch(ctx, csv, patch); err != nil {
272+
log.Error(err, "Removing finalizer")
273+
return err, false
274+
}
275+
276+
// Stop reconciliation as the csv is being deleted
277+
return nil, false
278+
}

0 commit comments

Comments
 (0)