mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-05 18:24:07 +00:00
Graduate ReadWriteOncePod to GA
This commit is contained in:
parent
f7cb8a5e8a
commit
2dbd405583
@ -1653,33 +1653,20 @@ var allowedTemplateObjectMetaFields = map[string]bool{
|
|||||||
|
|
||||||
// PersistentVolumeSpecValidationOptions contains the different settings for PeristentVolume validation
|
// PersistentVolumeSpecValidationOptions contains the different settings for PeristentVolume validation
|
||||||
type PersistentVolumeSpecValidationOptions struct {
|
type PersistentVolumeSpecValidationOptions struct {
|
||||||
// Allow spec to contain the "ReadWiteOncePod" access mode
|
|
||||||
AllowReadWriteOncePod bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidatePersistentVolumeName checks that a name is appropriate for a
|
// ValidatePersistentVolumeName checks that a name is appropriate for a
|
||||||
// PersistentVolumeName object.
|
// PersistentVolumeName object.
|
||||||
var ValidatePersistentVolumeName = apimachineryvalidation.NameIsDNSSubdomain
|
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 supportedReclaimPolicy = sets.NewString(string(core.PersistentVolumeReclaimDelete), string(core.PersistentVolumeReclaimRecycle), string(core.PersistentVolumeReclaimRetain))
|
||||||
|
|
||||||
var supportedVolumeModes = sets.NewString(string(core.PersistentVolumeBlock), string(core.PersistentVolumeFilesystem))
|
var supportedVolumeModes = sets.NewString(string(core.PersistentVolumeBlock), string(core.PersistentVolumeFilesystem))
|
||||||
|
|
||||||
func ValidationOptionsForPersistentVolume(pv, oldPv *core.PersistentVolume) PersistentVolumeSpecValidationOptions {
|
func ValidationOptionsForPersistentVolume(pv, oldPv *core.PersistentVolume) PersistentVolumeSpecValidationOptions {
|
||||||
opts := PersistentVolumeSpecValidationOptions{
|
return 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ValidatePersistentVolumeSpec(pvSpec *core.PersistentVolumeSpec, pvName string, validateInlinePersistentVolumeSpec bool, fldPath *field.Path, opts PersistentVolumeSpecValidationOptions) field.ErrorList {
|
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"), ""))
|
allErrs = append(allErrs, field.Required(fldPath.Child("accessModes"), ""))
|
||||||
}
|
}
|
||||||
|
|
||||||
expandedSupportedAccessModes := sets.StringKeySet(supportedAccessModes)
|
|
||||||
if opts.AllowReadWriteOncePod {
|
|
||||||
expandedSupportedAccessModes.Insert(string(core.ReadWriteOncePod))
|
|
||||||
}
|
|
||||||
|
|
||||||
foundReadWriteOncePod, foundNonReadWriteOncePod := false, false
|
foundReadWriteOncePod, foundNonReadWriteOncePod := false, false
|
||||||
for _, mode := range pvSpec.AccessModes {
|
for _, mode := range pvSpec.AccessModes {
|
||||||
if !expandedSupportedAccessModes.Has(string(mode)) {
|
if !supportedAccessModes.Has(string(mode)) {
|
||||||
allErrs = append(allErrs, field.NotSupported(fldPath.Child("accessModes"), mode, expandedSupportedAccessModes.List()))
|
allErrs = append(allErrs, field.NotSupported(fldPath.Child("accessModes"), mode, supportedAccessModes.List()))
|
||||||
}
|
}
|
||||||
|
|
||||||
if mode == core.ReadWriteOncePod {
|
if mode == core.ReadWriteOncePod {
|
||||||
@ -2016,8 +1998,6 @@ func ValidatePersistentVolumeStatusUpdate(newPv, oldPv *core.PersistentVolume) f
|
|||||||
}
|
}
|
||||||
|
|
||||||
type PersistentVolumeClaimSpecValidationOptions struct {
|
type PersistentVolumeClaimSpecValidationOptions struct {
|
||||||
// Allow spec to contain the "ReadWiteOncePod" access mode
|
|
||||||
AllowReadWriteOncePod bool
|
|
||||||
// Allow users to recover from previously failing expansion operation
|
// Allow users to recover from previously failing expansion operation
|
||||||
EnableRecoverFromExpansionFailure bool
|
EnableRecoverFromExpansionFailure bool
|
||||||
// Allow to validate the label value of the label selector
|
// Allow to validate the label value of the label selector
|
||||||
@ -2028,7 +2008,6 @@ type PersistentVolumeClaimSpecValidationOptions struct {
|
|||||||
|
|
||||||
func ValidationOptionsForPersistentVolumeClaim(pvc, oldPvc *core.PersistentVolumeClaim) PersistentVolumeClaimSpecValidationOptions {
|
func ValidationOptionsForPersistentVolumeClaim(pvc, oldPvc *core.PersistentVolumeClaim) PersistentVolumeClaimSpecValidationOptions {
|
||||||
opts := PersistentVolumeClaimSpecValidationOptions{
|
opts := PersistentVolumeClaimSpecValidationOptions{
|
||||||
AllowReadWriteOncePod: utilfeature.DefaultFeatureGate.Enabled(features.ReadWriteOncePod),
|
|
||||||
EnableRecoverFromExpansionFailure: utilfeature.DefaultFeatureGate.Enabled(features.RecoverVolumeExpansionFailure),
|
EnableRecoverFromExpansionFailure: utilfeature.DefaultFeatureGate.Enabled(features.RecoverVolumeExpansionFailure),
|
||||||
AllowInvalidLabelValueInSelector: false,
|
AllowInvalidLabelValueInSelector: false,
|
||||||
}
|
}
|
||||||
@ -2048,11 +2027,6 @@ func ValidationOptionsForPersistentVolumeClaim(pvc, oldPvc *core.PersistentVolum
|
|||||||
opts.AllowInvalidLabelValueInSelector = true
|
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) ||
|
if helper.ClaimContainsAllocatedResources(oldPvc) ||
|
||||||
helper.ClaimContainsAllocatedResourceStatus(oldPvc) {
|
helper.ClaimContainsAllocatedResourceStatus(oldPvc) {
|
||||||
opts.EnableRecoverFromExpansionFailure = true
|
opts.EnableRecoverFromExpansionFailure = true
|
||||||
@ -2062,7 +2036,6 @@ func ValidationOptionsForPersistentVolumeClaim(pvc, oldPvc *core.PersistentVolum
|
|||||||
|
|
||||||
func ValidationOptionsForPersistentVolumeClaimTemplate(claimTemplate, oldClaimTemplate *core.PersistentVolumeClaimTemplate) PersistentVolumeClaimSpecValidationOptions {
|
func ValidationOptionsForPersistentVolumeClaimTemplate(claimTemplate, oldClaimTemplate *core.PersistentVolumeClaimTemplate) PersistentVolumeClaimSpecValidationOptions {
|
||||||
opts := PersistentVolumeClaimSpecValidationOptions{
|
opts := PersistentVolumeClaimSpecValidationOptions{
|
||||||
AllowReadWriteOncePod: utilfeature.DefaultFeatureGate.Enabled(features.ReadWriteOncePod),
|
|
||||||
AllowInvalidLabelValueInSelector: false,
|
AllowInvalidLabelValueInSelector: false,
|
||||||
}
|
}
|
||||||
if oldClaimTemplate == nil {
|
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
|
// If the old object had an invalid label selector, continue to allow it in the new object
|
||||||
opts.AllowInvalidLabelValueInSelector = true
|
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
|
return opts
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2172,15 +2141,10 @@ func ValidatePersistentVolumeClaimSpec(spec *core.PersistentVolumeClaimSpec, fld
|
|||||||
allErrs = append(allErrs, unversionedvalidation.ValidateLabelSelector(spec.Selector, labelSelectorValidationOpts, fldPath.Child("selector"))...)
|
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
|
foundReadWriteOncePod, foundNonReadWriteOncePod := false, false
|
||||||
for _, mode := range spec.AccessModes {
|
for _, mode := range spec.AccessModes {
|
||||||
if !expandedSupportedAccessModes.Has(string(mode)) {
|
if !supportedAccessModes.Has(string(mode)) {
|
||||||
allErrs = append(allErrs, field.NotSupported(fldPath.Child("accessModes"), mode, expandedSupportedAccessModes.List()))
|
allErrs = append(allErrs, field.NotSupported(fldPath.Child("accessModes"), mode, supportedAccessModes.List()))
|
||||||
}
|
}
|
||||||
|
|
||||||
if mode == core.ReadWriteOncePod {
|
if mode == core.ReadWriteOncePod {
|
||||||
|
@ -109,9 +109,8 @@ func TestValidatePersistentVolumes(t *testing.T) {
|
|||||||
validMode := core.PersistentVolumeFilesystem
|
validMode := core.PersistentVolumeFilesystem
|
||||||
invalidMode := core.PersistentVolumeMode("fakeVolumeMode")
|
invalidMode := core.PersistentVolumeMode("fakeVolumeMode")
|
||||||
scenarios := map[string]struct {
|
scenarios := map[string]struct {
|
||||||
isExpectedFailure bool
|
isExpectedFailure bool
|
||||||
enableReadWriteOncePod bool
|
volume *core.PersistentVolume
|
||||||
volume *core.PersistentVolume
|
|
||||||
}{
|
}{
|
||||||
"good-volume": {
|
"good-volume": {
|
||||||
isExpectedFailure: false,
|
isExpectedFailure: false,
|
||||||
@ -253,9 +252,8 @@ func TestValidatePersistentVolumes(t *testing.T) {
|
|||||||
VolumeMode: &invalidMode,
|
VolumeMode: &invalidMode,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
"with-read-write-once-pod-feature-gate-enabled": {
|
"with-read-write-once-pod": {
|
||||||
isExpectedFailure: false,
|
isExpectedFailure: false,
|
||||||
enableReadWriteOncePod: true,
|
|
||||||
volume: testVolume("foo", "", core.PersistentVolumeSpec{
|
volume: testVolume("foo", "", core.PersistentVolumeSpec{
|
||||||
Capacity: core.ResourceList{
|
Capacity: core.ResourceList{
|
||||||
core.ResourceName(core.ResourceStorage): resource.MustParse("10G"),
|
core.ResourceName(core.ResourceStorage): resource.MustParse("10G"),
|
||||||
@ -269,25 +267,8 @@ func TestValidatePersistentVolumes(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
"with-read-write-once-pod-feature-gate-disabled": {
|
"with-read-write-once-pod-and-others": {
|
||||||
isExpectedFailure: true,
|
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,
|
|
||||||
volume: testVolume("foo", "", core.PersistentVolumeSpec{
|
volume: testVolume("foo", "", core.PersistentVolumeSpec{
|
||||||
Capacity: core.ResourceList{
|
Capacity: core.ResourceList{
|
||||||
core.ResourceName(core.ResourceStorage): resource.MustParse("10G"),
|
core.ResourceName(core.ResourceStorage): resource.MustParse("10G"),
|
||||||
@ -501,8 +482,6 @@ func TestValidatePersistentVolumes(t *testing.T) {
|
|||||||
|
|
||||||
for name, scenario := range scenarios {
|
for name, scenario := range scenarios {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ReadWriteOncePod, scenario.enableReadWriteOncePod)()
|
|
||||||
|
|
||||||
opts := ValidationOptionsForPersistentVolume(scenario.volume, nil)
|
opts := ValidationOptionsForPersistentVolume(scenario.volume, nil)
|
||||||
errs := ValidatePersistentVolume(scenario.volume, opts)
|
errs := ValidatePersistentVolume(scenario.volume, opts)
|
||||||
if len(errs) == 0 && scenario.isExpectedFailure {
|
if len(errs) == 0 && scenario.isExpectedFailure {
|
||||||
@ -903,51 +882,17 @@ func TestValidatePersistentVolumeSourceUpdate(t *testing.T) {
|
|||||||
|
|
||||||
func TestValidationOptionsForPersistentVolume(t *testing.T) {
|
func TestValidationOptionsForPersistentVolume(t *testing.T) {
|
||||||
tests := map[string]struct {
|
tests := map[string]struct {
|
||||||
oldPv *core.PersistentVolume
|
oldPv *core.PersistentVolume
|
||||||
enableReadWriteOncePod bool
|
expectValidationOpts PersistentVolumeSpecValidationOptions
|
||||||
expectValidationOpts PersistentVolumeSpecValidationOptions
|
|
||||||
}{
|
}{
|
||||||
"nil old pv": {
|
"nil old pv": {
|
||||||
oldPv: nil,
|
oldPv: nil,
|
||||||
enableReadWriteOncePod: true,
|
expectValidationOpts: PersistentVolumeSpecValidationOptions{},
|
||||||
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,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, tc := range tests {
|
for name, tc := range tests {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ReadWriteOncePod, tc.enableReadWriteOncePod)()
|
|
||||||
|
|
||||||
opts := ValidationOptionsForPersistentVolume(nil, tc.oldPv)
|
opts := ValidationOptionsForPersistentVolume(nil, tc.oldPv)
|
||||||
if opts != tc.expectValidationOpts {
|
if opts != tc.expectValidationOpts {
|
||||||
t.Errorf("Expected opts: %+v, received: %+v", 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
|
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 {
|
func pvcWithDataSource(dataSource *core.TypedLocalObjectReference) *core.PersistentVolumeClaim {
|
||||||
return &core.PersistentVolumeClaim{
|
return &core.PersistentVolumeClaim{
|
||||||
@ -1594,9 +1516,8 @@ func testValidatePVC(t *testing.T, ephemeral bool) {
|
|||||||
ten := int64(10)
|
ten := int64(10)
|
||||||
|
|
||||||
scenarios := map[string]struct {
|
scenarios := map[string]struct {
|
||||||
isExpectedFailure bool
|
isExpectedFailure bool
|
||||||
enableReadWriteOncePod bool
|
claim *core.PersistentVolumeClaim
|
||||||
claim *core.PersistentVolumeClaim
|
|
||||||
}{
|
}{
|
||||||
"good-claim": {
|
"good-claim": {
|
||||||
isExpectedFailure: false,
|
isExpectedFailure: false,
|
||||||
@ -1734,9 +1655,8 @@ func testValidatePVC(t *testing.T, ephemeral bool) {
|
|||||||
return claim
|
return claim
|
||||||
}(),
|
}(),
|
||||||
},
|
},
|
||||||
"with-read-write-once-pod-feature-gate-enabled": {
|
"with-read-write-once-pod": {
|
||||||
isExpectedFailure: false,
|
isExpectedFailure: false,
|
||||||
enableReadWriteOncePod: true,
|
|
||||||
claim: testVolumeClaim(goodName, goodNS, core.PersistentVolumeClaimSpec{
|
claim: testVolumeClaim(goodName, goodNS, core.PersistentVolumeClaimSpec{
|
||||||
AccessModes: []core.PersistentVolumeAccessMode{"ReadWriteOncePod"},
|
AccessModes: []core.PersistentVolumeAccessMode{"ReadWriteOncePod"},
|
||||||
Resources: core.VolumeResourceRequirements{
|
Resources: core.VolumeResourceRequirements{
|
||||||
@ -1746,21 +1666,8 @@ func testValidatePVC(t *testing.T, ephemeral bool) {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
"with-read-write-once-pod-feature-gate-disabled": {
|
"with-read-write-once-pod-and-others": {
|
||||||
isExpectedFailure: true,
|
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,
|
|
||||||
claim: testVolumeClaim(goodName, goodNS, core.PersistentVolumeClaimSpec{
|
claim: testVolumeClaim(goodName, goodNS, core.PersistentVolumeClaimSpec{
|
||||||
AccessModes: []core.PersistentVolumeAccessMode{"ReadWriteOncePod", "ReadWriteMany"},
|
AccessModes: []core.PersistentVolumeAccessMode{"ReadWriteOncePod", "ReadWriteMany"},
|
||||||
Resources: core.VolumeResourceRequirements{
|
Resources: core.VolumeResourceRequirements{
|
||||||
@ -1991,8 +1898,6 @@ func testValidatePVC(t *testing.T, ephemeral bool) {
|
|||||||
|
|
||||||
for name, scenario := range scenarios {
|
for name, scenario := range scenarios {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ReadWriteOncePod, scenario.enableReadWriteOncePod)()
|
|
||||||
|
|
||||||
var errs field.ErrorList
|
var errs field.ErrorList
|
||||||
if ephemeral {
|
if ephemeral {
|
||||||
volumes := []core.Volume{{
|
volumes := []core.Volume{{
|
||||||
@ -2754,47 +2659,12 @@ func TestValidationOptionsForPersistentVolumeClaim(t *testing.T) {
|
|||||||
invaildAPIGroup := "^invalid"
|
invaildAPIGroup := "^invalid"
|
||||||
|
|
||||||
tests := map[string]struct {
|
tests := map[string]struct {
|
||||||
oldPvc *core.PersistentVolumeClaim
|
oldPvc *core.PersistentVolumeClaim
|
||||||
enableReadWriteOncePod bool
|
expectValidationOpts PersistentVolumeClaimSpecValidationOptions
|
||||||
expectValidationOpts PersistentVolumeClaimSpecValidationOptions
|
|
||||||
}{
|
}{
|
||||||
"nil pv": {
|
"nil pv": {
|
||||||
oldPvc: nil,
|
oldPvc: nil,
|
||||||
enableReadWriteOncePod: true,
|
|
||||||
expectValidationOpts: PersistentVolumeClaimSpecValidationOptions{
|
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,
|
EnableRecoverFromExpansionFailure: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -2814,8 +2684,6 @@ func TestValidationOptionsForPersistentVolumeClaim(t *testing.T) {
|
|||||||
|
|
||||||
for name, tc := range tests {
|
for name, tc := range tests {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ReadWriteOncePod, tc.enableReadWriteOncePod)()
|
|
||||||
|
|
||||||
opts := ValidationOptionsForPersistentVolumeClaim(nil, tc.oldPvc)
|
opts := ValidationOptionsForPersistentVolumeClaim(nil, tc.oldPvc)
|
||||||
if opts != tc.expectValidationOpts {
|
if opts != tc.expectValidationOpts {
|
||||||
t.Errorf("Expected opts: %+v, received: %+v", tc.expectValidationOpts, opts)
|
t.Errorf("Expected opts: %+v, received: %+v", tc.expectValidationOpts, opts)
|
||||||
@ -2826,51 +2694,17 @@ func TestValidationOptionsForPersistentVolumeClaim(t *testing.T) {
|
|||||||
|
|
||||||
func TestValidationOptionsForPersistentVolumeClaimTemplate(t *testing.T) {
|
func TestValidationOptionsForPersistentVolumeClaimTemplate(t *testing.T) {
|
||||||
tests := map[string]struct {
|
tests := map[string]struct {
|
||||||
oldPvcTemplate *core.PersistentVolumeClaimTemplate
|
oldPvcTemplate *core.PersistentVolumeClaimTemplate
|
||||||
enableReadWriteOncePod bool
|
expectValidationOpts PersistentVolumeClaimSpecValidationOptions
|
||||||
expectValidationOpts PersistentVolumeClaimSpecValidationOptions
|
|
||||||
}{
|
}{
|
||||||
"nil pv": {
|
"nil pv": {
|
||||||
oldPvcTemplate: nil,
|
oldPvcTemplate: nil,
|
||||||
enableReadWriteOncePod: true,
|
expectValidationOpts: PersistentVolumeClaimSpecValidationOptions{},
|
||||||
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,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, tc := range tests {
|
for name, tc := range tests {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ReadWriteOncePod, tc.enableReadWriteOncePod)()
|
|
||||||
|
|
||||||
opts := ValidationOptionsForPersistentVolumeClaimTemplate(nil, tc.oldPvcTemplate)
|
opts := ValidationOptionsForPersistentVolumeClaimTemplate(nil, tc.oldPvcTemplate)
|
||||||
if opts != tc.expectValidationOpts {
|
if opts != tc.expectValidationOpts {
|
||||||
t.Errorf("Expected opts: %+v, received: %+v", opts, tc.expectValidationOpts)
|
t.Errorf("Expected opts: %+v, received: %+v", opts, tc.expectValidationOpts)
|
||||||
|
@ -670,6 +670,7 @@ const (
|
|||||||
// kep: https://kep.k8s.io/2485
|
// kep: https://kep.k8s.io/2485
|
||||||
// alpha: v1.22
|
// alpha: v1.22
|
||||||
// beta: v1.27
|
// beta: v1.27
|
||||||
|
// GA: v1.29
|
||||||
//
|
//
|
||||||
// Enables usage of the ReadWriteOncePod PersistentVolume access mode.
|
// Enables usage of the ReadWriteOncePod PersistentVolume access mode.
|
||||||
ReadWriteOncePod featuregate.Feature = "ReadWriteOncePod"
|
ReadWriteOncePod featuregate.Feature = "ReadWriteOncePod"
|
||||||
@ -1046,7 +1047,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
|
|||||||
|
|
||||||
QOSReserved: {Default: false, PreRelease: featuregate.Alpha},
|
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},
|
RecoverVolumeExpansionFailure: {Default: false, PreRelease: featuregate.Alpha},
|
||||||
|
|
||||||
|
@ -877,7 +877,6 @@ func Test_MarkDeviceAsMounted_Positive_NewVolume(t *testing.T) {
|
|||||||
// Verifies volume/pod combo exist using PodExistsInVolume()
|
// Verifies volume/pod combo exist using PodExistsInVolume()
|
||||||
func Test_AddPodToVolume_Positive_SELinux(t *testing.T) {
|
func Test_AddPodToVolume_Positive_SELinux(t *testing.T) {
|
||||||
// Arrange
|
// Arrange
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ReadWriteOncePod, true)()
|
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, true)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, true)()
|
||||||
volumePluginMgr, plugin := volumetesting.GetTestKubeletVolumePluginMgr(t)
|
volumePluginMgr, plugin := volumetesting.GetTestKubeletVolumePluginMgr(t)
|
||||||
asw := NewActualStateOfWorld("mynode" /* nodeName */, volumePluginMgr)
|
asw := NewActualStateOfWorld("mynode" /* nodeName */, volumePluginMgr)
|
||||||
@ -956,7 +955,6 @@ func Test_AddPodToVolume_Positive_SELinux(t *testing.T) {
|
|||||||
// Verifies newly added volume exists in GetGloballyMountedVolumes()
|
// Verifies newly added volume exists in GetGloballyMountedVolumes()
|
||||||
func Test_MarkDeviceAsMounted_Positive_SELinux(t *testing.T) {
|
func Test_MarkDeviceAsMounted_Positive_SELinux(t *testing.T) {
|
||||||
// Arrange
|
// Arrange
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ReadWriteOncePod, true)()
|
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, true)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, true)()
|
||||||
volumePluginMgr, plugin := volumetesting.GetTestKubeletVolumePluginMgr(t)
|
volumePluginMgr, plugin := volumetesting.GetTestKubeletVolumePluginMgr(t)
|
||||||
asw := NewActualStateOfWorld("mynode" /* nodeName */, volumePluginMgr)
|
asw := NewActualStateOfWorld("mynode" /* nodeName */, volumePluginMgr)
|
||||||
|
@ -609,7 +609,6 @@ func Test_AddPodToVolume_WithEmptyDirSizeLimit(t *testing.T) {
|
|||||||
// Verifies newly added pod/volume exists via PodExistsInVolume() without SELinux context
|
// Verifies newly added pod/volume exists via PodExistsInVolume() without SELinux context
|
||||||
// VolumeExists() and GetVolumesToMount() and no errors.
|
// VolumeExists() and GetVolumesToMount() and no errors.
|
||||||
func Test_AddPodToVolume_Positive_SELinuxNoRWOP(t *testing.T) {
|
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)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, true)()
|
||||||
// Arrange
|
// Arrange
|
||||||
plugins := []volume.VolumePlugin{
|
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
|
// Verifies newly added pod/volume exists via PodExistsInVolume() without SELinux context
|
||||||
// VolumeExists() and GetVolumesToMount() and no errors.
|
// VolumeExists() and GetVolumesToMount() and no errors.
|
||||||
func Test_AddPodToVolume_Positive_NoSELinuxPlugin(t *testing.T) {
|
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)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, true)()
|
||||||
// Arrange
|
// Arrange
|
||||||
plugins := []volume.VolumePlugin{
|
plugins := []volume.VolumePlugin{
|
||||||
@ -772,7 +770,6 @@ func Test_AddPodToVolume_Positive_NoSELinuxPlugin(t *testing.T) {
|
|||||||
// Verifies newly added pod/volume exists via PodExistsInVolume()
|
// Verifies newly added pod/volume exists via PodExistsInVolume()
|
||||||
// VolumeExists() and GetVolumesToMount() and no errors.
|
// VolumeExists() and GetVolumesToMount() and no errors.
|
||||||
func Test_AddPodToVolume_Positive_ExistingPodSameSELinuxRWOP(t *testing.T) {
|
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)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, true)()
|
||||||
// Arrange
|
// Arrange
|
||||||
plugins := []volume.VolumePlugin{
|
plugins := []volume.VolumePlugin{
|
||||||
@ -873,7 +870,6 @@ func Test_AddPodToVolume_Positive_ExistingPodSameSELinuxRWOP(t *testing.T) {
|
|||||||
// Verifies newly added pod/volume exists via PodExistsInVolume()
|
// Verifies newly added pod/volume exists via PodExistsInVolume()
|
||||||
// VolumeExists() and GetVolumesToMount() and no errors.
|
// VolumeExists() and GetVolumesToMount() and no errors.
|
||||||
func Test_AddPodToVolume_Negative_ExistingPodDifferentSELinuxRWOP(t *testing.T) {
|
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)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, true)()
|
||||||
// Arrange
|
// Arrange
|
||||||
plugins := []volume.VolumePlugin{
|
plugins := []volume.VolumePlugin{
|
||||||
|
@ -1189,7 +1189,6 @@ func TestCheckVolumeFSResize(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCheckVolumeSELinux(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)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, true)()
|
||||||
fullOpts := &v1.SELinuxOptions{
|
fullOpts := &v1.SELinuxOptions{
|
||||||
User: "system_u",
|
User: "system_u",
|
||||||
|
@ -21,7 +21,6 @@ package feature
|
|||||||
// the internal k8s features pkg.
|
// the internal k8s features pkg.
|
||||||
type Features struct {
|
type Features struct {
|
||||||
EnableDynamicResourceAllocation bool
|
EnableDynamicResourceAllocation bool
|
||||||
EnableReadWriteOncePod bool
|
|
||||||
EnableVolumeCapacityPriority bool
|
EnableVolumeCapacityPriority bool
|
||||||
EnableMinDomainsInPodTopologySpread bool
|
EnableMinDomainsInPodTopologySpread bool
|
||||||
EnableNodeInclusionPolicyInPodTopologySpread bool
|
EnableNodeInclusionPolicyInPodTopologySpread bool
|
||||||
|
@ -47,7 +47,6 @@ import (
|
|||||||
func NewInTreeRegistry() runtime.Registry {
|
func NewInTreeRegistry() runtime.Registry {
|
||||||
fts := plfeature.Features{
|
fts := plfeature.Features{
|
||||||
EnableDynamicResourceAllocation: feature.DefaultFeatureGate.Enabled(features.DynamicResourceAllocation),
|
EnableDynamicResourceAllocation: feature.DefaultFeatureGate.Enabled(features.DynamicResourceAllocation),
|
||||||
EnableReadWriteOncePod: feature.DefaultFeatureGate.Enabled(features.ReadWriteOncePod),
|
|
||||||
EnableVolumeCapacityPriority: feature.DefaultFeatureGate.Enabled(features.VolumeCapacityPriority),
|
EnableVolumeCapacityPriority: feature.DefaultFeatureGate.Enabled(features.VolumeCapacityPriority),
|
||||||
EnableMinDomainsInPodTopologySpread: feature.DefaultFeatureGate.Enabled(features.MinDomainsInPodTopologySpread),
|
EnableMinDomainsInPodTopologySpread: feature.DefaultFeatureGate.Enabled(features.MinDomainsInPodTopologySpread),
|
||||||
EnableNodeInclusionPolicyInPodTopologySpread: feature.DefaultFeatureGate.Enabled(features.NodeInclusionPolicyInPodTopologySpread),
|
EnableNodeInclusionPolicyInPodTopologySpread: feature.DefaultFeatureGate.Enabled(features.NodeInclusionPolicyInPodTopologySpread),
|
||||||
|
@ -33,9 +33,8 @@ import (
|
|||||||
|
|
||||||
// VolumeRestrictions is a plugin that checks volume restrictions.
|
// VolumeRestrictions is a plugin that checks volume restrictions.
|
||||||
type VolumeRestrictions struct {
|
type VolumeRestrictions struct {
|
||||||
pvcLister corelisters.PersistentVolumeClaimLister
|
pvcLister corelisters.PersistentVolumeClaimLister
|
||||||
sharedLister framework.SharedLister
|
sharedLister framework.SharedLister
|
||||||
enableReadWriteOncePod bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ framework.PreFilterPlugin = &VolumeRestrictions{}
|
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)
|
pvcs, err := pl.readWriteOncePodPVCsForPod(ctx, pod)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if apierrors.IsNotFound(err) {
|
if apierrors.IsNotFound(err) {
|
||||||
@ -198,9 +190,6 @@ func (pl *VolumeRestrictions) PreFilter(ctx context.Context, cycleState *framewo
|
|||||||
|
|
||||||
// AddPod from pre-computed data in cycleState.
|
// 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 {
|
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)
|
state, err := getPreFilterState(cycleState)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return framework.AsStatus(err)
|
return framework.AsStatus(err)
|
||||||
@ -211,9 +200,6 @@ func (pl *VolumeRestrictions) AddPod(ctx context.Context, cycleState *framework.
|
|||||||
|
|
||||||
// RemovePod from pre-computed data in cycleState.
|
// 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 {
|
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)
|
state, err := getPreFilterState(cycleState)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return framework.AsStatus(err)
|
return framework.AsStatus(err)
|
||||||
@ -321,9 +307,6 @@ func (pl *VolumeRestrictions) Filter(ctx context.Context, cycleState *framework.
|
|||||||
if !satisfyVolumeConflicts(pod, nodeInfo) {
|
if !satisfyVolumeConflicts(pod, nodeInfo) {
|
||||||
return framework.NewStatus(framework.Unschedulable, ErrReasonDiskConflict)
|
return framework.NewStatus(framework.Unschedulable, ErrReasonDiskConflict)
|
||||||
}
|
}
|
||||||
if !pl.enableReadWriteOncePod {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
state, err := getPreFilterState(cycleState)
|
state, err := getPreFilterState(cycleState)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return framework.AsStatus(err)
|
return framework.AsStatus(err)
|
||||||
@ -354,8 +337,7 @@ func New(_ context.Context, _ runtime.Object, handle framework.Handle, fts featu
|
|||||||
sharedLister := handle.SnapshotSharedLister()
|
sharedLister := handle.SnapshotSharedLister()
|
||||||
|
|
||||||
return &VolumeRestrictions{
|
return &VolumeRestrictions{
|
||||||
pvcLister: pvcLister,
|
pvcLister: pvcLister,
|
||||||
sharedLister: sharedLister,
|
sharedLister: sharedLister,
|
||||||
enableReadWriteOncePod: fts.EnableReadWriteOncePod,
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -24,9 +24,6 @@ import (
|
|||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"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/apis/config"
|
||||||
"k8s.io/kubernetes/pkg/scheduler/framework"
|
"k8s.io/kubernetes/pkg/scheduler/framework"
|
||||||
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/feature"
|
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/feature"
|
||||||
@ -355,8 +352,6 @@ func TestISCSIDiskConflicts(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAccessModeConflicts(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.
|
// 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()
|
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()
|
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 {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
pod *v1.Pod
|
pod *v1.Pod
|
||||||
nodeInfo *framework.NodeInfo
|
nodeInfo *framework.NodeInfo
|
||||||
existingPods []*v1.Pod
|
existingPods []*v1.Pod
|
||||||
existingNodes []*v1.Node
|
existingNodes []*v1.Node
|
||||||
existingPVCs []*v1.PersistentVolumeClaim
|
existingPVCs []*v1.PersistentVolumeClaim
|
||||||
enableReadWriteOncePod bool
|
preFilterWantStatus *framework.Status
|
||||||
preFilterWantStatus *framework.Status
|
wantStatus *framework.Status
|
||||||
wantStatus *framework.Status
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "nothing",
|
name: "nothing",
|
||||||
pod: &v1.Pod{},
|
pod: &v1.Pod{},
|
||||||
nodeInfo: framework.NewNodeInfo(),
|
nodeInfo: framework.NewNodeInfo(),
|
||||||
existingPods: []*v1.Pod{},
|
existingPods: []*v1.Pod{},
|
||||||
existingNodes: []*v1.Node{},
|
existingNodes: []*v1.Node{},
|
||||||
existingPVCs: []*v1.PersistentVolumeClaim{},
|
existingPVCs: []*v1.PersistentVolumeClaim{},
|
||||||
enableReadWriteOncePod: true,
|
preFilterWantStatus: framework.NewStatus(framework.Skip),
|
||||||
preFilterWantStatus: framework.NewStatus(framework.Skip),
|
wantStatus: nil,
|
||||||
wantStatus: nil,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "nothing, ReadWriteOncePod disabled",
|
name: "failed to get PVC",
|
||||||
pod: &v1.Pod{},
|
pod: podWithOnePVC,
|
||||||
nodeInfo: framework.NewNodeInfo(),
|
nodeInfo: framework.NewNodeInfo(),
|
||||||
existingPods: []*v1.Pod{},
|
existingPods: []*v1.Pod{},
|
||||||
existingNodes: []*v1.Node{},
|
existingNodes: []*v1.Node{},
|
||||||
existingPVCs: []*v1.PersistentVolumeClaim{},
|
existingPVCs: []*v1.PersistentVolumeClaim{},
|
||||||
enableReadWriteOncePod: false,
|
preFilterWantStatus: framework.NewStatus(framework.UnschedulableAndUnresolvable, "persistentvolumeclaim \"claim-with-rwop-1\" not found"),
|
||||||
preFilterWantStatus: framework.NewStatus(framework.Skip),
|
wantStatus: nil,
|
||||||
wantStatus: nil,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "failed to get PVC",
|
name: "no access mode conflict",
|
||||||
pod: podWithOnePVC,
|
pod: podWithOnePVC,
|
||||||
nodeInfo: framework.NewNodeInfo(),
|
nodeInfo: framework.NewNodeInfo(podWithReadWriteManyPVC),
|
||||||
existingPods: []*v1.Pod{},
|
existingPods: []*v1.Pod{podWithReadWriteManyPVC},
|
||||||
existingNodes: []*v1.Node{},
|
existingNodes: []*v1.Node{node},
|
||||||
existingPVCs: []*v1.PersistentVolumeClaim{},
|
existingPVCs: []*v1.PersistentVolumeClaim{readWriteOncePodPVC1, readWriteManyPVC},
|
||||||
enableReadWriteOncePod: true,
|
preFilterWantStatus: framework.NewStatus(framework.Skip),
|
||||||
preFilterWantStatus: framework.NewStatus(framework.UnschedulableAndUnresolvable, "persistentvolumeclaim \"claim-with-rwop-1\" not found"),
|
wantStatus: nil,
|
||||||
wantStatus: nil,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "no access mode conflict",
|
name: "access mode conflict, unschedulable",
|
||||||
pod: podWithOnePVC,
|
pod: podWithOneConflict,
|
||||||
nodeInfo: framework.NewNodeInfo(podWithReadWriteManyPVC),
|
nodeInfo: framework.NewNodeInfo(podWithOnePVC, podWithReadWriteManyPVC),
|
||||||
existingPods: []*v1.Pod{podWithReadWriteManyPVC},
|
existingPods: []*v1.Pod{podWithOnePVC, podWithReadWriteManyPVC},
|
||||||
existingNodes: []*v1.Node{node},
|
existingNodes: []*v1.Node{node},
|
||||||
existingPVCs: []*v1.PersistentVolumeClaim{readWriteOncePodPVC1, readWriteManyPVC},
|
existingPVCs: []*v1.PersistentVolumeClaim{readWriteOncePodPVC1, readWriteManyPVC},
|
||||||
enableReadWriteOncePod: true,
|
preFilterWantStatus: nil,
|
||||||
preFilterWantStatus: framework.NewStatus(framework.Skip),
|
wantStatus: framework.NewStatus(framework.Unschedulable, ErrReasonReadWriteOncePodConflict),
|
||||||
wantStatus: nil,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "access mode conflict, unschedulable",
|
name: "two conflicts, unschedulable",
|
||||||
pod: podWithOneConflict,
|
pod: podWithTwoConflicts,
|
||||||
nodeInfo: framework.NewNodeInfo(podWithOnePVC, podWithReadWriteManyPVC),
|
nodeInfo: framework.NewNodeInfo(podWithTwoPVCs, podWithReadWriteManyPVC),
|
||||||
existingPods: []*v1.Pod{podWithOnePVC, podWithReadWriteManyPVC},
|
existingPods: []*v1.Pod{podWithTwoPVCs, podWithReadWriteManyPVC},
|
||||||
existingNodes: []*v1.Node{node},
|
existingNodes: []*v1.Node{node},
|
||||||
existingPVCs: []*v1.PersistentVolumeClaim{readWriteOncePodPVC1, readWriteManyPVC},
|
existingPVCs: []*v1.PersistentVolumeClaim{readWriteOncePodPVC1, readWriteOncePodPVC2, readWriteManyPVC},
|
||||||
enableReadWriteOncePod: true,
|
preFilterWantStatus: nil,
|
||||||
preFilterWantStatus: nil,
|
wantStatus: framework.NewStatus(framework.Unschedulable, ErrReasonReadWriteOncePodConflict),
|
||||||
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),
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -483,7 +461,7 @@ func TestAccessModeConflicts(t *testing.T) {
|
|||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
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()
|
cycleState := framework.NewCycleState()
|
||||||
_, preFilterGotStatus := p.(framework.PreFilterPlugin).PreFilter(ctx, cycleState, test.pod)
|
_, preFilterGotStatus := p.(framework.PreFilterPlugin).PreFilter(ctx, cycleState, test.pod)
|
||||||
if diff := cmp.Diff(test.preFilterWantStatus, preFilterGotStatus); diff != "" {
|
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 {
|
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) {
|
pluginFactory := func(ctx context.Context, plArgs runtime.Object, fh framework.Handle) (framework.Plugin, error) {
|
||||||
return New(ctx, plArgs, fh, feature.Features{
|
return New(ctx, plArgs, fh, feature.Features{})
|
||||||
EnableReadWriteOncePod: enableReadWriteOncePod,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
snapshot := cache.NewSnapshot(pods, nodes)
|
snapshot := cache.NewSnapshot(pods, nodes)
|
||||||
|
|
||||||
|
@ -370,7 +370,6 @@ func TestPluginConstructVolumeSpec(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
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)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, tc.seLinuxMountEnabled)()
|
||||||
|
|
||||||
mounter, err := plug.NewMounter(
|
mounter, err := plug.NewMounter(
|
||||||
|
@ -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.
|
// Enforce ReadWriteOncePod access mode if it is the only one present. This is also enforced during scheduling.
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.ReadWriteOncePod) &&
|
if actualStateOfWorld.IsVolumeMountedElsewhere(volumeToMount.VolumeName, volumeToMount.PodName) &&
|
||||||
actualStateOfWorld.IsVolumeMountedElsewhere(volumeToMount.VolumeName, volumeToMount.PodName) &&
|
|
||||||
// Because we do not know what access mode the pod intends to use if there are multiple.
|
// Because we do not know what access mode the pod intends to use if there are multiple.
|
||||||
len(volumeToMount.VolumeSpec.PersistentVolume.Spec.AccessModes) == 1 &&
|
len(volumeToMount.VolumeSpec.PersistentVolume.Spec.AccessModes) == 1 &&
|
||||||
v1helper.ContainsAccessMode(volumeToMount.VolumeSpec.PersistentVolume.Spec.AccessModes, v1.ReadWriteOncePod) {
|
v1helper.ContainsAccessMode(volumeToMount.VolumeSpec.PersistentVolume.Spec.AccessModes, v1.ReadWriteOncePod) {
|
||||||
@ -1071,8 +1070,7 @@ func (og *operationGenerator) GenerateMapVolumeFunc(
|
|||||||
migrated := getMigratedStatusBySpec(volumeToMount.VolumeSpec)
|
migrated := getMigratedStatusBySpec(volumeToMount.VolumeSpec)
|
||||||
|
|
||||||
// Enforce ReadWriteOncePod access mode. This is also enforced during scheduling.
|
// Enforce ReadWriteOncePod access mode. This is also enforced during scheduling.
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.ReadWriteOncePod) &&
|
if actualStateOfWorld.IsVolumeMountedElsewhere(volumeToMount.VolumeName, volumeToMount.PodName) &&
|
||||||
actualStateOfWorld.IsVolumeMountedElsewhere(volumeToMount.VolumeName, volumeToMount.PodName) &&
|
|
||||||
// Because we do not know what access mode the pod intends to use if there are multiple.
|
// Because we do not know what access mode the pod intends to use if there are multiple.
|
||||||
len(volumeToMount.VolumeSpec.PersistentVolume.Spec.AccessModes) == 1 &&
|
len(volumeToMount.VolumeSpec.PersistentVolume.Spec.AccessModes) == 1 &&
|
||||||
v1helper.ContainsAccessMode(volumeToMount.VolumeSpec.PersistentVolume.Spec.AccessModes, v1.ReadWriteOncePod) {
|
v1helper.ContainsAccessMode(volumeToMount.VolumeSpec.PersistentVolume.Spec.AccessModes, v1.ReadWriteOncePod) {
|
||||||
|
@ -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.
|
// VolumeSupportsSELinuxMount returns true if given volume access mode can support mount with SELinux mount options.
|
||||||
func VolumeSupportsSELinuxMount(volumeSpec *volume.Spec) bool {
|
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) {
|
if !utilfeature.DefaultFeatureGate.Enabled(features.SELinuxMountReadWriteOncePod) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -616,7 +616,6 @@ func TestMakeAbsolutePath(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetPodVolumeNames(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)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, true)()
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
@ -1554,11 +1554,10 @@ var (
|
|||||||
|
|
||||||
func TestUnschedulablePodBecomesSchedulable(t *testing.T) {
|
func TestUnschedulablePodBecomesSchedulable(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
init func(kubernetes.Interface, string) error
|
init func(kubernetes.Interface, string) error
|
||||||
pod *testutils.PausePodConfig
|
pod *testutils.PausePodConfig
|
||||||
update func(kubernetes.Interface, string) error
|
update func(kubernetes.Interface, string) error
|
||||||
enableReadWriteOncePod bool
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "node gets added",
|
name: "node gets added",
|
||||||
@ -1765,13 +1764,10 @@ func TestUnschedulablePodBecomesSchedulable(t *testing.T) {
|
|||||||
update: func(cs kubernetes.Interface, ns string) error {
|
update: func(cs kubernetes.Interface, ns string) error {
|
||||||
return deletePod(cs, "pod-to-be-deleted", ns)
|
return deletePod(cs, "pod-to-be-deleted", ns)
|
||||||
},
|
},
|
||||||
enableReadWriteOncePod: true,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ReadWriteOncePod, tt.enableReadWriteOncePod)()
|
|
||||||
|
|
||||||
testCtx := initTest(t, "scheduler-informer")
|
testCtx := initTest(t, "scheduler-informer")
|
||||||
|
|
||||||
if tt.init != nil {
|
if tt.init != nil {
|
||||||
|
@ -1648,8 +1648,6 @@ func TestPreferNominatedNode(t *testing.T) {
|
|||||||
// TestReadWriteOncePodPreemption tests preemption scenarios for pods with
|
// TestReadWriteOncePodPreemption tests preemption scenarios for pods with
|
||||||
// ReadWriteOncePod PVCs.
|
// ReadWriteOncePod PVCs.
|
||||||
func TestReadWriteOncePodPreemption(t *testing.T) {
|
func TestReadWriteOncePodPreemption(t *testing.T) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, features.ReadWriteOncePod, true)()
|
|
||||||
|
|
||||||
cfg := configtesting.V1ToInternalWithDefaults(t, configv1.KubeSchedulerConfiguration{
|
cfg := configtesting.V1ToInternalWithDefaults(t, configv1.KubeSchedulerConfiguration{
|
||||||
Profiles: []configv1.KubeSchedulerProfile{{
|
Profiles: []configv1.KubeSchedulerProfile{{
|
||||||
SchedulerName: pointer.StringPtr(v1.DefaultSchedulerName),
|
SchedulerName: pointer.StringPtr(v1.DefaultSchedulerName),
|
||||||
|
Loading…
Reference in New Issue
Block a user