mirror of
https://github.com/kubernetes/kubernetes.git
synced 2026-02-03 20:40:26 -05:00
Record and require all kube-feature dependencies
This commit is contained in:
parent
4870d987d0
commit
36e3a8f269
5 changed files with 390 additions and 39 deletions
|
|
@ -41,19 +41,4 @@ if [[ -n "${direct_sets}" ]]; then
|
|||
rc=1
|
||||
fi
|
||||
|
||||
export LC_ALL=C
|
||||
# ensure all generic features are added in alphabetic order
|
||||
lines=$(git grep 'genericfeatures[.].*:' -- pkg/features/kube_features.go)
|
||||
sorted_lines=$(echo "$lines" | sort)
|
||||
if [[ "$lines" != "$sorted_lines" ]]; then
|
||||
echo "Generic features in pkg/features/kube_features.go not sorted" >&2
|
||||
echo >&2
|
||||
echo "Expected:" >&2
|
||||
echo "$sorted_lines" >&2
|
||||
echo >&2
|
||||
echo "Got:" >&2
|
||||
echo "$lines" >&2
|
||||
rc=1
|
||||
fi
|
||||
|
||||
exit $rc
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ import (
|
|||
"strings"
|
||||
|
||||
apiextensionsapiserver "k8s.io/apiextensions-apiserver/pkg/apiserver"
|
||||
genericfeatures "k8s.io/apiserver/pkg/features"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
aggregatorscheme "k8s.io/kube-aggregator/pkg/apiserver/scheme"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
|
|
@ -71,20 +70,6 @@ func validateAPIPriorityAndFairness(options *Options) []error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func validateNodeSelectorAuthorizationFeature() []error {
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.AuthorizeNodeWithSelectors) && !utilfeature.DefaultFeatureGate.Enabled(genericfeatures.AuthorizeWithSelectors) {
|
||||
return []error{fmt.Errorf("AuthorizeNodeWithSelectors feature requires AuthorizeWithSelectors feature to be enabled")}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validatePodCertificateRequestFeature() []error {
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.PodCertificateRequest) && !utilfeature.DefaultFeatureGate.Enabled(features.AuthorizeNodeWithSelectors) {
|
||||
return []error{fmt.Errorf("PodCertificateRequest feature requires AuthorizeNodeWithSelectors feature to be enabled")}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateUnknownVersionInteroperabilityProxyFlags(options *Options) []error {
|
||||
err := []error{}
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.UnknownVersionInteroperabilityProxy) {
|
||||
|
|
@ -151,8 +136,6 @@ func (s *Options) Validate() []error {
|
|||
errs = append(errs, validateTokenRequest(s)...)
|
||||
errs = append(errs, s.Metrics.Validate()...)
|
||||
errs = append(errs, validateUnknownVersionInteroperabilityProxyFlags(s)...)
|
||||
errs = append(errs, validateNodeSelectorAuthorizationFeature()...)
|
||||
errs = append(errs, validatePodCertificateRequestFeature()...)
|
||||
errs = append(errs, validateServiceAccountTokenSigningConfig(s)...)
|
||||
errs = append(errs, validateCoordinatedLeadershipFlags(s)...)
|
||||
|
||||
|
|
|
|||
|
|
@ -1999,10 +1999,387 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate
|
|||
//
|
||||
// Entries are alphabetized.
|
||||
var defaultKubernetesFeatureGateDependencies = map[featuregate.Feature][]featuregate.Feature{
|
||||
DisableAllocatorDualWrite: {MultiCIDRServiceAllocator},
|
||||
AllowDNSOnlyNodeCSR: {},
|
||||
|
||||
AllowInsecureKubeletCertificateSigningRequests: {},
|
||||
|
||||
AllowOverwriteTerminationGracePeriodSeconds: {},
|
||||
|
||||
AllowServiceLBStatusOnNonLB: {},
|
||||
|
||||
AnyVolumeDataSource: {},
|
||||
|
||||
AuthorizeNodeWithSelectors: {genericfeatures.AuthorizeWithSelectors},
|
||||
|
||||
CPUCFSQuotaPeriod: {},
|
||||
|
||||
CPUManagerPolicyAlphaOptions: {},
|
||||
|
||||
CPUManagerPolicyBetaOptions: {},
|
||||
|
||||
CPUManagerPolicyOptions: {},
|
||||
|
||||
CSIMigrationPortworx: {},
|
||||
|
||||
CSIVolumeHealth: {},
|
||||
|
||||
ClearingNominatedNodeNameAfterBinding: {},
|
||||
|
||||
ClusterTrustBundle: {},
|
||||
|
||||
ClusterTrustBundleProjection: {ClusterTrustBundle},
|
||||
|
||||
ContainerCheckpoint: {},
|
||||
|
||||
ContainerRestartRules: {},
|
||||
|
||||
ContainerStopSignals: {},
|
||||
|
||||
CoordinatedLeaderElection: {},
|
||||
|
||||
CrossNamespaceVolumeDataSource: {},
|
||||
|
||||
DRAAdminAccess: {DynamicResourceAllocation},
|
||||
|
||||
DRAConsumableCapacity: {DynamicResourceAllocation},
|
||||
|
||||
DRADeviceBindingConditions: {DynamicResourceAllocation, DRAResourceClaimDeviceStatus},
|
||||
|
||||
DRADeviceTaints: {DynamicResourceAllocation},
|
||||
|
||||
DRAExtendedResource: {DynamicResourceAllocation},
|
||||
|
||||
DRAPartitionableDevices: {DynamicResourceAllocation},
|
||||
|
||||
DRAPrioritizedList: {DynamicResourceAllocation},
|
||||
|
||||
DRAResourceClaimDeviceStatus: {}, // Soft dependency on DynamicResourceAllocation due to on/off-by-default conflict.
|
||||
|
||||
DRASchedulerFilterTimeout: {DynamicResourceAllocation},
|
||||
|
||||
DeploymentReplicaSetTerminatingReplicas: {},
|
||||
|
||||
DisableAllocatorDualWrite: {MultiCIDRServiceAllocator},
|
||||
|
||||
DisableCPUQuotaWithExclusiveCPUs: {},
|
||||
|
||||
DisableNodeKubeProxyVersion: {},
|
||||
|
||||
DynamicResourceAllocation: {},
|
||||
|
||||
EnvFiles: {},
|
||||
|
||||
EventedPLEG: {},
|
||||
|
||||
ExecProbeTimeout: {},
|
||||
|
||||
ExternalServiceAccountTokenSigner: {},
|
||||
|
||||
GitRepoVolumeDriver: {},
|
||||
|
||||
GracefulNodeShutdown: {},
|
||||
|
||||
GracefulNodeShutdownBasedOnPodPriority: {GracefulNodeShutdown},
|
||||
|
||||
HPAConfigurableTolerance: {},
|
||||
|
||||
HPAScaleToZero: {},
|
||||
|
||||
HonorPVReclaimPolicy: {},
|
||||
|
||||
HostnameOverride: {},
|
||||
|
||||
ImageMaximumGCAge: {},
|
||||
|
||||
ImageVolume: {},
|
||||
|
||||
InPlacePodVerticalScaling: {},
|
||||
|
||||
InPlacePodVerticalScalingAllocatedStatus: {InPlacePodVerticalScaling},
|
||||
InPlacePodVerticalScalingExclusiveCPUs: {InPlacePodVerticalScaling},
|
||||
|
||||
InPlacePodVerticalScalingExclusiveCPUs: {InPlacePodVerticalScaling},
|
||||
|
||||
InPlacePodVerticalScalingExclusiveMemory: {InPlacePodVerticalScaling, MemoryManager},
|
||||
|
||||
InTreePluginPortworxUnregister: {},
|
||||
|
||||
JobBackoffLimitPerIndex: {},
|
||||
|
||||
JobManagedBy: {},
|
||||
|
||||
JobPodReplacementPolicy: {},
|
||||
|
||||
JobSuccessPolicy: {},
|
||||
|
||||
KubeletCgroupDriverFromCRI: {},
|
||||
|
||||
KubeletCrashLoopBackOffMax: {},
|
||||
|
||||
KubeletEnsureSecretPulledImages: {},
|
||||
|
||||
KubeletFineGrainedAuthz: {},
|
||||
|
||||
KubeletInUserNamespace: {},
|
||||
|
||||
KubeletPSI: {},
|
||||
|
||||
KubeletPodResourcesDynamicResources: {},
|
||||
|
||||
KubeletPodResourcesGet: {},
|
||||
|
||||
KubeletPodResourcesListUseActivePods: {},
|
||||
|
||||
KubeletRegistrationGetOnExistsOnly: {},
|
||||
|
||||
KubeletSeparateDiskGC: {},
|
||||
|
||||
KubeletServiceAccountTokenForCredentialProviders: {},
|
||||
|
||||
KubeletTracing: {},
|
||||
|
||||
LoadBalancerIPMode: {},
|
||||
|
||||
LocalStorageCapacityIsolationFSQuotaMonitoring: {},
|
||||
|
||||
LogarithmicScaleDown: {},
|
||||
|
||||
MatchLabelKeysInPodAffinity: {},
|
||||
|
||||
MatchLabelKeysInPodTopologySpread: {},
|
||||
|
||||
MatchLabelKeysInPodTopologySpreadSelectorMerge: {MatchLabelKeysInPodTopologySpread},
|
||||
|
||||
MaxUnavailableStatefulSet: {},
|
||||
|
||||
MemoryManager: {},
|
||||
|
||||
MemoryQoS: {},
|
||||
|
||||
MultiCIDRServiceAllocator: {},
|
||||
|
||||
MutableCSINodeAllocatableCount: {},
|
||||
|
||||
NFTablesProxyMode: {},
|
||||
|
||||
NodeInclusionPolicyInPodTopologySpread: {},
|
||||
|
||||
NodeLogQuery: {},
|
||||
|
||||
NodeSwap: {},
|
||||
|
||||
NominatedNodeNameForExpectation: {},
|
||||
|
||||
OrderedNamespaceDeletion: {},
|
||||
|
||||
PodAndContainerStatsFromCRI: {},
|
||||
|
||||
PodCertificateRequest: {AuthorizeNodeWithSelectors},
|
||||
|
||||
PodDeletionCost: {},
|
||||
|
||||
PodLevelResources: {},
|
||||
|
||||
PodLifecycleSleepAction: {},
|
||||
|
||||
PodLifecycleSleepActionAllowZero: {PodLifecycleSleepAction},
|
||||
|
||||
PodLogsQuerySplitStreams: {},
|
||||
|
||||
PodObservedGenerationTracking: {},
|
||||
|
||||
PodReadyToStartContainersCondition: {},
|
||||
|
||||
PodSchedulingReadiness: {},
|
||||
|
||||
PodTopologyLabelsAdmission: {},
|
||||
|
||||
PortForwardWebsockets: {},
|
||||
|
||||
PreferSameTrafficDistribution: {},
|
||||
|
||||
PreventStaticPodAPIReferences: {},
|
||||
|
||||
ProcMountType: {UserNamespacesSupport},
|
||||
|
||||
QOSReserved: {},
|
||||
|
||||
RecoverVolumeExpansionFailure: {},
|
||||
|
||||
RecursiveReadOnlyMounts: {},
|
||||
|
||||
ReduceDefaultCrashLoopBackOffDecay: {},
|
||||
|
||||
RelaxedDNSSearchValidation: {},
|
||||
|
||||
RelaxedEnvironmentVariableValidation: {},
|
||||
|
||||
RelaxedServiceNameValidation: {},
|
||||
|
||||
ReloadKubeletServerCertificateFile: {},
|
||||
|
||||
ResourceHealthStatus: {DynamicResourceAllocation},
|
||||
|
||||
RotateKubeletServerCertificate: {},
|
||||
|
||||
RuntimeClassInImageCriAPI: {},
|
||||
|
||||
SELinuxChangePolicy: {},
|
||||
|
||||
SELinuxMount: {},
|
||||
|
||||
SELinuxMountReadWriteOncePod: {},
|
||||
|
||||
SchedulerAsyncAPICalls: {},
|
||||
|
||||
SchedulerAsyncPreemption: {},
|
||||
|
||||
SchedulerPopFromBackoffQ: {},
|
||||
|
||||
SchedulerQueueingHints: {},
|
||||
|
||||
SeparateTaintEvictionController: {},
|
||||
|
||||
ServiceAccountNodeAudienceRestriction: {},
|
||||
|
||||
ServiceAccountTokenJTI: {},
|
||||
|
||||
ServiceAccountTokenNodeBinding: {ServiceAccountTokenNodeBindingValidation},
|
||||
|
||||
ServiceAccountTokenNodeBindingValidation: {},
|
||||
|
||||
ServiceAccountTokenPodNodeInfo: {},
|
||||
|
||||
ServiceTrafficDistribution: {},
|
||||
|
||||
SidecarContainers: {},
|
||||
|
||||
StorageCapacityScoring: {},
|
||||
|
||||
StorageNamespaceIndex: {},
|
||||
|
||||
StorageVersionMigrator: {},
|
||||
|
||||
StreamingCollectionEncodingToJSON: {},
|
||||
|
||||
StreamingCollectionEncodingToProtobuf: {},
|
||||
|
||||
StrictIPCIDRValidation: {},
|
||||
|
||||
SupplementalGroupsPolicy: {},
|
||||
|
||||
SystemdWatchdog: {},
|
||||
|
||||
TopologyAwareHints: {},
|
||||
|
||||
TopologyManagerPolicyAlphaOptions: {},
|
||||
|
||||
TopologyManagerPolicyBetaOptions: {},
|
||||
|
||||
TopologyManagerPolicyOptions: {},
|
||||
|
||||
TranslateStreamCloseWebsocketRequests: {},
|
||||
|
||||
UnknownVersionInteroperabilityProxy: {},
|
||||
|
||||
UserNamespacesPodSecurityStandards: {},
|
||||
|
||||
UserNamespacesSupport: {},
|
||||
|
||||
VolumeAttributesClass: {},
|
||||
|
||||
WinDSR: {},
|
||||
|
||||
WinOverlay: {},
|
||||
|
||||
WindowsCPUAndMemoryAffinity: {MemoryManager},
|
||||
|
||||
WindowsGracefulNodeShutdown: {GracefulNodeShutdown},
|
||||
|
||||
WindowsHostNetwork: {},
|
||||
|
||||
apiextensionsfeatures.CRDValidationRatcheting: {},
|
||||
|
||||
apiextensionsfeatures.CustomResourceFieldSelectors: {},
|
||||
|
||||
genericfeatures.APIResponseCompression: {},
|
||||
|
||||
genericfeatures.APIServerIdentity: {},
|
||||
|
||||
genericfeatures.APIServerTracing: {},
|
||||
|
||||
genericfeatures.APIServingWithRoutine: {},
|
||||
|
||||
genericfeatures.AggregatedDiscoveryRemoveBetaType: {},
|
||||
|
||||
genericfeatures.AllowParsingUserUIDFromCertAuth: {},
|
||||
|
||||
genericfeatures.AllowUnsafeMalformedObjectDeletion: {},
|
||||
|
||||
genericfeatures.AnonymousAuthConfigurableEndpoints: {},
|
||||
|
||||
genericfeatures.AuthorizeWithSelectors: {},
|
||||
|
||||
genericfeatures.BtreeWatchCache: {},
|
||||
|
||||
genericfeatures.CBORServingAndStorage: {},
|
||||
|
||||
genericfeatures.ConcurrentWatchObjectDecode: {},
|
||||
|
||||
genericfeatures.ConsistentListFromCache: {},
|
||||
|
||||
genericfeatures.DeclarativeValidation: {},
|
||||
|
||||
genericfeatures.DeclarativeValidationTakeover: {genericfeatures.DeclarativeValidation},
|
||||
|
||||
genericfeatures.DetectCacheInconsistency: {},
|
||||
|
||||
genericfeatures.KMSv1: {},
|
||||
|
||||
genericfeatures.ListFromCacheSnapshot: {},
|
||||
|
||||
genericfeatures.MutatingAdmissionPolicy: {},
|
||||
|
||||
genericfeatures.OpenAPIEnums: {},
|
||||
|
||||
genericfeatures.RemoteRequestHeaderUID: {},
|
||||
|
||||
genericfeatures.ResilientWatchCacheInitialization: {},
|
||||
|
||||
genericfeatures.RetryGenerateName: {},
|
||||
|
||||
genericfeatures.SeparateCacheWatchRPC: {},
|
||||
|
||||
genericfeatures.SizeBasedListCostEstimate: {},
|
||||
|
||||
genericfeatures.StorageVersionAPI: {genericfeatures.APIServerIdentity},
|
||||
|
||||
genericfeatures.StorageVersionHash: {},
|
||||
|
||||
genericfeatures.StrictCostEnforcementForVAP: {},
|
||||
|
||||
genericfeatures.StrictCostEnforcementForWebhooks: {},
|
||||
|
||||
genericfeatures.StructuredAuthenticationConfiguration: {},
|
||||
|
||||
genericfeatures.StructuredAuthenticationConfigurationEgressSelector: {genericfeatures.StructuredAuthenticationConfiguration},
|
||||
|
||||
genericfeatures.StructuredAuthorizationConfiguration: {},
|
||||
|
||||
genericfeatures.TokenRequestServiceAccountUIDValidation: {},
|
||||
|
||||
genericfeatures.UnauthenticatedHTTP2DOSMitigation: {},
|
||||
|
||||
genericfeatures.WatchCacheInitializationPostStartHook: {},
|
||||
|
||||
genericfeatures.WatchFromStorageWithoutResourceVersion: {},
|
||||
|
||||
genericfeatures.WatchList: {},
|
||||
|
||||
kcmfeatures.CloudControllerManagerWebhook: {},
|
||||
|
||||
zpagesfeatures.ComponentFlagz: {},
|
||||
|
||||
zpagesfeatures.ComponentStatusz: {},
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ limitations under the License.
|
|||
package features
|
||||
|
||||
import (
|
||||
"maps"
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
|
|
@ -91,3 +93,12 @@ func TestEnsureAlphaGatesAreNotSwitchedOnByDefault(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAllDependenciesRegistered(t *testing.T) {
|
||||
registeredDependencies := utilfeature.DefaultFeatureGate.Dependencies()
|
||||
for _, f := range slices.Sorted(maps.Keys(defaultVersionedKubernetesFeatureGates)) {
|
||||
if _, depsRegistered := registeredDependencies[f]; !depsRegistered {
|
||||
t.Errorf("Feature %s did not register dependencies. All features must record explicit feature dependencies, even if there are none.", f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -295,11 +295,6 @@ func (o *BuiltInAuthenticationOptions) Validate() []error {
|
|||
}
|
||||
}
|
||||
|
||||
// verify that if ServiceAccountTokenNodeBinding is enabled, ServiceAccountTokenNodeBindingValidation is also enabled.
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.ServiceAccountTokenNodeBinding) && !utilfeature.DefaultFeatureGate.Enabled(features.ServiceAccountTokenNodeBindingValidation) {
|
||||
allErrors = append(allErrors, fmt.Errorf("the %q feature gate can only be enabled if the %q feature gate is also enabled", features.ServiceAccountTokenNodeBinding, features.ServiceAccountTokenNodeBindingValidation))
|
||||
}
|
||||
|
||||
if o.WebHook != nil {
|
||||
retryBackoff := o.WebHook.RetryBackoff
|
||||
if retryBackoff != nil && retryBackoff.Steps <= 0 {
|
||||
|
|
|
|||
Loading…
Reference in a new issue