@@ -30,6 +30,7 @@ import (
30
30
"github.com/google/go-cmp/cmp"
31
31
"github.com/google/go-cmp/cmp/cmpopts"
32
32
"github.com/stretchr/testify/assert"
33
+ "github.com/stretchr/testify/require"
33
34
v1 "k8s.io/api/core/v1"
34
35
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
35
36
"k8s.io/apimachinery/pkg/types"
@@ -45,6 +46,7 @@ import (
45
46
"k8s.io/kubernetes/pkg/kubelet/nodeshutdown/systemd"
46
47
"k8s.io/kubernetes/pkg/kubelet/prober"
47
48
probetest "k8s.io/kubernetes/pkg/kubelet/prober/testing"
49
+ "k8s.io/kubernetes/pkg/kubelet/volumemanager"
48
50
"k8s.io/utils/clock"
49
51
testingclock "k8s.io/utils/clock/testing"
50
52
)
@@ -348,10 +350,12 @@ func TestManager(t *testing.T) {
348
350
349
351
proberManager := probetest.FakeManager {}
350
352
fakeRecorder := & record.FakeRecorder {}
353
+ fakeVolumeManager := volumemanager .NewFakeVolumeManager ([]v1.UniqueVolumeName {}, 0 , nil )
351
354
nodeRef := & v1.ObjectReference {Kind : "Node" , Name : "test" , UID : types .UID ("test" ), Namespace : "" }
352
355
manager , _ := NewManager (& Config {
353
356
Logger : logger ,
354
357
ProbeManager : proberManager ,
358
+ VolumeManager : fakeVolumeManager ,
355
359
Recorder : fakeRecorder ,
356
360
NodeRef : nodeRef ,
357
361
GetPodsFunc : activePodsFunc ,
@@ -452,11 +456,13 @@ func TestFeatureEnabled(t *testing.T) {
452
456
453
457
proberManager := probetest.FakeManager {}
454
458
fakeRecorder := & record.FakeRecorder {}
459
+ fakeVolumeManager := volumemanager .NewFakeVolumeManager ([]v1.UniqueVolumeName {}, 0 , nil )
455
460
nodeRef := & v1.ObjectReference {Kind : "Node" , Name : "test" , UID : types .UID ("test" ), Namespace : "" }
456
461
457
462
manager , _ := NewManager (& Config {
458
463
Logger : logger ,
459
464
ProbeManager : proberManager ,
465
+ VolumeManager : fakeVolumeManager ,
460
466
Recorder : fakeRecorder ,
461
467
NodeRef : nodeRef ,
462
468
GetPodsFunc : activePodsFunc ,
@@ -509,10 +515,12 @@ func TestRestart(t *testing.T) {
509
515
510
516
proberManager := probetest.FakeManager {}
511
517
fakeRecorder := & record.FakeRecorder {}
518
+ fakeVolumeManager := volumemanager .NewFakeVolumeManager ([]v1.UniqueVolumeName {}, 0 , nil )
512
519
nodeRef := & v1.ObjectReference {Kind : "Node" , Name : "test" , UID : types .UID ("test" ), Namespace : "" }
513
520
manager , _ := NewManager (& Config {
514
521
Logger : logger ,
515
522
ProbeManager : proberManager ,
523
+ VolumeManager : fakeVolumeManager ,
516
524
Recorder : fakeRecorder ,
517
525
NodeRef : nodeRef ,
518
526
GetPodsFunc : activePodsFunc ,
@@ -738,17 +746,19 @@ func Test_groupByPriority(t *testing.T) {
738
746
739
747
func Test_managerImpl_processShutdownEvent (t * testing.T ) {
740
748
var (
741
- probeManager = probetest.FakeManager {}
742
- fakeRecorder = & record.FakeRecorder {}
743
- syncNodeStatus = func () {}
744
- nodeRef = & v1.ObjectReference {Kind : "Node" , Name : "test" , UID : types .UID ("test" ), Namespace : "" }
745
- fakeclock = testingclock .NewFakeClock (time .Now ())
749
+ probeManager = probetest.FakeManager {}
750
+ fakeRecorder = & record.FakeRecorder {}
751
+ fakeVolumeManager = volumemanager .NewFakeVolumeManager ([]v1.UniqueVolumeName {}, 0 , nil )
752
+ syncNodeStatus = func () {}
753
+ nodeRef = & v1.ObjectReference {Kind : "Node" , Name : "test" , UID : types .UID ("test" ), Namespace : "" }
754
+ fakeclock = testingclock .NewFakeClock (time .Now ())
746
755
)
747
756
748
757
type fields struct {
749
758
recorder record.EventRecorder
750
759
nodeRef * v1.ObjectReference
751
760
probeManager prober.Manager
761
+ volumeManager volumemanager.VolumeManager
752
762
shutdownGracePeriodByPodPriority []kubeletconfig.ShutdownGracePeriodByPodPriority
753
763
getPods eviction.ActivePodsFunc
754
764
killPodFunc eviction.KillPodFunc
@@ -767,9 +777,10 @@ func Test_managerImpl_processShutdownEvent(t *testing.T) {
767
777
{
768
778
name : "kill pod func take too long" ,
769
779
fields : fields {
770
- recorder : fakeRecorder ,
771
- nodeRef : nodeRef ,
772
- probeManager : probeManager ,
780
+ recorder : fakeRecorder ,
781
+ nodeRef : nodeRef ,
782
+ probeManager : probeManager ,
783
+ volumeManager : fakeVolumeManager ,
773
784
shutdownGracePeriodByPodPriority : []kubeletconfig.ShutdownGracePeriodByPodPriority {
774
785
{
775
786
Priority : 1 ,
@@ -808,6 +819,7 @@ func Test_managerImpl_processShutdownEvent(t *testing.T) {
808
819
)
809
820
m := & managerImpl {
810
821
logger : logger ,
822
+ volumeManager : tt .fields .volumeManager ,
811
823
recorder : tt .fields .recorder ,
812
824
nodeRef : tt .fields .nodeRef ,
813
825
probeManager : tt .fields .probeManager ,
@@ -839,3 +851,65 @@ func Test_managerImpl_processShutdownEvent(t *testing.T) {
839
851
})
840
852
}
841
853
}
854
+
855
+ func Test_processShutdownEvent_VolumeUnmountTimeout (t * testing.T ) {
856
+ var (
857
+ probeManager = probetest.FakeManager {}
858
+ fakeRecorder = & record.FakeRecorder {}
859
+ syncNodeStatus = func () {}
860
+ nodeRef = & v1.ObjectReference {Kind : "Node" , Name : "test" , UID : types .UID ("test" ), Namespace : "" }
861
+ fakeclock = testingclock .NewFakeClock (time .Now ())
862
+ shutdownGracePeriodSeconds = 2
863
+ )
864
+
865
+ fakeVolumeManager := volumemanager .NewFakeVolumeManager (
866
+ []v1.UniqueVolumeName {},
867
+ 3 * time .Second , // This value is intentionally longer than the shutdownGracePeriodSeconds (2s) to test the behavior
868
+ // for volume unmount operations that take longer than the allowed grace period.
869
+ fmt .Errorf ("unmount timeout" ),
870
+ )
871
+ logger := ktesting .NewLogger (t , ktesting .NewConfig (ktesting .BufferLogs (true )))
872
+ m := & managerImpl {
873
+ logger : logger ,
874
+ volumeManager : fakeVolumeManager ,
875
+ recorder : fakeRecorder ,
876
+ nodeRef : nodeRef ,
877
+ probeManager : probeManager ,
878
+ shutdownGracePeriodByPodPriority : []kubeletconfig.ShutdownGracePeriodByPodPriority {
879
+ {
880
+ Priority : 1 ,
881
+ ShutdownGracePeriodSeconds : int64 (shutdownGracePeriodSeconds ),
882
+ },
883
+ },
884
+ getPods : func () []* v1.Pod {
885
+ return []* v1.Pod {
886
+ makePod ("test-pod" , 1 , nil ),
887
+ }
888
+ },
889
+ killPodFunc : func (pod * v1.Pod , isEvicted bool , gracePeriodOverride * int64 , fn func (* v1.PodStatus )) error {
890
+ return nil
891
+ },
892
+ syncNodeStatus : syncNodeStatus ,
893
+ dbusCon : & fakeDbus {},
894
+ clock : fakeclock ,
895
+ }
896
+
897
+ start := fakeclock .Now ()
898
+ err := m .processShutdownEvent ()
899
+ end := fakeclock .Now ()
900
+
901
+ require .NoError (t , err , "managerImpl.processShutdownEvent() should not return an error" )
902
+
903
+ // Check if processShutdownEvent completed within the expected time
904
+ actualDuration := int (end .Sub (start ).Seconds ())
905
+ assert .LessOrEqual (t , actualDuration , shutdownGracePeriodSeconds , "processShutdownEvent took too long" )
906
+
907
+ underlier , ok := logger .GetSink ().(ktesting.Underlier )
908
+ if ! ok {
909
+ t .Fatalf ("Should have had a ktesting LogSink, got %T" , logger .GetSink ())
910
+ }
911
+
912
+ log := underlier .GetBuffer ().String ()
913
+ expectedLogMessage := "Failed while waiting for all the volumes belonging to Pods in this group to unmount"
914
+ assert .Contains (t , log , expectedLogMessage , "Expected log message not found" )
915
+ }
0 commit comments