Skip to content

Commit c35d8a7

Browse files
committed
feat: add workload test case for external tests
Signed-off-by: Patrick J.P. Culp <jpculp@amazon.com>
1 parent 78811ac commit c35d8a7

File tree

2 files changed

+193
-0
lines changed

2 files changed

+193
-0
lines changed

test/cases/workload/main_test.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
//go:build e2e
2+
3+
package workload
4+
5+
import (
6+
"context"
7+
"flag"
8+
"log"
9+
"os"
10+
"os/signal"
11+
"testing"
12+
13+
"sigs.k8s.io/e2e-framework/pkg/env"
14+
"sigs.k8s.io/e2e-framework/pkg/envconf"
15+
)
16+
17+
var (
18+
testenv env.Environment
19+
workloadTestCommand *string
20+
workloadTestImage *string
21+
workloadTestName *string
22+
workloadTestAccelerator *string
23+
)
24+
25+
func TestMain(m *testing.M) {
26+
workloadTestCommand = flag.String("workloadTestCommand", "", "command for workload test")
27+
workloadTestImage = flag.String("workloadTestImage", "", "image for workload test")
28+
workloadTestName = flag.String("workloadTestName", "workload-test", "name for workload test")
29+
workloadTestAccelerator = flag.String("workloadTestAccelerator", "", "accelerator for workload test: neuron, nvidia")
30+
cfg, err := envconf.NewFromFlags()
31+
if err != nil {
32+
log.Fatalf("failed to initialize test environment: %v", err)
33+
}
34+
testenv = env.NewWithConfig(cfg)
35+
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
36+
defer cancel()
37+
testenv = testenv.WithContext(ctx)
38+
39+
testenv.Setup(func(ctx context.Context, config *envconf.Config) (context.Context, error) {
40+
log.Println("Starting workload test suite...")
41+
return ctx, nil
42+
})
43+
44+
os.Exit(testenv.Run(m))
45+
}
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
//go:build e2e
2+
3+
package workload
4+
5+
import (
6+
"context"
7+
"testing"
8+
"time"
9+
10+
fwext "github.com/aws/aws-k8s-tester/internal/e2e"
11+
batchv1 "k8s.io/api/batch/v1"
12+
corev1 "k8s.io/api/core/v1"
13+
"k8s.io/apimachinery/pkg/api/resource"
14+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
15+
"sigs.k8s.io/e2e-framework/klient/wait"
16+
"sigs.k8s.io/e2e-framework/pkg/envconf"
17+
"sigs.k8s.io/e2e-framework/pkg/features"
18+
)
19+
20+
func createWorkloadJob(name, image, command, accelerator string) *batchv1.Job {
21+
backoffLimit := int32(4)
22+
job := &batchv1.Job{
23+
ObjectMeta: metav1.ObjectMeta{
24+
Name: name,
25+
Namespace: corev1.NamespaceDefault,
26+
Labels: map[string]string{"app": name},
27+
},
28+
Spec: batchv1.JobSpec{
29+
BackoffLimit: &backoffLimit,
30+
Template: corev1.PodTemplateSpec{
31+
ObjectMeta: metav1.ObjectMeta{
32+
Labels: map[string]string{"app": name},
33+
},
34+
Spec: corev1.PodSpec{
35+
RestartPolicy: corev1.RestartPolicyNever,
36+
Containers: []corev1.Container{
37+
{
38+
Name: name,
39+
Image: image,
40+
Command: []string{"/bin/bash", "-c"},
41+
Args: []string{command},
42+
ImagePullPolicy: corev1.PullAlways,
43+
},
44+
},
45+
},
46+
},
47+
},
48+
}
49+
50+
switch accelerator {
51+
case "neuron":
52+
job.Spec.Template.Spec.Containers[0].Resources = corev1.ResourceRequirements{
53+
Limits: corev1.ResourceList{
54+
"aws.amazon.com/neuron": resource.MustParse("1"),
55+
},
56+
Requests: corev1.ResourceList{
57+
"aws.amazon.com/neuron": resource.MustParse("1"),
58+
},
59+
}
60+
case "nvidia":
61+
job.Spec.Template.Spec.Containers[0].Resources = corev1.ResourceRequirements{
62+
Limits: corev1.ResourceList{
63+
"nvidia.com/gpu": resource.MustParse("1"),
64+
},
65+
Requests: corev1.ResourceList{
66+
"nvidia.com/gpu": resource.MustParse("1"),
67+
},
68+
}
69+
}
70+
71+
return job
72+
}
73+
74+
func TestWorkload(t *testing.T) {
75+
if *workloadTestName == "" {
76+
t.Fatal("workloadTestName must be set to run the test")
77+
}
78+
if *workloadTestCommand == "" {
79+
t.Fatal("workloadTestCommand must be set to run the test")
80+
}
81+
if *workloadTestImage == "" {
82+
t.Fatal("workloadTestImage must be set to run the test")
83+
}
84+
if *workloadTestAccelerator != "" && *workloadTestAccelerator != "neuron" && *workloadTestAccelerator != "nvidia" {
85+
t.Fatalf("Invalid acceleration type '%s', must be 'neuron' or 'nvidia'", *workloadTestAccelerator)
86+
}
87+
88+
feature := features.New(*workloadTestName).
89+
WithLabel("suite", "workload")
90+
91+
switch *workloadTestAccelerator {
92+
case "neuron":
93+
feature = feature.WithLabel("hardware", "neuron")
94+
case "nvidia":
95+
feature = feature.WithLabel("hardware", "gpu")
96+
}
97+
98+
workload := feature.Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
99+
job := createWorkloadJob(*workloadTestName, *workloadTestImage, *workloadTestCommand, *workloadTestAccelerator)
100+
if *workloadTestAccelerator != "" {
101+
t.Logf("Creating %s job with %s acceleration", *workloadTestName, *workloadTestAccelerator)
102+
} else {
103+
t.Logf("Creating %s job", *workloadTestName)
104+
}
105+
if err := cfg.Client().Resources().Create(ctx, job); err != nil {
106+
t.Fatal(err)
107+
}
108+
t.Logf("%s job created successfully", *workloadTestName)
109+
return ctx
110+
}).
111+
Assess("Job succeeds", func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
112+
job := &batchv1.Job{
113+
ObjectMeta: metav1.ObjectMeta{Name: *workloadTestName, Namespace: corev1.NamespaceDefault},
114+
}
115+
t.Logf("Waiting for %s job to complete", *workloadTestName)
116+
err := wait.For(fwext.NewConditionExtension(cfg.Client().Resources()).JobSucceeded(job),
117+
wait.WithContext(ctx),
118+
wait.WithTimeout(time.Minute*20),
119+
)
120+
if err != nil {
121+
t.Fatal(err)
122+
}
123+
return ctx
124+
}).
125+
Teardown(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
126+
log, err := fwext.GetJobLogs(cfg.Client().RESTConfig(), &batchv1.Job{
127+
ObjectMeta: metav1.ObjectMeta{Name: *workloadTestName, Namespace: corev1.NamespaceDefault},
128+
})
129+
if err != nil {
130+
t.Error(err)
131+
}
132+
t.Logf("Test log for %s:", *workloadTestName)
133+
t.Log(log)
134+
job := &batchv1.Job{
135+
ObjectMeta: metav1.ObjectMeta{Name: *workloadTestName, Namespace: corev1.NamespaceDefault},
136+
}
137+
if err := cfg.Client().Resources().Delete(ctx, job, func(do *metav1.DeleteOptions) {
138+
policy := metav1.DeletePropagationBackground
139+
do.PropagationPolicy = &policy
140+
}); err != nil {
141+
t.Error(err)
142+
}
143+
return ctx
144+
}).
145+
Feature()
146+
147+
testenv.Test(t, workload)
148+
}

0 commit comments

Comments
 (0)