@@ -10,6 +10,7 @@ import (
10
10
11
11
. "github.com/onsi/ginkgo/v2"
12
12
. "github.com/onsi/gomega"
13
+ coordination "k8s.io/api/coordination/v1"
13
14
core "k8s.io/api/core/v1"
14
15
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
15
16
"k8s.io/apimachinery/pkg/types"
@@ -22,7 +23,8 @@ import (
22
23
const (
23
24
// FIXME(bjee19): Find an automated way to keep the version updated here similar to dependabot.
24
25
// https://github.com/nginxinc/nginx-gateway-fabric/issues/1665
25
- debugImage = "busybox:1.28"
26
+ debugImage = "busybox:1.28"
27
+
26
28
teaURL = "https://cafe.example.com/tea"
27
29
coffeeURL = "http://cafe.example.com/coffee"
28
30
nginxContainerName = "nginx"
@@ -67,15 +69,20 @@ var _ = Describe("Graceful Recovery test", Ordered, Label("nfr", "graceful-recov
67
69
Expect (err ).ToNot (HaveOccurred ())
68
70
Expect (podNames ).ToNot (BeEmpty ())
69
71
72
+ leaseName , err := getLeaderElectionLeaseHolderName ()
73
+ Expect (err ).ToNot (HaveOccurred ())
74
+
70
75
output , err := restartNGFProcess (ngfContainerName )
71
76
Expect (err ).ToNot (HaveOccurred (), string (output ))
72
77
73
78
checkContainerLogsForErrors (podNames [0 ])
74
79
80
+ err = waitForLeaderLeaseToChange (leaseName )
81
+ Expect (err ).ToNot (HaveOccurred ())
82
+
75
83
err = waitForWorkingTraffic ()
76
84
Expect (err ).ToNot (HaveOccurred ())
77
85
78
- // I tried just deleting the routes and ran into a bunch of issues, deleting all the files was better
79
86
Expect (resourceManager .DeleteFromFiles (files , ns .Name )).To (Succeed ())
80
87
81
88
err = waitForFailingTraffic ()
@@ -93,11 +100,17 @@ var _ = Describe("Graceful Recovery test", Ordered, Label("nfr", "graceful-recov
93
100
Expect (err ).ToNot (HaveOccurred ())
94
101
Expect (podNames ).ToNot (BeEmpty ())
95
102
103
+ leaseName , err := getLeaderElectionLeaseHolderName ()
104
+ Expect (err ).ToNot (HaveOccurred ())
105
+
96
106
output , err := restartNginxContainer (nginxContainerName )
97
107
Expect (err ).ToNot (HaveOccurred (), string (output ))
98
108
99
109
checkContainerLogsForErrors (podNames [0 ])
100
110
111
+ err = waitForLeaderLeaseToChange (leaseName )
112
+ Expect (err ).ToNot (HaveOccurred ())
113
+
101
114
err = waitForWorkingTraffic ()
102
115
Expect (err ).ToNot (HaveOccurred ())
103
116
@@ -231,10 +244,10 @@ func waitForWorkingTraffic() error {
231
244
500 * time .Millisecond ,
232
245
true , /* poll immediately */
233
246
func (_ context.Context ) (bool , error ) {
234
- if err := expectRequest (teaURL , address , http . StatusOK , "URI: /tea" ); err != nil {
247
+ if err := expectRequestToSucceed (teaURL , address , "URI: /tea" ); err != nil {
235
248
return false , nil
236
249
}
237
- if err := expectRequest (coffeeURL , address , http . StatusOK , "URI: /coffee" ); err != nil {
250
+ if err := expectRequestToSucceed (coffeeURL , address , "URI: /coffee" ); err != nil {
238
251
return false , nil
239
252
}
240
253
return true , nil
@@ -246,39 +259,53 @@ func waitForFailingTraffic() error {
246
259
ctx , cancel := context .WithTimeout (context .Background (), timeoutConfig .RequestTimeout )
247
260
defer cancel ()
248
261
262
+ //nolint:nilerr
249
263
return wait .PollUntilContextCancel (
250
264
ctx ,
251
265
500 * time .Millisecond ,
252
266
true , /* poll immediately */
253
267
func (_ context.Context ) (bool , error ) {
254
- if err := expectRequest (teaURL , address , 0 , "URI: /tea" ); err = = nil {
268
+ if err := expectRequestToFail (teaURL , address , "URI: /tea" ); err ! = nil {
255
269
return false , nil
256
270
}
257
- if err := expectRequest (coffeeURL , address , 0 , "URI: /coffee" ); err = = nil {
271
+ if err := expectRequestToFail (coffeeURL , address , "URI: /coffee" ); err ! = nil {
258
272
return false , nil
259
273
}
260
274
return true , nil
261
275
},
262
276
)
263
277
}
264
278
265
- func expectRequest (appURL string , address string , httpStatus int , responseBodyMessage string ) error {
279
+ func expectRequestToSucceed (appURL string , address string , responseBodyMessage string ) error {
266
280
status , body , err := framework .Get (appURL , address , timeoutConfig .RequestTimeout )
267
- if status != httpStatus {
268
- return errors .New ("http statuses were not equal " )
281
+ if status != http . StatusOK {
282
+ return errors .New ("http status was not 200 " )
269
283
}
270
- if httpStatus == http .StatusOK {
271
- if ! strings .Contains (body , responseBodyMessage ) {
272
- return errors .New ("expected response body to contain body message" )
273
- }
274
- } else {
275
- if strings .Contains (body , responseBodyMessage ) {
276
- return errors .New ("expected response body to not contain body message" )
277
- }
284
+
285
+ if ! strings .Contains (body , responseBodyMessage ) {
286
+ return errors .New ("expected response body to contain correct body message" )
278
287
}
288
+
279
289
return err
280
290
}
281
291
292
+ func expectRequestToFail (appURL string , address string , responseBodyMessage string ) error {
293
+ status , body , err := framework .Get (appURL , address , timeoutConfig .RequestTimeout )
294
+ if status != 0 {
295
+ return errors .New ("expected http status to be 0" )
296
+ }
297
+
298
+ if strings .Contains (body , responseBodyMessage ) {
299
+ return errors .New ("expected response body to not contain correct body message" )
300
+ }
301
+
302
+ if err == nil {
303
+ return errors .New ("expected request to error" )
304
+ }
305
+
306
+ return nil
307
+ }
308
+
282
309
func checkContainerLogsForErrors (ngfPodName string ) {
283
310
sinceSeconds := int64 (15 )
284
311
logs , err := resourceManager .GetPodLogs (
@@ -297,3 +324,40 @@ func checkContainerLogsForErrors(ngfPodName string) {
297
324
Expect (err ).ToNot (HaveOccurred ())
298
325
Expect (logs ).ToNot (ContainSubstring ("error" ), logs )
299
326
}
327
+
328
+ func waitForLeaderLeaseToChange (originalLeaseName string ) error {
329
+ leaseCtx , leaseCancel := context .WithTimeout (context .Background (), 1 * time .Minute )
330
+ defer leaseCancel ()
331
+
332
+ //nolint:nilerr
333
+ return wait .PollUntilContextCancel (
334
+ leaseCtx ,
335
+ 500 * time .Millisecond ,
336
+ true , /* poll immediately */
337
+ func (_ context.Context ) (bool , error ) {
338
+ leaseName , err := getLeaderElectionLeaseHolderName ()
339
+ if err != nil {
340
+ return false , nil
341
+ }
342
+
343
+ if originalLeaseName != leaseName {
344
+ return true , nil
345
+ }
346
+
347
+ return false , nil
348
+ },
349
+ )
350
+ }
351
+
352
+ func getLeaderElectionLeaseHolderName () (string , error ) {
353
+ ctx , cancel := context .WithTimeout (context .Background (), timeoutConfig .GetTimeout )
354
+ defer cancel ()
355
+
356
+ var lease coordination.Lease
357
+ key := types.NamespacedName {Name : "ngf-test-nginx-gateway-fabric-leader-election" , Namespace : ngfNamespace }
358
+
359
+ if err := k8sClient .Get (ctx , key , & lease ); err != nil {
360
+ return "" , errors .New ("could not retrieve leader election lease" )
361
+ }
362
+ return * lease .Spec .HolderIdentity , nil
363
+ }
0 commit comments