]> git.feebdaed.xyz Git - 0xmirror/kubernetes.git/commitdiff
Fit tests: add DRA-aware test cases
authorEd Bartosh <eduard.bartosh@intel.com>
Mon, 1 Dec 2025 11:20:55 +0000 (13:20 +0200)
committerEd Bartosh <eduard.bartosh@intel.com>
Fri, 12 Dec 2025 13:48:18 +0000 (15:48 +0200)
pkg/scheduler/framework/plugins/noderesources/fit_test.go

index 2953b71876a6ee75fdf85241a20c20cb3a9dbc7e..9c7888093a3c1e9893e19eae58bcacd94336f792 100644 (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)
+                               }
+                       }
+               })
+       }
+}