From 014728e76378796f2896a4035a3ca7da6a02c12a Mon Sep 17 00:00:00 2001 From: Hemant Kumar Date: Wed, 23 Apr 2025 11:37:22 -0400 Subject: [PATCH] Check for newer fields when deciding expansion recovery feature status --- .../operationexecutor/operation_generator.go | 5 + .../operation_generator_test.go | 103 ++++++++++++++++++ 2 files changed, 108 insertions(+) diff --git a/pkg/volume/util/operationexecutor/operation_generator.go b/pkg/volume/util/operationexecutor/operation_generator.go index b450a8f0ddb..d4e4d555ce4 100644 --- a/pkg/volume/util/operationexecutor/operation_generator.go +++ b/pkg/volume/util/operationexecutor/operation_generator.go @@ -2089,6 +2089,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 0c267222e89..6bd7f51e04c 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{