Skip to content

Commit 8c1789c

Browse files
committed
update the event recorder for a passive clock
1 parent ec00d85 commit 8c1789c

File tree

10 files changed

+70
-30
lines changed

10 files changed

+70
-30
lines changed

pkg/controller/controllercmd/builder.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package controllercmd
33
import (
44
"context"
55
"fmt"
6+
"k8s.io/utils/clock"
67
"os"
78
"strings"
89
"sync"
@@ -40,6 +41,9 @@ type StartFunc func(context.Context, *ControllerContext) error
4041
type ControllerContext struct {
4142
ComponentConfig *unstructured.Unstructured
4243

44+
// Clock is a potentially fake clock that must be used to run controllers.
45+
Clock clock.Clock
46+
4347
// KubeConfig provides the REST config with no content type (it will default to JSON).
4448
// Use this config for CR resources.
4549
KubeConfig *rest.Config
@@ -71,6 +75,7 @@ type ControllerBuilder struct {
7175
fileObserverReactorFn func(file string, action fileobserver.ActionType) error
7276
eventRecorderOptions record.CorrelatorOptions
7377
componentOwnerReference *corev1.ObjectReference
78+
clock clock.Clock
7479

7580
startFunc StartFunc
7681
componentName string
@@ -121,10 +126,11 @@ func (i infrastructureStatusTopologyDetector) DetectTopology(ctx context.Context
121126
var _ TopologyDetector = (*infrastructureStatusTopologyDetector)(nil)
122127

123128
// NewController returns a builder struct for constructing the command you want to run
124-
func NewController(componentName string, startFunc StartFunc) *ControllerBuilder {
129+
func NewController(componentName string, startFunc StartFunc, clock clock.Clock) *ControllerBuilder {
125130
return &ControllerBuilder{
126131
startFunc: startFunc,
127132
componentName: componentName,
133+
clock: clock,
128134
observerInterval: defaultObserverInterval,
129135
nonZeroExitFn: func(args ...interface{}) {
130136
klog.Warning(args...)
@@ -266,7 +272,7 @@ func (b *ControllerBuilder) Run(ctx context.Context, config *unstructured.Unstru
266272
klog.Warningf("unable to get owner reference (falling back to namespace): %v", err)
267273
}
268274
}
269-
eventRecorder := events.NewKubeRecorderWithOptions(kubeClient.CoreV1().Events(namespace), b.eventRecorderOptions, b.componentName, controllerRef)
275+
eventRecorder := events.NewKubeRecorderWithOptions(kubeClient.CoreV1().Events(namespace), b.eventRecorderOptions, b.componentName, controllerRef, b.clock)
270276

271277
utilruntime.PanicHandlers = append(utilruntime.PanicHandlers, func(c context.Context, r interface{}) {
272278
eventRecorder.Warningf(fmt.Sprintf("%sPanic", strings.Title(b.componentName)), "Panic observed: %v", r)
@@ -336,6 +342,7 @@ func (b *ControllerBuilder) Run(ctx context.Context, config *unstructured.Unstru
336342

337343
controllerContext := &ControllerContext{
338344
ComponentConfig: config,
345+
Clock: b.clock,
339346
KubeConfig: clientConfig,
340347
ProtoKubeConfig: protoConfig,
341348
EventRecorder: eventRecorder,

pkg/controller/controllercmd/cmd.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package controllercmd
33
import (
44
"context"
55
"fmt"
6+
"k8s.io/utils/clock"
67
"math/rand"
78
"os"
89
"path/filepath"
@@ -41,6 +42,7 @@ type ControllerCommandConfig struct {
4142
componentName string
4243
startFunc StartFunc
4344
version version.Info
45+
clock clock.Clock
4446

4547
basicFlags *ControllerFlags
4648

@@ -76,11 +78,12 @@ type ControllerCommandConfig struct {
7678

7779
// NewControllerConfig returns a new ControllerCommandConfig which can be used to wire up all the boiler plate of a controller
7880
// TODO add more methods around wiring health checks and the like
79-
func NewControllerCommandConfig(componentName string, version version.Info, startFunc StartFunc) *ControllerCommandConfig {
81+
func NewControllerCommandConfig(componentName string, version version.Info, startFunc StartFunc, clock clock.Clock) *ControllerCommandConfig {
8082
return &ControllerCommandConfig{
8183
startFunc: startFunc,
8284
componentName: componentName,
8385
version: version,
86+
clock: clock,
8487

8588
basicFlags: NewControllerFlags(),
8689

@@ -322,7 +325,7 @@ func (c *ControllerCommandConfig) StartController(ctx context.Context) error {
322325
config.LeaderElection.RenewDeadline = c.RenewDeadline
323326
config.LeaderElection.RetryPeriod = c.RetryPeriod
324327

325-
builder := NewController(c.componentName, c.startFunc).
328+
builder := NewController(c.componentName, c.startFunc, c.clock).
326329
WithKubeConfigFile(c.basicFlags.KubeConfigFile, nil).
327330
WithComponentNamespace(c.basicFlags.Namespace).
328331
WithLeaderElection(config.LeaderElection, c.basicFlags.Namespace, c.componentName+"-lock").

pkg/operator/events/recorder.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@ import (
44
"context"
55
"errors"
66
"fmt"
7-
"os"
8-
"time"
9-
107
"k8s.io/client-go/kubernetes"
118
"k8s.io/klog/v2"
9+
"k8s.io/utils/clock"
10+
"os"
1211

1312
corev1 "k8s.io/api/core/v1"
1413
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -145,11 +144,12 @@ func guessControllerReferenceForNamespace(ctx context.Context, client corev1clie
145144
}
146145

147146
// NewRecorder returns new event recorder.
148-
func NewRecorder(client corev1client.EventInterface, sourceComponentName string, involvedObjectRef *corev1.ObjectReference) Recorder {
147+
func NewRecorder(client corev1client.EventInterface, sourceComponentName string, involvedObjectRef *corev1.ObjectReference, clock clock.PassiveClock) Recorder {
149148
return &recorder{
150149
eventClient: client,
151150
involvedObjectRef: involvedObjectRef,
152151
sourceComponent: sourceComponentName,
152+
clock: clock,
153153
}
154154
}
155155

@@ -158,6 +158,7 @@ type recorder struct {
158158
eventClient corev1client.EventInterface
159159
involvedObjectRef *corev1.ObjectReference
160160
sourceComponent string
161+
clock clock.PassiveClock
161162

162163
// TODO: This is not the right way to pass the context, but there is no other way without breaking event interface
163164
ctx context.Context
@@ -196,7 +197,7 @@ func (r *recorder) Warningf(reason, messageFmt string, args ...interface{}) {
196197

197198
// Event emits the normal type event.
198199
func (r *recorder) Event(reason, message string) {
199-
event := makeEvent(r.involvedObjectRef, r.sourceComponent, corev1.EventTypeNormal, reason, message)
200+
event := makeEvent(r.clock, r.involvedObjectRef, r.sourceComponent, corev1.EventTypeNormal, reason, message)
200201
ctx := context.Background()
201202
if r.ctx != nil {
202203
ctx = r.ctx
@@ -208,7 +209,7 @@ func (r *recorder) Event(reason, message string) {
208209

209210
// Warning emits the warning type event.
210211
func (r *recorder) Warning(reason, message string) {
211-
event := makeEvent(r.involvedObjectRef, r.sourceComponent, corev1.EventTypeWarning, reason, message)
212+
event := makeEvent(r.clock, r.involvedObjectRef, r.sourceComponent, corev1.EventTypeWarning, reason, message)
212213
ctx := context.Background()
213214
if r.ctx != nil {
214215
ctx = r.ctx
@@ -218,10 +219,11 @@ func (r *recorder) Warning(reason, message string) {
218219
}
219220
}
220221

221-
func makeEvent(involvedObjRef *corev1.ObjectReference, sourceComponent string, eventType, reason, message string) *corev1.Event {
222-
currentTime := metav1.Time{Time: time.Now()}
222+
func makeEvent(clock clock.PassiveClock, involvedObjRef *corev1.ObjectReference, sourceComponent string, eventType, reason, message string) *corev1.Event {
223+
currentTime := metav1.Time{Time: clock.Now()}
223224
event := &corev1.Event{
224225
ObjectMeta: metav1.ObjectMeta{
226+
// TODO this is always used to create a unique event. Perhaps we should hash the message to be unique enough for apply-configuration
225227
Name: fmt.Sprintf("%v.%x", involvedObjRef.Name, currentTime.UnixNano()),
226228
Namespace: involvedObjRef.Namespace,
227229
},

pkg/operator/events/recorder_in_memory.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package events
33
import (
44
"context"
55
"fmt"
6+
"k8s.io/utils/clock"
67
"sync"
78

89
corev1 "k8s.io/api/core/v1"
@@ -12,6 +13,7 @@ import (
1213
type inMemoryEventRecorder struct {
1314
events []*corev1.Event
1415
source string
16+
clock clock.PassiveClock
1517
ctx context.Context
1618
sync.Mutex
1719
}
@@ -31,8 +33,12 @@ type InMemoryRecorder interface {
3133

3234
// NewInMemoryRecorder provides event recorder that stores all events recorded in memory and allow to replay them using the Events() method.
3335
// This recorder should be only used in unit tests.
34-
func NewInMemoryRecorder(sourceComponent string) InMemoryRecorder {
35-
return &inMemoryEventRecorder{events: []*corev1.Event{}, source: sourceComponent}
36+
func NewInMemoryRecorder(sourceComponent string, clock clock.PassiveClock) InMemoryRecorder {
37+
return &inMemoryEventRecorder{
38+
events: []*corev1.Event{},
39+
source: sourceComponent,
40+
clock: clock,
41+
}
3642
}
3743

3844
func (r *inMemoryEventRecorder) ComponentName() string {
@@ -65,7 +71,7 @@ func (r *inMemoryEventRecorder) Events() []*corev1.Event {
6571
func (r *inMemoryEventRecorder) Event(reason, message string) {
6672
r.Lock()
6773
defer r.Unlock()
68-
event := makeEvent(&inMemoryDummyObjectReference, r.source, corev1.EventTypeNormal, reason, message)
74+
event := makeEvent(r.clock, &inMemoryDummyObjectReference, r.source, corev1.EventTypeNormal, reason, message)
6975
r.events = append(r.events, event)
7076
}
7177

@@ -76,7 +82,7 @@ func (r *inMemoryEventRecorder) Eventf(reason, messageFmt string, args ...interf
7682
func (r *inMemoryEventRecorder) Warning(reason, message string) {
7783
r.Lock()
7884
defer r.Unlock()
79-
event := makeEvent(&inMemoryDummyObjectReference, r.source, corev1.EventTypeWarning, reason, message)
85+
event := makeEvent(r.clock, &inMemoryDummyObjectReference, r.source, corev1.EventTypeWarning, reason, message)
8086
klog.Info(event.String())
8187
r.events = append(r.events, event)
8288
}

pkg/operator/events/recorder_logging.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ package events
33
import (
44
"context"
55
"fmt"
6+
"k8s.io/utils/clock"
67

78
corev1 "k8s.io/api/core/v1"
89
"k8s.io/klog/v2"
910
)
1011

1112
type LoggingEventRecorder struct {
1213
component string
14+
clock clock.PassiveClock
1315
ctx context.Context
1416
}
1517

@@ -19,8 +21,11 @@ func (r *LoggingEventRecorder) WithContext(ctx context.Context) Recorder {
1921
}
2022

2123
// NewLoggingEventRecorder provides event recorder that will log all recorded events via klog.
22-
func NewLoggingEventRecorder(component string) Recorder {
23-
return &LoggingEventRecorder{component: component}
24+
func NewLoggingEventRecorder(component string, clock clock.PassiveClock) Recorder {
25+
return &LoggingEventRecorder{
26+
component: component,
27+
clock: clock,
28+
}
2429
}
2530

2631
func (r *LoggingEventRecorder) ComponentName() string {
@@ -40,7 +45,7 @@ func (r *LoggingEventRecorder) WithComponentSuffix(suffix string) Recorder {
4045
}
4146

4247
func (r *LoggingEventRecorder) Event(reason, message string) {
43-
event := makeEvent(&inMemoryDummyObjectReference, "", corev1.EventTypeNormal, reason, message)
48+
event := makeEvent(r.clock, &inMemoryDummyObjectReference, "", corev1.EventTypeNormal, reason, message)
4449
klog.Info(event.String())
4550
}
4651

@@ -49,7 +54,7 @@ func (r *LoggingEventRecorder) Eventf(reason, messageFmt string, args ...interfa
4954
}
5055

5156
func (r *LoggingEventRecorder) Warning(reason, message string) {
52-
event := makeEvent(&inMemoryDummyObjectReference, "", corev1.EventTypeWarning, reason, message)
57+
event := makeEvent(r.clock, &inMemoryDummyObjectReference, "", corev1.EventTypeWarning, reason, message)
5358
klog.Warning(event.String())
5459
}
5560

pkg/operator/events/recorder_upstream.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package events
33
import (
44
"context"
55
"fmt"
6+
"k8s.io/utils/clock"
67
"strings"
78
"sync"
89

@@ -16,19 +17,19 @@ import (
1617
)
1718

1819
// NewKubeRecorder returns new event recorder with tweaked correlator options.
19-
func NewKubeRecorderWithOptions(client corev1client.EventInterface, options record.CorrelatorOptions, sourceComponentName string, involvedObjectRef *corev1.ObjectReference) Recorder {
20+
func NewKubeRecorderWithOptions(client corev1client.EventInterface, options record.CorrelatorOptions, sourceComponentName string, involvedObjectRef *corev1.ObjectReference, clock clock.PassiveClock) Recorder {
2021
return (&upstreamRecorder{
2122
client: client,
2223
component: sourceComponentName,
2324
involvedObjectRef: involvedObjectRef,
2425
options: options,
25-
fallbackRecorder: NewRecorder(client, sourceComponentName, involvedObjectRef),
26+
fallbackRecorder: NewRecorder(client, sourceComponentName, involvedObjectRef, clock),
2627
}).ForComponent(sourceComponentName)
2728
}
2829

2930
// NewKubeRecorder returns new event recorder with default correlator options.
30-
func NewKubeRecorder(client corev1client.EventInterface, sourceComponentName string, involvedObjectRef *corev1.ObjectReference) Recorder {
31-
return NewKubeRecorderWithOptions(client, record.CorrelatorOptions{}, sourceComponentName, involvedObjectRef)
31+
func NewKubeRecorder(client corev1client.EventInterface, sourceComponentName string, involvedObjectRef *corev1.ObjectReference, clock clock.PassiveClock) Recorder {
32+
return NewKubeRecorderWithOptions(client, record.CorrelatorOptions{}, sourceComponentName, involvedObjectRef, clock)
3233
}
3334

3435
// upstreamRecorder is an implementation of Recorder interface.

pkg/operator/staticpod/certsyncpod/certsync_cmd.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package certsyncpod
22

33
import (
44
"context"
5+
"k8s.io/utils/clock"
56
"os"
67
"time"
78

@@ -23,6 +24,7 @@ type CertSyncControllerOptions struct {
2324
KubeConfigFile string
2425
Namespace string
2526
DestinationDir string
27+
Clock clock.PassiveClock
2628

2729
configMaps []installer.UnrevisionedResource
2830
secrets []installer.UnrevisionedResource
@@ -33,6 +35,7 @@ type CertSyncControllerOptions struct {
3335

3436
func NewCertSyncControllerCommand(configmaps, secrets []installer.UnrevisionedResource) *cobra.Command {
3537
o := &CertSyncControllerOptions{
38+
Clock: clock.RealClock{},
3639
configMaps: configmaps,
3740
secrets: secrets,
3841
}
@@ -87,7 +90,7 @@ func (o *CertSyncControllerOptions) Run() error {
8790
Kind: "Pod",
8891
Namespace: os.Getenv("POD_NAMESPACE"),
8992
Name: os.Getenv("POD_NAME"),
90-
})
93+
}, o.Clock)
9194

9295
controller := NewCertSyncController(
9396
o.DestinationDir,

pkg/operator/staticpod/controllers.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package staticpod
22

33
import (
44
"fmt"
5+
"k8s.io/utils/clock"
56
"time"
67

78
operatorv1 "github.com/openshift/api/operator/v1"
@@ -39,6 +40,7 @@ type staticPodOperatorControllerBuilder struct {
3940
kubeClient kubernetes.Interface
4041
kubeInformers v1helpers.KubeInformersForNamespaces
4142
configInformers externalversions.SharedInformerFactory
43+
clock clock.Clock
4244
eventRecorder events.Recorder
4345

4446
// resource information
@@ -84,12 +86,14 @@ func NewBuilder(
8486
kubeClient kubernetes.Interface,
8587
kubeInformers v1helpers.KubeInformersForNamespaces,
8688
configInformers externalversions.SharedInformerFactory,
89+
clock clock.Clock,
8790
) Builder {
8891
return &staticPodOperatorControllerBuilder{
8992
staticPodOperatorClient: staticPodOperatorClient,
9093
kubeClient: kubeClient,
9194
kubeInformers: kubeInformers,
9295
configInformers: configInformers,
96+
clock: clock,
9397
}
9498
}
9599

@@ -209,7 +213,7 @@ func (b *staticPodOperatorControllerBuilder) ToControllers() (manager.Controller
209213

210214
eventRecorder := b.eventRecorder
211215
if eventRecorder == nil {
212-
eventRecorder = events.NewLoggingEventRecorder("static-pod-operator-controller")
216+
eventRecorder = events.NewLoggingEventRecorder("static-pod-operator-controller", b.clock)
213217
}
214218
versionRecorder := b.versionRecorder
215219
if versionRecorder == nil {

0 commit comments

Comments
 (0)