Skip to content

Commit 346807e

Browse files
Add VAP tests for PyTorchJobs
1 parent c7c6007 commit 346807e

File tree

1 file changed

+74
-13
lines changed

1 file changed

+74
-13
lines changed

tests/odh/validating_admission_policy_test.go

+74-13
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
awv1beta2 "github.com/project-codeflare/appwrapper/api/v1beta2"
2626
. "github.com/project-codeflare/codeflare-common/support"
2727
rayv1 "github.com/ray-project/kuberay/ray-operator/apis/ray/v1"
28+
kftrainingv1 "github.com/kubeflow/training-operator/pkg/apis/kubeflow.org/v1"
2829

2930
vapv1 "k8s.io/api/admissionregistration/v1"
3031
corev1 "k8s.io/api/core/v1"
@@ -35,26 +36,30 @@ import (
3536
"k8s.io/apimachinery/pkg/types"
3637
"k8s.io/client-go/kubernetes/scheme"
3738
kueuev1beta1 "sigs.k8s.io/kueue/apis/kueue/v1beta1"
39+
testingpytorchjob "sigs.k8s.io/kueue/pkg/util/testingjobs/pytorchjob"
3840
testingraycluster "sigs.k8s.io/kueue/pkg/util/testingjobs/raycluster"
3941
)
4042

4143
// Note: This test must run on an OCP v4.17 or later cluster.
4244
// The Validating Admission Policy feature gate is GA and enabled by default from OCP v4.17 (k8s v1.30)
4345

4446
var (
45-
ns *corev1.Namespace
46-
nsNoLabel *corev1.Namespace
47-
rf *kueuev1beta1.ResourceFlavor
48-
cq *kueuev1beta1.ClusterQueue
49-
lq *kueuev1beta1.LocalQueue
50-
rc *rayv1.RayCluster
51-
aw *awv1beta2.AppWrapper
52-
vapb *vapv1.ValidatingAdmissionPolicyBinding
53-
vapbCopy *vapv1.ValidatingAdmissionPolicyBinding
54-
awWithLQName = "aw-with-lq"
55-
awNoLQName = "aw-no-lq"
56-
rcWithLQName = "rc-with-lq"
57-
rcNoLQName = "rc-no-lq"
47+
ns *corev1.Namespace
48+
nsNoLabel *corev1.Namespace
49+
rf *kueuev1beta1.ResourceFlavor
50+
cq *kueuev1beta1.ClusterQueue
51+
lq *kueuev1beta1.LocalQueue
52+
rc *rayv1.RayCluster
53+
aw *awv1beta2.AppWrapper
54+
pyt *kftrainingv1.PyTorchJob
55+
vapb *vapv1.ValidatingAdmissionPolicyBinding
56+
vapbCopy *vapv1.ValidatingAdmissionPolicyBinding
57+
awWithLQName = "aw-with-lq"
58+
awNoLQName = "aw-no-lq"
59+
rcWithLQName = "rc-with-lq"
60+
rcNoLQName = "rc-no-lq"
61+
pytWithLQName = "pyt-with-lq"
62+
pytNoLQName = "pyt-no-lq"
5863
)
5964

6065
const (
@@ -156,6 +161,18 @@ func TestValidatingAdmissionPolicy(t *testing.T) {
156161
defer test.Client().Dynamic().Resource(awv1beta2.GroupVersion.WithResource("appwrappers")).Namespace(ns.Name).Delete(test.Ctx(), aw.Name, metav1.DeleteOptions{})
157162
})
158163
})
164+
t.Run("PyTorchJob Tests", func(t *testing.T) {
165+
t.Run("PyTorchJob should be admitted with the 'kueue.x-k8s.io/queue-name' label set", func(t *testing.T) {
166+
err = createPyTorchJob(test, ns.Name, withLQ)
167+
test.Expect(err).ToNot(HaveOccurred())
168+
defer test.Client().Kubeflow().KubeflowV1().PyTorchJobs(ns.Name).Delete(test.Ctx(), pyt.Name, metav1.DeleteOptions{})
169+
})
170+
t.Run("PyTorchJob should not be admitted without the 'kueue.x-k8s.io/queue-name' label set", func(t *testing.T) {
171+
err = createPyTorchJob(test, ns.Name, noLQ)
172+
test.Expect(err).ToNot(BeNil())
173+
defer test.Client().Kubeflow().KubeflowV1().PyTorchJobs(ns.Name).Delete(test.Ctx(), pyt.Name, metav1.DeleteOptions{})
174+
})
175+
})
159176
})
160177

