@@ -83,6 +83,9 @@ type controllerManager struct {
83
83
errChan chan error
84
84
stop <- chan struct {}
85
85
86
+ // stopper is the write side of the stop channel. They should have the same value.
87
+ stopper chan <- struct {}
88
+
86
89
startCache func (stop <- chan struct {}) error
87
90
}
88
91
@@ -192,13 +195,16 @@ func (cm *controllerManager) serveMetrics(stop <-chan struct{}) {
192
195
}
193
196
194
197
func (cm * controllerManager ) Start (stop <- chan struct {}) error {
198
+ // join the passed-in stop channel as an upstream feeding into cm.stopper
199
+ defer close (cm .stopper )
200
+
195
201
if cm .resourceLock != nil {
196
- err := cm .startLeaderElection (stop )
202
+ err := cm .startLeaderElection ()
197
203
if err != nil {
198
204
return err
199
205
}
200
206
} else {
201
- go cm .start (stop )
207
+ go cm .start ()
202
208
}
203
209
204
210
select {
@@ -211,45 +217,43 @@ func (cm *controllerManager) Start(stop <-chan struct{}) error {
211
217
}
212
218
}
213
219
214
- func (cm * controllerManager ) start (stop <- chan struct {} ) {
220
+ func (cm * controllerManager ) start () {
215
221
cm .mu .Lock ()
216
222
defer cm .mu .Unlock ()
217
223
218
- cm .stop = stop
219
-
220
224
// Start the Cache. Allow the function to start the cache to be mocked out for testing
221
225
if cm .startCache == nil {
222
226
cm .startCache = cm .cache .Start
223
227
}
224
228
go func () {
225
- if err := cm .startCache (stop ); err != nil {
229
+ if err := cm .startCache (cm . stop ); err != nil {
226
230
cm .errChan <- err
227
231
}
228
232
}()
229
233
230
234
// Start the metrics server
231
235
if cm .metricsListener != nil {
232
- go cm .serveMetrics (stop )
236
+ go cm .serveMetrics (cm . stop )
233
237
}
234
238
235
239
// Wait for the caches to sync.
236
240
// TODO(community): Check the return value and write a test
237
- cm .cache .WaitForCacheSync (stop )
241
+ cm .cache .WaitForCacheSync (cm . stop )
238
242
239
243
// Start the runnables after the cache has synced
240
244
for _ , c := range cm .runnables {
241
245
// Controllers block, but we want to return an error if any have an error starting.
242
246
// Write any Start errors to a channel so we can return them
243
247
ctrl := c
244
248
go func () {
245
- cm .errChan <- ctrl .Start (stop )
249
+ cm .errChan <- ctrl .Start (cm . stop )
246
250
}()
247
251
}
248
252
249
253
cm .started = true
250
254
}
251
255
252
- func (cm * controllerManager ) startLeaderElection (stop <- chan struct {} ) (err error ) {
256
+ func (cm * controllerManager ) startLeaderElection () (err error ) {
253
257
l , err := leaderelection .NewLeaderElector (leaderelection.LeaderElectionConfig {
254
258
Lock : cm .resourceLock ,
255
259
// Values taken from: https://github.com/kubernetes/apiserver/blob/master/pkg/apis/config/v1alpha1/defaults.go
@@ -259,7 +263,7 @@ func (cm *controllerManager) startLeaderElection(stop <-chan struct{}) (err erro
259
263
RetryPeriod : 2 * time .Second ,
260
264
Callbacks : leaderelection.LeaderCallbacks {
261
265
OnStartedLeading : func (_ <- chan struct {}) {
262
- cm .start (stop )
266
+ cm .start ()
263
267
},
264
268
OnStoppedLeading : func () {
265
269
// Most implementations of leader election log.Fatal() here.
0 commit comments