Merge pull request #54683 from liggitt/subresource-gvk
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. Fix subresource discovery and versioning Fixes https://github.com/kubernetes/kubernetes/issues/54684 Related to https://github.com/kubernetes/kubernetes/pull/54586 Allows distinct subresource group/version/kind to be used for each version (gives us a path to move to autoscaling/v1 for apps, or policy/v1 for eviction, etc) Added tests to ensure scale subresources have expected discovery info, and that the object returned matches discovery, and that the endpoint accepts the advertised version ```release-note Fixes discovery information for scale subresources in the apps API group ``` Kubernetes-commit: 0c1f25fc1ba118ade226dad74052e4e45a16bcb6
This commit is contained in:
commit
dc5f59979b
|
|
@ -3868,6 +3868,7 @@ func TestUpdateChecksAPIVersion(t *testing.T) {
|
||||||
|
|
||||||
type SimpleXGSubresourceRESTStorage struct {
|
type SimpleXGSubresourceRESTStorage struct {
|
||||||
item genericapitesting.SimpleXGSubresource
|
item genericapitesting.SimpleXGSubresource
|
||||||
|
itemGVK schema.GroupVersionKind
|
||||||
}
|
}
|
||||||
|
|
||||||
func (storage *SimpleXGSubresourceRESTStorage) New() runtime.Object {
|
func (storage *SimpleXGSubresourceRESTStorage) New() runtime.Object {
|
||||||
|
|
@ -3878,6 +3879,12 @@ func (storage *SimpleXGSubresourceRESTStorage) Get(ctx request.Context, id strin
|
||||||
return storage.item.DeepCopyObject(), nil
|
return storage.item.DeepCopyObject(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ = rest.GroupVersionKindProvider(&SimpleXGSubresourceRESTStorage{})
|
||||||
|
|
||||||
|
func (storage *SimpleXGSubresourceRESTStorage) GroupVersionKind(containingGV schema.GroupVersion) schema.GroupVersionKind {
|
||||||
|
return storage.itemGVK
|
||||||
|
}
|
||||||
|
|
||||||
func TestXGSubresource(t *testing.T) {
|
func TestXGSubresource(t *testing.T) {
|
||||||
container := restful.NewContainer()
|
container := restful.NewContainer()
|
||||||
container.Router(restful.CurlyRouter{})
|
container.Router(restful.CurlyRouter{})
|
||||||
|
|
@ -3888,6 +3895,7 @@ func TestXGSubresource(t *testing.T) {
|
||||||
item: genericapitesting.SimpleXGSubresource{
|
item: genericapitesting.SimpleXGSubresource{
|
||||||
SubresourceInfo: "foo",
|
SubresourceInfo: "foo",
|
||||||
},
|
},
|
||||||
|
itemGVK: testGroup2Version.WithKind("SimpleXGSubresource"),
|
||||||
}
|
}
|
||||||
storage := map[string]rest.Storage{
|
storage := map[string]rest.Storage{
|
||||||
"simple": &SimpleRESTStorage{},
|
"simple": &SimpleRESTStorage{},
|
||||||
|
|
@ -3913,10 +3921,6 @@ func TestXGSubresource(t *testing.T) {
|
||||||
GroupVersion: testGroupVersion,
|
GroupVersion: testGroupVersion,
|
||||||
OptionsExternalVersion: &testGroupVersion,
|
OptionsExternalVersion: &testGroupVersion,
|
||||||
Serializer: codecs,
|
Serializer: codecs,
|
||||||
|
|
||||||
SubresourceGroupVersionKind: map[string]schema.GroupVersionKind{
|
|
||||||
"simple/subsimple": testGroup2Version.WithKind("SimpleXGSubresource"),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := (&group).InstallREST(container); err != nil {
|
if err := (&group).InstallREST(container); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -75,12 +75,6 @@ type APIGroupVersion struct {
|
||||||
|
|
||||||
MinRequestTimeout time.Duration
|
MinRequestTimeout time.Duration
|
||||||
|
|
||||||
// SubresourceGroupVersionKind contains the GroupVersionKind overrides for each subresource that is
|
|
||||||
// accessible from this API group version. The GroupVersionKind is that of the external version of
|
|
||||||
// the subresource. The key of this map should be the path of the subresource. The keys here should
|
|
||||||
// match the keys in the Storage map above for subresources.
|
|
||||||
SubresourceGroupVersionKind map[string]schema.GroupVersionKind
|
|
||||||
|
|
||||||
// EnableAPIResponseCompression indicates whether API Responses should support compression
|
// EnableAPIResponseCompression indicates whether API Responses should support compression
|
||||||
// if the client requests it via Accept-Encoding
|
// if the client requests it via Accept-Encoding
|
||||||
EnableAPIResponseCompression bool
|
EnableAPIResponseCompression bool
|
||||||
|
|
|
||||||
|
|
@ -144,8 +144,9 @@ func (a *APIInstaller) newWebService() *restful.WebService {
|
||||||
// object. If the storage object is a subresource and has an override supplied for it, it returns
|
// object. If the storage object is a subresource and has an override supplied for it, it returns
|
||||||
// the group version kind supplied in the override.
|
// the group version kind supplied in the override.
|
||||||
func (a *APIInstaller) getResourceKind(path string, storage rest.Storage) (schema.GroupVersionKind, error) {
|
func (a *APIInstaller) getResourceKind(path string, storage rest.Storage) (schema.GroupVersionKind, error) {
|
||||||
if fqKindToRegister, ok := a.group.SubresourceGroupVersionKind[path]; ok {
|
// Let the storage tell us exactly what GVK it has
|
||||||
return fqKindToRegister, nil
|
if gvkProvider, ok := storage.(rest.GroupVersionKindProvider); ok {
|
||||||
|
return gvkProvider.GroupVersionKind(a.group.GroupVersion), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
object := storage.New()
|
object := storage.New()
|
||||||
|
|
@ -162,12 +163,6 @@ func (a *APIInstaller) getResourceKind(path string, storage rest.Storage) (schem
|
||||||
fqKindToRegister = a.group.GroupVersion.WithKind(fqKind.Kind)
|
fqKindToRegister = a.group.GroupVersion.WithKind(fqKind.Kind)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: keep rid of extensions api group dependency here
|
|
||||||
// This keeps it doing what it was doing before, but it doesn't feel right.
|
|
||||||
if fqKind.Group == "extensions" && fqKind.Kind == "ThirdPartyResourceData" {
|
|
||||||
fqKindToRegister = a.group.GroupVersion.WithKind(fqKind.Kind)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if fqKindToRegister.Empty() {
|
if fqKindToRegister.Empty() {
|
||||||
return schema.GroupVersionKind{}, fmt.Errorf("unable to locate fully qualified kind for %v: found %v when registering for %v", reflect.TypeOf(object), fqKinds, a.group.GroupVersion)
|
return schema.GroupVersionKind{}, fmt.Errorf("unable to locate fully qualified kind for %v: found %v when registering for %v", reflect.TypeOf(object), fqKinds, a.group.GroupVersion)
|
||||||
|
|
@ -878,7 +873,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
||||||
apiResource.Categories = categoriesProvider.Categories()
|
apiResource.Categories = categoriesProvider.Categories()
|
||||||
}
|
}
|
||||||
if gvkProvider, ok := storage.(rest.GroupVersionKindProvider); ok {
|
if gvkProvider, ok := storage.(rest.GroupVersionKindProvider); ok {
|
||||||
gvk := gvkProvider.GroupVersionKind()
|
gvk := gvkProvider.GroupVersionKind(a.group.GroupVersion)
|
||||||
apiResource.Group = gvk.Group
|
apiResource.Group = gvk.Group
|
||||||
apiResource.Version = gvk.Version
|
apiResource.Version = gvk.Version
|
||||||
apiResource.Kind = gvk.Kind
|
apiResource.Kind = gvk.Kind
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ type CategoriesProvider interface {
|
||||||
// This trumps KindProvider since it is capable of providing the information required.
|
// This trumps KindProvider since it is capable of providing the information required.
|
||||||
// TODO KindProvider (only used by federation) should be removed and replaced with this, but that presents greater risk late in 1.8.
|
// TODO KindProvider (only used by federation) should be removed and replaced with this, but that presents greater risk late in 1.8.
|
||||||
type GroupVersionKindProvider interface {
|
type GroupVersionKindProvider interface {
|
||||||
GroupVersionKind() schema.GroupVersionKind
|
GroupVersionKind(containingGV schema.GroupVersion) schema.GroupVersionKind
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lister is an object that can retrieve resources that match the provided field and label criteria.
|
// Lister is an object that can retrieve resources that match the provided field and label criteria.
|
||||||
|
|
|
||||||
|
|
@ -70,12 +70,6 @@ type APIGroupInfo struct {
|
||||||
NegotiatedSerializer runtime.NegotiatedSerializer
|
NegotiatedSerializer runtime.NegotiatedSerializer
|
||||||
// ParameterCodec performs conversions for query parameters passed to API calls
|
// ParameterCodec performs conversions for query parameters passed to API calls
|
||||||
ParameterCodec runtime.ParameterCodec
|
ParameterCodec runtime.ParameterCodec
|
||||||
|
|
||||||
// SubresourceGroupVersionKind contains the GroupVersionKind overrides for each subresource that is
|
|
||||||
// accessible from this API group version. The GroupVersionKind is that of the external version of
|
|
||||||
// the subresource. The key of this map should be the path of the subresource. The keys here should
|
|
||||||
// match the keys in the Storage map above for subresources.
|
|
||||||
SubresourceGroupVersionKind map[string]schema.GroupVersionKind
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenericAPIServer contains state for a Kubernetes cluster api server.
|
// GenericAPIServer contains state for a Kubernetes cluster api server.
|
||||||
|
|
@ -435,7 +429,6 @@ func (s *GenericAPIServer) newAPIGroupVersion(apiGroupInfo *APIGroupInfo, groupV
|
||||||
UnsafeConvertor: runtime.UnsafeObjectConvertor(apiGroupInfo.Scheme),
|
UnsafeConvertor: runtime.UnsafeObjectConvertor(apiGroupInfo.Scheme),
|
||||||
Defaulter: apiGroupInfo.Scheme,
|
Defaulter: apiGroupInfo.Scheme,
|
||||||
Typer: apiGroupInfo.Scheme,
|
Typer: apiGroupInfo.Scheme,
|
||||||
SubresourceGroupVersionKind: apiGroupInfo.SubresourceGroupVersionKind,
|
|
||||||
Linker: apiGroupInfo.GroupMeta.SelfLinker,
|
Linker: apiGroupInfo.GroupMeta.SelfLinker,
|
||||||
Mapper: apiGroupInfo.GroupMeta.RESTMapper,
|
Mapper: apiGroupInfo.GroupMeta.RESTMapper,
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue