diff --git a/pkg/volume/util/operationexecutor/operation_generator.go b/pkg/volume/util/operationexecutor/operation_generator.go index 37cc11cffeb..c49caa51b65 100644 --- a/pkg/volume/util/operationexecutor/operation_generator.go +++ b/pkg/volume/util/operationexecutor/operation_generator.go @@ -2083,6 +2083,11 @@ func (og *operationGenerator) checkForRecoveryFromExpansion(pvc *v1.PersistentVo featureGateStatus := utilfeature.DefaultFeatureGate.Enabled(features.RecoverVolumeExpansionFailure) if !featureGateStatus { + // even though RecoverVolumeExpansionFailure feature-gate is disabled, we should consider it enabled + // if resizeStatus is not empty or allocatedresources is set + if resizeStatus != "" || allocatedResource != nil { + return true + } return false } diff --git a/pkg/volume/util/operationexecutor/operation_generator_test.go b/pkg/volume/util/operationexecutor/operation_generator_test.go index 7bf0dabd38b..bf3c8e4e94e 100644 --- a/pkg/volume/util/operationexecutor/operation_generator_test.go +++ b/pkg/volume/util/operationexecutor/operation_generator_test.go @@ -402,6 +402,109 @@ func TestExpandDuringMount(t *testing.T) { }) } } +func TestCheckForRecoveryFromExpansion(t *testing.T) { + tests := []struct { + name string + pvc *v1.PersistentVolumeClaim + featureGateEnabled bool + expectedRecoveryCheck bool + }{ + { + name: "feature gate disabled, no resize status or allocated resources", + pvc: &v1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-pvc-1", + }, + Status: v1.PersistentVolumeClaimStatus{ + AllocatedResourceStatuses: nil, + AllocatedResources: nil, + }, + }, + featureGateEnabled: false, + expectedRecoveryCheck: false, + }, + { + name: "feature gate disabled, resize status set", + pvc: &v1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-pvc-2", + }, + Status: v1.PersistentVolumeClaimStatus{ + AllocatedResourceStatuses: map[v1.ResourceName]v1.ClaimResourceStatus{ + v1.ResourceStorage: v1.PersistentVolumeClaimNodeResizePending, + }, + }, + }, + featureGateEnabled: false, + expectedRecoveryCheck: true, + }, + { + name: "feature gate enabled, resize status and allocated resources set", + pvc: &v1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-pvc-3", + }, + Status: v1.PersistentVolumeClaimStatus{ + AllocatedResourceStatuses: map[v1.ResourceName]v1.ClaimResourceStatus{ + v1.ResourceStorage: v1.PersistentVolumeClaimNodeResizePending, + }, + AllocatedResources: v1.ResourceList{ + v1.ResourceStorage: resource.MustParse("10Gi"), + }, + }, + }, + featureGateEnabled: true, + expectedRecoveryCheck: true, + }, + { + name: "feature gate enabled, no resize status or allocated resources", + pvc: &v1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-pvc-4", + }, + Status: v1.PersistentVolumeClaimStatus{ + AllocatedResourceStatuses: nil, + AllocatedResources: nil, + }, + }, + featureGateEnabled: true, + expectedRecoveryCheck: false, + }, + { + name: "feature gate enabled, older external resize controller", + pvc: &v1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-pvc-5", + }, + Status: v1.PersistentVolumeClaimStatus{ + AllocatedResourceStatuses: nil, + AllocatedResources: nil, + }, + }, + featureGateEnabled: true, + expectedRecoveryCheck: false, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.RecoverVolumeExpansionFailure, test.featureGateEnabled) + + pod := getTestPod("test-pod", test.pvc.Name) + pv := getTestPV("test-vol0", "2G") + og := &operationGenerator{} + + vmt := VolumeToMount{ + Pod: pod, + VolumeName: v1.UniqueVolumeName(pv.Name), + VolumeSpec: volume.NewSpecFromPersistentVolume(pv, false), + } + result := og.checkForRecoveryFromExpansion(test.pvc, vmt) + + assert.Equal(t, test.expectedRecoveryCheck, result, "unexpected recovery check result for test: %s", test.name) + }) + } +} func getTestPod(podName, pvcName string) *v1.Pod { return &v1.Pod{