Skip to content

Commit a8fa7f2

Browse files
committed
Resource removal in OBC deletion
Signed-off-by: shirady <57721533+shirady@users.noreply.github.com>
1 parent b5961e8 commit a8fa7f2

File tree

2 files changed

+154
-5
lines changed

2 files changed

+154
-5
lines changed

config/rbac/role.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,16 @@ rules:
259259
- get
260260
- patch
261261
- update
262+
- apiGroups:
263+
- objectbucket.io
264+
resources:
265+
- objectbuckets
266+
verbs:
267+
- delete
268+
- get
269+
- list
270+
- update
271+
- watch
262272
- apiGroups:
263273
- ocs.openshift.io
264274
resources:

internal/controller/obc_controller.go

Lines changed: 144 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/red-hat-storage/ocs-client-operator/api/v1alpha1"
1111
"github.com/red-hat-storage/ocs-client-operator/pkg/utils"
1212
providerClient "github.com/red-hat-storage/ocs-operator/services/provider/api/v4/client"
13+
corev1 "k8s.io/api/core/v1"
1314
storagev1 "k8s.io/api/storage/v1"
1415
"k8s.io/apimachinery/pkg/api/errors"
1516
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -25,8 +26,9 @@ import (
2526
)
2627

2728
const (
28-
operatorObcFinalizer = "ocs-client-operator.ocs.openshift.io/obc"
29+
ObcFinalizer = nbv1.ObjectBucketFinalizer
2930
ObjectBucketClaimStatusPhaseFailed = "Failed"
31+
ObjectBucketClaimStatusPhaseBound = "Bound"
3032
)
3133

