diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json index 60fed4a0caa..2042fec737a 100644 --- a/api/openapi-spec/swagger.json +++ b/api/openapi-spec/swagger.json @@ -16024,7 +16024,7 @@ "x-kubernetes-list-type": "atomic" }, "extendedResourceName": { - "description": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is an alpha field.", + "description": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is a beta field.", "type": "string" }, "selectors": { @@ -17371,7 +17371,7 @@ "x-kubernetes-list-type": "atomic" }, "extendedResourceName": { - "description": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is an alpha field.", + "description": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is a beta field.", "type": "string" }, "selectors": { @@ -18544,7 +18544,7 @@ "x-kubernetes-list-type": "atomic" }, "extendedResourceName": { - "description": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is an alpha field.", + "description": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is a beta field.", "type": "string" }, "selectors": { diff --git a/api/openapi-spec/v3/apis__resource.k8s.io__v1_openapi.json b/api/openapi-spec/v3/apis__resource.k8s.io__v1_openapi.json index 01d13db7852..500d230dd8d 100644 --- a/api/openapi-spec/v3/apis__resource.k8s.io__v1_openapi.json +++ b/api/openapi-spec/v3/apis__resource.k8s.io__v1_openapi.json @@ -716,7 +716,7 @@ "x-kubernetes-list-type": "atomic" }, "extendedResourceName": { - "description": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is an alpha field.", + "description": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is a beta field.", "type": "string" }, "selectors": { diff --git a/api/openapi-spec/v3/apis__resource.k8s.io__v1beta1_openapi.json b/api/openapi-spec/v3/apis__resource.k8s.io__v1beta1_openapi.json index 894bed9e1c0..2143612f1f1 100644 --- a/api/openapi-spec/v3/apis__resource.k8s.io__v1beta1_openapi.json +++ b/api/openapi-spec/v3/apis__resource.k8s.io__v1beta1_openapi.json @@ -730,7 +730,7 @@ "x-kubernetes-list-type": "atomic" }, "extendedResourceName": { - "description": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is an alpha field.", + "description": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is a beta field.", "type": "string" }, "selectors": { diff --git a/api/openapi-spec/v3/apis__resource.k8s.io__v1beta2_openapi.json b/api/openapi-spec/v3/apis__resource.k8s.io__v1beta2_openapi.json index dad6c5644da..bfac68305f0 100644 --- a/api/openapi-spec/v3/apis__resource.k8s.io__v1beta2_openapi.json +++ b/api/openapi-spec/v3/apis__resource.k8s.io__v1beta2_openapi.json @@ -716,7 +716,7 @@ "x-kubernetes-list-type": "atomic" }, "extendedResourceName": { - "description": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is an alpha field.", + "description": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is a beta field.", "type": "string" }, "selectors": { diff --git a/pkg/features/kube_features.go b/pkg/features/kube_features.go index 29578df5ae8..ff1af01ec5e 100644 --- a/pkg/features/kube_features.go +++ b/pkg/features/kube_features.go @@ -1262,6 +1262,7 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate DRAExtendedResource: { {Version: version.MustParse("1.34"), Default: false, PreRelease: featuregate.Alpha}, + {Version: version.MustParse("1.36"), Default: true, PreRelease: featuregate.Beta}, }, DRAPartitionableDevices: { diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index fe42636cea2..837c8425563 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -47636,7 +47636,7 @@ func schema_k8sio_api_resource_v1_DeviceClassSpec(ref common.ReferenceCallback) }, "extendedResourceName": { SchemaProps: spec.SchemaProps{ - Description: "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is an alpha field.", + Description: "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is a beta field.", Type: []string{"string"}, Format: "", }, @@ -50144,7 +50144,7 @@ func schema_k8sio_api_resource_v1beta1_DeviceClassSpec(ref common.ReferenceCallb }, "extendedResourceName": { SchemaProps: spec.SchemaProps{ - Description: "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is an alpha field.", + Description: "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is a beta field.", Type: []string{"string"}, Format: "", }, @@ -52316,7 +52316,7 @@ func schema_k8sio_api_resource_v1beta2_DeviceClassSpec(ref common.ReferenceCallb }, "extendedResourceName": { SchemaProps: spec.SchemaProps{ - Description: "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is an alpha field.", + Description: "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is a beta field.", Type: []string{"string"}, Format: "", }, diff --git a/pkg/scheduler/framework/plugins/noderesources/balanced_allocation.go b/pkg/scheduler/framework/plugins/noderesources/balanced_allocation.go index 36041fb8d33..6a87b04226d 100644 --- a/pkg/scheduler/framework/plugins/noderesources/balanced_allocation.go +++ b/pkg/scheduler/framework/plugins/noderesources/balanced_allocation.go @@ -123,9 +123,18 @@ func (pl *BalancedAllocation) SignPod(ctx context.Context, pod *v1.Pod) ([]fwk.S EnablePodLevelResources: pl.enablePodLevelResources, EnableDRAExtendedResource: pl.enableDRAExtendedResource, } - if pl.enableDRAExtendedResource { - return nil, fwk.NewStatus(fwk.Unschedulable, "signature disabled when dra extended resources enabled") + podRequest := computePodResourceRequest(pod, opts) + for rName, rQuant := range podRequest.ScalarResources { + // Skip in case request quantity is zero + if rQuant == 0 { + continue + } + + if shouldDelegateResourceToDRA(rName, nil, pl.draManager, opts) { + return nil, fwk.NewStatus(fwk.Unschedulable, "signature disabled when dra extended resources are used in the cluster") + } + } } return []fwk.SignFragment{ @@ -187,6 +196,7 @@ func NewBalancedAllocation(_ context.Context, baArgs runtime.Object, h fwk.Handl useRequested: true, resources: args.Resources, enableInPlacePodLevelResourcesVerticalScaling: fts.EnableInPlacePodLevelResourcesVerticalScaling, + draManager: h.SharedDRAManager(), }, }, nil } diff --git a/pkg/scheduler/framework/plugins/noderesources/balanced_allocation_test.go b/pkg/scheduler/framework/plugins/noderesources/balanced_allocation_test.go index 23346916d84..fbe258037c1 100644 --- a/pkg/scheduler/framework/plugins/noderesources/balanced_allocation_test.go +++ b/pkg/scheduler/framework/plugins/noderesources/balanced_allocation_test.go @@ -29,6 +29,7 @@ import ( "k8s.io/kubernetes/pkg/scheduler/apis/config" "k8s.io/kubernetes/pkg/scheduler/backend/cache" "k8s.io/kubernetes/pkg/scheduler/framework" + "k8s.io/kubernetes/pkg/scheduler/framework/plugins/dynamicresources" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/feature" "k8s.io/kubernetes/pkg/scheduler/framework/runtime" st "k8s.io/kubernetes/pkg/scheduler/testing" @@ -359,16 +360,19 @@ func testNodeResourcesBalancedAllocation(tCtx ktesting.TContext) { } func TestBalancedAllocationSignPod(t *testing.T) { + testBalancedAllocationSignPod(ktesting.Init(t)) +} +func testBalancedAllocationSignPod(tCtx ktesting.TContext) { tests := map[string]struct { - name string - pod *v1.Pod - enableDRAExtendedResource bool - expectedFragments []fwk.SignFragment - expectedStatusCode fwk.Code + name string + pod *v1.Pod + disableDRAExtendedResource bool + expectedFragments []fwk.SignFragment + expectedStatusCode fwk.Code }{ "pod with CPU and memory requests": { - pod: st.MakePod().Req(cpuAndMemory("1000m", "2000")).Obj(), - enableDRAExtendedResource: false, + pod: st.MakePod().Req(cpuAndMemory("1000m", "2000")).Obj(), + disableDRAExtendedResource: true, expectedFragments: []fwk.SignFragment{ {Key: fwk.ResourcesSignerName, Value: computePodResourceRequest( st.MakePod().Req(cpuAndMemory("1000m", "2000")).Obj(), ResourceRequestsOptions{})}, @@ -376,8 +380,8 @@ func TestBalancedAllocationSignPod(t *testing.T) { expectedStatusCode: fwk.Success, }, "best-effort pod with no requests": { - pod: st.MakePod().Obj(), - enableDRAExtendedResource: false, + pod: st.MakePod().Obj(), + disableDRAExtendedResource: true, expectedFragments: []fwk.SignFragment{ {Key: fwk.ResourcesSignerName, Value: computePodResourceRequest(st.MakePod().Obj(), ResourceRequestsOptions{})}, }, @@ -387,7 +391,7 @@ func TestBalancedAllocationSignPod(t *testing.T) { pod: st.MakePod(). Container("container1").Req(cpuAndMemory("500m", "1000")). Container("container2").Req(cpuAndMemory("1500m", "3000")).Obj(), - enableDRAExtendedResource: false, + disableDRAExtendedResource: true, expectedFragments: []fwk.SignFragment{ {Key: fwk.ResourcesSignerName, Value: computePodResourceRequest(st.MakePod(). Container("container1").Req(cpuAndMemory("500m", "1000")). @@ -396,34 +400,68 @@ func TestBalancedAllocationSignPod(t *testing.T) { expectedStatusCode: fwk.Success, }, "DRA extended resource enabled - returns unschedulable": { - pod: st.MakePod().Req(cpuAndMemory("1000m", "2000")).Obj(), - enableDRAExtendedResource: true, - expectedFragments: nil, - expectedStatusCode: fwk.Unschedulable, + pod: st.MakePod().Req( + map[v1.ResourceName]string{ + v1.ResourceCPU: "1000m", + v1.ResourceMemory: "2000", + v1.ResourceName(extendedResourceName): "1", + }).Obj(), + disableDRAExtendedResource: false, + expectedFragments: nil, + expectedStatusCode: fwk.Unschedulable, + }, + "DRA extended resource disabled": { + pod: st.MakePod().Req( + map[v1.ResourceName]string{ + v1.ResourceCPU: "1000m", + v1.ResourceMemory: "2000", + v1.ResourceName(extendedResourceName): "1", + }).Obj(), + disableDRAExtendedResource: true, + expectedFragments: []fwk.SignFragment{ + {Key: fwk.ResourcesSignerName, Value: computePodResourceRequest(st.MakePod(). + Container("container1").Req( + map[v1.ResourceName]string{ + v1.ResourceCPU: "1000m", + v1.ResourceMemory: "2000", + v1.ResourceName(extendedResourceName): "1", + }).Obj(), ResourceRequestsOptions{})}, + }, + expectedStatusCode: fwk.Success, }, } for name, test := range tests { - t.Run(name, func(t *testing.T) { - _, ctx := ktesting.NewTestContext(t) + tCtx.SyncTest(name, func(tCtx ktesting.TContext) { + runOpts := []runtime.Option{} + var testDRAManager *dynamicresources.DefaultDRAManager + if !test.disableDRAExtendedResource { + testDRAManager = newTestDRAManager(tCtx, deviceClassWithExtendResourceName) + runOpts = append(runOpts, runtime.WithSharedDRAManager(testDRAManager)) + } + fh, _ := runtime.NewFramework(tCtx, nil, nil, runOpts...) + defer func() { + tCtx.Cancel("test has completed") + runtime.WaitForShutdown(fh) + }() - p, err := NewBalancedAllocation(ctx, &config.NodeResourcesBalancedAllocationArgs{}, nil, feature.Features{ - EnableDRAExtendedResource: test.enableDRAExtendedResource, + p, err := NewBalancedAllocation(tCtx, &config.NodeResourcesBalancedAllocationArgs{}, fh, feature.Features{ + EnableDRAExtendedResource: !test.disableDRAExtendedResource, }) if err != nil { - t.Fatalf("failed to create plugin: %v", err) + tCtx.Fatalf("failed to create plugin: %v", err) } ba := p.(*BalancedAllocation) - fragments, status := ba.SignPod(ctx, test.pod) + fragments, status := ba.SignPod(tCtx, test.pod) if status.Code() != test.expectedStatusCode { - t.Errorf("unexpected status code, want: %v, got: %v, message: %v", test.expectedStatusCode, status.Code(), status.Message()) + tCtx.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) + tCtx.Errorf("unexpected fragments, diff (-want,+got):\n%s", diff) } } }) diff --git a/pkg/scheduler/framework/plugins/noderesources/fit.go b/pkg/scheduler/framework/plugins/noderesources/fit.go index f20749e38d9..061284f3c94 100644 --- a/pkg/scheduler/framework/plugins/noderesources/fit.go +++ b/pkg/scheduler/framework/plugins/noderesources/fit.go @@ -177,8 +177,18 @@ func (pl *Fit) SignPod(ctx context.Context, pod *v1.Pod) ([]fwk.SignFragment, *f EnableDRAExtendedResource: pl.enableDRAExtendedResource, } if pl.enableDRAExtendedResource { - return nil, fwk.NewStatus(fwk.Unschedulable, "signature disabled when dra extended resources enabled") + podRequest := computePodResourceRequest(pod, opts) + for rName, rQuant := range podRequest.ScalarResources { + // Skip in case request quantity is zero + if rQuant == 0 { + continue + } + if shouldDelegateResourceToDRA(rName, nil, pl.draManager, opts) { + return nil, fwk.NewStatus(fwk.Unschedulable, "signature disabled when dra extended resources are used in the cluster") + } + } } + return []fwk.SignFragment{ {Key: fwk.ResourcesSignerName, Value: computePodResourceRequest(pod, opts)}, }, nil @@ -243,8 +253,10 @@ func shouldDelegateResourceToDRA(rName v1.ResourceName, nodeInfo fwk.NodeInfo, d return false } - if allocatable := nodeInfo.GetAllocatable().GetScalarResources()[rName]; allocatable > 0 { - return false + if nodeInfo != nil { + if allocatable := nodeInfo.GetAllocatable().GetScalarResources()[rName]; allocatable > 0 { + return false + } } if draManager == nil { diff --git a/pkg/scheduler/framework/plugins/noderesources/fit_test.go b/pkg/scheduler/framework/plugins/noderesources/fit_test.go index 9e07442b2ef..18f7b8ae537 100644 --- a/pkg/scheduler/framework/plugins/noderesources/fit_test.go +++ b/pkg/scheduler/framework/plugins/noderesources/fit_test.go @@ -2173,19 +2173,22 @@ func testHaveAnyRequestedResourcesIncreased(tCtx ktesting.TContext) { } func TestFitSignPod(t *testing.T) { + testFitSignPod(ktesting.Init(t)) +} +func testFitSignPod(tCtx ktesting.TContext) { tests := map[string]struct { - name string - pod *v1.Pod - enableDRAExtendedResource bool - expectedFragments []fwk.SignFragment - expectedStatusCode fwk.Code + name string + pod *v1.Pod + disableDRAExtendedResource 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, + disableDRAExtendedResource: true, expectedFragments: []fwk.SignFragment{ {Key: fwk.ResourcesSignerName, Value: computePodResourceRequest(st.MakePod().Req(map[v1.ResourceName]string{ v1.ResourceCPU: "1000m", @@ -2195,8 +2198,8 @@ func TestFitSignPod(t *testing.T) { expectedStatusCode: fwk.Success, }, "best-effort pod with no requests": { - pod: st.MakePod().Obj(), - enableDRAExtendedResource: false, + pod: st.MakePod().Obj(), + disableDRAExtendedResource: true, expectedFragments: []fwk.SignFragment{ {Key: fwk.ResourcesSignerName, Value: computePodResourceRequest(st.MakePod().Obj(), ResourceRequestsOptions{})}, }, @@ -2210,7 +2213,7 @@ func TestFitSignPod(t *testing.T) { v1.ResourceCPU: "1500m", v1.ResourceMemory: "3000", }).Obj(), - enableDRAExtendedResource: false, + disableDRAExtendedResource: true, expectedFragments: []fwk.SignFragment{ {Key: fwk.ResourcesSignerName, Value: computePodResourceRequest(st.MakePod().Container("container1").Req(map[v1.ResourceName]string{ v1.ResourceCPU: "500m", @@ -2224,37 +2227,66 @@ func TestFitSignPod(t *testing.T) { }, "DRA extended resource enabled - returns unschedulable": { pod: st.MakePod().Req(map[v1.ResourceName]string{ - v1.ResourceCPU: "1000m", - v1.ResourceMemory: "2000", + v1.ResourceCPU: "1000m", + v1.ResourceMemory: "2000", + v1.ResourceName(extendedResourceName): "1", }).Obj(), - enableDRAExtendedResource: true, - expectedFragments: nil, - expectedStatusCode: fwk.Unschedulable, + disableDRAExtendedResource: false, + expectedFragments: nil, + expectedStatusCode: fwk.Unschedulable, + }, + "DRA extended resource disabled": { + pod: st.MakePod().Req( + map[v1.ResourceName]string{ + v1.ResourceCPU: "1000m", + v1.ResourceMemory: "2000", + v1.ResourceName(extendedResourceName): "1", + }).Obj(), + disableDRAExtendedResource: true, + expectedFragments: []fwk.SignFragment{ + {Key: fwk.ResourcesSignerName, Value: computePodResourceRequest(st.MakePod(). + Container("container1").Req( + map[v1.ResourceName]string{ + v1.ResourceCPU: "1000m", + v1.ResourceMemory: "2000", + v1.ResourceName(extendedResourceName): "1", + }).Obj(), ResourceRequestsOptions{})}, + }, + expectedStatusCode: fwk.Success, }, } for name, test := range tests { - t.Run(name, func(t *testing.T) { - _, ctx := ktesting.NewTestContext(t) + tCtx.SyncTest(name, func(tCtx ktesting.TContext) { + runOpts := []runtime.Option{} + var testDRAManager *dynamicresources.DefaultDRAManager + if !test.disableDRAExtendedResource { + testDRAManager = newTestDRAManager(tCtx, deviceClassWithExtendResourceName) + runOpts = append(runOpts, runtime.WithSharedDRAManager(testDRAManager)) + } + fh, _ := runtime.NewFramework(tCtx, nil, nil, runOpts...) + defer func() { + tCtx.Cancel("test has completed") + runtime.WaitForShutdown(fh) + }() - fh, _ := runtime.NewFramework(ctx, nil, nil) - p, err := NewFit(ctx, &config.NodeResourcesFitArgs{ScoringStrategy: defaultScoringStrategy}, fh, plfeature.Features{ - EnableDRAExtendedResource: test.enableDRAExtendedResource, + p, err := NewFit(tCtx, &config.NodeResourcesFitArgs{ScoringStrategy: defaultScoringStrategy}, fh, plfeature.Features{ + EnableDRAExtendedResource: !test.disableDRAExtendedResource, }) if err != nil { - t.Fatalf("failed to create plugin: %v", err) + tCtx.Fatalf("failed to create plugin: %v", err) } fit := p.(*Fit) - fragments, status := fit.SignPod(ctx, test.pod) + fragments, status := fit.SignPod(tCtx, test.pod) if status.Code() != test.expectedStatusCode { - t.Errorf("unexpected status code, want: %v, got: %v, message: %v", test.expectedStatusCode, status.Code(), status.Message()) + tCtx.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) + tCtx.Errorf("unexpected fragments, diff (-want,+got):\n%s", diff) } } }) diff --git a/plugin/pkg/admission/resourcequota/admission_test.go b/plugin/pkg/admission/resourcequota/admission_test.go index 5f49cedde7b..54ea3f288b0 100644 --- a/plugin/pkg/admission/resourcequota/admission_test.go +++ b/plugin/pkg/admission/resourcequota/admission_test.go @@ -107,7 +107,7 @@ func createHandlerWithConfig(kubeClient kubernetes.Interface, informerFactory in if config == nil { config = &resourcequotaapi.Configuration{} } - quotaConfiguration, err := install.NewQuotaConfigurationForAdmission(nil, nil) + quotaConfiguration, err := install.NewQuotaConfigurationForAdmission(informerFactory, nil) if err != nil { return nil, err } diff --git a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles.yaml b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles.yaml index e8e1ac600fc..c46dd7756e6 100644 --- a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles.yaml +++ b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles.yaml @@ -944,6 +944,13 @@ items: - get - list - watch + - apiGroups: + - resource.k8s.io + resources: + - resourceclaims + verbs: + - create + - delete - apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: diff --git a/staging/src/k8s.io/api/resource/v1/generated.proto b/staging/src/k8s.io/api/resource/v1/generated.proto index 02684b4163e..f822ec8406b 100644 --- a/staging/src/k8s.io/api/resource/v1/generated.proto +++ b/staging/src/k8s.io/api/resource/v1/generated.proto @@ -707,7 +707,7 @@ message DeviceClassSpec { // If two classes are created at the same time, then the name of the class // lexicographically sorted first is picked. // - // This is an alpha field. + // This is a beta field. // +optional // +featureGate=DRAExtendedResource // +k8s:alpha(since: "1.36")=+k8s:optional diff --git a/staging/src/k8s.io/api/resource/v1/types.go b/staging/src/k8s.io/api/resource/v1/types.go index 2ed5ae0aefe..a19c8a2f65a 100644 --- a/staging/src/k8s.io/api/resource/v1/types.go +++ b/staging/src/k8s.io/api/resource/v1/types.go @@ -1832,7 +1832,7 @@ type DeviceClassSpec struct { // If two classes are created at the same time, then the name of the class // lexicographically sorted first is picked. // - // This is an alpha field. + // This is a beta field. // +optional // +featureGate=DRAExtendedResource // +k8s:alpha(since: "1.36")=+k8s:optional diff --git a/staging/src/k8s.io/api/resource/v1/types_swagger_doc_generated.go b/staging/src/k8s.io/api/resource/v1/types_swagger_doc_generated.go index c5d7aa393b8..86fa58ad420 100644 --- a/staging/src/k8s.io/api/resource/v1/types_swagger_doc_generated.go +++ b/staging/src/k8s.io/api/resource/v1/types_swagger_doc_generated.go @@ -226,7 +226,7 @@ var map_DeviceClassSpec = map[string]string{ "": "DeviceClassSpec is used in a [DeviceClass] to define what can be allocated and how to configure it.", "selectors": "Each selector must be satisfied by a device which is claimed via this class.", "config": "Config defines configuration parameters that apply to each device that is claimed via this class. Some classses may potentially be satisfied by multiple drivers, so each instance of a vendor configuration applies to exactly one driver.\n\nThey are passed to the driver, but are not considered while allocating the claim.", - "extendedResourceName": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is an alpha field.", + "extendedResourceName": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is a beta field.", } func (DeviceClassSpec) SwaggerDoc() map[string]string { diff --git a/staging/src/k8s.io/api/resource/v1beta1/generated.proto b/staging/src/k8s.io/api/resource/v1beta1/generated.proto index 14cec7635c0..a5d4fa92cdd 100644 --- a/staging/src/k8s.io/api/resource/v1beta1/generated.proto +++ b/staging/src/k8s.io/api/resource/v1beta1/generated.proto @@ -719,7 +719,7 @@ message DeviceClassSpec { // If two classes are created at the same time, then the name of the class // lexicographically sorted first is picked. // - // This is an alpha field. + // This is a beta field. // +optional // +featureGate=DRAExtendedResource // +k8s:alpha(since: "1.36")=+k8s:optional diff --git a/staging/src/k8s.io/api/resource/v1beta1/types.go b/staging/src/k8s.io/api/resource/v1beta1/types.go index 1242db2d1e7..8fbc0b802c4 100644 --- a/staging/src/k8s.io/api/resource/v1beta1/types.go +++ b/staging/src/k8s.io/api/resource/v1beta1/types.go @@ -1856,7 +1856,7 @@ type DeviceClassSpec struct { // If two classes are created at the same time, then the name of the class // lexicographically sorted first is picked. // - // This is an alpha field. + // This is a beta field. // +optional // +featureGate=DRAExtendedResource // +k8s:alpha(since: "1.36")=+k8s:optional diff --git a/staging/src/k8s.io/api/resource/v1beta1/types_swagger_doc_generated.go b/staging/src/k8s.io/api/resource/v1beta1/types_swagger_doc_generated.go index ad81bc05520..ec66105efb7 100644 --- a/staging/src/k8s.io/api/resource/v1beta1/types_swagger_doc_generated.go +++ b/staging/src/k8s.io/api/resource/v1beta1/types_swagger_doc_generated.go @@ -235,7 +235,7 @@ var map_DeviceClassSpec = map[string]string{ "": "DeviceClassSpec is used in a [DeviceClass] to define what can be allocated and how to configure it.", "selectors": "Each selector must be satisfied by a device which is claimed via this class.", "config": "Config defines configuration parameters that apply to each device that is claimed via this class. Some classses may potentially be satisfied by multiple drivers, so each instance of a vendor configuration applies to exactly one driver.\n\nThey are passed to the driver, but are not considered while allocating the claim.", - "extendedResourceName": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is an alpha field.", + "extendedResourceName": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is a beta field.", } func (DeviceClassSpec) SwaggerDoc() map[string]string { diff --git a/staging/src/k8s.io/api/resource/v1beta2/generated.proto b/staging/src/k8s.io/api/resource/v1beta2/generated.proto index 4fec76e2a63..d1793c68a85 100644 --- a/staging/src/k8s.io/api/resource/v1beta2/generated.proto +++ b/staging/src/k8s.io/api/resource/v1beta2/generated.proto @@ -710,7 +710,7 @@ message DeviceClassSpec { // If two classes are created at the same time, then the name of the class // lexicographically sorted first is picked. // - // This is an alpha field. + // This is a beta field. // +optional // +featureGate=DRAExtendedResource // +k8s:alpha(since: "1.36")=+k8s:optional diff --git a/staging/src/k8s.io/api/resource/v1beta2/types.go b/staging/src/k8s.io/api/resource/v1beta2/types.go index e4979efde0a..7affe6820fe 100644 --- a/staging/src/k8s.io/api/resource/v1beta2/types.go +++ b/staging/src/k8s.io/api/resource/v1beta2/types.go @@ -1843,7 +1843,7 @@ type DeviceClassSpec struct { // If two classes are created at the same time, then the name of the class // lexicographically sorted first is picked. // - // This is an alpha field. + // This is a beta field. // +optional // +featureGate=DRAExtendedResource // +k8s:alpha(since: "1.36")=+k8s:optional diff --git a/staging/src/k8s.io/api/resource/v1beta2/types_swagger_doc_generated.go b/staging/src/k8s.io/api/resource/v1beta2/types_swagger_doc_generated.go index 986fbb3837f..e17531dfd55 100644 --- a/staging/src/k8s.io/api/resource/v1beta2/types_swagger_doc_generated.go +++ b/staging/src/k8s.io/api/resource/v1beta2/types_swagger_doc_generated.go @@ -226,7 +226,7 @@ var map_DeviceClassSpec = map[string]string{ "": "DeviceClassSpec is used in a [DeviceClass] to define what can be allocated and how to configure it.", "selectors": "Each selector must be satisfied by a device which is claimed via this class.", "config": "Config defines configuration parameters that apply to each device that is claimed via this class. Some classses may potentially be satisfied by multiple drivers, so each instance of a vendor configuration applies to exactly one driver.\n\nThey are passed to the driver, but are not considered while allocating the claim.", - "extendedResourceName": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is an alpha field.", + "extendedResourceName": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is a beta field.", } func (DeviceClassSpec) SwaggerDoc() map[string]string { diff --git a/staging/src/k8s.io/client-go/applyconfigurations/resource/v1/deviceclassspec.go b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1/deviceclassspec.go index a304c7d8d2b..a6a3992c92f 100644 --- a/staging/src/k8s.io/client-go/applyconfigurations/resource/v1/deviceclassspec.go +++ b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1/deviceclassspec.go @@ -41,7 +41,7 @@ type DeviceClassSpecApplyConfiguration struct { // If two classes are created at the same time, then the name of the class // lexicographically sorted first is picked. // - // This is an alpha field. + // This is a beta field. ExtendedResourceName *string `json:"extendedResourceName,omitempty"` } diff --git a/staging/src/k8s.io/client-go/applyconfigurations/resource/v1beta1/deviceclassspec.go b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1beta1/deviceclassspec.go index 942da3efed8..c234bdd7329 100644 --- a/staging/src/k8s.io/client-go/applyconfigurations/resource/v1beta1/deviceclassspec.go +++ b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1beta1/deviceclassspec.go @@ -41,7 +41,7 @@ type DeviceClassSpecApplyConfiguration struct { // If two classes are created at the same time, then the name of the class // lexicographically sorted first is picked. // - // This is an alpha field. + // This is a beta field. ExtendedResourceName *string `json:"extendedResourceName,omitempty"` } diff --git a/staging/src/k8s.io/client-go/applyconfigurations/resource/v1beta2/deviceclassspec.go b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1beta2/deviceclassspec.go index e270c5908b9..4ae2eaa29f6 100644 --- a/staging/src/k8s.io/client-go/applyconfigurations/resource/v1beta2/deviceclassspec.go +++ b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1beta2/deviceclassspec.go @@ -41,7 +41,7 @@ type DeviceClassSpecApplyConfiguration struct { // If two classes are created at the same time, then the name of the class // lexicographically sorted first is picked. // - // This is an alpha field. + // This is a beta field. ExtendedResourceName *string `json:"extendedResourceName,omitempty"` } diff --git a/test/compatibility_lifecycle/reference/feature_list.md b/test/compatibility_lifecycle/reference/feature_list.md index 012636983c6..0a3ba234c72 100644 --- a/test/compatibility_lifecycle/reference/feature_list.md +++ b/test/compatibility_lifecycle/reference/feature_list.md @@ -55,7 +55,7 @@ | DRADeviceBindingConditions | | | 1.34– | | | | DRAResourceClaimDeviceStatus
DynamicResourceAllocation | [code](https://cs.k8s.io/?q=%5CbDRADeviceBindingConditions%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbDRADeviceBindingConditions%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | DRADeviceTaintRules | | | 1.35– | | | | DRADeviceTaints | [code](https://cs.k8s.io/?q=%5CbDRADeviceTaintRules%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbDRADeviceTaintRules%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | DRADeviceTaints | | | 1.33– | | | | DynamicResourceAllocation | [code](https://cs.k8s.io/?q=%5CbDRADeviceTaints%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbDRADeviceTaints%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | -| DRAExtendedResource | | | 1.34– | | | | DynamicResourceAllocation | [code](https://cs.k8s.io/?q=%5CbDRAExtendedResource%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbDRAExtendedResource%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | +| DRAExtendedResource | :ballot_box_with_check: 1.36+ | | 1.34–1.35 | 1.36– | | | DynamicResourceAllocation | [code](https://cs.k8s.io/?q=%5CbDRAExtendedResource%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbDRAExtendedResource%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | DRAPartitionableDevices | | | 1.33– | | | | DynamicResourceAllocation | [code](https://cs.k8s.io/?q=%5CbDRAPartitionableDevices%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbDRAPartitionableDevices%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | DRAPrioritizedList | :ballot_box_with_check: 1.34+ | | 1.33 | 1.34– | | | DynamicResourceAllocation | [code](https://cs.k8s.io/?q=%5CbDRAPrioritizedList%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbDRAPrioritizedList%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | | DRAResourceClaimDeviceStatus | :ballot_box_with_check: 1.33+ | | 1.32 | 1.33– | | | | [code](https://cs.k8s.io/?q=%5CbDRAResourceClaimDeviceStatus%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbDRAResourceClaimDeviceStatus%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) | diff --git a/test/compatibility_lifecycle/reference/versioned_feature_list.yaml b/test/compatibility_lifecycle/reference/versioned_feature_list.yaml index 8a9441929b9..b586d4f38e1 100644 --- a/test/compatibility_lifecycle/reference/versioned_feature_list.yaml +++ b/test/compatibility_lifecycle/reference/versioned_feature_list.yaml @@ -543,6 +543,10 @@ lockToDefault: false preRelease: Alpha version: "1.34" + - default: true + lockToDefault: false + preRelease: Beta + version: "1.36" - name: DRAPartitionableDevices versionedSpecs: - default: false diff --git a/test/integration/quota/quota_test.go b/test/integration/quota/quota_test.go index f3dcd4d8022..ebd96f1db55 100644 --- a/test/integration/quota/quota_test.go +++ b/test/integration/quota/quota_test.go @@ -90,7 +90,7 @@ func TestQuota(t *testing.T) { discoveryFunc := clientset.Discovery().ServerPreferredNamespacedResources listerFuncForResource := generic.ListerFuncForResourceFunc(informers.ForResource) - qc, err := quotainstall.NewQuotaConfigurationForControllers(listerFuncForResource, nil) + qc, err := quotainstall.NewQuotaConfigurationForControllers(listerFuncForResource, informers) if err != nil { t.Fatalf("unexpected err: %v", err) } @@ -322,7 +322,7 @@ plugins: discoveryFunc := clientset.Discovery().ServerPreferredNamespacedResources listerFuncForResource := generic.ListerFuncForResourceFunc(informers.ForResource) - qc, err := quotainstall.NewQuotaConfigurationForControllers(listerFuncForResource, nil) + qc, err := quotainstall.NewQuotaConfigurationForControllers(listerFuncForResource, informers) if err != nil { t.Fatalf("unexpected err: %v", err) } @@ -451,7 +451,7 @@ plugins: discoveryFunc := clientset.Discovery().ServerPreferredNamespacedResources listerFuncForResource := generic.ListerFuncForResourceFunc(informers.ForResource) - qc, err := quotainstall.NewQuotaConfigurationForControllers(listerFuncForResource, nil) + qc, err := quotainstall.NewQuotaConfigurationForControllers(listerFuncForResource, informers) if err != nil { t.Fatalf("unexpected err: %v", err) }