Skip to content

Commit 01ec624

Browse files
committed
Tests change
Signed-off-by: gshaibi <gshaibi@nvidia.com>
1 parent e3ea7fc commit 01ec624

2 files changed

Lines changed: 80 additions & 59 deletions

File tree

pkg/podgrouper/integration_tests/workload_integration_test.go

Lines changed: 0 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -36,35 +36,6 @@ var _ = Describe("Workload API translation", func() {
3636
_ = k8sClient.Delete(ctx, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: ns}})
3737
})
3838

39-
It("creates a KAI PodGroup with MinMember=gang.minCount for a Gang-policy Workload", func(ctx context.Context) {
40-
wl := &schedulingv1alpha1.Workload{
41-
ObjectMeta: metav1.ObjectMeta{Namespace: ns, Name: "my-training"},
42-
Spec: schedulingv1alpha1.WorkloadSpec{
43-
PodGroups: []schedulingv1alpha1.PodGroup{{
44-
Name: "workers",
45-
Policy: schedulingv1alpha1.PodGroupPolicy{
46-
Gang: &schedulingv1alpha1.GangSchedulingPolicy{MinCount: 3},
47-
},
48-
}},
49-
},
50-
}
51-
Expect(k8sClient.Create(ctx, wl)).To(Succeed())
52-
53-
pod := newPod(ns, "worker-0", &corev1.WorkloadReference{
54-
Name: "my-training", PodGroup: "workers", PodGroupReplicaKey: "0",
55-
})
56-
Expect(k8sClient.Create(ctx, pod)).To(Succeed())
57-
58-
// The podgrouper names the KAI PodGroup {workload}-{podGroup}-{replicaKey}.
59-
pg := &schedulingv2alpha2.PodGroup{}
60-
Eventually(func() error {
61-
return k8sClient.Get(ctx, types.NamespacedName{Namespace: ns, Name: "my-training-workers-0"}, pg)
62-
}, assertTimeout, assertInterval).Should(Succeed())
63-
Expect(pg.Spec.MinMember).NotTo(BeNil())
64-
Expect(*pg.Spec.MinMember).To(Equal(int32(3)))
65-
Expect(pg.Spec.SubGroups).To(BeEmpty())
66-
})
67-
6839
It("collapses all replica keys into one KAI PodGroup for a Basic-policy Workload", func(ctx context.Context) {
6940
wl := &schedulingv1alpha1.Workload{
7041
ObjectMeta: metav1.ObjectMeta{Namespace: ns, Name: "serving"},
@@ -97,35 +68,6 @@ var _ = Describe("Workload API translation", func() {
9768
Expect(kerrors.IsNotFound(err)).To(BeTrue(), fmt.Sprintf("expected NotFound, got %v", err))
9869
})
9970

100-
It("propagates a kai.scheduler/queue label from the Workload onto the KAI PodGroup", func(ctx context.Context) {
101-
const wlQueue = "ml-training"
102-
wl := &schedulingv1alpha1.Workload{
103-
ObjectMeta: metav1.ObjectMeta{
104-
Namespace: ns, Name: "queued",
105-
Labels: map[string]string{commonconstants.DefaultQueueLabel: wlQueue},
106-
},
107-
Spec: schedulingv1alpha1.WorkloadSpec{
108-
PodGroups: []schedulingv1alpha1.PodGroup{{
109-
Name: "g",
110-
Policy: schedulingv1alpha1.PodGroupPolicy{
111-
Gang: &schedulingv1alpha1.GangSchedulingPolicy{MinCount: 1},
112-
},
113-
}},
114-
},
115-
}
116-
Expect(k8sClient.Create(ctx, wl)).To(Succeed())
117-
118-
pod := newPod(ns, "qpod", &corev1.WorkloadReference{Name: "queued", PodGroup: "g"})
119-
Expect(k8sClient.Create(ctx, pod)).To(Succeed())
120-
121-
pg := &schedulingv2alpha2.PodGroup{}
122-
Eventually(func() error {
123-
return k8sClient.Get(ctx, types.NamespacedName{Namespace: ns, Name: "queued-g"}, pg)
124-
}, assertTimeout, assertInterval).Should(Succeed())
125-
Expect(pg.Spec.Queue).To(Equal(wlQueue),
126-
"Workload's queue label must override the queue derived by the top-owner plugin")
127-
})
128-
12971
It("does not propagate Workload kai.scheduler/queue label changes to the existing PodGroup", func(ctx context.Context) {
13072
const initialQueue = "ml-training"
13173
const updatedQueue = "ml-batch"

test/e2e/suites/workload/workload_specs.go

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"github.com/kai-scheduler/KAI-scheduler/test/e2e/modules/resources/rd"
2828
"github.com/kai-scheduler/KAI-scheduler/test/e2e/modules/resources/rd/queue"
2929
"github.com/kai-scheduler/KAI-scheduler/test/e2e/modules/utils"
30+
"github.com/kai-scheduler/KAI-scheduler/test/e2e/modules/wait"
3031
)
3132

3233
const (
@@ -192,7 +193,7 @@ func DescribeWorkloadSpecs() bool {
192193
pod := rd.CreatePodObject(testQ, corev1.ResourceRequirements{})
193194
pod.Spec.WorkloadRef = &corev1.WorkloadReference{Name: wlName, PodGroup: "g"}
194195
pod.Annotations[commonconstants.WorkloadIgnoreAnnotationKey] = "true"
195-
_, err := rd.CreatePod(ctx, testCtx.KubeClientset, pod)
196+
pod, err := rd.CreatePod(ctx, testCtx.KubeClientset, pod)
196197
Expect(err).NotTo(HaveOccurred())
197198

198199
// The Workload-derived PodGroup must NOT appear.
@@ -203,6 +204,26 @@ func DescribeWorkloadSpecs() bool {
203204
return kerrors.IsNotFound(err)
204205
}, 3*time.Second, pgPollTick).Should(BeTrue(),
205206
"Workload-derived PodGroup must not be created when opt-out is set")
207+
208+
// Opt-out must release the pod into the default top-owner path:
209+
// the pod is annotated with a non-Workload PodGroup name and the
210+
// pod schedules. Without this assertion, opt-out could silently
211+
// strand the pod.
212+
var pgName string
213+
Eventually(func() string {
214+
cur := &corev1.Pod{}
215+
if err := testCtx.ControllerClient.Get(ctx, types.NamespacedName{
216+
Namespace: pod.Namespace, Name: pod.Name,
217+
}, cur); err != nil {
218+
return ""
219+
}
220+
pgName = cur.Annotations[commonconstants.PodGroupAnnotationForPod]
221+
return pgName
222+
}, pgWaitTimeout, pgPollTick).ShouldNot(BeEmpty(),
223+
"opt-out pod must receive a default PodGroup annotation")
224+
Expect(pgName).NotTo(Equal(wlName+"-g"),
225+
"opt-out pod must not be annotated with the Workload-derived PodGroup name")
226+
wait.ForPodScheduled(ctx, testCtx.ControllerClient, pod)
206227
})
207228

208229
It("layers a Workload override on top of a real top-owner controller (Job)", func(ctx context.Context) {
@@ -289,6 +310,64 @@ func DescribeWorkloadSpecs() bool {
289310
"PodGroup ownerReferences must point at the Job (top owner), not the Workload")
290311
})
291312

313+
It("gates gang scheduling on the Workload's MinCount", func(ctx context.Context) {
314+
// Smoke test that the Workload-derived PodGroup actually drives
315+
// scheduling end-to-end: a single pod referencing a Workload with
316+
// gang.MinCount=2 must stay unscheduled until the second pod
317+
// arrives, then both schedule together. Pure-translation tests
318+
// can't catch a regression where the spec is correct but the
319+
// scheduler ignores the resulting PodGroup.
320+
wlName := "gang-quorum-" + rand.String(6)
321+
ns := queue.GetConnectedNamespaceToQueue(testQ)
322+
wl := &schedulingv1alpha1.Workload{
323+
ObjectMeta: metav1.ObjectMeta{Namespace: ns, Name: wlName},
324+
Spec: schedulingv1alpha1.WorkloadSpec{
325+
PodGroups: []schedulingv1alpha1.PodGroup{{
326+
Name: "workers",
327+
Policy: schedulingv1alpha1.PodGroupPolicy{
328+
Gang: &schedulingv1alpha1.GangSchedulingPolicy{MinCount: 2},
329+
},
330+
}},
331+
},
332+
}
333+
Expect(testCtx.ControllerClient.Create(ctx, wl)).To(Succeed())
334+
DeferCleanup(func(ctx context.Context) {
335+
_ = testCtx.ControllerClient.Delete(ctx, wl)
336+
})
337+
338+
newGangPod := func() *corev1.Pod {
339+
p := rd.CreatePodObject(testQ, corev1.ResourceRequirements{})
340+
p.Spec.WorkloadRef = &corev1.WorkloadReference{
341+
Name: wlName, PodGroup: "workers", PodGroupReplicaKey: "0",
342+
}
343+
return p
344+
}
345+
346+
pod1, err := rd.CreatePod(ctx, testCtx.KubeClientset, newGangPod())
347+
Expect(err).NotTo(HaveOccurred())
348+
349+
waitForPodGroup(ctx, testCtx, ns, fmt.Sprintf("%s-workers-0", wlName))
350+
351+
// Below quorum: pod1 must remain unbound to a node. NodeName is
352+
// the authoritative bind signal — checking it avoids depending on
353+
// the exact Unschedulable-condition reason the scheduler chose.
354+
Consistently(func() string {
355+
cur := &corev1.Pod{}
356+
if err := testCtx.ControllerClient.Get(ctx, types.NamespacedName{
357+
Namespace: pod1.Namespace, Name: pod1.Name,
358+
}, cur); err != nil {
359+
return ""
360+
}
361+
return cur.Spec.NodeName
362+
}, 5*time.Second, pgPollTick).Should(BeEmpty(),
363+
"pod must stay unbound while the gang is below MinCount=2")
364+
365+
pod2, err := rd.CreatePod(ctx, testCtx.KubeClientset, newGangPod())
366+
Expect(err).NotTo(HaveOccurred())
367+
368+
wait.ForPodsScheduled(ctx, testCtx.ControllerClient, ns, []*corev1.Pod{pod1, pod2})
369+
})
370+
292371
})
293372
}
294373

0 commit comments

Comments
 (0)