Add declarative validation of ResourceClaim status pool field

This commit is contained in:
Joe Betz 2025-09-16 17:58:00 -04:00
parent e8f243dac2
commit 8606fa03dc
4 changed files with 39 additions and 3 deletions

View file

@ -20,6 +20,8 @@ import (
"context"
"errors"
"sigs.k8s.io/structured-merge-diff/v6/fieldpath"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
@ -40,7 +42,6 @@ import (
"k8s.io/kubernetes/pkg/features"
resourceutils "k8s.io/kubernetes/pkg/registry/resource"
"k8s.io/utils/ptr"
"sigs.k8s.io/structured-merge-diff/v6/fieldpath"
)
// resourceclaimStrategy implements behavior for ResourceClaim objects
@ -207,8 +208,25 @@ func (r *resourceclaimStatusStrategy) ValidateUpdate(ctx context.Context, obj, o
if oldClaim.Status.Allocation != nil {
oldAllocationResult = oldClaim.Status.Allocation.Devices.Results
}
allErrs := resourceutils.AuthorizedForAdminStatus(ctx, newAllocationResult, oldAllocationResult, newClaim.Namespace, r.nsClient)
return append(allErrs, validation.ValidateResourceClaimStatusUpdate(newClaim, oldClaim)...)
errs := resourceutils.AuthorizedForAdminStatus(ctx, newAllocationResult, oldAllocationResult, newClaim.Namespace, r.nsClient)
errs = append(errs, validation.ValidateResourceClaimStatusUpdate(newClaim, oldClaim)...)
// If DeclarativeValidation feature gate is enabled, also run declarative validation
if utilfeature.DefaultFeatureGate.Enabled(features.DeclarativeValidation) {
// Determine if takeover is enabled
takeover := utilfeature.DefaultFeatureGate.Enabled(features.DeclarativeValidationTakeover)
// Run declarative update validation with panic recovery
declarativeErrs := rest.ValidateUpdateDeclaratively(ctx, legacyscheme.Scheme, newClaim, oldClaim, rest.WithTakeover(takeover))
// Compare imperative and declarative errors and emit metric if there's a mismatch
rest.CompareDeclarativeErrorsAndEmitMismatches(ctx, errs, declarativeErrs, takeover, "dc_status_update")
// Only apply declarative errors if takeover is enabled
if takeover {
errs = append(errs.RemoveCoveredByDeclarative(), declarativeErrs...)
}
}
return errs
}
// WarningsOnUpdate returns warnings for the given update.

View file

@ -678,6 +678,7 @@ type ResourceSliceList struct {
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +k8s:prerelease-lifecycle-gen:introduced=1.34
// +k8s:supportsSubresource=/status
// ResourceClaim describes a request for access to resources in the cluster,
// for use by workloads. For example, if a workload needs an accelerator device
@ -1346,6 +1347,7 @@ type ResourceClaimStatus struct {
// Allocation is set once the claim has been allocated successfully.
//
// +optional
// +k8s:optional
Allocation *AllocationResult `json:"allocation,omitempty" protobuf:"bytes,1,opt,name=allocation"`
// ReservedFor indicates which entities are currently allowed to use
@ -1369,6 +1371,7 @@ type ResourceClaimStatus struct {
// the future, but not reduced.
//
// +optional
// +k8s:optional
// +listType=map
// +listMapKey=uid
// +patchStrategy=merge
@ -1385,6 +1388,7 @@ type ResourceClaimStatus struct {
// information. Entries are owned by their respective drivers.
//
// +optional
// +k8s:optional
// +listType=map
// +listMapKey=driver
// +listMapKey=device
@ -1502,6 +1506,8 @@ type DeviceRequestAllocationResult struct {
// DNS sub-domains separated by slashes.
//
// +required
// +k8s:required
// +k8s:format=k8s-resource-pool-name
Pool string `json:"pool" protobuf:"bytes,3,name=pool"`
// Device references one device instance via its name in the driver's

View file

@ -682,6 +682,7 @@ type ResourceSliceList struct {
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +k8s:prerelease-lifecycle-gen:introduced=1.32
// +k8s:supportsSubresource=/status
// ResourceClaim describes a request for access to resources in the cluster,
// for use by workloads. For example, if a workload needs an accelerator device
@ -1354,6 +1355,7 @@ type ResourceClaimStatus struct {
// Allocation is set once the claim has been allocated successfully.
//
// +optional
// +k8s:optional
Allocation *AllocationResult `json:"allocation,omitempty" protobuf:"bytes,1,opt,name=allocation"`
// ReservedFor indicates which entities are currently allowed to use
@ -1377,6 +1379,7 @@ type ResourceClaimStatus struct {
// the future, but not reduced.
//
// +optional
// +k8s:optional
// +listType=map
// +listMapKey=uid
// +patchStrategy=merge
@ -1393,6 +1396,7 @@ type ResourceClaimStatus struct {
// information. Entries are owned by their respective drivers.
//
// +optional
// +k8s:optional
// +listType=map
// +listMapKey=driver
// +listMapKey=device
@ -1510,6 +1514,8 @@ type DeviceRequestAllocationResult struct {
// DNS sub-domains separated by slashes.
//
// +required
// +k8s:required
// +k8s:format=k8s-resource-pool-name
Pool string `json:"pool" protobuf:"bytes,3,name=pool"`
// Device references one device instance via its name in the driver's

View file

@ -678,6 +678,7 @@ type ResourceSliceList struct {
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +k8s:prerelease-lifecycle-gen:introduced=1.33
// +k8s:supportsSubresource=/status
// ResourceClaim describes a request for access to resources in the cluster,
// for use by workloads. For example, if a workload needs an accelerator device
@ -1346,6 +1347,7 @@ type ResourceClaimStatus struct {
// Allocation is set once the claim has been allocated successfully.
//
// +optional
// +k8s:optional
Allocation *AllocationResult `json:"allocation,omitempty" protobuf:"bytes,1,opt,name=allocation"`
// ReservedFor indicates which entities are currently allowed to use
@ -1369,6 +1371,7 @@ type ResourceClaimStatus struct {
// the future, but not reduced.
//
// +optional
// +k8s:optional
// +listType=map
// +listMapKey=uid
// +patchStrategy=merge
@ -1385,6 +1388,7 @@ type ResourceClaimStatus struct {
// information. Entries are owned by their respective drivers.
//
// +optional
// +k8s:optional
// +listType=map
// +listMapKey=driver
// +listMapKey=device
@ -1502,6 +1506,8 @@ type DeviceRequestAllocationResult struct {
// DNS sub-domains separated by slashes.
//
// +required
// +k8s:required
// +k8s:format=k8s-resource-pool-name
Pool string `json:"pool" protobuf:"bytes,3,name=pool"`
// Device references one device instance via its name in the driver's