Fit tests: add DRA-aware test cases

This commit is contained in:
Ed Bartosh
2025-12-01 13:20:55 +02:00
parent 7860effc2c
commit 1820dc7535

View File

@@ -29,6 +29,7 @@ import (
resourceapi "k8s.io/api/resource/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
apiruntime "k8s.io/apimachinery/pkg/runtime"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes/fake"
@@ -1031,6 +1032,7 @@ func TestFitScore(t *testing.T) {
expectedPriorities fwk.NodeScoreList
nodeResourcesFitArgs config.NodeResourcesFitArgs
runPreScore bool
draObjects []apiruntime.Object
}{
{
name: "test case for ScoringStrategy RequestedToCapacityRatio case1",
@@ -1250,11 +1252,57 @@ func TestFitScore(t *testing.T) {
},
runPreScore: true,
},
{
name: "test case for ScoringStrategy LeastAllocated with Extended resources",
requestedPod: st.MakePod().Req(map[v1.ResourceName]string{extendedResourceDRA: "1"}).Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node1").Obj(),
st.MakeNode().Name("node2").Obj(),
},
expectedPriorities: []fwk.NodeScore{{Name: "node1", Score: 66}, {Name: "node2", Score: 50}},
draObjects: []apiruntime.Object{
deviceClassWithExtendResourceName,
st.MakeResourceSlice("node1", "test-driver").Device("device-1").Device("device-2").Device("device-3").Obj(),
st.MakeResourceSlice("node2", "test-driver").Device("device-1").Device("device-2").Obj(),
},
nodeResourcesFitArgs: config.NodeResourcesFitArgs{
ScoringStrategy: &config.ScoringStrategy{
Type: config.LeastAllocated,
Resources: []config.ResourceSpec{
{Name: extendedResourceName, Weight: 1},
},
},
},
runPreScore: true,
},
{
name: "test case for ScoringStrategy LeastAllocated with Extended resources if PreScore is not called",
requestedPod: st.MakePod().Req(map[v1.ResourceName]string{extendedResourceDRA: "1"}).Obj(),
nodes: []*v1.Node{
st.MakeNode().Name("node1").Obj(),
st.MakeNode().Name("node2").Obj(),
},
expectedPriorities: []fwk.NodeScore{{Name: "node1", Score: 66}, {Name: "node2", Score: 50}},
draObjects: []apiruntime.Object{
deviceClassWithExtendResourceName,
st.MakeResourceSlice("node1", "test-driver").Device("device-1").Device("device-2").Device("device-3").Obj(),
st.MakeResourceSlice("node2", "test-driver").Device("device-1").Device("device-2").Obj(),
},
nodeResourcesFitArgs: config.NodeResourcesFitArgs{
ScoringStrategy: &config.ScoringStrategy{
Type: config.LeastAllocated,
Resources: []config.ResourceSpec{
{Name: extendedResourceName, Weight: 1},
},
},
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
_, ctx := ktesting.NewTestContext(t)
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.DRAExtendedResource, test.draObjects != nil)
logger, ctx := ktesting.NewTestContext(t)
ctx, cancel := context.WithCancel(ctx)
defer cancel()
@@ -1262,11 +1310,21 @@ func TestFitScore(t *testing.T) {
snapshot := cache.NewSnapshot(test.existingPods, test.nodes)
fh, _ := runtime.NewFramework(ctx, nil, nil, runtime.WithSnapshotSharedLister(snapshot))
args := test.nodeResourcesFitArgs
p, err := NewFit(ctx, &args, fh, plfeature.Features{})
p, err := NewFit(ctx, &args, fh, plfeature.Features{
EnableDRAExtendedResource: test.draObjects != nil,
})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if test.draObjects != nil {
draManager, err := newTestDRAManager(t, ctx, logger, test.draObjects...)
if err != nil {
t.Fatalf("failed to create test DRA manager: %v", err)
}
p.(*Fit).draManager = draManager
}
var gotPriorities fwk.NodeScoreList
for _, n := range test.nodes {
if test.runPreScore {
@@ -2143,3 +2201,92 @@ func TestHaveAnyRequestedResourcesIncreased(t *testing.T) {
})
}
}
func TestFitSignPod(t *testing.T) {
tests := map[string]struct {
name string
pod *v1.Pod
enableDRAExtendedResource bool
expectedFragments []fwk.SignFragment
expectedStatusCode fwk.Code
}{
"pod with CPU and memory requests": {
pod: st.MakePod().Req(map[v1.ResourceName]string{
v1.ResourceCPU: "1000m",
v1.ResourceMemory: "2000",
}).Obj(),
enableDRAExtendedResource: false,
expectedFragments: []fwk.SignFragment{
{Key: fwk.ResourcesSignerName, Value: computePodResourceRequest(st.MakePod().Req(map[v1.ResourceName]string{
v1.ResourceCPU: "1000m",
v1.ResourceMemory: "2000",
}).Obj(), ResourceRequestsOptions{})},
},
expectedStatusCode: fwk.Success,
},
"best-effort pod with no requests": {
pod: st.MakePod().Obj(),
enableDRAExtendedResource: false,
expectedFragments: []fwk.SignFragment{
{Key: fwk.ResourcesSignerName, Value: computePodResourceRequest(st.MakePod().Obj(), ResourceRequestsOptions{})},
},
expectedStatusCode: fwk.Success,
},
"pod with multiple containers": {
pod: st.MakePod().Container("container1").Req(map[v1.ResourceName]string{
v1.ResourceCPU: "500m",
v1.ResourceMemory: "1000",
}).Container("container2").Req(map[v1.ResourceName]string{
v1.ResourceCPU: "1500m",
v1.ResourceMemory: "3000",
}).Obj(),
enableDRAExtendedResource: false,
expectedFragments: []fwk.SignFragment{
{Key: fwk.ResourcesSignerName, Value: computePodResourceRequest(st.MakePod().Container("container1").Req(map[v1.ResourceName]string{
v1.ResourceCPU: "500m",
v1.ResourceMemory: "1000",
}).Container("container2").Req(map[v1.ResourceName]string{
v1.ResourceCPU: "1500m",
v1.ResourceMemory: "3000",
}).Obj(), ResourceRequestsOptions{})},
},
expectedStatusCode: fwk.Success,
},
"DRA extended resource enabled - returns unschedulable": {
pod: st.MakePod().Req(map[v1.ResourceName]string{
v1.ResourceCPU: "1000m",
v1.ResourceMemory: "2000",
}).Obj(),
enableDRAExtendedResource: true,
expectedFragments: nil,
expectedStatusCode: fwk.Unschedulable,
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
_, ctx := ktesting.NewTestContext(t)
fh, _ := runtime.NewFramework(ctx, nil, nil)
p, err := NewFit(ctx, &config.NodeResourcesFitArgs{ScoringStrategy: defaultScoringStrategy}, fh, plfeature.Features{
EnableDRAExtendedResource: test.enableDRAExtendedResource,
})
if err != nil {
t.Fatalf("failed to create plugin: %v", err)
}
fit := p.(*Fit)
fragments, status := fit.SignPod(ctx, test.pod)
if status.Code() != test.expectedStatusCode {
t.Errorf("unexpected status code, want: %v, got: %v, message: %v", test.expectedStatusCode, status.Code(), status.Message())
}
if test.expectedStatusCode == fwk.Success {
if diff := cmp.Diff(test.expectedFragments, fragments); diff != "" {
t.Errorf("unexpected fragments, diff (-want,+got):\n%s", diff)
}
}
})
}
}