diff --git a/cmd/kube-apiserver/app/aggregator.go b/cmd/kube-apiserver/app/aggregator.go index b719a4547a8..2466dcc21be 100644 --- a/cmd/kube-apiserver/app/aggregator.go +++ b/cmd/kube-apiserver/app/aggregator.go @@ -27,6 +27,7 @@ import ( "k8s.io/klog/v2" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apiextensionsinformers "k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -146,7 +147,7 @@ func createAggregatorServer(aggregatorConfig *aggregatorapiserver.Config, delega // let the CRD controller process the initial set of CRDs before starting the autoregistration controller. // this prevents the autoregistration controller's initial sync from deleting APIServices for CRDs that still exist. // we only need to do this if CRDs are enabled on this server. We can't use discovery because we are the source for discovery. - if aggregatorConfig.GenericConfig.MergedResourceConfig.AnyResourceForGroupEnabled("apiextensions.k8s.io") { + if aggregatorConfig.GenericConfig.MergedResourceConfig.ResourceEnabled(apiextensionsv1.SchemeGroupVersion.WithResource("customresourcedefinitions")) { crdRegistrationController.WaitForInitialSync() } autoRegistrationController.Run(5, context.StopCh) diff --git a/pkg/controlplane/instance.go b/pkg/controlplane/instance.go index 6ab11031e0c..5456849e42a 100644 --- a/pkg/controlplane/instance.go +++ b/pkg/controlplane/instance.go @@ -55,6 +55,7 @@ import ( storageapiv1alpha1 "k8s.io/api/storage/v1alpha1" storageapiv1beta1 "k8s.io/api/storage/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" utilnet "k8s.io/apimachinery/pkg/util/net" "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/wait" @@ -549,7 +550,7 @@ func (m *Instance) InstallLegacyAPI(c *completedConfig, restOptionsGetter generi // RESTStorageProvider is a factory type for REST storage. type RESTStorageProvider interface { GroupName() string - NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) + NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, error) } // InstallAPIs will install the APIs for the restStorageProviders if they are enabled. @@ -564,16 +565,14 @@ func (m *Instance) InstallAPIs(apiResourceConfigSource serverstorage.APIResource for _, restStorageBuilder := range restStorageProviders { groupName := restStorageBuilder.GroupName() - if !apiResourceConfigSource.AnyResourceForGroupEnabled(groupName) { - klog.V(1).Infof("Skipping disabled API group %q.", groupName) - continue - } - apiGroupInfo, enabled, err := restStorageBuilder.NewRESTStorage(apiResourceConfigSource, restOptionsGetter) + apiGroupInfo, err := restStorageBuilder.NewRESTStorage(apiResourceConfigSource, restOptionsGetter) if err != nil { return fmt.Errorf("problem initializing API group %q : %v", groupName, err) } - if !enabled { - klog.Warningf("API group %q is not enabled, skipping.", groupName) + if len(apiGroupInfo.VersionedResourcesStorageMap) == 0 { + // If we have no storage for any resource configured, this API group is effectively disabled. + // This can happen when an entire API group, version, or development-stage (alpha, beta, GA) is disabled. + klog.Infof("API group %q is not enabled, skipping.", groupName) continue } @@ -640,11 +639,9 @@ func (n nodeAddressProvider) externalAddresses() ([]string, error) { return addrs, nil } -// DefaultAPIResourceConfigSource returns default configuration for an APIResource. -func DefaultAPIResourceConfigSource() *serverstorage.ResourceConfig { - ret := serverstorage.NewResourceConfig() - // NOTE: GroupVersions listed here will be enabled by default. Don't put alpha versions in the list. - ret.EnableVersions( +var ( + // stableAPIGroupVersionsEnabledByDefault is a list of our stable versions. + stableAPIGroupVersionsEnabledByDefault = []schema.GroupVersion{ admissionregistrationv1.SchemeGroupVersion, apiv1.SchemeGroupVersion, appsv1.SchemeGroupVersion, @@ -652,34 +649,73 @@ func DefaultAPIResourceConfigSource() *serverstorage.ResourceConfig { authorizationapiv1.SchemeGroupVersion, autoscalingapiv1.SchemeGroupVersion, autoscalingapiv2.SchemeGroupVersion, - autoscalingapiv2beta1.SchemeGroupVersion, - autoscalingapiv2beta2.SchemeGroupVersion, batchapiv1.SchemeGroupVersion, - batchapiv1beta1.SchemeGroupVersion, certificatesapiv1.SchemeGroupVersion, coordinationapiv1.SchemeGroupVersion, discoveryv1.SchemeGroupVersion, - discoveryv1beta1.SchemeGroupVersion, eventsv1.SchemeGroupVersion, - eventsv1beta1.SchemeGroupVersion, networkingapiv1.SchemeGroupVersion, nodev1.SchemeGroupVersion, - nodev1beta1.SchemeGroupVersion, // remove in 1.26 policyapiv1.SchemeGroupVersion, - policyapiv1beta1.SchemeGroupVersion, rbacv1.SchemeGroupVersion, storageapiv1.SchemeGroupVersion, - storageapiv1beta1.SchemeGroupVersion, schedulingapiv1.SchemeGroupVersion, - flowcontrolv1beta2.SchemeGroupVersion, + } + + // legacyBetaEnabledByDefaultResources is the list of beta resources we enable. You may only add to this list + // if your resource is already enabled by default in a beta level we still serve AND there is no stable API for it. + // see https://github.com/kubernetes/enhancements/tree/master/keps/sig-architecture/3136-beta-apis-off-by-default + // for more details. + legacyBetaEnabledByDefaultResources = []schema.GroupVersionResource{ + autoscalingapiv2beta1.SchemeGroupVersion.WithResource("horizontalpodautoscalers"), // remove in 1.25 + autoscalingapiv2beta2.SchemeGroupVersion.WithResource("horizontalpodautoscalers"), // remove in 1.26 + batchapiv1beta1.SchemeGroupVersion.WithResource("cronjobs"), // remove in 1.25 + discoveryv1beta1.SchemeGroupVersion.WithResource("endpointslices"), // remove in 1.25 + eventsv1beta1.SchemeGroupVersion.WithResource("events"), // remove in 1.25 + nodev1beta1.SchemeGroupVersion.WithResource("runtimeclasses"), // remove in 1.25 + policyapiv1beta1.SchemeGroupVersion.WithResource("poddisruptionbudgets"), // remove in 1.25 + policyapiv1beta1.SchemeGroupVersion.WithResource("podsecuritypolicies"), // remove in 1.25 + storageapiv1beta1.SchemeGroupVersion.WithResource("csinodes"), // remove in 1.25 + storageapiv1beta1.SchemeGroupVersion.WithResource("csistoragecapacities"), // remove in 1.27 + flowcontrolv1beta1.SchemeGroupVersion.WithResource("flowschemas"), // remove in 1.26 + flowcontrolv1beta1.SchemeGroupVersion.WithResource("prioritylevelconfigurations"), // remove in 1.26 + flowcontrolv1beta2.SchemeGroupVersion.WithResource("flowschemas"), // remove in 1.29 + flowcontrolv1beta2.SchemeGroupVersion.WithResource("prioritylevelconfigurations"), // remove in 1.29 + } + // betaAPIGroupVersionsDisabledByDefault is for all future beta groupVersions. + betaAPIGroupVersionsDisabledByDefault = []schema.GroupVersion{ + autoscalingapiv2beta1.SchemeGroupVersion, + autoscalingapiv2beta2.SchemeGroupVersion, + batchapiv1beta1.SchemeGroupVersion, + discoveryv1beta1.SchemeGroupVersion, + eventsv1beta1.SchemeGroupVersion, + nodev1beta1.SchemeGroupVersion, // remove in 1.26 + policyapiv1beta1.SchemeGroupVersion, + storageapiv1beta1.SchemeGroupVersion, flowcontrolv1beta1.SchemeGroupVersion, - ) - // disable alpha versions explicitly so we have a full list of what's possible to serve - ret.DisableVersions( + flowcontrolv1beta2.SchemeGroupVersion, + } + + // alphaAPIGroupVersionsDisabledByDefault holds the alpha APIs we have. They are always disabled by default. + alphaAPIGroupVersionsDisabledByDefault = []schema.GroupVersion{ apiserverinternalv1alpha1.SchemeGroupVersion, storageapiv1alpha1.SchemeGroupVersion, flowcontrolv1alpha1.SchemeGroupVersion, - ) + } +) + +// DefaultAPIResourceConfigSource returns default configuration for an APIResource. +func DefaultAPIResourceConfigSource() *serverstorage.ResourceConfig { + ret := serverstorage.NewResourceConfig() + // NOTE: GroupVersions listed here will be enabled by default. Don't put alpha or beta versions in the list. + ret.EnableVersions(stableAPIGroupVersionsEnabledByDefault...) + + // disable alpha and beta versions explicitly so we have a full list of what's possible to serve + ret.DisableVersions(betaAPIGroupVersionsDisabledByDefault...) + ret.DisableVersions(alphaAPIGroupVersionsDisabledByDefault...) + + // enable the legacy beta resources that were present before stopped serving new beta APIs by default. + ret.EnableResources(legacyBetaEnabledByDefaultResources...) return ret } diff --git a/pkg/controlplane/instance_test.go b/pkg/controlplane/instance_test.go index 06dade03301..ff5e56f1b28 100644 --- a/pkg/controlplane/instance_test.go +++ b/pkg/controlplane/instance_test.go @@ -28,8 +28,16 @@ import ( "strings" "testing" + autoscalingapiv2beta1 "k8s.io/api/autoscaling/v2beta1" + autoscalingapiv2beta2 "k8s.io/api/autoscaling/v2beta2" + batchapiv1beta1 "k8s.io/api/batch/v1beta1" certificatesapiv1beta1 "k8s.io/api/certificates/v1beta1" apiv1 "k8s.io/api/core/v1" + discoveryv1beta1 "k8s.io/api/discovery/v1beta1" + eventsv1beta1 "k8s.io/api/events/v1beta1" + nodev1beta1 "k8s.io/api/node/v1beta1" + policyapiv1beta1 "k8s.io/api/policy/v1beta1" + storageapiv1beta1 "k8s.io/api/storage/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" utilnet "k8s.io/apimachinery/pkg/util/net" @@ -50,6 +58,7 @@ import ( kubeversion "k8s.io/component-base/version" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/batch" + flowcontrolv1beta2 "k8s.io/kubernetes/pkg/apis/flowcontrol/v1beta2" "k8s.io/kubernetes/pkg/apis/networking" apisstorage "k8s.io/kubernetes/pkg/apis/storage" "k8s.io/kubernetes/pkg/controlplane/reconcilers" @@ -173,7 +182,7 @@ func TestCertificatesRestStorageStrategies(t *testing.T) { defer etcdserver.Terminate(t) certStorageProvider := certificatesrest.RESTStorageProvider{} - apiGroupInfo, _, err := certStorageProvider.NewRESTStorage(apiserverCfg.ExtraConfig.APIResourceConfigSource, apiserverCfg.GenericConfig.RESTOptionsGetter) + apiGroupInfo, err := certStorageProvider.NewRESTStorage(apiserverCfg.ExtraConfig.APIResourceConfigSource, apiserverCfg.GenericConfig.RESTOptionsGetter) if err != nil { t.Fatalf("unexpected error from REST storage: %v", err) } @@ -460,3 +469,56 @@ func TestNoAlphaVersionsEnabledByDefault(t *testing.T) { } } } + +func TestNoBetaVersionsEnabledByDefault(t *testing.T) { + config := DefaultAPIResourceConfigSource() + for gv, enable := range config.GroupVersionConfigs { + if enable && strings.Contains(gv.Version, "beta") { + t.Errorf("Beta API version %s enabled by default", gv.String()) + } + } +} + +func TestNewBetaResourcesEnabledByDefault(t *testing.T) { + // legacyEnabledBetaResources is nearly a duplication from elsewhere. This is intentional. These types already have + // GA equivalents available and should therefore never have a beta enabled by default again. + legacyEnabledBetaResources := map[schema.GroupVersionResource]bool{ + autoscalingapiv2beta1.SchemeGroupVersion.WithResource("horizontalpodautoscalers"): true, + autoscalingapiv2beta2.SchemeGroupVersion.WithResource("horizontalpodautoscalers"): true, + batchapiv1beta1.SchemeGroupVersion.WithResource("cronjobs"): true, + discoveryv1beta1.SchemeGroupVersion.WithResource("endpointslices"): true, + eventsv1beta1.SchemeGroupVersion.WithResource("events"): true, + nodev1beta1.SchemeGroupVersion.WithResource("runtimeclasses"): true, + policyapiv1beta1.SchemeGroupVersion.WithResource("poddisruptionbudgets"): true, + policyapiv1beta1.SchemeGroupVersion.WithResource("podsecuritypolicies"): true, + storageapiv1beta1.SchemeGroupVersion.WithResource("csinodes"): true, + storageapiv1beta1.SchemeGroupVersion.WithResource("csistoragecapacities"): true, + } + + // legacyBetaResourcesWithoutStableEquivalents contains those groupresources that were enabled by default as beta + // before we changed that policy and do not have stable versions. These resources are allowed to have additional + // beta versions enabled by default. Nothing new should be added here. There are no future exceptions because there + // are no more beta resources enabled by default. + legacyBetaResourcesWithoutStableEquivalents := map[schema.GroupResource]bool{ + storageapiv1beta1.SchemeGroupVersion.WithResource("csistoragecapacities").GroupResource(): true, + flowcontrolv1beta2.SchemeGroupVersion.WithResource("flowschemas").GroupResource(): true, + flowcontrolv1beta2.SchemeGroupVersion.WithResource("prioritylevelconfigurations").GroupResource(): true, + } + + config := DefaultAPIResourceConfigSource() + for gvr, enable := range config.ResourceConfigs { + if !strings.Contains(gvr.Version, "beta") { + continue // only check beta things + } + if !enable { + continue // only check things that are enabled + } + if legacyEnabledBetaResources[gvr] { + continue // this is a legacy beta resource + } + if legacyBetaResourcesWithoutStableEquivalents[gvr.GroupResource()] { + continue // this is another beta of a legacy beta resource with no stable equivalent + } + t.Errorf("no new beta resources can be enabled by default, see https://github.com/kubernetes/enhancements/blob/0ad0fc8269165ca300d05ca51c7ce190a79976a5/keps/sig-architecture/3136-beta-apis-off-by-default/README.md: %v", gvr) + } +} diff --git a/pkg/registry/admissionregistration/rest/storage_apiserver.go b/pkg/registry/admissionregistration/rest/storage_apiserver.go index 2c8b6eac55c..0e03b7186dc 100644 --- a/pkg/registry/admissionregistration/rest/storage_apiserver.go +++ b/pkg/registry/admissionregistration/rest/storage_apiserver.go @@ -30,17 +30,17 @@ import ( type RESTStorageProvider struct{} -func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, error) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(admissionregistration.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // TODO refactor the plumbing to provide the information in the APIGroupInfo if storageMap, err := p.v1Storage(apiResourceConfigSource, restOptionsGetter); err != nil { - return genericapiserver.APIGroupInfo{}, false, err + return genericapiserver.APIGroupInfo{}, err } else if len(storageMap) > 0 { apiGroupInfo.VersionedResourcesStorageMap[admissionregistrationv1.SchemeGroupVersion.Version] = storageMap } - return apiGroupInfo, true, nil + return apiGroupInfo, nil } func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) { diff --git a/pkg/registry/apiserverinternal/rest/storage.go b/pkg/registry/apiserverinternal/rest/storage.go index f749e37eaf0..602d51f68a6 100644 --- a/pkg/registry/apiserverinternal/rest/storage.go +++ b/pkg/registry/apiserverinternal/rest/storage.go @@ -31,16 +31,16 @@ import ( type StorageProvider struct{} // NewRESTStorage returns a StorageProvider -func (p StorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) { +func (p StorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, error) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(apiserverinternal.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) if storageMap, err := p.v1alpha1Storage(apiResourceConfigSource, restOptionsGetter); err != nil { - return genericapiserver.APIGroupInfo{}, false, err + return genericapiserver.APIGroupInfo{}, err } else if len(storageMap) > 0 { apiGroupInfo.VersionedResourcesStorageMap[apiserverv1alpha1.SchemeGroupVersion.Version] = storageMap } - return apiGroupInfo, true, nil + return apiGroupInfo, nil } func (p StorageProvider) v1alpha1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) { diff --git a/pkg/registry/apps/rest/storage_apps.go b/pkg/registry/apps/rest/storage_apps.go index d4046942f44..d8357fe6592 100644 --- a/pkg/registry/apps/rest/storage_apps.go +++ b/pkg/registry/apps/rest/storage_apps.go @@ -35,18 +35,18 @@ import ( type StorageProvider struct{} // NewRESTStorage returns APIGroupInfo object. -func (p StorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) { +func (p StorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, error) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(apps.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // TODO refactor the plumbing to provide the information in the APIGroupInfo if storageMap, err := p.v1Storage(apiResourceConfigSource, restOptionsGetter); err != nil { - return genericapiserver.APIGroupInfo{}, false, err + return genericapiserver.APIGroupInfo{}, err } else if len(storageMap) > 0 { apiGroupInfo.VersionedResourcesStorageMap[appsapiv1.SchemeGroupVersion.Version] = storageMap } - return apiGroupInfo, true, nil + return apiGroupInfo, nil } func (p StorageProvider) v1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) { diff --git a/pkg/registry/authentication/rest/storage_authentication.go b/pkg/registry/authentication/rest/storage_authentication.go index 0152d5d766c..fcd0f5c5921 100644 --- a/pkg/registry/authentication/rest/storage_authentication.go +++ b/pkg/registry/authentication/rest/storage_authentication.go @@ -33,7 +33,7 @@ type RESTStorageProvider struct { APIAudiences authenticator.Audiences } -func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, error) { // TODO figure out how to make the swagger generation stable, while allowing this endpoint to be disabled. // if p.Authenticator == nil { // return genericapiserver.APIGroupInfo{}, false @@ -47,7 +47,7 @@ func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorag apiGroupInfo.VersionedResourcesStorageMap[authenticationv1.SchemeGroupVersion.Version] = storageMap } - return apiGroupInfo, true, nil + return apiGroupInfo, nil } func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { diff --git a/pkg/registry/authorization/rest/storage_authorization.go b/pkg/registry/authorization/rest/storage_authorization.go index 77b9eb2faef..4f17771bba2 100644 --- a/pkg/registry/authorization/rest/storage_authorization.go +++ b/pkg/registry/authorization/rest/storage_authorization.go @@ -36,9 +36,9 @@ type RESTStorageProvider struct { RuleResolver authorizer.RuleResolver } -func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, error) { if p.Authorizer == nil { - return genericapiserver.APIGroupInfo{}, false, nil + return genericapiserver.APIGroupInfo{}, nil } apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(authorization.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) @@ -49,7 +49,7 @@ func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorag apiGroupInfo.VersionedResourcesStorageMap[authorizationv1.SchemeGroupVersion.Version] = storageMap } - return apiGroupInfo, true, nil + return apiGroupInfo, nil } func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage { diff --git a/pkg/registry/autoscaling/rest/storage_autoscaling.go b/pkg/registry/autoscaling/rest/storage_autoscaling.go index a610e34f283..c4fa097ade2 100644 --- a/pkg/registry/autoscaling/rest/storage_autoscaling.go +++ b/pkg/registry/autoscaling/rest/storage_autoscaling.go @@ -32,36 +32,36 @@ import ( type RESTStorageProvider struct{} -func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, error) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(autoscaling.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // TODO refactor the plumbing to provide the information in the APIGroupInfo if storageMap, err := p.v2beta2Storage(apiResourceConfigSource, restOptionsGetter); err != nil { - return genericapiserver.APIGroupInfo{}, false, err + return genericapiserver.APIGroupInfo{}, err } else if len(storageMap) > 0 { apiGroupInfo.VersionedResourcesStorageMap[autoscalingapiv2beta2.SchemeGroupVersion.Version] = storageMap } if storageMap, err := p.v2Storage(apiResourceConfigSource, restOptionsGetter); err != nil { - return genericapiserver.APIGroupInfo{}, false, err + return genericapiserver.APIGroupInfo{}, err } else if len(storageMap) > 0 { apiGroupInfo.VersionedResourcesStorageMap[autoscalingapiv2.SchemeGroupVersion.Version] = storageMap } if storageMap, err := p.v2beta1Storage(apiResourceConfigSource, restOptionsGetter); err != nil { - return genericapiserver.APIGroupInfo{}, false, err + return genericapiserver.APIGroupInfo{}, err } else if len(storageMap) > 0 { apiGroupInfo.VersionedResourcesStorageMap[autoscalingapiv2beta1.SchemeGroupVersion.Version] = storageMap } if storageMap, err := p.v1Storage(apiResourceConfigSource, restOptionsGetter); err != nil { - return genericapiserver.APIGroupInfo{}, false, err + return genericapiserver.APIGroupInfo{}, err } else if len(storageMap) > 0 { apiGroupInfo.VersionedResourcesStorageMap[autoscalingapiv1.SchemeGroupVersion.Version] = storageMap } - return apiGroupInfo, true, nil + return apiGroupInfo, nil } func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) { diff --git a/pkg/registry/batch/rest/storage_batch.go b/pkg/registry/batch/rest/storage_batch.go index a1e2e0c173b..d76c748d57e 100644 --- a/pkg/registry/batch/rest/storage_batch.go +++ b/pkg/registry/batch/rest/storage_batch.go @@ -31,24 +31,24 @@ import ( type RESTStorageProvider struct{} -func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, error) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(batch.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // TODO refactor the plumbing to provide the information in the APIGroupInfo if storageMap, err := p.v1Storage(apiResourceConfigSource, restOptionsGetter); err != nil { - return genericapiserver.APIGroupInfo{}, false, err + return genericapiserver.APIGroupInfo{}, err } else if len(storageMap) > 0 { apiGroupInfo.VersionedResourcesStorageMap[batchapiv1.SchemeGroupVersion.Version] = storageMap } if storageMap, err := p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter); err != nil { - return genericapiserver.APIGroupInfo{}, false, err + return genericapiserver.APIGroupInfo{}, err } else if len(storageMap) > 0 { apiGroupInfo.VersionedResourcesStorageMap[batchapiv1beta1.SchemeGroupVersion.Version] = storageMap } - return apiGroupInfo, true, nil + return apiGroupInfo, nil } func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) { diff --git a/pkg/registry/certificates/rest/storage_certificates.go b/pkg/registry/certificates/rest/storage_certificates.go index ee80be7c26f..ce65458e494 100644 --- a/pkg/registry/certificates/rest/storage_certificates.go +++ b/pkg/registry/certificates/rest/storage_certificates.go @@ -29,18 +29,18 @@ import ( type RESTStorageProvider struct{} -func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, error) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(certificates.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // TODO refactor the plumbing to provide the information in the APIGroupInfo if storageMap, err := p.v1Storage(apiResourceConfigSource, restOptionsGetter); err != nil { - return genericapiserver.APIGroupInfo{}, false, err + return genericapiserver.APIGroupInfo{}, err } else if len(storageMap) > 0 { apiGroupInfo.VersionedResourcesStorageMap[certificatesapiv1.SchemeGroupVersion.Version] = storageMap } - return apiGroupInfo, true, nil + return apiGroupInfo, nil } func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) { diff --git a/pkg/registry/coordination/rest/storage_coordination.go b/pkg/registry/coordination/rest/storage_coordination.go index e1bfc3e67fd..3cfe51d304e 100644 --- a/pkg/registry/coordination/rest/storage_coordination.go +++ b/pkg/registry/coordination/rest/storage_coordination.go @@ -29,17 +29,17 @@ import ( type RESTStorageProvider struct{} -func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, error) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(coordination.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // TODO refactor the plumbing to provide the information in the APIGroupInfo if storageMap, err := p.v1Storage(apiResourceConfigSource, restOptionsGetter); err != nil { - return genericapiserver.APIGroupInfo{}, false, err + return genericapiserver.APIGroupInfo{}, err } else if len(storageMap) > 0 { apiGroupInfo.VersionedResourcesStorageMap[coordinationv1.SchemeGroupVersion.Version] = storageMap } - return apiGroupInfo, true, nil + return apiGroupInfo, nil } func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) { diff --git a/pkg/registry/discovery/rest/storage_discovery.go b/pkg/registry/discovery/rest/storage_discovery.go index 0f30206a2ec..02f76a139a8 100644 --- a/pkg/registry/discovery/rest/storage_discovery.go +++ b/pkg/registry/discovery/rest/storage_discovery.go @@ -32,24 +32,24 @@ import ( type StorageProvider struct{} // NewRESTStorage returns a new storage provider. -func (p StorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) { +func (p StorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, error) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(discovery.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // TODO refactor the plumbing to provide the information in the APIGroupInfo if storageMap, err := p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter); err != nil { - return genericapiserver.APIGroupInfo{}, false, err + return genericapiserver.APIGroupInfo{}, err } else if len(storageMap) > 0 { apiGroupInfo.VersionedResourcesStorageMap[discoveryv1beta1.SchemeGroupVersion.Version] = storageMap } if storageMap, err := p.v1Storage(apiResourceConfigSource, restOptionsGetter); err != nil { - return genericapiserver.APIGroupInfo{}, false, err + return genericapiserver.APIGroupInfo{}, err } else if len(storageMap) > 0 { apiGroupInfo.VersionedResourcesStorageMap[discoveryv1.SchemeGroupVersion.Version] = storageMap } - return apiGroupInfo, true, nil + return apiGroupInfo, nil } func (p StorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) { diff --git a/pkg/registry/events/rest/storage_events.go b/pkg/registry/events/rest/storage_events.go index c727d4440d0..147e1d5c1c6 100644 --- a/pkg/registry/events/rest/storage_events.go +++ b/pkg/registry/events/rest/storage_events.go @@ -34,24 +34,24 @@ type RESTStorageProvider struct { TTL time.Duration } -func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, error) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(events.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // TODO refactor the plumbing to provide the information in the APIGroupInfo if storageMap, err := p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter); err != nil { - return genericapiserver.APIGroupInfo{}, false, err + return genericapiserver.APIGroupInfo{}, err } else if len(storageMap) > 0 { apiGroupInfo.VersionedResourcesStorageMap[eventsapiv1beta1.SchemeGroupVersion.Version] = storageMap } if storageMap, err := p.v1Storage(apiResourceConfigSource, restOptionsGetter); err != nil { - return genericapiserver.APIGroupInfo{}, false, err + return genericapiserver.APIGroupInfo{}, err } else if len(storageMap) > 0 { apiGroupInfo.VersionedResourcesStorageMap[eventsapiv1.SchemeGroupVersion.Version] = storageMap } - return apiGroupInfo, true, nil + return apiGroupInfo, nil } func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) { diff --git a/pkg/registry/flowcontrol/rest/storage_flowcontrol.go b/pkg/registry/flowcontrol/rest/storage_flowcontrol.go index c6084d93ae6..72a7db56bc7 100644 --- a/pkg/registry/flowcontrol/rest/storage_flowcontrol.go +++ b/pkg/registry/flowcontrol/rest/storage_flowcontrol.go @@ -54,28 +54,28 @@ type RESTStorageProvider struct { const PostStartHookName = "priority-and-fairness-config-producer" // NewRESTStorage creates a new rest storage for flow-control api models. -func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, error) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(flowcontrol.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) if storageMap, err := p.storage(apiResourceConfigSource, restOptionsGetter, flowcontrolapisv1alpha1.SchemeGroupVersion); err != nil { - return genericapiserver.APIGroupInfo{}, false, err + return genericapiserver.APIGroupInfo{}, err } else if len(storageMap) > 0 { apiGroupInfo.VersionedResourcesStorageMap[flowcontrolapisv1alpha1.SchemeGroupVersion.Version] = storageMap } if storageMap, err := p.storage(apiResourceConfigSource, restOptionsGetter, flowcontrolapisv1beta1.SchemeGroupVersion); err != nil { - return genericapiserver.APIGroupInfo{}, false, err + return genericapiserver.APIGroupInfo{}, err } else if len(storageMap) > 0 { apiGroupInfo.VersionedResourcesStorageMap[flowcontrolapisv1beta1.SchemeGroupVersion.Version] = storageMap } if storageMap, err := p.storage(apiResourceConfigSource, restOptionsGetter, flowcontrolapisv1beta2.SchemeGroupVersion); err != nil { - return genericapiserver.APIGroupInfo{}, false, err + return genericapiserver.APIGroupInfo{}, err } else if len(storageMap) > 0 { apiGroupInfo.VersionedResourcesStorageMap[flowcontrolapisv1beta2.SchemeGroupVersion.Version] = storageMap } - return apiGroupInfo, true, nil + return apiGroupInfo, nil } func (p RESTStorageProvider) storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter, groupVersion schema.GroupVersion) (map[string]rest.Storage, error) { diff --git a/pkg/registry/networking/rest/storage_settings.go b/pkg/registry/networking/rest/storage_settings.go index bb84bdb42a2..e287d1120dd 100644 --- a/pkg/registry/networking/rest/storage_settings.go +++ b/pkg/registry/networking/rest/storage_settings.go @@ -31,18 +31,18 @@ import ( type RESTStorageProvider struct{} -func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, error) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(networking.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // TODO refactor the plumbing to provide the information in the APIGroupInfo if storageMap, err := p.v1Storage(apiResourceConfigSource, restOptionsGetter); err != nil { - return genericapiserver.APIGroupInfo{}, false, err + return genericapiserver.APIGroupInfo{}, err } else if len(storageMap) > 0 { apiGroupInfo.VersionedResourcesStorageMap[networkingapiv1.SchemeGroupVersion.Version] = storageMap } - return apiGroupInfo, true, nil + return apiGroupInfo, nil } func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) { diff --git a/pkg/registry/node/rest/runtime_class.go b/pkg/registry/node/rest/runtime_class.go index 0b561817178..0252d1d0f91 100644 --- a/pkg/registry/node/rest/runtime_class.go +++ b/pkg/registry/node/rest/runtime_class.go @@ -32,23 +32,23 @@ import ( type RESTStorageProvider struct{} // NewRESTStorage returns a RESTStorageProvider -func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, error) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(nodeinternal.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) if storageMap, err := p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter); err != nil { // remove in 1.26 - return genericapiserver.APIGroupInfo{}, false, err + return genericapiserver.APIGroupInfo{}, err } else if len(storageMap) > 0 { apiGroupInfo.VersionedResourcesStorageMap[nodev1beta1.SchemeGroupVersion.Version] = storageMap } if storageMap, err := p.v1Storage(apiResourceConfigSource, restOptionsGetter); err != nil { - return genericapiserver.APIGroupInfo{}, false, err + return genericapiserver.APIGroupInfo{}, err } else if len(storageMap) > 0 { apiGroupInfo.VersionedResourcesStorageMap[nodev1.SchemeGroupVersion.Version] = storageMap } - return apiGroupInfo, true, nil + return apiGroupInfo, nil } func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) { diff --git a/pkg/registry/policy/rest/storage_policy.go b/pkg/registry/policy/rest/storage_policy.go index 5b4f4d0cbe3..49ac0f2f590 100644 --- a/pkg/registry/policy/rest/storage_policy.go +++ b/pkg/registry/policy/rest/storage_policy.go @@ -31,24 +31,24 @@ import ( type RESTStorageProvider struct{} -func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, error) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(policy.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // TODO refactor the plumbing to provide the information in the APIGroupInfo if storageMap, err := p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter); err != nil { - return genericapiserver.APIGroupInfo{}, false, err + return genericapiserver.APIGroupInfo{}, err } else if len(storageMap) > 0 { apiGroupInfo.VersionedResourcesStorageMap[policyapiv1beta1.SchemeGroupVersion.Version] = storageMap } if storageMap, err := p.v1Storage(apiResourceConfigSource, restOptionsGetter); err != nil { - return genericapiserver.APIGroupInfo{}, false, err + return genericapiserver.APIGroupInfo{}, err } else if len(storageMap) > 0 { apiGroupInfo.VersionedResourcesStorageMap[policyapiv1.SchemeGroupVersion.Version] = storageMap } - return apiGroupInfo, true, nil + return apiGroupInfo, nil } func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) { diff --git a/pkg/registry/rbac/rest/storage_rbac.go b/pkg/registry/rbac/rest/storage_rbac.go index 964acc43138..ae3218eb0b5 100644 --- a/pkg/registry/rbac/rest/storage_rbac.go +++ b/pkg/registry/rbac/rest/storage_rbac.go @@ -65,18 +65,18 @@ type RESTStorageProvider struct { var _ genericapiserver.PostStartHookProvider = RESTStorageProvider{} -func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, error) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(rbac.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // TODO refactor the plumbing to provide the information in the APIGroupInfo if storageMap, err := p.storage(rbacapiv1.SchemeGroupVersion, apiResourceConfigSource, restOptionsGetter); err != nil { - return genericapiserver.APIGroupInfo{}, false, err + return genericapiserver.APIGroupInfo{}, err } else if len(storageMap) > 0 { apiGroupInfo.VersionedResourcesStorageMap[rbacapiv1.SchemeGroupVersion.Version] = storageMap } - return apiGroupInfo, true, nil + return apiGroupInfo, nil } func (p RESTStorageProvider) storage(version schema.GroupVersion, apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) { diff --git a/pkg/registry/scheduling/rest/storage_scheduling.go b/pkg/registry/scheduling/rest/storage_scheduling.go index 26930931831..01bd84de357 100644 --- a/pkg/registry/scheduling/rest/storage_scheduling.go +++ b/pkg/registry/scheduling/rest/storage_scheduling.go @@ -44,16 +44,16 @@ type RESTStorageProvider struct{} var _ genericapiserver.PostStartHookProvider = RESTStorageProvider{} -func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, error) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(scheduling.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) if storageMap, err := p.v1Storage(apiResourceConfigSource, restOptionsGetter); err != nil { - return genericapiserver.APIGroupInfo{}, false, err + return genericapiserver.APIGroupInfo{}, err } else if len(storageMap) > 0 { apiGroupInfo.VersionedResourcesStorageMap[schedulingapiv1.SchemeGroupVersion.Version] = storageMap } - return apiGroupInfo, true, nil + return apiGroupInfo, nil } func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) { diff --git a/pkg/registry/storage/rest/storage_storage.go b/pkg/registry/storage/rest/storage_storage.go index c3280f59ba4..b4d73aafe1d 100644 --- a/pkg/registry/storage/rest/storage_storage.go +++ b/pkg/registry/storage/rest/storage_storage.go @@ -36,28 +36,28 @@ import ( type RESTStorageProvider struct { } -func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool, error) { +func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, error) { apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(storageapi.GroupName, legacyscheme.Scheme, legacyscheme.ParameterCodec, legacyscheme.Codecs) // If you add a version here, be sure to add an entry in `k8s.io/kubernetes/cmd/kube-apiserver/app/aggregator.go with specific priorities. // TODO refactor the plumbing to provide the information in the APIGroupInfo if storageMap, err := p.v1alpha1Storage(apiResourceConfigSource, restOptionsGetter); err != nil { - return genericapiserver.APIGroupInfo{}, false, err + return genericapiserver.APIGroupInfo{}, err } else if len(storageMap) > 0 { apiGroupInfo.VersionedResourcesStorageMap[storageapiv1alpha1.SchemeGroupVersion.Version] = storageMap } if storageMap, err := p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter); err != nil { - return genericapiserver.APIGroupInfo{}, false, err + return genericapiserver.APIGroupInfo{}, err } else if len(storageMap) > 0 { apiGroupInfo.VersionedResourcesStorageMap[storageapiv1beta1.SchemeGroupVersion.Version] = storageMap } if storageMap, err := p.v1Storage(apiResourceConfigSource, restOptionsGetter); err != nil { - return genericapiserver.APIGroupInfo{}, false, err + return genericapiserver.APIGroupInfo{}, err } else if len(storageMap) > 0 { apiGroupInfo.VersionedResourcesStorageMap[storageapiv1.SchemeGroupVersion.Version] = storageMap } - return apiGroupInfo, true, nil + return apiGroupInfo, nil } func (p RESTStorageProvider) v1alpha1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) { diff --git a/staging/src/k8s.io/apiserver/pkg/server/resourceconfig/helpers.go b/staging/src/k8s.io/apiserver/pkg/server/resourceconfig/helpers.go index f0e30701c9b..e90aa916199 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/resourceconfig/helpers.go +++ b/staging/src/k8s.io/apiserver/pkg/server/resourceconfig/helpers.go @@ -76,25 +76,8 @@ var ( } groupVersionMatchersOrder = []string{APIAll, APIGA, APIBeta, APIAlpha} - - groupVersionResourceMatchers = map[string]func(gvr schema.GroupVersionResource) bool{ - // allows users to address all api versions - APIAll: func(gvr schema.GroupVersionResource) bool { return true }, - // allows users to address all api versions in the form v[0-9]+ - APIGA: func(gvr schema.GroupVersionResource) bool { return gaPattern.MatchString(gvr.Version) }, - // allows users to address all beta api versions - APIBeta: func(gvr schema.GroupVersionResource) bool { return betaPattern.MatchString(gvr.Version) }, - // allows users to address all alpha api versions - APIAlpha: func(gvr schema.GroupVersionResource) bool { return alphaPattern.MatchString(gvr.Version) }, - } ) -func resourceMatcherForVersion(gv schema.GroupVersion) func(gvr schema.GroupVersionResource) bool { - return func(gvr schema.GroupVersionResource) bool { - return gv == gvr.GroupVersion() - } -} - // MergeAPIResourceConfigs merges the given defaultAPIResourceConfig with the given resourceConfigOverrides. // Exclude the groups not registered in registry, and check if version is // not registered in group, then it will fail. @@ -115,8 +98,6 @@ func MergeAPIResourceConfigs( } else { return nil, fmt.Errorf("invalid value %v=%v", flag, value) } - // remove individual resource preferences that were hardcoded into the default. The override trumps those settings. - resourceConfig.RemoveMatchingResourcePreferences(groupVersionResourceMatchers[flag]) } } @@ -187,8 +168,6 @@ func MergeAPIResourceConfigs( // apply version preferences first, so that we can remove the hardcoded resource preferences that are being overridden for _, versionPreference := range versionPreferences { - // if a user has expressed a preference about a version, that preference takes priority over the hardcoded resources - resourceConfig.RemoveMatchingResourcePreferences(resourceMatcherForVersion(versionPreference.groupVersion)) if versionPreference.enabled { // enable the groupVersion for "group/version=true" resourceConfig.EnableVersions(versionPreference.groupVersion) diff --git a/staging/src/k8s.io/apiserver/pkg/server/resourceconfig/helpers_test.go b/staging/src/k8s.io/apiserver/pkg/server/resourceconfig/helpers_test.go index cd27e16f566..71ba229dd4e 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/resourceconfig/helpers_test.go +++ b/staging/src/k8s.io/apiserver/pkg/server/resourceconfig/helpers_test.go @@ -80,8 +80,15 @@ func TestParseRuntimeConfig(t *testing.T) { config.DisableVersions(extensionsapiv1beta1.SchemeGroupVersion) return config }, - expectedEnabledAPIs: defaultFakeEnabledResources(), - err: false, + expectedEnabledAPIs: map[schema.GroupVersionResource]bool{ + extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"): false, // this becomes false because the DisableVersions set in the defaultConfig is now order dependent. + extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"): false, + extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets"): false, + extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets"): false, + appsv1.SchemeGroupVersion.WithResource("deployments"): true, + apiv1.SchemeGroupVersion.WithResource("pods"): true, + }, + err: false, }, { name: "version-enabled-by-runtimeConfig-override", @@ -147,8 +154,6 @@ func TestParseRuntimeConfig(t *testing.T) { expectedAPIConfig: func() *serverstore.ResourceConfig { config := newFakeAPIResourceConfigSource() config.EnableVersions(scheme.PrioritizedVersionsAllGroups()...) - // disabling groups of APIs removes the individual resource preferences from the default - config.RemoveMatchingResourcePreferences(matchAllExplicitResourcesForFake) return config }, expectedEnabledAPIs: map[schema.GroupVersionResource]bool{ @@ -174,8 +179,6 @@ func TestParseRuntimeConfig(t *testing.T) { config := newFakeAPIResourceConfigSource() config.DisableVersions(appsv1.SchemeGroupVersion) config.DisableVersions(extensionsapiv1beta1.SchemeGroupVersion) - // disabling groups of APIs removes the individual resource preferences from the default - config.RemoveMatchingResourcePreferences(matchAllExplicitResourcesForFake) return config }, expectedEnabledAPIs: map[schema.GroupVersionResource]bool{ @@ -243,8 +246,6 @@ func TestParseRuntimeConfig(t *testing.T) { expectedAPIConfig: func() *serverstore.ResourceConfig { config := newFakeAPIResourceConfigSource() config.DisableVersions(extensionsapiv1beta1.SchemeGroupVersion) - // disabling groups of APIs removes the individual resource preferences from the default - config.RemoveMatchingResourcePreferences(matchAllExplicitResourcesForFake) return config }, expectedEnabledAPIs: map[schema.GroupVersionResource]bool{ @@ -290,8 +291,6 @@ func TestParseRuntimeConfig(t *testing.T) { expectedAPIConfig: func() *serverstore.ResourceConfig { config := newFakeAPIResourceConfigSource() config.DisableVersions(extensionsapiv1beta1.SchemeGroupVersion) - // disabling groups of APIs removes the individual resource preferences from the default - config.RemoveMatchingResourcePreferences(matchAllExplicitResourcesForFake) return config }, expectedEnabledAPIs: map[schema.GroupVersionResource]bool{ @@ -568,17 +567,6 @@ func newFakeAPIResourceConfigSource() *serverstore.ResourceConfig { return ret } -func matchAllExplicitResourcesForFake(gvr schema.GroupVersionResource) bool { - switch gvr { - case extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"), - extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"), - extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets"), - extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets"): - return true - } - return false -} - // apiResourcesToCheck are the apis we use in this set of unit tests. They will be check for enable/disable status func apiResourcesToCheck() []schema.GroupVersionResource { return []schema.GroupVersionResource{ diff --git a/staging/src/k8s.io/apiserver/pkg/server/storage/resource_config.go b/staging/src/k8s.io/apiserver/pkg/server/storage/resource_config.go index 7a409f566c7..ce8d1822aa0 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/storage/resource_config.go +++ b/staging/src/k8s.io/apiserver/pkg/server/storage/resource_config.go @@ -37,27 +37,38 @@ func NewResourceConfig() *ResourceConfig { return &ResourceConfig{GroupVersionConfigs: map[schema.GroupVersion]bool{}, ResourceConfigs: map[schema.GroupVersionResource]bool{}} } -// DisableMatchingVersions disables all group/versions for which the matcher function returns true. It does not modify individual resource enablement/disablement. +// DisableMatchingVersions disables all group/versions for which the matcher function returns true. +// This will remove any preferences previously set on individual resources. func (o *ResourceConfig) DisableMatchingVersions(matcher func(gv schema.GroupVersion) bool) { - for k := range o.GroupVersionConfigs { - if matcher(k) { - o.GroupVersionConfigs[k] = false + for version := range o.GroupVersionConfigs { + if matcher(version) { + o.GroupVersionConfigs[version] = false + o.removeMatchingResourcePreferences(resourceMatcherForVersion(version)) } } } -// EnableMatchingVersions enables all group/versions for which the matcher function returns true. It does not modify individual resource enablement/disablement. +// EnableMatchingVersions enables all group/versions for which the matcher function returns true. +// This will remove any preferences previously set on individual resources. func (o *ResourceConfig) EnableMatchingVersions(matcher func(gv schema.GroupVersion) bool) { - for k := range o.GroupVersionConfigs { - if matcher(k) { - o.GroupVersionConfigs[k] = true + for version := range o.GroupVersionConfigs { + if matcher(version) { + o.GroupVersionConfigs[version] = true + o.removeMatchingResourcePreferences(resourceMatcherForVersion(version)) } } } -// RemoveMatchingResourcePreferences removes individual resource preferences that match. This is useful when an override of a version or level enablement should +// resourceMatcherForVersion matches resources in the specified version +func resourceMatcherForVersion(gv schema.GroupVersion) func(gvr schema.GroupVersionResource) bool { + return func(gvr schema.GroupVersionResource) bool { + return gv == gvr.GroupVersion() + } +} + +// removeMatchingResourcePreferences removes individual resource preferences that match. This is useful when an override of a version or level enablement should // override the previously individual preferences. -func (o *ResourceConfig) RemoveMatchingResourcePreferences(matcher func(gvr schema.GroupVersionResource) bool) { +func (o *ResourceConfig) removeMatchingResourcePreferences(matcher func(gvr schema.GroupVersionResource) bool) { keysToRemove := []schema.GroupVersionResource{} for k := range o.ResourceConfigs { if matcher(k) { @@ -70,20 +81,30 @@ func (o *ResourceConfig) RemoveMatchingResourcePreferences(matcher func(gvr sche } // DisableVersions disables the versions entirely. +// This will remove any preferences previously set on individual resources. func (o *ResourceConfig) DisableVersions(versions ...schema.GroupVersion) { for _, version := range versions { o.GroupVersionConfigs[version] = false + + // a preference about a version takes priority over the previously set resources + o.removeMatchingResourcePreferences(resourceMatcherForVersion(version)) } } +// EnableVersions enables all resources in a given groupVersion. +// This will remove any preferences previously set on individual resources. func (o *ResourceConfig) EnableVersions(versions ...schema.GroupVersion) { for _, version := range versions { o.GroupVersionConfigs[version] = true + + // a preference about a version takes priority over the previously set resources + o.removeMatchingResourcePreferences(resourceMatcherForVersion(version)) } + } // TODO this must be removed and we enable/disable individual resources. -func (o *ResourceConfig) VersionEnabled(version schema.GroupVersion) bool { +func (o *ResourceConfig) versionEnabled(version schema.GroupVersion) bool { enabled, _ := o.GroupVersionConfigs[version] return enabled } @@ -107,7 +128,7 @@ func (o *ResourceConfig) ResourceEnabled(resource schema.GroupVersionResource) b return resourceEnabled } - if !o.VersionEnabled(resource.GroupVersion()) { + if !o.versionEnabled(resource.GroupVersion()) { return false } // they are enabled by default. @@ -117,7 +138,7 @@ func (o *ResourceConfig) ResourceEnabled(resource schema.GroupVersionResource) b func (o *ResourceConfig) AnyResourceForGroupEnabled(group string) bool { for version := range o.GroupVersionConfigs { if version.Group == group { - if o.VersionEnabled(version) { + if o.versionEnabled(version) { return true } } diff --git a/staging/src/k8s.io/apiserver/pkg/server/storage/resource_config_test.go b/staging/src/k8s.io/apiserver/pkg/server/storage/resource_config_test.go index 431179115bd..dcbf8f8dcf0 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/storage/resource_config_test.go +++ b/staging/src/k8s.io/apiserver/pkg/server/storage/resource_config_test.go @@ -32,13 +32,13 @@ func TestDisabledVersion(t *testing.T) { config.DisableVersions(g1v1) config.EnableVersions(g1v2, g2v1) - if config.VersionEnabled(g1v1) { + if config.versionEnabled(g1v1) { t.Errorf("expected disabled for %v, from %v", g1v1, config) } - if !config.VersionEnabled(g1v2) { + if !config.versionEnabled(g1v2) { t.Errorf("expected enabled for %v, from %v", g1v1, config) } - if !config.VersionEnabled(g2v1) { + if !config.versionEnabled(g2v1) { t.Errorf("expected enabled for %v, from %v", g1v1, config) } } diff --git a/staging/src/k8s.io/apiserver/pkg/server/storage/storage_factory.go b/staging/src/k8s.io/apiserver/pkg/server/storage/storage_factory.go index dfe8d4104a7..d8de4cd84fb 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/storage/storage_factory.go +++ b/staging/src/k8s.io/apiserver/pkg/server/storage/storage_factory.go @@ -240,6 +240,7 @@ func getAllResourcesAlias(resource schema.GroupResource) schema.GroupResource { func (s *DefaultStorageFactory) getStorageGroupResource(groupResource schema.GroupResource) schema.GroupResource { for _, potentialStorageResource := range s.Overrides[groupResource].cohabitatingResources { + // TODO deads2k or liggitt determine if have ever stored any of our cohabitating resources in a different location on new clusters if s.APIResourceConfigSource.AnyResourceForGroupEnabled(potentialStorageResource.Group) { return potentialStorageResource } diff --git a/test/integration/apiserver/no_new_betas_test.go b/test/integration/apiserver/no_new_betas_test.go new file mode 100644 index 00000000000..af7a6e5196b --- /dev/null +++ b/test/integration/apiserver/no_new_betas_test.go @@ -0,0 +1,96 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package apiserver + +import ( + "strings" + "testing" + + "k8s.io/apimachinery/pkg/runtime/schema" +) + +func TestNoNewBetaAPIsByDefault(t *testing.T) { + // yes, this *is* a copy/paste from somewhere else. We really do mean it when we say you shouldn't be modifying + // this list and this test was created to make it more painful. + // legacyBetaEnabledByDefaultResources is the list of beta resources we enable. You may not add to this list + legacyBetaEnabledByDefaultResources := map[schema.GroupVersionResource]bool{ + gvr("autoscaling", "v2beta1", "horizontalpodautoscalers"): true, // remove in 1.25 + gvr("autoscaling", "v2beta2", "horizontalpodautoscalers"): true, // remove in 1.26 + gvr("batch", "v1beta1", "jobtemplates"): true, // remove in 1.25 + gvr("batch", "v1beta1", "cronjobs"): true, // remove in 1.25 + gvr("discovery.k8s.io", "v1beta1", "endpointslices"): true, // remove in 1.25 + gvr("events.k8s.io", "v1beta1", "events"): true, // remove in 1.25 + gvr("node.k8s.io", "v1beta1", "runtimeclasses"): true, // remove in 1.25 + gvr("policy", "v1beta1", "poddisruptionbudgets"): true, // remove in 1.25 + gvr("policy", "v1beta1", "podsecuritypolicies"): true, // remove in 1.25 + gvr("storage.k8s.io", "v1beta1", "csinodes"): true, // remove in 1.25 + gvr("storage.k8s.io", "v1beta1", "csistoragecapacities"): true, // remove in 1.27 + gvr("flowcontrol.apiserver.k8s.io", "v1beta1", "flowschemas"): true, // remove in 1.26 + gvr("flowcontrol.apiserver.k8s.io", "v1beta1", "prioritylevelconfigurations"): true, // remove in 1.26 + gvr("flowcontrol.apiserver.k8s.io", "v1beta2", "flowschemas"): true, // remove in 1.29 + gvr("flowcontrol.apiserver.k8s.io", "v1beta2", "prioritylevelconfigurations"): true, // remove in 1.29 + } + + // legacyBetaResourcesWithoutStableEquivalents contains those groupresources that were enabled by default as beta + // before we changed that policy and do not have stable versions. These resources are allowed to have additional + // beta versions enabled by default. Nothing new should be added here. There are no future exceptions because there + // are no more beta resources enabled by default. + legacyBetaResourcesWithoutStableEquivalents := map[schema.GroupResource]bool{ + gvr("storage.k8s.io", "v1beta1", "csistoragecapacities").GroupResource(): true, + gvr("flowcontrol.apiserver.k8s.io", "v1beta1", "flowschemas").GroupResource(): true, + gvr("flowcontrol.apiserver.k8s.io", "v1beta1", "prioritylevelconfigurations").GroupResource(): true, + } + + // if you found this because you want to create an integration test for your new beta API, the method you're looking for + // is this setupWithResources method and you need to pass the resource you want to enable into it. + _, kubeClient, closeFn := setupWithResources(t, + []schema.GroupVersion{}, + []schema.GroupVersionResource{}, + ) + defer closeFn() + + _, allResourceLists, err := kubeClient.Discovery().ServerGroupsAndResources() + if err != nil { + t.Error(err) + } + + for _, currResourceList := range allResourceLists { + for _, currResource := range currResourceList.APIResources { + if !strings.Contains(currResource.Version, "beta") { + continue // skip non-beta apis + } + if strings.Contains(currResource.Name, "/") { + continue // skip subresources + } + enabledGVR := schema.GroupVersionResource{ + Group: currResource.Group, + Version: currResource.Version, + Resource: currResource.Name, + } + if legacyBetaEnabledByDefaultResources[enabledGVR] { + continue + } + if legacyBetaResourcesWithoutStableEquivalents[enabledGVR.GroupResource()] { + continue + } + + t.Errorf("%v is a new beta API. New beta APIs may not be enabled by default. "+ + "See https://github.com/kubernetes/enhancements/blob/0ad0fc8269165ca300d05ca51c7ce190a79976a5/keps/sig-architecture/3136-beta-apis-off-by-default/README.md "+ + "for more details.", enabledGVR) + } + } +}