161178
/**************************************************************************
@@ -196,6 +213,18 @@ func TestValidatingAdmissionPolicy(t *testing.T) {
196213
defer test.Client().Dynamic().Resource(awv1beta2.GroupVersion.WithResource("appwrappers")).Namespace(ns.Name).Delete(test.Ctx(), aw.Name, metav1.DeleteOptions{})
197214
})
198215
})
216+
t.Run("PyTorchJob Tests", func(t *testing.T) {
217+
t.Run("PyTorchJob should be admitted with the 'kueue.x-k8s.io/queue-name' label set", func(t *testing.T) {
218+
err = createPyTorchJob(test, ns.Name, withLQ)
219+
test.Expect(err).ToNot(HaveOccurred())
220+
defer test.Client().Kubeflow().KubeflowV1().PyTorchJobs(ns.Name).Delete(test.Ctx(), pyt.Name, metav1.DeleteOptions{})
221+
})
222+
t.Run("PyTorchJob should be admitted without the 'kueue.x-k8s.io/queue-name' label set", func(t *testing.T) {
223+
err = createPyTorchJob(test, ns.Name, noLQ)
224+
test.Expect(err).ToNot(HaveOccurred())
225+
defer test.Client().Kubeflow().KubeflowV1().PyTorchJobs(ns.Name).Delete(test.Ctx(), pyt.Name, metav1.DeleteOptions{})
226+
})
227+
})
199228
})
200229

201230
/**************************************************************************
@@ -271,6 +300,28 @@ func TestValidatingAdmissionPolicy(t *testing.T) {
271300
defer test.Client().Dynamic().Resource(awv1beta2.GroupVersion.WithResource("appwrappers")).Namespace(nsNoLabel.Name).Delete(test.Ctx(), aw.Name, metav1.DeleteOptions{})
272301
})
273302
})
303+
t.Run("PyTorchJob Tests", func(t *testing.T) {
304+
t.Run("PyTorchJob should be admitted with the 'kueue.x-k8s.io/queue-name' label in a labeled namespace", func(t *testing.T) {
305+
err = createPyTorchJob(test, ns.Name, withLQ)
306+
test.Expect(err).ToNot(HaveOccurred())
307+
defer test.Client().Kubeflow().KubeflowV1().PyTorchJobs(ns.Name).Delete(test.Ctx(), pyt.Name, metav1.DeleteOptions{})
308+
})
309+
t.Run("PyTorchJob should not be admitted without the 'kueue.x-k8s.io/queue-name' label in a labeled namespace", func(t *testing.T) {
310+
err = createPyTorchJob(test, ns.Name, noLQ)
311+
test.Expect(err).ToNot(BeNil())
312+
defer test.Client().Kubeflow().KubeflowV1().PyTorchJobs(ns.Name).Delete(test.Ctx(), pyt.Name, metav1.DeleteOptions{})
313+
})
314+
t.Run("PyTorchJob should be admitted with the 'kueue.x-k8s.io/queue-name' label in any other namespace", func(t *testing.T) {
315+
err = createPyTorchJob(test, nsNoLabel.Name, withLQ)
316+
test.Expect(err).ToNot(HaveOccurred())
317+
defer test.Client().Kubeflow().KubeflowV1().PyTorchJobs(ns.Name).Delete(test.Ctx(), pyt.Name, metav1.DeleteOptions{})
318+
})
319+
t.Run("PyTorchJob should be admitted without the 'kueue.x-k8s.io/queue-name' label in any other namespace", func(t *testing.T) {
320+
err = createPyTorchJob(test, nsNoLabel.Name, noLQ)
321+
test.Expect(err).ToNot(HaveOccurred())
322+
defer test.Client().Kubeflow().KubeflowV1().PyTorchJobs(ns.Name).Delete(test.Ctx(), pyt.Name, metav1.DeleteOptions{})
323+
})
324+
})
274325
})
275326
}
276327

@@ -315,3 +366,13 @@ func createAppWrapper(test Test, namespaceName string, localQueue bool) error {
315366
_, err := test.Client().Dynamic().Resource(awv1beta2.GroupVersion.WithResource("appwrappers")).Namespace(namespaceName).Create(test.Ctx(), &unstructured.Unstructured{Object: awMap}, metav1.CreateOptions{})
316367
return err
317368
}
369+
370+
func createPyTorchJob(test Test, namespaceName string, localQueue bool) error {
371+
if localQueue {
372+
pyt = testingpytorchjob.MakePyTorchJob(uniqueSuffix(pytWithLQName), namespaceName).Queue(lq.Name).Obj()
373+
} else {
374+
pyt = testingpytorchjob.MakePyTorchJob(uniqueSuffix(pytNoLQName), namespaceName).Obj()
375+
}
376+
_, err := test.Client().Kubeflow().KubeflowV1().PyTorchJobs(namespaceName).Create(test.Ctx(), pyt, metav1.CreateOptions{})
377+
return err
378+
}

0 commit comments

Comments
 (0)