@@ -27,6 +27,7 @@ import (
27
27
v1 "k8s.io/api/core/v1"
28
28
"k8s.io/apimachinery/pkg/fields"
29
29
"k8s.io/apimachinery/pkg/labels"
30
+ "k8s.io/apimachinery/pkg/types"
30
31
"k8s.io/client-go/kubernetes/fake"
31
32
"k8s.io/kubernetes/pkg/controller/testutil"
32
33
@@ -83,10 +84,20 @@ func (p *podHolder) setPod(pod *v1.Pod) {
83
84
}
84
85
85
86
type nodeHolder struct {
87
+ lock sync.Mutex
88
+
86
89
node * v1.Node
87
90
}
88
91
92
+ func (n * nodeHolder ) setNode (node * v1.Node ) {
93
+ n .lock .Lock ()
94
+ defer n .lock .Unlock ()
95
+ n .node = node
96
+ }
97
+
89
98
func (n * nodeHolder ) getNode (name string ) (* v1.Node , error ) {
99
+ n .lock .Lock ()
100
+ defer n .lock .Unlock ()
90
101
return n .node , nil
91
102
}
92
103
@@ -362,7 +373,7 @@ func TestCreateNode(t *testing.T) {
362
373
for _ , item := range testCases {
363
374
stopCh := make (chan struct {})
364
375
fakeClientset := fake .NewSimpleClientset (& v1.PodList {Items : item .pods })
365
- controller := NewNoExecuteTaintManager (fakeClientset , getPodFromClientset (fakeClientset ), (& nodeHolder {item .node }).getNode , getPodsAssignedToNode (fakeClientset ))
376
+ controller := NewNoExecuteTaintManager (fakeClientset , getPodFromClientset (fakeClientset ), (& nodeHolder {node : item .node }).getNode , getPodsAssignedToNode (fakeClientset ))
366
377
controller .recorder = testutil .NewFakeRecorder ()
367
378
go controller .Run (stopCh )
368
379
controller .NodeUpdated (nil , item .node )
@@ -483,7 +494,7 @@ func TestUpdateNode(t *testing.T) {
483
494
for _ , item := range testCases {
484
495
stopCh := make (chan struct {})
485
496
fakeClientset := fake .NewSimpleClientset (& v1.PodList {Items : item .pods })
486
- controller := NewNoExecuteTaintManager (fakeClientset , getPodFromClientset (fakeClientset ), (& nodeHolder {item .newNode }).getNode , getPodsAssignedToNode (fakeClientset ))
497
+ controller := NewNoExecuteTaintManager (fakeClientset , getPodFromClientset (fakeClientset ), (& nodeHolder {node : item .newNode }).getNode , getPodsAssignedToNode (fakeClientset ))
487
498
controller .recorder = testutil .NewFakeRecorder ()
488
499
go controller .Run (stopCh )
489
500
controller .NodeUpdated (item .oldNode , item .newNode )
@@ -506,6 +517,74 @@ func TestUpdateNode(t *testing.T) {
506
517
}
507
518
}
508
519
520
+ func TestUpdateNodeWithMultipleTaints (t * testing.T ) {
521
+ taint1 := createNoExecuteTaint (1 )
522
+ taint2 := createNoExecuteTaint (2 )
523
+
524
+ minute := int64 (60 )
525
+ pod := testutil .NewPod ("pod1" , "node1" )
526
+ pod .Spec .Tolerations = []v1.Toleration {
527
+ {Key : taint1 .Key , Operator : v1 .TolerationOpExists , Effect : v1 .TaintEffectNoExecute },
528
+ {Key : taint2 .Key , Operator : v1 .TolerationOpExists , Effect : v1 .TaintEffectNoExecute , TolerationSeconds : & minute },
529
+ }
530
+ podNamespacedName := types.NamespacedName {Namespace : pod .Namespace , Name : pod .Name }
531
+
532
+ untaintedNode := testutil .NewNode ("node1" )
533
+
534
+ doubleTaintedNode := testutil .NewNode ("node1" )
535
+ doubleTaintedNode .Spec .Taints = []v1.Taint {taint1 , taint2 }
536
+
537
+ singleTaintedNode := testutil .NewNode ("node1" )
538
+ singleTaintedNode .Spec .Taints = []v1.Taint {taint1 }
539
+
540
+ stopCh := make (chan struct {})
541
+ fakeClientset := fake .NewSimpleClientset (pod )
542
+ holder := & nodeHolder {node : untaintedNode }
543
+ controller := NewNoExecuteTaintManager (fakeClientset , getPodFromClientset (fakeClientset ), (holder ).getNode , getPodsAssignedToNode (fakeClientset ))
544
+ controller .recorder = testutil .NewFakeRecorder ()
545
+ go controller .Run (stopCh )
546
+
547
+ // no taint
548
+ holder .setNode (untaintedNode )
549
+ controller .handleNodeUpdate (nodeUpdateItem {"node1" })
550
+ // verify pod is not queued for deletion
551
+ if controller .taintEvictionQueue .GetWorkerUnsafe (podNamespacedName .String ()) != nil {
552
+ t .Fatalf ("pod queued for deletion with no taints" )
553
+ }
554
+
555
+ // no taint -> infinitely tolerated taint
556
+ holder .setNode (singleTaintedNode )
557
+ controller .handleNodeUpdate (nodeUpdateItem {"node1" })
558
+ // verify pod is not queued for deletion
559
+ if controller .taintEvictionQueue .GetWorkerUnsafe (podNamespacedName .String ()) != nil {
560
+ t .Fatalf ("pod queued for deletion with permanently tolerated taint" )
561
+ }
562
+
563
+ // infinitely tolerated taint -> temporarily tolerated taint
564
+ holder .setNode (doubleTaintedNode )
565
+ controller .handleNodeUpdate (nodeUpdateItem {"node1" })
566
+ // verify pod is queued for deletion
567
+ if controller .taintEvictionQueue .GetWorkerUnsafe (podNamespacedName .String ()) == nil {
568
+ t .Fatalf ("pod not queued for deletion after addition of temporarily tolerated taint" )
569
+ }
570
+
571
+ // temporarily tolerated taint -> infinitely tolerated taint
572
+ holder .setNode (singleTaintedNode )
573
+ controller .handleNodeUpdate (nodeUpdateItem {"node1" })
574
+ // verify pod is not queued for deletion
575
+ if controller .taintEvictionQueue .GetWorkerUnsafe (podNamespacedName .String ()) != nil {
576
+ t .Fatalf ("pod queued for deletion after removal of temporarily tolerated taint" )
577
+ }
578
+
579
+ // verify pod is not deleted
580
+ for _ , action := range fakeClientset .Actions () {
581
+ if action .GetVerb () == "delete" && action .GetResource ().Resource == "pods" {
582
+ t .Error ("Unexpected deletion" )
583
+ }
584
+ }
585
+ close (stopCh )
586
+ }
587
+
509
588
func TestUpdateNodeWithMultiplePods (t * testing.T ) {
510
589
testCases := []struct {
511
590
description string
@@ -549,7 +628,7 @@ func TestUpdateNodeWithMultiplePods(t *testing.T) {
549
628
stopCh := make (chan struct {})
550
629
fakeClientset := fake .NewSimpleClientset (& v1.PodList {Items : item .pods })
551
630
sort .Sort (item .expectedDeleteTimes )
552
- controller := NewNoExecuteTaintManager (fakeClientset , getPodFromClientset (fakeClientset ), (& nodeHolder {item .newNode }).getNode , getPodsAssignedToNode (fakeClientset ))
631
+ controller := NewNoExecuteTaintManager (fakeClientset , getPodFromClientset (fakeClientset ), (& nodeHolder {node : item .newNode }).getNode , getPodsAssignedToNode (fakeClientset ))
553
632
controller .recorder = testutil .NewFakeRecorder ()
554
633
go controller .Run (stopCh )
555
634
controller .NodeUpdated (item .oldNode , item .newNode )
@@ -749,7 +828,7 @@ func TestEventualConsistency(t *testing.T) {
749
828
stopCh := make (chan struct {})
750
829
fakeClientset := fake .NewSimpleClientset (& v1.PodList {Items : item .pods })
751
830
holder := & podHolder {}
752
- controller := NewNoExecuteTaintManager (fakeClientset , holder .getPod , (& nodeHolder {item .newNode }).getNode , getPodsAssignedToNode (fakeClientset ))
831
+ controller := NewNoExecuteTaintManager (fakeClientset , holder .getPod , (& nodeHolder {node : item .newNode }).getNode , getPodsAssignedToNode (fakeClientset ))
753
832
controller .recorder = testutil .NewFakeRecorder ()
754
833
go controller .Run (stopCh )
755
834
0 commit comments