Graduate ReadWriteOncePod to GA

This commit is contained in:
Chris Henzie 2023-10-11 10:56:00 -07:00
parent f7cb8a5e8a
commit 2dbd405583
16 changed files with 93 additions and 359 deletions

View File

@ -1653,33 +1653,20 @@ var allowedTemplateObjectMetaFields = map[string]bool{
// PersistentVolumeSpecValidationOptions contains the different settings for PeristentVolume validation
type PersistentVolumeSpecValidationOptions struct {
// Allow spec to contain the "ReadWiteOncePod" access mode
AllowReadWriteOncePod bool
}
// ValidatePersistentVolumeName checks that a name is appropriate for a
// PersistentVolumeName object.
var ValidatePersistentVolumeName = apimachineryvalidation.NameIsDNSSubdomain
var supportedAccessModes = sets.NewString(string(core.ReadWriteOnce), string(core.ReadOnlyMany), string(core.ReadWriteMany))
var supportedAccessModes = sets.NewString(string(core.ReadWriteOnce), string(core.ReadOnlyMany), string(core.ReadWriteMany), string(core.ReadWriteOncePod))
var supportedReclaimPolicy = sets.NewString(string(core.PersistentVolumeReclaimDelete), string(core.PersistentVolumeReclaimRecycle), string(core.PersistentVolumeReclaimRetain))
var supportedVolumeModes = sets.NewString(string(core.PersistentVolumeBlock), string(core.PersistentVolumeFilesystem))
func ValidationOptionsForPersistentVolume(pv, oldPv *core.PersistentVolume) PersistentVolumeSpecValidationOptions {
opts := PersistentVolumeSpecValidationOptions{
AllowReadWriteOncePod: utilfeature.DefaultFeatureGate.Enabled(features.ReadWriteOncePod),
}
if oldPv == nil {
// If there's no old PV, use the options based solely on feature enablement
return opts
}
if helper.ContainsAccessMode(oldPv.Spec.AccessModes, core.ReadWriteOncePod) {
// If the old object allowed "ReadWriteOncePod", continue to allow it in the new object
opts.AllowReadWriteOncePod = true
}
return opts
return PersistentVolumeSpecValidationOptions{}
}
func ValidatePersistentVolumeSpec(pvSpec *core.PersistentVolumeSpec, pvName string, validateInlinePersistentVolumeSpec bool, fldPath *field.Path, opts PersistentVolumeSpecValidationOptions) field.ErrorList {
@ -1701,15 +1688,10 @@ func ValidatePersistentVolumeSpec(pvSpec *core.PersistentVolumeSpec, pvName stri
allErrs = append(allErrs, field.Required(fldPath.Child("accessModes"), ""))
}
expandedSupportedAccessModes := sets.StringKeySet(supportedAccessModes)
if opts.AllowReadWriteOncePod {
expandedSupportedAccessModes.Insert(string(core.ReadWriteOncePod))
}
foundReadWriteOncePod, foundNonReadWriteOncePod := false, false
for _, mode := range pvSpec.AccessModes {
if !expandedSupportedAccessModes.Has(string(mode)) {
allErrs = append(allErrs, field.NotSupported(fldPath.Child("accessModes"), mode, expandedSupportedAccessModes.List()))
if !supportedAccessModes.Has(string(mode)) {
allErrs = append(allErrs, field.NotSupported(fldPath.Child("accessModes"), mode, supportedAccessModes.List()))
}
if mode == core.ReadWriteOncePod {
@ -2016,8 +1998,6 @@ func ValidatePersistentVolumeStatusUpdate(newPv, oldPv *core.PersistentVolume) f
}
type PersistentVolumeClaimSpecValidationOptions struct {
// Allow spec to contain the "ReadWiteOncePod" access mode
AllowReadWriteOncePod bool
// Allow users to recover from previously failing expansion operation
EnableRecoverFromExpansionFailure bool
// Allow to validate the label value of the label selector
@ -2028,7 +2008,6 @@ type PersistentVolumeClaimSpecValidationOptions struct {
func ValidationOptionsForPersistentVolumeClaim(pvc, oldPvc *core.PersistentVolumeClaim) PersistentVolumeClaimSpecValidationOptions {
opts := PersistentVolumeClaimSpecValidationOptions{
AllowReadWriteOncePod: utilfeature.DefaultFeatureGate.Enabled(features.ReadWriteOncePod),
EnableRecoverFromExpansionFailure: utilfeature.DefaultFeatureGate.Enabled(features.RecoverVolumeExpansionFailure),
AllowInvalidLabelValueInSelector: false,
}
@ -2048,11 +2027,6 @@ func ValidationOptionsForPersistentVolumeClaim(pvc, oldPvc *core.PersistentVolum
opts.AllowInvalidLabelValueInSelector = true
}
if helper.ContainsAccessMode(oldPvc.Spec.AccessModes, core.ReadWriteOncePod) {
// If the old object allowed "ReadWriteOncePod", continue to allow it in the new object
opts.AllowReadWriteOncePod = true
}
if helper.ClaimContainsAllocatedResources(oldPvc) ||
helper.ClaimContainsAllocatedResourceStatus(oldPvc) {
opts.EnableRecoverFromExpansionFailure = true
@ -2062,7 +2036,6 @@ func ValidationOptionsForPersistentVolumeClaim(pvc, oldPvc *core.PersistentVolum
func ValidationOptionsForPersistentVolumeClaimTemplate(claimTemplate, oldClaimTemplate *core.PersistentVolumeClaimTemplate) PersistentVolumeClaimSpecValidationOptions {
opts := PersistentVolumeClaimSpecValidationOptions{
AllowReadWriteOncePod: utilfeature.DefaultFeatureGate.Enabled(features.ReadWriteOncePod),
AllowInvalidLabelValueInSelector: false,
}
if oldClaimTemplate == nil {
@ -2076,10 +2049,6 @@ func ValidationOptionsForPersistentVolumeClaimTemplate(claimTemplate, oldClaimTe
// If the old object had an invalid label selector, continue to allow it in the new object
opts.AllowInvalidLabelValueInSelector = true
}
if helper.ContainsAccessMode(oldClaimTemplate.Spec.AccessModes, core.ReadWriteOncePod) {
// If the old object allowed "ReadWriteOncePod", continue to allow it in the new object
opts.AllowReadWriteOncePod = true
}
return opts
}
@ -2172,15 +2141,10 @@ func ValidatePersistentVolumeClaimSpec(spec *core.PersistentVolumeClaimSpec, fld
allErrs = append(allErrs, unversionedvalidation.ValidateLabelSelector(spec.Selector, labelSelectorValidationOpts, fldPath.Child("selector"))...)
}
expandedSupportedAccessModes := sets.StringKeySet(supportedAccessModes)
if opts.AllowReadWriteOncePod {
expandedSupportedAccessModes.Insert(string(core.ReadWriteOncePod))
}
foundReadWriteOncePod, foundNonReadWriteOncePod := false, false
for _, mode := range spec.AccessModes {
if !expandedSupportedAccessModes.Has(string(mode)) {
allErrs = append(allErrs, field.NotSupported(fldPath.Child("accessModes"), mode, expandedSupportedAccessModes.List()))
if !supportedAccessModes.Has(string(mode)) {
allErrs = append(allErrs, field.NotSupported(fldPath.Child("accessModes"), mode, supportedAccessModes.List()))
}
if mode == core.ReadWriteOncePod {

View File

@ -109,9 +109,8 @@ func TestValidatePersistentVolumes(t *testing.T) {
validMode := core.PersistentVolumeFilesystem
invalidMode := core.PersistentVolumeMode("fakeVolumeMode")
scenarios := map[string]struct {
isExpectedFailure bool
enableReadWriteOncePod bool
volume *core.PersistentVolume
isExpectedFailure bool
volume *core.PersistentVolume
}{
"good-volume": {
isExpectedFailure: false,
@ -253,9 +252,8 @@ func TestValidatePersistentVolumes(t *testing.T) {
VolumeMode: &invalidMode,
}),
},
"with-read-write-once-pod-feature-gate-enabled": {
isExpectedFailure: false,
enableReadWriteOncePod: true,
"with-read-write-once-pod": {
isExpectedFailure: false,
volume: testVolume("foo", "", core.PersistentVolumeSpec{
Capacity: core.ResourceList{
core.ResourceName(core.ResourceStorage): resource.MustParse("10G"),
@ -269,25 +267,8 @@ func TestValidatePersistentVolumes(t *testing.T) {
},
}),
},
"with-read-write-once-pod-feature-gate-disabled": {
isExpectedFailure: true,
enableReadWriteOncePod: false,
volume: testVolume("foo", "", core.PersistentVolumeSpec{
Capacity: core.ResourceList{
core.ResourceName(core.ResourceStorage): resource.MustParse("10G"),
},
AccessModes: []core.PersistentVolumeAccessMode{"ReadWriteOncePod"},
PersistentVolumeSource: core.PersistentVolumeSource{
HostPath: &core.HostPathVolumeSource{
Path: "/foo",
Type: newHostPathType(string(core.HostPathDirectory)),
},
},
}),
},
"with-read-write-once-pod-and-others-feature-gate-enabled": {
isExpectedFailure: true,
enableReadWriteOncePod: true,
"with-read-write-once-pod-and-others": {
isExpectedFailure: true,
volume: testVolume("foo", "", core.PersistentVolumeSpec{
Capacity: core.ResourceList{
core.ResourceName(core.ResourceStorage): resource.MustParse("10G"),
@ -501,8 +482,6 @@ func TestValidatePersistentVolumes(t *testing.T) {
for name, scenario := range scenarios {
t.Run(name, func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ReadWriteOncePod, scenario.enableReadWriteOncePod)()
opts := ValidationOptionsForPersistentVolume(scenario.volume, nil)
errs := ValidatePersistentVolume(scenario.volume, opts)
if len(errs) == 0 && scenario.isExpectedFailure {
@ -903,51 +882,17 @@ func TestValidatePersistentVolumeSourceUpdate(t *testing.T) {
func TestValidationOptionsForPersistentVolume(t *testing.T) {
tests := map[string]struct {
oldPv *core.PersistentVolume
enableReadWriteOncePod bool
expectValidationOpts PersistentVolumeSpecValidationOptions
oldPv *core.PersistentVolume
expectValidationOpts PersistentVolumeSpecValidationOptions
}{
"nil old pv": {
oldPv: nil,
enableReadWriteOncePod: true,
expectValidationOpts: PersistentVolumeSpecValidationOptions{
AllowReadWriteOncePod: true,
},
},
"rwop allowed because feature enabled": {
oldPv: pvWithAccessModes([]core.PersistentVolumeAccessMode{core.ReadWriteOnce}),
enableReadWriteOncePod: true,
expectValidationOpts: PersistentVolumeSpecValidationOptions{
AllowReadWriteOncePod: true,
},
},
"rwop not allowed because not used and feature disabled": {
oldPv: pvWithAccessModes([]core.PersistentVolumeAccessMode{core.ReadWriteOnce}),
enableReadWriteOncePod: false,
expectValidationOpts: PersistentVolumeSpecValidationOptions{
AllowReadWriteOncePod: false,
},
},
"rwop allowed because used and feature enabled": {
oldPv: pvWithAccessModes([]core.PersistentVolumeAccessMode{core.ReadWriteOncePod}),
enableReadWriteOncePod: true,
expectValidationOpts: PersistentVolumeSpecValidationOptions{
AllowReadWriteOncePod: true,
},
},
"rwop allowed because used and feature disabled": {
oldPv: pvWithAccessModes([]core.PersistentVolumeAccessMode{core.ReadWriteOncePod}),
enableReadWriteOncePod: false,
expectValidationOpts: PersistentVolumeSpecValidationOptions{
AllowReadWriteOncePod: true,
},
oldPv: nil,
expectValidationOpts: PersistentVolumeSpecValidationOptions{},
},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ReadWriteOncePod, tc.enableReadWriteOncePod)()
opts := ValidationOptionsForPersistentVolume(nil, tc.oldPv)
if opts != tc.expectValidationOpts {
t.Errorf("Expected opts: %+v, received: %+v", opts, tc.expectValidationOpts)
@ -973,29 +918,6 @@ func getCSIVolumeWithSecret(pv *core.PersistentVolume, secret *core.SecretRefere
return pvCopy
}
func pvWithAccessModes(accessModes []core.PersistentVolumeAccessMode) *core.PersistentVolume {
return &core.PersistentVolume{
Spec: core.PersistentVolumeSpec{
AccessModes: accessModes,
},
}
}
func pvcWithAccessModes(accessModes []core.PersistentVolumeAccessMode) *core.PersistentVolumeClaim {
return &core.PersistentVolumeClaim{
Spec: core.PersistentVolumeClaimSpec{
AccessModes: accessModes,
},
}
}
func pvcTemplateWithAccessModes(accessModes []core.PersistentVolumeAccessMode) *core.PersistentVolumeClaimTemplate {
return &core.PersistentVolumeClaimTemplate{
Spec: core.PersistentVolumeClaimSpec{
AccessModes: accessModes,
},
}
}
func pvcWithDataSource(dataSource *core.TypedLocalObjectReference) *core.PersistentVolumeClaim {
return &core.PersistentVolumeClaim{
@ -1594,9 +1516,8 @@ func testValidatePVC(t *testing.T, ephemeral bool) {
ten := int64(10)
scenarios := map[string]struct {
isExpectedFailure bool
enableReadWriteOncePod bool
claim *core.PersistentVolumeClaim
isExpectedFailure bool
claim *core.PersistentVolumeClaim
}{
"good-claim": {
isExpectedFailure: false,
@ -1734,9 +1655,8 @@ func testValidatePVC(t *testing.T, ephemeral bool) {
return claim
}(),
},
"with-read-write-once-pod-feature-gate-enabled": {
isExpectedFailure: false,
enableReadWriteOncePod: true,
"with-read-write-once-pod": {
isExpectedFailure: false,
claim: testVolumeClaim(goodName, goodNS, core.PersistentVolumeClaimSpec{
AccessModes: []core.PersistentVolumeAccessMode{"ReadWriteOncePod"},
Resources: core.VolumeResourceRequirements{
@ -1746,21 +1666,8 @@ func testValidatePVC(t *testing.T, ephemeral bool) {
},
}),
},
"with-read-write-once-pod-feature-gate-disabled": {
isExpectedFailure: true,
enableReadWriteOncePod: false,
claim: testVolumeClaim(goodName, goodNS, core.PersistentVolumeClaimSpec{
AccessModes: []core.PersistentVolumeAccessMode{"ReadWriteOncePod"},
Resources: core.VolumeResourceRequirements{
Requests: core.ResourceList{
core.ResourceName(core.ResourceStorage): resource.MustParse("10G"),
},
},
}),
},
"with-read-write-once-pod-and-others-feature-gate-enabled": {
isExpectedFailure: true,
enableReadWriteOncePod: true,
"with-read-write-once-pod-and-others": {
isExpectedFailure: true,
claim: testVolumeClaim(goodName, goodNS, core.PersistentVolumeClaimSpec{
AccessModes: []core.PersistentVolumeAccessMode{"ReadWriteOncePod", "ReadWriteMany"},
Resources: core.VolumeResourceRequirements{
@ -1991,8 +1898,6 @@ func testValidatePVC(t *testing.T, ephemeral bool) {
for name, scenario := range scenarios {
t.Run(name, func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ReadWriteOncePod, scenario.enableReadWriteOncePod)()
var errs field.ErrorList
if ephemeral {
volumes := []core.Volume{{
@ -2754,47 +2659,12 @@ func TestValidationOptionsForPersistentVolumeClaim(t *testing.T) {
invaildAPIGroup := "^invalid"
tests := map[string]struct {
oldPvc *core.PersistentVolumeClaim
enableReadWriteOncePod bool
expectValidationOpts PersistentVolumeClaimSpecValidationOptions
oldPvc *core.PersistentVolumeClaim
expectValidationOpts PersistentVolumeClaimSpecValidationOptions
}{
"nil pv": {
oldPvc: nil,
enableReadWriteOncePod: true,
oldPvc: nil,
expectValidationOpts: PersistentVolumeClaimSpecValidationOptions{
AllowReadWriteOncePod: true,
EnableRecoverFromExpansionFailure: false,
},
},
"rwop allowed because feature enabled": {
oldPvc: pvcWithAccessModes([]core.PersistentVolumeAccessMode{core.ReadWriteOnce}),
enableReadWriteOncePod: true,
expectValidationOpts: PersistentVolumeClaimSpecValidationOptions{
AllowReadWriteOncePod: true,
EnableRecoverFromExpansionFailure: false,
},
},
"rwop not allowed because not used and feature disabled": {
oldPvc: pvcWithAccessModes([]core.PersistentVolumeAccessMode{core.ReadWriteOnce}),
enableReadWriteOncePod: false,
expectValidationOpts: PersistentVolumeClaimSpecValidationOptions{
AllowReadWriteOncePod: false,
EnableRecoverFromExpansionFailure: false,
},
},
"rwop allowed because used and feature enabled": {
oldPvc: pvcWithAccessModes([]core.PersistentVolumeAccessMode{core.ReadWriteOncePod}),
enableReadWriteOncePod: true,
expectValidationOpts: PersistentVolumeClaimSpecValidationOptions{
AllowReadWriteOncePod: true,
EnableRecoverFromExpansionFailure: false,
},
},
"rwop allowed because used and feature disabled": {
oldPvc: pvcWithAccessModes([]core.PersistentVolumeAccessMode{core.ReadWriteOncePod}),
enableReadWriteOncePod: false,
expectValidationOpts: PersistentVolumeClaimSpecValidationOptions{
AllowReadWriteOncePod: true,
EnableRecoverFromExpansionFailure: false,
},
},
@ -2814,8 +2684,6 @@ func TestValidationOptionsForPersistentVolumeClaim(t *testing.T) {
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ReadWriteOncePod, tc.enableReadWriteOncePod)()
opts := ValidationOptionsForPersistentVolumeClaim(nil, tc.oldPvc)
if opts != tc.expectValidationOpts {
t.Errorf("Expected opts: %+v, received: %+v", tc.expectValidationOpts, opts)
@ -2826,51 +2694,17 @@ func TestValidationOptionsForPersistentVolumeClaim(t *testing.T) {
func TestValidationOptionsForPersistentVolumeClaimTemplate(t *testing.T) {
tests := map[string]struct {
oldPvcTemplate *core.PersistentVolumeClaimTemplate
enableReadWriteOncePod bool
expectValidationOpts PersistentVolumeClaimSpecValidationOptions
oldPvcTemplate *core.PersistentVolumeClaimTemplate
expectValidationOpts PersistentVolumeClaimSpecValidationOptions
}{
"nil pv": {
oldPvcTemplate: nil,
enableReadWriteOncePod: true,
expectValidationOpts: PersistentVolumeClaimSpecValidationOptions{
AllowReadWriteOncePod: true,
},
},
"rwop allowed because feature enabled": {
oldPvcTemplate: pvcTemplateWithAccessModes([]core.PersistentVolumeAccessMode{core.ReadWriteOnce}),
enableReadWriteOncePod: true,
expectValidationOpts: PersistentVolumeClaimSpecValidationOptions{
AllowReadWriteOncePod: true,
},
},
"rwop not allowed because not used and feature disabled": {
oldPvcTemplate: pvcTemplateWithAccessModes([]core.PersistentVolumeAccessMode{core.ReadWriteOnce}),
enableReadWriteOncePod: false,
expectValidationOpts: PersistentVolumeClaimSpecValidationOptions{
AllowReadWriteOncePod: false,
},
},
"rwop allowed because used and feature enabled": {
oldPvcTemplate: pvcTemplateWithAccessModes([]core.PersistentVolumeAccessMode{core.ReadWriteOncePod}),
enableReadWriteOncePod: true,
expectValidationOpts: PersistentVolumeClaimSpecValidationOptions{
AllowReadWriteOncePod: true,
},
},
"rwop allowed because used and feature disabled": {
oldPvcTemplate: pvcTemplateWithAccessModes([]core.PersistentVolumeAccessMode{core.ReadWriteOncePod}),
enableReadWriteOncePod: false,
expectValidationOpts: PersistentVolumeClaimSpecValidationOptions{
AllowReadWriteOncePod: true,
},
oldPvcTemplate: nil,
expectValidationOpts: PersistentVolumeClaimSpecValidationOptions{},
},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ReadWriteOncePod, tc.enableReadWriteOncePod)()
opts := ValidationOptionsForPersistentVolumeClaimTemplate(nil, tc.oldPvcTemplate)
if opts != tc.expectValidationOpts {
t.Errorf("Expected opts: %+v, received: %+v", opts, tc.expectValidationOpts)

View File

@ -670,6 +670,7 @@ const (
// kep: https://kep.k8s.io/2485
// alpha: v1.22
// beta: v1.27
// GA: v1.29
//
// Enables usage of the ReadWriteOncePod PersistentVolume access mode.
ReadWriteOncePod featuregate.Feature = "ReadWriteOncePod"
@ -1046,7 +1047,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
QOSReserved: {Default: false, PreRelease: featuregate.Alpha},
ReadWriteOncePod: {Default: true, PreRelease: featuregate.Beta},
ReadWriteOncePod: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.31
RecoverVolumeExpansionFailure: {Default: false, PreRelease: featuregate.Alpha},

View File

@ -877,7 +877,6 @@ func Test_MarkDeviceAsMounted_Positive_NewVolume(t *testing.T) {
// Verifies volume/pod combo exist using PodExistsInVolume()
func Test_AddPodToVolume_Positive_SELinux(t *testing.T) {
// Arrange
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ReadWriteOncePod, true)()
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, true)()
volumePluginMgr, plugin := volumetesting.GetTestKubeletVolumePluginMgr(t)
asw := NewActualStateOfWorld("mynode" /* nodeName */, volumePluginMgr)
@ -956,7 +955,6 @@ func Test_AddPodToVolume_Positive_SELinux(t *testing.T) {
// Verifies newly added volume exists in GetGloballyMountedVolumes()
func Test_MarkDeviceAsMounted_Positive_SELinux(t *testing.T) {
// Arrange
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ReadWriteOncePod, true)()
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, true)()
volumePluginMgr, plugin := volumetesting.GetTestKubeletVolumePluginMgr(t)
asw := NewActualStateOfWorld("mynode" /* nodeName */, volumePluginMgr)

View File

@ -609,7 +609,6 @@ func Test_AddPodToVolume_WithEmptyDirSizeLimit(t *testing.T) {
// Verifies newly added pod/volume exists via PodExistsInVolume() without SELinux context
// VolumeExists() and GetVolumesToMount() and no errors.
func Test_AddPodToVolume_Positive_SELinuxNoRWOP(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ReadWriteOncePod, true)()
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, true)()
// Arrange
plugins := []volume.VolumePlugin{
@ -690,7 +689,6 @@ func Test_AddPodToVolume_Positive_SELinuxNoRWOP(t *testing.T) {
// Verifies newly added pod/volume exists via PodExistsInVolume() without SELinux context
// VolumeExists() and GetVolumesToMount() and no errors.
func Test_AddPodToVolume_Positive_NoSELinuxPlugin(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ReadWriteOncePod, true)()
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, true)()
// Arrange
plugins := []volume.VolumePlugin{
@ -772,7 +770,6 @@ func Test_AddPodToVolume_Positive_NoSELinuxPlugin(t *testing.T) {
// Verifies newly added pod/volume exists via PodExistsInVolume()
// VolumeExists() and GetVolumesToMount() and no errors.
func Test_AddPodToVolume_Positive_ExistingPodSameSELinuxRWOP(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ReadWriteOncePod, true)()
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, true)()
// Arrange
plugins := []volume.VolumePlugin{
@ -873,7 +870,6 @@ func Test_AddPodToVolume_Positive_ExistingPodSameSELinuxRWOP(t *testing.T) {
// Verifies newly added pod/volume exists via PodExistsInVolume()
// VolumeExists() and GetVolumesToMount() and no errors.
func Test_AddPodToVolume_Negative_ExistingPodDifferentSELinuxRWOP(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ReadWriteOncePod, true)()
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, true)()
// Arrange
plugins := []volume.VolumePlugin{

View File

@ -1189,7 +1189,6 @@ func TestCheckVolumeFSResize(t *testing.T) {
}
func TestCheckVolumeSELinux(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ReadWriteOncePod, true)()
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, true)()
fullOpts := &v1.SELinuxOptions{
User: "system_u",

View File

@ -21,7 +21,6 @@ package feature
// the internal k8s features pkg.
type Features struct {
EnableDynamicResourceAllocation bool
EnableReadWriteOncePod bool
EnableVolumeCapacityPriority bool
EnableMinDomainsInPodTopologySpread bool
EnableNodeInclusionPolicyInPodTopologySpread bool

View File

@ -47,7 +47,6 @@ import (
func NewInTreeRegistry() runtime.Registry {
fts := plfeature.Features{
EnableDynamicResourceAllocation: feature.DefaultFeatureGate.Enabled(features.DynamicResourceAllocation),
EnableReadWriteOncePod: feature.DefaultFeatureGate.Enabled(features.ReadWriteOncePod),
EnableVolumeCapacityPriority: feature.DefaultFeatureGate.Enabled(features.VolumeCapacityPriority),
EnableMinDomainsInPodTopologySpread: feature.DefaultFeatureGate.Enabled(features.MinDomainsInPodTopologySpread),
EnableNodeInclusionPolicyInPodTopologySpread: feature.DefaultFeatureGate.Enabled(features.NodeInclusionPolicyInPodTopologySpread),

View File

@ -33,9 +33,8 @@ import (
// VolumeRestrictions is a plugin that checks volume restrictions.
type VolumeRestrictions struct {
pvcLister corelisters.PersistentVolumeClaimLister
sharedLister framework.SharedLister
enableReadWriteOncePod bool
pvcLister corelisters.PersistentVolumeClaimLister
sharedLister framework.SharedLister
}
var _ framework.PreFilterPlugin = &VolumeRestrictions{}
@ -169,13 +168,6 @@ func (pl *VolumeRestrictions) PreFilter(ctx context.Context, cycleState *framewo
}
}
if !pl.enableReadWriteOncePod {
if needsCheck {
return nil, nil
}
return nil, framework.NewStatus(framework.Skip)
}
pvcs, err := pl.readWriteOncePodPVCsForPod(ctx, pod)
if err != nil {
if apierrors.IsNotFound(err) {
@ -198,9 +190,6 @@ func (pl *VolumeRestrictions) PreFilter(ctx context.Context, cycleState *framewo
// AddPod from pre-computed data in cycleState.
func (pl *VolumeRestrictions) AddPod(ctx context.Context, cycleState *framework.CycleState, podToSchedule *v1.Pod, podInfoToAdd *framework.PodInfo, nodeInfo *framework.NodeInfo) *framework.Status {
if !pl.enableReadWriteOncePod {
return nil
}
state, err := getPreFilterState(cycleState)
if err != nil {
return framework.AsStatus(err)
@ -211,9 +200,6 @@ func (pl *VolumeRestrictions) AddPod(ctx context.Context, cycleState *framework.
// RemovePod from pre-computed data in cycleState.
func (pl *VolumeRestrictions) RemovePod(ctx context.Context, cycleState *framework.CycleState, podToSchedule *v1.Pod, podInfoToRemove *framework.PodInfo, nodeInfo *framework.NodeInfo) *framework.Status {
if !pl.enableReadWriteOncePod {
return nil
}
state, err := getPreFilterState(cycleState)
if err != nil {
return framework.AsStatus(err)
@ -321,9 +307,6 @@ func (pl *VolumeRestrictions) Filter(ctx context.Context, cycleState *framework.
if !satisfyVolumeConflicts(pod, nodeInfo) {
return framework.NewStatus(framework.Unschedulable, ErrReasonDiskConflict)
}
if !pl.enableReadWriteOncePod {
return nil
}
state, err := getPreFilterState(cycleState)
if err != nil {
return framework.AsStatus(err)
@ -354,8 +337,7 @@ func New(_ context.Context, _ runtime.Object, handle framework.Handle, fts featu
sharedLister := handle.SnapshotSharedLister()
return &VolumeRestrictions{
pvcLister: pvcLister,
sharedLister: sharedLister,
enableReadWriteOncePod: fts.EnableReadWriteOncePod,
pvcLister: pvcLister,
sharedLister: sharedLister,
}, nil
}

View File

@ -24,9 +24,6 @@ import (
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
utilfeature "k8s.io/apiserver/pkg/util/feature"
featuregatetesting "k8s.io/component-base/featuregate/testing"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/scheduler/apis/config"
"k8s.io/kubernetes/pkg/scheduler/framework"
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/feature"
@ -355,8 +352,6 @@ func TestISCSIDiskConflicts(t *testing.T) {
}
func TestAccessModeConflicts(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ReadWriteOncePod, true)()
// Required for querying lister for PVCs in the same namespace.
podWithOnePVC := st.MakePod().Name("pod-with-one-pvc").Namespace(metav1.NamespaceDefault).PVC("claim-with-rwop-1").Node("node-1").Obj()
podWithTwoPVCs := st.MakePod().Name("pod-with-two-pvcs").Namespace(metav1.NamespaceDefault).PVC("claim-with-rwop-1").PVC("claim-with-rwop-2").Node("node-1").Obj()
@ -401,81 +396,64 @@ func TestAccessModeConflicts(t *testing.T) {
}
tests := []struct {
name string
pod *v1.Pod
nodeInfo *framework.NodeInfo
existingPods []*v1.Pod
existingNodes []*v1.Node
existingPVCs []*v1.PersistentVolumeClaim
enableReadWriteOncePod bool
preFilterWantStatus *framework.Status
wantStatus *framework.Status
name string
pod *v1.Pod
nodeInfo *framework.NodeInfo
existingPods []*v1.Pod
existingNodes []*v1.Node
existingPVCs []*v1.PersistentVolumeClaim
preFilterWantStatus *framework.Status
wantStatus *framework.Status
}{
{
name: "nothing",
pod: &v1.Pod{},
nodeInfo: framework.NewNodeInfo(),
existingPods: []*v1.Pod{},
existingNodes: []*v1.Node{},
existingPVCs: []*v1.PersistentVolumeClaim{},
enableReadWriteOncePod: true,
preFilterWantStatus: framework.NewStatus(framework.Skip),
wantStatus: nil,
name: "nothing",
pod: &v1.Pod{},
nodeInfo: framework.NewNodeInfo(),
existingPods: []*v1.Pod{},
existingNodes: []*v1.Node{},
existingPVCs: []*v1.PersistentVolumeClaim{},
preFilterWantStatus: framework.NewStatus(framework.Skip),
wantStatus: nil,
},
{
name: "nothing, ReadWriteOncePod disabled",
pod: &v1.Pod{},
nodeInfo: framework.NewNodeInfo(),
existingPods: []*v1.Pod{},
existingNodes: []*v1.Node{},
existingPVCs: []*v1.PersistentVolumeClaim{},
enableReadWriteOncePod: false,
preFilterWantStatus: framework.NewStatus(framework.Skip),
wantStatus: nil,
name: "failed to get PVC",
pod: podWithOnePVC,
nodeInfo: framework.NewNodeInfo(),
existingPods: []*v1.Pod{},
existingNodes: []*v1.Node{},
existingPVCs: []*v1.PersistentVolumeClaim{},
preFilterWantStatus: framework.NewStatus(framework.UnschedulableAndUnresolvable, "persistentvolumeclaim \"claim-with-rwop-1\" not found"),
wantStatus: nil,
},
{
name: "failed to get PVC",
pod: podWithOnePVC,
nodeInfo: framework.NewNodeInfo(),
existingPods: []*v1.Pod{},
existingNodes: []*v1.Node{},
existingPVCs: []*v1.PersistentVolumeClaim{},
enableReadWriteOncePod: true,
preFilterWantStatus: framework.NewStatus(framework.UnschedulableAndUnresolvable, "persistentvolumeclaim \"claim-with-rwop-1\" not found"),
wantStatus: nil,
name: "no access mode conflict",
pod: podWithOnePVC,
nodeInfo: framework.NewNodeInfo(podWithReadWriteManyPVC),
existingPods: []*v1.Pod{podWithReadWriteManyPVC},
existingNodes: []*v1.Node{node},
existingPVCs: []*v1.PersistentVolumeClaim{readWriteOncePodPVC1, readWriteManyPVC},
preFilterWantStatus: framework.NewStatus(framework.Skip),
wantStatus: nil,
},
{
name: "no access mode conflict",
pod: podWithOnePVC,
nodeInfo: framework.NewNodeInfo(podWithReadWriteManyPVC),
existingPods: []*v1.Pod{podWithReadWriteManyPVC},
existingNodes: []*v1.Node{node},
existingPVCs: []*v1.PersistentVolumeClaim{readWriteOncePodPVC1, readWriteManyPVC},
enableReadWriteOncePod: true,
preFilterWantStatus: framework.NewStatus(framework.Skip),
wantStatus: nil,
name: "access mode conflict, unschedulable",
pod: podWithOneConflict,
nodeInfo: framework.NewNodeInfo(podWithOnePVC, podWithReadWriteManyPVC),
existingPods: []*v1.Pod{podWithOnePVC, podWithReadWriteManyPVC},
existingNodes: []*v1.Node{node},
existingPVCs: []*v1.PersistentVolumeClaim{readWriteOncePodPVC1, readWriteManyPVC},
preFilterWantStatus: nil,
wantStatus: framework.NewStatus(framework.Unschedulable, ErrReasonReadWriteOncePodConflict),
},
{
name: "access mode conflict, unschedulable",
pod: podWithOneConflict,
nodeInfo: framework.NewNodeInfo(podWithOnePVC, podWithReadWriteManyPVC),
existingPods: []*v1.Pod{podWithOnePVC, podWithReadWriteManyPVC},
existingNodes: []*v1.Node{node},
existingPVCs: []*v1.PersistentVolumeClaim{readWriteOncePodPVC1, readWriteManyPVC},
enableReadWriteOncePod: true,
preFilterWantStatus: nil,
wantStatus: framework.NewStatus(framework.Unschedulable, ErrReasonReadWriteOncePodConflict),
},
{
name: "two conflicts, unschedulable",
pod: podWithTwoConflicts,
nodeInfo: framework.NewNodeInfo(podWithTwoPVCs, podWithReadWriteManyPVC),
existingPods: []*v1.Pod{podWithTwoPVCs, podWithReadWriteManyPVC},
existingNodes: []*v1.Node{node},
existingPVCs: []*v1.PersistentVolumeClaim{readWriteOncePodPVC1, readWriteOncePodPVC2, readWriteManyPVC},
enableReadWriteOncePod: true,
preFilterWantStatus: nil,
wantStatus: framework.NewStatus(framework.Unschedulable, ErrReasonReadWriteOncePodConflict),
name: "two conflicts, unschedulable",
pod: podWithTwoConflicts,
nodeInfo: framework.NewNodeInfo(podWithTwoPVCs, podWithReadWriteManyPVC),
existingPods: []*v1.Pod{podWithTwoPVCs, podWithReadWriteManyPVC},
existingNodes: []*v1.Node{node},
existingPVCs: []*v1.PersistentVolumeClaim{readWriteOncePodPVC1, readWriteOncePodPVC2, readWriteManyPVC},
preFilterWantStatus: nil,
wantStatus: framework.NewStatus(framework.Unschedulable, ErrReasonReadWriteOncePodConflict),
},
}
@ -483,7 +461,7 @@ func TestAccessModeConflicts(t *testing.T) {
t.Run(test.name, func(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
p := newPluginWithListers(ctx, t, test.existingPods, test.existingNodes, test.existingPVCs, test.enableReadWriteOncePod)
p := newPluginWithListers(ctx, t, test.existingPods, test.existingNodes, test.existingPVCs)
cycleState := framework.NewCycleState()
_, preFilterGotStatus := p.(framework.PreFilterPlugin).PreFilter(ctx, cycleState, test.pod)
if diff := cmp.Diff(test.preFilterWantStatus, preFilterGotStatus); diff != "" {
@ -501,14 +479,12 @@ func TestAccessModeConflicts(t *testing.T) {
}
func newPlugin(ctx context.Context, t *testing.T) framework.Plugin {
return newPluginWithListers(ctx, t, nil, nil, nil, true)
return newPluginWithListers(ctx, t, nil, nil, nil)
}
func newPluginWithListers(ctx context.Context, t *testing.T, pods []*v1.Pod, nodes []*v1.Node, pvcs []*v1.PersistentVolumeClaim, enableReadWriteOncePod bool) framework.Plugin {
func newPluginWithListers(ctx context.Context, t *testing.T, pods []*v1.Pod, nodes []*v1.Node, pvcs []*v1.PersistentVolumeClaim) framework.Plugin {
pluginFactory := func(ctx context.Context, plArgs runtime.Object, fh framework.Handle) (framework.Plugin, error) {
return New(ctx, plArgs, fh, feature.Features{
EnableReadWriteOncePod: enableReadWriteOncePod,
})
return New(ctx, plArgs, fh, feature.Features{})
}
snapshot := cache.NewSnapshot(pods, nodes)

View File

@ -370,7 +370,6 @@ func TestPluginConstructVolumeSpec(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ReadWriteOncePod, tc.seLinuxMountEnabled)()
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, tc.seLinuxMountEnabled)()
mounter, err := plug.NewMounter(

View File

@ -580,8 +580,7 @@ func (og *operationGenerator) GenerateMountVolumeFunc(
}
// Enforce ReadWriteOncePod access mode if it is the only one present. This is also enforced during scheduling.
if utilfeature.DefaultFeatureGate.Enabled(features.ReadWriteOncePod) &&
actualStateOfWorld.IsVolumeMountedElsewhere(volumeToMount.VolumeName, volumeToMount.PodName) &&
if actualStateOfWorld.IsVolumeMountedElsewhere(volumeToMount.VolumeName, volumeToMount.PodName) &&
// Because we do not know what access mode the pod intends to use if there are multiple.
len(volumeToMount.VolumeSpec.PersistentVolume.Spec.AccessModes) == 1 &&
v1helper.ContainsAccessMode(volumeToMount.VolumeSpec.PersistentVolume.Spec.AccessModes, v1.ReadWriteOncePod) {
@ -1071,8 +1070,7 @@ func (og *operationGenerator) GenerateMapVolumeFunc(
migrated := getMigratedStatusBySpec(volumeToMount.VolumeSpec)
// Enforce ReadWriteOncePod access mode. This is also enforced during scheduling.
if utilfeature.DefaultFeatureGate.Enabled(features.ReadWriteOncePod) &&
actualStateOfWorld.IsVolumeMountedElsewhere(volumeToMount.VolumeName, volumeToMount.PodName) &&
if actualStateOfWorld.IsVolumeMountedElsewhere(volumeToMount.VolumeName, volumeToMount.PodName) &&
// Because we do not know what access mode the pod intends to use if there are multiple.
len(volumeToMount.VolumeSpec.PersistentVolume.Spec.AccessModes) == 1 &&
v1helper.ContainsAccessMode(volumeToMount.VolumeSpec.PersistentVolume.Spec.AccessModes, v1.ReadWriteOncePod) {

View File

@ -168,10 +168,6 @@ func SupportsSELinuxContextMount(volumeSpec *volume.Spec, volumePluginMgr *volum
// VolumeSupportsSELinuxMount returns true if given volume access mode can support mount with SELinux mount options.
func VolumeSupportsSELinuxMount(volumeSpec *volume.Spec) bool {
// Right now, SELinux mount is supported only for ReadWriteOncePod volumes.
if !utilfeature.DefaultFeatureGate.Enabled(features.ReadWriteOncePod) {
return false
}
if !utilfeature.DefaultFeatureGate.Enabled(features.SELinuxMountReadWriteOncePod) {
return false
}

View File

@ -616,7 +616,6 @@ func TestMakeAbsolutePath(t *testing.T) {
}
func TestGetPodVolumeNames(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ReadWriteOncePod, true)()
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, true)()
tests := []struct {
name string

View File

@ -1554,11 +1554,10 @@ var (
func TestUnschedulablePodBecomesSchedulable(t *testing.T) {
tests := []struct {
name string
init func(kubernetes.Interface, string) error
pod *testutils.PausePodConfig
update func(kubernetes.Interface, string) error
enableReadWriteOncePod bool
name string
init func(kubernetes.Interface, string) error
pod *testutils.PausePodConfig
update func(kubernetes.Interface, string) error
}{
{
name: "node gets added",
@ -1765,13 +1764,10 @@ func TestUnschedulablePodBecomesSchedulable(t *testing.T) {
update: func(cs kubernetes.Interface, ns string) error {
return deletePod(cs, "pod-to-be-deleted", ns)
},
enableReadWriteOncePod: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ReadWriteOncePod, tt.enableReadWriteOncePod)()
testCtx := initTest(t, "scheduler-informer")
if tt.init != nil {

View File

@ -1648,8 +1648,6 @@ func TestPreferNominatedNode(t *testing.T) {
// TestReadWriteOncePodPreemption tests preemption scenarios for pods with
// ReadWriteOncePod PVCs.
func TestReadWriteOncePodPreemption(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, features.ReadWriteOncePod, true)()
cfg := configtesting.V1ToInternalWithDefaults(t, configv1.KubeSchedulerConfiguration{
Profiles: []configv1.KubeSchedulerProfile{{
SchedulerName: pointer.StringPtr(v1.DefaultSchedulerName),