Skip to content

Commit b508d98

Browse files
[no-relnote] E2E Create test objects from file
Signed-off-by: Carlos Eduardo Arango Gutierrez <[email protected]>
1 parent 047d5f4 commit b508d98

File tree

4 files changed

+104
-53
lines changed

4 files changed

+104
-53
lines changed

tests/e2e/data/job-1.yaml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
apiVersion: batch/v1
2+
kind: Job
3+
metadata:
4+
name: j-e2e-1
5+
labels:
6+
app.nvidia.com: k8s-device-plugin-test-app
7+
spec:
8+
template:
9+
metadata:
10+
name: gpu-pod
11+
spec:
12+
restartPolicy: Never
13+
containers:
14+
- name: cuda-container
15+
image: nvcr.io/nvidia/k8s/cuda-sample:nbody-cuda11.7.1-ubuntu18.04
16+
args:
17+
- "--benchmark"
18+
- "--numbodies=10000"
19+
resources:
20+
limits:
21+
nvidia.com/gpu: "1"
22+
tolerations:
23+
- key: "nvidia.com/gpu"
24+
operator: "Exists"
25+
effect: "NoSchedule"

tests/e2e/device-plugin_test.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,15 +133,12 @@ var _ = Describe("GPU Device Plugin", Ordered, func() {
133133
})
134134
It("it should run GPU jobs", func(ctx context.Context) {
135135
By("Creating a GPU job")
136-
job := newGPUJob(testNamespace.Name)
137-
job.Namespace = testNamespace.Name
138-
139-
_, err := clientSet.BatchV1().Jobs(testNamespace.Name).Create(ctx, job, metav1.CreateOptions{})
136+
job, err := CreateOrUpdateJobsFromFile(ctx, clientSet, "job-1.yaml", testNamespace.Name)
140137
Expect(err).NotTo(HaveOccurred())
141138

142139
By("Waiting for job to complete")
143140
Eventually(func() error {
144-
job, err := clientSet.BatchV1().Jobs(testNamespace.Name).Get(ctx, job.Name, metav1.GetOptions{})
141+
job, err := clientSet.BatchV1().Jobs(testNamespace.Name).Get(ctx, job[0], metav1.GetOptions{})
145142
if err != nil {
146143
return err
147144
}

tests/e2e/e2e_test.go

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import (
2323
"log"
2424
"os"
2525
"path/filepath"
26-
"runtime"
2726
"strconv"
2827
"testing"
2928
"time"
@@ -34,11 +33,9 @@ import (
3433
. "github.com/onsi/ginkgo/v2"
3534
. "github.com/onsi/gomega"
3635

37-
batchv1 "k8s.io/api/batch/v1"
3836
corev1 "k8s.io/api/core/v1"
3937
extclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
4038
apierrors "k8s.io/apimachinery/pkg/api/errors"
41-
"k8s.io/apimachinery/pkg/api/resource"
4239
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
4340
"k8s.io/apimachinery/pkg/util/rand"
4441
"k8s.io/apimachinery/pkg/util/wait"
@@ -56,7 +53,6 @@ const (
5653
)
5754

5855
var (
59-
packagePath string
6056
Kubeconfig string
6157
Timeout time.Duration
6258
HelmChart string
@@ -186,9 +182,6 @@ func getTestEnv() {
186182
defer GinkgoRecover()
187183
var err error
188184

189-
_, thisFile, _, _ := runtime.Caller(0)
190-
packagePath = filepath.Dir(thisFile)
191-
192185
Kubeconfig = os.Getenv("KUBECONFIG")
193186
Expect(Kubeconfig).NotTo(BeEmpty(), "KUBECONFIG must be set")
194187

@@ -284,44 +277,3 @@ func CreateTestingNS(baseName string, c clientset.Interface, labels map[string]s
284277

285278
return got, nil
286279
}
287-
288-
func newGPUJob(namespace string) *batchv1.Job {
289-
return &batchv1.Job{
290-
ObjectMeta: metav1.ObjectMeta{
291-
Name: "gpu-job",
292-
Namespace: namespace,
293-
Labels: map[string]string{
294-
"app.nvidia.com": "k8s-device-plugin-test-app",
295-
},
296-
},
297-
Spec: batchv1.JobSpec{
298-
Template: corev1.PodTemplateSpec{
299-
ObjectMeta: metav1.ObjectMeta{
300-
Name: "gpu-pod",
301-
},
302-
Spec: corev1.PodSpec{
303-
RestartPolicy: corev1.RestartPolicyNever,
304-
Containers: []corev1.Container{
305-
{
306-
Name: "cuda-container",
307-
Image: "nvcr.io/nvidia/k8s/cuda-sample:nbody-cuda11.7.1-ubuntu18.04",
308-
Args: []string{"--benchmark", "--numbodies=10000"},
309-
Resources: corev1.ResourceRequirements{
310-
Limits: corev1.ResourceList{
311-
"nvidia.com/gpu": resource.MustParse("1"),
312-
},
313-
},
314-
},
315-
},
316-
Tolerations: []corev1.Toleration{
317-
{
318-
Key: "nvidia.com/gpu",
319-
Operator: corev1.TolerationOpExists,
320-
Effect: corev1.TaintEffectNoSchedule,
321-
},
322-
},
323-
},
324-
},
325-
},
326-
}
327-
}

tests/e2e/utils.go

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,31 @@
1818
package e2e
1919

2020
import (
21+
"bytes"
2122
"context"
2223
"fmt"
2324
"math/rand"
25+
"os"
26+
"path/filepath"
2427
"regexp"
28+
"runtime"
2529
"strconv"
2630
"strings"
2731
"time"
2832

2933
. "github.com/onsi/gomega"
3034
gomegatypes "github.com/onsi/gomega/types"
3135

36+
batchv1 "k8s.io/api/batch/v1"
3237
corev1 "k8s.io/api/core/v1"
3338
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
39+
apiruntime "k8s.io/apimachinery/pkg/runtime"
3440
clientset "k8s.io/client-go/kubernetes"
41+
k8sscheme "k8s.io/client-go/kubernetes/scheme"
3542
)
3643

44+
var packagePath string
45+
3746
type k8sLabels map[string]string
3847

3948
// eventuallyNonControlPlaneNodes is a helper for asserting node properties
@@ -254,3 +263,71 @@ func getNode(nodes []corev1.Node, nodeName string) corev1.Node {
254263
}
255264
return corev1.Node{}
256265
}
266+
267+
// CreateOrUpdateJobsFromFile creates or updates jobs from a file
268+
func CreateOrUpdateJobsFromFile(ctx context.Context, cli clientset.Interface, filename, namespace string) ([]string, error) {
269+
jobs, err := newJobFromfile(filepath.Join(packagePath, "data", filename))
270+
if err != nil {
271+
return nil, fmt.Errorf("failed to create Pod from file: %w", err)
272+
}
273+
274+
names := make([]string, len(jobs))
275+
for i, job := range jobs {
276+
job.Namespace = namespace
277+
278+
names[i] = job.Name
279+
280+
_, err := cli.BatchV1().Jobs(namespace).Get(ctx, job.Name, metav1.GetOptions{})
281+
if err != nil {
282+
return nil, fmt.Errorf("failed to create Pod: %w", err)
283+
}
284+
}
285+
return names, nil
286+
}
287+
288+
func newJobFromfile(path string) ([]*batchv1.Job, error) {
289+
objs, err := apiObjsFromFile(path, k8sscheme.Codecs.UniversalDeserializer())
290+
if err != nil {
291+
return nil, err
292+
}
293+
294+
jobs := make([]*batchv1.Job, len(objs))
295+
296+
for i, obj := range objs {
297+
var ok bool
298+
jobs[i], ok = obj.(*batchv1.Job)
299+
if !ok {
300+
return nil, fmt.Errorf("unexpected type %t when reading %q", obj, path)
301+
}
302+
}
303+
304+
return jobs, nil
305+
}
306+
func apiObjsFromFile(path string, decoder apiruntime.Decoder) ([]apiruntime.Object, error) {
307+
data, err := os.ReadFile(path)
308+
if err != nil {
309+
return nil, err
310+
}
311+
312+
// TODO: find out a nicer way to decode multiple api objects from a single
313+
// file (K8s must have that somewhere)
314+
split := bytes.Split(data, []byte("---"))
315+
objs := []apiruntime.Object{}
316+
317+
for _, slice := range split {
318+
if len(slice) == 0 {
319+
continue
320+
}
321+
obj, _, err := decoder.Decode(slice, nil, nil)
322+
if err != nil {
323+
return nil, err
324+
}
325+
objs = append(objs, obj)
326+
}
327+
return objs, err
328+
}
329+
330+
func init() {
331+
_, thisFile, _, _ := runtime.Caller(0)
332+
packagePath = filepath.Dir(thisFile)
333+
}

0 commit comments

Comments
 (0)