provide directly decodable versions for storageversion API

Kubernetes-commit: fa03dee68cea605b285b00ae5b6ce22659d95026
This commit is contained in:
David Eads 2021-03-08 09:33:46 -05:00 committed by Kubernetes Publisher
parent 605b55af85
commit 3f9e652c39
4 changed files with 50 additions and 18 deletions

View File

@ -36,6 +36,13 @@ import (
openapiproto "k8s.io/kube-openapi/pkg/util/proto"
)
// ConvertabilityChecker indicates what versions a GroupKind is available in.
type ConvertabilityChecker interface {
// VersionsForGroupKind indicates what versions are available to convert a group kind. This determines
// what our decoding abilities are.
VersionsForGroupKind(gk schema.GroupKind) []schema.GroupVersion
}
// APIGroupVersion is a helper for exposing rest.Storage objects as http.Handlers via go-restful
// It handles URLs of the form:
// /${storage_key}[/${object_name}]
@ -67,13 +74,14 @@ type APIGroupVersion struct {
Serializer runtime.NegotiatedSerializer
ParameterCodec runtime.ParameterCodec
Typer runtime.ObjectTyper
Creater runtime.ObjectCreater
Convertor runtime.ObjectConvertor
Defaulter runtime.ObjectDefaulter
Linker runtime.SelfLinker
UnsafeConvertor runtime.ObjectConvertor
TypeConverter fieldmanager.TypeConverter
Typer runtime.ObjectTyper
Creater runtime.ObjectCreater
Convertor runtime.ObjectConvertor
ConvertabilityChecker ConvertabilityChecker
Defaulter runtime.ObjectDefaulter
Linker runtime.SelfLinker
UnsafeConvertor runtime.ObjectConvertor
TypeConverter fieldmanager.TypeConverter
EquivalentResourceRegistry runtime.EquivalentResourceRegistry

View File

@ -513,6 +513,10 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
if err != nil {
return nil, nil, err
}
decodableVersions := []schema.GroupVersion{}
if a.group.ConvertabilityChecker != nil {
decodableVersions = a.group.ConvertabilityChecker.VersionsForGroupKind(fqKindToRegister.GroupKind())
}
resourceInfo = &storageversion.ResourceInfo{
GroupResource: schema.GroupResource{
Group: a.group.GroupVersion.Group,
@ -523,6 +527,8 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
// DecodableVersions immediately because API installation must
// be completed first for us to know equivalent APIs
EquivalentResourceMapper: a.group.EquivalentResourceRegistry,
DirectlyDecodableVersions: decodableVersions,
}
}

View File

@ -549,14 +549,15 @@ func (s *GenericAPIServer) newAPIGroupVersion(apiGroupInfo *APIGroupInfo, groupV
GroupVersion: groupVersion,
MetaGroupVersion: apiGroupInfo.MetaGroupVersion,
ParameterCodec: apiGroupInfo.ParameterCodec,
Serializer: apiGroupInfo.NegotiatedSerializer,
Creater: apiGroupInfo.Scheme,
Convertor: apiGroupInfo.Scheme,
UnsafeConvertor: runtime.UnsafeObjectConvertor(apiGroupInfo.Scheme),
Defaulter: apiGroupInfo.Scheme,
Typer: apiGroupInfo.Scheme,
Linker: runtime.SelfLinker(meta.NewAccessor()),
ParameterCodec: apiGroupInfo.ParameterCodec,
Serializer: apiGroupInfo.NegotiatedSerializer,
Creater: apiGroupInfo.Scheme,
Convertor: apiGroupInfo.Scheme,
ConvertabilityChecker: apiGroupInfo.Scheme,
UnsafeConvertor: runtime.UnsafeObjectConvertor(apiGroupInfo.Scheme),
Defaulter: apiGroupInfo.Scheme,
Typer: apiGroupInfo.Scheme,
Linker: runtime.SelfLinker(meta.NewAccessor()),
EquivalentResourceRegistry: s.EquivalentResourceRegistry,

View File

@ -40,6 +40,10 @@ type ResourceInfo struct {
// Used to calculate decodable versions. Can only be used after all
// equivalent versions are registered by InstallREST.
EquivalentResourceMapper runtime.EquivalentResourceRegistry
// 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
}
// Manager records the resources whose StorageVersions need updates, and provides a method to update those StorageVersions.
@ -133,13 +137,13 @@ func (s *defaultManager) UpdateStorageVersions(kubeAPIServerClientConfig *rest.C
// StorageVersion objects have CommonEncodingVersion (each with one server registered).
sortResourceInfosByGroupResource(resources)
for _, r := range dedupResourceInfos(resources) {
dv := decodableVersions(r.EquivalentResourceMapper, r.GroupResource)
decodableVersions := decodableVersions(r.DirectlyDecodableVersions, r.EquivalentResourceMapper, r.GroupResource)
gr := r.GroupResource
// Group must be a valid subdomain in DNS (RFC 1123)
if len(gr.Group) == 0 {
gr.Group = "core"
}
if err := updateStorageVersionFor(sc, serverID, gr, r.EncodingVersion, dv); err != nil {
if err := updateStorageVersionFor(sc, serverID, gr, r.EncodingVersion, decodableVersions); err != nil {
utilruntime.HandleError(fmt.Errorf("failed to update storage version for %v: %v", r.GroupResource, err))
s.recordStatusFailure(&r, err)
hasFailure = true
@ -267,10 +271,23 @@ func (s *defaultManager) Completed() bool {
return s.completed.Load().(bool)
}
func decodableVersions(e runtime.EquivalentResourceRegistry, gr schema.GroupResource) []string {
func decodableVersions(directlyDecodableVersions []schema.GroupVersion, e runtime.EquivalentResourceRegistry, gr schema.GroupResource) []string {
var versions []string
for _, decodableVersions := range directlyDecodableVersions {
versions = append(versions, decodableVersions.String())
}
decodingGVRs := e.EquivalentResourcesFor(gr.WithVersion(""), "")
for _, v := range decodingGVRs {
found := false
for _, existingVersion := range versions {
if existingVersion == v.GroupVersion().String() {
found = true
}
}
if found {
continue
}
versions = append(versions, v.GroupVersion().String())
}
return versions