Update all tests to account for BlockVolume enabled by default

pull/58/head
Matthew Wong 2018-07-04 16:08:06 -04:00
parent 7a6acefd21
commit dd517c9ff2
13 changed files with 217 additions and 95 deletions

View File

@ -403,11 +403,15 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
pv.Status.Message = c.RandString() pv.Status.Message = c.RandString()
reclamationPolicies := []core.PersistentVolumeReclaimPolicy{core.PersistentVolumeReclaimRecycle, core.PersistentVolumeReclaimRetain} reclamationPolicies := []core.PersistentVolumeReclaimPolicy{core.PersistentVolumeReclaimRecycle, core.PersistentVolumeReclaimRetain}
pv.Spec.PersistentVolumeReclaimPolicy = reclamationPolicies[c.Rand.Intn(len(reclamationPolicies))] pv.Spec.PersistentVolumeReclaimPolicy = reclamationPolicies[c.Rand.Intn(len(reclamationPolicies))]
volumeModes := []core.PersistentVolumeMode{core.PersistentVolumeFilesystem, core.PersistentVolumeBlock}
pv.Spec.VolumeMode = &volumeModes[c.Rand.Intn(len(volumeModes))]
}, },
func(pvc *core.PersistentVolumeClaim, c fuzz.Continue) { func(pvc *core.PersistentVolumeClaim, c fuzz.Continue) {
c.FuzzNoCustom(pvc) // fuzz self without calling this function again c.FuzzNoCustom(pvc) // fuzz self without calling this function again
types := []core.PersistentVolumeClaimPhase{core.ClaimBound, core.ClaimPending, core.ClaimLost} types := []core.PersistentVolumeClaimPhase{core.ClaimBound, core.ClaimPending, core.ClaimLost}
pvc.Status.Phase = types[c.Rand.Intn(len(types))] pvc.Status.Phase = types[c.Rand.Intn(len(types))]
volumeModes := []core.PersistentVolumeMode{core.PersistentVolumeFilesystem, core.PersistentVolumeBlock}
pvc.Spec.VolumeMode = &volumeModes[c.Rand.Intn(len(volumeModes))]
}, },
func(obj *core.AzureDiskVolumeSource, c fuzz.Continue) { func(obj *core.AzureDiskVolumeSource, c fuzz.Continue) {
if obj.CachingMode == nil { if obj.CachingMode == nil {

View File

@ -27,8 +27,10 @@ import (
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/intstr"
utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeature "k8s.io/apiserver/pkg/util/feature"
utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing"
"k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/legacyscheme"
corev1 "k8s.io/kubernetes/pkg/apis/core/v1" corev1 "k8s.io/kubernetes/pkg/apis/core/v1"
"k8s.io/kubernetes/pkg/features"
utilpointer "k8s.io/utils/pointer" utilpointer "k8s.io/utils/pointer"
// enforce that all types are installed // enforce that all types are installed
@ -803,6 +805,7 @@ func TestSetDefaultSecret(t *testing.T) {
} }
func TestSetDefaultPersistentVolume(t *testing.T) { func TestSetDefaultPersistentVolume(t *testing.T) {
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, false)()
pv := &v1.PersistentVolume{} pv := &v1.PersistentVolume{}
obj2 := roundTrip(t, runtime.Object(pv)) obj2 := roundTrip(t, runtime.Object(pv))
pv2 := obj2.(*v1.PersistentVolume) pv2 := obj2.(*v1.PersistentVolume)
@ -834,15 +837,10 @@ func TestSetDefaultPersistentVolume(t *testing.T) {
} else if *outputMode3 != defaultMode { } else if *outputMode3 != defaultMode {
t.Errorf("Expected VolumeMode to be defaulted to: %+v, got: %+v", defaultMode, outputMode3) t.Errorf("Expected VolumeMode to be defaulted to: %+v, got: %+v", defaultMode, outputMode3)
} }
err = utilfeature.DefaultFeatureGate.Set("BlockVolume=false")
if err != nil {
t.Fatalf("Failed to disable feature gate for BlockVolume: %v", err)
}
} }
func TestSetDefaultPersistentVolumeClaim(t *testing.T) { func TestSetDefaultPersistentVolumeClaim(t *testing.T) {
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, false)()
pvc := &v1.PersistentVolumeClaim{} pvc := &v1.PersistentVolumeClaim{}
obj2 := roundTrip(t, runtime.Object(pvc)) obj2 := roundTrip(t, runtime.Object(pvc))
pvc2 := obj2.(*v1.PersistentVolumeClaim) pvc2 := obj2.(*v1.PersistentVolumeClaim)
@ -871,11 +869,6 @@ func TestSetDefaultPersistentVolumeClaim(t *testing.T) {
} else if *outputMode3 != defaultMode { } else if *outputMode3 != defaultMode {
t.Errorf("Expected VolumeMode to be defaulted to: %+v, got: %+v", defaultMode, outputMode3) t.Errorf("Expected VolumeMode to be defaulted to: %+v, got: %+v", defaultMode, outputMode3)
} }
err = utilfeature.DefaultFeatureGate.Set("BlockVolume=false")
if err != nil {
t.Fatalf("Failed to disable feature gate for BlockVolume: %v", err)
}
} }
func TestSetDefaulEndpointsProtocol(t *testing.T) { func TestSetDefaulEndpointsProtocol(t *testing.T) {

View File

@ -66,9 +66,11 @@ func testVolume(name string, namespace string, spec core.PersistentVolumeSpec) *
func TestValidatePersistentVolumes(t *testing.T) { func TestValidatePersistentVolumes(t *testing.T) {
validMode := core.PersistentVolumeFilesystem validMode := core.PersistentVolumeFilesystem
invalidMode := core.PersistentVolumeMode("fakeVolumeMode")
scenarios := map[string]struct { scenarios := map[string]struct {
isExpectedFailure bool isExpectedFailure bool
volume *core.PersistentVolume volume *core.PersistentVolume
disableBlockVolume bool
}{ }{
"good-volume": { "good-volume": {
isExpectedFailure: false, isExpectedFailure: false,
@ -147,6 +149,22 @@ func TestValidatePersistentVolumes(t *testing.T) {
PersistentVolumeReclaimPolicy: core.PersistentVolumeReclaimRetain, PersistentVolumeReclaimPolicy: core.PersistentVolumeReclaimRetain,
}), }),
}, },
"good-volume-with-volume-mode": {
isExpectedFailure: false,
volume: testVolume("foo", "", core.PersistentVolumeSpec{
Capacity: core.ResourceList{
core.ResourceName(core.ResourceStorage): resource.MustParse("10G"),
},
AccessModes: []core.PersistentVolumeAccessMode{core.ReadWriteOnce},
PersistentVolumeSource: core.PersistentVolumeSource{
HostPath: &core.HostPathVolumeSource{
Path: "/foo",
Type: newHostPathType(string(core.HostPathDirectory)),
},
},
VolumeMode: &validMode,
}),
},
"invalid-accessmode": { "invalid-accessmode": {
isExpectedFailure: true, isExpectedFailure: true,
volume: testVolume("foo", "", core.PersistentVolumeSpec{ volume: testVolume("foo", "", core.PersistentVolumeSpec{
@ -178,6 +196,22 @@ func TestValidatePersistentVolumes(t *testing.T) {
PersistentVolumeReclaimPolicy: "fakeReclaimPolicy", PersistentVolumeReclaimPolicy: "fakeReclaimPolicy",
}), }),
}, },
"invalid-volume-mode": {
isExpectedFailure: true,
volume: testVolume("foo", "", core.PersistentVolumeSpec{
Capacity: core.ResourceList{
core.ResourceName(core.ResourceStorage): resource.MustParse("10G"),
},
AccessModes: []core.PersistentVolumeAccessMode{core.ReadWriteOnce},
PersistentVolumeSource: core.PersistentVolumeSource{
HostPath: &core.HostPathVolumeSource{
Path: "/foo",
Type: newHostPathType(string(core.HostPathDirectory)),
},
},
VolumeMode: &invalidMode,
}),
},
"unexpected-namespace": { "unexpected-namespace": {
isExpectedFailure: true, isExpectedFailure: true,
volume: testVolume("foo", "unexpected-namespace", core.PersistentVolumeSpec{ volume: testVolume("foo", "unexpected-namespace", core.PersistentVolumeSpec{
@ -336,9 +370,8 @@ func TestValidatePersistentVolumes(t *testing.T) {
StorageClassName: "-invalid-", StorageClassName: "-invalid-",
}), }),
}, },
// VolumeMode alpha feature disabled "feature disabled valid volume mode": {
// TODO: remove when no longer alpha disableBlockVolume: true,
"alpha disabled valid volume mode": {
isExpectedFailure: true, isExpectedFailure: true,
volume: testVolume("foo", "", core.PersistentVolumeSpec{ volume: testVolume("foo", "", core.PersistentVolumeSpec{
Capacity: core.ResourceList{ Capacity: core.ResourceList{
@ -400,6 +433,10 @@ func TestValidatePersistentVolumes(t *testing.T) {
} }
for name, scenario := range scenarios { for name, scenario := range scenarios {
var restore func()
if scenario.disableBlockVolume {
restore = utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, false)
}
errs := ValidatePersistentVolume(scenario.volume) errs := ValidatePersistentVolume(scenario.volume)
if len(errs) == 0 && scenario.isExpectedFailure { if len(errs) == 0 && scenario.isExpectedFailure {
t.Errorf("Unexpected success for scenario: %s", name) t.Errorf("Unexpected success for scenario: %s", name)
@ -407,6 +444,9 @@ func TestValidatePersistentVolumes(t *testing.T) {
if len(errs) > 0 && !scenario.isExpectedFailure { if len(errs) > 0 && !scenario.isExpectedFailure {
t.Errorf("Unexpected failure for scenario: %s - %+v", name, errs) t.Errorf("Unexpected failure for scenario: %s - %+v", name, errs)
} }
if scenario.disableBlockVolume {
restore()
}
} }
} }
@ -791,10 +831,12 @@ func testVolumeClaimStorageClassInAnnotationAndSpec(name, namespace, scNameInAnn
func TestValidatePersistentVolumeClaim(t *testing.T) { func TestValidatePersistentVolumeClaim(t *testing.T) {
invalidClassName := "-invalid-" invalidClassName := "-invalid-"
validClassName := "valid" validClassName := "valid"
invalidMode := core.PersistentVolumeMode("fakeVolumeMode")
validMode := core.PersistentVolumeFilesystem validMode := core.PersistentVolumeFilesystem
scenarios := map[string]struct { scenarios := map[string]struct {
isExpectedFailure bool isExpectedFailure bool
claim *core.PersistentVolumeClaim claim *core.PersistentVolumeClaim
disableBlockVolume bool
}{ }{
"good-claim": { "good-claim": {
isExpectedFailure: false, isExpectedFailure: false,
@ -817,6 +859,7 @@ func TestValidatePersistentVolumeClaim(t *testing.T) {
}, },
}, },
StorageClassName: &validClassName, StorageClassName: &validClassName,
VolumeMode: &validMode,
}), }),
}, },
"invalid-claim-zero-capacity": { "invalid-claim-zero-capacity": {
@ -988,9 +1031,8 @@ func TestValidatePersistentVolumeClaim(t *testing.T) {
StorageClassName: &invalidClassName, StorageClassName: &invalidClassName,
}), }),
}, },
// VolumeMode alpha feature disabled "feature disabled valid volume mode": {
// TODO: remove when no longer alpha disableBlockVolume: true,
"disabled alpha valid volume mode": {
isExpectedFailure: true, isExpectedFailure: true,
claim: testVolumeClaim("foo", "ns", core.PersistentVolumeClaimSpec{ claim: testVolumeClaim("foo", "ns", core.PersistentVolumeClaimSpec{
Selector: &metav1.LabelSelector{ Selector: &metav1.LabelSelector{
@ -1014,9 +1056,28 @@ func TestValidatePersistentVolumeClaim(t *testing.T) {
VolumeMode: &validMode, VolumeMode: &validMode,
}), }),
}, },
"invalid-volume-mode": {
isExpectedFailure: true,
claim: testVolumeClaim("foo", "ns", core.PersistentVolumeClaimSpec{
AccessModes: []core.PersistentVolumeAccessMode{
core.ReadWriteOnce,
core.ReadOnlyMany,
},
Resources: core.ResourceRequirements{
Requests: core.ResourceList{
core.ResourceName(core.ResourceStorage): resource.MustParse("10G"),
},
},
VolumeMode: &invalidMode,
}),
},
} }
for name, scenario := range scenarios { for name, scenario := range scenarios {
var restore func()
if scenario.disableBlockVolume {
restore = utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, false)
}
errs := ValidatePersistentVolumeClaim(scenario.claim) errs := ValidatePersistentVolumeClaim(scenario.claim)
if len(errs) == 0 && scenario.isExpectedFailure { if len(errs) == 0 && scenario.isExpectedFailure {
t.Errorf("Unexpected success for scenario: %s", name) t.Errorf("Unexpected success for scenario: %s", name)
@ -1024,6 +1085,9 @@ func TestValidatePersistentVolumeClaim(t *testing.T) {
if len(errs) > 0 && !scenario.isExpectedFailure { if len(errs) > 0 && !scenario.isExpectedFailure {
t.Errorf("Unexpected failure for scenario: %s - %+v", name, errs) t.Errorf("Unexpected failure for scenario: %s - %+v", name, errs)
} }
if scenario.disableBlockVolume {
restore()
}
} }
} }

View File

@ -23,6 +23,8 @@ import (
storage "k8s.io/api/storage/v1" storage "k8s.io/api/storage/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeature "k8s.io/apiserver/pkg/util/feature"
utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing"
"k8s.io/kubernetes/pkg/features"
) )
// Test single call to syncClaim and syncVolume methods. // Test single call to syncClaim and syncVolume methods.
@ -35,8 +37,6 @@ func TestSync(t *testing.T) {
"foo": "true", "foo": "true",
"bar": "false", "bar": "false",
} }
modeBlock := v1.PersistentVolumeBlock
modeFile := v1.PersistentVolumeFilesystem
tests := []controllerTest{ tests := []controllerTest{
// [Unit test set 1] User did not care which PV they get. // [Unit test set 1] User did not care which PV they get.
@ -589,9 +589,22 @@ func TestSync(t *testing.T) {
newClaimArray("claim13-5", "uid13-5", "1Gi", "volume13-5", v1.ClaimBound, nil, annBoundByController, annBindCompleted), newClaimArray("claim13-5", "uid13-5", "1Gi", "volume13-5", v1.ClaimBound, nil, annBoundByController, annBindCompleted),
noevents, noerrors, testSyncClaim, noevents, noerrors, testSyncClaim,
}, },
}
runSyncTests(t, tests, []*storage.StorageClass{
{
ObjectMeta: metav1.ObjectMeta{Name: classWait},
VolumeBindingMode: &modeWait,
},
}, []*v1.Pod{})
}
func TestSyncBlockVolumeDisabled(t *testing.T) {
modeBlock := v1.PersistentVolumeBlock
modeFile := v1.PersistentVolumeFilesystem
// All of these should bind as feature set is not enabled for BlockVolume // All of these should bind as feature set is not enabled for BlockVolume
// meaning volumeMode will be ignored and dropped // meaning volumeMode will be ignored and dropped
tests := []controllerTest{
{ {
// syncVolume binds a requested block claim to a block volume // syncVolume binds a requested block claim to a block volume
"14-1 - binding to volumeMode block", "14-1 - binding to volumeMode block",
@ -639,6 +652,7 @@ func TestSync(t *testing.T) {
}, },
} }
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, false)()
runSyncTests(t, tests, []*storage.StorageClass{ runSyncTests(t, tests, []*storage.StorageClass{
{ {
ObjectMeta: metav1.ObjectMeta{Name: classWait}, ObjectMeta: metav1.ObjectMeta{Name: classWait},
@ -647,7 +661,7 @@ func TestSync(t *testing.T) {
}, []*v1.Pod{}) }, []*v1.Pod{})
} }
func TestSyncAlphaBlockVolume(t *testing.T) { func TestSyncBlockVolume(t *testing.T) {
modeBlock := v1.PersistentVolumeBlock modeBlock := v1.PersistentVolumeBlock
modeFile := v1.PersistentVolumeFilesystem modeFile := v1.PersistentVolumeFilesystem
@ -827,12 +841,7 @@ func TestSyncAlphaBlockVolume(t *testing.T) {
}, },
} }
err := utilfeature.DefaultFeatureGate.Set("BlockVolume=true") defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
if err != nil {
t.Errorf("Failed to enable feature gate for BlockVolume: %v", err)
return
}
defer utilfeature.DefaultFeatureGate.Set("BlockVolume=false")
runSyncTests(t, tests, []*storage.StorageClass{}, []*v1.Pod{}) runSyncTests(t, tests, []*storage.StorageClass{}, []*v1.Pod{})
} }

View File

@ -38,6 +38,7 @@ import (
"k8s.io/apimachinery/pkg/util/diff" "k8s.io/apimachinery/pkg/util/diff"
"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apimachinery/pkg/watch" "k8s.io/apimachinery/pkg/watch"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
clientset "k8s.io/client-go/kubernetes" clientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/fake" "k8s.io/client-go/kubernetes/fake"
@ -48,6 +49,7 @@ import (
"k8s.io/client-go/tools/record" "k8s.io/client-go/tools/record"
"k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/api/testapi"
"k8s.io/kubernetes/pkg/controller" "k8s.io/kubernetes/pkg/controller"
"k8s.io/kubernetes/pkg/features"
vol "k8s.io/kubernetes/pkg/volume" vol "k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/util/recyclerclient" "k8s.io/kubernetes/pkg/volume/util/recyclerclient"
) )
@ -179,6 +181,12 @@ func (r *volumeReactor) React(action core.Action) (handled bool, ret runtime.Obj
return true, nil, fmt.Errorf("Cannot create volume %s: volume already exists", volume.Name) return true, nil, fmt.Errorf("Cannot create volume %s: volume already exists", volume.Name)
} }
// mimic apiserver defaulting
if volume.Spec.VolumeMode == nil && utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
volume.Spec.VolumeMode = new(v1.PersistentVolumeMode)
*volume.Spec.VolumeMode = v1.PersistentVolumeFilesystem
}
// Store the updated object to appropriate places. // Store the updated object to appropriate places.
r.volumes[volume.Name] = volume r.volumes[volume.Name] = volume
r.changedObjects = append(r.changedObjects, volume) r.changedObjects = append(r.changedObjects, volume)
@ -630,6 +638,7 @@ func newTestController(kubeClient clientset.Interface, informerFactory informers
// newVolume returns a new volume with given attributes // newVolume returns a new volume with given attributes
func newVolume(name, capacity, boundToClaimUID, boundToClaimName string, phase v1.PersistentVolumePhase, reclaimPolicy v1.PersistentVolumeReclaimPolicy, class string, annotations ...string) *v1.PersistentVolume { func newVolume(name, capacity, boundToClaimUID, boundToClaimName string, phase v1.PersistentVolumePhase, reclaimPolicy v1.PersistentVolumeReclaimPolicy, class string, annotations ...string) *v1.PersistentVolume {
fs := v1.PersistentVolumeFilesystem
volume := v1.PersistentVolume{ volume := v1.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: name, Name: name,
@ -645,6 +654,7 @@ func newVolume(name, capacity, boundToClaimUID, boundToClaimName string, phase v
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce, v1.ReadOnlyMany}, AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce, v1.ReadOnlyMany},
PersistentVolumeReclaimPolicy: reclaimPolicy, PersistentVolumeReclaimPolicy: reclaimPolicy,
StorageClassName: class, StorageClassName: class,
VolumeMode: &fs,
}, },
Status: v1.PersistentVolumeStatus{ Status: v1.PersistentVolumeStatus{
Phase: phase, Phase: phase,
@ -740,6 +750,7 @@ func newVolumeArray(name, capacity, boundToClaimUID, boundToClaimName string, ph
// newClaim returns a new claim with given attributes // newClaim returns a new claim with given attributes
func newClaim(name, claimUID, capacity, boundToVolume string, phase v1.PersistentVolumeClaimPhase, class *string, annotations ...string) *v1.PersistentVolumeClaim { func newClaim(name, claimUID, capacity, boundToVolume string, phase v1.PersistentVolumeClaimPhase, class *string, annotations ...string) *v1.PersistentVolumeClaim {
fs := v1.PersistentVolumeFilesystem
claim := v1.PersistentVolumeClaim{ claim := v1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: name, Name: name,
@ -756,6 +767,7 @@ func newClaim(name, claimUID, capacity, boundToVolume string, phase v1.Persisten
}, },
VolumeName: boundToVolume, VolumeName: boundToVolume,
StorageClassName: class, StorageClassName: class,
VolumeMode: &fs,
}, },
Status: v1.PersistentVolumeClaimStatus{ Status: v1.PersistentVolumeClaimStatus{
Phase: phase, Phase: phase,
@ -1226,6 +1238,7 @@ func (plugin *mockVolumePlugin) Provision(selectedNode *v1.Node, allowedTopologi
Phase: v1.VolumeAvailable, Phase: v1.VolumeAvailable,
}, },
} }
pv.Spec.VolumeMode = plugin.provisionOptions.PVC.Spec.VolumeMode
} }
plugin.provisionCallCounter++ plugin.provisionCallCounter++

View File

@ -158,13 +158,13 @@ func findMatchingVolume(
volumeQty := volume.Spec.Capacity[v1.ResourceStorage] volumeQty := volume.Spec.Capacity[v1.ResourceStorage]
// check if volumeModes do not match (Alpha and feature gate protected) // check if volumeModes do not match (feature gate protected)
isMisMatch, err := checkVolumeModeMisMatches(&claim.Spec, &volume.Spec) isMismatch, err := checkVolumeModeMismatches(&claim.Spec, &volume.Spec)
if err != nil { if err != nil {
return nil, fmt.Errorf("error checking if volumeMode was a mismatch: %v", err) return nil, fmt.Errorf("error checking if volumeMode was a mismatch: %v", err)
} }
// filter out mismatching volumeModes // filter out mismatching volumeModes
if isMisMatch { if isMismatch {
continue continue
} }
@ -258,18 +258,16 @@ func findMatchingVolume(
return nil, nil return nil, nil
} }
// checkVolumeModeMatches is a convenience method that checks volumeMode for PersistentVolume // checkVolumeModeMismatches is a convenience method that checks volumeMode for PersistentVolume
// and PersistentVolumeClaims along with making sure that the Alpha feature gate BlockVolume is // and PersistentVolumeClaims along with making sure that the feature gate BlockVolume is enabled.
// enabled. func checkVolumeModeMismatches(pvcSpec *v1.PersistentVolumeClaimSpec, pvSpec *v1.PersistentVolumeSpec) (bool, error) {
// This is Alpha and could change in the future.
func checkVolumeModeMisMatches(pvcSpec *v1.PersistentVolumeClaimSpec, pvSpec *v1.PersistentVolumeSpec) (bool, error) {
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) { if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
if pvSpec.VolumeMode != nil && pvcSpec.VolumeMode != nil { if pvSpec.VolumeMode != nil && pvcSpec.VolumeMode != nil {
requestedVolumeMode := *pvcSpec.VolumeMode requestedVolumeMode := *pvcSpec.VolumeMode
pvVolumeMode := *pvSpec.VolumeMode pvVolumeMode := *pvSpec.VolumeMode
return requestedVolumeMode != pvVolumeMode, nil return requestedVolumeMode != pvVolumeMode, nil
} else { } else {
// This also should retrun an error, this means that // This also should return an error, this means that
// the defaulting has failed. // the defaulting has failed.
return true, fmt.Errorf("api defaulting for volumeMode failed") return true, fmt.Errorf("api defaulting for volumeMode failed")
} }

View File

@ -33,6 +33,7 @@ import (
) )
func makePVC(size string, modfn func(*v1.PersistentVolumeClaim)) *v1.PersistentVolumeClaim { func makePVC(size string, modfn func(*v1.PersistentVolumeClaim)) *v1.PersistentVolumeClaim {
fs := v1.PersistentVolumeFilesystem
pvc := v1.PersistentVolumeClaim{ pvc := v1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "claim01", Name: "claim01",
@ -45,6 +46,7 @@ func makePVC(size string, modfn func(*v1.PersistentVolumeClaim)) *v1.PersistentV
v1.ResourceName(v1.ResourceStorage): resource.MustParse(size), v1.ResourceName(v1.ResourceStorage): resource.MustParse(size),
}, },
}, },
VolumeMode: &fs,
}, },
} }
if modfn != nil { if modfn != nil {
@ -197,6 +199,7 @@ func TestMatchVolume(t *testing.T) {
} }
func TestMatchingWithBoundVolumes(t *testing.T) { func TestMatchingWithBoundVolumes(t *testing.T) {
fs := v1.PersistentVolumeFilesystem
volumeIndex := newPersistentVolumeOrderedIndex() volumeIndex := newPersistentVolumeOrderedIndex()
// two similar volumes, one is bound // two similar volumes, one is bound
pv1 := &v1.PersistentVolume{ pv1 := &v1.PersistentVolume{
@ -214,6 +217,7 @@ func TestMatchingWithBoundVolumes(t *testing.T) {
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce, v1.ReadOnlyMany}, AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce, v1.ReadOnlyMany},
// this one we're pretending is already bound // this one we're pretending is already bound
ClaimRef: &v1.ObjectReference{UID: "abc123"}, ClaimRef: &v1.ObjectReference{UID: "abc123"},
VolumeMode: &fs,
}, },
Status: v1.PersistentVolumeStatus{ Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeBound, Phase: v1.VolumeBound,
@ -233,6 +237,7 @@ func TestMatchingWithBoundVolumes(t *testing.T) {
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{}, GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{},
}, },
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce, v1.ReadOnlyMany}, AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce, v1.ReadOnlyMany},
VolumeMode: &fs,
}, },
Status: v1.PersistentVolumeStatus{ Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable, Phase: v1.VolumeAvailable,
@ -254,6 +259,7 @@ func TestMatchingWithBoundVolumes(t *testing.T) {
v1.ResourceName(v1.ResourceStorage): resource.MustParse("1G"), v1.ResourceName(v1.ResourceStorage): resource.MustParse("1G"),
}, },
}, },
VolumeMode: &fs,
}, },
} }
@ -328,6 +334,7 @@ func TestAllPossibleAccessModes(t *testing.T) {
} }
func TestFindingVolumeWithDifferentAccessModes(t *testing.T) { func TestFindingVolumeWithDifferentAccessModes(t *testing.T) {
fs := v1.PersistentVolumeFilesystem
gce := &v1.PersistentVolume{ gce := &v1.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{UID: "001", Name: "gce"}, ObjectMeta: metav1.ObjectMeta{UID: "001", Name: "gce"},
Spec: v1.PersistentVolumeSpec{ Spec: v1.PersistentVolumeSpec{
@ -337,6 +344,7 @@ func TestFindingVolumeWithDifferentAccessModes(t *testing.T) {
v1.ReadWriteOnce, v1.ReadWriteOnce,
v1.ReadOnlyMany, v1.ReadOnlyMany,
}, },
VolumeMode: &fs,
}, },
Status: v1.PersistentVolumeStatus{ Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable, Phase: v1.VolumeAvailable,
@ -351,6 +359,7 @@ func TestFindingVolumeWithDifferentAccessModes(t *testing.T) {
AccessModes: []v1.PersistentVolumeAccessMode{ AccessModes: []v1.PersistentVolumeAccessMode{
v1.ReadWriteOnce, v1.ReadWriteOnce,
}, },
VolumeMode: &fs,
}, },
Status: v1.PersistentVolumeStatus{ Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable, Phase: v1.VolumeAvailable,
@ -367,6 +376,7 @@ func TestFindingVolumeWithDifferentAccessModes(t *testing.T) {
v1.ReadOnlyMany, v1.ReadOnlyMany,
v1.ReadWriteMany, v1.ReadWriteMany,
}, },
VolumeMode: &fs,
}, },
Status: v1.PersistentVolumeStatus{ Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable, Phase: v1.VolumeAvailable,
@ -381,6 +391,7 @@ func TestFindingVolumeWithDifferentAccessModes(t *testing.T) {
Spec: v1.PersistentVolumeClaimSpec{ Spec: v1.PersistentVolumeClaimSpec{
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
Resources: v1.ResourceRequirements{Requests: v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse("1G")}}, Resources: v1.ResourceRequirements{Requests: v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse("1G")}},
VolumeMode: &fs,
}, },
} }
@ -440,6 +451,7 @@ func TestFindingVolumeWithDifferentAccessModes(t *testing.T) {
} }
func createTestVolumes() []*v1.PersistentVolume { func createTestVolumes() []*v1.PersistentVolume {
fs := v1.PersistentVolumeFilesystem
// these volumes are deliberately out-of-order to test indexing and sorting // these volumes are deliberately out-of-order to test indexing and sorting
return []*v1.PersistentVolume{ return []*v1.PersistentVolume{
{ {
@ -458,6 +470,7 @@ func createTestVolumes() []*v1.PersistentVolume {
v1.ReadWriteOnce, v1.ReadWriteOnce,
v1.ReadOnlyMany, v1.ReadOnlyMany,
}, },
VolumeMode: &fs,
}, },
Status: v1.PersistentVolumeStatus{ Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable, Phase: v1.VolumeAvailable,
@ -481,6 +494,7 @@ func createTestVolumes() []*v1.PersistentVolume {
}, },
// this one we're pretending is already bound // this one we're pretending is already bound
ClaimRef: &v1.ObjectReference{UID: "def456"}, ClaimRef: &v1.ObjectReference{UID: "def456"},
VolumeMode: &fs,
}, },
Status: v1.PersistentVolumeStatus{ Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeBound, Phase: v1.VolumeBound,
@ -503,6 +517,7 @@ func createTestVolumes() []*v1.PersistentVolume {
v1.ReadOnlyMany, v1.ReadOnlyMany,
v1.ReadWriteMany, v1.ReadWriteMany,
}, },
VolumeMode: &fs,
}, },
Status: v1.PersistentVolumeStatus{ Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable, Phase: v1.VolumeAvailable,
@ -526,6 +541,7 @@ func createTestVolumes() []*v1.PersistentVolume {
}, },
// this one we're pretending is already bound // this one we're pretending is already bound
ClaimRef: &v1.ObjectReference{UID: "abc123"}, ClaimRef: &v1.ObjectReference{UID: "abc123"},
VolumeMode: &fs,
}, },
Status: v1.PersistentVolumeStatus{ Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeBound, Phase: v1.VolumeBound,
@ -548,6 +564,7 @@ func createTestVolumes() []*v1.PersistentVolume {
v1.ReadOnlyMany, v1.ReadOnlyMany,
v1.ReadWriteMany, v1.ReadWriteMany,
}, },
VolumeMode: &fs,
}, },
Status: v1.PersistentVolumeStatus{ Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable, Phase: v1.VolumeAvailable,
@ -569,6 +586,7 @@ func createTestVolumes() []*v1.PersistentVolume {
v1.ReadWriteOnce, v1.ReadWriteOnce,
v1.ReadOnlyMany, v1.ReadOnlyMany,
}, },
VolumeMode: &fs,
}, },
Status: v1.PersistentVolumeStatus{ Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable, Phase: v1.VolumeAvailable,
@ -591,6 +609,7 @@ func createTestVolumes() []*v1.PersistentVolume {
v1.ReadOnlyMany, v1.ReadOnlyMany,
v1.ReadWriteMany, v1.ReadWriteMany,
}, },
VolumeMode: &fs,
}, },
Status: v1.PersistentVolumeStatus{ Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable, Phase: v1.VolumeAvailable,
@ -614,6 +633,7 @@ func createTestVolumes() []*v1.PersistentVolume {
AccessModes: []v1.PersistentVolumeAccessMode{ AccessModes: []v1.PersistentVolumeAccessMode{
v1.ReadWriteOnce, v1.ReadWriteOnce,
}, },
VolumeMode: &fs,
}, },
Status: v1.PersistentVolumeStatus{ Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable, Phase: v1.VolumeAvailable,
@ -638,6 +658,7 @@ func createTestVolumes() []*v1.PersistentVolume {
v1.ReadWriteOnce, v1.ReadWriteOnce,
}, },
StorageClassName: classSilver, StorageClassName: classSilver,
VolumeMode: &fs,
}, },
Status: v1.PersistentVolumeStatus{ Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable, Phase: v1.VolumeAvailable,
@ -659,6 +680,7 @@ func createTestVolumes() []*v1.PersistentVolume {
v1.ReadWriteOnce, v1.ReadWriteOnce,
}, },
StorageClassName: classSilver, StorageClassName: classSilver,
VolumeMode: &fs,
}, },
Status: v1.PersistentVolumeStatus{ Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable, Phase: v1.VolumeAvailable,
@ -680,6 +702,7 @@ func createTestVolumes() []*v1.PersistentVolume {
v1.ReadWriteOnce, v1.ReadWriteOnce,
}, },
StorageClassName: classGold, StorageClassName: classGold,
VolumeMode: &fs,
}, },
Status: v1.PersistentVolumeStatus{ Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable, Phase: v1.VolumeAvailable,
@ -703,6 +726,7 @@ func createTestVolumes() []*v1.PersistentVolume {
v1.ReadWriteMany, v1.ReadWriteMany,
}, },
StorageClassName: classLarge, StorageClassName: classLarge,
VolumeMode: &fs,
}, },
Status: v1.PersistentVolumeStatus{ Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable, Phase: v1.VolumeAvailable,
@ -726,6 +750,7 @@ func createTestVolumes() []*v1.PersistentVolume {
v1.ReadWriteMany, v1.ReadWriteMany,
}, },
StorageClassName: classLarge, StorageClassName: classLarge,
VolumeMode: &fs,
}, },
Status: v1.PersistentVolumeStatus{ Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable, Phase: v1.VolumeAvailable,
@ -749,6 +774,7 @@ func createTestVolumes() []*v1.PersistentVolume {
}, },
StorageClassName: classWait, StorageClassName: classWait,
NodeAffinity: getVolumeNodeAffinity("key1", "value1"), NodeAffinity: getVolumeNodeAffinity("key1", "value1"),
VolumeMode: &fs,
}, },
Status: v1.PersistentVolumeStatus{ Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable, Phase: v1.VolumeAvailable,
@ -772,6 +798,7 @@ func createTestVolumes() []*v1.PersistentVolume {
}, },
StorageClassName: classWait, StorageClassName: classWait,
NodeAffinity: getVolumeNodeAffinity("key1", "value1"), NodeAffinity: getVolumeNodeAffinity("key1", "value1"),
VolumeMode: &fs,
}, },
Status: v1.PersistentVolumeStatus{ Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable, Phase: v1.VolumeAvailable,
@ -796,6 +823,7 @@ func createTestVolumes() []*v1.PersistentVolume {
StorageClassName: classWait, StorageClassName: classWait,
ClaimRef: &v1.ObjectReference{Name: "claim02", Namespace: "myns"}, ClaimRef: &v1.ObjectReference{Name: "claim02", Namespace: "myns"},
NodeAffinity: getVolumeNodeAffinity("key1", "value1"), NodeAffinity: getVolumeNodeAffinity("key1", "value1"),
VolumeMode: &fs,
}, },
Status: v1.PersistentVolumeStatus{ Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable, Phase: v1.VolumeAvailable,
@ -819,6 +847,7 @@ func createTestVolumes() []*v1.PersistentVolume {
}, },
StorageClassName: classWait, StorageClassName: classWait,
NodeAffinity: getVolumeNodeAffinity("key1", "value3"), NodeAffinity: getVolumeNodeAffinity("key1", "value3"),
VolumeMode: &fs,
}, },
Status: v1.PersistentVolumeStatus{ Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable, Phase: v1.VolumeAvailable,
@ -842,6 +871,7 @@ func createTestVolumes() []*v1.PersistentVolume {
}, },
StorageClassName: classWait, StorageClassName: classWait,
NodeAffinity: getVolumeNodeAffinity("key1", "value4"), NodeAffinity: getVolumeNodeAffinity("key1", "value4"),
VolumeMode: &fs,
}, },
Status: v1.PersistentVolumeStatus{ Status: v1.PersistentVolumeStatus{
Phase: v1.VolumePending, Phase: v1.VolumePending,
@ -865,6 +895,7 @@ func createTestVolumes() []*v1.PersistentVolume {
}, },
StorageClassName: classWait, StorageClassName: classWait,
NodeAffinity: getVolumeNodeAffinity("key1", "value4"), NodeAffinity: getVolumeNodeAffinity("key1", "value4"),
VolumeMode: &fs,
}, },
Status: v1.PersistentVolumeStatus{ Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeFailed, Phase: v1.VolumeFailed,
@ -888,6 +919,7 @@ func createTestVolumes() []*v1.PersistentVolume {
}, },
StorageClassName: classWait, StorageClassName: classWait,
NodeAffinity: getVolumeNodeAffinity("key1", "value4"), NodeAffinity: getVolumeNodeAffinity("key1", "value4"),
VolumeMode: &fs,
}, },
Status: v1.PersistentVolumeStatus{ Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeReleased, Phase: v1.VolumeReleased,
@ -911,12 +943,14 @@ func createTestVolumes() []*v1.PersistentVolume {
}, },
StorageClassName: classWait, StorageClassName: classWait,
NodeAffinity: getVolumeNodeAffinity("key1", "value4"), NodeAffinity: getVolumeNodeAffinity("key1", "value4"),
VolumeMode: &fs,
}, },
}, },
} }
} }
func testVolume(name, size string) *v1.PersistentVolume { func testVolume(name, size string) *v1.PersistentVolume {
fs := v1.PersistentVolumeFilesystem
return &v1.PersistentVolume{ return &v1.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: name, Name: name,
@ -926,6 +960,7 @@ func testVolume(name, size string) *v1.PersistentVolume {
Capacity: v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse(size)}, Capacity: v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse(size)},
PersistentVolumeSource: v1.PersistentVolumeSource{HostPath: &v1.HostPathVolumeSource{}}, PersistentVolumeSource: v1.PersistentVolumeSource{HostPath: &v1.HostPathVolumeSource{}},
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
VolumeMode: &fs,
}, },
Status: v1.PersistentVolumeStatus{ Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable, Phase: v1.VolumeAvailable,
@ -1009,28 +1044,7 @@ func createTestVolOrderedIndex(pv *v1.PersistentVolume) persistentVolumeOrderedI
return volFile return volFile
} }
func toggleFeature(toggleFlag bool, featureName string, t *testing.T) { func TestVolumeModeCheck(t *testing.T) {
var valueStr string
if toggleFlag {
// Enable feature
valueStr = featureName + "=true"
err := utilfeature.DefaultFeatureGate.Set(valueStr)
if err != nil {
t.Errorf("Failed to enable feature gate for %s: %v", featureName, err)
return
}
} else {
// Disable feature
valueStr = featureName + "=false"
err := utilfeature.DefaultFeatureGate.Set(valueStr)
if err != nil {
t.Errorf("Failed to disable feature gate for %s: %v", featureName, err)
return
}
}
}
func TestAlphaVolumeModeCheck(t *testing.T) {
blockMode := v1.PersistentVolumeBlock blockMode := v1.PersistentVolumeBlock
filesystemMode := v1.PersistentVolumeFilesystem filesystemMode := v1.PersistentVolumeFilesystem
@ -1038,55 +1052,55 @@ func TestAlphaVolumeModeCheck(t *testing.T) {
// If feature gate is enabled, VolumeMode will always be defaulted // If feature gate is enabled, VolumeMode will always be defaulted
// If feature gate is disabled, VolumeMode is dropped by API and ignored // If feature gate is disabled, VolumeMode is dropped by API and ignored
scenarios := map[string]struct { scenarios := map[string]struct {
isExpectedMisMatch bool isExpectedMismatch bool
vol *v1.PersistentVolume vol *v1.PersistentVolume
pvc *v1.PersistentVolumeClaim pvc *v1.PersistentVolumeClaim
enableBlock bool enableBlock bool
}{ }{
"feature enabled - pvc block and pv filesystem": { "feature enabled - pvc block and pv filesystem": {
isExpectedMisMatch: true, isExpectedMismatch: true,
vol: createVolumeModeFilesystemTestVolume(), vol: createVolumeModeFilesystemTestVolume(),
pvc: makeVolumeModePVC("8G", &blockMode, nil), pvc: makeVolumeModePVC("8G", &blockMode, nil),
enableBlock: true, enableBlock: true,
}, },
"feature enabled - pvc filesystem and pv block": { "feature enabled - pvc filesystem and pv block": {
isExpectedMisMatch: true, isExpectedMismatch: true,
vol: createVolumeModeBlockTestVolume(), vol: createVolumeModeBlockTestVolume(),
pvc: makeVolumeModePVC("8G", &filesystemMode, nil), pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
enableBlock: true, enableBlock: true,
}, },
"feature enabled - pvc block and pv block": { "feature enabled - pvc block and pv block": {
isExpectedMisMatch: false, isExpectedMismatch: false,
vol: createVolumeModeBlockTestVolume(), vol: createVolumeModeBlockTestVolume(),
pvc: makeVolumeModePVC("8G", &blockMode, nil), pvc: makeVolumeModePVC("8G", &blockMode, nil),
enableBlock: true, enableBlock: true,
}, },
"feature enabled - pvc filesystem and pv filesystem": { "feature enabled - pvc filesystem and pv filesystem": {
isExpectedMisMatch: false, isExpectedMismatch: false,
vol: createVolumeModeFilesystemTestVolume(), vol: createVolumeModeFilesystemTestVolume(),
pvc: makeVolumeModePVC("8G", &filesystemMode, nil), pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
enableBlock: true, enableBlock: true,
}, },
"feature disabled - pvc block and pv filesystem": { "feature disabled - pvc block and pv filesystem": {
isExpectedMisMatch: false, isExpectedMismatch: false,
vol: createVolumeModeFilesystemTestVolume(), vol: createVolumeModeFilesystemTestVolume(),
pvc: makeVolumeModePVC("8G", &blockMode, nil), pvc: makeVolumeModePVC("8G", &blockMode, nil),
enableBlock: false, enableBlock: false,
}, },
"feature disabled - pvc filesystem and pv block": { "feature disabled - pvc filesystem and pv block": {
isExpectedMisMatch: false, isExpectedMismatch: false,
vol: createVolumeModeBlockTestVolume(), vol: createVolumeModeBlockTestVolume(),
pvc: makeVolumeModePVC("8G", &filesystemMode, nil), pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
enableBlock: false, enableBlock: false,
}, },
"feature disabled - pvc block and pv block": { "feature disabled - pvc block and pv block": {
isExpectedMisMatch: false, isExpectedMismatch: false,
vol: createVolumeModeBlockTestVolume(), vol: createVolumeModeBlockTestVolume(),
pvc: makeVolumeModePVC("8G", &blockMode, nil), pvc: makeVolumeModePVC("8G", &blockMode, nil),
enableBlock: false, enableBlock: false,
}, },
"feature disabled - pvc filesystem and pv filesystem": { "feature disabled - pvc filesystem and pv filesystem": {
isExpectedMisMatch: false, isExpectedMismatch: false,
vol: createVolumeModeFilesystemTestVolume(), vol: createVolumeModeFilesystemTestVolume(),
pvc: makeVolumeModePVC("8G", &filesystemMode, nil), pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
enableBlock: false, enableBlock: false,
@ -1094,25 +1108,23 @@ func TestAlphaVolumeModeCheck(t *testing.T) {
} }
for name, scenario := range scenarios { for name, scenario := range scenarios {
toggleFeature(scenario.enableBlock, "BlockVolume", t) recover := utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, scenario.enableBlock)
expectedMisMatch, err := checkVolumeModeMisMatches(&scenario.pvc.Spec, &scenario.vol.Spec) expectedMismatch, err := checkVolumeModeMismatches(&scenario.pvc.Spec, &scenario.vol.Spec)
if err != nil { if err != nil {
t.Errorf("Unexpected failure for checkVolumeModeMisMatches: %v", err) t.Errorf("Unexpected failure for checkVolumeModeMismatches: %v", err)
} }
// expected to match but either got an error or no returned pvmatch // expected to match but either got an error or no returned pvmatch
if expectedMisMatch && !scenario.isExpectedMisMatch { if expectedMismatch && !scenario.isExpectedMismatch {
t.Errorf("Unexpected failure for scenario, expected not to mismatch on modes but did: %s", name) t.Errorf("Unexpected failure for scenario, expected not to mismatch on modes but did: %s", name)
} }
if !expectedMisMatch && scenario.isExpectedMisMatch { if !expectedMismatch && scenario.isExpectedMismatch {
t.Errorf("Unexpected failure for scenario, did not mismatch on mode when expected to mismatch: %s", name) t.Errorf("Unexpected failure for scenario, did not mismatch on mode when expected to mismatch: %s", name)
} }
recover()
} }
// make sure feature gate is turned off
toggleFeature(false, "BlockVolume", t)
} }
func TestAlphaFilteringVolumeModes(t *testing.T) { func TestFilteringVolumeModes(t *testing.T) {
blockMode := v1.PersistentVolumeBlock blockMode := v1.PersistentVolumeBlock
filesystemMode := v1.PersistentVolumeFilesystem filesystemMode := v1.PersistentVolumeFilesystem
@ -1187,7 +1199,7 @@ func TestAlphaFilteringVolumeModes(t *testing.T) {
} }
for name, scenario := range scenarios { for name, scenario := range scenarios {
toggleFeature(scenario.enableBlock, "BlockVolume", t) recover := utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, scenario.enableBlock)
pvmatch, err := scenario.vol.findBestMatchForClaim(scenario.pvc, false) pvmatch, err := scenario.vol.findBestMatchForClaim(scenario.pvc, false)
// expected to match but either got an error or no returned pvmatch // expected to match but either got an error or no returned pvmatch
if pvmatch == nil && scenario.isExpectedMatch { if pvmatch == nil && scenario.isExpectedMatch {
@ -1203,13 +1215,12 @@ func TestAlphaFilteringVolumeModes(t *testing.T) {
if err != nil && !scenario.isExpectedMatch { if err != nil && !scenario.isExpectedMatch {
t.Errorf("Unexpected failure for scenario: %s - %+v", name, err) t.Errorf("Unexpected failure for scenario: %s - %+v", name, err)
} }
recover()
} }
// make sure feature gate is turned off
toggleFeature(false, "BlockVolume", t)
} }
func TestStorageObjectInUseProtectionFiltering(t *testing.T) { func TestStorageObjectInUseProtectionFiltering(t *testing.T) {
fs := v1.PersistentVolumeFilesystem
pv := &v1.PersistentVolume{ pv := &v1.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "pv1", Name: "pv1",
@ -1219,6 +1230,7 @@ func TestStorageObjectInUseProtectionFiltering(t *testing.T) {
Capacity: v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse("1G")}, Capacity: v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse("1G")},
PersistentVolumeSource: v1.PersistentVolumeSource{HostPath: &v1.HostPathVolumeSource{}}, PersistentVolumeSource: v1.PersistentVolumeSource{HostPath: &v1.HostPathVolumeSource{}},
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
VolumeMode: &fs,
}, },
Status: v1.PersistentVolumeStatus{ Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable, Phase: v1.VolumeAvailable,
@ -1237,6 +1249,7 @@ func TestStorageObjectInUseProtectionFiltering(t *testing.T) {
Spec: v1.PersistentVolumeClaimSpec{ Spec: v1.PersistentVolumeClaimSpec{
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
Resources: v1.ResourceRequirements{Requests: v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse("1G")}}, Resources: v1.ResourceRequirements{Requests: v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse("1G")}},
VolumeMode: &fs,
}, },
} }
@ -1343,6 +1356,7 @@ func TestStorageObjectInUseProtectionFiltering(t *testing.T) {
} }
func TestFindingPreboundVolumes(t *testing.T) { func TestFindingPreboundVolumes(t *testing.T) {
fs := v1.PersistentVolumeFilesystem
claim := &v1.PersistentVolumeClaim{ claim := &v1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "claim01", Name: "claim01",
@ -1352,6 +1366,7 @@ func TestFindingPreboundVolumes(t *testing.T) {
Spec: v1.PersistentVolumeClaimSpec{ Spec: v1.PersistentVolumeClaimSpec{
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}, AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
Resources: v1.ResourceRequirements{Requests: v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse("1Gi")}}, Resources: v1.ResourceRequirements{Requests: v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse("1Gi")}},
VolumeMode: &fs,
}, },
} }
claimRef, err := ref.GetReference(scheme.Scheme, claim) claimRef, err := ref.GetReference(scheme.Scheme, claim)

