diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json index f8106bd9892..d51c1efb2f2 100644 --- a/api/openapi-spec/swagger.json +++ b/api/openapi-spec/swagger.json @@ -9052,7 +9052,7 @@ "properties": { "lastPhaseTransitionTime": { "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.Time", - "description": "lastPhaseTransitionTime is the time the phase transitioned from one to another and automatically resets to current time everytime a volume phase transitions. This is a beta field and requires the PersistentVolumeLastPhaseTransitionTime feature to be enabled (enabled by default)." + "description": "lastPhaseTransitionTime is the time the phase transitioned from one to another and automatically resets to current time everytime a volume phase transitions." }, "message": { "description": "message is a human-readable message indicating details about why the volume is in this state.", diff --git a/api/openapi-spec/v3/api__v1_openapi.json b/api/openapi-spec/v3/api__v1_openapi.json index 5dbe3ec3604..c974fc0b87f 100644 --- a/api/openapi-spec/v3/api__v1_openapi.json +++ b/api/openapi-spec/v3/api__v1_openapi.json @@ -4863,7 +4863,7 @@ "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.apis.meta.v1.Time" } ], - "description": "lastPhaseTransitionTime is the time the phase transitioned from one to another and automatically resets to current time everytime a volume phase transitions. This is a beta field and requires the PersistentVolumeLastPhaseTransitionTime feature to be enabled (enabled by default)." + "description": "lastPhaseTransitionTime is the time the phase transitioned from one to another and automatically resets to current time everytime a volume phase transitions." }, "message": { "description": "message is a human-readable message indicating details about why the volume is in this state.", diff --git a/pkg/api/persistentvolume/util.go b/pkg/api/persistentvolume/util.go index bf703f7aa69..a4125b5fdff 100644 --- a/pkg/api/persistentvolume/util.go +++ b/pkg/api/persistentvolume/util.go @@ -41,14 +41,6 @@ func DropDisabledSpecFields(pvSpec *api.PersistentVolumeSpec, oldPVSpec *api.Per } } -// DropDisabledStatusFields removes disabled fields from the pv status. -// This should be called from PrepareForUpdate for all resources containing a pv status. -func DropDisabledStatusFields(oldStatus, newStatus *api.PersistentVolumeStatus) { - if !utilfeature.DefaultFeatureGate.Enabled(features.PersistentVolumeLastPhaseTransitionTime) && oldStatus.LastPhaseTransitionTime.IsZero() { - newStatus.LastPhaseTransitionTime = nil - } -} - func GetWarningsForPersistentVolume(pv *api.PersistentVolume) []string { if pv == nil { return nil diff --git a/pkg/apis/core/types.go b/pkg/apis/core/types.go index 49f36e1a735..05ddfe643f7 100644 --- a/pkg/apis/core/types.go +++ b/pkg/apis/core/types.go @@ -392,8 +392,6 @@ type PersistentVolumeStatus struct { Reason string // LastPhaseTransitionTime is the time the phase transitioned from one to another // and automatically resets to current time everytime a volume phase transitions. - // This is a beta field and requires the PersistentVolumeLastPhaseTransitionTime feature to be enabled (enabled by default). - // +featureGate=PersistentVolumeLastPhaseTransitionTime // +optional LastPhaseTransitionTime *metav1.Time } diff --git a/pkg/features/kube_features.go b/pkg/features/kube_features.go index cceca24271f..72bfbf37a06 100644 --- a/pkg/features/kube_features.go +++ b/pkg/features/kube_features.go @@ -544,6 +544,7 @@ const ( // kep: https://kep.k8s.io/3762 // alpha: v1.28 // beta: v1.29 + // GA: v1.31 // // Adds a new field to persistent volumes which holds a timestamp of when the volume last transitioned its phase. PersistentVolumeLastPhaseTransitionTime featuregate.Feature = "PersistentVolumeLastPhaseTransitionTime" @@ -1112,7 +1113,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS PDBUnhealthyPodEvictionPolicy: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.33 - PersistentVolumeLastPhaseTransitionTime: {Default: true, PreRelease: featuregate.Beta}, + PersistentVolumeLastPhaseTransitionTime: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.33 PodAndContainerStatsFromCRI: {Default: false, PreRelease: featuregate.Alpha}, diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index b9f01a3a04d..00b5b69cde1 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -26138,7 +26138,7 @@ func schema_k8sio_api_core_v1_PersistentVolumeStatus(ref common.ReferenceCallbac }, "lastPhaseTransitionTime": { SchemaProps: spec.SchemaProps{ - Description: "lastPhaseTransitionTime is the time the phase transitioned from one to another and automatically resets to current time everytime a volume phase transitions. This is a beta field and requires the PersistentVolumeLastPhaseTransitionTime feature to be enabled (enabled by default).", + Description: "lastPhaseTransitionTime is the time the phase transitioned from one to another and automatically resets to current time everytime a volume phase transitions.", Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"), }, }, diff --git a/pkg/registry/core/persistentvolume/storage/storage_test.go b/pkg/registry/core/persistentvolume/storage/storage_test.go index 089dff339f3..5989d7f23cc 100644 --- a/pkg/registry/core/persistentvolume/storage/storage_test.go +++ b/pkg/registry/core/persistentvolume/storage/storage_test.go @@ -33,10 +33,7 @@ import ( genericregistrytest "k8s.io/apiserver/pkg/registry/generic/testing" "k8s.io/apiserver/pkg/registry/rest" etcd3testing "k8s.io/apiserver/pkg/storage/etcd3/testing" - utilfeature "k8s.io/apiserver/pkg/util/feature" - featuregatetesting "k8s.io/component-base/featuregate/testing" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/registry/core/persistentvolume" "k8s.io/kubernetes/pkg/registry/registrytest" ) @@ -174,7 +171,6 @@ func TestWatch(t *testing.T) { } func TestUpdateStatus(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PersistentVolumeLastPhaseTransitionTime, true) storage, statusStorage, server := newStorage(t) defer server.Terminate(t) defer storage.Store.DestroyFunc() diff --git a/pkg/registry/core/persistentvolume/strategy.go b/pkg/registry/core/persistentvolume/strategy.go index 8ca4a921863..144092b93e5 100644 --- a/pkg/registry/core/persistentvolume/strategy.go +++ b/pkg/registry/core/persistentvolume/strategy.go @@ -21,9 +21,6 @@ import ( "fmt" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - utilfeature "k8s.io/apiserver/pkg/util/feature" - "k8s.io/kubernetes/pkg/features" - "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" @@ -70,11 +67,9 @@ func (persistentvolumeStrategy) PrepareForCreate(ctx context.Context, obj runtim pv := obj.(*api.PersistentVolume) pv.Status = api.PersistentVolumeStatus{} - if utilfeature.DefaultFeatureGate.Enabled(features.PersistentVolumeLastPhaseTransitionTime) { - pv.Status.Phase = api.VolumePending - now := NowFunc() - pv.Status.LastPhaseTransitionTime = &now - } + pv.Status.Phase = api.VolumePending + now := NowFunc() + pv.Status.LastPhaseTransitionTime = &now } func (persistentvolumeStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList { @@ -148,20 +143,17 @@ func (persistentvolumeStatusStrategy) PrepareForUpdate(ctx context.Context, obj, oldPv := old.(*api.PersistentVolume) newPv.Spec = oldPv.Spec - if utilfeature.DefaultFeatureGate.Enabled(features.PersistentVolumeLastPhaseTransitionTime) { - switch { - case oldPv.Status.Phase == newPv.Status.Phase && newPv.Status.LastPhaseTransitionTime == nil: - // phase didn't change, preserve the existing transition time if set - newPv.Status.LastPhaseTransitionTime = oldPv.Status.LastPhaseTransitionTime + switch { + case oldPv.Status.Phase == newPv.Status.Phase && newPv.Status.LastPhaseTransitionTime == nil: + // phase didn't change, preserve the existing transition time if set + newPv.Status.LastPhaseTransitionTime = oldPv.Status.LastPhaseTransitionTime - case oldPv.Status.Phase != newPv.Status.Phase && (newPv.Status.LastPhaseTransitionTime == nil || newPv.Status.LastPhaseTransitionTime.Equal(oldPv.Status.LastPhaseTransitionTime)): - // phase changed and client didn't set or didn't change the transition time - now := NowFunc() - newPv.Status.LastPhaseTransitionTime = &now - } + case oldPv.Status.Phase != newPv.Status.Phase && (newPv.Status.LastPhaseTransitionTime == nil || newPv.Status.LastPhaseTransitionTime.Equal(oldPv.Status.LastPhaseTransitionTime)): + // phase changed and client didn't set or didn't change the transition time + now := NowFunc() + newPv.Status.LastPhaseTransitionTime = &now } - pvutil.DropDisabledStatusFields(&oldPv.Status, &newPv.Status) } func (persistentvolumeStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList { diff --git a/pkg/registry/core/persistentvolume/strategy_test.go b/pkg/registry/core/persistentvolume/strategy_test.go index 42e913dde9c..aeab3662f98 100644 --- a/pkg/registry/core/persistentvolume/strategy_test.go +++ b/pkg/registry/core/persistentvolume/strategy_test.go @@ -21,11 +21,8 @@ import ( "github.com/google/go-cmp/cmp" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - utilfeature "k8s.io/apiserver/pkg/util/feature" - featuregatetesting "k8s.io/component-base/featuregate/testing" apitesting "k8s.io/kubernetes/pkg/api/testing" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/features" "reflect" "testing" "time" @@ -53,14 +50,12 @@ func TestStatusUpdate(t *testing.T) { }() tests := []struct { name string - fg bool oldObj *api.PersistentVolume newObj *api.PersistentVolume expectedObj *api.PersistentVolume }{ { - name: "feature enabled: timestamp is updated when phase changes", - fg: true, + name: "timestamp is updated when phase changes", oldObj: &api.PersistentVolume{ ObjectMeta: metav1.ObjectMeta{ Name: "foo", @@ -88,8 +83,7 @@ func TestStatusUpdate(t *testing.T) { }, }, { - name: "feature enabled: timestamp is updated when phase changes and old pv has a timestamp", - fg: true, + name: "timestamp is updated when phase changes and old pv has a timestamp", oldObj: &api.PersistentVolume{ ObjectMeta: metav1.ObjectMeta{ Name: "foo", @@ -118,8 +112,7 @@ func TestStatusUpdate(t *testing.T) { }, }, { - name: "feature enabled: user timestamp change is respected on no phase change", - fg: true, + name: "user timestamp change is respected on no phase change", oldObj: &api.PersistentVolume{ ObjectMeta: metav1.ObjectMeta{ Name: "foo", @@ -148,8 +141,7 @@ func TestStatusUpdate(t *testing.T) { }, }, { - name: "feature enabled: user timestamp is respected on phase change", - fg: true, + name: "user timestamp is respected on phase change", oldObj: &api.PersistentVolume{ ObjectMeta: metav1.ObjectMeta{ Name: "foo", @@ -179,8 +171,7 @@ func TestStatusUpdate(t *testing.T) { }, }, { - name: "feature enabled: user timestamp change is respected on no phase change when old pv has a timestamp", - fg: true, + name: "user timestamp change is respected on no phase change when old pv has a timestamp", oldObj: &api.PersistentVolume{ ObjectMeta: metav1.ObjectMeta{ Name: "foo", @@ -210,8 +201,7 @@ func TestStatusUpdate(t *testing.T) { }, }, { - name: "feature enabled: timestamp is updated when phase changes and both new and old timestamp matches", - fg: true, + name: "timestamp is updated when phase changes and both new and old timestamp matches", oldObj: &api.PersistentVolume{ ObjectMeta: metav1.ObjectMeta{ Name: "foo", @@ -240,131 +230,10 @@ func TestStatusUpdate(t *testing.T) { }, }, }, - { - name: "feature disabled: timestamp is not updated", - fg: false, - oldObj: &api.PersistentVolume{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - }, - Status: api.PersistentVolumeStatus{ - Phase: api.VolumePending, - }, - }, - newObj: &api.PersistentVolume{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - }, - Status: api.PersistentVolumeStatus{ - Phase: api.VolumeBound, - }, - }, - expectedObj: &api.PersistentVolume{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - }, - Status: api.PersistentVolumeStatus{ - Phase: api.VolumeBound, - }, - }, - }, - { - name: "feature disabled: user timestamp is overwritten on phase change to nil", - fg: false, - oldObj: &api.PersistentVolume{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - }, - Status: api.PersistentVolumeStatus{ - Phase: api.VolumePending, - }, - }, - newObj: &api.PersistentVolume{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - }, - Status: api.PersistentVolumeStatus{ - Phase: api.VolumePending, - LastPhaseTransitionTime: &later, - }, - }, - expectedObj: &api.PersistentVolume{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - }, - Status: api.PersistentVolumeStatus{ - Phase: api.VolumePending, - LastPhaseTransitionTime: nil, - }, - }, - }, - { - name: "feature disabled: user timestamp change is respected on phase change", - fg: false, - oldObj: &api.PersistentVolume{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - }, - Status: api.PersistentVolumeStatus{ - Phase: api.VolumePending, - LastPhaseTransitionTime: &origin, - }, - }, - newObj: &api.PersistentVolume{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - }, - Status: api.PersistentVolumeStatus{ - Phase: api.VolumeBound, - LastPhaseTransitionTime: &later, - }, - }, - expectedObj: &api.PersistentVolume{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - }, - Status: api.PersistentVolumeStatus{ - Phase: api.VolumeBound, - LastPhaseTransitionTime: &later, - }, - }, - }, - { - name: "feature disabled: user timestamp change is respected on no phase change", - fg: false, - oldObj: &api.PersistentVolume{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - }, - Status: api.PersistentVolumeStatus{ - Phase: api.VolumeBound, - LastPhaseTransitionTime: &origin, - }, - }, - newObj: &api.PersistentVolume{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - }, - Status: api.PersistentVolumeStatus{ - Phase: api.VolumeBound, - LastPhaseTransitionTime: &later, - }, - }, - expectedObj: &api.PersistentVolume{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - }, - Status: api.PersistentVolumeStatus{ - Phase: api.VolumeBound, - LastPhaseTransitionTime: &later, - }, - }, - }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PersistentVolumeLastPhaseTransitionTime, tc.fg) obj := tc.newObj.DeepCopy() StatusStrategy.PrepareForUpdate(context.TODO(), obj, tc.oldObj.DeepCopy()) @@ -383,13 +252,11 @@ func TestStatusCreate(t *testing.T) { }() tests := []struct { name string - fg bool newObj *api.PersistentVolume expectedObj *api.PersistentVolume }{ { - name: "feature enabled: pv is in pending phase and has a timestamp", - fg: true, + name: "pv is in pending phase and has a timestamp", newObj: &api.PersistentVolume{ ObjectMeta: metav1.ObjectMeta{ Name: "foo", @@ -405,26 +272,11 @@ func TestStatusCreate(t *testing.T) { }, }, }, - { - name: "feature disabled: pv does not have phase and timestamp", - fg: false, - newObj: &api.PersistentVolume{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - }, - }, - expectedObj: &api.PersistentVolume{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - }, - }, - }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PersistentVolumeLastPhaseTransitionTime, tc.fg) obj := tc.newObj.DeepCopy() StatusStrategy.PrepareForCreate(context.TODO(), obj) if !reflect.DeepEqual(obj, tc.expectedObj) { diff --git a/staging/src/k8s.io/api/core/v1/generated.proto b/staging/src/k8s.io/api/core/v1/generated.proto index 1e10dad160d..fa70d7981b5 100644 --- a/staging/src/k8s.io/api/core/v1/generated.proto +++ b/staging/src/k8s.io/api/core/v1/generated.proto @@ -3415,8 +3415,6 @@ message PersistentVolumeStatus { // lastPhaseTransitionTime is the time the phase transitioned from one to another // and automatically resets to current time everytime a volume phase transitions. - // This is a beta field and requires the PersistentVolumeLastPhaseTransitionTime feature to be enabled (enabled by default). - // +featureGate=PersistentVolumeLastPhaseTransitionTime // +optional optional .k8s.io.apimachinery.pkg.apis.meta.v1.Time lastPhaseTransitionTime = 4; } diff --git a/staging/src/k8s.io/api/core/v1/types.go b/staging/src/k8s.io/api/core/v1/types.go index 0ef5fe6d62c..ba69881b36d 100644 --- a/staging/src/k8s.io/api/core/v1/types.go +++ b/staging/src/k8s.io/api/core/v1/types.go @@ -426,8 +426,6 @@ type PersistentVolumeStatus struct { Reason string `json:"reason,omitempty" protobuf:"bytes,3,opt,name=reason"` // lastPhaseTransitionTime is the time the phase transitioned from one to another // and automatically resets to current time everytime a volume phase transitions. - // This is a beta field and requires the PersistentVolumeLastPhaseTransitionTime feature to be enabled (enabled by default). - // +featureGate=PersistentVolumeLastPhaseTransitionTime // +optional LastPhaseTransitionTime *metav1.Time `json:"lastPhaseTransitionTime,omitempty" protobuf:"bytes,4,opt,name=lastPhaseTransitionTime"` } diff --git a/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go b/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go index 65d2a9fded9..0e30088853c 100644 --- a/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go +++ b/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go @@ -1511,7 +1511,7 @@ var map_PersistentVolumeStatus = map[string]string{ "phase": "phase indicates if a volume is available, bound to a claim, or released by a claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#phase", "message": "message is a human-readable message indicating details about why the volume is in this state.", "reason": "reason is a brief CamelCase string that describes any failure and is meant for machine parsing and tidy display in the CLI.", - "lastPhaseTransitionTime": "lastPhaseTransitionTime is the time the phase transitioned from one to another and automatically resets to current time everytime a volume phase transitions. This is a beta field and requires the PersistentVolumeLastPhaseTransitionTime feature to be enabled (enabled by default).", + "lastPhaseTransitionTime": "lastPhaseTransitionTime is the time the phase transitioned from one to another and automatically resets to current time everytime a volume phase transitions.", } func (PersistentVolumeStatus) SwaggerDoc() map[string]string { diff --git a/test/e2e/feature/feature.go b/test/e2e/feature/feature.go index 0471601a22b..b8b3b71c099 100644 --- a/test/e2e/feature/feature.go +++ b/test/e2e/feature/feature.go @@ -237,9 +237,6 @@ var ( // Marks a single test that tests pod-to-pod connectivity between every pair of nodes. NoSNAT = framework.WithFeature(framework.ValidFeatures.Add("NoSNAT")) - // TODO: document the feature (owning SIG, when to use this feature for a test) - PersistentVolumeLastPhaseTransitionTime = framework.WithFeature(framework.ValidFeatures.Add("PersistentVolumeLastPhaseTransitionTime")) - // Owner: sig-network // Marks a single test that tests cluster DNS performance with many services. PerformanceDNS = framework.WithFeature(framework.ValidFeatures.Add("PerformanceDNS")) diff --git a/test/e2e/storage/persistent_volumes.go b/test/e2e/storage/persistent_volumes.go index 3bbcaad53cb..7686a0b6fac 100644 --- a/test/e2e/storage/persistent_volumes.go +++ b/test/e2e/storage/persistent_volumes.go @@ -34,7 +34,6 @@ import ( "k8s.io/apimachinery/pkg/util/uuid" clientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/util/retry" - "k8s.io/kubernetes/test/e2e/feature" "k8s.io/kubernetes/test/e2e/framework" e2epod "k8s.io/kubernetes/test/e2e/framework/pod" e2epv "k8s.io/kubernetes/test/e2e/framework/pv" @@ -213,7 +212,7 @@ var _ = utils.SIGDescribe("PersistentVolumes", func() { }) // Create new PV without claim, verify it's in Available state and LastPhaseTransitionTime is set. - f.It("create a PV: test phase transition timestamp is set and phase is Available", feature.PersistentVolumeLastPhaseTransitionTime, func(ctx context.Context) { + f.It("create a PV: test phase transition timestamp is set and phase is Available", func(ctx context.Context) { pvObj := e2epv.MakePersistentVolume(pvConfig) pv, err = e2epv.CreatePV(ctx, c, f.Timeouts, pvObj) framework.ExpectNoError(err) @@ -232,7 +231,7 @@ var _ = utils.SIGDescribe("PersistentVolumes", func() { // Create PV and pre-bound PVC that matches the PV, verify that when PV and PVC bind // the LastPhaseTransitionTime filed of the PV is updated. - f.It("create a PV and a pre-bound PVC: test phase transition timestamp is set", feature.PersistentVolumeLastPhaseTransitionTime, func(ctx context.Context) { + f.It("create a PV and a pre-bound PVC: test phase transition timestamp is set", func(ctx context.Context) { pv, pvc, err = e2epv.CreatePVPVC(ctx, c, f.Timeouts, pvConfig, pvcConfig, ns, true) framework.ExpectNoError(err) @@ -252,7 +251,7 @@ var _ = utils.SIGDescribe("PersistentVolumes", func() { // Create PV and pre-bound PVC that matches the PV, verify that when PV and PVC bind // the LastPhaseTransitionTime field of the PV is set, then delete the PVC to change PV phase to // released and validate PV LastPhaseTransitionTime correctly updated timestamp. - f.It("create a PV and a pre-bound PVC: test phase transition timestamp multiple updates", feature.PersistentVolumeLastPhaseTransitionTime, func(ctx context.Context) { + f.It("create a PV and a pre-bound PVC: test phase transition timestamp multiple updates", func(ctx context.Context) { pv, pvc, err = e2epv.CreatePVPVC(ctx, c, f.Timeouts, pvConfig, pvcConfig, ns, true) framework.ExpectNoError(err)