diff --git a/pkg/controlplane/apiserver/config.go b/pkg/controlplane/apiserver/config.go index 7a1b42ee127..a22a0cb503e 100644 --- a/pkg/controlplane/apiserver/config.go +++ b/pkg/controlplane/apiserver/config.go @@ -231,9 +231,7 @@ func BuildGenericConfig( return } - if utilfeature.DefaultFeatureGate.Enabled(genericfeatures.AggregatedDiscoveryEndpoint) { - genericConfig.AggregatedDiscoveryGroupManager = aggregated.NewResourceManager("apis") - } + genericConfig.AggregatedDiscoveryGroupManager = aggregated.NewResourceManager("apis") return } diff --git a/pkg/features/versioned_kube_features.go b/pkg/features/versioned_kube_features.go index 9a9e1e7cd0b..e43eb5132b4 100644 --- a/pkg/features/versioned_kube_features.go +++ b/pkg/features/versioned_kube_features.go @@ -204,12 +204,6 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate {Version: version.MustParse("1.30"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, }, - genericfeatures.AggregatedDiscoveryEndpoint: { - {Version: version.MustParse("1.26"), Default: false, PreRelease: featuregate.Alpha}, - {Version: version.MustParse("1.27"), Default: true, PreRelease: featuregate.Beta}, - {Version: version.MustParse("1.30"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, - }, - genericfeatures.AllowParsingUserUIDFromCertAuth: { {Version: version.MustParse("1.33"), Default: true, PreRelease: featuregate.Beta}, }, diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/discovery/aggregated/wrapper.go b/staging/src/k8s.io/apiserver/pkg/endpoints/discovery/aggregated/wrapper.go index 25fe90fa4ba..c9f0907e7d1 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/discovery/aggregated/wrapper.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/discovery/aggregated/wrapper.go @@ -28,8 +28,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/endpoints/handlers/negotiation" - genericfeatures "k8s.io/apiserver/pkg/features" - utilfeature "k8s.io/apiserver/pkg/util/feature" ) type WrappedHandler struct { @@ -39,13 +37,11 @@ type WrappedHandler struct { } func (wrapped *WrappedHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) { - if utilfeature.DefaultFeatureGate.Enabled(genericfeatures.AggregatedDiscoveryEndpoint) { - mediaType, _ := negotiation.NegotiateMediaTypeOptions(req.Header.Get("Accept"), wrapped.s.SupportedMediaTypes(), DiscoveryEndpointRestrictions) - // mediaType.Convert looks at the request accept headers and is used to control whether the discovery document will be aggregated. - if IsAggregatedDiscoveryGVK(mediaType.Convert) { - wrapped.aggHandler.ServeHTTP(resp, req) - return - } + mediaType, _ := negotiation.NegotiateMediaTypeOptions(req.Header.Get("Accept"), wrapped.s.SupportedMediaTypes(), DiscoveryEndpointRestrictions) + // mediaType.Convert looks at the request accept headers and is used to control whether the discovery document will be aggregated. + if IsAggregatedDiscoveryGVK(mediaType.Convert) { + wrapped.aggHandler.ServeHTTP(resp, req) + return } wrapped.handler.ServeHTTP(resp, req) } diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/discovery/aggregated/wrapper_test.go b/staging/src/k8s.io/apiserver/pkg/endpoints/discovery/aggregated/wrapper_test.go index 3db842afbaf..91071b6470e 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/discovery/aggregated/wrapper_test.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/discovery/aggregated/wrapper_test.go @@ -24,9 +24,6 @@ import ( "testing" "github.com/stretchr/testify/assert" - genericfeatures "k8s.io/apiserver/pkg/features" - utilfeature "k8s.io/apiserver/pkg/util/feature" - featuregatetesting "k8s.io/component-base/featuregate/testing" ) const discoveryPath = "/apis" @@ -60,8 +57,6 @@ func (f fakeHTTPHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) } func TestAggregationEnabled(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.AggregatedDiscoveryEndpoint, true) - unaggregated := fakeHTTPHandler{data: "unaggregated"} aggregated := fakeHTTPHandler{data: "aggregated"} wrapped := WrapAggregatedDiscoveryToHandler(unaggregated, aggregated) diff --git a/staging/src/k8s.io/apiserver/pkg/features/kube_features.go b/staging/src/k8s.io/apiserver/pkg/features/kube_features.go index 4b731f1d256..fce29818868 100644 --- a/staging/src/k8s.io/apiserver/pkg/features/kube_features.go +++ b/staging/src/k8s.io/apiserver/pkg/features/kube_features.go @@ -41,13 +41,6 @@ const ( // Enables usage of MatchConditions fields to use CEL expressions for matching on admission webhooks AdmissionWebhookMatchConditions featuregate.Feature = "AdmissionWebhookMatchConditions" - // owner: @jefftree @alexzielenski - // stable: v1.30 - // - // Enables an single HTTP endpoint /discovery/ which supports native HTTP - // caching with ETags containing all APIResources known to the apiserver. - AggregatedDiscoveryEndpoint featuregate.Feature = "AggregatedDiscoveryEndpoint" - // owner: @modulitos // // Allow user.DefaultInfo.UID to be set from x509 cert during cert auth. @@ -266,12 +259,6 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate {Version: version.MustParse("1.30"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, }, - AggregatedDiscoveryEndpoint: { - {Version: version.MustParse("1.26"), Default: false, PreRelease: featuregate.Alpha}, - {Version: version.MustParse("1.27"), Default: true, PreRelease: featuregate.Beta}, - {Version: version.MustParse("1.30"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, - }, - AllowParsingUserUIDFromCertAuth: { {Version: version.MustParse("1.33"), Default: true, PreRelease: featuregate.Beta}, }, diff --git a/staging/src/k8s.io/apiserver/pkg/server/config.go b/staging/src/k8s.io/apiserver/pkg/server/config.go index 9e9bf4e3d20..c2f88594832 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/config.go +++ b/staging/src/k8s.io/apiserver/pkg/server/config.go @@ -845,14 +845,12 @@ func (c completedConfig) New(name string, delegationTarget DelegationTarget) (*G muxAndDiscoveryCompleteSignals: map[string]<-chan struct{}{}, } - if c.FeatureGate.Enabled(genericfeatures.AggregatedDiscoveryEndpoint) { - manager := c.AggregatedDiscoveryGroupManager - if manager == nil { - manager = discoveryendpoint.NewResourceManager("apis") - } - s.AggregatedDiscoveryGroupManager = manager - s.AggregatedLegacyDiscoveryGroupManager = discoveryendpoint.NewResourceManager("api") + manager := c.AggregatedDiscoveryGroupManager + if manager == nil { + manager = discoveryendpoint.NewResourceManager("apis") } + s.AggregatedDiscoveryGroupManager = manager + s.AggregatedLegacyDiscoveryGroupManager = discoveryendpoint.NewResourceManager("api") for { if c.JSONPatchMaxCopyBytes <= 0 { break @@ -1111,12 +1109,8 @@ func installAPI(name string, s *GenericAPIServer, c *Config) { routes.Version{Version: c.EffectiveVersion.BinaryVersion().Info()}.Install(s.Handler.GoRestfulContainer) if c.EnableDiscovery { - if c.FeatureGate.Enabled(genericfeatures.AggregatedDiscoveryEndpoint) { - wrapped := discoveryendpoint.WrapAggregatedDiscoveryToHandler(s.DiscoveryGroupManager, s.AggregatedDiscoveryGroupManager) - s.Handler.GoRestfulContainer.Add(wrapped.GenerateWebService("/apis", metav1.APIGroupList{})) - } else { - s.Handler.GoRestfulContainer.Add(s.DiscoveryGroupManager.WebService()) - } + wrapped := discoveryendpoint.WrapAggregatedDiscoveryToHandler(s.DiscoveryGroupManager, s.AggregatedDiscoveryGroupManager) + s.Handler.GoRestfulContainer.Add(wrapped.GenerateWebService("/apis", metav1.APIGroupList{})) } if c.FlowControl != nil { c.FlowControl.Install(s.Handler.NonGoRestfulMux) diff --git a/staging/src/k8s.io/apiserver/pkg/server/genericapiserver.go b/staging/src/k8s.io/apiserver/pkg/server/genericapiserver.go index 82b9df9441b..c2d9f5c5ba0 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/genericapiserver.go +++ b/staging/src/k8s.io/apiserver/pkg/server/genericapiserver.go @@ -785,28 +785,26 @@ func (s *GenericAPIServer) installAPIResources(apiPrefix string, apiGroupInfo *A } resourceInfos = append(resourceInfos, r...) - if s.FeatureGate.Enabled(features.AggregatedDiscoveryEndpoint) { - // Aggregated discovery only aggregates resources under /apis - if apiPrefix == APIGroupPrefix { - s.AggregatedDiscoveryGroupManager.AddGroupVersion( - groupVersion.Group, - apidiscoveryv2.APIVersionDiscovery{ - Freshness: apidiscoveryv2.DiscoveryFreshnessCurrent, - Version: groupVersion.Version, - Resources: discoveryAPIResources, - }, - ) - } else { - // There is only one group version for legacy resources, priority can be defaulted to 0. - s.AggregatedLegacyDiscoveryGroupManager.AddGroupVersion( - groupVersion.Group, - apidiscoveryv2.APIVersionDiscovery{ - Freshness: apidiscoveryv2.DiscoveryFreshnessCurrent, - Version: groupVersion.Version, - Resources: discoveryAPIResources, - }, - ) - } + // Aggregated discovery only aggregates resources under /apis + if apiPrefix == APIGroupPrefix { + s.AggregatedDiscoveryGroupManager.AddGroupVersion( + groupVersion.Group, + apidiscoveryv2.APIVersionDiscovery{ + Freshness: apidiscoveryv2.DiscoveryFreshnessCurrent, + Version: groupVersion.Version, + Resources: discoveryAPIResources, + }, + ) + } else { + // There is only one group version for legacy resources, priority can be defaulted to 0. + s.AggregatedLegacyDiscoveryGroupManager.AddGroupVersion( + groupVersion.Group, + apidiscoveryv2.APIVersionDiscovery{ + Freshness: apidiscoveryv2.DiscoveryFreshnessCurrent, + Version: groupVersion.Version, + Resources: discoveryAPIResources, + }, + ) } } @@ -844,12 +842,8 @@ func (s *GenericAPIServer) InstallLegacyAPIGroup(apiPrefix string, apiGroupInfo // Install the version handler. // Add a handler at / to enumerate the supported api versions. legacyRootAPIHandler := discovery.NewLegacyRootAPIHandler(s.discoveryAddresses, s.Serializer, apiPrefix) - if s.FeatureGate.Enabled(features.AggregatedDiscoveryEndpoint) { - wrapped := discoveryendpoint.WrapAggregatedDiscoveryToHandler(legacyRootAPIHandler, s.AggregatedLegacyDiscoveryGroupManager) - s.Handler.GoRestfulContainer.Add(wrapped.GenerateWebService("/api", metav1.APIVersions{})) - } else { - s.Handler.GoRestfulContainer.Add(legacyRootAPIHandler.WebService()) - } + wrapped := discoveryendpoint.WrapAggregatedDiscoveryToHandler(legacyRootAPIHandler, s.AggregatedLegacyDiscoveryGroupManager) + s.Handler.GoRestfulContainer.Add(wrapped.GenerateWebService("/api", metav1.APIVersions{})) s.registerStorageReadinessCheck("", apiGroupInfo) return nil diff --git a/staging/src/k8s.io/kube-aggregator/pkg/apiserver/apiserver.go b/staging/src/k8s.io/kube-aggregator/pkg/apiserver/apiserver.go index 62a8ef24fa3..a1fc88d7b7b 100644 --- a/staging/src/k8s.io/kube-aggregator/pkg/apiserver/apiserver.go +++ b/staging/src/k8s.io/kube-aggregator/pkg/apiserver/apiserver.go @@ -275,12 +275,8 @@ func (c completedConfig) NewWithDelegate(delegationTarget genericapiserver.Deleg discoveryGroup: discoveryGroup(enabledVersions), } - if utilfeature.DefaultFeatureGate.Enabled(genericfeatures.AggregatedDiscoveryEndpoint) { - apisHandlerWithAggregationSupport := aggregated.WrapAggregatedDiscoveryToHandler(apisHandler, s.GenericAPIServer.AggregatedDiscoveryGroupManager) - s.GenericAPIServer.Handler.NonGoRestfulMux.Handle("/apis", apisHandlerWithAggregationSupport) - } else { - s.GenericAPIServer.Handler.NonGoRestfulMux.Handle("/apis", apisHandler) - } + apisHandlerWithAggregationSupport := aggregated.WrapAggregatedDiscoveryToHandler(apisHandler, s.GenericAPIServer.AggregatedDiscoveryGroupManager) + s.GenericAPIServer.Handler.NonGoRestfulMux.Handle("/apis", apisHandlerWithAggregationSupport) s.GenericAPIServer.Handler.NonGoRestfulMux.UnlistedHandle("/apis/", apisHandler) apiserviceRegistrationController := NewAPIServiceRegistrationController(informerFactory.Apiregistration().V1().APIServices(), s) @@ -365,41 +361,39 @@ func (c completedConfig) NewWithDelegate(delegationTarget genericapiserver.Deleg return nil }) - if utilfeature.DefaultFeatureGate.Enabled(genericfeatures.AggregatedDiscoveryEndpoint) { - s.discoveryAggregationController = NewDiscoveryManager( - // Use aggregator as the source name to avoid overwriting native/CRD - // groups - s.GenericAPIServer.AggregatedDiscoveryGroupManager.WithSource(aggregated.AggregatorSource), - ) + s.discoveryAggregationController = NewDiscoveryManager( + // Use aggregator as the source name to avoid overwriting native/CRD + // groups + s.GenericAPIServer.AggregatedDiscoveryGroupManager.WithSource(aggregated.AggregatorSource), + ) - // Setup discovery endpoint - s.GenericAPIServer.AddPostStartHookOrDie("apiservice-discovery-controller", func(context genericapiserver.PostStartHookContext) error { - // Discovery aggregation depends on the apiservice registration controller - // having the full list of APIServices already synced - select { - case <-context.Done(): - return nil - // Context cancelled, should abort/clean goroutines - case <-apiServiceRegistrationControllerInitiated: - } - - // Run discovery manager's worker to watch for new/removed/updated - // APIServices to the discovery document can be updated at runtime - // When discovery is ready, all APIServices will be present, with APIServices - // that have not successfully synced discovery to be present but marked as Stale. - discoverySyncedCh := make(chan struct{}) - go s.discoveryAggregationController.Run(context.Done(), discoverySyncedCh) - - select { - case <-context.Done(): - return nil - // Context cancelled, should abort/clean goroutines - case <-discoverySyncedCh: - // API services successfully sync - } + // Setup discovery endpoint + s.GenericAPIServer.AddPostStartHookOrDie("apiservice-discovery-controller", func(context genericapiserver.PostStartHookContext) error { + // Discovery aggregation depends on the apiservice registration controller + // having the full list of APIServices already synced + select { + case <-context.Done(): return nil - }) - } + // Context cancelled, should abort/clean goroutines + case <-apiServiceRegistrationControllerInitiated: + } + + // Run discovery manager's worker to watch for new/removed/updated + // APIServices to the discovery document can be updated at runtime + // When discovery is ready, all APIServices will be present, with APIServices + // that have not successfully synced discovery to be present but marked as Stale. + discoverySyncedCh := make(chan struct{}) + go s.discoveryAggregationController.Run(context.Done(), discoverySyncedCh) + + select { + case <-context.Done(): + return nil + // Context cancelled, should abort/clean goroutines + case <-discoverySyncedCh: + // API services successfully sync + } + return nil + }) if utilfeature.DefaultFeatureGate.Enabled(genericfeatures.StorageVersionAPI) && utilfeature.DefaultFeatureGate.Enabled(genericfeatures.APIServerIdentity) { diff --git a/test/featuregates_linter/test_data/versioned_feature_list.yaml b/test/featuregates_linter/test_data/versioned_feature_list.yaml index 5206476a42e..8930f1a51a6 100644 --- a/test/featuregates_linter/test_data/versioned_feature_list.yaml +++ b/test/featuregates_linter/test_data/versioned_feature_list.yaml @@ -12,20 +12,6 @@ lockToDefault: true preRelease: GA version: "1.30" -- name: AggregatedDiscoveryEndpoint - versionedSpecs: - - default: false - lockToDefault: false - preRelease: Alpha - version: "1.26" - - default: true - lockToDefault: false - preRelease: Beta - version: "1.27" - - default: true - lockToDefault: true - preRelease: GA - version: "1.30" - name: AllowDNSOnlyNodeCSR versionedSpecs: - default: true diff --git a/test/integration/apiserver/discovery/discovery_test.go b/test/integration/apiserver/discovery/discovery_test.go index 336dd07580c..cf41ffe620e 100644 --- a/test/integration/apiserver/discovery/discovery_test.go +++ b/test/integration/apiserver/discovery/discovery_test.go @@ -39,13 +39,10 @@ import ( utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/sets" discoveryendpoint "k8s.io/apiserver/pkg/endpoints/discovery/aggregated" - genericfeatures "k8s.io/apiserver/pkg/features" - utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/discovery" "k8s.io/client-go/dynamic" kubernetes "k8s.io/client-go/kubernetes" k8sscheme "k8s.io/client-go/kubernetes/scheme" - featuregatetesting "k8s.io/component-base/featuregate/testing" apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1" aggregator "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset" aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" @@ -185,8 +182,6 @@ func setup(t *testing.T) (context.Context, testClientSet, context.CancelFunc) { } func TestReadinessAggregatedAPIServiceDiscovery(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.AggregatedDiscoveryEndpoint, true) - // Keep any goroutines spawned from running past the execution of this test ctx, client, cleanup := setup(t) defer cleanup() @@ -284,8 +279,6 @@ func unregisterAPIService(ctx context.Context, client aggregator.Interface, gv m } func TestAggregatedAPIServiceDiscovery(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.AggregatedDiscoveryEndpoint, true) - // Keep any goroutines spawned from running past the execution of this test ctx, client, cleanup := setup(t) defer cleanup() @@ -386,8 +379,6 @@ func runTestCases(t *testing.T, cases []testCase) { // Declarative tests targeting CRD integration func TestCRD(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.AggregatedDiscoveryEndpoint, true) - runTestCases(t, []testCase{ { // Show that when a CRD is added it gets included on the discovery doc @@ -626,8 +617,6 @@ func TestCRD(t *testing.T) { } func TestFreshness(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.AggregatedDiscoveryEndpoint, true) - requireStaleGVs := func(gvs ...metav1.GroupVersion) inlineAction { return inlineAction(func(ctx context.Context, client testClient) error { document, err := FetchV2Discovery(ctx, client) @@ -716,8 +705,6 @@ func TestFreshness(t *testing.T) { // Shows a group for which multiple APIServices specify a GroupPriorityMinimum, // it is sorted the same in both versions of discovery func TestGroupPriority(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.AggregatedDiscoveryEndpoint, true) - makeApiServiceSpec := func(gv metav1.GroupVersion, groupPriorityMin, versionPriority int) apiregistrationv1.APIServiceSpec { return apiregistrationv1.APIServiceSpec{ Group: gv.Group,