@@ -69,7 +69,7 @@ type controllerManager struct {
69
69
// (and EventHandlers, Sources and Predicates).
70
70
recorderProvider recorder.Provider
71
71
72
- // resourceLock
72
+ // resourceLock forms the basis for leader election
73
73
resourceLock resourcelock.Interface
74
74
75
75
// mapper is used to map resources to kind, and map kind and version.
@@ -81,7 +81,16 @@ type controllerManager struct {
81
81
mu sync.Mutex
82
82
started bool
83
83
errChan chan error
84
- stop <- chan struct {}
84
+
85
+ // internalStop is the stop channel *actually* used by everything involved
86
+ // with the manager as a stop channel, so that we can pass a stop channel
87
+ // to things that need it off the bat (like the Channel source). It can
88
+ // be closed via `internalStopper` (by being the same underlying channel).
89
+ internalStop <- chan struct {}
90
+
91
+ // internalStopper is the write side of the internal stop channel, allowing us to close it.
92
+ // It and `internalStop` should point to the same channel.
93
+ internalStopper chan <- struct {}
85
94
86
95
startCache func (stop <- chan struct {}) error
87
96
}
@@ -101,7 +110,7 @@ func (cm *controllerManager) Add(r Runnable) error {
101
110
if cm .started {
102
111
// If already started, start the controller
103
112
go func () {
104
- cm .errChan <- r .Start (cm .stop )
113
+ cm .errChan <- r .Start (cm .internalStop )
105
114
}()
106
115
}
107
116
@@ -124,7 +133,7 @@ func (cm *controllerManager) SetFields(i interface{}) error {
124
133
if _ , err := inject .InjectorInto (cm .SetFields , i ); err != nil {
125
134
return err
126
135
}
127
- if _ , err := inject .StopChannelInto (cm .stop , i ); err != nil {
136
+ if _ , err := inject .StopChannelInto (cm .internalStop , i ); err != nil {
128
137
return err
129
138
}
130
139
if _ , err := inject .DecoderInto (cm .admissionDecoder , i ); err != nil {
@@ -192,13 +201,16 @@ func (cm *controllerManager) serveMetrics(stop <-chan struct{}) {
192
201
}
193
202
194
203
func (cm * controllerManager ) Start (stop <- chan struct {}) error {
204
+ // join the passed-in stop channel as an upstream feeding into cm.internalStopper
205
+ defer close (cm .internalStopper )
206
+
195
207
if cm .resourceLock != nil {
196
- err := cm .startLeaderElection (stop )
208
+ err := cm .startLeaderElection ()
197
209
if err != nil {
198
210
return err
199
211
}
200
212
} else {
201
- go cm .start (stop )
213
+ go cm .start ()
202
214
}
203
215
204
216
select {
@@ -211,45 +223,43 @@ func (cm *controllerManager) Start(stop <-chan struct{}) error {
211
223
}
212
224
}
213
225
214
- func (cm * controllerManager ) start (stop <- chan struct {} ) {
226
+ func (cm * controllerManager ) start () {
215
227
cm .mu .Lock ()
216
228
defer cm .mu .Unlock ()
217
229
218
- cm .stop = stop
219
-
220
230
// Start the Cache. Allow the function to start the cache to be mocked out for testing
221
231
if cm .startCache == nil {
222
232
cm .startCache = cm .cache .Start
223
233
}
224
234
go func () {
225
- if err := cm .startCache (stop ); err != nil {
235
+ if err := cm .startCache (cm . internalStop ); err != nil {
226
236
cm .errChan <- err
227
237
}
228
238
}()
229
239
230
240
// Start the metrics server
231
241
if cm .metricsListener != nil {
232
- go cm .serveMetrics (stop )
242
+ go cm .serveMetrics (cm . internalStop )
233
243
}
234
244
235
245
// Wait for the caches to sync.
236
246
// TODO(community): Check the return value and write a test
237
- cm .cache .WaitForCacheSync (stop )
247
+ cm .cache .WaitForCacheSync (cm . internalStop )
238
248
239
249
// Start the runnables after the cache has synced
240
250
for _ , c := range cm .runnables {
241
251
// Controllers block, but we want to return an error if any have an error starting.
242
252
// Write any Start errors to a channel so we can return them
243
253
ctrl := c
244
254
go func () {
245
- cm .errChan <- ctrl .Start (stop )
255
+ cm .errChan <- ctrl .Start (cm . internalStop )
246
256
}()
247
257
}
248
258
249
259
cm .started = true
250
260
}
251
261
252
- func (cm * controllerManager ) startLeaderElection (stop <- chan struct {} ) (err error ) {
262
+ func (cm * controllerManager ) startLeaderElection () (err error ) {
253
263
l , err := leaderelection .NewLeaderElector (leaderelection.LeaderElectionConfig {
254
264
Lock : cm .resourceLock ,
255
265
// Values taken from: https://github.com/kubernetes/apiserver/blob/master/pkg/apis/config/v1alpha1/defaults.go
@@ -259,7 +269,7 @@ func (cm *controllerManager) startLeaderElection(stop <-chan struct{}) (err erro
259
269
RetryPeriod : 2 * time .Second ,
260
270
Callbacks : leaderelection.LeaderCallbacks {
261
271
OnStartedLeading : func (_ <- chan struct {}) {
262
- cm .start (stop )
272
+ cm .start ()
263
273
},
264
274
OnStoppedLeading : func () {
265
275
// Most implementations of leader election log.Fatal() here.
0 commit comments