Fix validation options for old pvc

Also update comments on allocatedresourcestatuses fields
This commit is contained in:
Hemant Kumar 2023-07-14 12:04:27 -04:00
parent d765fa6b74
commit 137474e283
5 changed files with 70 additions and 38 deletions

View File

@ -360,6 +360,13 @@ func ContainsAccessMode(modes []core.PersistentVolumeAccessMode, mode core.Persi
return false return false
} }
func ClaimContainsAllocatedResources(pvc *core.PersistentVolumeClaim) bool {
if pvc.Status.AllocatedResourceStatuses != nil || pvc.Status.AllocatedResources != nil {
return true
}
return false
}
// GetTolerationsFromPodAnnotations gets the json serialized tolerations data from Pod.Annotations // GetTolerationsFromPodAnnotations gets the json serialized tolerations data from Pod.Annotations
// and converts it to the []Toleration type in core. // and converts it to the []Toleration type in core.
func GetTolerationsFromPodAnnotations(annotations map[string]string) ([]core.Toleration, error) { func GetTolerationsFromPodAnnotations(annotations map[string]string) ([]core.Toleration, error) {

View File

@ -521,7 +521,7 @@ const (
type ClaimResourceStatus string type ClaimResourceStatus string
const ( const (
// State set when resize controller starts expanding the volume in control-plane // State set when resize controller starts resizing the volume in control-plane
PersistentVolumeClaimControllerResizeInProgress ClaimResourceStatus = "ControllerResizeInProgress" PersistentVolumeClaimControllerResizeInProgress ClaimResourceStatus = "ControllerResizeInProgress"
// State set when resize has failed in resize controller with a terminal error. // State set when resize has failed in resize controller with a terminal error.
@ -566,11 +566,13 @@ type PersistentVolumeClaimStatus struct {
// +optional // +optional
Conditions []PersistentVolumeClaimCondition Conditions []PersistentVolumeClaimCondition
// AllocatedResources tracks the resources allocated to a PVC including its capacity. // AllocatedResources tracks the resources allocated to a PVC including its capacity.
// Following are valid key names for allocatedResources: // Key names follow standard Kubernetes label syntax. Valid values are either:
// - storage // * Un-prefixed keys:
// - example.com/foobar // - storage - the capacity of the volume.
// * Custom resources must use implementation-defined prefixed names such as "example.com/my-custom-resource"
// Apart from above values - keys that are unprefixed or have kubernetes.io prefix are considered // Apart from above values - keys that are unprefixed or have kubernetes.io prefix are considered
// reserved and hence may not be used. // reserved and hence may not be used.
//
// Capacity reported here may be larger than the actual capacity when a volume expansion operation // Capacity reported here may be larger than the actual capacity when a volume expansion operation
// is requested. // is requested.
// For storage quota, the larger value from allocatedResources and PVC.spec.resources is used. // For storage quota, the larger value from allocatedResources and PVC.spec.resources is used.
@ -578,19 +580,27 @@ type PersistentVolumeClaimStatus struct {
// If a volume expansion capacity request is lowered, allocatedResources is only // If a volume expansion capacity request is lowered, allocatedResources is only
// lowered if there are no expansion operations in progress and if the actual volume capacity // lowered if there are no expansion operations in progress and if the actual volume capacity
// is equal or lower than the requested capacity. // is equal or lower than the requested capacity.
//
// A controller that receives PVC update with previously unknown resourceName
// should ignore the update for the purpose it was designed. For example - a controller that
// only is responsible for resizing capacity of the volume, should ignore PVC updates that change other valid
// resources associated with PVC.
//
// This is an alpha field and requires enabling RecoverVolumeExpansionFailure feature. // This is an alpha field and requires enabling RecoverVolumeExpansionFailure feature.
// +featureGate=RecoverVolumeExpansionFailure // +featureGate=RecoverVolumeExpansionFailure
// +optional // +optional
AllocatedResources ResourceList AllocatedResources ResourceList
// AllocatedResourceStatuses stores status of resource being resized for the given PVC. // AllocatedResourceStatuses stores status of resource being resized for the given PVC.
// Following are valid key names for allocatedResourceStatuses: // Key names follow standard Kubernetes label syntax. Valid values are either:
// - storage // * Un-prefixed keys:
// - example.com/foobar // - storage - the capacity of the volume.
// * Custom resources must use implementation-defined prefixed names such as "example.com/my-custom-resource"
// Apart from above values - keys that are unprefixed or have kubernetes.io prefix are considered // Apart from above values - keys that are unprefixed or have kubernetes.io prefix are considered
// reserved and hence may not be used. // reserved and hence may not be used.
//
// ClaimResourceStatus can be in any of following states: // ClaimResourceStatus can be in any of following states:
// - ControllerResizeInProgress: // - ControllerResizeInProgress:
// State set when resize controller starts expanding the volume in control-plane. // State set when resize controller starts resizing the volume in control-plane.
// - ControllerResizeFailed: // - ControllerResizeFailed:
// State set when resize has failed in resize controller with a terminal error. // State set when resize has failed in resize controller with a terminal error.
// - NodeResizePending: // - NodeResizePending:
@ -608,10 +618,12 @@ type PersistentVolumeClaimStatus struct {
// - pvc.status.allocatedResourceStatus['storage'] = "NodeResizeInProgress" // - pvc.status.allocatedResourceStatus['storage'] = "NodeResizeInProgress"
// - pvc.status.allocatedResourceStatus['storage'] = "NodeResizeFailed" // - pvc.status.allocatedResourceStatus['storage'] = "NodeResizeFailed"
// When this field is not set, it means that no resize operation is in progress for the given PVC. // When this field is not set, it means that no resize operation is in progress for the given PVC.
//
// A controller that receives PVC update with previously unknown resourceName or ClaimResourceStatus // A controller that receives PVC update with previously unknown resourceName or ClaimResourceStatus
// should ignore the update for the purpose it was designed. For example - a controller that // should ignore the update for the purpose it was designed. For example - a controller that
// only is responsible for resizing capacity of the volume, should ignore pvc updates that change other valid // only is responsible for resizing capacity of the volume, should ignore PVC updates that change other valid
// resources associated with PVC. // resources associated with PVC.
//
// This is an alpha field and requires enabling RecoverVolumeExpansionFailure feature. // This is an alpha field and requires enabling RecoverVolumeExpansionFailure feature.
// +featureGate=RecoverVolumeExpansionFailure // +featureGate=RecoverVolumeExpansionFailure
// +mapType=granular // +mapType=granular

View File

@ -2046,6 +2046,10 @@ func ValidationOptionsForPersistentVolumeClaim(pvc, oldPvc *core.PersistentVolum
// If the old object allowed "ReadWriteOncePod", continue to allow it in the new object // If the old object allowed "ReadWriteOncePod", continue to allow it in the new object
opts.AllowReadWriteOncePod = true opts.AllowReadWriteOncePod = true
} }
if helper.ClaimContainsAllocatedResources(oldPvc) {
opts.EnableRecoverFromExpansionFailure = true
}
return opts return opts
} }

View File

@ -18450,34 +18450,29 @@ func TestValidatePersistentVolumeClaimStatusUpdate(t *testing.T) {
isExpectedFailure bool isExpectedFailure bool
oldClaim *core.PersistentVolumeClaim oldClaim *core.PersistentVolumeClaim
newClaim *core.PersistentVolumeClaim newClaim *core.PersistentVolumeClaim
enableResize bool
enableRecoverFromExpansion bool enableRecoverFromExpansion bool
}{ }{
"condition-update-with-enabled-feature-gate": { "condition-update-with-enabled-feature-gate": {
isExpectedFailure: false, isExpectedFailure: false,
oldClaim: validClaim, oldClaim: validClaim,
newClaim: validConditionUpdate, newClaim: validConditionUpdate,
enableResize: true,
}, },
"status-update-with-valid-allocatedResources-feature-enabled": { "status-update-with-valid-allocatedResources-feature-enabled": {
isExpectedFailure: false, isExpectedFailure: false,
oldClaim: validClaim, oldClaim: validClaim,
newClaim: validAllocatedResources, newClaim: validAllocatedResources,
enableResize: true,
enableRecoverFromExpansion: true, enableRecoverFromExpansion: true,
}, },
"status-update-with-invalid-allocatedResources-native-key-feature-enabled": { "status-update-with-invalid-allocatedResources-native-key-feature-enabled": {
isExpectedFailure: true, isExpectedFailure: true,
oldClaim: validClaim, oldClaim: validClaim,
newClaim: invalidNativeResourceAllocatedKey, newClaim: invalidNativeResourceAllocatedKey,
enableResize: true,
enableRecoverFromExpansion: true, enableRecoverFromExpansion: true,
}, },
"status-update-with-valid-allocatedResources-external-key-feature-enabled": { "status-update-with-valid-allocatedResources-external-key-feature-enabled": {
isExpectedFailure: false, isExpectedFailure: false,
oldClaim: validClaim, oldClaim: validClaim,
newClaim: validExternalAllocatedResource, newClaim: validExternalAllocatedResource,
enableResize: true,
enableRecoverFromExpansion: true, enableRecoverFromExpansion: true,
}, },
@ -18485,85 +18480,87 @@ func TestValidatePersistentVolumeClaimStatusUpdate(t *testing.T) {
isExpectedFailure: true, isExpectedFailure: true,
oldClaim: validClaim, oldClaim: validClaim,
newClaim: invalidAllocatedResources, newClaim: invalidAllocatedResources,
enableResize: true,
enableRecoverFromExpansion: true, enableRecoverFromExpansion: true,
}, },
"status-update-with-no-storage-update": { "status-update-with-no-storage-update": {
isExpectedFailure: true, isExpectedFailure: true,
oldClaim: validClaim, oldClaim: validClaim,
newClaim: noStoraegeClaimStatus, newClaim: noStoraegeClaimStatus,
enableResize: true,
enableRecoverFromExpansion: true, enableRecoverFromExpansion: true,
}, },
"staus-update-with-controller-resize-failed": { "staus-update-with-controller-resize-failed": {
isExpectedFailure: false, isExpectedFailure: false,
oldClaim: validClaim, oldClaim: validClaim,
newClaim: validResizeStatusControllerResizeFailed, newClaim: validResizeStatusControllerResizeFailed,
enableResize: true,
enableRecoverFromExpansion: true, enableRecoverFromExpansion: true,
}, },
"staus-update-with-node-resize-pending": { "staus-update-with-node-resize-pending": {
isExpectedFailure: false, isExpectedFailure: false,
oldClaim: validClaim, oldClaim: validClaim,
newClaim: validNodeResizePending, newClaim: validNodeResizePending,
enableResize: true,
enableRecoverFromExpansion: true, enableRecoverFromExpansion: true,
}, },
"staus-update-with-node-resize-inprogress": { "staus-update-with-node-resize-inprogress": {
isExpectedFailure: false, isExpectedFailure: false,
oldClaim: validClaim, oldClaim: validClaim,
newClaim: validNodeResizeInProgress, newClaim: validNodeResizeInProgress,
enableResize: true,
enableRecoverFromExpansion: true, enableRecoverFromExpansion: true,
}, },
"staus-update-with-node-resize-failed": { "staus-update-with-node-resize-failed": {
isExpectedFailure: false, isExpectedFailure: false,
oldClaim: validClaim, oldClaim: validClaim,
newClaim: validNodeResizeFailed, newClaim: validNodeResizeFailed,
enableResize: true,
enableRecoverFromExpansion: true, enableRecoverFromExpansion: true,
}, },
"staus-update-with-invalid-native-resource-status-key": { "staus-update-with-invalid-native-resource-status-key": {
isExpectedFailure: true, isExpectedFailure: true,
oldClaim: validClaim, oldClaim: validClaim,
newClaim: invalidNativeResizeStatusPVC, newClaim: invalidNativeResizeStatusPVC,
enableResize: true,
enableRecoverFromExpansion: true, enableRecoverFromExpansion: true,
}, },
"staus-update-with-valid-external-resource-status-key": { "staus-update-with-valid-external-resource-status-key": {
isExpectedFailure: false, isExpectedFailure: false,
oldClaim: validClaim, oldClaim: validClaim,
newClaim: validExternalResizeStatusPVC, newClaim: validExternalResizeStatusPVC,
enableResize: true,
enableRecoverFromExpansion: true, enableRecoverFromExpansion: true,
}, },
"status-update-with-multiple-resources-key": { "status-update-with-multiple-resources-key": {
isExpectedFailure: false, isExpectedFailure: false,
oldClaim: validClaim, oldClaim: validClaim,
newClaim: multipleResourceStatusPVC, newClaim: multipleResourceStatusPVC,
enableResize: true,
enableRecoverFromExpansion: true, enableRecoverFromExpansion: true,
}, },
"status-update-with-valid-pvc-resize-status": { "status-update-with-valid-pvc-resize-status": {
isExpectedFailure: false, isExpectedFailure: false,
oldClaim: validClaim, oldClaim: validClaim,
newClaim: validResizeStatusPVC, newClaim: validResizeStatusPVC,
enableResize: true,
enableRecoverFromExpansion: true, enableRecoverFromExpansion: true,
}, },
"status-update-with-invalid-pvc-resize-status": { "status-update-with-invalid-pvc-resize-status": {
isExpectedFailure: true, isExpectedFailure: true,
oldClaim: validClaim, oldClaim: validClaim,
newClaim: invalidResizeStatusPVC, newClaim: invalidResizeStatusPVC,
enableResize: true,
enableRecoverFromExpansion: true, enableRecoverFromExpansion: true,
}, },
"status-update-with-old-pvc-valid-resourcestatus-newpvc-invalid-recovery-disabled": {
isExpectedFailure: true,
oldClaim: validResizeStatusPVC,
newClaim: invalidResizeStatusPVC,
enableRecoverFromExpansion: false,
},
"status-update-with-old-pvc-valid-allocatedResource-newpvc-invalid-recovery-disabled": {
isExpectedFailure: true,
oldClaim: validExternalAllocatedResource,
newClaim: invalidNativeResourceAllocatedKey,
enableRecoverFromExpansion: false,
},
} }
for name, scenario := range scenarios { for name, scenario := range scenarios {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
validateOpts := PersistentVolumeClaimSpecValidationOptions{ defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.RecoverVolumeExpansionFailure, scenario.enableRecoverFromExpansion)()
EnableRecoverFromExpansionFailure: scenario.enableRecoverFromExpansion,
} validateOpts := ValidationOptionsForPersistentVolumeClaim(scenario.newClaim, scenario.oldClaim)
// ensure we have a resource version specified for updates // ensure we have a resource version specified for updates
scenario.oldClaim.ResourceVersion = "1" scenario.oldClaim.ResourceVersion = "1"
scenario.newClaim.ResourceVersion = "1" scenario.newClaim.ResourceVersion = "1"

View File

@ -564,7 +564,7 @@ const (
type ClaimResourceStatus string type ClaimResourceStatus string
const ( const (
// State set when resize controller starts expanding the volume in control-plane // State set when resize controller starts resizing the volume in control-plane.
PersistentVolumeClaimControllerResizeInProgress ClaimResourceStatus = "ControllerResizeInProgress" PersistentVolumeClaimControllerResizeInProgress ClaimResourceStatus = "ControllerResizeInProgress"
// State set when resize has failed in resize controller with a terminal error. // State set when resize has failed in resize controller with a terminal error.
@ -620,11 +620,13 @@ type PersistentVolumeClaimStatus struct {
// +patchStrategy=merge // +patchStrategy=merge
Conditions []PersistentVolumeClaimCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,4,rep,name=conditions"` Conditions []PersistentVolumeClaimCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,4,rep,name=conditions"`
// allocatedResources tracks the resources allocated to a PVC including its capacity. // allocatedResources tracks the resources allocated to a PVC including its capacity.
// Following are valid key names for allocatedResources: // Key names follow standard Kubernetes label syntax. Valid values are either:
// - storage // * Un-prefixed keys:
// - example.com/foobar // - storage - the capacity of the volume.
// * Custom resources must use implementation-defined prefixed names such as "example.com/my-custom-resource"
// Apart from above values - keys that are unprefixed or have kubernetes.io prefix are considered // Apart from above values - keys that are unprefixed or have kubernetes.io prefix are considered
// reserved and hence may not be used. // reserved and hence may not be used.
//
// Capacity reported here may be larger than the actual capacity when a volume expansion operation // Capacity reported here may be larger than the actual capacity when a volume expansion operation
// is requested. // is requested.
// For storage quota, the larger value from allocatedResources and PVC.spec.resources is used. // For storage quota, the larger value from allocatedResources and PVC.spec.resources is used.
@ -632,6 +634,12 @@ type PersistentVolumeClaimStatus struct {
// If a volume expansion capacity request is lowered, allocatedResources is only // If a volume expansion capacity request is lowered, allocatedResources is only
// lowered if there are no expansion operations in progress and if the actual volume capacity // lowered if there are no expansion operations in progress and if the actual volume capacity
// is equal or lower than the requested capacity. // is equal or lower than the requested capacity.
//
// A controller that receives PVC update with previously unknown resourceName
// should ignore the update for the purpose it was designed. For example - a controller that
// only is responsible for resizing capacity of the volume, should ignore PVC updates that change other valid
// resources associated with PVC.
//
// This is an alpha field and requires enabling RecoverVolumeExpansionFailure feature. // This is an alpha field and requires enabling RecoverVolumeExpansionFailure feature.
// +featureGate=RecoverVolumeExpansionFailure // +featureGate=RecoverVolumeExpansionFailure
// +optional // +optional
@ -641,14 +649,16 @@ type PersistentVolumeClaimStatus struct {
// ResizeStatus *PersistentVolumeClaimResizeStatus `json:"resizeStatus,omitempty" protobuf:"bytes,6,opt,name=resizeStatus,casttype=PersistentVolumeClaimResizeStatus"` // ResizeStatus *PersistentVolumeClaimResizeStatus `json:"resizeStatus,omitempty" protobuf:"bytes,6,opt,name=resizeStatus,casttype=PersistentVolumeClaimResizeStatus"`
// allocatedResourceStatuses stores status of resource being resized for the given PVC. // allocatedResourceStatuses stores status of resource being resized for the given PVC.
// Following are valid key names for allocatedResourceStatuses: // Key names follow standard Kubernetes label syntax. Valid values are either:
// - storage // * Un-prefixed keys:
// - example.com/foobar // - storage - the capacity of the volume.
// * Custom resources must use implementation-defined prefixed names such as "example.com/my-custom-resource"
// Apart from above values - keys that are unprefixed or have kubernetes.io prefix are considered // Apart from above values - keys that are unprefixed or have kubernetes.io prefix are considered
// reserved and hence may not be used. // reserved and hence may not be used.
//
// ClaimResourceStatus can be in any of following states: // ClaimResourceStatus can be in any of following states:
// - ControllerResizeInProgress: // - ControllerResizeInProgress:
// State set when resize controller starts expanding the volume in control-plane. // State set when resize controller starts resizing the volume in control-plane.
// - ControllerResizeFailed: // - ControllerResizeFailed:
// State set when resize has failed in resize controller with a terminal error. // State set when resize has failed in resize controller with a terminal error.
// - NodeResizePending: // - NodeResizePending:
@ -659,17 +669,19 @@ type PersistentVolumeClaimStatus struct {
// - NodeResizeFailed: // - NodeResizeFailed:
// State set when resizing has failed in kubelet with a terminal error. Transient errors don't set // State set when resizing has failed in kubelet with a terminal error. Transient errors don't set
// NodeResizeFailed. // NodeResizeFailed.
// For example expanding a PVC for more capacity - this field can be one of the following states: // For example: if expanding a PVC for more capacity - this field can be one of the following states:
// - pvc.status.allocatedResourceStatus['storage'] = "ControllerResizeInProgress" // - pvc.status.allocatedResourceStatus['storage'] = "ControllerResizeInProgress"
// - pvc.status.allocatedResourceStatus['storage'] = "ControllerResizeFailed" // - pvc.status.allocatedResourceStatus['storage'] = "ControllerResizeFailed"
// - pvc.status.allocatedResourceStatus['storage'] = "NodeResizePending" // - pvc.status.allocatedResourceStatus['storage'] = "NodeResizePending"
// - pvc.status.allocatedResourceStatus['storage'] = "NodeResizeInProgress" // - pvc.status.allocatedResourceStatus['storage'] = "NodeResizeInProgress"
// - pvc.status.allocatedResourceStatus['storage'] = "NodeResizeFailed" // - pvc.status.allocatedResourceStatus['storage'] = "NodeResizeFailed"
// When this field is not set, it means that no resize operation is in progress for the given PVC. // When this field is not set, it means that no resize operation is in progress for the given PVC.
//
// A controller that receives PVC update with previously unknown resourceName or ClaimResourceStatus // A controller that receives PVC update with previously unknown resourceName or ClaimResourceStatus
// should ignore the update for the purpose it was designed. For example - a controller that // should ignore the update for the purpose it was designed. For example - a controller that
// only is responsible for resizing capacity of the volume, should ignore pvc updates that change other valid // only is responsible for resizing capacity of the volume, should ignore PVC updates that change other valid
// resources associated with PVC. // resources associated with PVC.
//
// This is an alpha field and requires enabling RecoverVolumeExpansionFailure feature. // This is an alpha field and requires enabling RecoverVolumeExpansionFailure feature.
// +featureGate=RecoverVolumeExpansionFailure // +featureGate=RecoverVolumeExpansionFailure
// +mapType=granular // +mapType=granular