When implementing feature-gated fields, always preserve existing field values when the feature gate is disabled, but drop new field values that depend on disabled features. This prevents breaking existing functionality during feature gate transitions or version skew scenarios.
When implementing feature-gated fields, always preserve existing field values when the feature gate is disabled, but drop new field values that depend on disabled features. This prevents breaking existing functionality during feature gate transitions or version skew scenarios.
Key principles:
DefaultFeatureGate.Enabled()
callsExample implementation:
func dropDisabledDRAFields(newSlice, oldSlice *resource.ResourceSlice) {
// Check if feature is enabled OR was already in use
if utilfeature.DefaultFeatureGate.Enabled(features.DRANewFeature) ||
draNewFeatureInUse(oldSlice) {
return
}
// Only drop fields if not previously used
for i := range newSlice.Spec.Devices {
newSlice.Spec.Devices[i].NewFeatureField = nil
}
}
// Separate validation for new features
if !utilfeature.DefaultFeatureGate.Enabled(features.DRANewFeature) &&
!newFeatureInUse(oldPodSpec, oldPodStatus) {
// Drop new feature fields
dropNewFeatureFields(podSpec)
}
This approach ensures backward compatibility, prevents data loss during upgrades/downgrades, and maintains clean separation between feature-gated and stable functionality.
Enter the URL of a public GitHub repository