From a8f94535c481fe0bf8dd0d1bac754e9240e48392 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Schottst=C3=A4dt?= Date: Sun, 23 Aug 2026 22:33:53 +0100 Subject: [PATCH] fix(kubernetes): wait for PVC binding --- internal/runtime/kubernetes/resources_test.go | 16 ++++++++++++++++ internal/runtime/kubernetes/wait_jobs.go | 3 +++ 2 files changed, 19 insertions(+) diff --git a/internal/runtime/kubernetes/resources_test.go b/internal/runtime/kubernetes/resources_test.go index baaeef1..312e959 100644 --- a/internal/runtime/kubernetes/resources_test.go +++ b/internal/runtime/kubernetes/resources_test.go @@ -779,6 +779,22 @@ func TestWaitForJobImmediatelyReportsUnschedulablePod(t *testing.T) { } } +func TestJobStartupFailureWaitsForImmediatePVCBinding(t *testing.T) { + job := &batchv1.Job{ObjectMeta: metav1.ObjectMeta{Name: "pvc-binding", Namespace: "druid"}} + pod := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: "pvc-binding-pod", Namespace: "druid", Labels: map[string]string{"job-name": job.Name}}, + Status: corev1.PodStatus{Conditions: []corev1.PodCondition{{ + Type: corev1.PodScheduled, Status: corev1.ConditionFalse, Reason: corev1.PodReasonUnschedulable, + Message: "0/3 nodes are available: pod has unbound immediate PersistentVolumeClaims", + }}}, + } + backend := NewWithClient(Config{Namespace: "druid"}, fake.NewSimpleClientset(job, pod)) + + if _, _, failed := backend.jobStartupFailure(context.Background(), "druid", job.Name, false); failed { + t.Fatal("jobStartupFailure reported transient PVC binding as terminal") + } +} + func TestWaitForJobUsesRecentSuccessfulDeletion(t *testing.T) { backend := NewWithClient(Config{Namespace: "druid"}, fake.NewSimpleClientset()) backend.recordJobExit("druid", "finished", 0) diff --git a/internal/runtime/kubernetes/wait_jobs.go b/internal/runtime/kubernetes/wait_jobs.go index 64629b5..29d0e29 100644 --- a/internal/runtime/kubernetes/wait_jobs.go +++ b/internal/runtime/kubernetes/wait_jobs.go @@ -151,6 +151,9 @@ func (b *Backend) jobStartupFailure(ctx context.Context, namespace string, jobNa for _, pod := range pods.Items { for _, condition := range pod.Status.Conditions { if condition.Type == corev1.PodScheduled && condition.Status == corev1.ConditionFalse && condition.Reason == corev1.PodReasonUnschedulable { + if strings.Contains(condition.Message, "unbound immediate PersistentVolumeClaims") { + continue + } return 1, fmt.Sprintf("pod %s is unschedulable: %s", pod.Name, condition.Message), true } }