Skip to content

Commit 5053776

Browse files
zachomediak8s-publishing-bot
authored andcommitted
Add lease release tests in leader election
Kubernetes-commit: 9030fc47a24f630770b6966bc2b08153c57b4cc8
1 parent 228a223 commit 5053776

File tree

1 file changed

+155
-0
lines changed

1 file changed

+155
-0
lines changed

tools/leaderelection/leaderelection_test.go

+155
Original file line numberDiff line numberDiff line change
@@ -917,3 +917,158 @@ func TestTryAcquireOrRenewEndpointsLeases(t *testing.T) {
917917
func TestTryAcquireOrRenewConfigMapsLeases(t *testing.T) {
918918
testTryAcquireOrRenewMultiLock(t, "configmapsleases")
919919
}
920+
921+
func testReleaseLease(t *testing.T, objectType string) {
922+
tests := []struct {
923+
name string
924+
observedRecord rl.LeaderElectionRecord
925+
observedTime time.Time
926+
reactors []Reactor
927+
928+
expectSuccess bool
929+
transitionLeader bool
930+
outHolder string
931+
}{
932+
{
933+
name: "release acquired lock from no object",
934+
reactors: []Reactor{
935+
{
936+
verb: "get",
937+
objectType: objectType,
938+
reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) {
939+
return true, nil, errors.NewNotFound(action.(fakeclient.GetAction).GetResource().GroupResource(), action.(fakeclient.GetAction).GetName())
940+
},
941+
},
942+
{
943+
verb: "create",
944+
objectType: objectType,
945+
reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) {
946+
return true, action.(fakeclient.CreateAction).GetObject(), nil
947+
},
948+
},
949+
{
950+
verb: "update",
951+
objectType: objectType,
952+
reaction: func(action fakeclient.Action) (handled bool, ret runtime.Object, err error) {
953+
return true, action.(fakeclient.UpdateAction).GetObject(), nil
954+
},
955+
},
956+
},
957+
expectSuccess: true,
958+
outHolder: "",
959+
},
960+
}
961+
962+
for i := range tests {
963+
test := &tests[i]
964+
t.Run(test.name, func(t *testing.T) {
965+
// OnNewLeader is called async so we have to wait for it.
966+
var wg sync.WaitGroup
967+
wg.Add(1)
968+
var reportedLeader string
969+
var lock rl.Interface
970+
971+
objectMeta := metav1.ObjectMeta{Namespace: "foo", Name: "bar"}
972+
resourceLockConfig := rl.ResourceLockConfig{
973+
Identity: "baz",
974+
EventRecorder: &record.FakeRecorder{},
975+
}
976+
c := &fake.Clientset{}
977+
for _, reactor := range test.reactors {
978+
c.AddReactor(reactor.verb, objectType, reactor.reaction)
979+
}
980+
c.AddReactor("*", "*", func(action fakeclient.Action) (bool, runtime.Object, error) {
981+
t.Errorf("unreachable action. testclient called too many times: %+v", action)
982+
return true, nil, fmt.Errorf("unreachable action")
983+
})
984+
985+
switch objectType {
986+
case "endpoints":
987+
lock = &rl.EndpointsLock{
988+
EndpointsMeta: objectMeta,
989+
LockConfig: resourceLockConfig,
990+
Client: c.CoreV1(),
991+
}
992+
case "configmaps":
993+
lock = &rl.ConfigMapLock{
994+
ConfigMapMeta: objectMeta,
995+
LockConfig: resourceLockConfig,
996+
Client: c.CoreV1(),
997+
}
998+
case "leases":
999+
lock = &rl.LeaseLock{
1000+
LeaseMeta: objectMeta,
1001+
LockConfig: resourceLockConfig,
1002+
Client: c.CoordinationV1(),
1003+
}
1004+
}
1005+
1006+
lec := LeaderElectionConfig{
1007+
Lock: lock,
1008+
LeaseDuration: 10 * time.Second,
1009+
Callbacks: LeaderCallbacks{
1010+
OnNewLeader: func(l string) {
1011+
defer wg.Done()
1012+
reportedLeader = l
1013+
},
1014+
},
1015+
}
1016+
observedRawRecord := GetRawRecordOrDie(t, objectType, test.observedRecord)
1017+
le := &LeaderElector{
1018+
config: lec,
1019+
observedRecord: test.observedRecord,
1020+
observedRawRecord: observedRawRecord,
1021+
observedTime: test.observedTime,
1022+
clock: clock.RealClock{},
1023+
}
1024+
if !le.tryAcquireOrRenew(context.Background()) {
1025+
t.Errorf("unexpected result of tryAcquireOrRenew: [succeeded=%v]", true)
1026+
}
1027+
1028+
le.maybeReportTransition()
1029+
1030+
// Wait for a response to the leader transition, and add 1 so that we can track the final transition.
1031+
wg.Wait()
1032+
wg.Add(1)
1033+
1034+
if test.expectSuccess != le.release() {
1035+
t.Errorf("unexpected result of release: [succeeded=%v]", !test.expectSuccess)
1036+
}
1037+
1038+
le.observedRecord.AcquireTime = metav1.Time{}
1039+
le.observedRecord.RenewTime = metav1.Time{}
1040+
if le.observedRecord.HolderIdentity != test.outHolder {
1041+
t.Errorf("expected holder:\n\t%+v\ngot:\n\t%+v", test.outHolder, le.observedRecord.HolderIdentity)
1042+
}
1043+
if len(test.reactors) != len(c.Actions()) {
1044+
t.Errorf("wrong number of api interactions")
1045+
}
1046+
if test.transitionLeader && le.observedRecord.LeaderTransitions != 1 {
1047+
t.Errorf("leader should have transitioned but did not")
1048+
}
1049+
if !test.transitionLeader && le.observedRecord.LeaderTransitions != 0 {
1050+
t.Errorf("leader should not have transitioned but did")
1051+
}
1052+
le.maybeReportTransition()
1053+
wg.Wait()
1054+
if reportedLeader != test.outHolder {
1055+
t.Errorf("reported leader was not the new leader. expected %q, got %q", test.outHolder, reportedLeader)
1056+
}
1057+
})
1058+
}
1059+
}
1060+
1061+
// Will test leader election using endpoints as the resource
1062+
func TestReleaseLeaseEndpoints(t *testing.T) {
1063+
testReleaseLease(t, "endpoints")
1064+
}
1065+
1066+
// Will test leader election using endpoints as the resource
1067+
func TestReleaseLeaseConfigMaps(t *testing.T) {
1068+
testReleaseLease(t, "configmaps")
1069+
}
1070+
1071+
// Will test leader election using endpoints as the resource
1072+
func TestReleaseLeaseLeases(t *testing.T) {
1073+
testReleaseLease(t, "leases")
1074+
}

0 commit comments

Comments
 (0)