View File

@ -270,11 +270,11 @@ func checkVolumeSatisfyClaim(volume *v1.PersistentVolume, claim *v1.PersistentVo
return fmt.Errorf("storageClassName does not match") return fmt.Errorf("storageClassName does not match")
} }
isMisMatch, err := checkVolumeModeMisMatches(&claim.Spec, &volume.Spec) isMismatch, err := checkVolumeModeMismatches(&claim.Spec, &volume.Spec)
if err != nil { if err != nil {
return fmt.Errorf("error checking volumeMode: %v", err) return fmt.Errorf("error checking volumeMode: %v", err)
} }
if isMisMatch { if isMismatch {
return fmt.Errorf("incompatible volumeMode") return fmt.Errorf("incompatible volumeMode")
} }
@ -613,7 +613,7 @@ func (ctrl *PersistentVolumeController) syncVolume(volume *v1.PersistentVolume)
} }
return nil return nil
} else if claim.Spec.VolumeName == "" { } else if claim.Spec.VolumeName == "" {
if isMisMatch, err := checkVolumeModeMisMatches(&claim.Spec, &volume.Spec); err != nil || isMisMatch { if isMismatch, err := checkVolumeModeMismatches(&claim.Spec, &volume.Spec); err != nil || isMismatch {
// Binding for the volume won't be called in syncUnboundClaim, // Binding for the volume won't be called in syncUnboundClaim,
// because findBestMatchForClaim won't return the volume due to volumeMode mismatch. // because findBestMatchForClaim won't return the volume due to volumeMode mismatch.
volumeMsg := fmt.Sprintf("Cannot bind PersistentVolume to requested PersistentVolumeClaim %q due to incompatible volumeMode.", claim.Name) volumeMsg := fmt.Sprintf("Cannot bind PersistentVolume to requested PersistentVolumeClaim %q due to incompatible volumeMode.", claim.Name)

View File

@ -426,6 +426,7 @@ const (
) )
func makeTestPVC(name, size, node string, pvcBoundState int, pvName, resourceVersion string, className *string) *v1.PersistentVolumeClaim { func makeTestPVC(name, size, node string, pvcBoundState int, pvName, resourceVersion string, className *string) *v1.PersistentVolumeClaim {
fs := v1.PersistentVolumeFilesystem
pvc := &v1.PersistentVolumeClaim{ pvc := &v1.PersistentVolumeClaim{
TypeMeta: metav1.TypeMeta{ TypeMeta: metav1.TypeMeta{
Kind: "PersistentVolumeClaim", Kind: "PersistentVolumeClaim",
@ -445,6 +446,7 @@ func makeTestPVC(name, size, node string, pvcBoundState int, pvName, resourceVer
}, },
}, },
StorageClassName: className, StorageClassName: className,
VolumeMode: &fs,
}, },
} }
@ -462,6 +464,7 @@ func makeTestPVC(name, size, node string, pvcBoundState int, pvName, resourceVer
} }
func makeBadPVC() *v1.PersistentVolumeClaim { func makeBadPVC() *v1.PersistentVolumeClaim {
fs := v1.PersistentVolumeFilesystem
return &v1.PersistentVolumeClaim{ return &v1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "bad-pvc", Name: "bad-pvc",
@ -477,11 +480,13 @@ func makeBadPVC() *v1.PersistentVolumeClaim {
}, },
}, },
StorageClassName: &waitClass, StorageClassName: &waitClass,
VolumeMode: &fs,
}, },
} }
} }
func makeTestPV(name, node, capacity, version string, boundToPVC *v1.PersistentVolumeClaim, className string) *v1.PersistentVolume { func makeTestPV(name, node, capacity, version string, boundToPVC *v1.PersistentVolumeClaim, className string) *v1.PersistentVolume {
fs := v1.PersistentVolumeFilesystem
pv := &v1.PersistentVolume{ pv := &v1.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: name, Name: name,
@ -492,6 +497,7 @@ func makeTestPV(name, node, capacity, version string, boundToPVC *v1.PersistentV
v1.ResourceName(v1.ResourceStorage): resource.MustParse(capacity), v1.ResourceName(v1.ResourceStorage): resource.MustParse(capacity),
}, },
StorageClassName: className, StorageClassName: className,
VolumeMode: &fs,
}, },
Status: v1.PersistentVolumeStatus{ Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable, Phase: v1.VolumeAvailable,

View File

@ -46,12 +46,14 @@ import (
func TestFindAndAddNewPods_FindAndRemoveDeletedPods(t *testing.T) { func TestFindAndAddNewPods_FindAndRemoveDeletedPods(t *testing.T) {
// create dswp // create dswp
mode := v1.PersistentVolumeFilesystem
pv := &v1.PersistentVolume{ pv := &v1.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "dswp-test-volume-name", Name: "dswp-test-volume-name",
}, },
Spec: v1.PersistentVolumeSpec{ Spec: v1.PersistentVolumeSpec{
ClaimRef: &v1.ObjectReference{Namespace: "ns", Name: "file-bound"}, ClaimRef: &v1.ObjectReference{Namespace: "ns", Name: "file-bound"},
VolumeMode: &mode,
}, },
} }
pvc := &v1.PersistentVolumeClaim{ pvc := &v1.PersistentVolumeClaim{
@ -453,6 +455,7 @@ func TestCreateVolumeSpec_Invalid_Block_VolumeMounts(t *testing.T) {
} }
func TestCheckVolumeFSResize(t *testing.T) { func TestCheckVolumeFSResize(t *testing.T) {
mode := v1.PersistentVolumeFilesystem
pv := &v1.PersistentVolume{ pv := &v1.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "dswp-test-volume-name", Name: "dswp-test-volume-name",
@ -461,6 +464,7 @@ func TestCheckVolumeFSResize(t *testing.T) {
PersistentVolumeSource: v1.PersistentVolumeSource{RBD: &v1.RBDPersistentVolumeSource{}}, PersistentVolumeSource: v1.PersistentVolumeSource{RBD: &v1.RBDPersistentVolumeSource{}},
Capacity: volumeCapacity(1), Capacity: volumeCapacity(1),
ClaimRef: &v1.ObjectReference{Namespace: "ns", Name: "file-bound"}, ClaimRef: &v1.ObjectReference{Namespace: "ns", Name: "file-bound"},
VolumeMode: &mode,
}, },
} }
pvc := &v1.PersistentVolumeClaim{ pvc := &v1.PersistentVolumeClaim{

View File

@ -949,6 +949,7 @@ func Test_GenerateUnmapDeviceFunc_Plugin_Not_Found(t *testing.T) {
func Test_Run_Positive_VolumeFSResizeControllerAttachEnabled(t *testing.T) { func Test_Run_Positive_VolumeFSResizeControllerAttachEnabled(t *testing.T) {
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ExpandInUsePersistentVolumes, true)() defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ExpandInUsePersistentVolumes, true)()
fs := v1.PersistentVolumeFilesystem
pv := &v1.PersistentVolume{ pv := &v1.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "pv", Name: "pv",
@ -956,6 +957,7 @@ func Test_Run_Positive_VolumeFSResizeControllerAttachEnabled(t *testing.T) {
}, },
Spec: v1.PersistentVolumeSpec{ Spec: v1.PersistentVolumeSpec{
ClaimRef: &v1.ObjectReference{Name: "pvc"}, ClaimRef: &v1.ObjectReference{Name: "pvc"},
VolumeMode: &fs,
}, },
} }
pvc := &v1.PersistentVolumeClaim{ pvc := &v1.PersistentVolumeClaim{
@ -965,6 +967,7 @@ func Test_Run_Positive_VolumeFSResizeControllerAttachEnabled(t *testing.T) {
}, },
Spec: v1.PersistentVolumeClaimSpec{ Spec: v1.PersistentVolumeClaimSpec{
VolumeName: "pv", VolumeName: "pv",
VolumeMode: &fs,
}, },
} }
pod := &v1.Pod{ pod := &v1.Pod{

View File

@ -167,6 +167,7 @@ func TestGetExtraSupplementalGroupsForPod(t *testing.T) {
} }
for _, tc := range cases { for _, tc := range cases {
fs := v1.PersistentVolumeFilesystem
pv := &v1.PersistentVolume{ pv := &v1.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "pvA", Name: "pvA",
@ -183,6 +184,7 @@ func TestGetExtraSupplementalGroupsForPod(t *testing.T) {
ClaimRef: &v1.ObjectReference{ ClaimRef: &v1.ObjectReference{
Name: claim.ObjectMeta.Name, Name: claim.ObjectMeta.Name,
}, },
VolumeMode: &fs,
}, },
} }
kubeClient := fake.NewSimpleClientset(node, pod, pv, claim) kubeClient := fake.NewSimpleClientset(node, pod, pv, claim)
@ -273,6 +275,7 @@ func createObjects() (*v1.Node, *v1.Pod, *v1.PersistentVolume, *v1.PersistentVol
}, },
}, },
} }
fs := v1.PersistentVolumeFilesystem
pv := &v1.PersistentVolume{ pv := &v1.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "pvA", Name: "pvA",
@ -286,6 +289,7 @@ func createObjects() (*v1.Node, *v1.Pod, *v1.PersistentVolume, *v1.PersistentVol
ClaimRef: &v1.ObjectReference{ ClaimRef: &v1.ObjectReference{
Name: "claimA", Name: "claimA",
}, },
VolumeMode: &fs,
}, },
} }
claim := &v1.PersistentVolumeClaim{ claim := &v1.PersistentVolumeClaim{

View File

@ -254,6 +254,7 @@ func TestPluginVolume(t *testing.T) {
func TestPluginPersistentVolume(t *testing.T) { func TestPluginPersistentVolume(t *testing.T) {
lun := int32(0) lun := int32(0)
fs := v1.PersistentVolumeFilesystem
vol := &v1.PersistentVolume{ vol := &v1.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "vol1", Name: "vol1",
@ -266,6 +267,7 @@ func TestPluginPersistentVolume(t *testing.T) {
Lun: &lun, Lun: &lun,
}, },
}, },
VolumeMode: &fs,
}, },
} }
doTestPlugin(t, volume.NewSpecFromPersistentVolume(vol, false)) doTestPlugin(t, volume.NewSpecFromPersistentVolume(vol, false))
@ -285,6 +287,7 @@ func TestPluginVolumeWWIDs(t *testing.T) {
} }
func TestPluginPersistentVolumeWWIDs(t *testing.T) { func TestPluginPersistentVolumeWWIDs(t *testing.T) {
fs := v1.PersistentVolumeFilesystem
vol := &v1.PersistentVolume{ vol := &v1.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "vol1", Name: "vol1",
@ -296,6 +299,7 @@ func TestPluginPersistentVolumeWWIDs(t *testing.T) {
FSType: "ext4", FSType: "ext4",
}, },
}, },
VolumeMode: &fs,
}, },
} }
doTestPlugin(t, volume.NewSpecFromPersistentVolume(vol, false)) doTestPlugin(t, volume.NewSpecFromPersistentVolume(vol, false))
@ -314,6 +318,7 @@ func TestPluginVolumeNoDiskInfo(t *testing.T) {
} }
func TestPluginPersistentVolumeNoDiskInfo(t *testing.T) { func TestPluginPersistentVolumeNoDiskInfo(t *testing.T) {
fs := v1.PersistentVolumeFilesystem
vol := &v1.PersistentVolume{ vol := &v1.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "vol1", Name: "vol1",
@ -324,6 +329,7 @@ func TestPluginPersistentVolumeNoDiskInfo(t *testing.T) {
FSType: "ext4", FSType: "ext4",
}, },
}, },
VolumeMode: &fs,
}, },
} }
doTestPluginNilMounter(t, volume.NewSpecFromPersistentVolume(vol, false)) doTestPluginNilMounter(t, volume.NewSpecFromPersistentVolume(vol, false))
@ -337,6 +343,7 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) {
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
lun := int32(0) lun := int32(0)
fs := v1.PersistentVolumeFilesystem
pv := &v1.PersistentVolume{ pv := &v1.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "pvA", Name: "pvA",
@ -352,6 +359,7 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) {
ClaimRef: &v1.ObjectReference{ ClaimRef: &v1.ObjectReference{
Name: "claimA", Name: "claimA",
}, },
VolumeMode: &fs,
}, },
} }
@ -362,6 +370,7 @@ func TestPersistentClaimReadOnlyFlag(t *testing.T) {
}, },
Spec: v1.PersistentVolumeClaimSpec{ Spec: v1.PersistentVolumeClaimSpec{
VolumeName: "pvA", VolumeName: "pvA",
VolumeMode: &fs,
}, },
Status: v1.PersistentVolumeClaimStatus{ Status: v1.PersistentVolumeClaimStatus{
Phase: v1.ClaimBound, Phase: v1.ClaimBound,