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()
reclamationPolicies := []core.PersistentVolumeReclaimPolicy{core.PersistentVolumeReclaimRecycle, core.PersistentVolumeReclaimRetain}
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) {
c.FuzzNoCustom(pvc) // fuzz self without calling this function again
types := []core.PersistentVolumeClaimPhase{core.ClaimBound, core.ClaimPending, core.ClaimLost}
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) {
if obj.CachingMode == nil {

View File

@ -27,8 +27,10 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/intstr"
utilfeature "k8s.io/apiserver/pkg/util/feature"
utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing"
"k8s.io/kubernetes/pkg/api/legacyscheme"
corev1 "k8s.io/kubernetes/pkg/apis/core/v1"
"k8s.io/kubernetes/pkg/features"
utilpointer "k8s.io/utils/pointer"
// enforce that all types are installed
@ -803,6 +805,7 @@ func TestSetDefaultSecret(t *testing.T) {
}
func TestSetDefaultPersistentVolume(t *testing.T) {
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, false)()
pv := &v1.PersistentVolume{}
obj2 := roundTrip(t, runtime.Object(pv))
pv2 := obj2.(*v1.PersistentVolume)
@ -834,15 +837,10 @@ func TestSetDefaultPersistentVolume(t *testing.T) {
} else if *outputMode3 != defaultMode {
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) {
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, false)()
pvc := &v1.PersistentVolumeClaim{}
obj2 := roundTrip(t, runtime.Object(pvc))
pvc2 := obj2.(*v1.PersistentVolumeClaim)
@ -871,11 +869,6 @@ func TestSetDefaultPersistentVolumeClaim(t *testing.T) {
} else if *outputMode3 != defaultMode {
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) {

View File

@ -66,9 +66,11 @@ func testVolume(name string, namespace string, spec core.PersistentVolumeSpec) *
func TestValidatePersistentVolumes(t *testing.T) {
validMode := core.PersistentVolumeFilesystem
invalidMode := core.PersistentVolumeMode("fakeVolumeMode")
scenarios := map[string]struct {
isExpectedFailure bool
volume *core.PersistentVolume
isExpectedFailure bool
volume *core.PersistentVolume
disableBlockVolume bool
}{
"good-volume": {
isExpectedFailure: false,
@ -147,6 +149,22 @@ func TestValidatePersistentVolumes(t *testing.T) {
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": {
isExpectedFailure: true,
volume: testVolume("foo", "", core.PersistentVolumeSpec{
@ -178,6 +196,22 @@ func TestValidatePersistentVolumes(t *testing.T) {
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": {
isExpectedFailure: true,
volume: testVolume("foo", "unexpected-namespace", core.PersistentVolumeSpec{
@ -336,10 +370,9 @@ func TestValidatePersistentVolumes(t *testing.T) {
StorageClassName: "-invalid-",
}),
},
// VolumeMode alpha feature disabled
// TODO: remove when no longer alpha
"alpha disabled valid volume mode": {
isExpectedFailure: true,
"feature disabled valid volume mode": {
disableBlockVolume: true,
isExpectedFailure: true,
volume: testVolume("foo", "", core.PersistentVolumeSpec{
Capacity: core.ResourceList{
core.ResourceName(core.ResourceStorage): resource.MustParse("10G"),
@ -400,6 +433,10 @@ func TestValidatePersistentVolumes(t *testing.T) {
}
for name, scenario := range scenarios {
var restore func()
if scenario.disableBlockVolume {
restore = utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, false)
}
errs := ValidatePersistentVolume(scenario.volume)
if len(errs) == 0 && scenario.isExpectedFailure {
t.Errorf("Unexpected success for scenario: %s", name)
@ -407,6 +444,9 @@ func TestValidatePersistentVolumes(t *testing.T) {
if len(errs) > 0 && !scenario.isExpectedFailure {
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) {
invalidClassName := "-invalid-"
validClassName := "valid"
invalidMode := core.PersistentVolumeMode("fakeVolumeMode")
validMode := core.PersistentVolumeFilesystem
scenarios := map[string]struct {
isExpectedFailure bool
claim *core.PersistentVolumeClaim
isExpectedFailure bool
claim *core.PersistentVolumeClaim
disableBlockVolume bool
}{
"good-claim": {
isExpectedFailure: false,
@ -817,6 +859,7 @@ func TestValidatePersistentVolumeClaim(t *testing.T) {
},
},
StorageClassName: &validClassName,
VolumeMode: &validMode,
}),
},
"invalid-claim-zero-capacity": {
@ -988,10 +1031,9 @@ func TestValidatePersistentVolumeClaim(t *testing.T) {
StorageClassName: &invalidClassName,
}),
},
// VolumeMode alpha feature disabled
// TODO: remove when no longer alpha
"disabled alpha valid volume mode": {
isExpectedFailure: true,
"feature disabled valid volume mode": {
disableBlockVolume: true,
isExpectedFailure: true,
claim: testVolumeClaim("foo", "ns", core.PersistentVolumeClaimSpec{
Selector: &metav1.LabelSelector{
MatchExpressions: []metav1.LabelSelectorRequirement{
@ -1014,9 +1056,28 @@ func TestValidatePersistentVolumeClaim(t *testing.T) {
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 {
var restore func()
if scenario.disableBlockVolume {
restore = utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, false)
}
errs := ValidatePersistentVolumeClaim(scenario.claim)
if len(errs) == 0 && scenario.isExpectedFailure {
t.Errorf("Unexpected success for scenario: %s", name)
@ -1024,6 +1085,9 @@ func TestValidatePersistentVolumeClaim(t *testing.T) {
if len(errs) > 0 && !scenario.isExpectedFailure {
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"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
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.
@ -35,8 +37,6 @@ func TestSync(t *testing.T) {
"foo": "true",
"bar": "false",
}
modeBlock := v1.PersistentVolumeBlock
modeFile := v1.PersistentVolumeFilesystem
tests := []controllerTest{
// [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),
noevents, noerrors, testSyncClaim,
},
}
// All of these should bind as feature set is not enabled for BlockVolume
// meaning volumeMode will be ignored and dropped
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
// meaning volumeMode will be ignored and dropped
tests := []controllerTest{
{
// syncVolume binds a requested block claim to a block volume
"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{
{
ObjectMeta: metav1.ObjectMeta{Name: classWait},
@ -647,7 +661,7 @@ func TestSync(t *testing.T) {
}, []*v1.Pod{})
}
func TestSyncAlphaBlockVolume(t *testing.T) {
func TestSyncBlockVolume(t *testing.T) {
modeBlock := v1.PersistentVolumeBlock
modeFile := v1.PersistentVolumeFilesystem
@ -827,12 +841,7 @@ func TestSyncAlphaBlockVolume(t *testing.T) {
},
}
err := utilfeature.DefaultFeatureGate.Set("BlockVolume=true")
if err != nil {
t.Errorf("Failed to enable feature gate for BlockVolume: %v", err)
return
}
defer utilfeature.DefaultFeatureGate.Set("BlockVolume=false")
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
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/wait"
"k8s.io/apimachinery/pkg/watch"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/informers"
clientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/fake"
@ -48,6 +49,7 @@ import (
"k8s.io/client-go/tools/record"
"k8s.io/kubernetes/pkg/api/testapi"
"k8s.io/kubernetes/pkg/controller"
"k8s.io/kubernetes/pkg/features"
vol "k8s.io/kubernetes/pkg/volume"
"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)
}
// 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.
r.volumes[volume.Name] = 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
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{
ObjectMeta: metav1.ObjectMeta{
Name: name,
@ -645,6 +654,7 @@ func newVolume(name, capacity, boundToClaimUID, boundToClaimName string, phase v
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce, v1.ReadOnlyMany},
PersistentVolumeReclaimPolicy: reclaimPolicy,
StorageClassName: class,
VolumeMode: &fs,
},
Status: v1.PersistentVolumeStatus{
Phase: phase,
@ -740,6 +750,7 @@ func newVolumeArray(name, capacity, boundToClaimUID, boundToClaimName string, ph
// newClaim returns a new claim with given attributes
func newClaim(name, claimUID, capacity, boundToVolume string, phase v1.PersistentVolumeClaimPhase, class *string, annotations ...string) *v1.PersistentVolumeClaim {
fs := v1.PersistentVolumeFilesystem
claim := v1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: name,
@ -756,6 +767,7 @@ func newClaim(name, claimUID, capacity, boundToVolume string, phase v1.Persisten
},
VolumeName: boundToVolume,
StorageClassName: class,
VolumeMode: &fs,
},
Status: v1.PersistentVolumeClaimStatus{
Phase: phase,
@ -1226,6 +1238,7 @@ func (plugin *mockVolumePlugin) Provision(selectedNode *v1.Node, allowedTopologi
Phase: v1.VolumeAvailable,
},
}
pv.Spec.VolumeMode = plugin.provisionOptions.PVC.Spec.VolumeMode
}
plugin.provisionCallCounter++

View File

@ -158,13 +158,13 @@ func findMatchingVolume(
volumeQty := volume.Spec.Capacity[v1.ResourceStorage]
// check if volumeModes do not match (Alpha and feature gate protected)
isMisMatch, err := checkVolumeModeMisMatches(&claim.Spec, &volume.Spec)
// check if volumeModes do not match (feature gate protected)
isMismatch, err := checkVolumeModeMismatches(&claim.Spec, &volume.Spec)
if err != nil {
return nil, fmt.Errorf("error checking if volumeMode was a mismatch: %v", err)
}
// filter out mismatching volumeModes
if isMisMatch {
if isMismatch {
continue
}
@ -258,18 +258,16 @@ func findMatchingVolume(
return nil, nil
}
// checkVolumeModeMatches is a convenience method that checks volumeMode for PersistentVolume
// and PersistentVolumeClaims along with making sure that the Alpha feature gate BlockVolume is
// enabled.
// This is Alpha and could change in the future.
func checkVolumeModeMisMatches(pvcSpec *v1.PersistentVolumeClaimSpec, pvSpec *v1.PersistentVolumeSpec) (bool, error) {
// checkVolumeModeMismatches is a convenience method that checks volumeMode for PersistentVolume
// and PersistentVolumeClaims along with making sure that the feature gate BlockVolume is enabled.
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 retrun an error, this means that
// This also should return an error, this means that
// the defaulting has 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 {
fs := v1.PersistentVolumeFilesystem
pvc := v1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: "claim01",
@ -45,6 +46,7 @@ func makePVC(size string, modfn func(*v1.PersistentVolumeClaim)) *v1.PersistentV
v1.ResourceName(v1.ResourceStorage): resource.MustParse(size),
},
},
VolumeMode: &fs,
},
}
if modfn != nil {
@ -197,6 +199,7 @@ func TestMatchVolume(t *testing.T) {
}
func TestMatchingWithBoundVolumes(t *testing.T) {
fs := v1.PersistentVolumeFilesystem
volumeIndex := newPersistentVolumeOrderedIndex()
// two similar volumes, one is bound
pv1 := &v1.PersistentVolume{
@ -213,7 +216,8 @@ func TestMatchingWithBoundVolumes(t *testing.T) {
},
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce, v1.ReadOnlyMany},
// this one we're pretending is already bound
ClaimRef: &v1.ObjectReference{UID: "abc123"},
ClaimRef: &v1.ObjectReference{UID: "abc123"},
VolumeMode: &fs,
},
Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeBound,
@ -233,6 +237,7 @@ func TestMatchingWithBoundVolumes(t *testing.T) {
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{},
},
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce, v1.ReadOnlyMany},
VolumeMode: &fs,
},
Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable,
@ -254,6 +259,7 @@ func TestMatchingWithBoundVolumes(t *testing.T) {
v1.ResourceName(v1.ResourceStorage): resource.MustParse("1G"),
},
},
VolumeMode: &fs,
},
}
@ -328,6 +334,7 @@ func TestAllPossibleAccessModes(t *testing.T) {
}
func TestFindingVolumeWithDifferentAccessModes(t *testing.T) {
fs := v1.PersistentVolumeFilesystem
gce := &v1.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{UID: "001", Name: "gce"},
Spec: v1.PersistentVolumeSpec{
@ -337,6 +344,7 @@ func TestFindingVolumeWithDifferentAccessModes(t *testing.T) {
v1.ReadWriteOnce,
v1.ReadOnlyMany,
},
VolumeMode: &fs,
},
Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable,
@ -351,6 +359,7 @@ func TestFindingVolumeWithDifferentAccessModes(t *testing.T) {
AccessModes: []v1.PersistentVolumeAccessMode{
v1.ReadWriteOnce,
},
VolumeMode: &fs,
},
Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable,
@ -367,6 +376,7 @@ func TestFindingVolumeWithDifferentAccessModes(t *testing.T) {
v1.ReadOnlyMany,
v1.ReadWriteMany,
},
VolumeMode: &fs,
},
Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable,
@ -381,6 +391,7 @@ func TestFindingVolumeWithDifferentAccessModes(t *testing.T) {
Spec: v1.PersistentVolumeClaimSpec{
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
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 {
fs := v1.PersistentVolumeFilesystem
// these volumes are deliberately out-of-order to test indexing and sorting
return []*v1.PersistentVolume{
{
@ -458,6 +470,7 @@ func createTestVolumes() []*v1.PersistentVolume {
v1.ReadWriteOnce,
v1.ReadOnlyMany,
},
VolumeMode: &fs,
},
Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable,
@ -480,7 +493,8 @@ func createTestVolumes() []*v1.PersistentVolume {
v1.ReadOnlyMany,
},
// this one we're pretending is already bound
ClaimRef: &v1.ObjectReference{UID: "def456"},
ClaimRef: &v1.ObjectReference{UID: "def456"},
VolumeMode: &fs,
},
Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeBound,
@ -503,6 +517,7 @@ func createTestVolumes() []*v1.PersistentVolume {
v1.ReadOnlyMany,
v1.ReadWriteMany,
},
VolumeMode: &fs,
},
Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable,
@ -525,7 +540,8 @@ func createTestVolumes() []*v1.PersistentVolume {
v1.ReadOnlyMany,
},
// this one we're pretending is already bound
ClaimRef: &v1.ObjectReference{UID: "abc123"},
ClaimRef: &v1.ObjectReference{UID: "abc123"},
VolumeMode: &fs,
},
Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeBound,
@ -548,6 +564,7 @@ func createTestVolumes() []*v1.PersistentVolume {
v1.ReadOnlyMany,
v1.ReadWriteMany,
},
VolumeMode: &fs,
},
Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable,
@ -569,6 +586,7 @@ func createTestVolumes() []*v1.PersistentVolume {
v1.ReadWriteOnce,
v1.ReadOnlyMany,
},
VolumeMode: &fs,
},
Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable,
@ -591,6 +609,7 @@ func createTestVolumes() []*v1.PersistentVolume {
v1.ReadOnlyMany,
v1.ReadWriteMany,
},
VolumeMode: &fs,
},
Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable,
@ -614,6 +633,7 @@ func createTestVolumes() []*v1.PersistentVolume {
AccessModes: []v1.PersistentVolumeAccessMode{
v1.ReadWriteOnce,
},
VolumeMode: &fs,
},
Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable,
@ -638,6 +658,7 @@ func createTestVolumes() []*v1.PersistentVolume {
v1.ReadWriteOnce,
},
StorageClassName: classSilver,
VolumeMode: &fs,
},
Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable,
@ -659,6 +680,7 @@ func createTestVolumes() []*v1.PersistentVolume {
v1.ReadWriteOnce,
},
StorageClassName: classSilver,
VolumeMode: &fs,
},
Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable,
@ -680,6 +702,7 @@ func createTestVolumes() []*v1.PersistentVolume {
v1.ReadWriteOnce,
},
StorageClassName: classGold,
VolumeMode: &fs,
},
Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable,
@ -703,6 +726,7 @@ func createTestVolumes() []*v1.PersistentVolume {
v1.ReadWriteMany,
},
StorageClassName: classLarge,
VolumeMode: &fs,
},
Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable,
@ -726,6 +750,7 @@ func createTestVolumes() []*v1.PersistentVolume {
v1.ReadWriteMany,
},
StorageClassName: classLarge,
VolumeMode: &fs,
},
Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable,
@ -749,6 +774,7 @@ func createTestVolumes() []*v1.PersistentVolume {
},
StorageClassName: classWait,
NodeAffinity: getVolumeNodeAffinity("key1", "value1"),
VolumeMode: &fs,
},
Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable,
@ -772,6 +798,7 @@ func createTestVolumes() []*v1.PersistentVolume {
},
StorageClassName: classWait,
NodeAffinity: getVolumeNodeAffinity("key1", "value1"),
VolumeMode: &fs,
},
Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable,
@ -796,6 +823,7 @@ func createTestVolumes() []*v1.PersistentVolume {
StorageClassName: classWait,
ClaimRef: &v1.ObjectReference{Name: "claim02", Namespace: "myns"},
NodeAffinity: getVolumeNodeAffinity("key1", "value1"),
VolumeMode: &fs,
},
Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable,
@ -819,6 +847,7 @@ func createTestVolumes() []*v1.PersistentVolume {
},
StorageClassName: classWait,
NodeAffinity: getVolumeNodeAffinity("key1", "value3"),
VolumeMode: &fs,
},
Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable,
@ -842,6 +871,7 @@ func createTestVolumes() []*v1.PersistentVolume {
},
StorageClassName: classWait,
NodeAffinity: getVolumeNodeAffinity("key1", "value4"),
VolumeMode: &fs,
},
Status: v1.PersistentVolumeStatus{
Phase: v1.VolumePending,
@ -865,6 +895,7 @@ func createTestVolumes() []*v1.PersistentVolume {
},
StorageClassName: classWait,
NodeAffinity: getVolumeNodeAffinity("key1", "value4"),
VolumeMode: &fs,
},
Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeFailed,
@ -888,6 +919,7 @@ func createTestVolumes() []*v1.PersistentVolume {
},
StorageClassName: classWait,
NodeAffinity: getVolumeNodeAffinity("key1", "value4"),
VolumeMode: &fs,
},
Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeReleased,
@ -911,12 +943,14 @@ func createTestVolumes() []*v1.PersistentVolume {
},
StorageClassName: classWait,
NodeAffinity: getVolumeNodeAffinity("key1", "value4"),
VolumeMode: &fs,
},
},
}
}
func testVolume(name, size string) *v1.PersistentVolume {
fs := v1.PersistentVolumeFilesystem
return &v1.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{
Name: name,
@ -926,6 +960,7 @@ func testVolume(name, size string) *v1.PersistentVolume {
Capacity: v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse(size)},
PersistentVolumeSource: v1.PersistentVolumeSource{HostPath: &v1.HostPathVolumeSource{}},
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
VolumeMode: &fs,
},
Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable,
@ -1009,28 +1044,7 @@ func createTestVolOrderedIndex(pv *v1.PersistentVolume) persistentVolumeOrderedI
return volFile
}
func toggleFeature(toggleFlag bool, featureName string, 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) {
func TestVolumeModeCheck(t *testing.T) {
blockMode := v1.PersistentVolumeBlock
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 disabled, VolumeMode is dropped by API and ignored
scenarios := map[string]struct {
isExpectedMisMatch bool
isExpectedMismatch bool
vol *v1.PersistentVolume
pvc *v1.PersistentVolumeClaim
enableBlock bool
}{
"feature enabled - pvc block and pv filesystem": {
isExpectedMisMatch: true,
isExpectedMismatch: true,
vol: createVolumeModeFilesystemTestVolume(),
pvc: makeVolumeModePVC("8G", &blockMode, nil),
enableBlock: true,
},
"feature enabled - pvc filesystem and pv block": {
isExpectedMisMatch: true,
isExpectedMismatch: true,
vol: createVolumeModeBlockTestVolume(),
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
enableBlock: true,
},
"feature enabled - pvc block and pv block": {
isExpectedMisMatch: false,
isExpectedMismatch: false,
vol: createVolumeModeBlockTestVolume(),
pvc: makeVolumeModePVC("8G", &blockMode, nil),
enableBlock: true,
},
"feature enabled - pvc filesystem and pv filesystem": {
isExpectedMisMatch: false,
isExpectedMismatch: false,
vol: createVolumeModeFilesystemTestVolume(),
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
enableBlock: true,
},
"feature disabled - pvc block and pv filesystem": {
isExpectedMisMatch: false,
isExpectedMismatch: false,
vol: createVolumeModeFilesystemTestVolume(),
pvc: makeVolumeModePVC("8G", &blockMode, nil),
enableBlock: false,
},
"feature disabled - pvc filesystem and pv block": {
isExpectedMisMatch: false,
isExpectedMismatch: false,
vol: createVolumeModeBlockTestVolume(),
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
enableBlock: false,
},
"feature disabled - pvc block and pv block": {
isExpectedMisMatch: false,
isExpectedMismatch: false,
vol: createVolumeModeBlockTestVolume(),
pvc: makeVolumeModePVC("8G", &blockMode, nil),
enableBlock: false,
},
"feature disabled - pvc filesystem and pv filesystem": {
isExpectedMisMatch: false,
isExpectedMismatch: false,
vol: createVolumeModeFilesystemTestVolume(),
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
enableBlock: false,
@ -1094,25 +1108,23 @@ func TestAlphaVolumeModeCheck(t *testing.T) {
}
for name, scenario := range scenarios {
toggleFeature(scenario.enableBlock, "BlockVolume", t)
expectedMisMatch, err := checkVolumeModeMisMatches(&scenario.pvc.Spec, &scenario.vol.Spec)
recover := utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, scenario.enableBlock)
expectedMismatch, err := checkVolumeModeMismatches(&scenario.pvc.Spec, &scenario.vol.Spec)
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
if expectedMisMatch && !scenario.isExpectedMisMatch {
if expectedMismatch && !scenario.isExpectedMismatch {
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)
}
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
filesystemMode := v1.PersistentVolumeFilesystem
@ -1187,7 +1199,7 @@ func TestAlphaFilteringVolumeModes(t *testing.T) {
}
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)
// expected to match but either got an error or no returned pvmatch
if pvmatch == nil && scenario.isExpectedMatch {
@ -1203,13 +1215,12 @@ func TestAlphaFilteringVolumeModes(t *testing.T) {
if err != nil && !scenario.isExpectedMatch {
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) {
fs := v1.PersistentVolumeFilesystem
pv := &v1.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{
Name: "pv1",
@ -1219,6 +1230,7 @@ func TestStorageObjectInUseProtectionFiltering(t *testing.T) {
Capacity: v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse("1G")},
PersistentVolumeSource: v1.PersistentVolumeSource{HostPath: &v1.HostPathVolumeSource{}},
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
VolumeMode: &fs,
},
Status: v1.PersistentVolumeStatus{
Phase: v1.VolumeAvailable,
@ -1237,6 +1249,7 @@ func TestStorageObjectInUseProtectionFiltering(t *testing.T) {
Spec: v1.PersistentVolumeClaimSpec{
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
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) {
fs := v1.PersistentVolumeFilesystem
claim := &v1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: "claim01",
@ -1352,6 +1366,7 @@ func TestFindingPreboundVolumes(t *testing.T) {
Spec: v1.PersistentVolumeClaimSpec{
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
Resources: v1.ResourceRequirements{Requests: v1.ResourceList{v1.ResourceName(v1.ResourceStorage): resource.MustParse("1Gi")}},
VolumeMode: &fs,
},
}
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")
}
isMisMatch, err := checkVolumeModeMisMatches(&claim.Spec, &volume.Spec)
isMismatch, err := checkVolumeModeMismatches(&claim.Spec, &volume.Spec)
if err != nil {
return fmt.Errorf("error checking volumeMode: %v", err)
}
if isMisMatch {
if isMismatch {
return fmt.Errorf("incompatible volumeMode")
}
@ -613,7 +613,7 @@ func (ctrl *PersistentVolumeController) syncVolume(volume *v1.PersistentVolume)
}
return nil
} 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,
// 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)

View File

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

View File

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

View File

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

View File

@ -167,6 +167,7 @@ func TestGetExtraSupplementalGroupsForPod(t *testing.T) {
}
for _, tc := range cases {
fs := v1.PersistentVolumeFilesystem
pv := &v1.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{
Name: "pvA",
@ -183,6 +184,7 @@ func TestGetExtraSupplementalGroupsForPod(t *testing.T) {
ClaimRef: &v1.ObjectReference{
Name: claim.ObjectMeta.Name,
},
VolumeMode: &fs,
},
}
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{
ObjectMeta: metav1.ObjectMeta{
Name: "pvA",
@ -286,6 +289,7 @@ func createObjects() (*v1.Node, *v1.Pod, *v1.PersistentVolume, *v1.PersistentVol
ClaimRef: &v1.ObjectReference{
Name: "claimA",
},
VolumeMode: &fs,
},
}
claim := &v1.PersistentVolumeClaim{

View File

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