Skip to content

Commit 6f981d5

Browse files
committed
baisc test for AppWrappers containing RayJobs and RayClusters
1 parent 0ac3e10 commit 6f981d5

File tree

2 files changed

+137
-1
lines changed

2 files changed

+137
-1
lines changed

test/e2e/appwrapper_test.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,21 @@ var _ = Describe("AppWrapper E2E Test", func() {
8282
})
8383
})
8484

85-
// TODO: KubeRay GVKs (would have to deploy KubeRay operator on e2e test cluster)
85+
Describe("Creation of Kuberay GVKs", Label("Kueue", "Standalone"), func() {
86+
It("RayClusters", func() {
87+
aw := createAppWrapper(ctx, raycluster(500, 2, 250))
88+
appwrappers = append(appwrappers, aw)
89+
// Non-functonal RayCluster; will never reach Running Phase
90+
Eventually(AppWrapperPhase(ctx, aw), 15*time.Second).Should(Equal(workloadv1beta2.AppWrapperResuming))
91+
})
92+
93+
It("RayJobs", func() {
94+
aw := createAppWrapper(ctx, rayjob(500, 2, 250))
95+
appwrappers = append(appwrappers, aw)
96+
// Non-functonal RayJob; will never reach Running Phase
97+
Eventually(AppWrapperPhase(ctx, aw), 15*time.Second).Should(Equal(workloadv1beta2.AppWrapperResuming))
98+
})
99+
})
86100

87101
// TODO: JobSets (would have to deploy JobSet controller on e2e test cluster)
88102

test/e2e/fixtures_test.go

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,128 @@ func pytorchjob(replicasWorker int, milliCPUWorker int64) workloadv1beta2.AppWra
341341
}
342342
}
343343

344+
// This is not a functional RayCluster:
345+
// 1. Using a dummy busybox image to avoid pulling a large & rate-limited image from dockerhub,
346+
// which means the command injected by the kuberay operator will never work.
347+
//
348+
// It is only useful to check that we validate the PodSpecTemplates and can reach the Resuming state.
349+
const rayclusterYAML = `
350+
apiVersion: ray.io/v1
351+
kind: RayCluster
352+
metadata:
353+
name: %v
354+
spec:
355+
rayVersion: '2.9.0'
356+
headGroupSpec:
357+
rayStartParams: {}
358+
template:
359+
spec:
360+
containers:
361+
- name: ray-head
362+
image: quay.io/project-codeflare/busybox:1.36
363+
command: ["sh", "-c", "sleep 10"]
364+
resources:
365+
requests:
366+
cpu: %v
367+
368+
workerGroupSpecs:
369+
- replicas: %v
370+
minReplicas: %v
371+
maxReplicas: %v
372+
groupName: small-group
373+
rayStartParams: {}
374+
# Pod template
375+
template:
376+
spec:
377+
containers:
378+
- name: ray-worker
379+
image: quay.io/project-codeflare/busybox:1.36
380+
command: ["sh", "-c", "sleep 10"]
381+
resources:
382+
requests:
383+
cpu: %v
384+
`
385+
386+
func raycluster(milliCPUHead int64, replicasWorker int, milliCPUWorker int64) workloadv1beta2.AppWrapperComponent {
387+
yamlString := fmt.Sprintf(rayclusterYAML,
388+
randName("raycluster"),
389+
resource.NewMilliQuantity(milliCPUHead, resource.DecimalSI),
390+
replicasWorker, replicasWorker, replicasWorker,
391+
resource.NewMilliQuantity(milliCPUWorker, resource.DecimalSI),
392+
)
393+
jsonBytes, err := yaml.YAMLToJSON([]byte(yamlString))
394+
Expect(err).NotTo(HaveOccurred())
395+
return workloadv1beta2.AppWrapperComponent{
396+
DeclaredPodSets: []workloadv1beta2.AppWrapperPodSet{
397+
{Replicas: ptr.To(int32(1)), Path: "template.spec.headGroupSpec.template"},
398+
{Replicas: ptr.To(int32(replicasWorker)), Path: "template.spec.workerGroupSpecs[0].template"},
399+
},
400+
Template: runtime.RawExtension{Raw: jsonBytes},
401+
}
402+
}
403+
404+
// This is not a functional RayJob:
405+
// 1. Using a dummy busybox image to avoid pulling a large & rate-limited image from dockerhub,
406+
// which means the command injected by the kuberay operator will never work.
407+
//
408+
// It is only useful to check that we validate the PodSpecTemplates and can reach the Resuming state.
409+
const rayjobYAML = `
410+
apiVersion: ray.io/v1
411+
kind: RayJob
412+
metadata:
413+
name: %v
414+
spec:
415+
shutdownAfterJobFinishes: true
416+
rayClusterSpec:
417+
rayVersion: '2.9.0'
418+
headGroupSpec:
419+
rayStartParams: {}
420+
template:
421+
spec:
422+
containers:
423+
- name: ray-head
424+
image: quay.io/project-codeflare/busybox:1.36
425+
command: ["sh", "-c", "sleep 10"]
426+
resources:
427+
requests:
428+
cpu: %v
429+
430+
workerGroupSpecs:
431+
- replicas: %v
432+
minReplicas: %v
433+
maxReplicas: %v
434+
groupName: small-group
435+
rayStartParams: {}
436+
# Pod template
437+
template:
438+
spec:
439+
containers:
440+
- name: ray-worker
441+
image: quay.io/project-codeflare/busybox:1.36
442+
command: ["sh", "-c", "sleep 10"]
443+
resources:
444+
requests:
445+
cpu: %v
446+
`
447+
448+
func rayjob(milliCPUHead int64, replicasWorker int, milliCPUWorker int64) workloadv1beta2.AppWrapperComponent {
449+
yamlString := fmt.Sprintf(rayjobYAML,
450+
randName("raycluster"),
451+
resource.NewMilliQuantity(milliCPUHead, resource.DecimalSI),
452+
replicasWorker, replicasWorker, replicasWorker,
453+
resource.NewMilliQuantity(milliCPUWorker, resource.DecimalSI),
454+
)
455+
jsonBytes, err := yaml.YAMLToJSON([]byte(yamlString))
456+
Expect(err).NotTo(HaveOccurred())
457+
return workloadv1beta2.AppWrapperComponent{
458+
DeclaredPodSets: []workloadv1beta2.AppWrapperPodSet{
459+
{Replicas: ptr.To(int32(1)), Path: "template.spec.rayClusterSpec.headGroupSpec.template"},
460+
{Replicas: ptr.To(int32(replicasWorker)), Path: "template.spec.rayClusterSpec.workerGroupSpecs[0].template"},
461+
},
462+
Template: runtime.RawExtension{Raw: jsonBytes},
463+
}
464+
}
465+
344466
const jobSetYAML = `
345467
apiVersion: jobset.x-k8s.io/v1alpha2
346468
kind: JobSet

0 commit comments

Comments
 (0)