diff --git a/pkg/controller/volume/persistentvolume/index.go b/pkg/controller/volume/persistentvolume/index.go index 613a04c0c4c..19195e81523 100644 --- a/pkg/controller/volume/persistentvolume/index.go +++ b/pkg/controller/volume/persistentvolume/index.go @@ -259,22 +259,23 @@ func findMatchingVolume( } // checkVolumeModeMismatches is a convenience method that checks volumeMode for PersistentVolume -// and PersistentVolumeClaims along with making sure that the feature gate BlockVolume is enabled. +// and PersistentVolumeClaims func checkVolumeModeMismatches(pvcSpec *v1.PersistentVolumeClaimSpec, pvSpec *v1.PersistentVolumeSpec) (bool, error) { - if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { - if pvSpec.VolumeMode != nil && pvcSpec.VolumeMode != nil { - requestedVolumeMode := *pvcSpec.VolumeMode - pvVolumeMode := *pvSpec.VolumeMode - return requestedVolumeMode != pvVolumeMode, nil - } else { - // This also should return an error, this means that - // the defaulting has failed. - return true, fmt.Errorf("api defaulting for volumeMode failed") - } - } else { - // feature gate is disabled + if !utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { return false, nil } + + // In HA upgrades, we cannot guarantee that the apiserver is on a version >= controller-manager. + // So we default a nil volumeMode to filesystem + requestedVolumeMode := v1.PersistentVolumeFilesystem + if pvcSpec.VolumeMode != nil { + requestedVolumeMode = *pvcSpec.VolumeMode + } + pvVolumeMode := v1.PersistentVolumeFilesystem + if pvSpec.VolumeMode != nil { + pvVolumeMode = *pvSpec.VolumeMode + } + return requestedVolumeMode != pvVolumeMode, nil } // findBestMatchForClaim is a convenience method that finds a volume by the claim's AccessModes and requests for Storage diff --git a/pkg/controller/volume/persistentvolume/index_test.go b/pkg/controller/volume/persistentvolume/index_test.go index fa3d0340d7e..8729891c2c7 100644 --- a/pkg/controller/volume/persistentvolume/index_test.go +++ b/pkg/controller/volume/persistentvolume/index_test.go @@ -1038,6 +1038,29 @@ func createVolumeModeFilesystemTestVolume() *v1.PersistentVolume { } } +func createVolumeModeNilTestVolume() *v1.PersistentVolume { + return &v1.PersistentVolume{ + ObjectMeta: metav1.ObjectMeta{ + UID: "local-1", + Name: "nil-mode", + }, + Spec: v1.PersistentVolumeSpec{ + Capacity: v1.ResourceList{ + v1.ResourceName(v1.ResourceStorage): resource.MustParse("10G"), + }, + PersistentVolumeSource: v1.PersistentVolumeSource{ + Local: &v1.LocalVolumeSource{}, + }, + AccessModes: []v1.PersistentVolumeAccessMode{ + v1.ReadWriteOnce, + }, + }, + Status: v1.PersistentVolumeStatus{ + Phase: v1.VolumeAvailable, + }, + } +} + func createTestVolOrderedIndex(pv *v1.PersistentVolume) persistentVolumeOrderedIndex { volFile := newPersistentVolumeOrderedIndex() volFile.store.Add(pv) @@ -1081,6 +1104,36 @@ func TestVolumeModeCheck(t *testing.T) { pvc: makeVolumeModePVC("8G", &filesystemMode, nil), enableBlock: true, }, + "feature enabled - pvc filesystem and pv nil": { + isExpectedMismatch: false, + vol: createVolumeModeNilTestVolume(), + pvc: makeVolumeModePVC("8G", &filesystemMode, nil), + enableBlock: true, + }, + "feature enabled - pvc nil and pv filesytem": { + isExpectedMismatch: false, + vol: createVolumeModeFilesystemTestVolume(), + pvc: makeVolumeModePVC("8G", nil, nil), + enableBlock: true, + }, + "feature enabled - pvc nil and pv nil": { + isExpectedMismatch: false, + vol: createVolumeModeNilTestVolume(), + pvc: makeVolumeModePVC("8G", nil, nil), + enableBlock: true, + }, + "feature enabled - pvc nil and pv block": { + isExpectedMismatch: true, + vol: createVolumeModeBlockTestVolume(), + pvc: makeVolumeModePVC("8G", nil, nil), + enableBlock: true, + }, + "feature enabled - pvc block and pv nil": { + isExpectedMismatch: true, + vol: createVolumeModeNilTestVolume(), + pvc: makeVolumeModePVC("8G", &blockMode, nil), + enableBlock: true, + }, "feature disabled - pvc block and pv filesystem": { isExpectedMismatch: false, vol: createVolumeModeFilesystemTestVolume(),