@@ -66,6 +66,19 @@ func newPod(name string, jobId int32) *corev1.Pod {
6666 }
6767}
6868
69+ func newTerminatingPod (name string , jobId int32 ) * corev1.Pod {
70+ pod := newPod (name , jobId )
71+ now := metav1 .Now ()
72+ pod .DeletionTimestamp = & now
73+ return pod
74+ }
75+
76+ func newTerminalPod (name string , jobId int32 ) * corev1.Pod {
77+ pod := newPod (name , jobId )
78+ pod .Status .Phase = corev1 .PodSucceeded
79+ return pod
80+ }
81+
6982func newRequest (name string ) ctrl.Request {
7083 return ctrl.Request {
7184 NamespacedName : types.NamespacedName {
@@ -225,6 +238,65 @@ var _ = Describe("syncSlurm()", func() {
225238 Expect (exists ).To (BeTrue ())
226239 })
227240
241+ It ("Should not terminate the job for a terminating pod" , func () {
242+ By ("Setting the pod as terminating but non-terminal" )
243+ key := types.NamespacedName {Namespace : corev1 .NamespaceDefault , Name : podName }
244+ pod := & corev1.Pod {}
245+ err := controller .Get (ctx , key , pod )
246+ Expect (apierrors .IsNotFound (err )).ToNot (BeTrue ())
247+ now := metav1 .Now ()
248+ pod .DeletionTimestamp = & now
249+ err = controller .Update (ctx , pod )
250+ Expect (err ).NotTo (HaveOccurred ())
251+
252+ By ("Reconciling" )
253+ err = controller .syncSlurm (ctx , req )
254+ Expect (err ).NotTo (HaveOccurred ())
255+
256+ By ("Check job is still running" )
257+ exists , err := controller .slurmControl .IsJobRunning (ctx , pod )
258+ Expect (err ).ToNot (HaveOccurred ())
259+ Expect (exists ).To (BeTrue ())
260+ })
261+
262+ It ("Should not terminate the job while another pod is terminating" , func () {
263+ By ("Creating a terminal pod and a non-terminal terminating pod for the same Slurm job" )
264+ terminalPod := newTerminalPod ("foo-terminal" , jobId )
265+ terminatingPod := newTerminatingPod ("foo-terminating" , jobId )
266+ podList := & corev1.PodList {
267+ Items : []corev1.Pod {* terminalPod , * terminatingPod },
268+ }
269+ jobList := & slurmtypes.V0044JobInfoList {
270+ Items : []slurmtypes.V0044JobInfo {
271+ {
272+ V0044JobInfo : api.V0044JobInfo {
273+ JobId : ptr .To (jobId ),
274+ JobState : & []api.V0044JobInfoJobState {api .V0044JobInfoJobStateRUNNING },
275+ AdminComment : ptr .To (newPlaceholderInfo ("foo-terminal" ).ToString ()),
276+ },
277+ },
278+ },
279+ }
280+ c := slurmclientfake .NewClientBuilder ().WithLists (jobList ).Build ()
281+ localController := & PodReconciler {
282+ Client : fake .NewFakeClient (podList ),
283+ Scheme : scheme .Scheme ,
284+ SlurmClient : c ,
285+ EventCh : make (chan event.GenericEvent , 5 ),
286+ slurmControl : slurmcontrol .NewControl (c ),
287+ eventRecorder : record .NewFakeRecorder (10 ),
288+ }
289+
290+ By ("Reconciling the terminal pod" )
291+ err := localController .syncSlurm (ctx , newRequest ("foo-terminal" ))
292+ Expect (err ).NotTo (HaveOccurred ())
293+
294+ By ("Check job is still running because a non-terminal pod still exists" )
295+ exists , err := localController .slurmControl .IsJobRunning (ctx , terminatingPod )
296+ Expect (err ).ToNot (HaveOccurred ())
297+ Expect (exists ).To (BeTrue ())
298+ })
299+
228300 It ("Should terminate the job" , func () {
229301 By ("Terminating the corresponding Slurm job" )
230302 key := types.NamespacedName {Namespace : corev1 .NamespaceDefault , Name : "bar" }
@@ -402,5 +474,46 @@ var _ = Describe("prepareTerminalPod()", func() {
402474 err = controller .Get (ctx , claimKey , claim )
403475 Expect (apierrors .IsNotFound (err )).To (BeTrue ())
404476 })
477+
478+ It ("Should not remove finalizer for terminating pod" , func () {
479+ By ("Creating a non-terminal terminating pod with finalizer and claim" )
480+ podName := "terminating"
481+ terminatingPod := newTerminatingPod (podName , 1 )
482+ terminatingPod .Finalizers = []string {wellknown .FinalizerScheduler }
483+ terminatingPod .Status .ExtendedResourceClaimStatus = & corev1.PodExtendedResourceClaimStatus {
484+ ResourceClaimName : "terminating-claim" ,
485+ }
486+ claim := & resourcev1.ResourceClaim {
487+ ObjectMeta : metav1.ObjectMeta {
488+ Name : "terminating-claim" ,
489+ Namespace : metav1 .NamespaceDefault ,
490+ },
491+ }
492+ localController := & PodReconciler {
493+ Client : fake .NewFakeClient (terminatingPod , claim ),
494+ Scheme : scheme .Scheme ,
495+ SlurmClient : slurmclientfake .NewFakeClient (),
496+ EventCh : make (chan event.GenericEvent , 5 ),
497+ slurmControl : slurmcontrol .NewControl (slurmclientfake .NewFakeClient ()),
498+ eventRecorder : record .NewFakeRecorder (10 ),
499+ }
500+
501+ By ("Reconciling" )
502+ err := localController .prepareTerminalPod (ctx , newRequest (podName ))
503+ Expect (err ).NotTo (HaveOccurred ())
504+
505+ By ("Check finalizer still exists" )
506+ podKey := types.NamespacedName {Namespace : metav1 .NamespaceDefault , Name : podName }
507+ pod := & corev1.Pod {}
508+ err = localController .Get (ctx , podKey , pod )
509+ Expect (apierrors .IsNotFound (err )).ToNot (BeTrue ())
510+ Expect (pod .ObjectMeta .Finalizers ).To (Equal ([]string {wellknown .FinalizerScheduler }))
511+
512+ By ("Check ResourceClaim still exists" )
513+ claimKey := types.NamespacedName {Namespace : metav1 .NamespaceDefault , Name : "terminating-claim" }
514+ gotClaim := & resourcev1.ResourceClaim {}
515+ err = localController .Get (ctx , claimKey , gotClaim )
516+ Expect (err ).NotTo (HaveOccurred ())
517+ })
405518 })
406519})
0 commit comments