@@ -304,6 +304,11 @@ func (m *Manager) StartWorkspace(ctx context.Context, req *api.StartWorkspaceReq
304
304
return nil , err
305
305
}
306
306
307
+ err = wait .PollWithContext (ctx , 100 * time .Millisecond , 10 * time .Minute , podRunning (m .Clientset , pod .Name , pod .Namespace ))
308
+ if err != nil {
309
+ return nil , xerrors .Errorf ("workspace pod never reached Running state: %w" , err )
310
+ }
311
+
307
312
// we only calculate the time that PVC restoring from VolumeSnapshot
308
313
if createPVC && startContext .VolumeSnapshot != nil && startContext .VolumeSnapshot .VolumeSnapshotName != "" {
309
314
err := wait .PollWithContext (ctx , 100 * time .Millisecond , 5 * time .Minute , pvcRunning (m .Clientset , pvc .Name , pvc .Namespace ))
@@ -556,6 +561,41 @@ func areValidPorts(value interface{}) error {
556
561
return nil
557
562
}
558
563
564
+ func podRunning (clientset client.Client , podName , namespace string ) wait.ConditionWithContextFunc {
565
+ return func (ctx context.Context ) (bool , error ) {
566
+ var pod corev1.Pod
567
+ err := clientset .Get (ctx , types.NamespacedName {Namespace : namespace , Name : podName }, & pod )
568
+ if err != nil {
569
+ return false , nil
570
+ }
571
+
572
+ switch pod .Status .Phase {
573
+ case corev1 .PodFailed :
574
+ if strings .HasPrefix (pod .Status .Reason , "OutOf" ) {
575
+ return false , xerrors .Errorf ("cannot schedule pod due to out of resources, reason: %s" , pod .Status .Reason )
576
+ }
577
+ return false , fmt .Errorf ("pod failed with reason: %s" , pod .Status .Reason )
578
+ case corev1 .PodSucceeded :
579
+ return false , fmt .Errorf ("pod ran to completion" )
580
+ case corev1 .PodPending :
581
+ for _ , c := range pod .Status .Conditions {
582
+ if c .Type == corev1 .PodScheduled && c .Status == corev1 .ConditionTrue {
583
+ // even if pod is pending but was scheduled already, it means kubelet is pulling images and running init containers
584
+ // we can consider this as pod running
585
+ return true , nil
586
+ }
587
+ }
588
+
589
+ // if pod is pending, wait for it to get scheduled
590
+ return false , nil
591
+ case corev1 .PodRunning :
592
+ return true , nil
593
+ }
594
+
595
+ return false , xerrors .Errorf ("pod in unknown state: %s" , pod .Status .Phase )
596
+ }
597
+ }
598
+
559
599
func areValidFeatureFlags (value interface {}) error {
560
600
s , ok := value .([]api.WorkspaceFeatureFlag )
561
601
if ! ok {
0 commit comments