Skip to content

Commit 10701c7

Browse files
committed
feat(collectors): reconcile collectors if extra config map is updated
Also, refactor collector mangement related structs.
1 parent 41dee87 commit 10701c7

32 files changed

+2022
-1486
lines changed

go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ require (
4747
github.com/antchfx/xpath v1.3.4 // indirect
4848
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
4949
github.com/beorn7/perks v1.0.1 // indirect
50+
github.com/bep/debounce v1.2.1 // indirect
5051
github.com/blang/semver/v4 v4.0.0 // indirect
5152
github.com/brunoga/deep v1.2.5 // indirect
5253
github.com/cenkalti/backoff/v5 v5.0.2 // indirect
@@ -57,7 +58,7 @@ require (
5758
github.com/emicklei/go-restful/v3 v3.12.1 // indirect
5859
github.com/evanphx/json-patch v5.9.0+incompatible // indirect
5960
github.com/evanphx/json-patch/v5 v5.9.11 // indirect
60-
github.com/fsnotify/fsnotify v1.8.0 // indirect
61+
github.com/fsnotify/fsnotify v1.9.0 // indirect
6162
github.com/fxamacker/cbor/v2 v2.8.0 // indirect
6263
github.com/go-jose/go-jose/v4 v4.1.0 // indirect
6364
github.com/go-logr/stdr v1.2.2 // indirect

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8
3131
github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g=
3232
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
3333
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
34+
github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY=
35+
github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0=
3436
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
3537
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
3638
github.com/brunoga/deep v1.2.5 h1:bigq4eooqbeJXfvTfZBn3AH3B1iW+rtetxVeh0GiLrg=
@@ -59,6 +61,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk
5961
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
6062
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
6163
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
64+
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
65+
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
6266
github.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vtxU=
6367
github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
6468
github.com/go-jose/go-jose/v4 v4.1.0 h1:cYSYxd3pw5zd2FSXk2vGdn9igQU2PS8MuxrCOCl0FdY=

internal/collectors/collector_controller.go

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,25 @@ import (
2020
"sigs.k8s.io/controller-runtime/pkg/reconcile"
2121

2222
"github.com/dash0hq/dash0-operator/internal/collectors/otelcolresources"
23-
"github.com/dash0hq/dash0-operator/internal/util"
2423
)
2524

2625
type CollectorReconciler struct {
2726
client.Client
28-
CollectorManager *CollectorManager
29-
Images util.Images
30-
OperatorNamespace string
31-
OTelCollectorNamePrefix string
27+
collectorManager *CollectorManager
28+
operatorNamespace string
29+
oTelCollectorNamePrefix string
30+
}
31+
32+
func NewCollectorReconciler(
33+
k8sClient client.Client,
34+
collectorManager *CollectorManager,
35+
oTelCollectorNamePrefix string,
36+
) *CollectorReconciler {
37+
return &CollectorReconciler{
38+
Client: k8sClient,
39+
collectorManager: collectorManager,
40+
oTelCollectorNamePrefix: oTelCollectorNamePrefix,
41+
}
3242
}
3343

3444
func (r *CollectorReconciler) SetupWithManager(mgr ctrl.Manager) error {
@@ -38,42 +48,42 @@ func (r *CollectorReconciler) SetupWithManager(mgr ctrl.Manager) error {
3848
&corev1.ConfigMap{},
3949
&handler.EnqueueRequestForObject{},
4050
r.withNamePredicate([]string{
41-
otelcolresources.DaemonSetCollectorConfigConfigMapName(r.OTelCollectorNamePrefix),
42-
otelcolresources.DeploymentCollectorConfigConfigMapName(r.OTelCollectorNamePrefix),
51+
otelcolresources.DaemonSetCollectorConfigConfigMapName(r.oTelCollectorNamePrefix),
52+
otelcolresources.DeploymentCollectorConfigConfigMapName(r.oTelCollectorNamePrefix),
4353
// Note: We are deliberately not watching the filelog receiver offsets ConfigMap, since it is updated
4454
// frequently by the filelog offset sync container and does not require reconciliation.
4555
})).
4656
Watches(
4757
&rbacv1.ClusterRole{},
4858
&handler.EnqueueRequestForObject{},
4959
r.withNamePredicate([]string{
50-
otelcolresources.DaemonSetClusterRoleName(r.OTelCollectorNamePrefix),
51-
otelcolresources.DeploymentClusterRoleName(r.OTelCollectorNamePrefix),
60+
otelcolresources.DaemonSetClusterRoleName(r.oTelCollectorNamePrefix),
61+
otelcolresources.DeploymentClusterRoleName(r.oTelCollectorNamePrefix),
5262
})).
5363
Watches(
5464
&rbacv1.ClusterRoleBinding{},
5565
&handler.EnqueueRequestForObject{},
5666
r.withNamePredicate([]string{
57-
otelcolresources.DeploymentClusterRoleBindingName(r.OTelCollectorNamePrefix),
58-
otelcolresources.DeploymentClusterRoleName(r.OTelCollectorNamePrefix),
67+
otelcolresources.DeploymentClusterRoleBindingName(r.oTelCollectorNamePrefix),
68+
otelcolresources.DeploymentClusterRoleName(r.oTelCollectorNamePrefix),
5969
})).
6070
Watches(
6171
&corev1.Service{},
6272
&handler.EnqueueRequestForObject{},
6373
r.withNamePredicate([]string{
64-
otelcolresources.ServiceName(r.OTelCollectorNamePrefix),
74+
otelcolresources.ServiceName(r.oTelCollectorNamePrefix),
6575
})).
6676
Watches(
6777
&appsv1.DaemonSet{},
6878
&handler.EnqueueRequestForObject{},
6979
r.withNamePredicate([]string{
70-
otelcolresources.DaemonSetName(r.OTelCollectorNamePrefix),
80+
otelcolresources.DaemonSetName(r.oTelCollectorNamePrefix),
7181
})).
7282
Watches(
7383
&appsv1.Deployment{},
7484
&handler.EnqueueRequestForObject{},
7585
r.withNamePredicate([]string{
76-
otelcolresources.DeploymentName(r.OTelCollectorNamePrefix),
86+
otelcolresources.DeploymentName(r.oTelCollectorNamePrefix),
7787
})).
7888
Complete(r)
7989
}
@@ -83,7 +93,7 @@ func (r *CollectorReconciler) withNamePredicate(resourceNames []string) builder.
8393
}
8494

8595
func (r *CollectorReconciler) createFilterPredicate(resourceNames []string) predicate.Funcs {
86-
resourceNamespace := r.OperatorNamespace
96+
resourceNamespace := r.operatorNamespace
8797
return predicate.Funcs{
8898
CreateFunc: func(e event.CreateEvent) bool {
8999
return resourceMatches(e.Object, resourceNamespace, resourceNames)
@@ -115,10 +125,8 @@ func (r *CollectorReconciler) Reconcile(
115125
logger := log.FromContext(ctx)
116126
logger.Info("reconciling collector resources", "request", request)
117127

118-
err, hasBeenReconciled := r.CollectorManager.ReconcileOpenTelemetryCollector(
128+
hasBeenReconciled, err := r.collectorManager.ReconcileOpenTelemetryCollector(
119129
ctx,
120-
r.Images,
121-
r.OperatorNamespace,
122130
nil,
123131
TriggeredByWatchEvent,
124132
)

internal/collectors/collector_manager.go

Lines changed: 62 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package collectors
66
import (
77
"context"
88
"fmt"
9+
"reflect"
910
"slices"
1011
"strings"
1112
"sync/atomic"
@@ -27,8 +28,10 @@ import (
2728

2829
type CollectorManager struct {
2930
client.Client
30-
Clientset *kubernetes.Clientset
31-
*otelcolresources.OTelColResourceManager
31+
clientset *kubernetes.Clientset
32+
oTelColResourceManager *otelcolresources.OTelColResourceManager
33+
extraConfig atomic.Pointer[util.ExtraConfig]
34+
developmentMode bool
3235
updateInProgress atomic.Bool
3336
resourcesHaveBeenDeletedByOperator atomic.Bool
3437
}
@@ -40,11 +43,44 @@ const (
4043
TriggeredByDash0ResourceReconcile CollectorReconcileTrigger = "resource"
4144
)
4245

46+
func NewCollectorManager(
47+
k8sClient client.Client,
48+
clientset *kubernetes.Clientset,
49+
extraConfig util.ExtraConfig,
50+
developmentMode bool,
51+
oTelColResourceManager *otelcolresources.OTelColResourceManager,
52+
) *CollectorManager {
53+
m := &CollectorManager{
54+
Client: k8sClient,
55+
clientset: clientset,
56+
developmentMode: developmentMode,
57+
oTelColResourceManager: oTelColResourceManager,
58+
}
59+
m.extraConfig.Store(&extraConfig)
60+
return m
61+
}
62+
63+
func (m *CollectorManager) UpdateExtraConfig(ctx context.Context, newConfig util.ExtraConfig, logger *logr.Logger) {
64+
previousConfig := m.extraConfig.Swap(&newConfig)
65+
if previousConfig == nil || !reflect.DeepEqual(*previousConfig, newConfig) {
66+
hasBeenReconciled, err := m.ReconcileOpenTelemetryCollector(ctx, nil, TriggeredByWatchEvent)
67+
if err != nil {
68+
logger.Error(err, "Failed to create/update collector resources after extra config map update.")
69+
}
70+
if hasBeenReconciled {
71+
logger.Info("successfully reconciled collector resources after extra config map update")
72+
}
73+
} else {
74+
logger.Info("ignoring extra config map update, both the new and the old extra config map have the same content")
75+
}
76+
}
77+
4378
// ReconcileOpenTelemetryCollector can be triggered by a
4479
// 1. a reconcile request from the Dash0OperatorConfiguration resource.
4580
// 2. a reconcile request from a Dash0Monitoring resource in the cluster.
4681
// 3. a change event on one of the OpenTelemetry collector related resources that the operator manages (a change to one
4782
// of "our" config maps or similar).
83+
// 4. a file change event picked up by the extra config map watcher
4884
//
4985
// The parameter triggeringMonitoringResource is only != nil for case (2).
5086
//
@@ -54,31 +90,29 @@ const (
5490
// deleted; it only indicates that the reconciliation has been performed.
5591
func (m *CollectorManager) ReconcileOpenTelemetryCollector(
5692
ctx context.Context,
57-
images util.Images,
58-
operatorNamespace string,
5993
triggeringMonitoringResource *dash0v1beta1.Dash0Monitoring,
6094
trigger CollectorReconcileTrigger,
61-
) (error, bool) {
95+
) (bool, error) {
6296
logger := log.FromContext(ctx)
6397
if m.resourcesHaveBeenDeletedByOperator.Load() {
6498
if trigger == TriggeredByWatchEvent {
65-
if m.DevelopmentMode {
99+
if m.developmentMode {
66100
logger.Info("OpenTelemetry collector resources have already been deleted, ignoring reconciliation request.")
67101
}
68-
return nil, false
102+
return false, nil
69103
} else if trigger == TriggeredByDash0ResourceReconcile {
70-
if m.DevelopmentMode {
104+
if m.developmentMode {
71105
logger.Info("resetting resourcesHaveBeenDeletedByOperator")
72106
}
73107
m.resourcesHaveBeenDeletedByOperator.Store(false)
74108
}
75109
}
76110
if m.updateInProgress.Load() {
77-
if m.DevelopmentMode {
111+
if m.developmentMode {
78112
logger.Info("creation/update of the OpenTelemetry collector resources is already in progress, skipping " +
79113
"additional reconciliation request.")
80114
}
81-
return nil, false
115+
return false, nil
82116
}
83117

84118
m.updateInProgress.Store(true)
@@ -88,11 +122,11 @@ func (m *CollectorManager) ReconcileOpenTelemetryCollector(
88122

89123
operatorConfigurationResource, err := m.findOperatorConfigurationResource(ctx, &logger)
90124
if err != nil {
91-
return err, false
125+
return false, err
92126
}
93127
allMonitoringResources, err := m.findAllMonitoringResources(ctx, &logger)
94128
if err != nil {
95-
return err, false
129+
return false, err
96130
}
97131
var export *dash0common.Export
98132
if operatorConfigurationResource != nil && operatorConfigurationResource.Spec.Export != nil {
@@ -125,26 +159,29 @@ func (m *CollectorManager) ReconcileOpenTelemetryCollector(
125159
}
126160
}
127161

162+
extraConfig := m.extraConfig.Load()
163+
if extraConfig == nil {
164+
return false, fmt.Errorf("extra config is nil in CollectorManager#ReconcileOpenTelemetryCollector")
165+
}
128166
if operatorConfigurationResource != nil && !util.ReadBoolPointerWithDefault(operatorConfigurationResource.Spec.TelemetryCollection.Enabled, true) {
129167
logger.Info(
130168
fmt.Sprintf("Telemetry collection has been disabled explicitly via the operator configuration "+
131169
"resource (\"%s\"), property telemetryCollection.enabled=false, no Dash0 OpenTelemetry collector "+
132170
"will be created, existing Dash0 OpenTelemetry collectors (if any) will be removed.",
133171
operatorConfigurationResource.Name),
134172
)
135-
err = m.removeOpenTelemetryCollector(ctx, operatorNamespace, &logger)
136-
return err, err == nil
173+
err = m.removeOpenTelemetryCollector(ctx, *extraConfig, &logger)
174+
return err == nil, err
137175
} else if export != nil {
138176
err = m.createOrUpdateOpenTelemetryCollector(
139177
ctx,
140-
operatorNamespace,
141-
images,
142178
operatorConfigurationResource,
143179
allMonitoringResources,
180+
*extraConfig,
144181
export,
145182
&logger,
146183
)
147-
return err, err == nil
184+
return err == nil, err
148185
} else {
149186
// This should actually never happen, as the operator configuration has a kubebuilder validation comment that
150187
// makes the export a required field.
@@ -155,25 +192,23 @@ func (m *CollectorManager) ReconcileOpenTelemetryCollector(
155192
"collectors (if any) will be removed.", operatorConfigurationResource.Name),
156193
)
157194
}
158-
err = m.removeOpenTelemetryCollector(ctx, operatorNamespace, &logger)
159-
return err, err == nil
195+
err = m.removeOpenTelemetryCollector(ctx, *extraConfig, &logger)
196+
return err == nil, err
160197
}
161198
}
162199

163200
func (m *CollectorManager) createOrUpdateOpenTelemetryCollector(
164201
ctx context.Context,
165-
operatorNamespace string,
166-
images util.Images,
167202
operatorConfigurationResource *dash0v1alpha1.Dash0OperatorConfiguration,
168203
allMonitoringResources []dash0v1beta1.Dash0Monitoring,
204+
extraConfig util.ExtraConfig,
169205
export *dash0common.Export,
170206
logger *logr.Logger,
171207
) error {
172208
resourcesHaveBeenCreated, resourcesHaveBeenUpdated, err :=
173-
m.OTelColResourceManager.CreateOrUpdateOpenTelemetryCollectorResources(
209+
m.oTelColResourceManager.CreateOrUpdateOpenTelemetryCollectorResources(
174210
ctx,
175-
operatorNamespace,
176-
images,
211+
extraConfig,
177212
operatorConfigurationResource,
178213
allMonitoringResources,
179214
export,
@@ -199,12 +234,12 @@ func (m *CollectorManager) createOrUpdateOpenTelemetryCollector(
199234

200235
func (m *CollectorManager) removeOpenTelemetryCollector(
201236
ctx context.Context,
202-
operatorNamespace string,
237+
extraConfig util.ExtraConfig,
203238
logger *logr.Logger,
204239
) error {
205-
resourcesHaveBeenDeleted, err := m.OTelColResourceManager.DeleteResources(
240+
resourcesHaveBeenDeleted, err := m.oTelColResourceManager.DeleteResources(
206241
ctx,
207-
operatorNamespace,
242+
extraConfig,
208243
logger,
209244
)
210245
if err != nil {

0 commit comments

Comments
 (0)