@@ -378,6 +378,85 @@ var _ = Describe("manger.Manager", func() {
378
378
379
379
Expect (cm .gracefulShutdownTimeout .Nanoseconds ()).To (Equal (int64 (0 )))
380
380
})
381
+
382
+ It ("should prevent leader election when shutting down a non-elected manager" , func () {
383
+ var rl resourcelock.Interface
384
+ m1 , err := New (cfg , Options {
385
+ LeaderElection : true ,
386
+ LeaderElectionNamespace : "default" ,
387
+ LeaderElectionID : "test-leader-election-id" ,
388
+ newResourceLock : func (config * rest.Config , recorderProvider recorder.Provider , options leaderelection.Options ) (resourcelock.Interface , error ) {
389
+ var err error
390
+ rl , err = leaderelection .NewResourceLock (config , recorderProvider , options )
391
+ return rl , err
392
+ },
393
+ HealthProbeBindAddress : "0" ,
394
+ Metrics : metricsserver.Options {BindAddress : "0" },
395
+ PprofBindAddress : "0" ,
396
+ })
397
+ Expect (err ).ToNot (HaveOccurred ())
398
+ Expect (m1 ).ToNot (BeNil ())
399
+ Expect (rl .Describe ()).To (Equal ("default/test-leader-election-id" ))
400
+
401
+ m1cm , ok := m1 .(* controllerManager )
402
+ Expect (ok ).To (BeTrue ())
403
+ m1cm .onStoppedLeading = func () {}
404
+
405
+ m2 , err := New (cfg , Options {
406
+ LeaderElection : true ,
407
+ LeaderElectionNamespace : "default" ,
408
+ LeaderElectionID : "test-leader-election-id" ,
409
+ newResourceLock : func (config * rest.Config , recorderProvider recorder.Provider , options leaderelection.Options ) (resourcelock.Interface , error ) {
410
+ var err error
411
+ rl , err = leaderelection .NewResourceLock (config , recorderProvider , options )
412
+ return rl , err
413
+ },
414
+ HealthProbeBindAddress : "0" ,
415
+ Metrics : metricsserver.Options {BindAddress : "0" },
416
+ PprofBindAddress : "0" ,
417
+ })
418
+ Expect (err ).ToNot (HaveOccurred ())
419
+ Expect (m2 ).ToNot (BeNil ())
420
+ Expect (rl .Describe ()).To (Equal ("default/test-leader-election-id" ))
421
+
422
+ m1done := make (chan struct {})
423
+ Expect (m1 .Add (RunnableFunc (func (ctx context.Context ) error {
424
+ defer GinkgoRecover ()
425
+ close (m1done )
426
+ return nil
427
+ }))).To (Succeed ())
428
+
429
+ ctx1 , cancel1 := context .WithCancel (context .Background ())
430
+ defer cancel1 ()
431
+ go func () {
432
+ defer GinkgoRecover ()
433
+ Expect (m1 .Elected ()).ShouldNot (BeClosed ())
434
+ Expect (m1 .Start (ctx1 )).NotTo (HaveOccurred ())
435
+ }()
436
+ <- m1 .Elected ()
437
+ <- m1done
438
+
439
+ electionRunnable := & needElection {make (chan struct {})}
440
+
441
+ Expect (m2 .Add (electionRunnable )).To (Succeed ())
442
+
443
+ ctx2 , cancel2 := context .WithCancel (context .Background ())
444
+ m2done := make (chan struct {})
445
+ go func () {
446
+ defer GinkgoRecover ()
447
+ Expect (m2 .Start (ctx2 )).NotTo (HaveOccurred ())
448
+ close (m2done )
449
+ }()
450
+ Consistently (m2 .Elected ()).ShouldNot (Receive ())
451
+
452
+ go func () {
453
+ defer GinkgoRecover ()
454
+ Consistently (electionRunnable .ch ).ShouldNot (Receive ())
455
+ }()
456
+ cancel2 ()
457
+ <- m2done
458
+ })
459
+
381
460
It ("should default ID to controller-runtime if ID is not set" , func () {
382
461
var rl resourcelock.Interface
383
462
m1 , err := New (cfg , Options {
@@ -1929,3 +2008,16 @@ func (f *fakeDeferredLoader) InjectScheme(scheme *runtime.Scheme) error {
1929
2008
type metricsDefaultServer interface {
1930
2009
GetBindAddr () string
1931
2010
}
2011
+
2012
+ type needElection struct {
2013
+ ch chan struct {}
2014
+ }
2015
+
2016
+ func (n * needElection ) Start (_ context.Context ) error {
2017
+ n .ch <- struct {}{}
2018
+ return nil
2019
+ }
2020
+
2021
+ func (n * needElection ) NeedLeaderElection () bool {
2022
+ return true
2023
+ }
0 commit comments