1
16
17 package leaderelection
18
19 import (
20 "context"
21 "fmt"
22 "testing"
23 "time"
24
25 "net/http"
26
27 rl "k8s.io/client-go/tools/leaderelection/resourcelock"
28 testingclock "k8s.io/utils/clock/testing"
29 )
30
31 type fakeLock struct {
32 identity string
33 }
34
35
36 func (fl *fakeLock) Get(ctx context.Context) (ler *rl.LeaderElectionRecord, rawRecord []byte, err error) {
37 return nil, nil, nil
38 }
39
40
41 func (fl *fakeLock) Create(ctx context.Context, ler rl.LeaderElectionRecord) error {
42 return nil
43 }
44
45
46 func (fl *fakeLock) Update(ctx context.Context, ler rl.LeaderElectionRecord) error {
47 return nil
48 }
49
50
51 func (fl *fakeLock) RecordEvent(string) {}
52
53
54 func (fl *fakeLock) Identity() string {
55 return fl.identity
56 }
57
58
59 func (fl *fakeLock) Describe() string {
60 return "Dummy implementation of lock for testing"
61 }
62
63
64 func TestLeaderElectionHealthChecker(t *testing.T) {
65 current := time.Now()
66 req := &http.Request{}
67
68 tests := []struct {
69 description string
70 expected error
71 adaptorTimeout time.Duration
72 elector *LeaderElector
73 }{
74 {
75 description: "call check before leader elector initialized",
76 expected: nil,
77 adaptorTimeout: time.Second * 20,
78 elector: nil,
79 },
80 {
81 description: "call check when the lease is far expired",
82 expected: fmt.Errorf("failed election to renew leadership on lease %s", "foo"),
83 adaptorTimeout: time.Second * 20,
84 elector: &LeaderElector{
85 config: LeaderElectionConfig{
86 Lock: &fakeLock{identity: "healthTest"},
87 LeaseDuration: time.Minute,
88 Name: "foo",
89 },
90 observedRecord: rl.LeaderElectionRecord{
91 HolderIdentity: "healthTest",
92 },
93 observedTime: current,
94 clock: testingclock.NewFakeClock(current.Add(time.Hour)),
95 },
96 },
97 {
98 description: "call check when the lease is far expired but held by another server",
99 expected: nil,
100 adaptorTimeout: time.Second * 20,
101 elector: &LeaderElector{
102 config: LeaderElectionConfig{
103 Lock: &fakeLock{identity: "healthTest"},
104 LeaseDuration: time.Minute,
105 Name: "foo",
106 },
107 observedRecord: rl.LeaderElectionRecord{
108 HolderIdentity: "otherServer",
109 },
110 observedTime: current,
111 clock: testingclock.NewFakeClock(current.Add(time.Hour)),
112 },
113 },
114 {
115 description: "call check when the lease is not expired",
116 expected: nil,
117 adaptorTimeout: time.Second * 20,
118 elector: &LeaderElector{
119 config: LeaderElectionConfig{
120 Lock: &fakeLock{identity: "healthTest"},
121 LeaseDuration: time.Minute,
122 Name: "foo",
123 },
124 observedRecord: rl.LeaderElectionRecord{
125 HolderIdentity: "healthTest",
126 },
127 observedTime: current,
128 clock: testingclock.NewFakeClock(current),
129 },
130 },
131 {
132 description: "call check when the lease is expired but inside the timeout",
133 expected: nil,
134 adaptorTimeout: time.Second * 20,
135 elector: &LeaderElector{
136 config: LeaderElectionConfig{
137 Lock: &fakeLock{identity: "healthTest"},
138 LeaseDuration: time.Minute,
139 Name: "foo",
140 },
141 observedRecord: rl.LeaderElectionRecord{
142 HolderIdentity: "healthTest",
143 },
144 observedTime: current,
145 clock: testingclock.NewFakeClock(current.Add(time.Minute).Add(time.Second)),
146 },
147 },
148 }
149
150 for _, test := range tests {
151 adaptor := NewLeaderHealthzAdaptor(test.adaptorTimeout)
152 if adaptor.le != nil {
153 t.Errorf("[%s] leaderChecker started with a LeaderElector %v", test.description, adaptor.le)
154 }
155 if test.elector != nil {
156 test.elector.config.WatchDog = adaptor
157 adaptor.SetLeaderElection(test.elector)
158 if adaptor.le == nil {
159 t.Errorf("[%s] adaptor failed to set the LeaderElector", test.description)
160 }
161 }
162 err := adaptor.Check(req)
163 if test.expected == nil {
164 if err == nil {
165 continue
166 }
167 t.Errorf("[%s] called check, expected no error but received \"%v\"", test.description, err)
168 } else {
169 if err == nil {
170 t.Errorf("[%s] called check and failed to received the expected error \"%v\"", test.description, test.expected)
171 }
172 if err.Error() != test.expected.Error() {
173 t.Errorf("[%s] called check, expected %v, received %v", test.description, test.expected, err)
174 }
175 }
176 }
177 }
178
View as plain text