@@ -17,7 +17,6 @@ package controllers
17
17
18
18
import (
19
19
"context"
20
- "fmt"
21
20
"sort"
22
21
23
22
"github.com/go-logr/logr"
@@ -30,12 +29,14 @@ import (
30
29
policyV1 "k8s.io/api/policy/v1"
31
30
rbacv1 "k8s.io/api/rbac/v1"
32
31
apierrors "k8s.io/apimachinery/pkg/api/errors"
32
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
33
33
"k8s.io/apimachinery/pkg/labels"
34
34
"k8s.io/apimachinery/pkg/runtime"
35
35
"k8s.io/apimachinery/pkg/types"
36
36
"k8s.io/client-go/tools/record"
37
37
ctrl "sigs.k8s.io/controller-runtime"
38
38
"sigs.k8s.io/controller-runtime/pkg/client"
39
+ "sigs.k8s.io/controller-runtime/pkg/cluster"
39
40
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
40
41
41
42
"github.com/open-telemetry/opentelemetry-operator/apis/v1alpha1"
@@ -53,6 +54,8 @@ import (
53
54
"github.com/open-telemetry/opentelemetry-operator/pkg/featuregate"
54
55
)
55
56
57
+ const resourceOwnerKey = ".metadata.owner"
58
+
56
59
var (
57
60
ownedClusterObjectTypes = []client.Object {
58
61
& rbacv1.ClusterRole {},
@@ -82,51 +85,42 @@ type Params struct {
82
85
83
86
func (r * OpenTelemetryCollectorReconciler ) findOtelOwnedObjects (ctx context.Context , params manifests.Params ) (map [types.UID ]client.Object , error ) {
84
87
ownedObjects := map [types.UID ]client.Object {}
85
- ownedObjectTypes := []client.Object {
86
- & autoscalingv2.HorizontalPodAutoscaler {},
87
- & networkingv1.Ingress {},
88
- & policyV1.PodDisruptionBudget {},
89
- }
90
- listOps := & client.ListOptions {
91
- Namespace : params .OtelCol .Namespace ,
92
- LabelSelector : labels .SelectorFromSet (manifestutils .SelectorLabels (params .OtelCol .ObjectMeta , collector .ComponentOpenTelemetryCollector )),
93
- }
94
- if featuregate .PrometheusOperatorIsAvailable .IsEnabled () && r .config .PrometheusCRAvailability () == prometheus .Available {
95
- ownedObjectTypes = append (ownedObjectTypes ,
96
- & monitoringv1.ServiceMonitor {},
97
- & monitoringv1.PodMonitor {},
98
- )
99
- }
100
- if params .Config .OpenShiftRoutesAvailability () == openshift .RoutesAvailable {
101
- ownedObjectTypes = append (ownedObjectTypes , & routev1.Route {})
88
+ collectorConfigMaps := []* corev1.ConfigMap {}
89
+ ownedObjectTypes := r .GetOwnedResourceTypes ()
90
+ listOpts := []client.ListOption {
91
+ client .InNamespace (params .OtelCol .Namespace ),
92
+ client.MatchingFields {resourceOwnerKey : params .OtelCol .Name },
102
93
}
103
94
for _ , objectType := range ownedObjectTypes {
104
- objs , err := getList (ctx , r , objectType , listOps )
95
+ objs , err := getList (ctx , r , objectType , listOpts ... )
105
96
if err != nil {
106
97
return nil , err
107
98
}
108
99
for uid , object := range objs {
109
100
ownedObjects [uid ] = object
110
101
}
111
- }
112
- if params .Config .CreateRBACPermissions () == rbac .Available {
113
- objs , err := r .findClusterRoleObjects (ctx , params )
114
- if err != nil {
115
- return nil , err
116
- }
117
- for uid , object := range objs {
118
- ownedObjects [uid ] = object
102
+ // save Collector ConfigMaps into a separate slice, we need to do additional filtering on them
103
+ switch objectType .(type ) {
104
+ case * corev1.ConfigMap :
105
+ for _ , object := range objs {
106
+ if ! featuregate .CollectorUsesTargetAllocatorCR .IsEnabled () && object .GetLabels ()["app.kubernetes.io/component" ] != "opentelemetry-collector" {
107
+ // we only apply this to collector ConfigMaps
108
+ continue
109
+ }
110
+ configMap := object .(* corev1.ConfigMap )
111
+ collectorConfigMaps = append (collectorConfigMaps , configMap )
112
+ }
113
+ default :
119
114
}
120
115
}
121
116
122
- configMapList := & corev1.ConfigMapList {}
123
- err := r .List (ctx , configMapList , listOps )
124
- if err != nil {
125
- return nil , fmt .Errorf ("error listing ConfigMaps: %w" , err )
126
- }
127
- ownedConfigMaps := r .getConfigMapsToRemove (params .OtelCol .Spec .ConfigVersions , configMapList )
128
- for i := range ownedConfigMaps {
129
- ownedObjects [ownedConfigMaps [i ].GetUID ()] = & ownedConfigMaps [i ]
117
+ // at this point we don't know if the most recent ConfigMap will still be the most recent after reconciliation, or
118
+ // if a new one will be created. We keep one additional ConfigMap to account for this. The next reconciliation that
119
+ // doesn't spawn a new ConfigMap will delete the extra one we kept here.
120
+ configVersionsToKeep := max (params .OtelCol .Spec .ConfigVersions , 1 ) + 1
121
+ configMapsToKeep := getCollectorConfigMapsToKeep (configVersionsToKeep , collectorConfigMaps )
122
+ for _ , configMap := range configMapsToKeep {
123
+ delete (ownedObjects , configMap .GetUID ())
130
124
}
131
125
132
126
return ownedObjects , nil
@@ -138,7 +132,8 @@ func (r *OpenTelemetryCollectorReconciler) findClusterRoleObjects(ctx context.Co
138
132
// Remove cluster roles and bindings.
139
133
// Users might switch off the RBAC creation feature on the operator which should remove existing RBAC.
140
134
listOpsCluster := & client.ListOptions {
141
- LabelSelector : labels .SelectorFromSet (manifestutils .SelectorLabels (params .OtelCol .ObjectMeta , collector .ComponentOpenTelemetryCollector )),
135
+ LabelSelector : labels .SelectorFromSet (
136
+ manifestutils .SelectorLabels (params .OtelCol .ObjectMeta , collector .ComponentOpenTelemetryCollector )),
142
137
}
143
138
for _ , objectType := range ownedClusterObjectTypes {
144
139
objs , err := getList (ctx , r , objectType , listOpsCluster )
@@ -152,25 +147,21 @@ func (r *OpenTelemetryCollectorReconciler) findClusterRoleObjects(ctx context.Co
152
147
return ownedObjects , nil
153
148
}
154
149
155
- // getConfigMapsToRemove returns a list of ConfigMaps to remove based on the number of ConfigMaps to keep.
156
- // It keeps the newest ConfigMap, the `configVersionsToKeep` next newest ConfigMaps, and returns the remainder.
157
- func (r * OpenTelemetryCollectorReconciler ) getConfigMapsToRemove (configVersionsToKeep int , configMapList * corev1.ConfigMapList ) []corev1.ConfigMap {
150
+ // getCollectorConfigMapsToKeep gets ConfigMaps the controller would normally delete, but which we want to keep around
151
+ // anyway. This is part of a feature to keep around previous ConfigMap versions to make rollbacks easier.
152
+ // Fundamentally, this just sorts by time created and picks configVersionsToKeep latest ones.
153
+ func getCollectorConfigMapsToKeep (configVersionsToKeep int , configMaps []* corev1.ConfigMap ) []* corev1.ConfigMap {
158
154
configVersionsToKeep = max (1 , configVersionsToKeep )
159
- ownedConfigMaps := []corev1.ConfigMap {}
160
- sort .Slice (configMapList .Items , func (i , j int ) bool {
161
- iTime := configMapList .Items [i ].GetCreationTimestamp ().Time
162
- jTime := configMapList .Items [j ].GetCreationTimestamp ().Time
155
+ sort .Slice (configMaps , func (i , j int ) bool {
156
+ iTime := configMaps [i ].GetCreationTimestamp ().Time
157
+ jTime := configMaps [j ].GetCreationTimestamp ().Time
163
158
// sort the ConfigMaps newest to oldest
164
159
return iTime .After (jTime )
165
160
})
166
161
167
- for i := range configMapList .Items {
168
- if i > configVersionsToKeep {
169
- ownedConfigMaps = append (ownedConfigMaps , configMapList .Items [i ])
170
- }
171
- }
172
-
173
- return ownedConfigMaps
162
+ configMapsToKeep := min (configVersionsToKeep , len (configMaps ))
163
+ // return the first configVersionsToKeep items
164
+ return configMaps [:configMapsToKeep ]
174
165
}
175
166
176
167
func (r * OpenTelemetryCollectorReconciler ) GetParams (ctx context.Context , instance v1beta1.OpenTelemetryCollector ) (manifests.Params , error ) {
@@ -310,32 +301,74 @@ func (r *OpenTelemetryCollectorReconciler) Reconcile(ctx context.Context, req ct
310
301
311
302
// SetupWithManager tells the manager what our controller is interested in.
312
303
func (r * OpenTelemetryCollectorReconciler ) SetupWithManager (mgr ctrl.Manager ) error {
304
+ err := r .SetupCaches (mgr )
305
+ if err != nil {
306
+ return err
307
+ }
308
+
309
+ ownedResources := r .GetOwnedResourceTypes ()
313
310
builder := ctrl .NewControllerManagedBy (mgr ).
314
- For (& v1beta1.OpenTelemetryCollector {}).
315
- Owns (& corev1.ConfigMap {}).
316
- Owns (& corev1.ServiceAccount {}).
317
- Owns (& corev1.Service {}).
318
- Owns (& appsv1.Deployment {}).
319
- Owns (& appsv1.DaemonSet {}).
320
- Owns (& appsv1.StatefulSet {}).
321
- Owns (& networkingv1.Ingress {}).
322
- Owns (& autoscalingv2.HorizontalPodAutoscaler {}).
323
- Owns (& policyV1.PodDisruptionBudget {})
311
+ For (& v1beta1.OpenTelemetryCollector {})
312
+
313
+ for _ , resource := range ownedResources {
314
+ builder .Owns (resource )
315
+ }
316
+
317
+ return builder .Complete (r )
318
+ }
319
+
320
+ // SetupCaches sets up caching and indexing for our controller.
321
+ func (r * OpenTelemetryCollectorReconciler ) SetupCaches (cluster cluster.Cluster ) error {
322
+ ownedResources := r .GetOwnedResourceTypes ()
323
+ for _ , resource := range ownedResources {
324
+ if err := cluster .GetCache ().IndexField (context .Background (), resource , resourceOwnerKey , func (rawObj client.Object ) []string {
325
+ owner := metav1 .GetControllerOf (rawObj )
326
+ if owner == nil {
327
+ return nil
328
+ }
329
+ // make sure it's an OpenTelemetryCollector
330
+ if owner .Kind != "OpenTelemetryCollector" {
331
+ return nil
332
+ }
333
+
334
+ return []string {owner .Name }
335
+ }); err != nil {
336
+ return err
337
+ }
338
+ }
339
+ return nil
340
+ }
341
+
342
+ // GetOwnedResourceTypes returns all the resource types the controller can own. Even though this method returns an array
343
+ // of client.Object, these are (empty) example structs rather than actual resources.
344
+ func (r * OpenTelemetryCollectorReconciler ) GetOwnedResourceTypes () []client.Object {
345
+ ownedResources := []client.Object {
346
+ & corev1.ConfigMap {},
347
+ & corev1.ServiceAccount {},
348
+ & corev1.Service {},
349
+ & appsv1.Deployment {},
350
+ & appsv1.DaemonSet {},
351
+ & appsv1.StatefulSet {},
352
+ & networkingv1.Ingress {},
353
+ & autoscalingv2.HorizontalPodAutoscaler {},
354
+ & policyV1.PodDisruptionBudget {},
355
+ }
324
356
325
357
if r .config .CreateRBACPermissions () == rbac .Available {
326
- builder . Owns ( & rbacv1.ClusterRoleBinding {})
327
- builder . Owns ( & rbacv1.ClusterRole {})
358
+ ownedResources = append ( ownedResources , & rbacv1.ClusterRole {})
359
+ ownedResources = append ( ownedResources , & rbacv1.ClusterRoleBinding {})
328
360
}
329
361
330
362
if featuregate .PrometheusOperatorIsAvailable .IsEnabled () && r .config .PrometheusCRAvailability () == prometheus .Available {
331
- builder . Owns ( & monitoringv1.ServiceMonitor {})
332
- builder . Owns ( & monitoringv1.PodMonitor {})
363
+ ownedResources = append ( ownedResources , & monitoringv1.PodMonitor {})
364
+ ownedResources = append ( ownedResources , & monitoringv1.ServiceMonitor {})
333
365
}
366
+
334
367
if r .config .OpenShiftRoutesAvailability () == openshift .RoutesAvailable {
335
- builder . Owns ( & routev1.Route {})
368
+ ownedResources = append ( ownedResources , & routev1.Route {})
336
369
}
337
370
338
- return builder . Complete ( r )
371
+ return ownedResources
339
372
}
340
373
341
374
const collectorFinalizer = "opentelemetrycollector.opentelemetry.io/finalizer"
0 commit comments