From d50f814bea47801445edf239bad71cba2ff326bf Mon Sep 17 00:00:00 2001 From: yliao Date: Mon, 3 Nov 2025 01:57:12 +0000 Subject: [PATCH 1/5] promote DRA Extended Resource feature to beta in 1.36 --- pkg/features/kube_features.go | 1 + staging/src/k8s.io/api/resource/v1/types.go | 2 +- staging/src/k8s.io/api/resource/v1beta1/types.go | 2 +- staging/src/k8s.io/api/resource/v1beta2/types.go | 2 +- test/compatibility_lifecycle/reference/feature_list.md | 2 +- .../reference/versioned_feature_list.yaml | 4 ++++ 6 files changed, 9 insertions(+), 4 deletions(-) diff --git a/pkg/features/kube_features.go b/pkg/features/kube_features.go index fd89103983f..42626102909 100644 --- a/pkg/features/kube_features.go +++ b/pkg/features/kube_features.go @@ -1228,6 +1228,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/staging/src/k8s.io/api/resource/v1/types.go b/staging/src/k8s.io/api/resource/v1/types.go index 1ea035d0033..528f3d888c7 100644 --- a/staging/src/k8s.io/api/resource/v1/types.go +++ b/staging/src/k8s.io/api/resource/v1/types.go @@ -1815,7 +1815,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:optional diff --git a/staging/src/k8s.io/api/resource/v1beta1/types.go b/staging/src/k8s.io/api/resource/v1beta1/types.go index a070049d4c8..76d9acfe77b 100644 --- a/staging/src/k8s.io/api/resource/v1beta1/types.go +++ b/staging/src/k8s.io/api/resource/v1beta1/types.go @@ -1837,7 +1837,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:optional diff --git a/staging/src/k8s.io/api/resource/v1beta2/types.go b/staging/src/k8s.io/api/resource/v1beta2/types.go index a33adb1e418..7884e58735a 100644 --- a/staging/src/k8s.io/api/resource/v1beta2/types.go +++ b/staging/src/k8s.io/api/resource/v1beta2/types.go @@ -1824,7 +1824,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:optional diff --git a/test/compatibility_lifecycle/reference/feature_list.md b/test/compatibility_lifecycle/reference/feature_list.md index 76af12ac2d1..d7c0dbf343a 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 ed916ccbb12..67c3c1a1307 100644 --- a/test/compatibility_lifecycle/reference/versioned_feature_list.yaml +++ b/test/compatibility_lifecycle/reference/versioned_feature_list.yaml @@ -535,6 +535,10 @@ lockToDefault: false preRelease: Alpha version: "1.34" + - default: true + lockToDefault: false + preRelease: Beta + version: "1.36" - name: DRAPartitionableDevices versionedSpecs: - default: false From 58da2e682f1ecba5d848da4810c49ad6baf886a1 Mon Sep 17 00:00:00 2001 From: yliao Date: Wed, 14 Jan 2026 21:34:37 +0000 Subject: [PATCH 2/5] codegen --- api/openapi-spec/swagger.json | 6 +++--- api/openapi-spec/v3/apis__resource.k8s.io__v1_openapi.json | 2 +- .../v3/apis__resource.k8s.io__v1beta1_openapi.json | 2 +- .../v3/apis__resource.k8s.io__v1beta2_openapi.json | 2 +- pkg/generated/openapi/zz_generated.openapi.go | 6 +++--- staging/src/k8s.io/api/resource/v1/generated.proto | 2 +- .../k8s.io/api/resource/v1/types_swagger_doc_generated.go | 2 +- staging/src/k8s.io/api/resource/v1beta1/generated.proto | 2 +- .../api/resource/v1beta1/types_swagger_doc_generated.go | 2 +- staging/src/k8s.io/api/resource/v1beta2/generated.proto | 2 +- .../api/resource/v1beta2/types_swagger_doc_generated.go | 2 +- .../applyconfigurations/resource/v1/deviceclassspec.go | 2 +- .../applyconfigurations/resource/v1beta1/deviceclassspec.go | 2 +- .../applyconfigurations/resource/v1beta2/deviceclassspec.go | 2 +- 14 files changed, 18 insertions(+), 18 deletions(-) diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json index aac2ad83575..d67a54d36a8 100644 --- a/api/openapi-spec/swagger.json +++ b/api/openapi-spec/swagger.json @@ -16021,7 +16021,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": { @@ -17368,7 +17368,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": { @@ -18541,7 +18541,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 d80ad017640..d41c8b4064a 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 f2b2f27c769..d18ecd8b37e 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 678be7cb21b..f546e0efe58 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/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index d8e978336dd..c9dda6e2947 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -47625,7 +47625,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: "", }, @@ -50133,7 +50133,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: "", }, @@ -52305,7 +52305,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/staging/src/k8s.io/api/resource/v1/generated.proto b/staging/src/k8s.io/api/resource/v1/generated.proto index 1e87627497c..515f7d9a6d2 100644 --- a/staging/src/k8s.io/api/resource/v1/generated.proto +++ b/staging/src/k8s.io/api/resource/v1/generated.proto @@ -705,7 +705,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: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 f1d9291fbce..4cb345e9b95 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 5a3ed4ada98..2205089f99e 100644 --- a/staging/src/k8s.io/api/resource/v1beta1/generated.proto +++ b/staging/src/k8s.io/api/resource/v1beta1/generated.proto @@ -717,7 +717,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: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 070536e67f7..ab90e8f9d29 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 44816e484a6..0556b720c9d 100644 --- a/staging/src/k8s.io/api/resource/v1beta2/generated.proto +++ b/staging/src/k8s.io/api/resource/v1beta2/generated.proto @@ -708,7 +708,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: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 a086f9bf23e..1ababeebe15 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"` } From 80b9ee1abc9b6123773a011927c203b4c35377a9 Mon Sep 17 00:00:00 2001 From: yliao Date: Thu, 29 Jan 2026 19:09:14 +0000 Subject: [PATCH 3/5] fix unit test --- plugin/pkg/admission/resourcequota/admission_test.go | 2 +- .../rbac/bootstrappolicy/testdata/cluster-roles.yaml | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) 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: From cc9731f2911ee987ad9677e0b4ba365e1a659141 Mon Sep 17 00:00:00 2001 From: yliao Date: Thu, 29 Jan 2026 20:55:19 +0000 Subject: [PATCH 4/5] fix quota integration test --- test/integration/quota/quota_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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) } From c215164395fb9b929b1e195418ed8ac76c0e0c45 Mon Sep 17 00:00:00 2001 From: yliao Date: Mon, 2 Feb 2026 19:08:17 +0000 Subject: [PATCH 5/5] fix test/integration/scheduler/batch --- .../noderesources/balanced_allocation.go | 14 +++- .../noderesources/balanced_allocation_test.go | 82 ++++++++++++++----- .../framework/plugins/noderesources/fit.go | 18 +++- .../plugins/noderesources/fit_test.go | 78 ++++++++++++------ 4 files changed, 142 insertions(+), 50 deletions(-) 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) } } })