@@ -2,15 +2,20 @@ package operators
2
2
3
3
import (
4
4
"context"
5
+ "fmt"
5
6
"reflect"
6
7
7
8
"github.com/go-logr/logr"
9
+ admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
10
+ rbacv1 "k8s.io/api/rbac/v1"
8
11
apierrors "k8s.io/apimachinery/pkg/api/errors"
9
12
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
10
13
"k8s.io/apimachinery/pkg/runtime"
14
+ utilerrors "k8s.io/apimachinery/pkg/util/errors"
11
15
ctrl "sigs.k8s.io/controller-runtime"
12
16
"sigs.k8s.io/controller-runtime/pkg/builder"
13
17
"sigs.k8s.io/controller-runtime/pkg/client"
18
+ "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
14
19
"sigs.k8s.io/controller-runtime/pkg/event"
15
20
"sigs.k8s.io/controller-runtime/pkg/handler"
16
21
"sigs.k8s.io/controller-runtime/pkg/predicate"
@@ -95,6 +100,10 @@ func (r *OperatorConditionGeneratorReconciler) Reconcile(ctx context.Context, re
95
100
return ctrl.Result {}, client .IgnoreNotFound (err )
96
101
}
97
102
103
+ if err , ok := r .processFinalizer (ctx , in ); ! ok {
104
+ return ctrl.Result {}, err
105
+ }
106
+
98
107
operatorCondition := & operatorsv2.OperatorCondition {
99
108
ObjectMeta : metav1.ObjectMeta {
100
109
// For now, only generate an OperatorCondition with the same name as the csv.
@@ -170,3 +179,100 @@ func (r *OperatorConditionGeneratorReconciler) ensureOperatorCondition(operatorC
170
179
existingOperatorCondition .Spec .ServiceAccounts = operatorCondition .Spec .ServiceAccounts
171
180
return r .Client .Update (context .TODO (), existingOperatorCondition )
172
181
}
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