3234
// OBCReconciler reconciles a ObjectBucketClaim object
@@ -66,8 +68,11 @@ func (r *OBCReconciler) SetupWithManager(mgr ctrl.Manager) error {
6668

6769
//+kubebuilder:rbac:groups=objectbucket.io,resources=objectbucketclaims,verbs=get;list;watch;update
6870
//+kubebuilder:rbac:groups=objectbucket.io,resources=objectbucketclaims/status,verbs=get;update;patch
71+
//+kubebuilder:rbac:groups=objectbucket.io,resources=objectbuckets,verbs=get;list;watch;update;delete
6972
//+kubebuilder:rbac:groups=ocs.openshift.io,resources=storageclients,verbs=get
7073
//+kubebuilder:rbac:groups=storage.k8s.io,resources=storageclasses,verbs=get
74+
//+kubebuilder:rbac:groups="",resources=configmaps,verbs=get;update
75+
//+kubebuilder:rbac:groups="",resources=secrets,verbs=get;update
7176

7277
func (r *OBCReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
7378
r.ctx = ctx
@@ -97,8 +102,20 @@ func (r *OBCReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R
97102
r.log.Error(err, "failed to notify provider of OBC deletion", "namespaced/name", client.ObjectKeyFromObject(obc))
98103
return reconcile.Result{}, fmt.Errorf("failed to delete the OBC on provider cluster: %v", err)
99104
}
100-
if controllerutil.RemoveFinalizer(obc, operatorObcFinalizer) {
101-
r.log.Info("removing finalizer from OBC.", "namespaced/name", client.ObjectKeyFromObject(obc))
105+
if obc.Status.Phase == ObjectBucketClaimStatusPhaseBound {
106+
r.log.Info("OBC is Bound - release resources", "namespaced/name", client.ObjectKeyFromObject(obc))
107+
ob, cm, secret, errs := r.getResources(obc)
108+
if len(errs) > 0 {
109+
r.log.Error(errs[0], "failed to get related resources for OBC delete")
110+
return reconcile.Result{}, fmt.Errorf("failed to get related resources for OBC delete: %v", errs)
111+
}
112+
if err := r.deleteResources(ob, cm, secret, obc); err != nil {
113+
r.log.Error(err, "failed to delete resources for OBC delete")
114+
return reconcile.Result{}, fmt.Errorf("failed to delete resources for OBC delete: %v", err)
115+
}
116+
}
117+
if controllerutil.RemoveFinalizer(obc, ObcFinalizer) {
118+
r.log.Info("removing finalizer from OBC", "namespaced/name", client.ObjectKeyFromObject(obc))
102119
if err := r.Update(r.ctx, obc); err != nil {
103120
r.log.Info("Failed to remove finalizer from OBC", "namespaced/name", client.ObjectKeyFromObject(obc))
104121
return reconcile.Result{}, fmt.Errorf("failed to remove finalizer from OBC: %v", err)
@@ -108,8 +125,8 @@ func (r *OBCReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R
108125
}
109126

110127
r.log.Info("OBC created", "namespace", obc.Namespace, "name", obc.Name)
111-
if controllerutil.AddFinalizer(obc, operatorObcFinalizer) {
112-
r.log.Info("Finalizer not found for OBC. Adding finalizer.", "namespaced/name", client.ObjectKeyFromObject(obc))
128+
if controllerutil.AddFinalizer(obc, ObcFinalizer) {
129+
r.log.Info("Finalizer not found for OBC. Adding finalizer", "namespaced/name", client.ObjectKeyFromObject(obc))
113130
if err := r.Update(r.ctx, obc); err != nil {
114131
r.log.Info("Failed to add finalizer to OBC", "namespaced/name", client.ObjectKeyFromObject(obc))
115132
return reconcile.Result{}, fmt.Errorf("failed to add finalizer to OBC: %v", err)
@@ -209,3 +226,125 @@ func NewProviderClientForStorageClient(ctx context.Context, sc *v1alpha1.Storage
209226
}
210227
return pc, nil
211228
}
229+
230+
// getResources gets the resources that were created as part of the OBC provisioning.
231+
// The names of the ConfigMap and Secret are always the same as the OBC name.
232+
// The names of the OB's are of the following format: "obc-<namespace_of_OBC>-<OBC_name>"
233+
func (r *OBCReconciler) getResources(obc *nbv1.ObjectBucketClaim) (ob *nbv1.ObjectBucket, cm *corev1.ConfigMap, secret *corev1.Secret, errs []error) {
234+
obName := fmt.Sprintf("obc-%s-%s", obc.Namespace, obc.Name)
235+
ob = &nbv1.ObjectBucket{}
236+
if err := r.Get(r.ctx, types.NamespacedName{Name: obName}, ob); err != nil {
237+
ob = nil
238+
if !errors.IsNotFound(err) {
239+
errs = append(errs, fmt.Errorf("failed to get OB: %w", err))
240+
}
241+
}
242+
cm = &corev1.ConfigMap{}
243+
if err := r.Get(r.ctx, types.NamespacedName{Namespace: obc.Namespace, Name: obc.Name}, cm); err != nil {
244+
cm = nil
245+
if !errors.IsNotFound(err) {
246+
errs = append(errs, fmt.Errorf("failed to get config map: %w", err))
247+
}
248+
}
249+
secret = &corev1.Secret{}
250+
if err := r.Get(r.ctx, types.NamespacedName{Namespace: obc.Namespace, Name: obc.Name}, secret); err != nil {
251+
secret = nil
252+
if !errors.IsNotFound(err) {
253+
errs = append(errs, fmt.Errorf("failed to get secret: %w", err))
254+
}
255+
}
256+
return ob, cm, secret, errs
257+
}
258+
259+
// deleteResources handles the related resurces that were created as part of the OBC provisioning
260+
// Since the secret and configmap's ownerReference is the OBC they will be garbage collected once their finalizers are removed.
261+
// The OB must be explicitly deleted since it is a global resource and cannot have a namespaced ownerReference.
262+
func (r *OBCReconciler) deleteResources(ob *nbv1.ObjectBucket, cm *corev1.ConfigMap, secret *corev1.Secret, obc *nbv1.ObjectBucketClaim) (err error) {
263+
264+
if delErr := r.releaseAndDeleteOB(ob); delErr != nil {
265+
r.log.Error(delErr, "error deleting OB", ob.Name)
266+
err = delErr
267+
}
268+
if delErr := r.releaseObcSecret(secret); delErr != nil {
269+
r.log.Error(delErr, "error releasing secret")
270+
err = delErr
271+
}
272+
if delErr := r.releaseObcConfigMap(cm); delErr != nil {
273+
r.log.Error(delErr, "error releasing configMap")
274+
err = delErr
275+
}
276+
return err
277+
}
278+
279+
// The OB does not have an ownerReference and must be explicitly deleted after its finalizer is removed.
280+
func (r *OBCReconciler) releaseAndDeleteOB(ob *nbv1.ObjectBucket) error {
281+
if ob == nil {
282+
r.log.Info("got nil OB, skipping")
283+
return nil
284+
}
285+
286+
if controllerutil.RemoveFinalizer(ob, nbv1.ObjectBucketFinalizer) {
287+
r.log.Info("removing finalizer from OB", "name", ob.Name)
288+
if err := r.Update(r.ctx, ob); err != nil {
289+
r.log.Info("Failed to remove finalizer from OB", "name", ob.Name)
290+
return fmt.Errorf("failed to remove finalizer from OB: %v", err)
291+
}
292+
}
293+
294+
r.log.Info("deleting OB", "name", ob.Name)
295+
if err := r.Delete(r.ctx, ob); err != nil {
296+
r.log.Info("Failed to delete OB", "name", ob.Name)
297+
return fmt.Errorf("failed to delete OB: %v", err)
298+
}
299+
300+
r.log.Info("OB deleted", "name", ob.Name)
301+
return nil
302+
}
303+
304+
// releaseSecret releases the finalizer from the secret.
305+
// The secret will be garbage collected since its ownerReference refers to the parent OBC.
306+
func (r *OBCReconciler) releaseObcSecret(secret *corev1.Secret) (err error) {
307+
if secret == nil {
308+
r.log.Info("got nil secret, skipping")
309+
return nil
310+
}
311+
if err := r.Get(r.ctx, types.NamespacedName{Namespace: secret.Namespace, Name: secret.Name}, secret); err != nil {
312+
r.log.Info("Failed to get secret", "namespaced/name", client.ObjectKeyFromObject(secret))
313+
return fmt.Errorf("failed to get secret: %v", err)
314+
}
315+
316+
if controllerutil.RemoveFinalizer(secret, nbv1.ObjectBucketFinalizer) {
317+
r.log.Info("removing finalizer from secret", "name", secret.Name)
318+
if err := r.Update(r.ctx, secret); err != nil {
319+
r.log.Info("Failed to remove finalizer from secret", "namespaced/name", client.ObjectKeyFromObject(secret))
320+
return fmt.Errorf("failed to remove finalizer from secret: %v", err)
321+
}
322+
}
323+
324+
r.log.Info("secret finalizer removed", "namespaced/name", client.ObjectKeyFromObject(secret))
325+
return nil
326+
}
327+
328+
// releaseObcConfigMap releases the finalizer from the configmap.
329+
// The configmap will be garbage collected since its ownerReference refers to the parent OBC.
330+
func (r *OBCReconciler) releaseObcConfigMap(cm *corev1.ConfigMap) (err error) {
331+
if cm == nil {
332+
r.log.Info("got nil configmap, skipping")
333+
return nil
334+
}
335+
if err := r.Get(r.ctx, types.NamespacedName{Namespace: cm.Namespace, Name: cm.Name}, cm); err != nil {
336+
r.log.Info("Failed to get configmap", "namespaced/name", client.ObjectKeyFromObject(cm))
337+
return fmt.Errorf("failed to get configmap: %v", err)
338+
}
339+
340+
if controllerutil.RemoveFinalizer(cm, nbv1.ObjectBucketFinalizer) {
341+
r.log.Info("removing finalizer from configmap", "name", cm.Name)
342+
if err := r.Update(r.ctx, cm); err != nil {
343+
r.log.Info("Failed to remove finalizer from configmap", "namespaced/name", client.ObjectKeyFromObject(cm))
344+
return fmt.Errorf("failed to remove finalizer from configmap: %v", err)
345+
}
346+
}
347+
348+
r.log.Info("configmap finalizer removed", "namespaced/name", client.ObjectKeyFromObject(cm))
349+
return nil
350+
}

0 commit comments

Comments
 (0)