@@ -26,6 +26,7 @@ import (
26
26
"k8s.io/api/core/v1"
27
27
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
28
28
"k8s.io/apimachinery/pkg/runtime"
29
+ "k8s.io/apimachinery/pkg/util/clock"
29
30
"k8s.io/apimachinery/pkg/util/sets"
30
31
"k8s.io/client-go/informers"
31
32
clientset "k8s.io/client-go/kubernetes"
@@ -252,48 +253,125 @@ func TestDefaultErrorFunc(t *testing.T) {
252
253
client := fake .NewSimpleClientset (& v1.PodList {Items : []v1.Pod {* testPod }})
253
254
stopCh := make (chan struct {})
254
255
defer close (stopCh )
255
- queue := & internalqueue.FIFO {FIFO : cache .NewFIFO (cache .MetaNamespaceKeyFunc )}
256
+
257
+ timestamp := time .Now ()
258
+ queue := internalqueue .NewPriorityQueueWithClock (nil , clock .NewFakeClock (timestamp ))
256
259
schedulerCache := internalcache .New (30 * time .Second , stopCh )
257
- podBackoff := internalqueue .NewPodBackoffMap (1 * time .Second , 60 * time .Second )
258
- errFunc := MakeDefaultErrorFunc (client , podBackoff , queue , schedulerCache , stopCh )
260
+ errFunc := MakeDefaultErrorFunc (client , queue , schedulerCache , stopCh )
259
261
262
+ // Trigger error handling again to put the pod in unschedulable queue
260
263
errFunc (testPod , nil )
261
264
262
- for {
263
- // This is a terrible way to do this but I plan on replacing this
264
- // whole error handling system in the future. The test will time
265
- // out if something doesn't work.
266
- time .Sleep (10 * time .Millisecond )
267
- got , exists , _ := queue . Get ( testPod )
268
- if ! exists {
265
+ // Try up to a minute to retrieve the error pod from priority queue
266
+ foundPodFlag := false
267
+ maxIterations := 10 * 60
268
+ for i := 0 ; i < maxIterations ; i ++ {
269
+ time .Sleep (100 * time .Millisecond )
270
+ got := getPodfromPriorityQueue ( queue , testPod )
271
+ if got == nil {
269
272
continue
270
273
}
271
- requestReceived := false
272
- actions := client .Actions ()
273
- for _ , a := range actions {
274
- if a .GetVerb () == "get" {
275
- getAction , ok := a .(clienttesting.GetAction )
276
- if ! ok {
277
- t .Errorf ("Can't cast action object to GetAction interface" )
278
- break
279
- }
280
- name := getAction .GetName ()
281
- ns := a .GetNamespace ()
282
- if name != "foo" || ns != "bar" {
283
- t .Errorf ("Expected name %s namespace %s, got %s %s" ,
284
- "foo" , "bar" , name , ns )
285
- }
286
- requestReceived = true
287
- }
274
+
275
+ testClientGetPodRequest (client , t , testPod .Namespace , testPod .Name )
276
+
277
+ if e , a := testPod , got ; ! reflect .DeepEqual (e , a ) {
278
+ t .Errorf ("Expected %v, got %v" , e , a )
288
279
}
289
- if ! requestReceived {
290
- t .Errorf ("Get pod request not received" )
280
+
281
+ foundPodFlag = true
282
+ break
283
+ }
284
+
285
+ if ! foundPodFlag {
286
+ t .Errorf ("Failed to get pod from the unschedulable queue after waiting for a minute: %v" , testPod )
287
+ }
288
+
289
+ // Remove the pod from priority queue to test putting error
290
+ // pod in backoff queue.
291
+ queue .Delete (testPod )
292
+
293
+ // Trigger a move request
294
+ queue .MoveAllToActiveQueue ()
295
+
296
+ // Trigger error handling again to put the pod in backoff queue
297
+ errFunc (testPod , nil )
298
+
299
+ foundPodFlag = false
300
+ for i := 0 ; i < maxIterations ; i ++ {
301
+ time .Sleep (100 * time .Millisecond )
302
+ // The pod should be found from backoff queue at this time
303
+ got := getPodfromPriorityQueue (queue , testPod )
304
+ if got == nil {
305
+ continue
291
306
}
307
+
308
+ testClientGetPodRequest (client , t , testPod .Namespace , testPod .Name )
309
+
292
310
if e , a := testPod , got ; ! reflect .DeepEqual (e , a ) {
293
311
t .Errorf ("Expected %v, got %v" , e , a )
294
312
}
313
+
314
+ foundPodFlag = true
295
315
break
296
316
}
317
+
318
+ if ! foundPodFlag {
319
+ t .Errorf ("Failed to get pod from the backoff queue after waiting for a minute: %v" , testPod )
320
+ }
321
+ }
322
+
323
+ // getPodfromPriorityQueue is the function used in the TestDefaultErrorFunc test to get
324
+ // the specific pod from the given priority queue. It returns the found pod in the priority queue.
325
+ func getPodfromPriorityQueue (queue * internalqueue.PriorityQueue , pod * v1.Pod ) * v1.Pod {
326
+ podList := queue .PendingPods ()
327
+ if len (podList ) == 0 {
328
+ return nil
329
+ }
330
+
331
+ queryPodKey , err := cache .MetaNamespaceKeyFunc (pod )
332
+ if err != nil {
333
+ return nil
334
+ }
335
+
336
+ for _ , foundPod := range podList {
337
+ foundPodKey , err := cache .MetaNamespaceKeyFunc (foundPod )
338
+ if err != nil {
339
+ return nil
340
+ }
341
+
342
+ if foundPodKey == queryPodKey {
343
+ return foundPod
344
+ }
345
+ }
346
+
347
+ return nil
348
+ }
349
+
350
+ // testClientGetPodRequest function provides a routine used by TestDefaultErrorFunc test.
351
+ // It tests whether the fake client can receive request and correctly "get" the namespace
352
+ // and name of the error pod.
353
+ func testClientGetPodRequest (client * fake.Clientset , t * testing.T , podNs string , podName string ) {
354
+ requestReceived := false
355
+ actions := client .Actions ()
356
+ for _ , a := range actions {
357
+ if a .GetVerb () == "get" {
358
+ getAction , ok := a .(clienttesting.GetAction )
359
+ if ! ok {
360
+ t .Errorf ("Can't cast action object to GetAction interface" )
361
+ break
362
+ }
363
+ name := getAction .GetName ()
364
+ ns := a .GetNamespace ()
365
+ if name != podName || ns != podNs {
366
+ t .Errorf ("Expected name %s namespace %s, got %s %s" ,
367
+ podName , podNs , name , ns )
368
+ }
369
+ requestReceived = true
370
+ }
371
+ }
372
+ if ! requestReceived {
373
+ t .Errorf ("Get pod request not received" )
374
+ }
297
375
}
298
376
299
377
func TestBind (t * testing.T ) {
0 commit comments