From 5ed33dc31d69be8f8099d738693ada94a8242518 Mon Sep 17 00:00:00 2001 From: David Eads Date: Wed, 12 Jul 2023 18:27:27 -0400 Subject: [PATCH] add list of served versions to storage version Kubernetes-commit: 90ab7580aaeca1c6e949df15554ad5bc408dca8e --- pkg/endpoints/groupversion.go | 5 +++++ pkg/endpoints/installer.go | 3 +++ pkg/server/genericapiserver.go | 17 +++++++++++++++-- pkg/storageversion/manager.go | 17 ++++++++--------- 4 files changed, 31 insertions(+), 11 deletions(-) diff --git a/pkg/endpoints/groupversion.go b/pkg/endpoints/groupversion.go index 3c70e89ec..0ce06ab10 100644 --- a/pkg/endpoints/groupversion.go +++ b/pkg/endpoints/groupversion.go @@ -56,6 +56,11 @@ type APIGroupVersion struct { // GroupVersion is the external group version GroupVersion schema.GroupVersion + // AllServedVersionsByResource is indexed by resource and maps to a list of versions that resource exists in. + // This was created so that StorageVersion for APIs can include a list of all version that are served for each + // GroupResource tuple. + AllServedVersionsByResource map[string][]string + // OptionsExternalVersion controls the Kubernetes APIVersion used for common objects in the apiserver // schema like api.Status, api.DeleteOptions, and metav1.ListOptions. Other implementors may // define a version "v1beta1" but want to use the Kubernetes "v1" internal objects. If diff --git a/pkg/endpoints/installer.go b/pkg/endpoints/installer.go index f1adddba5..342c3b3d2 100644 --- a/pkg/endpoints/installer.go +++ b/pkg/endpoints/installer.go @@ -600,6 +600,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag if a.group.ConvertabilityChecker != nil { decodableVersions = a.group.ConvertabilityChecker.VersionsForGroupKind(fqKindToRegister.GroupKind()) } + resourceInfo = &storageversion.ResourceInfo{ GroupResource: schema.GroupResource{ Group: a.group.GroupVersion.Group, @@ -612,6 +613,8 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag EquivalentResourceMapper: a.group.EquivalentResourceRegistry, DirectlyDecodableVersions: decodableVersions, + + ServedVersions: a.group.AllServedVersionsByResource[path], } } diff --git a/pkg/server/genericapiserver.go b/pkg/server/genericapiserver.go index 794a5db2f..665f20beb 100644 --- a/pkg/server/genericapiserver.go +++ b/pkg/server/genericapiserver.go @@ -911,9 +911,22 @@ func (s *GenericAPIServer) getAPIGroupVersion(apiGroupInfo *APIGroupInfo, groupV } func (s *GenericAPIServer) newAPIGroupVersion(apiGroupInfo *APIGroupInfo, groupVersion schema.GroupVersion) *genericapi.APIGroupVersion { + + allServedVersionsByResource := map[string][]string{} + for version, resourcesInVersion := range apiGroupInfo.VersionedResourcesStorageMap { + for resource := range resourcesInVersion { + if len(groupVersion.Group) == 0 { + allServedVersionsByResource[resource] = append(allServedVersionsByResource[resource], version) + } else { + allServedVersionsByResource[resource] = append(allServedVersionsByResource[resource], fmt.Sprintf("%s/%s", groupVersion.Group, version)) + } + } + } + return &genericapi.APIGroupVersion{ - GroupVersion: groupVersion, - MetaGroupVersion: apiGroupInfo.MetaGroupVersion, + GroupVersion: groupVersion, + AllServedVersionsByResource: allServedVersionsByResource, + MetaGroupVersion: apiGroupInfo.MetaGroupVersion, ParameterCodec: apiGroupInfo.ParameterCodec, Serializer: apiGroupInfo.NegotiatedSerializer, diff --git a/pkg/storageversion/manager.go b/pkg/storageversion/manager.go index 87ab4ac78..d7d386311 100644 --- a/pkg/storageversion/manager.go +++ b/pkg/storageversion/manager.go @@ -25,7 +25,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" utilruntime "k8s.io/apimachinery/pkg/util/runtime" - serverstorage "k8s.io/apiserver/pkg/server/storage" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" _ "k8s.io/component-base/metrics/prometheus/workqueue" // for workqueue metric registration @@ -45,6 +44,10 @@ type ResourceInfo struct { // DirectlyDecodableVersions is a list of versions that the converter for REST storage knows how to convert. This // contains items like apiextensions.k8s.io/v1beta1 even if we don't serve that version. DirectlyDecodableVersions []schema.GroupVersion + + // ServedVersions holds a list of all versions of GroupResource that are served. Note that a server may be able to + // decode a particular version, but still not serve it. + ServedVersions []string } // Manager records the resources whose StorageVersions need updates, and provides a method to update those StorageVersions. @@ -52,7 +55,7 @@ type Manager interface { // AddResourceInfo records resources whose StorageVersions need updates AddResourceInfo(resources ...*ResourceInfo) // UpdateStorageVersions tries to update the StorageVersions of the recorded resources - UpdateStorageVersions(kubeAPIServerClientConfig *rest.Config, apiserverID string, apiResourceConfigSource serverstorage.APIResourceConfigSource) + UpdateStorageVersions(kubeAPIServerClientConfig *rest.Config, apiserverID string) // PendingUpdate returns true if the StorageVersion of the given resource is still pending update. PendingUpdate(gr schema.GroupResource) bool // LastUpdateError returns the last error hit when updating the storage version of the given resource. @@ -112,7 +115,7 @@ func (s *defaultManager) addPendingManagedStatusLocked(r *ResourceInfo) { } // UpdateStorageVersions tries to update the StorageVersions of the recorded resources -func (s *defaultManager) UpdateStorageVersions(kubeAPIServerClientConfig *rest.Config, serverID string, apiResourceConfigSource serverstorage.APIResourceConfigSource) { +func (s *defaultManager) UpdateStorageVersions(kubeAPIServerClientConfig *rest.Config, serverID string) { clientset, err := kubernetes.NewForConfig(kubeAPIServerClientConfig) if err != nil { utilruntime.HandleError(fmt.Errorf("failed to get clientset: %v", err)) @@ -145,12 +148,8 @@ func (s *defaultManager) UpdateStorageVersions(kubeAPIServerClientConfig *rest.C gr.Group = "core" } - servedVersions := []string{} - for _, dv := range decodableVersions { - if apiResourceConfigSource.ResourceEnabled(gr.WithVersion(dv)) { - servedVersions = append(servedVersions, dv) - } - } + servedVersions := r.ServedVersions + if err := updateStorageVersionFor(sc, serverID, gr, r.EncodingVersion, decodableVersions, servedVersions); err != nil { utilruntime.HandleError(fmt.Errorf("failed to update storage version for %v: %v", r.GroupResource, err)) s.recordStatusFailure(&r, err)