Merge pull request #19356 from mikedanese/le-2
Auto commit by PR queue bot
This commit is contained in:
		@@ -121,12 +121,15 @@ type LeaderElectionConfig struct {
 | 
				
			|||||||
//
 | 
					//
 | 
				
			||||||
// possible future callbacks:
 | 
					// possible future callbacks:
 | 
				
			||||||
//  * OnChallenge()
 | 
					//  * OnChallenge()
 | 
				
			||||||
//  * OnNewLeader()
 | 
					 | 
				
			||||||
type LeaderCallbacks struct {
 | 
					type LeaderCallbacks struct {
 | 
				
			||||||
	// OnStartedLeading is called when a LeaderElector client starts leading
 | 
						// OnStartedLeading is called when a LeaderElector client starts leading
 | 
				
			||||||
	OnStartedLeading func(stop <-chan struct{})
 | 
						OnStartedLeading func(stop <-chan struct{})
 | 
				
			||||||
	// OnStoppedLeading is called when a LeaderElector client stops leading
 | 
						// OnStoppedLeading is called when a LeaderElector client stops leading
 | 
				
			||||||
	OnStoppedLeading func()
 | 
						OnStoppedLeading func()
 | 
				
			||||||
 | 
						// OnNewLeader is called when the client observes a leader that is
 | 
				
			||||||
 | 
						// not the previously observed leader. This includes the first observed
 | 
				
			||||||
 | 
						// leader when the client starts.
 | 
				
			||||||
 | 
						OnNewLeader func(identity string)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// LeaderElector is a leader election client.
 | 
					// LeaderElector is a leader election client.
 | 
				
			||||||
@@ -139,6 +142,10 @@ type LeaderElector struct {
 | 
				
			|||||||
	// internal bookkeeping
 | 
						// internal bookkeeping
 | 
				
			||||||
	observedRecord LeaderElectionRecord
 | 
						observedRecord LeaderElectionRecord
 | 
				
			||||||
	observedTime   time.Time
 | 
						observedTime   time.Time
 | 
				
			||||||
 | 
						// used to implement OnNewLeader(), may lag slightly from the
 | 
				
			||||||
 | 
						// value observedRecord.HolderIdentity if the transistion has
 | 
				
			||||||
 | 
						// not yet been reported.
 | 
				
			||||||
 | 
						reportedLeader string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// LeaderElectionRecord is the record that is stored in the leader election annotation.
 | 
					// LeaderElectionRecord is the record that is stored in the leader election annotation.
 | 
				
			||||||
@@ -182,6 +189,7 @@ func (le *LeaderElector) acquire() {
 | 
				
			|||||||
	stop := make(chan struct{})
 | 
						stop := make(chan struct{})
 | 
				
			||||||
	util.Until(func() {
 | 
						util.Until(func() {
 | 
				
			||||||
		succeeded := le.tryAcquireOrRenew()
 | 
							succeeded := le.tryAcquireOrRenew()
 | 
				
			||||||
 | 
							le.maybeReportTransition()
 | 
				
			||||||
		if !succeeded {
 | 
							if !succeeded {
 | 
				
			||||||
			glog.V(4).Infof("failed to renew lease %v/%v", le.config.EndpointsMeta.Namespace, le.config.EndpointsMeta.Name)
 | 
								glog.V(4).Infof("failed to renew lease %v/%v", le.config.EndpointsMeta.Namespace, le.config.EndpointsMeta.Name)
 | 
				
			||||||
			time.Sleep(wait.Jitter(le.config.RetryPeriod, JitterFactor))
 | 
								time.Sleep(wait.Jitter(le.config.RetryPeriod, JitterFactor))
 | 
				
			||||||
@@ -200,6 +208,7 @@ func (le *LeaderElector) renew() {
 | 
				
			|||||||
		err := wait.Poll(le.config.RetryPeriod, le.config.RenewDeadline, func() (bool, error) {
 | 
							err := wait.Poll(le.config.RetryPeriod, le.config.RenewDeadline, func() (bool, error) {
 | 
				
			||||||
			return le.tryAcquireOrRenew(), nil
 | 
								return le.tryAcquireOrRenew(), nil
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
 | 
							le.maybeReportTransition()
 | 
				
			||||||
		if err == nil {
 | 
							if err == nil {
 | 
				
			||||||
			glog.V(4).Infof("succesfully renewed lease %v/%v", le.config.EndpointsMeta.Namespace, le.config.EndpointsMeta.Name)
 | 
								glog.V(4).Infof("succesfully renewed lease %v/%v", le.config.EndpointsMeta.Namespace, le.config.EndpointsMeta.Name)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
@@ -296,3 +305,13 @@ func (le *LeaderElector) tryAcquireOrRenew() bool {
 | 
				
			|||||||
	le.observedTime = time.Now()
 | 
						le.observedTime = time.Now()
 | 
				
			||||||
	return true
 | 
						return true
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (l *LeaderElector) maybeReportTransition() {
 | 
				
			||||||
 | 
						if l.observedRecord.HolderIdentity == l.reportedLeader {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						l.reportedLeader = l.observedRecord.HolderIdentity
 | 
				
			||||||
 | 
						if l.config.Callbacks.OnNewLeader != nil {
 | 
				
			||||||
 | 
							go l.config.Callbacks.OnNewLeader(l.reportedLeader)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,6 +22,7 @@ package leaderelection
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -195,14 +196,24 @@ func TestTryAcquireOrRenew(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	lec := LeaderElectionConfig{
 | 
					 | 
				
			||||||
		EndpointsMeta: api.ObjectMeta{Namespace: "foo", Name: "bar"},
 | 
					 | 
				
			||||||
		Identity:      "baz",
 | 
					 | 
				
			||||||
		EventRecorder: &record.FakeRecorder{},
 | 
					 | 
				
			||||||
		LeaseDuration: 10 * time.Second,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for i, test := range tests {
 | 
						for i, test := range tests {
 | 
				
			||||||
 | 
							// OnNewLeader is called async so we have to wait for it.
 | 
				
			||||||
 | 
							var wg sync.WaitGroup
 | 
				
			||||||
 | 
							wg.Add(1)
 | 
				
			||||||
 | 
							var reportedLeader string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							lec := LeaderElectionConfig{
 | 
				
			||||||
 | 
								EndpointsMeta: api.ObjectMeta{Namespace: "foo", Name: "bar"},
 | 
				
			||||||
 | 
								Identity:      "baz",
 | 
				
			||||||
 | 
								EventRecorder: &record.FakeRecorder{},
 | 
				
			||||||
 | 
								LeaseDuration: 10 * time.Second,
 | 
				
			||||||
 | 
								Callbacks: LeaderCallbacks{
 | 
				
			||||||
 | 
									OnNewLeader: func(l string) {
 | 
				
			||||||
 | 
										defer wg.Done()
 | 
				
			||||||
 | 
										reportedLeader = l
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		c := &testclient.Fake{}
 | 
							c := &testclient.Fake{}
 | 
				
			||||||
		for _, reactor := range test.reactors {
 | 
							for _, reactor := range test.reactors {
 | 
				
			||||||
			c.AddReactor(reactor.verb, "endpoints", reactor.reaction)
 | 
								c.AddReactor(reactor.verb, "endpoints", reactor.reaction)
 | 
				
			||||||
@@ -237,5 +248,11 @@ func TestTryAcquireOrRenew(t *testing.T) {
 | 
				
			|||||||
		if !test.transitionLeader && le.observedRecord.LeaderTransitions != 0 {
 | 
							if !test.transitionLeader && le.observedRecord.LeaderTransitions != 0 {
 | 
				
			||||||
			t.Errorf("[%v]leader should not have transitioned but did", i)
 | 
								t.Errorf("[%v]leader should not have transitioned but did", i)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							le.maybeReportTransition()
 | 
				
			||||||
 | 
							wg.Wait()
 | 
				
			||||||
 | 
							if reportedLeader != test.outHolder {
 | 
				
			||||||
 | 
								t.Errorf("[%v]reported leader was not the new leader. expected %q, got %q", i, test.outHolder, reportedLeader)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user