Change:
<!-- Please use this template while reporting a bug and provide as much info as possible. Not doing so may result in your bug not being addressed in a timely manner. Thanks! If the matter is security related, please disclose it privately via --What happened: While glancing through storage , I noticed that we were doing feature gate checking in validation for CSI inline migration. At first glance, I think this will cause validation errors when downgrading to a version with the feature disabled. What you expected to happen: We generally don't do feature gate checking in validation in order to support downgrade cases. How to reproduce it (as minimally and precisely as possible): Anything else we need to know?: Environment: Kubernetes version (use ): Cloud provider or hardware configuration: OS (e.g: ): Kernel (e.g. ): Install tools: Network plugin and version (if this is a network-related bug): Others:
/assign cc
In validateVolumeAttachmentSource : If we don't check feature gate, it seems source.InlineVolumeSpec != nil case can be dropped. Otherwise:
These were based on presence of other feature-gate validation like . Now it makes sense to align with their removal/being made unconditional as well. There are a couple of instances of feature-gate checking in validation in non-storage areas as well: and . I assume those will be changed to unconditional too?
/cc for other identified features that may share this issue.
I wonder if this PR from has already corrected the fallback problem.
Both SCTPSupport (in ) and HPAScaleToZero (in the PR where it was introduced) ensure existing objects with feature-gated data are still considered valid even when the feature gate is disabled. This is a particularly fragile/nuanced area of the project. I'm working on a comprehensive way to tag fields as alpha and exercise the following cases in integration tests to ensure we don't regress: feature enabled creating object with alpha data is allowed and persisted creating object without alpha data is allowed and persisted update existing object without alpha data to one with alpha data is allowed and persisted (for objects that allow mutation) update existing object with alpha data to one without alpha data is allowed and persisted (for objects that allow mutation) feature disabled creating object with alpha data is either rejected or persisted without the alpha data creating object without alpha data is allowed and persisted update existing object without alpha data to one with alpha data is either rejected or persisted without alpha data (for objects that allow mutation) update existing object with alpha data to one without alpha data is allowed and persisted (for objects that allow mutation)

Discussion:
allErrs = append(allErrs, field.Required(fldPath.Child("persistentVolumeName"), "must specify non empty persistentVolumeName")) } case source.InlineVolumeSpec != nil: <del> if utilfeature.DefaultFeatureGate.Enabled(features.CSIMigration) { allErrs = append(allErrs, storagevalidation.ValidatePersistentVolumeSpec(source.InlineVolumeSpec, "", true, fldPath.Child("inlineVolumeSpec"))...) } else { allErrs = append(allErrs, field.Forbidden(fldPath, "may not specify inlineVolumeSpec when CSIMigration feature is disabled")) } </del> <ins> allErrs = append(allErrs, storagevalidation.ValidatePersistentVolumeSpec(source.InlineVolumeSpec, "", true, fldPath.Child("inlineVolumeSpec"))...) </ins> } return allErrs }

}, }, }, <del> } for _, volumeAttachment := range migrationDisabledSuccessCases { if errs := ValidateVolumeAttachment(&volumeAttachment); len(errs) != 0 { t.Errorf("expected success: %v %v", volumeAttachment, errs) } } migrationDisabledErrorCases := []storage.VolumeAttachment{ </del> { // InlineSpec specified with migration disabled ObjectMeta: metav1.ObjectMeta{Name: "foo"},

}, }, } <del> for _, volumeAttachment := range migrationDisabledErrorCases { if errs := ValidateVolumeAttachment(&volumeAttachment); len(errs) == 0 { t.Errorf("expected failure: %v %v", volumeAttachment, errs) </del> <ins> for _, volumeAttachment := range migrationDisabledSuccessCases { if errs := ValidateVolumeAttachment(&volumeAttachment); len(errs) != 0 { t.Errorf("expected success: %v %v", volumeAttachment, errs) </ins> } } } func TestVolumeAttachmentUpdateValidation(t *testing.T) {