Skip to content

Commit 326314c

Browse files
authored
Cleanup cluster roles and bindings (#2938)
* Fix Signed-off-by: Pavol Loffay <[email protected]> * Fix Signed-off-by: Pavol Loffay <[email protected]> * Fix Signed-off-by: Pavol Loffay <[email protected]> * Fix Signed-off-by: Pavol Loffay <[email protected]> * Add test Signed-off-by: Pavol Loffay <[email protected]> --------- Signed-off-by: Pavol Loffay <[email protected]>
1 parent f8032cc commit 326314c

File tree

6 files changed

+229
-38
lines changed

6 files changed

+229
-38
lines changed

.chloggen/cleanup-roles.yaml

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
2+
change_type: bug_fix
3+
4+
# The name of the component, or a single word describing the area of concern, (e.g. collector, target allocator, auto-instrumentation, opamp, github action)
5+
component: collector
6+
7+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
8+
note: Cleanup ClusterRoles and ClusterRoleBindings created by the operator
9+
10+
# One or more tracking issues related to the change
11+
issues: [2938]
12+
13+
# (Optional) One or more lines of additional information to render under the primary note.
14+
# These lines will be padded with 2 spaces and then inserted directly into the document.
15+
# Use pipe (|) for multiline entries.
16+
subtext: The operator uses finalizer on the collector to run the cleanup

controllers/common.go

+11-5
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,18 @@ func reconcileDesiredObjects(ctx context.Context, kubeClient client.Client, logg
122122
if len(errs) > 0 {
123123
return fmt.Errorf("failed to create objects for %s: %w", owner.GetName(), errors.Join(errs...))
124124
}
125+
// Pruning owned objects in the cluster which are not should not be present after the reconciliation.
126+
err := deleteObjects(ctx, kubeClient, logger, ownedObjects)
127+
if err != nil {
128+
return fmt.Errorf("failed to prune objects for %s: %w", owner.GetName(), err)
129+
}
130+
return nil
131+
}
132+
133+
func deleteObjects(ctx context.Context, kubeClient client.Client, logger logr.Logger, objects map[types.UID]client.Object) error {
125134
// Pruning owned objects in the cluster which are not should not be present after the reconciliation.
126135
pruneErrs := []error{}
127-
for _, obj := range ownedObjects {
136+
for _, obj := range objects {
128137
l := logger.WithValues(
129138
"object_name", obj.GetName(),
130139
"object_kind", obj.GetObjectKind().GroupVersionKind(),
@@ -137,8 +146,5 @@ func reconcileDesiredObjects(ctx context.Context, kubeClient client.Client, logg
137146
pruneErrs = append(pruneErrs, err)
138147
}
139148
}
140-
if len(pruneErrs) > 0 {
141-
return fmt.Errorf("failed to prune objects for %s: %w", owner.GetName(), errors.Join(pruneErrs...))
142-
}
143-
return nil
149+
return errors.Join(pruneErrs...)
144150
}

controllers/opentelemetrycollector_controller.go

+82-4
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import (
3535
"k8s.io/client-go/tools/record"
3636
ctrl "sigs.k8s.io/controller-runtime"
3737
"sigs.k8s.io/controller-runtime/pkg/client"
38+
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
3839

3940
"github.com/open-telemetry/opentelemetry-operator/apis/v1beta1"
4041
"github.com/open-telemetry/opentelemetry-operator/internal/autodetect/openshift"
@@ -127,7 +128,42 @@ func (r *OpenTelemetryCollectorReconciler) findOtelOwnedObjects(ctx context.Cont
127128
for i := range pdbList.Items {
128129
ownedObjects[pdbList.Items[i].GetUID()] = &pdbList.Items[i]
129130
}
131+
if params.Config.CreateRBACPermissions() == rbac.Available {
132+
clusterObjects, err := r.findClusterRoleObjects(ctx, params)
133+
if err != nil {
134+
return nil, err
135+
}
136+
for k, v := range clusterObjects {
137+
ownedObjects[k] = v
138+
}
139+
}
140+
return ownedObjects, nil
141+
}
130142

143+
// The cluster scope objects do not have owner reference.
144+
func (r *OpenTelemetryCollectorReconciler) findClusterRoleObjects(ctx context.Context, params manifests.Params) (map[types.UID]client.Object, error) {
145+
ownedObjects := map[types.UID]client.Object{}
146+
// Remove cluster roles and bindings.
147+
// Users might switch off the RBAC creation feature on the operator which should remove existing RBAC.
148+
listOpsCluster := &client.ListOptions{
149+
LabelSelector: labels.SelectorFromSet(manifestutils.SelectorLabels(params.OtelCol.ObjectMeta, collector.ComponentOpenTelemetryCollector)),
150+
}
151+
clusterroleList := &rbacv1.ClusterRoleList{}
152+
err := r.List(ctx, clusterroleList, listOpsCluster)
153+
if err != nil {
154+
return nil, fmt.Errorf("error listing ClusterRoles: %w", err)
155+
}
156+
for i := range clusterroleList.Items {
157+
ownedObjects[clusterroleList.Items[i].GetUID()] = &clusterroleList.Items[i]
158+
}
159+
clusterrolebindingList := &rbacv1.ClusterRoleBindingList{}
160+
err = r.List(ctx, clusterrolebindingList, listOpsCluster)
161+
if err != nil {
162+
return nil, fmt.Errorf("error listing ClusterRoleBIndings: %w", err)
163+
}
164+
for i := range clusterrolebindingList.Items {
165+
ownedObjects[clusterrolebindingList.Items[i].GetUID()] = &clusterrolebindingList.Items[i]
166+
}
131167
return ownedObjects, nil
132168
}
133169

@@ -193,8 +229,32 @@ func (r *OpenTelemetryCollectorReconciler) Reconcile(ctx context.Context, req ct
193229
// on deleted requests.
194230
return ctrl.Result{}, client.IgnoreNotFound(err)
195231
}
232+
233+
params, err := r.getParams(instance)
234+
if err != nil {
235+
log.Error(err, "Failed to create manifest.Params")
236+
return ctrl.Result{}, err
237+
}
238+
196239
// We have a deletion, short circuit and let the deletion happen
197240
if deletionTimestamp := instance.GetDeletionTimestamp(); deletionTimestamp != nil {
241+
if controllerutil.ContainsFinalizer(&instance, collectorFinalizer) {
242+
// If the finalization logic fails, don't remove the finalizer so
243+
// that we can retry during the next reconciliation.
244+
if err = r.finalizeCollector(ctx, params); err != nil {
245+
return ctrl.Result{}, err
246+
}
247+
248+
// Once all finalizers have been
249+
// removed, the object will be deleted.
250+
if controllerutil.RemoveFinalizer(&instance, collectorFinalizer) {
251+
err = r.Update(ctx, &instance)
252+
if err != nil {
253+
return ctrl.Result{}, err
254+
}
255+
}
256+
}
257+
198258
return ctrl.Result{}, nil
199259
}
200260

@@ -204,10 +264,14 @@ func (r *OpenTelemetryCollectorReconciler) Reconcile(ctx context.Context, req ct
204264
return ctrl.Result{}, nil
205265
}
206266

207-
params, err := r.getParams(instance)
208-
if err != nil {
209-
log.Error(err, "Failed to create manifest.Params")
210-
return ctrl.Result{}, err
267+
// Add finalizer for this CR
268+
if !controllerutil.ContainsFinalizer(&instance, collectorFinalizer) {
269+
if controllerutil.AddFinalizer(&instance, collectorFinalizer) {
270+
err = r.Update(ctx, &instance)
271+
if err != nil {
272+
return ctrl.Result{}, err
273+
}
274+
}
211275
}
212276

213277
desiredObjects, buildErr := BuildCollector(params)
@@ -255,3 +319,17 @@ func (r *OpenTelemetryCollectorReconciler) SetupWithManager(mgr ctrl.Manager) er
255319

256320
return builder.Complete(r)
257321
}
322+
323+
const collectorFinalizer = "opentelemetrycollector.opentelemetry.io/finalizer"
324+
325+
func (r *OpenTelemetryCollectorReconciler) finalizeCollector(ctx context.Context, params manifests.Params) error {
326+
// The cluster scope objects do not have owner reference. They need to be deleted explicitly
327+
if params.Config.CreateRBACPermissions() == rbac.Available {
328+
objects, err := r.findClusterRoleObjects(ctx, params)
329+
if err != nil {
330+
return err
331+
}
332+
return deleteObjects(ctx, r.Client, r.log, objects)
333+
}
334+
return nil
335+
}

0 commit comments

Comments
 (0)