Use v2 types with agg discovery
This commit is contained in:
@@ -23,7 +23,7 @@ import (
|
|||||||
|
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
apidiscoveryv2 "k8s.io/api/apidiscovery/v2"
|
||||||
autoscaling "k8s.io/api/autoscaling/v1"
|
autoscaling "k8s.io/api/autoscaling/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
@@ -87,7 +87,7 @@ func (c *DiscoveryController) sync(version schema.GroupVersion) error {
|
|||||||
|
|
||||||
apiVersionsForDiscovery := []metav1.GroupVersionForDiscovery{}
|
apiVersionsForDiscovery := []metav1.GroupVersionForDiscovery{}
|
||||||
apiResourcesForDiscovery := []metav1.APIResource{}
|
apiResourcesForDiscovery := []metav1.APIResource{}
|
||||||
aggregatedApiResourcesForDiscovery := []apidiscoveryv2beta1.APIResourceDiscovery{}
|
aggregatedAPIResourcesForDiscovery := []apidiscoveryv2.APIResourceDiscovery{}
|
||||||
versionsForDiscoveryMap := map[metav1.GroupVersion]bool{}
|
versionsForDiscoveryMap := map[metav1.GroupVersion]bool{}
|
||||||
|
|
||||||
crds, err := c.crdLister.List(labels.Everything())
|
crds, err := c.crdLister.List(labels.Everything())
|
||||||
@@ -158,13 +158,13 @@ func (c *DiscoveryController) sync(version schema.GroupVersion) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if c.resourceManager != nil {
|
if c.resourceManager != nil {
|
||||||
var scope apidiscoveryv2beta1.ResourceScope
|
var scope apidiscoveryv2.ResourceScope
|
||||||
if crd.Spec.Scope == apiextensionsv1.NamespaceScoped {
|
if crd.Spec.Scope == apiextensionsv1.NamespaceScoped {
|
||||||
scope = apidiscoveryv2beta1.ScopeNamespace
|
scope = apidiscoveryv2.ScopeNamespace
|
||||||
} else {
|
} else {
|
||||||
scope = apidiscoveryv2beta1.ScopeCluster
|
scope = apidiscoveryv2.ScopeCluster
|
||||||
}
|
}
|
||||||
apiResourceDiscovery := apidiscoveryv2beta1.APIResourceDiscovery{
|
apiResourceDiscovery := apidiscoveryv2.APIResourceDiscovery{
|
||||||
Resource: crd.Status.AcceptedNames.Plural,
|
Resource: crd.Status.AcceptedNames.Plural,
|
||||||
SingularResource: crd.Status.AcceptedNames.Singular,
|
SingularResource: crd.Status.AcceptedNames.Singular,
|
||||||
Scope: scope,
|
Scope: scope,
|
||||||
@@ -178,7 +178,7 @@ func (c *DiscoveryController) sync(version schema.GroupVersion) error {
|
|||||||
Categories: crd.Status.AcceptedNames.Categories,
|
Categories: crd.Status.AcceptedNames.Categories,
|
||||||
}
|
}
|
||||||
if subresources != nil && subresources.Status != nil {
|
if subresources != nil && subresources.Status != nil {
|
||||||
apiResourceDiscovery.Subresources = append(apiResourceDiscovery.Subresources, apidiscoveryv2beta1.APISubresourceDiscovery{
|
apiResourceDiscovery.Subresources = append(apiResourceDiscovery.Subresources, apidiscoveryv2.APISubresourceDiscovery{
|
||||||
Subresource: "status",
|
Subresource: "status",
|
||||||
ResponseKind: &metav1.GroupVersionKind{
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
Group: version.Group,
|
Group: version.Group,
|
||||||
@@ -189,7 +189,7 @@ func (c *DiscoveryController) sync(version schema.GroupVersion) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
if subresources != nil && subresources.Scale != nil {
|
if subresources != nil && subresources.Scale != nil {
|
||||||
apiResourceDiscovery.Subresources = append(apiResourceDiscovery.Subresources, apidiscoveryv2beta1.APISubresourceDiscovery{
|
apiResourceDiscovery.Subresources = append(apiResourceDiscovery.Subresources, apidiscoveryv2.APISubresourceDiscovery{
|
||||||
Subresource: "scale",
|
Subresource: "scale",
|
||||||
ResponseKind: &metav1.GroupVersionKind{
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
Group: autoscaling.GroupName,
|
Group: autoscaling.GroupName,
|
||||||
@@ -200,7 +200,7 @@ func (c *DiscoveryController) sync(version schema.GroupVersion) error {
|
|||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
aggregatedApiResourcesForDiscovery = append(aggregatedApiResourcesForDiscovery, apiResourceDiscovery)
|
aggregatedAPIResourcesForDiscovery = append(aggregatedAPIResourcesForDiscovery, apiResourceDiscovery)
|
||||||
}
|
}
|
||||||
|
|
||||||
if subresources != nil && subresources.Status != nil {
|
if subresources != nil && subresources.Status != nil {
|
||||||
@@ -260,14 +260,14 @@ func (c *DiscoveryController) sync(version schema.GroupVersion) error {
|
|||||||
return apiResourcesForDiscovery
|
return apiResourcesForDiscovery
|
||||||
})))
|
})))
|
||||||
|
|
||||||
sort.Slice(aggregatedApiResourcesForDiscovery[:], func(i, j int) bool {
|
sort.Slice(aggregatedAPIResourcesForDiscovery, func(i, j int) bool {
|
||||||
return aggregatedApiResourcesForDiscovery[i].Resource < aggregatedApiResourcesForDiscovery[j].Resource
|
return aggregatedAPIResourcesForDiscovery[i].Resource < aggregatedAPIResourcesForDiscovery[j].Resource
|
||||||
})
|
})
|
||||||
if c.resourceManager != nil {
|
if c.resourceManager != nil {
|
||||||
c.resourceManager.AddGroupVersion(version.Group, apidiscoveryv2beta1.APIVersionDiscovery{
|
c.resourceManager.AddGroupVersion(version.Group, apidiscoveryv2.APIVersionDiscovery{
|
||||||
Freshness: apidiscoveryv2beta1.DiscoveryFreshnessCurrent,
|
Freshness: apidiscoveryv2.DiscoveryFreshnessCurrent,
|
||||||
Version: version.Version,
|
Version: version.Version,
|
||||||
Resources: aggregatedApiResourcesForDiscovery,
|
Resources: aggregatedAPIResourcesForDiscovery,
|
||||||
})
|
})
|
||||||
// Default priority for CRDs
|
// Default priority for CRDs
|
||||||
c.resourceManager.SetGroupVersionPriority(metav1.GroupVersion(version), 1000, 100)
|
c.resourceManager.SetGroupVersionPriority(metav1.GroupVersion(version), 1000, 100)
|
||||||
|
@@ -22,7 +22,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
apidiscoveryv2 "k8s.io/api/apidiscovery/v2"
|
||||||
v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||||
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake"
|
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake"
|
||||||
@@ -125,13 +125,13 @@ var coolBarCRD = &v1.CustomResourceDefinition{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var coolFooDiscovery apidiscoveryv2beta1.APIVersionDiscovery = apidiscoveryv2beta1.APIVersionDiscovery{
|
var coolFooDiscovery apidiscoveryv2.APIVersionDiscovery = apidiscoveryv2.APIVersionDiscovery{
|
||||||
Version: "v1",
|
Version: "v1",
|
||||||
Freshness: apidiscoveryv2beta1.DiscoveryFreshnessCurrent,
|
Freshness: apidiscoveryv2.DiscoveryFreshnessCurrent,
|
||||||
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
Resources: []apidiscoveryv2.APIResourceDiscovery{
|
||||||
{
|
{
|
||||||
Resource: "coolfoos",
|
Resource: "coolfoos",
|
||||||
Scope: apidiscoveryv2beta1.ScopeCluster,
|
Scope: apidiscoveryv2.ScopeCluster,
|
||||||
SingularResource: "coolfoo",
|
SingularResource: "coolfoo",
|
||||||
Verbs: []string{"delete", "deletecollection", "get", "list", "patch", "create", "update", "watch"},
|
Verbs: []string{"delete", "deletecollection", "get", "list", "patch", "create", "update", "watch"},
|
||||||
ShortNames: []string{"foo"},
|
ShortNames: []string{"foo"},
|
||||||
@@ -141,7 +141,7 @@ var coolFooDiscovery apidiscoveryv2beta1.APIVersionDiscovery = apidiscoveryv2bet
|
|||||||
Version: "v1",
|
Version: "v1",
|
||||||
Kind: "CoolFoo",
|
Kind: "CoolFoo",
|
||||||
},
|
},
|
||||||
Subresources: []apidiscoveryv2beta1.APISubresourceDiscovery{
|
Subresources: []apidiscoveryv2.APISubresourceDiscovery{
|
||||||
{
|
{
|
||||||
Subresource: "status",
|
Subresource: "status",
|
||||||
Verbs: []string{"get", "patch", "update"},
|
Verbs: []string{"get", "patch", "update"},
|
||||||
@@ -157,13 +157,13 @@ var coolFooDiscovery apidiscoveryv2beta1.APIVersionDiscovery = apidiscoveryv2bet
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var mergedDiscovery apidiscoveryv2beta1.APIVersionDiscovery = apidiscoveryv2beta1.APIVersionDiscovery{
|
var mergedDiscovery apidiscoveryv2.APIVersionDiscovery = apidiscoveryv2.APIVersionDiscovery{
|
||||||
Version: "v1",
|
Version: "v1",
|
||||||
Freshness: apidiscoveryv2beta1.DiscoveryFreshnessCurrent,
|
Freshness: apidiscoveryv2.DiscoveryFreshnessCurrent,
|
||||||
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
Resources: []apidiscoveryv2.APIResourceDiscovery{
|
||||||
{
|
{
|
||||||
Resource: "coolbars",
|
Resource: "coolbars",
|
||||||
Scope: apidiscoveryv2beta1.ScopeCluster,
|
Scope: apidiscoveryv2.ScopeCluster,
|
||||||
SingularResource: "coolbar",
|
SingularResource: "coolbar",
|
||||||
Verbs: []string{"delete", "deletecollection", "get", "list", "patch", "create", "update", "watch"},
|
Verbs: []string{"delete", "deletecollection", "get", "list", "patch", "create", "update", "watch"},
|
||||||
ShortNames: []string{"bar"},
|
ShortNames: []string{"bar"},
|
||||||
@@ -175,7 +175,7 @@ var mergedDiscovery apidiscoveryv2beta1.APIVersionDiscovery = apidiscoveryv2beta
|
|||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
Resource: "coolfoos",
|
Resource: "coolfoos",
|
||||||
Scope: apidiscoveryv2beta1.ScopeCluster,
|
Scope: apidiscoveryv2.ScopeCluster,
|
||||||
SingularResource: "coolfoo",
|
SingularResource: "coolfoo",
|
||||||
Verbs: []string{"delete", "deletecollection", "get", "list", "patch", "create", "update", "watch"},
|
Verbs: []string{"delete", "deletecollection", "get", "list", "patch", "create", "update", "watch"},
|
||||||
ShortNames: []string{"foo"},
|
ShortNames: []string{"foo"},
|
||||||
@@ -185,7 +185,7 @@ var mergedDiscovery apidiscoveryv2beta1.APIVersionDiscovery = apidiscoveryv2beta
|
|||||||
Version: "v1",
|
Version: "v1",
|
||||||
Kind: "CoolFoo",
|
Kind: "CoolFoo",
|
||||||
},
|
},
|
||||||
Subresources: []apidiscoveryv2beta1.APISubresourceDiscovery{
|
Subresources: []apidiscoveryv2.APISubresourceDiscovery{
|
||||||
{
|
{
|
||||||
Subresource: "status",
|
Subresource: "status",
|
||||||
Verbs: []string{"get", "patch", "update"},
|
Verbs: []string{"get", "patch", "update"},
|
||||||
|
@@ -0,0 +1,226 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2024 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// This file was duplicated from the auto-generated file by conversion-gen in
|
||||||
|
// k8s.io/kubernetes/pkg/apis/apidiscovery Unlike most k8s types discovery is
|
||||||
|
// served by all apiservers and conversion is needed by all apiservers. The
|
||||||
|
// concept of internal/hub type does not exist for discovery as we work directly
|
||||||
|
// with the versioned types.
|
||||||
|
|
||||||
|
// The conversion code here facilities conversion strictly between v2beta1 and
|
||||||
|
// v2 types. It is only necessary in k8s versions where mixed state could be
|
||||||
|
// possible before the full removal of the v2beta1 types. It is placed in this
|
||||||
|
// directory such that all apiservers can benefit from the conversion without
|
||||||
|
// having to implement their own if the client/server they're communicating with
|
||||||
|
// only supports one version.
|
||||||
|
|
||||||
|
// Once the v2beta1 types are removed (intended for Kubernetes v1.33), this file
|
||||||
|
// will be removed.
|
||||||
|
package v2
|
||||||
|
|
||||||
|
import (
|
||||||
|
unsafe "unsafe"
|
||||||
|
|
||||||
|
v2 "k8s.io/api/apidiscovery/v2"
|
||||||
|
v2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
||||||
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||||
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RegisterConversions adds conversion functions to the given scheme.
|
||||||
|
// Public to allow building arbitrary schemes.
|
||||||
|
func RegisterConversions(s *runtime.Scheme) error {
|
||||||
|
if err := s.AddGeneratedConversionFunc((*v2beta1.APIGroupDiscovery)(nil), (*v2.APIGroupDiscovery)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
|
return Convertv2beta1APIGroupDiscoveryTov2APIGroupDiscovery(a.(*v2beta1.APIGroupDiscovery), b.(*v2.APIGroupDiscovery), scope)
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := s.AddGeneratedConversionFunc((*v2.APIGroupDiscovery)(nil), (*v2beta1.APIGroupDiscovery)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
|
return Convertv2APIGroupDiscoveryTov2beta1APIGroupDiscovery(a.(*v2.APIGroupDiscovery), b.(*v2beta1.APIGroupDiscovery), scope)
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := s.AddGeneratedConversionFunc((*v2beta1.APIGroupDiscoveryList)(nil), (*v2.APIGroupDiscoveryList)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
|
return Convertv2beta1APIGroupDiscoveryListTov2APIGroupDiscoveryList(a.(*v2beta1.APIGroupDiscoveryList), b.(*v2.APIGroupDiscoveryList), scope)
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := s.AddGeneratedConversionFunc((*v2.APIGroupDiscoveryList)(nil), (*v2beta1.APIGroupDiscoveryList)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
|
return Convertv2APIGroupDiscoveryListTov2beta1APIGroupDiscoveryList(a.(*v2.APIGroupDiscoveryList), b.(*v2beta1.APIGroupDiscoveryList), scope)
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := s.AddGeneratedConversionFunc((*v2beta1.APIResourceDiscovery)(nil), (*v2.APIResourceDiscovery)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
|
return Convertv2beta1APIResourceDiscoveryTov2APIResourceDiscovery(a.(*v2beta1.APIResourceDiscovery), b.(*v2.APIResourceDiscovery), scope)
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := s.AddGeneratedConversionFunc((*v2.APIResourceDiscovery)(nil), (*v2beta1.APIResourceDiscovery)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
|
return Convertv2APIResourceDiscoveryTov2beta1APIResourceDiscovery(a.(*v2.APIResourceDiscovery), b.(*v2beta1.APIResourceDiscovery), scope)
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := s.AddGeneratedConversionFunc((*v2beta1.APISubresourceDiscovery)(nil), (*v2.APISubresourceDiscovery)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
|
return Convertv2beta1APISubresourceDiscoveryTov2APISubresourceDiscovery(a.(*v2beta1.APISubresourceDiscovery), b.(*v2.APISubresourceDiscovery), scope)
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := s.AddGeneratedConversionFunc((*v2.APISubresourceDiscovery)(nil), (*v2beta1.APISubresourceDiscovery)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
|
return Convertv2APISubresourceDiscoveryTov2beta1APISubresourceDiscovery(a.(*v2.APISubresourceDiscovery), b.(*v2beta1.APISubresourceDiscovery), scope)
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := s.AddGeneratedConversionFunc((*v2beta1.APIVersionDiscovery)(nil), (*v2.APIVersionDiscovery)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
|
return Convertv2beta1APIVersionDiscoveryTov2APIVersionDiscovery(a.(*v2beta1.APIVersionDiscovery), b.(*v2.APIVersionDiscovery), scope)
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := s.AddGeneratedConversionFunc((*v2.APIVersionDiscovery)(nil), (*v2beta1.APIVersionDiscovery)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
|
return Convertv2APIVersionDiscoveryTov2beta1APIVersionDiscovery(a.(*v2.APIVersionDiscovery), b.(*v2beta1.APIVersionDiscovery), scope)
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func autoConvertv2beta1APIGroupDiscoveryTov2APIGroupDiscovery(in *v2beta1.APIGroupDiscovery, out *v2.APIGroupDiscovery, s conversion.Scope) error {
|
||||||
|
out.ObjectMeta = in.ObjectMeta
|
||||||
|
out.Versions = *(*[]v2.APIVersionDiscovery)(unsafe.Pointer(&in.Versions))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convertv2beta1APIGroupDiscoveryTov2APIGroupDiscovery is an autogenerated conversion function.
|
||||||
|
func Convertv2beta1APIGroupDiscoveryTov2APIGroupDiscovery(in *v2beta1.APIGroupDiscovery, out *v2.APIGroupDiscovery, s conversion.Scope) error {
|
||||||
|
return autoConvertv2beta1APIGroupDiscoveryTov2APIGroupDiscovery(in, out, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func autoConvertv2APIGroupDiscoveryTov2beta1APIGroupDiscovery(in *v2.APIGroupDiscovery, out *v2beta1.APIGroupDiscovery, s conversion.Scope) error {
|
||||||
|
out.ObjectMeta = in.ObjectMeta
|
||||||
|
out.Versions = *(*[]v2beta1.APIVersionDiscovery)(unsafe.Pointer(&in.Versions))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convertv2APIGroupDiscoveryTov2beta1APIGroupDiscovery is an autogenerated conversion function.
|
||||||
|
func Convertv2APIGroupDiscoveryTov2beta1APIGroupDiscovery(in *v2.APIGroupDiscovery, out *v2beta1.APIGroupDiscovery, s conversion.Scope) error {
|
||||||
|
return autoConvertv2APIGroupDiscoveryTov2beta1APIGroupDiscovery(in, out, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func autoConvertv2beta1APIGroupDiscoveryListTov2APIGroupDiscoveryList(in *v2beta1.APIGroupDiscoveryList, out *v2.APIGroupDiscoveryList, s conversion.Scope) error {
|
||||||
|
out.ListMeta = in.ListMeta
|
||||||
|
out.Items = *(*[]v2.APIGroupDiscovery)(unsafe.Pointer(&in.Items))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convertv2beta1APIGroupDiscoveryListTov2APIGroupDiscoveryList is an autogenerated conversion function.
|
||||||
|
func Convertv2beta1APIGroupDiscoveryListTov2APIGroupDiscoveryList(in *v2beta1.APIGroupDiscoveryList, out *v2.APIGroupDiscoveryList, s conversion.Scope) error {
|
||||||
|
return autoConvertv2beta1APIGroupDiscoveryListTov2APIGroupDiscoveryList(in, out, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func autoConvertv2APIGroupDiscoveryListTov2beta1APIGroupDiscoveryList(in *v2.APIGroupDiscoveryList, out *v2beta1.APIGroupDiscoveryList, s conversion.Scope) error {
|
||||||
|
out.ListMeta = in.ListMeta
|
||||||
|
out.Items = *(*[]v2beta1.APIGroupDiscovery)(unsafe.Pointer(&in.Items))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convertv2APIGroupDiscoveryListTov2beta1APIGroupDiscoveryList is an autogenerated conversion function.
|
||||||
|
func Convertv2APIGroupDiscoveryListTov2beta1APIGroupDiscoveryList(in *v2.APIGroupDiscoveryList, out *v2beta1.APIGroupDiscoveryList, s conversion.Scope) error {
|
||||||
|
return autoConvertv2APIGroupDiscoveryListTov2beta1APIGroupDiscoveryList(in, out, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func autoConvertv2beta1APIResourceDiscoveryTov2APIResourceDiscovery(in *v2beta1.APIResourceDiscovery, out *v2.APIResourceDiscovery, s conversion.Scope) error {
|
||||||
|
out.Resource = in.Resource
|
||||||
|
out.ResponseKind = (*v1.GroupVersionKind)(unsafe.Pointer(in.ResponseKind))
|
||||||
|
out.Scope = v2.ResourceScope(in.Scope)
|
||||||
|
out.SingularResource = in.SingularResource
|
||||||
|
out.Verbs = *(*[]string)(unsafe.Pointer(&in.Verbs))
|
||||||
|
out.ShortNames = *(*[]string)(unsafe.Pointer(&in.ShortNames))
|
||||||
|
out.Categories = *(*[]string)(unsafe.Pointer(&in.Categories))
|
||||||
|
out.Subresources = *(*[]v2.APISubresourceDiscovery)(unsafe.Pointer(&in.Subresources))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convertv2beta1APIResourceDiscoveryTov2APIResourceDiscovery is an autogenerated conversion function.
|
||||||
|
func Convertv2beta1APIResourceDiscoveryTov2APIResourceDiscovery(in *v2beta1.APIResourceDiscovery, out *v2.APIResourceDiscovery, s conversion.Scope) error {
|
||||||
|
return autoConvertv2beta1APIResourceDiscoveryTov2APIResourceDiscovery(in, out, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func autoConvertv2APIResourceDiscoveryTov2beta1APIResourceDiscovery(in *v2.APIResourceDiscovery, out *v2beta1.APIResourceDiscovery, s conversion.Scope) error {
|
||||||
|
out.Resource = in.Resource
|
||||||
|
out.ResponseKind = (*v1.GroupVersionKind)(unsafe.Pointer(in.ResponseKind))
|
||||||
|
out.Scope = v2beta1.ResourceScope(in.Scope)
|
||||||
|
out.SingularResource = in.SingularResource
|
||||||
|
out.Verbs = *(*[]string)(unsafe.Pointer(&in.Verbs))
|
||||||
|
out.ShortNames = *(*[]string)(unsafe.Pointer(&in.ShortNames))
|
||||||
|
out.Categories = *(*[]string)(unsafe.Pointer(&in.Categories))
|
||||||
|
out.Subresources = *(*[]v2beta1.APISubresourceDiscovery)(unsafe.Pointer(&in.Subresources))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convertv2APIResourceDiscoveryTov2beta1APIResourceDiscovery is an autogenerated conversion function.
|
||||||
|
func Convertv2APIResourceDiscoveryTov2beta1APIResourceDiscovery(in *v2.APIResourceDiscovery, out *v2beta1.APIResourceDiscovery, s conversion.Scope) error {
|
||||||
|
return autoConvertv2APIResourceDiscoveryTov2beta1APIResourceDiscovery(in, out, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func autoConvertv2beta1APISubresourceDiscoveryTov2APISubresourceDiscovery(in *v2beta1.APISubresourceDiscovery, out *v2.APISubresourceDiscovery, s conversion.Scope) error {
|
||||||
|
out.Subresource = in.Subresource
|
||||||
|
out.ResponseKind = (*v1.GroupVersionKind)(unsafe.Pointer(in.ResponseKind))
|
||||||
|
out.AcceptedTypes = *(*[]v1.GroupVersionKind)(unsafe.Pointer(&in.AcceptedTypes))
|
||||||
|
out.Verbs = *(*[]string)(unsafe.Pointer(&in.Verbs))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convertv2beta1APISubresourceDiscoveryTov2APISubresourceDiscovery is an autogenerated conversion function.
|
||||||
|
func Convertv2beta1APISubresourceDiscoveryTov2APISubresourceDiscovery(in *v2beta1.APISubresourceDiscovery, out *v2.APISubresourceDiscovery, s conversion.Scope) error {
|
||||||
|
return autoConvertv2beta1APISubresourceDiscoveryTov2APISubresourceDiscovery(in, out, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func autoConvertv2APISubresourceDiscoveryTov2beta1APISubresourceDiscovery(in *v2.APISubresourceDiscovery, out *v2beta1.APISubresourceDiscovery, s conversion.Scope) error {
|
||||||
|
out.Subresource = in.Subresource
|
||||||
|
out.ResponseKind = (*v1.GroupVersionKind)(unsafe.Pointer(in.ResponseKind))
|
||||||
|
out.AcceptedTypes = *(*[]v1.GroupVersionKind)(unsafe.Pointer(&in.AcceptedTypes))
|
||||||
|
out.Verbs = *(*[]string)(unsafe.Pointer(&in.Verbs))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convertv2APISubresourceDiscoveryTov2beta1APISubresourceDiscovery is an autogenerated conversion function.
|
||||||
|
func Convertv2APISubresourceDiscoveryTov2beta1APISubresourceDiscovery(in *v2.APISubresourceDiscovery, out *v2beta1.APISubresourceDiscovery, s conversion.Scope) error {
|
||||||
|
return autoConvertv2APISubresourceDiscoveryTov2beta1APISubresourceDiscovery(in, out, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func autoConvertv2beta1APIVersionDiscoveryTov2APIVersionDiscovery(in *v2beta1.APIVersionDiscovery, out *v2.APIVersionDiscovery, s conversion.Scope) error {
|
||||||
|
out.Version = in.Version
|
||||||
|
out.Resources = *(*[]v2.APIResourceDiscovery)(unsafe.Pointer(&in.Resources))
|
||||||
|
out.Freshness = v2.DiscoveryFreshness(in.Freshness)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convertv2beta1APIVersionDiscoveryTov2APIVersionDiscovery is an autogenerated conversion function.
|
||||||
|
func Convertv2beta1APIVersionDiscoveryTov2APIVersionDiscovery(in *v2beta1.APIVersionDiscovery, out *v2.APIVersionDiscovery, s conversion.Scope) error {
|
||||||
|
return autoConvertv2beta1APIVersionDiscoveryTov2APIVersionDiscovery(in, out, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func autoConvertv2APIVersionDiscoveryTov2beta1APIVersionDiscovery(in *v2.APIVersionDiscovery, out *v2beta1.APIVersionDiscovery, s conversion.Scope) error {
|
||||||
|
out.Version = in.Version
|
||||||
|
out.Resources = *(*[]v2beta1.APIResourceDiscovery)(unsafe.Pointer(&in.Resources))
|
||||||
|
out.Freshness = v2beta1.DiscoveryFreshness(in.Freshness)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convertv2APIVersionDiscoveryTov2beta1APIVersionDiscovery is an autogenerated conversion function.
|
||||||
|
func Convertv2APIVersionDiscoveryTov2beta1APIVersionDiscovery(in *v2.APIVersionDiscovery, out *v2beta1.APIVersionDiscovery, s conversion.Scope) error {
|
||||||
|
return autoConvertv2APIVersionDiscoveryTov2beta1APIVersionDiscovery(in, out, s)
|
||||||
|
}
|
19
staging/src/k8s.io/apiserver/pkg/apis/apidiscovery/v2/doc.go
Normal file
19
staging/src/k8s.io/apiserver/pkg/apis/apidiscovery/v2/doc.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2024 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// +groupName=apidiscovery.k8s.io
|
||||||
|
|
||||||
|
package v2 // import "k8s.io/apiserver/pkg/apis/apidiscovery/v2"
|
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2024 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 v2_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
v2 "k8s.io/api/apidiscovery/v2"
|
||||||
|
v2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
||||||
|
v2scheme "k8s.io/apiserver/pkg/apis/apidiscovery/v2"
|
||||||
|
v2beta1scheme "k8s.io/apiserver/pkg/apis/apidiscovery/v2beta1"
|
||||||
|
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
|
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
fuzz "github.com/google/gofuzz"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestConversionRoundTrip(t *testing.T) {
|
||||||
|
scheme := runtime.NewScheme()
|
||||||
|
err := v2beta1scheme.AddToScheme(scheme)
|
||||||
|
require.NoError(t, err)
|
||||||
|
v2scheme.SchemeBuilder.Register(v2scheme.RegisterConversions)
|
||||||
|
err = v2scheme.AddToScheme(scheme)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
fuzzer := fuzz.NewWithSeed(2374375)
|
||||||
|
|
||||||
|
// v2 -> v2beta1 -> v2
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
expected := &v2.APIGroupDiscoveryList{}
|
||||||
|
fuzzer.Fuzz(expected)
|
||||||
|
expected.TypeMeta = metav1.TypeMeta{
|
||||||
|
Kind: "APIGroupDiscoveryList",
|
||||||
|
APIVersion: "apidiscovery.k8s.io/v2",
|
||||||
|
}
|
||||||
|
o, err := scheme.ConvertToVersion(expected, v2beta1.SchemeGroupVersion)
|
||||||
|
require.NoError(t, err)
|
||||||
|
v2beta1Type := o.(*v2beta1.APIGroupDiscoveryList)
|
||||||
|
|
||||||
|
o2, err := scheme.ConvertToVersion(v2beta1Type, v2.SchemeGroupVersion)
|
||||||
|
require.NoError(t, err)
|
||||||
|
actual := o2.(*v2.APIGroupDiscoveryList)
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(expected, actual) {
|
||||||
|
t.Error(cmp.Diff(expected, actual))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// v2beta1 -> v2 -> v2beta1
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
expected := &v2beta1.APIGroupDiscoveryList{}
|
||||||
|
fuzzer.Fuzz(expected)
|
||||||
|
expected.TypeMeta = metav1.TypeMeta{
|
||||||
|
Kind: "APIGroupDiscoveryList",
|
||||||
|
APIVersion: "apidiscovery.k8s.io/v2beta1",
|
||||||
|
}
|
||||||
|
o, err := scheme.ConvertToVersion(expected, v2.SchemeGroupVersion)
|
||||||
|
require.NoError(t, err)
|
||||||
|
v2Type := o.(*v2.APIGroupDiscoveryList)
|
||||||
|
|
||||||
|
o2, err := scheme.ConvertToVersion(v2Type, v2beta1.SchemeGroupVersion)
|
||||||
|
require.NoError(t, err)
|
||||||
|
actual := o2.(*v2beta1.APIGroupDiscoveryList)
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(expected, actual) {
|
||||||
|
t.Error(cmp.Diff(expected, actual))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2024 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 v2
|
||||||
|
|
||||||
|
import (
|
||||||
|
apidiscoveryv2 "k8s.io/api/apidiscovery/v2"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GroupName is the group name use in this package
|
||||||
|
const GroupName = "apidiscovery.k8s.io"
|
||||||
|
|
||||||
|
// SchemeGroupVersion is group version used to register these objects
|
||||||
|
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v2"}
|
||||||
|
|
||||||
|
// Resource takes an unqualified resource and returns a Group qualified GroupResource
|
||||||
|
func Resource(resource string) schema.GroupResource {
|
||||||
|
return SchemeGroupVersion.WithResource(resource).GroupResource()
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
SchemeBuilder = &apidiscoveryv2.SchemeBuilder
|
||||||
|
// AddToScheme adds api to a scheme
|
||||||
|
AddToScheme = SchemeBuilder.AddToScheme
|
||||||
|
)
|
@@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// +groupName=apidiscovery.k8s.io
|
||||||
|
|
||||||
|
package v2beta1 // import "k8s.io/apiserver/pkg/apis/apidiscovery/v2beta1"
|
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
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 v2beta1
|
||||||
|
|
||||||
|
import (
|
||||||
|
apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GroupName is the group name use in this package
|
||||||
|
const GroupName = "apidiscovery.k8s.io"
|
||||||
|
|
||||||
|
// SchemeGroupVersion is group version used to register these objects
|
||||||
|
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v2beta1"}
|
||||||
|
|
||||||
|
// Resource takes an unqualified resource and returns a Group qualified GroupResource
|
||||||
|
func Resource(resource string) schema.GroupResource {
|
||||||
|
return SchemeGroupVersion.WithResource(resource).GroupResource()
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
localSchemeBuilder = &apidiscoveryv2beta1.SchemeBuilder
|
||||||
|
// AddToScheme adds api to a scheme
|
||||||
|
AddToScheme = localSchemeBuilder.AddToScheme
|
||||||
|
)
|
@@ -24,6 +24,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
|
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -39,6 +40,7 @@ import (
|
|||||||
func ServeHTTPWithETag(
|
func ServeHTTPWithETag(
|
||||||
object runtime.Object,
|
object runtime.Object,
|
||||||
hash string,
|
hash string,
|
||||||
|
targetGV schema.GroupVersion,
|
||||||
serializer runtime.NegotiatedSerializer,
|
serializer runtime.NegotiatedSerializer,
|
||||||
w http.ResponseWriter,
|
w http.ResponseWriter,
|
||||||
req *http.Request,
|
req *http.Request,
|
||||||
@@ -64,7 +66,7 @@ func ServeHTTPWithETag(
|
|||||||
responsewriters.WriteObjectNegotiated(
|
responsewriters.WriteObjectNegotiated(
|
||||||
serializer,
|
serializer,
|
||||||
DiscoveryEndpointRestrictions,
|
DiscoveryEndpointRestrictions,
|
||||||
AggregatedDiscoveryGV,
|
targetGV,
|
||||||
w,
|
w,
|
||||||
req,
|
req,
|
||||||
http.StatusOK,
|
http.StatusOK,
|
||||||
|
@@ -26,7 +26,7 @@ import (
|
|||||||
|
|
||||||
"github.com/emicklei/go-restful/v3"
|
"github.com/emicklei/go-restful/v3"
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
apidiscoveryv2 "k8s.io/api/apidiscovery/v2"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
)
|
)
|
||||||
@@ -122,7 +122,7 @@ func (f *recorderResourceManager) SetGroupVersionPriority(gv metav1.GroupVersion
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *recorderResourceManager) AddGroupVersion(groupName string, value apidiscoveryv2beta1.APIVersionDiscovery) {
|
func (f *recorderResourceManager) AddGroupVersion(groupName string, value apidiscoveryv2.APIVersionDiscovery) {
|
||||||
f.lock.Lock()
|
f.lock.Lock()
|
||||||
defer f.lock.Unlock()
|
defer f.lock.Unlock()
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ func (f *recorderResourceManager) RemoveGroupVersion(gv metav1.GroupVersion) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
func (f *recorderResourceManager) SetGroups(values []apidiscoveryv2beta1.APIGroupDiscovery) {
|
func (f *recorderResourceManager) SetGroups(values []apidiscoveryv2.APIGroupDiscovery) {
|
||||||
f.lock.Lock()
|
f.lock.Lock()
|
||||||
defer f.lock.Unlock()
|
defer f.lock.Unlock()
|
||||||
|
|
||||||
|
@@ -17,15 +17,22 @@ limitations under the License.
|
|||||||
package aggregated
|
package aggregated
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
apidiscoveryv2 "k8s.io/api/apidiscovery/v2"
|
||||||
apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
"k8s.io/apimachinery/pkg/version"
|
"k8s.io/apimachinery/pkg/version"
|
||||||
|
apidiscoveryv2conversion "k8s.io/apiserver/pkg/apis/apidiscovery/v2"
|
||||||
|
|
||||||
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
|
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
|
||||||
|
|
||||||
|
"k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
|
||||||
"k8s.io/apiserver/pkg/endpoints/metrics"
|
"k8s.io/apiserver/pkg/endpoints/metrics"
|
||||||
|
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
@@ -51,7 +58,7 @@ type ResourceManager interface {
|
|||||||
// Adds knowledge of the given groupversion to the discovery document
|
// Adds knowledge of the given groupversion to the discovery document
|
||||||
// If it was already being tracked, updates the stored APIVersionDiscovery
|
// If it was already being tracked, updates the stored APIVersionDiscovery
|
||||||
// Thread-safe
|
// Thread-safe
|
||||||
AddGroupVersion(groupName string, value apidiscoveryv2beta1.APIVersionDiscovery)
|
AddGroupVersion(groupName string, value apidiscoveryv2.APIVersionDiscovery)
|
||||||
|
|
||||||
// Sets a priority to be used while sorting a specific group and
|
// Sets a priority to be used while sorting a specific group and
|
||||||
// group-version. If two versions report different priorities for
|
// group-version. If two versions report different priorities for
|
||||||
@@ -72,7 +79,7 @@ type ResourceManager interface {
|
|||||||
// Resets the manager's known list of group-versions and replaces them
|
// Resets the manager's known list of group-versions and replaces them
|
||||||
// with the given groups
|
// with the given groups
|
||||||
// Thread-Safe
|
// Thread-Safe
|
||||||
SetGroups([]apidiscoveryv2beta1.APIGroupDiscovery)
|
SetGroups([]apidiscoveryv2.APIGroupDiscovery)
|
||||||
|
|
||||||
// Returns the same resource manager using a different source
|
// Returns the same resource manager using a different source
|
||||||
// The source is used to decide how to de-duplicate groups.
|
// The source is used to decide how to de-duplicate groups.
|
||||||
@@ -87,7 +94,7 @@ type resourceManager struct {
|
|||||||
*resourceDiscoveryManager
|
*resourceDiscoveryManager
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rm resourceManager) AddGroupVersion(groupName string, value apidiscoveryv2beta1.APIVersionDiscovery) {
|
func (rm resourceManager) AddGroupVersion(groupName string, value apidiscoveryv2.APIVersionDiscovery) {
|
||||||
rm.resourceDiscoveryManager.AddGroupVersion(rm.source, groupName, value)
|
rm.resourceDiscoveryManager.AddGroupVersion(rm.source, groupName, value)
|
||||||
}
|
}
|
||||||
func (rm resourceManager) SetGroupVersionPriority(gv metav1.GroupVersion, grouppriority, versionpriority int) {
|
func (rm resourceManager) SetGroupVersionPriority(gv metav1.GroupVersion, grouppriority, versionpriority int) {
|
||||||
@@ -99,7 +106,7 @@ func (rm resourceManager) RemoveGroup(groupName string) {
|
|||||||
func (rm resourceManager) RemoveGroupVersion(gv metav1.GroupVersion) {
|
func (rm resourceManager) RemoveGroupVersion(gv metav1.GroupVersion) {
|
||||||
rm.resourceDiscoveryManager.RemoveGroupVersion(rm.source, gv)
|
rm.resourceDiscoveryManager.RemoveGroupVersion(rm.source, gv)
|
||||||
}
|
}
|
||||||
func (rm resourceManager) SetGroups(groups []apidiscoveryv2beta1.APIGroupDiscovery) {
|
func (rm resourceManager) SetGroups(groups []apidiscoveryv2.APIGroupDiscovery) {
|
||||||
rm.resourceDiscoveryManager.SetGroups(rm.source, groups)
|
rm.resourceDiscoveryManager.SetGroups(rm.source, groups)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,7 +140,7 @@ type resourceDiscoveryManager struct {
|
|||||||
// Writes protected by the lock.
|
// Writes protected by the lock.
|
||||||
// List of all apigroups & resources indexed by the resource manager
|
// List of all apigroups & resources indexed by the resource manager
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
apiGroups map[groupKey]*apidiscoveryv2beta1.APIGroupDiscovery
|
apiGroups map[groupKey]*apidiscoveryv2.APIGroupDiscovery
|
||||||
versionPriorities map[groupVersionKey]priorityInfo
|
versionPriorities map[groupVersionKey]priorityInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,8 +151,12 @@ type priorityInfo struct {
|
|||||||
|
|
||||||
func NewResourceManager(path string) ResourceManager {
|
func NewResourceManager(path string) ResourceManager {
|
||||||
scheme := runtime.NewScheme()
|
scheme := runtime.NewScheme()
|
||||||
codecs := serializer.NewCodecFactory(scheme)
|
// Register conversion for apidiscovery
|
||||||
|
apidiscoveryv2.SchemeBuilder.Register(apidiscoveryv2conversion.RegisterConversions)
|
||||||
|
utilruntime.Must(apidiscoveryv2.AddToScheme(scheme))
|
||||||
utilruntime.Must(apidiscoveryv2beta1.AddToScheme(scheme))
|
utilruntime.Must(apidiscoveryv2beta1.AddToScheme(scheme))
|
||||||
|
|
||||||
|
codecs := serializer.NewCodecFactory(scheme)
|
||||||
rdm := &resourceDiscoveryManager{
|
rdm := &resourceDiscoveryManager{
|
||||||
serializer: codecs,
|
serializer: codecs,
|
||||||
versionPriorities: make(map[groupVersionKey]priorityInfo),
|
versionPriorities: make(map[groupVersionKey]priorityInfo),
|
||||||
@@ -181,7 +192,7 @@ func (rdm *resourceDiscoveryManager) SetGroupVersionPriority(source Source, gv m
|
|||||||
rdm.cache.Store(nil)
|
rdm.cache.Store(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rdm *resourceDiscoveryManager) SetGroups(source Source, groups []apidiscoveryv2beta1.APIGroupDiscovery) {
|
func (rdm *resourceDiscoveryManager) SetGroups(source Source, groups []apidiscoveryv2.APIGroupDiscovery) {
|
||||||
rdm.lock.Lock()
|
rdm.lock.Lock()
|
||||||
defer rdm.lock.Unlock()
|
defer rdm.lock.Unlock()
|
||||||
|
|
||||||
@@ -221,17 +232,17 @@ func (rdm *resourceDiscoveryManager) SetGroups(source Source, groups []apidiscov
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rdm *resourceDiscoveryManager) AddGroupVersion(source Source, groupName string, value apidiscoveryv2beta1.APIVersionDiscovery) {
|
func (rdm *resourceDiscoveryManager) AddGroupVersion(source Source, groupName string, value apidiscoveryv2.APIVersionDiscovery) {
|
||||||
rdm.lock.Lock()
|
rdm.lock.Lock()
|
||||||
defer rdm.lock.Unlock()
|
defer rdm.lock.Unlock()
|
||||||
|
|
||||||
rdm.addGroupVersionLocked(source, groupName, value)
|
rdm.addGroupVersionLocked(source, groupName, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rdm *resourceDiscoveryManager) addGroupVersionLocked(source Source, groupName string, value apidiscoveryv2beta1.APIVersionDiscovery) {
|
func (rdm *resourceDiscoveryManager) addGroupVersionLocked(source Source, groupName string, value apidiscoveryv2.APIVersionDiscovery) {
|
||||||
|
|
||||||
if rdm.apiGroups == nil {
|
if rdm.apiGroups == nil {
|
||||||
rdm.apiGroups = make(map[groupKey]*apidiscoveryv2beta1.APIGroupDiscovery)
|
rdm.apiGroups = make(map[groupKey]*apidiscoveryv2.APIGroupDiscovery)
|
||||||
}
|
}
|
||||||
|
|
||||||
key := groupKey{
|
key := groupKey{
|
||||||
@@ -264,11 +275,11 @@ func (rdm *resourceDiscoveryManager) addGroupVersionLocked(source Source, groupN
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
group := &apidiscoveryv2beta1.APIGroupDiscovery{
|
group := &apidiscoveryv2.APIGroupDiscovery{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: groupName,
|
Name: groupName,
|
||||||
},
|
},
|
||||||
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{value},
|
Versions: []apidiscoveryv2.APIVersionDiscovery{value},
|
||||||
}
|
}
|
||||||
rdm.apiGroups[key] = group
|
rdm.apiGroups[key] = group
|
||||||
}
|
}
|
||||||
@@ -354,12 +365,12 @@ func (rdm *resourceDiscoveryManager) RemoveGroup(source Source, groupName string
|
|||||||
|
|
||||||
// Prepares the api group list for serving by converting them from map into
|
// Prepares the api group list for serving by converting them from map into
|
||||||
// list and sorting them according to insertion order
|
// list and sorting them according to insertion order
|
||||||
func (rdm *resourceDiscoveryManager) calculateAPIGroupsLocked() []apidiscoveryv2beta1.APIGroupDiscovery {
|
func (rdm *resourceDiscoveryManager) calculateAPIGroupsLocked() []apidiscoveryv2.APIGroupDiscovery {
|
||||||
regenerationCounter.Inc()
|
regenerationCounter.Inc()
|
||||||
// Re-order the apiGroups by their priority.
|
// Re-order the apiGroups by their priority.
|
||||||
groups := []apidiscoveryv2beta1.APIGroupDiscovery{}
|
groups := []apidiscoveryv2.APIGroupDiscovery{}
|
||||||
|
|
||||||
groupsToUse := map[string]apidiscoveryv2beta1.APIGroupDiscovery{}
|
groupsToUse := map[string]apidiscoveryv2.APIGroupDiscovery{}
|
||||||
sourcesUsed := map[metav1.GroupVersion]Source{}
|
sourcesUsed := map[metav1.GroupVersion]Source{}
|
||||||
|
|
||||||
for key, group := range rdm.apiGroups {
|
for key, group := range rdm.apiGroups {
|
||||||
@@ -475,7 +486,7 @@ func (rdm *resourceDiscoveryManager) fetchFromCache() *cachedGroupList {
|
|||||||
if cacheLoad != nil {
|
if cacheLoad != nil {
|
||||||
return cacheLoad
|
return cacheLoad
|
||||||
}
|
}
|
||||||
response := apidiscoveryv2beta1.APIGroupDiscoveryList{
|
response := apidiscoveryv2.APIGroupDiscoveryList{
|
||||||
Items: rdm.calculateAPIGroupsLocked(),
|
Items: rdm.calculateAPIGroupsLocked(),
|
||||||
}
|
}
|
||||||
etag, err := calculateETag(response)
|
etag, err := calculateETag(response)
|
||||||
@@ -492,7 +503,13 @@ func (rdm *resourceDiscoveryManager) fetchFromCache() *cachedGroupList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type cachedGroupList struct {
|
type cachedGroupList struct {
|
||||||
cachedResponse apidiscoveryv2beta1.APIGroupDiscoveryList
|
cachedResponse apidiscoveryv2.APIGroupDiscoveryList
|
||||||
|
// etag is calculated based on a SHA hash of only the JSON object.
|
||||||
|
// A response via different Accept encodings (eg: protobuf, json) will
|
||||||
|
// yield the same etag. This is okay because Accept is part of the Vary header.
|
||||||
|
// Per RFC7231 a client must only cache a response etag pair if the header field
|
||||||
|
// matches as indicated by the Vary field. Thus, protobuf and json and other Accept
|
||||||
|
// encodings will not be cached as the same response despite having the same etag.
|
||||||
cachedResponseETag string
|
cachedResponseETag string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -505,11 +522,30 @@ func (rdm *resourceDiscoveryManager) serveHTTP(resp http.ResponseWriter, req *ht
|
|||||||
response := cache.cachedResponse
|
response := cache.cachedResponse
|
||||||
etag := cache.cachedResponseETag
|
etag := cache.cachedResponseETag
|
||||||
|
|
||||||
|
mediaType, _, err := negotiation.NegotiateOutputMediaType(req, rdm.serializer, DiscoveryEndpointRestrictions)
|
||||||
|
if err != nil {
|
||||||
|
// Should never happen. wrapper.go will only proxy requests to this
|
||||||
|
// handler if the media type passes DiscoveryEndpointRestrictions
|
||||||
|
utilruntime.HandleError(err)
|
||||||
|
resp.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var targetGV schema.GroupVersion
|
||||||
|
if mediaType.Convert == nil ||
|
||||||
|
(mediaType.Convert.GroupVersion() != apidiscoveryv2.SchemeGroupVersion &&
|
||||||
|
mediaType.Convert.GroupVersion() != apidiscoveryv2beta1.SchemeGroupVersion) {
|
||||||
|
utilruntime.HandleError(fmt.Errorf("expected aggregated discovery group version, got group: %s, version %s", mediaType.Convert.Group, mediaType.Convert.Version))
|
||||||
|
resp.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
targetGV = mediaType.Convert.GroupVersion()
|
||||||
|
|
||||||
if len(etag) > 0 {
|
if len(etag) > 0 {
|
||||||
// Use proper e-tag headers if one is available
|
// Use proper e-tag headers if one is available
|
||||||
ServeHTTPWithETag(
|
ServeHTTPWithETag(
|
||||||
&response,
|
&response,
|
||||||
etag,
|
etag,
|
||||||
|
targetGV,
|
||||||
rdm.serializer,
|
rdm.serializer,
|
||||||
resp,
|
resp,
|
||||||
req,
|
req,
|
||||||
@@ -520,7 +556,7 @@ func (rdm *resourceDiscoveryManager) serveHTTP(resp http.ResponseWriter, req *ht
|
|||||||
responsewriters.WriteObjectNegotiated(
|
responsewriters.WriteObjectNegotiated(
|
||||||
rdm.serializer,
|
rdm.serializer,
|
||||||
DiscoveryEndpointRestrictions,
|
DiscoveryEndpointRestrictions,
|
||||||
AggregatedDiscoveryGV,
|
targetGV,
|
||||||
resp,
|
resp,
|
||||||
req,
|
req,
|
||||||
http.StatusOK,
|
http.StatusOK,
|
||||||
|
@@ -32,11 +32,15 @@ import (
|
|||||||
fuzz "github.com/google/gofuzz"
|
fuzz "github.com/google/gofuzz"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
apidiscoveryv2 "k8s.io/api/apidiscovery/v2"
|
||||||
apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
"k8s.io/apimachinery/pkg/version"
|
"k8s.io/apimachinery/pkg/version"
|
||||||
|
apidiscoveryv2conversion "k8s.io/apiserver/pkg/apis/apidiscovery/v2"
|
||||||
discoveryendpoint "k8s.io/apiserver/pkg/endpoints/discovery/aggregated"
|
discoveryendpoint "k8s.io/apiserver/pkg/endpoints/discovery/aggregated"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -46,21 +50,23 @@ var codecs = runtimeserializer.NewCodecFactory(scheme)
|
|||||||
const discoveryPath = "/apis"
|
const discoveryPath = "/apis"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
// Add all builtin types to scheme
|
// Register conversion for apidiscovery
|
||||||
apidiscoveryv2beta1.AddToScheme(scheme)
|
apidiscoveryv2.SchemeBuilder.Register(apidiscoveryv2conversion.RegisterConversions)
|
||||||
|
utilruntime.Must(apidiscoveryv2.AddToScheme(scheme))
|
||||||
|
utilruntime.Must(apidiscoveryv2beta1.AddToScheme(scheme))
|
||||||
codecs = runtimeserializer.NewCodecFactory(scheme)
|
codecs = runtimeserializer.NewCodecFactory(scheme)
|
||||||
}
|
}
|
||||||
|
|
||||||
func fuzzAPIGroups(atLeastNumGroups, maxNumGroups int, seed int64) apidiscoveryv2beta1.APIGroupDiscoveryList {
|
func fuzzAPIGroups(atLeastNumGroups, maxNumGroups int, seed int64) apidiscoveryv2.APIGroupDiscoveryList {
|
||||||
fuzzer := fuzz.NewWithSeed(seed)
|
fuzzer := fuzz.NewWithSeed(seed)
|
||||||
fuzzer.NumElements(atLeastNumGroups, maxNumGroups)
|
fuzzer.NumElements(atLeastNumGroups, maxNumGroups)
|
||||||
fuzzer.NilChance(0)
|
fuzzer.NilChance(0)
|
||||||
fuzzer.Funcs(func(o *apidiscoveryv2beta1.APIGroupDiscovery, c fuzz.Continue) {
|
fuzzer.Funcs(func(o *apidiscoveryv2.APIGroupDiscovery, c fuzz.Continue) {
|
||||||
c.FuzzNoCustom(o)
|
c.FuzzNoCustom(o)
|
||||||
|
|
||||||
// The ResourceManager will just not serve the group if its versions
|
// The ResourceManager will just not serve the group if its versions
|
||||||
// list is empty
|
// list is empty
|
||||||
atLeastOne := apidiscoveryv2beta1.APIVersionDiscovery{}
|
atLeastOne := apidiscoveryv2.APIVersionDiscovery{}
|
||||||
c.Fuzz(&atLeastOne)
|
c.Fuzz(&atLeastOne)
|
||||||
o.Versions = append(o.Versions, atLeastOne)
|
o.Versions = append(o.Versions, atLeastOne)
|
||||||
sort.Slice(o.Versions[:], func(i, j int) bool {
|
sort.Slice(o.Versions[:], func(i, j int) bool {
|
||||||
@@ -75,28 +81,58 @@ func fuzzAPIGroups(atLeastNumGroups, maxNumGroups int, seed int64) apidiscoveryv
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
var apis []apidiscoveryv2beta1.APIGroupDiscovery
|
var apis []apidiscoveryv2.APIGroupDiscovery
|
||||||
fuzzer.Fuzz(&apis)
|
fuzzer.Fuzz(&apis)
|
||||||
sort.Slice(apis[:], func(i, j int) bool {
|
sort.Slice(apis[:], func(i, j int) bool {
|
||||||
return apis[i].Name < apis[j].Name
|
return apis[i].Name < apis[j].Name
|
||||||
})
|
})
|
||||||
|
|
||||||
return apidiscoveryv2beta1.APIGroupDiscoveryList{
|
return apidiscoveryv2.APIGroupDiscoveryList{
|
||||||
TypeMeta: metav1.TypeMeta{
|
TypeMeta: metav1.TypeMeta{
|
||||||
Kind: "APIGroupDiscoveryList",
|
Kind: "APIGroupDiscoveryList",
|
||||||
APIVersion: "apidiscovery.k8s.io/v2beta1",
|
APIVersion: "apidiscovery.k8s.io/v2",
|
||||||
},
|
},
|
||||||
Items: apis,
|
Items: apis,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchPath(handler http.Handler, acceptPrefix string, path string, etag string) (*http.Response, []byte, *apidiscoveryv2beta1.APIGroupDiscoveryList) {
|
func fetchPathV2Beta1(handler http.Handler, acceptPrefix string, path string, etag string) (*http.Response, []byte, *apidiscoveryv2beta1.APIGroupDiscoveryList) {
|
||||||
|
acceptSuffix := ";g=apidiscovery.k8s.io;v=v2beta1;as=APIGroupDiscoveryList"
|
||||||
|
r, bytes := fetchPathHelper(handler, acceptPrefix+acceptSuffix, path, etag)
|
||||||
|
var decoded *apidiscoveryv2beta1.APIGroupDiscoveryList
|
||||||
|
if len(bytes) > 0 {
|
||||||
|
decoded = &apidiscoveryv2beta1.APIGroupDiscoveryList{}
|
||||||
|
err := runtime.DecodeInto(codecs.UniversalDecoder(), bytes, decoded)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("failed to decode response: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return r, bytes, decoded
|
||||||
|
}
|
||||||
|
|
||||||
|
func fetchPath(handler http.Handler, acceptPrefix string, path string, etag string) (*http.Response, []byte, *apidiscoveryv2.APIGroupDiscoveryList) {
|
||||||
|
acceptSuffix := ";g=apidiscovery.k8s.io;v=v2;as=APIGroupDiscoveryList,"
|
||||||
|
acceptSuffixV2Beta1 := ";g=apidiscovery.k8s.io;v=v2beta1;as=APIGroupDiscoveryList,"
|
||||||
|
r, bytes := fetchPathHelper(handler, acceptPrefix+acceptSuffix+","+acceptPrefix+acceptSuffixV2Beta1, path, etag)
|
||||||
|
var decoded *apidiscoveryv2.APIGroupDiscoveryList
|
||||||
|
if len(bytes) > 0 {
|
||||||
|
decoded = &apidiscoveryv2.APIGroupDiscoveryList{}
|
||||||
|
err := runtime.DecodeInto(codecs.UniversalDecoder(), bytes, decoded)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("failed to decode response: %v", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r, bytes, decoded
|
||||||
|
}
|
||||||
|
|
||||||
|
func fetchPathHelper(handler http.Handler, accept string, path string, etag string) (*http.Response, []byte) {
|
||||||
// Expect json-formatted apis group list
|
// Expect json-formatted apis group list
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
req := httptest.NewRequest("GET", discoveryPath, nil)
|
req := httptest.NewRequest("GET", discoveryPath, nil)
|
||||||
|
|
||||||
// Ask for JSON response
|
// Ask for JSON response
|
||||||
req.Header.Set("Accept", acceptPrefix+";g=apidiscovery.k8s.io;v=v2beta1;as=APIGroupDiscoveryList")
|
req.Header.Set("Accept", accept)
|
||||||
|
|
||||||
if etag != "" {
|
if etag != "" {
|
||||||
// Quote provided etag if unquoted
|
// Quote provided etag if unquoted
|
||||||
@@ -110,13 +146,7 @@ func fetchPath(handler http.Handler, acceptPrefix string, path string, etag stri
|
|||||||
handler.ServeHTTP(w, req)
|
handler.ServeHTTP(w, req)
|
||||||
|
|
||||||
bytes := w.Body.Bytes()
|
bytes := w.Body.Bytes()
|
||||||
var decoded *apidiscoveryv2beta1.APIGroupDiscoveryList
|
return w.Result(), bytes
|
||||||
if len(bytes) > 0 {
|
|
||||||
decoded = &apidiscoveryv2beta1.APIGroupDiscoveryList{}
|
|
||||||
runtime.DecodeInto(codecs.UniversalDecoder(), bytes, decoded)
|
|
||||||
}
|
|
||||||
|
|
||||||
return w.Result(), bytes, decoded
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add all builtin APIServices to the manager and check the output
|
// Add all builtin APIServices to the manager and check the output
|
||||||
@@ -132,7 +162,7 @@ func TestBasicResponse(t *testing.T) {
|
|||||||
require.NoError(t, err, "json marshal should always succeed")
|
require.NoError(t, err, "json marshal should always succeed")
|
||||||
|
|
||||||
assert.Equal(t, http.StatusOK, response.StatusCode, "response should be 200 OK")
|
assert.Equal(t, http.StatusOK, response.StatusCode, "response should be 200 OK")
|
||||||
assert.Equal(t, "application/json;g=apidiscovery.k8s.io;v=v2beta1;as=APIGroupDiscoveryList", response.Header.Get("Content-Type"), "Content-Type response header should be as requested in Accept header if supported")
|
assert.Equal(t, "application/json;g=apidiscovery.k8s.io;v=v2;as=APIGroupDiscoveryList", response.Header.Get("Content-Type"), "Content-Type response header should be as requested in Accept header if supported")
|
||||||
assert.NotEmpty(t, response.Header.Get("ETag"), "E-Tag should be set")
|
assert.NotEmpty(t, response.Header.Get("ETag"), "E-Tag should be set")
|
||||||
|
|
||||||
assert.NoError(t, err, "decode should always succeed")
|
assert.NoError(t, err, "decode should always succeed")
|
||||||
@@ -149,11 +179,39 @@ func TestBasicResponseProtobuf(t *testing.T) {
|
|||||||
|
|
||||||
response, _, decoded := fetchPath(manager, "application/vnd.kubernetes.protobuf", discoveryPath, "")
|
response, _, decoded := fetchPath(manager, "application/vnd.kubernetes.protobuf", discoveryPath, "")
|
||||||
assert.Equal(t, http.StatusOK, response.StatusCode, "response should be 200 OK")
|
assert.Equal(t, http.StatusOK, response.StatusCode, "response should be 200 OK")
|
||||||
assert.Equal(t, "application/vnd.kubernetes.protobuf;g=apidiscovery.k8s.io;v=v2beta1;as=APIGroupDiscoveryList", response.Header.Get("Content-Type"), "Content-Type response header should be as requested in Accept header if supported")
|
assert.Equal(t, "application/vnd.kubernetes.protobuf;g=apidiscovery.k8s.io;v=v2;as=APIGroupDiscoveryList", response.Header.Get("Content-Type"), "Content-Type response header should be as requested in Accept header if supported")
|
||||||
assert.NotEmpty(t, response.Header.Get("ETag"), "E-Tag should be set")
|
assert.NotEmpty(t, response.Header.Get("ETag"), "E-Tag should be set")
|
||||||
assert.EqualValues(t, &apis, decoded, "decoded value should equal input")
|
assert.EqualValues(t, &apis, decoded, "decoded value should equal input")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// V2Beta1 should still be served
|
||||||
|
func TestV2Beta1SkewSupport(t *testing.T) {
|
||||||
|
manager := discoveryendpoint.NewResourceManager("apis")
|
||||||
|
|
||||||
|
apis := fuzzAPIGroups(1, 3, 10)
|
||||||
|
manager.SetGroups(apis.Items)
|
||||||
|
|
||||||
|
converted, err := scheme.ConvertToVersion(&apis, &schema.GroupVersion{Group: "apidiscovery.k8s.io", Version: "v2beta1"})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
v2beta1apis := converted.(*apidiscoveryv2beta1.APIGroupDiscoveryList)
|
||||||
|
|
||||||
|
response, body, decoded := fetchPathV2Beta1(manager, "application/json", discoveryPath, "")
|
||||||
|
|
||||||
|
jsonFormatted, err := json.Marshal(v2beta1apis)
|
||||||
|
require.NoError(t, err, "json marshal should always succeed")
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusOK, response.StatusCode, "response should be 200 OK")
|
||||||
|
assert.Equal(t, "application/json;g=apidiscovery.k8s.io;v=v2beta1;as=APIGroupDiscoveryList", response.Header.Get("Content-Type"), "Content-Type response header should be as requested in Accept header if supported")
|
||||||
|
assert.NotEmpty(t, response.Header.Get("ETag"), "E-Tag should be set")
|
||||||
|
|
||||||
|
assert.NoError(t, err, "decode should always succeed")
|
||||||
|
assert.EqualValues(t, v2beta1apis, decoded, "decoded value should equal input")
|
||||||
|
assert.Equal(t, string(jsonFormatted)+"\n", string(body), "response should be the api group list")
|
||||||
|
}
|
||||||
|
|
||||||
// Test that an etag associated with the service only depends on the apiresources
|
// Test that an etag associated with the service only depends on the apiresources
|
||||||
// e.g.: Multiple services with the same contents should have the same etag.
|
// e.g.: Multiple services with the same contents should have the same etag.
|
||||||
func TestEtagConsistent(t *testing.T) {
|
func TestEtagConsistent(t *testing.T) {
|
||||||
@@ -348,7 +406,7 @@ func TestUpdateService(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
var newapis apidiscoveryv2beta1.APIGroupDiscoveryList
|
var newapis apidiscoveryv2.APIGroupDiscoveryList
|
||||||
err = json.Unmarshal(b, &newapis)
|
err = json.Unmarshal(b, &newapis)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
@@ -369,7 +427,7 @@ func TestUpdateService(t *testing.T) {
|
|||||||
func TestMultipleSources(t *testing.T) {
|
func TestMultipleSources(t *testing.T) {
|
||||||
type pair struct {
|
type pair struct {
|
||||||
manager discoveryendpoint.ResourceManager
|
manager discoveryendpoint.ResourceManager
|
||||||
apis apidiscoveryv2beta1.APIGroupDiscoveryList
|
apis apidiscoveryv2.APIGroupDiscoveryList
|
||||||
}
|
}
|
||||||
|
|
||||||
pairs := []pair{}
|
pairs := []pair{}
|
||||||
@@ -388,7 +446,7 @@ func TestMultipleSources(t *testing.T) {
|
|||||||
pairs = append(pairs, pair{manager, apis})
|
pairs = append(pairs, pair{manager, apis})
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedResult := []apidiscoveryv2beta1.APIGroupDiscovery{}
|
expectedResult := []apidiscoveryv2.APIGroupDiscovery{}
|
||||||
|
|
||||||
groupCounter := 0
|
groupCounter := 0
|
||||||
for _, p := range pairs {
|
for _, p := range pairs {
|
||||||
@@ -422,7 +480,7 @@ func TestSourcePrecedence(t *testing.T) {
|
|||||||
apis := fuzzAPIGroups(1, 3, int64(15))
|
apis := fuzzAPIGroups(1, 3, int64(15))
|
||||||
for _, g := range apis.Items {
|
for _, g := range apis.Items {
|
||||||
for i, v := range g.Versions {
|
for i, v := range g.Versions {
|
||||||
v.Freshness = apidiscoveryv2beta1.DiscoveryFreshnessCurrent
|
v.Freshness = apidiscoveryv2.DiscoveryFreshnessCurrent
|
||||||
g.Versions[i] = v
|
g.Versions[i] = v
|
||||||
otherManager.AddGroupVersion(g.Name, v)
|
otherManager.AddGroupVersion(g.Name, v)
|
||||||
}
|
}
|
||||||
@@ -434,12 +492,12 @@ func TestSourcePrecedence(t *testing.T) {
|
|||||||
// Add the first groupversion under default.
|
// Add the first groupversion under default.
|
||||||
// No versions should appear in discovery document except this one
|
// No versions should appear in discovery document except this one
|
||||||
overrideVersion := initialDocument.Items[0].Versions[0]
|
overrideVersion := initialDocument.Items[0].Versions[0]
|
||||||
overrideVersion.Freshness = apidiscoveryv2beta1.DiscoveryFreshnessStale
|
overrideVersion.Freshness = apidiscoveryv2.DiscoveryFreshnessStale
|
||||||
defaultManager.AddGroupVersion(initialDocument.Items[0].Name, overrideVersion)
|
defaultManager.AddGroupVersion(initialDocument.Items[0].Name, overrideVersion)
|
||||||
|
|
||||||
_, _, maskedDocument := fetchPath(defaultManager, "application/json", discoveryPath, "")
|
_, _, maskedDocument := fetchPath(defaultManager, "application/json", discoveryPath, "")
|
||||||
masked := initialDocument.DeepCopy()
|
masked := initialDocument.DeepCopy()
|
||||||
masked.Items[0].Versions[0].Freshness = apidiscoveryv2beta1.DiscoveryFreshnessStale
|
masked.Items[0].Versions[0].Freshness = apidiscoveryv2.DiscoveryFreshnessStale
|
||||||
|
|
||||||
require.Equal(t, masked.Items, maskedDocument.Items)
|
require.Equal(t, masked.Items, maskedDocument.Items)
|
||||||
|
|
||||||
@@ -593,19 +651,19 @@ func TestAbuse(t *testing.T) {
|
|||||||
func TestVersionSortingNoPriority(t *testing.T) {
|
func TestVersionSortingNoPriority(t *testing.T) {
|
||||||
manager := discoveryendpoint.NewResourceManager("apis")
|
manager := discoveryendpoint.NewResourceManager("apis")
|
||||||
|
|
||||||
manager.AddGroupVersion("default", apidiscoveryv2beta1.APIVersionDiscovery{
|
manager.AddGroupVersion("default", apidiscoveryv2.APIVersionDiscovery{
|
||||||
Version: "v1alpha1",
|
Version: "v1alpha1",
|
||||||
})
|
})
|
||||||
manager.AddGroupVersion("default", apidiscoveryv2beta1.APIVersionDiscovery{
|
manager.AddGroupVersion("default", apidiscoveryv2.APIVersionDiscovery{
|
||||||
Version: "v2beta1",
|
Version: "v2beta1",
|
||||||
})
|
})
|
||||||
manager.AddGroupVersion("default", apidiscoveryv2beta1.APIVersionDiscovery{
|
manager.AddGroupVersion("default", apidiscoveryv2.APIVersionDiscovery{
|
||||||
Version: "v1",
|
Version: "v1",
|
||||||
})
|
})
|
||||||
manager.AddGroupVersion("default", apidiscoveryv2beta1.APIVersionDiscovery{
|
manager.AddGroupVersion("default", apidiscoveryv2.APIVersionDiscovery{
|
||||||
Version: "v1beta1",
|
Version: "v1beta1",
|
||||||
})
|
})
|
||||||
manager.AddGroupVersion("default", apidiscoveryv2beta1.APIVersionDiscovery{
|
manager.AddGroupVersion("default", apidiscoveryv2.APIVersionDiscovery{
|
||||||
Version: "v2",
|
Version: "v2",
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -625,11 +683,11 @@ func TestVersionSortingNoPriority(t *testing.T) {
|
|||||||
func TestVersionSortingWithPriority(t *testing.T) {
|
func TestVersionSortingWithPriority(t *testing.T) {
|
||||||
manager := discoveryendpoint.NewResourceManager("apis")
|
manager := discoveryendpoint.NewResourceManager("apis")
|
||||||
|
|
||||||
manager.AddGroupVersion("default", apidiscoveryv2beta1.APIVersionDiscovery{
|
manager.AddGroupVersion("default", apidiscoveryv2.APIVersionDiscovery{
|
||||||
Version: "v1",
|
Version: "v1",
|
||||||
})
|
})
|
||||||
manager.SetGroupVersionPriority(metav1.GroupVersion{Group: "default", Version: "v1"}, 1000, 100)
|
manager.SetGroupVersionPriority(metav1.GroupVersion{Group: "default", Version: "v1"}, 1000, 100)
|
||||||
manager.AddGroupVersion("default", apidiscoveryv2beta1.APIVersionDiscovery{
|
manager.AddGroupVersion("default", apidiscoveryv2.APIVersionDiscovery{
|
||||||
Version: "v1alpha1",
|
Version: "v1alpha1",
|
||||||
})
|
})
|
||||||
manager.SetGroupVersionPriority(metav1.GroupVersion{Group: "default", Version: "v1alpha1"}, 1000, 200)
|
manager.SetGroupVersionPriority(metav1.GroupVersion{Group: "default", Version: "v1alpha1"}, 1000, 200)
|
||||||
@@ -648,15 +706,15 @@ func TestVersionSortingWithPriority(t *testing.T) {
|
|||||||
func TestGroupVersionSortingConflictingPriority(t *testing.T) {
|
func TestGroupVersionSortingConflictingPriority(t *testing.T) {
|
||||||
manager := discoveryendpoint.NewResourceManager("apis")
|
manager := discoveryendpoint.NewResourceManager("apis")
|
||||||
|
|
||||||
manager.AddGroupVersion("default", apidiscoveryv2beta1.APIVersionDiscovery{
|
manager.AddGroupVersion("default", apidiscoveryv2.APIVersionDiscovery{
|
||||||
Version: "v1",
|
Version: "v1",
|
||||||
})
|
})
|
||||||
manager.SetGroupVersionPriority(metav1.GroupVersion{Group: "default", Version: "v1"}, 1000, 100)
|
manager.SetGroupVersionPriority(metav1.GroupVersion{Group: "default", Version: "v1"}, 1000, 100)
|
||||||
manager.AddGroupVersion("test", apidiscoveryv2beta1.APIVersionDiscovery{
|
manager.AddGroupVersion("test", apidiscoveryv2.APIVersionDiscovery{
|
||||||
Version: "v1alpha1",
|
Version: "v1alpha1",
|
||||||
})
|
})
|
||||||
manager.SetGroupVersionPriority(metav1.GroupVersion{Group: "test", Version: "v1alpha1"}, 500, 100)
|
manager.SetGroupVersionPriority(metav1.GroupVersion{Group: "test", Version: "v1alpha1"}, 500, 100)
|
||||||
manager.AddGroupVersion("test", apidiscoveryv2beta1.APIVersionDiscovery{
|
manager.AddGroupVersion("test", apidiscoveryv2.APIVersionDiscovery{
|
||||||
Version: "v1alpha2",
|
Version: "v1alpha2",
|
||||||
})
|
})
|
||||||
manager.SetGroupVersionPriority(metav1.GroupVersion{Group: "test", Version: "v1alpha1"}, 2000, 100)
|
manager.SetGroupVersionPriority(metav1.GroupVersion{Group: "test", Version: "v1alpha1"}, 2000, 100)
|
||||||
@@ -679,17 +737,17 @@ func TestStatelessGroupPriorityMinimum(t *testing.T) {
|
|||||||
stableGroup := "stable.example.com"
|
stableGroup := "stable.example.com"
|
||||||
experimentalGroup := "experimental.example.com"
|
experimentalGroup := "experimental.example.com"
|
||||||
|
|
||||||
manager.AddGroupVersion(stableGroup, apidiscoveryv2beta1.APIVersionDiscovery{
|
manager.AddGroupVersion(stableGroup, apidiscoveryv2.APIVersionDiscovery{
|
||||||
Version: "v1",
|
Version: "v1",
|
||||||
})
|
})
|
||||||
manager.SetGroupVersionPriority(metav1.GroupVersion{Group: stableGroup, Version: "v1"}, 1000, 100)
|
manager.SetGroupVersionPriority(metav1.GroupVersion{Group: stableGroup, Version: "v1"}, 1000, 100)
|
||||||
|
|
||||||
manager.AddGroupVersion(experimentalGroup, apidiscoveryv2beta1.APIVersionDiscovery{
|
manager.AddGroupVersion(experimentalGroup, apidiscoveryv2.APIVersionDiscovery{
|
||||||
Version: "v1",
|
Version: "v1",
|
||||||
})
|
})
|
||||||
manager.SetGroupVersionPriority(metav1.GroupVersion{Group: experimentalGroup, Version: "v1"}, 100, 100)
|
manager.SetGroupVersionPriority(metav1.GroupVersion{Group: experimentalGroup, Version: "v1"}, 100, 100)
|
||||||
|
|
||||||
manager.AddGroupVersion(experimentalGroup, apidiscoveryv2beta1.APIVersionDiscovery{
|
manager.AddGroupVersion(experimentalGroup, apidiscoveryv2.APIVersionDiscovery{
|
||||||
Version: "v1alpha1",
|
Version: "v1alpha1",
|
||||||
})
|
})
|
||||||
manager.SetGroupVersionPriority(metav1.GroupVersion{Group: experimentalGroup, Version: "v1alpha1"}, 10000, 100)
|
manager.SetGroupVersionPriority(metav1.GroupVersion{Group: experimentalGroup, Version: "v1alpha1"}, 10000, 100)
|
||||||
|
@@ -20,8 +20,6 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
)
|
)
|
||||||
|
|
||||||
var AggregatedDiscoveryGV = schema.GroupVersion{Group: "apidiscovery.k8s.io", Version: "v2beta1"}
|
|
||||||
|
|
||||||
// Interface is from "k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
|
// Interface is from "k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
|
||||||
|
|
||||||
// DiscoveryEndpointRestrictions allows requests to /apis to provide a Content Negotiation GVK for aggregated discovery.
|
// DiscoveryEndpointRestrictions allows requests to /apis to provide a Content Negotiation GVK for aggregated discovery.
|
||||||
@@ -39,7 +37,7 @@ func (discoveryEndpointRestrictions) AllowsStreamSchema(s string) bool { return
|
|||||||
// IsAggregatedDiscoveryGVK checks if a provided GVK is the GVK for serving aggregated discovery.
|
// IsAggregatedDiscoveryGVK checks if a provided GVK is the GVK for serving aggregated discovery.
|
||||||
func IsAggregatedDiscoveryGVK(gvk *schema.GroupVersionKind) bool {
|
func IsAggregatedDiscoveryGVK(gvk *schema.GroupVersionKind) bool {
|
||||||
if gvk != nil {
|
if gvk != nil {
|
||||||
return gvk.Group == "apidiscovery.k8s.io" && gvk.Version == "v2beta1" && gvk.Kind == "APIGroupDiscoveryList"
|
return gvk.Group == "apidiscovery.k8s.io" && (gvk.Version == "v2beta1" || gvk.Version == "v2") && gvk.Kind == "APIGroupDiscoveryList"
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@@ -19,8 +19,10 @@ package aggregated
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
apidiscoveryv2 "k8s.io/api/apidiscovery/v2"
|
||||||
apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
||||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
|
|
||||||
"github.com/emicklei/go-restful/v3"
|
"github.com/emicklei/go-restful/v3"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
@@ -69,10 +71,11 @@ func (wrapped *WrappedHandler) GenerateWebService(prefix string, returnType inte
|
|||||||
// WrapAggregatedDiscoveryToHandler wraps a handler with an option to
|
// WrapAggregatedDiscoveryToHandler wraps a handler with an option to
|
||||||
// emit the aggregated discovery by passing in the aggregated
|
// emit the aggregated discovery by passing in the aggregated
|
||||||
// discovery type in content negotiation headers: eg: (Accept:
|
// discovery type in content negotiation headers: eg: (Accept:
|
||||||
// application/json;v=v2beta1;g=apidiscovery.k8s.io;as=APIGroupDiscoveryList)
|
// application/json;v=v2;g=apidiscovery.k8s.io;as=APIGroupDiscoveryList)
|
||||||
func WrapAggregatedDiscoveryToHandler(handler http.Handler, aggHandler http.Handler) *WrappedHandler {
|
func WrapAggregatedDiscoveryToHandler(handler http.Handler, aggHandler http.Handler) *WrappedHandler {
|
||||||
scheme := runtime.NewScheme()
|
scheme := runtime.NewScheme()
|
||||||
apidiscoveryv2beta1.AddToScheme(scheme)
|
utilruntime.Must(apidiscoveryv2.AddToScheme(scheme))
|
||||||
|
utilruntime.Must(apidiscoveryv2beta1.AddToScheme(scheme))
|
||||||
codecs := serializer.NewCodecFactory(scheme)
|
codecs := serializer.NewCodecFactory(scheme)
|
||||||
return &WrappedHandler{codecs, handler, aggHandler}
|
return &WrappedHandler{codecs, handler, aggHandler}
|
||||||
}
|
}
|
||||||
|
@@ -32,8 +32,11 @@ import (
|
|||||||
const discoveryPath = "/apis"
|
const discoveryPath = "/apis"
|
||||||
const jsonAccept = "application/json"
|
const jsonAccept = "application/json"
|
||||||
const protobufAccept = "application/vnd.kubernetes.protobuf"
|
const protobufAccept = "application/vnd.kubernetes.protobuf"
|
||||||
const aggregatedAcceptSuffix = ";g=apidiscovery.k8s.io;v=v2beta1;as=APIGroupDiscoveryList"
|
const aggregatedV2Beta1AcceptSuffix = ";g=apidiscovery.k8s.io;v=v2beta1;as=APIGroupDiscoveryList"
|
||||||
|
const aggregatedAcceptSuffix = ";g=apidiscovery.k8s.io;v=v2;as=APIGroupDiscoveryList"
|
||||||
|
|
||||||
|
const aggregatedV2Beta1JSONAccept = jsonAccept + aggregatedV2Beta1AcceptSuffix
|
||||||
|
const aggregatedV2Beta1ProtoAccept = protobufAccept + aggregatedV2Beta1AcceptSuffix
|
||||||
const aggregatedJSONAccept = jsonAccept + aggregatedAcceptSuffix
|
const aggregatedJSONAccept = jsonAccept + aggregatedAcceptSuffix
|
||||||
const aggregatedProtoAccept = protobufAccept + aggregatedAcceptSuffix
|
const aggregatedProtoAccept = protobufAccept + aggregatedAcceptSuffix
|
||||||
|
|
||||||
@@ -75,6 +78,12 @@ func TestAggregationEnabled(t *testing.T) {
|
|||||||
// Empty accept headers are valid and should be handled by the unaggregated handler
|
// Empty accept headers are valid and should be handled by the unaggregated handler
|
||||||
accept: "",
|
accept: "",
|
||||||
expected: "unaggregated",
|
expected: "unaggregated",
|
||||||
|
}, {
|
||||||
|
accept: aggregatedV2Beta1JSONAccept,
|
||||||
|
expected: "aggregated",
|
||||||
|
}, {
|
||||||
|
accept: aggregatedV2Beta1ProtoAccept,
|
||||||
|
expected: "aggregated",
|
||||||
}, {
|
}, {
|
||||||
accept: aggregatedJSONAccept,
|
accept: aggregatedJSONAccept,
|
||||||
expected: "aggregated",
|
expected: "aggregated",
|
||||||
|
@@ -22,7 +22,7 @@ import (
|
|||||||
|
|
||||||
restful "github.com/emicklei/go-restful/v3"
|
restful "github.com/emicklei/go-restful/v3"
|
||||||
|
|
||||||
apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
apidiscoveryv2 "k8s.io/api/apidiscovery/v2"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
@@ -107,7 +107,7 @@ type APIGroupVersion struct {
|
|||||||
// InstallREST registers the REST handlers (storage, watch, proxy and redirect) into a restful Container.
|
// InstallREST registers the REST handlers (storage, watch, proxy and redirect) into a restful Container.
|
||||||
// It is expected that the provided path root prefix will serve all operations. Root MUST NOT end
|
// It is expected that the provided path root prefix will serve all operations. Root MUST NOT end
|
||||||
// in a slash.
|
// in a slash.
|
||||||
func (g *APIGroupVersion) InstallREST(container *restful.Container) ([]apidiscoveryv2beta1.APIResourceDiscovery, []*storageversion.ResourceInfo, error) {
|
func (g *APIGroupVersion) InstallREST(container *restful.Container) ([]apidiscoveryv2.APIResourceDiscovery, []*storageversion.ResourceInfo, error) {
|
||||||
prefix := path.Join(g.Root, g.GroupVersion.Group, g.GroupVersion.Version)
|
prefix := path.Join(g.Root, g.GroupVersion.Group, g.GroupVersion.Version)
|
||||||
installer := &APIInstaller{
|
installer := &APIInstaller{
|
||||||
group: g,
|
group: g,
|
||||||
|
@@ -28,7 +28,7 @@ import (
|
|||||||
restful "github.com/emicklei/go-restful/v3"
|
restful "github.com/emicklei/go-restful/v3"
|
||||||
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
|
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
|
||||||
|
|
||||||
apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
apidiscoveryv2 "k8s.io/api/apidiscovery/v2"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/conversion"
|
"k8s.io/apimachinery/pkg/conversion"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
@@ -71,8 +71,8 @@ type action struct {
|
|||||||
AllNamespaces bool // true iff the action is namespaced but works on aggregate result for all namespaces
|
AllNamespaces bool // true iff the action is namespaced but works on aggregate result for all namespaces
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConvertGroupVersionIntoToDiscovery(list []metav1.APIResource) ([]apidiscoveryv2beta1.APIResourceDiscovery, error) {
|
func ConvertGroupVersionIntoToDiscovery(list []metav1.APIResource) ([]apidiscoveryv2.APIResourceDiscovery, error) {
|
||||||
var apiResourceList []apidiscoveryv2beta1.APIResourceDiscovery
|
var apiResourceList []apidiscoveryv2.APIResourceDiscovery
|
||||||
parentResources := make(map[string]int)
|
parentResources := make(map[string]int)
|
||||||
|
|
||||||
// Loop through all top-level resources
|
// Loop through all top-level resources
|
||||||
@@ -82,14 +82,14 @@ func ConvertGroupVersionIntoToDiscovery(list []metav1.APIResource) ([]apidiscove
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var scope apidiscoveryv2beta1.ResourceScope
|
var scope apidiscoveryv2.ResourceScope
|
||||||
if r.Namespaced {
|
if r.Namespaced {
|
||||||
scope = apidiscoveryv2beta1.ScopeNamespace
|
scope = apidiscoveryv2.ScopeNamespace
|
||||||
} else {
|
} else {
|
||||||
scope = apidiscoveryv2beta1.ScopeCluster
|
scope = apidiscoveryv2.ScopeCluster
|
||||||
}
|
}
|
||||||
|
|
||||||
resource := apidiscoveryv2beta1.APIResourceDiscovery{
|
resource := apidiscoveryv2.APIResourceDiscovery{
|
||||||
Resource: r.Name,
|
Resource: r.Name,
|
||||||
Scope: scope,
|
Scope: scope,
|
||||||
ResponseKind: &metav1.GroupVersionKind{
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
@@ -116,17 +116,17 @@ func ConvertGroupVersionIntoToDiscovery(list []metav1.APIResource) ([]apidiscove
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var scope apidiscoveryv2beta1.ResourceScope
|
var scope apidiscoveryv2.ResourceScope
|
||||||
if r.Namespaced {
|
if r.Namespaced {
|
||||||
scope = apidiscoveryv2beta1.ScopeNamespace
|
scope = apidiscoveryv2.ScopeNamespace
|
||||||
} else {
|
} else {
|
||||||
scope = apidiscoveryv2beta1.ScopeCluster
|
scope = apidiscoveryv2.ScopeCluster
|
||||||
}
|
}
|
||||||
|
|
||||||
parentidx, exists := parentResources[split[0]]
|
parentidx, exists := parentResources[split[0]]
|
||||||
if !exists {
|
if !exists {
|
||||||
// If a subresource exists without a parent, create a parent
|
// If a subresource exists without a parent, create a parent
|
||||||
apiResourceList = append(apiResourceList, apidiscoveryv2beta1.APIResourceDiscovery{
|
apiResourceList = append(apiResourceList, apidiscoveryv2.APIResourceDiscovery{
|
||||||
Resource: split[0],
|
Resource: split[0],
|
||||||
Scope: scope,
|
Scope: scope,
|
||||||
// avoid nil panics in v0.26.0-v0.26.3 client-go clients
|
// avoid nil panics in v0.26.0-v0.26.3 client-go clients
|
||||||
@@ -142,7 +142,7 @@ func ConvertGroupVersionIntoToDiscovery(list []metav1.APIResource) ([]apidiscove
|
|||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
subresource := apidiscoveryv2beta1.APISubresourceDiscovery{
|
subresource := apidiscoveryv2.APISubresourceDiscovery{
|
||||||
Subresource: split[1],
|
Subresource: split[1],
|
||||||
Verbs: r.Verbs,
|
Verbs: r.Verbs,
|
||||||
// avoid nil panics in v0.26.0-v0.26.3 client-go clients
|
// avoid nil panics in v0.26.0-v0.26.3 client-go clients
|
||||||
|
@@ -20,7 +20,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
apidiscoveryv2 "k8s.io/api/apidiscovery/v2"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -106,7 +106,7 @@ func TestConvertAPIResourceToDiscovery(t *testing.T) {
|
|||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
resources []metav1.APIResource
|
resources []metav1.APIResource
|
||||||
wantAPIResourceDiscovery []apidiscoveryv2beta1.APIResourceDiscovery
|
wantAPIResourceDiscovery []apidiscoveryv2.APIResourceDiscovery
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
@@ -121,10 +121,10 @@ func TestConvertAPIResourceToDiscovery(t *testing.T) {
|
|||||||
Verbs: []string{"create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"},
|
Verbs: []string{"create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantAPIResourceDiscovery: []apidiscoveryv2beta1.APIResourceDiscovery{
|
wantAPIResourceDiscovery: []apidiscoveryv2.APIResourceDiscovery{
|
||||||
{
|
{
|
||||||
Resource: "pods",
|
Resource: "pods",
|
||||||
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
Scope: apidiscoveryv2.ScopeNamespace,
|
||||||
ResponseKind: &metav1.GroupVersionKind{
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
Kind: "Pod",
|
Kind: "Pod",
|
||||||
},
|
},
|
||||||
@@ -146,10 +146,10 @@ func TestConvertAPIResourceToDiscovery(t *testing.T) {
|
|||||||
Verbs: []string{"create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"},
|
Verbs: []string{"create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantAPIResourceDiscovery: []apidiscoveryv2beta1.APIResourceDiscovery{
|
wantAPIResourceDiscovery: []apidiscoveryv2.APIResourceDiscovery{
|
||||||
{
|
{
|
||||||
Resource: "cronjobs",
|
Resource: "cronjobs",
|
||||||
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
Scope: apidiscoveryv2.ScopeNamespace,
|
||||||
ResponseKind: &metav1.GroupVersionKind{
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
Group: "batch",
|
Group: "batch",
|
||||||
Version: "v1",
|
Version: "v1",
|
||||||
@@ -182,10 +182,10 @@ func TestConvertAPIResourceToDiscovery(t *testing.T) {
|
|||||||
Verbs: []string{"create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"},
|
Verbs: []string{"create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantAPIResourceDiscovery: []apidiscoveryv2beta1.APIResourceDiscovery{
|
wantAPIResourceDiscovery: []apidiscoveryv2.APIResourceDiscovery{
|
||||||
{
|
{
|
||||||
Resource: "cronjobs",
|
Resource: "cronjobs",
|
||||||
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
Scope: apidiscoveryv2.ScopeNamespace,
|
||||||
ResponseKind: &metav1.GroupVersionKind{
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
Group: "batch",
|
Group: "batch",
|
||||||
Version: "v1",
|
Version: "v1",
|
||||||
@@ -193,7 +193,7 @@ func TestConvertAPIResourceToDiscovery(t *testing.T) {
|
|||||||
},
|
},
|
||||||
ShortNames: []string{"cj"},
|
ShortNames: []string{"cj"},
|
||||||
Verbs: []string{"create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"},
|
Verbs: []string{"create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"},
|
||||||
Subresources: []apidiscoveryv2beta1.APISubresourceDiscovery{{
|
Subresources: []apidiscoveryv2.APISubresourceDiscovery{{
|
||||||
Subresource: "status",
|
Subresource: "status",
|
||||||
ResponseKind: &metav1.GroupVersionKind{
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
Group: "batch",
|
Group: "batch",
|
||||||
@@ -245,10 +245,10 @@ func TestConvertAPIResourceToDiscovery(t *testing.T) {
|
|||||||
Verbs: []string{"create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"},
|
Verbs: []string{"create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantAPIResourceDiscovery: []apidiscoveryv2beta1.APIResourceDiscovery{
|
wantAPIResourceDiscovery: []apidiscoveryv2.APIResourceDiscovery{
|
||||||
{
|
{
|
||||||
Resource: "cronjobs",
|
Resource: "cronjobs",
|
||||||
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
Scope: apidiscoveryv2.ScopeNamespace,
|
||||||
ResponseKind: &metav1.GroupVersionKind{
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
Group: "batch",
|
Group: "batch",
|
||||||
Version: "v1",
|
Version: "v1",
|
||||||
@@ -256,7 +256,7 @@ func TestConvertAPIResourceToDiscovery(t *testing.T) {
|
|||||||
},
|
},
|
||||||
ShortNames: []string{"cj"},
|
ShortNames: []string{"cj"},
|
||||||
Verbs: []string{"create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"},
|
Verbs: []string{"create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"},
|
||||||
Subresources: []apidiscoveryv2beta1.APISubresourceDiscovery{{
|
Subresources: []apidiscoveryv2.APISubresourceDiscovery{{
|
||||||
Subresource: "status",
|
Subresource: "status",
|
||||||
ResponseKind: &metav1.GroupVersionKind{
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
Group: "batch",
|
Group: "batch",
|
||||||
@@ -267,7 +267,7 @@ func TestConvertAPIResourceToDiscovery(t *testing.T) {
|
|||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Resource: "deployments",
|
Resource: "deployments",
|
||||||
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
Scope: apidiscoveryv2.ScopeNamespace,
|
||||||
ResponseKind: &metav1.GroupVersionKind{
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
Group: "apps",
|
Group: "apps",
|
||||||
Version: "v1",
|
Version: "v1",
|
||||||
@@ -275,7 +275,7 @@ func TestConvertAPIResourceToDiscovery(t *testing.T) {
|
|||||||
},
|
},
|
||||||
ShortNames: []string{"deploy"},
|
ShortNames: []string{"deploy"},
|
||||||
Verbs: []string{"create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"},
|
Verbs: []string{"create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"},
|
||||||
Subresources: []apidiscoveryv2beta1.APISubresourceDiscovery{{
|
Subresources: []apidiscoveryv2.APISubresourceDiscovery{{
|
||||||
Subresource: "status",
|
Subresource: "status",
|
||||||
ResponseKind: &metav1.GroupVersionKind{
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
Group: "apps",
|
Group: "apps",
|
||||||
@@ -298,13 +298,13 @@ func TestConvertAPIResourceToDiscovery(t *testing.T) {
|
|||||||
Verbs: []string{"create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"},
|
Verbs: []string{"create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantAPIResourceDiscovery: []apidiscoveryv2beta1.APIResourceDiscovery{
|
wantAPIResourceDiscovery: []apidiscoveryv2.APIResourceDiscovery{
|
||||||
{
|
{
|
||||||
Resource: "cronjobs",
|
Resource: "cronjobs",
|
||||||
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
Scope: apidiscoveryv2.ScopeNamespace,
|
||||||
// populated to avoid nil panics
|
// populated to avoid nil panics
|
||||||
ResponseKind: &metav1.GroupVersionKind{},
|
ResponseKind: &metav1.GroupVersionKind{},
|
||||||
Subresources: []apidiscoveryv2beta1.APISubresourceDiscovery{{
|
Subresources: []apidiscoveryv2.APISubresourceDiscovery{{
|
||||||
Subresource: "status",
|
Subresource: "status",
|
||||||
ResponseKind: &metav1.GroupVersionKind{
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
Group: "batch",
|
Group: "batch",
|
||||||
@@ -327,13 +327,13 @@ func TestConvertAPIResourceToDiscovery(t *testing.T) {
|
|||||||
Verbs: []string{"create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"},
|
Verbs: []string{"create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantAPIResourceDiscovery: []apidiscoveryv2beta1.APIResourceDiscovery{
|
wantAPIResourceDiscovery: []apidiscoveryv2.APIResourceDiscovery{
|
||||||
{
|
{
|
||||||
Resource: "cronjobs",
|
Resource: "cronjobs",
|
||||||
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
Scope: apidiscoveryv2.ScopeNamespace,
|
||||||
// populated to avoid nil panics
|
// populated to avoid nil panics
|
||||||
ResponseKind: &metav1.GroupVersionKind{},
|
ResponseKind: &metav1.GroupVersionKind{},
|
||||||
Subresources: []apidiscoveryv2beta1.APISubresourceDiscovery{{
|
Subresources: []apidiscoveryv2.APISubresourceDiscovery{{
|
||||||
Subresource: "status",
|
Subresource: "status",
|
||||||
// populated to avoid nil panics
|
// populated to avoid nil panics
|
||||||
ResponseKind: &metav1.GroupVersionKind{},
|
ResponseKind: &metav1.GroupVersionKind{},
|
||||||
@@ -364,7 +364,7 @@ func TestConvertAPIResourceToDiscovery(t *testing.T) {
|
|||||||
Verbs: []string{"create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"},
|
Verbs: []string{"create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantAPIResourceDiscovery: []apidiscoveryv2beta1.APIResourceDiscovery{},
|
wantAPIResourceDiscovery: []apidiscoveryv2.APIResourceDiscovery{},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -378,10 +378,10 @@ func TestConvertAPIResourceToDiscovery(t *testing.T) {
|
|||||||
Verbs: []string{"create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"},
|
Verbs: []string{"create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantAPIResourceDiscovery: []apidiscoveryv2beta1.APIResourceDiscovery{
|
wantAPIResourceDiscovery: []apidiscoveryv2.APIResourceDiscovery{
|
||||||
{
|
{
|
||||||
Resource: "nodes",
|
Resource: "nodes",
|
||||||
Scope: apidiscoveryv2beta1.ScopeCluster,
|
Scope: apidiscoveryv2.ScopeCluster,
|
||||||
ResponseKind: &metav1.GroupVersionKind{
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
Kind: "Node",
|
Kind: "Node",
|
||||||
},
|
},
|
||||||
@@ -401,10 +401,10 @@ func TestConvertAPIResourceToDiscovery(t *testing.T) {
|
|||||||
Verbs: []string{"create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"},
|
Verbs: []string{"create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantAPIResourceDiscovery: []apidiscoveryv2beta1.APIResourceDiscovery{
|
wantAPIResourceDiscovery: []apidiscoveryv2.APIResourceDiscovery{
|
||||||
{
|
{
|
||||||
Resource: "nodes",
|
Resource: "nodes",
|
||||||
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
Scope: apidiscoveryv2.ScopeNamespace,
|
||||||
ResponseKind: &metav1.GroupVersionKind{
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
Kind: "Node",
|
Kind: "Node",
|
||||||
},
|
},
|
||||||
@@ -424,11 +424,11 @@ func TestConvertAPIResourceToDiscovery(t *testing.T) {
|
|||||||
Verbs: []string{"create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"},
|
Verbs: []string{"create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantAPIResourceDiscovery: []apidiscoveryv2beta1.APIResourceDiscovery{
|
wantAPIResourceDiscovery: []apidiscoveryv2.APIResourceDiscovery{
|
||||||
{
|
{
|
||||||
Resource: "nodes",
|
Resource: "nodes",
|
||||||
SingularResource: "node",
|
SingularResource: "node",
|
||||||
Scope: apidiscoveryv2beta1.ScopeCluster,
|
Scope: apidiscoveryv2.ScopeCluster,
|
||||||
ResponseKind: &metav1.GroupVersionKind{
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
Kind: "Node",
|
Kind: "Node",
|
||||||
},
|
},
|
||||||
|
@@ -29,7 +29,7 @@ import (
|
|||||||
systemd "github.com/coreos/go-systemd/v22/daemon"
|
systemd "github.com/coreos/go-systemd/v22/daemon"
|
||||||
|
|
||||||
"golang.org/x/time/rate"
|
"golang.org/x/time/rate"
|
||||||
apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
apidiscoveryv2 "k8s.io/api/apidiscovery/v2"
|
||||||
"k8s.io/apimachinery/pkg/api/meta"
|
"k8s.io/apimachinery/pkg/api/meta"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
@@ -756,8 +756,8 @@ func (s *GenericAPIServer) installAPIResources(apiPrefix string, apiGroupInfo *A
|
|||||||
if apiPrefix == APIGroupPrefix {
|
if apiPrefix == APIGroupPrefix {
|
||||||
s.AggregatedDiscoveryGroupManager.AddGroupVersion(
|
s.AggregatedDiscoveryGroupManager.AddGroupVersion(
|
||||||
groupVersion.Group,
|
groupVersion.Group,
|
||||||
apidiscoveryv2beta1.APIVersionDiscovery{
|
apidiscoveryv2.APIVersionDiscovery{
|
||||||
Freshness: apidiscoveryv2beta1.DiscoveryFreshnessCurrent,
|
Freshness: apidiscoveryv2.DiscoveryFreshnessCurrent,
|
||||||
Version: groupVersion.Version,
|
Version: groupVersion.Version,
|
||||||
Resources: discoveryAPIResources,
|
Resources: discoveryAPIResources,
|
||||||
},
|
},
|
||||||
@@ -766,8 +766,8 @@ func (s *GenericAPIServer) installAPIResources(apiPrefix string, apiGroupInfo *A
|
|||||||
// There is only one group version for legacy resources, priority can be defaulted to 0.
|
// There is only one group version for legacy resources, priority can be defaulted to 0.
|
||||||
s.AggregatedLegacyDiscoveryGroupManager.AddGroupVersion(
|
s.AggregatedLegacyDiscoveryGroupManager.AddGroupVersion(
|
||||||
groupVersion.Group,
|
groupVersion.Group,
|
||||||
apidiscoveryv2beta1.APIVersionDiscovery{
|
apidiscoveryv2.APIVersionDiscovery{
|
||||||
Freshness: apidiscoveryv2beta1.DiscoveryFreshnessCurrent,
|
Freshness: apidiscoveryv2.DiscoveryFreshnessCurrent,
|
||||||
Version: groupVersion.Version,
|
Version: groupVersion.Version,
|
||||||
Resources: discoveryAPIResources,
|
Resources: discoveryAPIResources,
|
||||||
},
|
},
|
||||||
|
@@ -19,7 +19,8 @@ package discovery
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
apidiscovery "k8s.io/api/apidiscovery/v2beta1"
|
apidiscovery "k8s.io/api/apidiscovery/v2"
|
||||||
|
apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
)
|
)
|
||||||
@@ -154,3 +155,124 @@ func convertAPISubresource(parent metav1.APIResource, in apidiscovery.APISubreso
|
|||||||
result.Verbs = in.Verbs
|
result.Verbs = in.Verbs
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Please note the functions below will be removed in v1.33. They facilitate conversion
|
||||||
|
// between the deprecated type apidiscoveryv2beta1.APIGroupDiscoveryList.
|
||||||
|
|
||||||
|
// SplitGroupsAndResourcesV2Beta1 transforms "aggregated" discovery top-level structure into
|
||||||
|
// the previous "unaggregated" discovery groups and resources.
|
||||||
|
// Deprecated: Please use SplitGroupsAndResources
|
||||||
|
func SplitGroupsAndResourcesV2Beta1(aggregatedGroups apidiscoveryv2beta1.APIGroupDiscoveryList) (
|
||||||
|
*metav1.APIGroupList,
|
||||||
|
map[schema.GroupVersion]*metav1.APIResourceList,
|
||||||
|
map[schema.GroupVersion]error) {
|
||||||
|
// Aggregated group list will contain the entirety of discovery, including
|
||||||
|
// groups, versions, and resources. GroupVersions marked "stale" are failed.
|
||||||
|
groups := []*metav1.APIGroup{}
|
||||||
|
failedGVs := map[schema.GroupVersion]error{}
|
||||||
|
resourcesByGV := map[schema.GroupVersion]*metav1.APIResourceList{}
|
||||||
|
for _, aggGroup := range aggregatedGroups.Items {
|
||||||
|
group, resources, failed := convertAPIGroupv2beta1(aggGroup)
|
||||||
|
groups = append(groups, group)
|
||||||
|
for gv, resourceList := range resources {
|
||||||
|
resourcesByGV[gv] = resourceList
|
||||||
|
}
|
||||||
|
for gv, err := range failed {
|
||||||
|
failedGVs[gv] = err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Transform slice of groups to group list before returning.
|
||||||
|
groupList := &metav1.APIGroupList{}
|
||||||
|
groupList.Groups = make([]metav1.APIGroup, 0, len(groups))
|
||||||
|
for _, group := range groups {
|
||||||
|
groupList.Groups = append(groupList.Groups, *group)
|
||||||
|
}
|
||||||
|
return groupList, resourcesByGV, failedGVs
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertAPIGroupv2beta1 tranforms an "aggregated" APIGroupDiscovery to an "legacy" APIGroup,
|
||||||
|
// also returning the map of APIResourceList for resources within GroupVersions.
|
||||||
|
func convertAPIGroupv2beta1(g apidiscoveryv2beta1.APIGroupDiscovery) (
|
||||||
|
*metav1.APIGroup,
|
||||||
|
map[schema.GroupVersion]*metav1.APIResourceList,
|
||||||
|
map[schema.GroupVersion]error) {
|
||||||
|
// Iterate through versions to convert to group and resources.
|
||||||
|
group := &metav1.APIGroup{}
|
||||||
|
gvResources := map[schema.GroupVersion]*metav1.APIResourceList{}
|
||||||
|
failedGVs := map[schema.GroupVersion]error{}
|
||||||
|
group.Name = g.ObjectMeta.Name
|
||||||
|
for _, v := range g.Versions {
|
||||||
|
gv := schema.GroupVersion{Group: g.Name, Version: v.Version}
|
||||||
|
if v.Freshness == apidiscoveryv2beta1.DiscoveryFreshnessStale {
|
||||||
|
failedGVs[gv] = StaleGroupVersionError{gv: gv}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
version := metav1.GroupVersionForDiscovery{}
|
||||||
|
version.GroupVersion = gv.String()
|
||||||
|
version.Version = v.Version
|
||||||
|
group.Versions = append(group.Versions, version)
|
||||||
|
// PreferredVersion is first non-stale Version
|
||||||
|
if group.PreferredVersion == (metav1.GroupVersionForDiscovery{}) {
|
||||||
|
group.PreferredVersion = version
|
||||||
|
}
|
||||||
|
resourceList := &metav1.APIResourceList{}
|
||||||
|
resourceList.GroupVersion = gv.String()
|
||||||
|
for _, r := range v.Resources {
|
||||||
|
resource, err := convertAPIResourcev2beta1(r)
|
||||||
|
if err == nil {
|
||||||
|
resourceList.APIResources = append(resourceList.APIResources, resource)
|
||||||
|
}
|
||||||
|
// Subresources field in new format get transformed into full APIResources.
|
||||||
|
// It is possible a partial result with an error was returned to be used
|
||||||
|
// as the parent resource for the subresource.
|
||||||
|
for _, subresource := range r.Subresources {
|
||||||
|
sr, err := convertAPISubresourcev2beta1(resource, subresource)
|
||||||
|
if err == nil {
|
||||||
|
resourceList.APIResources = append(resourceList.APIResources, sr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gvResources[gv] = resourceList
|
||||||
|
}
|
||||||
|
return group, gvResources, failedGVs
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertAPIResource tranforms a APIResourceDiscovery to an APIResource. We are
|
||||||
|
// resilient to missing GVK, since this resource might be the parent resource
|
||||||
|
// for a subresource. If the parent is missing a GVK, it is not returned in
|
||||||
|
// discovery, and the subresource MUST have the GVK.
|
||||||
|
func convertAPIResourcev2beta1(in apidiscoveryv2beta1.APIResourceDiscovery) (metav1.APIResource, error) {
|
||||||
|
result := metav1.APIResource{
|
||||||
|
Name: in.Resource,
|
||||||
|
SingularName: in.SingularResource,
|
||||||
|
Namespaced: in.Scope == apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
Verbs: in.Verbs,
|
||||||
|
ShortNames: in.ShortNames,
|
||||||
|
Categories: in.Categories,
|
||||||
|
}
|
||||||
|
// Can return partial result with error, which can be the parent for a
|
||||||
|
// subresource. Do not add this result to the returned discovery resources.
|
||||||
|
if in.ResponseKind == nil || (*in.ResponseKind) == emptyKind {
|
||||||
|
return result, fmt.Errorf("discovery resource %s missing GVK", in.Resource)
|
||||||
|
}
|
||||||
|
result.Group = in.ResponseKind.Group
|
||||||
|
result.Version = in.ResponseKind.Version
|
||||||
|
result.Kind = in.ResponseKind.Kind
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertAPISubresource tranforms a APISubresourceDiscovery to an APIResource.
|
||||||
|
func convertAPISubresourcev2beta1(parent metav1.APIResource, in apidiscoveryv2beta1.APISubresourceDiscovery) (metav1.APIResource, error) {
|
||||||
|
result := metav1.APIResource{}
|
||||||
|
if in.ResponseKind == nil || (*in.ResponseKind) == emptyKind {
|
||||||
|
return result, fmt.Errorf("subresource %s/%s missing GVK", parent.Name, in.Subresource)
|
||||||
|
}
|
||||||
|
result.Name = fmt.Sprintf("%s/%s", parent.Name, in.Subresource)
|
||||||
|
result.SingularName = parent.SingularName
|
||||||
|
result.Namespaced = parent.Namespaced
|
||||||
|
result.Group = in.ResponseKind.Group
|
||||||
|
result.Version = in.ResponseKind.Version
|
||||||
|
result.Kind = in.ResponseKind.Kind
|
||||||
|
result.Verbs = in.Verbs
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
@@ -20,7 +20,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
apidiscovery "k8s.io/api/apidiscovery/v2beta1"
|
apidiscovery "k8s.io/api/apidiscovery/v2"
|
||||||
|
apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
)
|
)
|
||||||
@@ -961,3 +962,941 @@ func TestSplitGroupsAndResources(t *testing.T) {
|
|||||||
assert.Equal(t, test.expectedGVResources, resourcesByGV)
|
assert.Equal(t, test.expectedGVResources, resourcesByGV)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Duplicated from test above. Remove after 1.33
|
||||||
|
func TestSplitGroupsAndResourcesV2Beta1(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
agg apidiscoveryv2beta1.APIGroupDiscoveryList
|
||||||
|
expectedGroups metav1.APIGroupList
|
||||||
|
expectedGVResources map[schema.GroupVersion]*metav1.APIResourceList
|
||||||
|
expectedFailedGVs map[schema.GroupVersion]error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Aggregated discovery: core/v1 group and pod resource",
|
||||||
|
agg: apidiscoveryv2beta1.APIGroupDiscoveryList{
|
||||||
|
Items: []apidiscoveryv2beta1.APIGroupDiscovery{
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "",
|
||||||
|
},
|
||||||
|
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
||||||
|
{
|
||||||
|
Version: "v1",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
Resource: "pods",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Pod",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedGroups: metav1.APIGroupList{
|
||||||
|
Groups: []metav1.APIGroup{
|
||||||
|
{
|
||||||
|
Name: "",
|
||||||
|
Versions: []metav1.GroupVersionForDiscovery{
|
||||||
|
{
|
||||||
|
GroupVersion: "v1",
|
||||||
|
Version: "v1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
PreferredVersion: metav1.GroupVersionForDiscovery{
|
||||||
|
GroupVersion: "v1",
|
||||||
|
Version: "v1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedGVResources: map[schema.GroupVersion]*metav1.APIResourceList{
|
||||||
|
{Group: "", Version: "v1"}: {
|
||||||
|
GroupVersion: "v1",
|
||||||
|
APIResources: []metav1.APIResource{
|
||||||
|
{
|
||||||
|
Name: "pods",
|
||||||
|
Namespaced: true,
|
||||||
|
Group: "",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Pod",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedFailedGVs: map[schema.GroupVersion]error{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Aggregated discovery: 1 group/1 resources at /api, 1 group/2 versions/1 resources at /apis",
|
||||||
|
agg: apidiscoveryv2beta1.APIGroupDiscoveryList{
|
||||||
|
Items: []apidiscoveryv2beta1.APIGroupDiscovery{
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "apps",
|
||||||
|
},
|
||||||
|
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
||||||
|
{
|
||||||
|
Version: "v2",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
Resource: "deployments",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v2",
|
||||||
|
Kind: "Deployment",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Version: "v1",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
Resource: "deployments",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Deployment",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedGroups: metav1.APIGroupList{
|
||||||
|
Groups: []metav1.APIGroup{
|
||||||
|
{
|
||||||
|
Name: "apps",
|
||||||
|
Versions: []metav1.GroupVersionForDiscovery{
|
||||||
|
{
|
||||||
|
GroupVersion: "apps/v2",
|
||||||
|
Version: "v2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
GroupVersion: "apps/v1",
|
||||||
|
Version: "v1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
PreferredVersion: metav1.GroupVersionForDiscovery{
|
||||||
|
GroupVersion: "apps/v2",
|
||||||
|
Version: "v2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedGVResources: map[schema.GroupVersion]*metav1.APIResourceList{
|
||||||
|
{Group: "apps", Version: "v1"}: {
|
||||||
|
GroupVersion: "apps/v1",
|
||||||
|
APIResources: []metav1.APIResource{
|
||||||
|
{
|
||||||
|
Name: "deployments",
|
||||||
|
Namespaced: true,
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Deployment",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{Group: "apps", Version: "v2"}: {
|
||||||
|
GroupVersion: "apps/v2",
|
||||||
|
APIResources: []metav1.APIResource{
|
||||||
|
{
|
||||||
|
Name: "deployments",
|
||||||
|
Namespaced: true,
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v2",
|
||||||
|
Kind: "Deployment",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedFailedGVs: map[schema.GroupVersion]error{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Aggregated discovery: 1 group/2 resources at /api, 1 group/2 resources at /apis",
|
||||||
|
agg: apidiscoveryv2beta1.APIGroupDiscoveryList{
|
||||||
|
Items: []apidiscoveryv2beta1.APIGroupDiscovery{
|
||||||
|
{
|
||||||
|
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
||||||
|
{
|
||||||
|
Version: "v1",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
Resource: "pods",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Pod",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Resource: "services",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Service",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "apps",
|
||||||
|
},
|
||||||
|
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
||||||
|
{
|
||||||
|
Version: "v1",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
Resource: "deployments",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Deployment",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Resource: "statefulsets",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "StatefulSet",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedGroups: metav1.APIGroupList{
|
||||||
|
Groups: []metav1.APIGroup{
|
||||||
|
{
|
||||||
|
Name: "",
|
||||||
|
Versions: []metav1.GroupVersionForDiscovery{
|
||||||
|
{
|
||||||
|
GroupVersion: "v1",
|
||||||
|
Version: "v1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
PreferredVersion: metav1.GroupVersionForDiscovery{
|
||||||
|
GroupVersion: "v1",
|
||||||
|
Version: "v1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "apps",
|
||||||
|
Versions: []metav1.GroupVersionForDiscovery{
|
||||||
|
{
|
||||||
|
GroupVersion: "apps/v1",
|
||||||
|
Version: "v1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
PreferredVersion: metav1.GroupVersionForDiscovery{
|
||||||
|
GroupVersion: "apps/v1",
|
||||||
|
Version: "v1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedGVResources: map[schema.GroupVersion]*metav1.APIResourceList{
|
||||||
|
{Group: "", Version: "v1"}: {
|
||||||
|
GroupVersion: "v1",
|
||||||
|
APIResources: []metav1.APIResource{
|
||||||
|
{
|
||||||
|
Name: "pods",
|
||||||
|
Namespaced: true,
|
||||||
|
Group: "",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Pod",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "services",
|
||||||
|
Namespaced: true,
|
||||||
|
Group: "",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Service",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{Group: "apps", Version: "v1"}: {
|
||||||
|
GroupVersion: "apps/v1",
|
||||||
|
APIResources: []metav1.APIResource{
|
||||||
|
{
|
||||||
|
Name: "deployments",
|
||||||
|
Namespaced: true,
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Deployment",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "statefulsets",
|
||||||
|
Namespaced: true,
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "StatefulSet",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedFailedGVs: map[schema.GroupVersion]error{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Aggregated discovery: multiple groups with cluster-scoped resources",
|
||||||
|
agg: apidiscoveryv2beta1.APIGroupDiscoveryList{
|
||||||
|
Items: []apidiscoveryv2beta1.APIGroupDiscovery{
|
||||||
|
{
|
||||||
|
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
||||||
|
{
|
||||||
|
Version: "v1",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
Resource: "pods",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Pod",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Resource: "namespaces",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Namespace",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeCluster,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "rbac.authorization.k8s.io",
|
||||||
|
},
|
||||||
|
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
||||||
|
{
|
||||||
|
Version: "v1",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
Resource: "roles",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "rbac.authorization.k8s.io",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Role",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeCluster,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Resource: "clusterroles",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "rbac.authorization.k8s.io",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "ClusterRole",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeCluster,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedGroups: metav1.APIGroupList{
|
||||||
|
Groups: []metav1.APIGroup{
|
||||||
|
{
|
||||||
|
Name: "",
|
||||||
|
Versions: []metav1.GroupVersionForDiscovery{
|
||||||
|
{
|
||||||
|
GroupVersion: "v1",
|
||||||
|
Version: "v1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
PreferredVersion: metav1.GroupVersionForDiscovery{
|
||||||
|
GroupVersion: "v1",
|
||||||
|
Version: "v1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "rbac.authorization.k8s.io",
|
||||||
|
Versions: []metav1.GroupVersionForDiscovery{
|
||||||
|
{
|
||||||
|
GroupVersion: "rbac.authorization.k8s.io/v1",
|
||||||
|
Version: "v1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
PreferredVersion: metav1.GroupVersionForDiscovery{
|
||||||
|
GroupVersion: "rbac.authorization.k8s.io/v1",
|
||||||
|
Version: "v1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedGVResources: map[schema.GroupVersion]*metav1.APIResourceList{
|
||||||
|
{Group: "", Version: "v1"}: {
|
||||||
|
GroupVersion: "v1",
|
||||||
|
APIResources: []metav1.APIResource{
|
||||||
|
{
|
||||||
|
Name: "pods",
|
||||||
|
Namespaced: true,
|
||||||
|
Group: "",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Pod",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "namespaces",
|
||||||
|
Namespaced: false,
|
||||||
|
Group: "",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Namespace",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{Group: "rbac.authorization.k8s.io", Version: "v1"}: {
|
||||||
|
GroupVersion: "rbac.authorization.k8s.io/v1",
|
||||||
|
APIResources: []metav1.APIResource{
|
||||||
|
{
|
||||||
|
Name: "roles",
|
||||||
|
Namespaced: false,
|
||||||
|
Group: "rbac.authorization.k8s.io",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Role",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "clusterroles",
|
||||||
|
Namespaced: false,
|
||||||
|
Group: "rbac.authorization.k8s.io",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "ClusterRole",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedFailedGVs: map[schema.GroupVersion]error{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Aggregated discovery with single subresource",
|
||||||
|
agg: apidiscoveryv2beta1.APIGroupDiscoveryList{
|
||||||
|
Items: []apidiscoveryv2beta1.APIGroupDiscovery{
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "apps",
|
||||||
|
},
|
||||||
|
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
||||||
|
{
|
||||||
|
Version: "v1",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
Resource: "deployments",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Deployment",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
SingularResource: "deployment",
|
||||||
|
ShortNames: []string{"deploy"},
|
||||||
|
Verbs: []string{"parentverb1", "parentverb2", "parentverb3", "parentverb4"},
|
||||||
|
Categories: []string{"all", "testcategory"},
|
||||||
|
Subresources: []apidiscoveryv2beta1.APISubresourceDiscovery{
|
||||||
|
{
|
||||||
|
Subresource: "scale",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Deployment",
|
||||||
|
},
|
||||||
|
Verbs: []string{"get", "patch", "update"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedGroups: metav1.APIGroupList{
|
||||||
|
Groups: []metav1.APIGroup{
|
||||||
|
{
|
||||||
|
Name: "apps",
|
||||||
|
Versions: []metav1.GroupVersionForDiscovery{
|
||||||
|
{
|
||||||
|
GroupVersion: "apps/v1",
|
||||||
|
Version: "v1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
PreferredVersion: metav1.GroupVersionForDiscovery{
|
||||||
|
GroupVersion: "apps/v1",
|
||||||
|
Version: "v1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedGVResources: map[schema.GroupVersion]*metav1.APIResourceList{
|
||||||
|
{Group: "apps", Version: "v1"}: {
|
||||||
|
GroupVersion: "apps/v1",
|
||||||
|
APIResources: []metav1.APIResource{
|
||||||
|
{
|
||||||
|
Name: "deployments",
|
||||||
|
SingularName: "deployment",
|
||||||
|
Namespaced: true,
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Deployment",
|
||||||
|
Verbs: []string{"parentverb1", "parentverb2", "parentverb3", "parentverb4"},
|
||||||
|
ShortNames: []string{"deploy"},
|
||||||
|
Categories: []string{"all", "testcategory"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "deployments/scale",
|
||||||
|
SingularName: "deployment",
|
||||||
|
Namespaced: true,
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Deployment",
|
||||||
|
Verbs: []string{"get", "patch", "update"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedFailedGVs: map[schema.GroupVersion]error{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Aggregated discovery with single subresource and parent missing GVK",
|
||||||
|
agg: apidiscoveryv2beta1.APIGroupDiscoveryList{
|
||||||
|
Items: []apidiscoveryv2beta1.APIGroupDiscovery{
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "external.metrics.k8s.io",
|
||||||
|
},
|
||||||
|
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
||||||
|
{
|
||||||
|
Version: "v1beta1",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
// resilient to nil GVK for parent
|
||||||
|
Resource: "*",
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
SingularResource: "",
|
||||||
|
Subresources: []apidiscoveryv2beta1.APISubresourceDiscovery{
|
||||||
|
{
|
||||||
|
Subresource: "other-external-metric",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Kind: "MetricValueList",
|
||||||
|
},
|
||||||
|
Verbs: []string{"get"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedGroups: metav1.APIGroupList{
|
||||||
|
Groups: []metav1.APIGroup{
|
||||||
|
{
|
||||||
|
Name: "external.metrics.k8s.io",
|
||||||
|
Versions: []metav1.GroupVersionForDiscovery{
|
||||||
|
{
|
||||||
|
GroupVersion: "external.metrics.k8s.io/v1beta1",
|
||||||
|
Version: "v1beta1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
PreferredVersion: metav1.GroupVersionForDiscovery{
|
||||||
|
GroupVersion: "external.metrics.k8s.io/v1beta1",
|
||||||
|
Version: "v1beta1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedGVResources: map[schema.GroupVersion]*metav1.APIResourceList{
|
||||||
|
{Group: "external.metrics.k8s.io", Version: "v1beta1"}: {
|
||||||
|
GroupVersion: "external.metrics.k8s.io/v1beta1",
|
||||||
|
APIResources: []metav1.APIResource{
|
||||||
|
// Since parent GVK was nil, it is NOT returned--only the subresource.
|
||||||
|
{
|
||||||
|
Name: "*/other-external-metric",
|
||||||
|
SingularName: "",
|
||||||
|
Namespaced: true,
|
||||||
|
Group: "",
|
||||||
|
Version: "",
|
||||||
|
Kind: "MetricValueList",
|
||||||
|
Verbs: []string{"get"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedFailedGVs: map[schema.GroupVersion]error{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Aggregated discovery with single subresource and parent empty GVK",
|
||||||
|
agg: apidiscoveryv2beta1.APIGroupDiscoveryList{
|
||||||
|
Items: []apidiscoveryv2beta1.APIGroupDiscovery{
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "external.metrics.k8s.io",
|
||||||
|
},
|
||||||
|
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
||||||
|
{
|
||||||
|
Version: "v1beta1",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
// resilient to empty GVK for parent
|
||||||
|
Resource: "*",
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
SingularResource: "",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{},
|
||||||
|
Subresources: []apidiscoveryv2beta1.APISubresourceDiscovery{
|
||||||
|
{
|
||||||
|
Subresource: "other-external-metric",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Kind: "MetricValueList",
|
||||||
|
},
|
||||||
|
Verbs: []string{"get"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedGroups: metav1.APIGroupList{
|
||||||
|
Groups: []metav1.APIGroup{
|
||||||
|
{
|
||||||
|
Name: "external.metrics.k8s.io",
|
||||||
|
Versions: []metav1.GroupVersionForDiscovery{
|
||||||
|
{
|
||||||
|
GroupVersion: "external.metrics.k8s.io/v1beta1",
|
||||||
|
Version: "v1beta1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
PreferredVersion: metav1.GroupVersionForDiscovery{
|
||||||
|
GroupVersion: "external.metrics.k8s.io/v1beta1",
|
||||||
|
Version: "v1beta1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedGVResources: map[schema.GroupVersion]*metav1.APIResourceList{
|
||||||
|
{Group: "external.metrics.k8s.io", Version: "v1beta1"}: {
|
||||||
|
GroupVersion: "external.metrics.k8s.io/v1beta1",
|
||||||
|
APIResources: []metav1.APIResource{
|
||||||
|
// Since parent GVK was nil, it is NOT returned--only the subresource.
|
||||||
|
{
|
||||||
|
Name: "*/other-external-metric",
|
||||||
|
SingularName: "",
|
||||||
|
Namespaced: true,
|
||||||
|
Group: "",
|
||||||
|
Version: "",
|
||||||
|
Kind: "MetricValueList",
|
||||||
|
Verbs: []string{"get"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedFailedGVs: map[schema.GroupVersion]error{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Aggregated discovery with multiple subresources",
|
||||||
|
agg: apidiscoveryv2beta1.APIGroupDiscoveryList{
|
||||||
|
Items: []apidiscoveryv2beta1.APIGroupDiscovery{
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "apps",
|
||||||
|
},
|
||||||
|
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
||||||
|
{
|
||||||
|
Version: "v1",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
Resource: "deployments",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Deployment",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
SingularResource: "deployment",
|
||||||
|
Subresources: []apidiscoveryv2beta1.APISubresourceDiscovery{
|
||||||
|
{
|
||||||
|
Subresource: "scale",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Deployment",
|
||||||
|
},
|
||||||
|
Verbs: []string{"get", "patch", "update"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Subresource: "status",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Deployment",
|
||||||
|
},
|
||||||
|
Verbs: []string{"get", "patch", "update"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedGroups: metav1.APIGroupList{
|
||||||
|
Groups: []metav1.APIGroup{
|
||||||
|
{
|
||||||
|
Name: "apps",
|
||||||
|
Versions: []metav1.GroupVersionForDiscovery{
|
||||||
|
{
|
||||||
|
GroupVersion: "apps/v1",
|
||||||
|
Version: "v1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
PreferredVersion: metav1.GroupVersionForDiscovery{
|
||||||
|
GroupVersion: "apps/v1",
|
||||||
|
Version: "v1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedGVResources: map[schema.GroupVersion]*metav1.APIResourceList{
|
||||||
|
{Group: "apps", Version: "v1"}: {
|
||||||
|
GroupVersion: "apps/v1",
|
||||||
|
APIResources: []metav1.APIResource{
|
||||||
|
{
|
||||||
|
Name: "deployments",
|
||||||
|
SingularName: "deployment",
|
||||||
|
Namespaced: true,
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Deployment",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "deployments/scale",
|
||||||
|
SingularName: "deployment",
|
||||||
|
Namespaced: true,
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Deployment",
|
||||||
|
Verbs: []string{"get", "patch", "update"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "deployments/status",
|
||||||
|
SingularName: "deployment",
|
||||||
|
Namespaced: true,
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Deployment",
|
||||||
|
Verbs: []string{"get", "patch", "update"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedFailedGVs: map[schema.GroupVersion]error{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Aggregated discovery: single failed GV at /api",
|
||||||
|
agg: apidiscoveryv2beta1.APIGroupDiscoveryList{
|
||||||
|
Items: []apidiscoveryv2beta1.APIGroupDiscovery{
|
||||||
|
{
|
||||||
|
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
||||||
|
{
|
||||||
|
Version: "v1",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
Resource: "pods",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Pod",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Resource: "services",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Service",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Freshness: apidiscoveryv2beta1.DiscoveryFreshnessStale,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Single core Group/Version is stale, so no Version within Group.
|
||||||
|
expectedGroups: metav1.APIGroupList{
|
||||||
|
Groups: []metav1.APIGroup{{Name: ""}},
|
||||||
|
},
|
||||||
|
// Single core Group/Version is stale, so there are no expected resources.
|
||||||
|
expectedGVResources: map[schema.GroupVersion]*metav1.APIResourceList{},
|
||||||
|
expectedFailedGVs: map[schema.GroupVersion]error{
|
||||||
|
{Group: "", Version: "v1"}: StaleGroupVersionError{gv: schema.GroupVersion{Group: "", Version: "v1"}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Aggregated discovery: single failed GV at /apis",
|
||||||
|
agg: apidiscoveryv2beta1.APIGroupDiscoveryList{
|
||||||
|
Items: []apidiscoveryv2beta1.APIGroupDiscovery{
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "apps",
|
||||||
|
},
|
||||||
|
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
||||||
|
{
|
||||||
|
Version: "v1",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
Resource: "deployments",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Deployment",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Resource: "statefulsets",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "StatefulSets",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Freshness: apidiscoveryv2beta1.DiscoveryFreshnessStale,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Single apps/v1 Group/Version is stale, so no Version within Group.
|
||||||
|
expectedGroups: metav1.APIGroupList{
|
||||||
|
Groups: []metav1.APIGroup{{Name: "apps"}},
|
||||||
|
},
|
||||||
|
// Single apps/v1 Group/Version is stale, so there are no expected resources.
|
||||||
|
expectedGVResources: map[schema.GroupVersion]*metav1.APIResourceList{},
|
||||||
|
expectedFailedGVs: map[schema.GroupVersion]error{
|
||||||
|
{Group: "apps", Version: "v1"}: StaleGroupVersionError{gv: schema.GroupVersion{Group: "apps", Version: "v1"}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Aggregated discovery: 1 group/2 versions/1 failed GV at /apis",
|
||||||
|
agg: apidiscoveryv2beta1.APIGroupDiscoveryList{
|
||||||
|
Items: []apidiscoveryv2beta1.APIGroupDiscovery{
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "apps",
|
||||||
|
},
|
||||||
|
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
||||||
|
// Stale v2 should report failed GV.
|
||||||
|
{
|
||||||
|
Version: "v2",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
Resource: "daemonsets",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v2",
|
||||||
|
Kind: "DaemonSets",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Freshness: apidiscoveryv2beta1.DiscoveryFreshnessStale,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Version: "v1",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
Resource: "deployments",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Deployment",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Only apps/v1 is non-stale expected Group/Version
|
||||||
|
expectedGroups: metav1.APIGroupList{
|
||||||
|
Groups: []metav1.APIGroup{
|
||||||
|
{
|
||||||
|
Name: "apps",
|
||||||
|
Versions: []metav1.GroupVersionForDiscovery{
|
||||||
|
{
|
||||||
|
GroupVersion: "apps/v1",
|
||||||
|
Version: "v1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// PreferredVersion must be apps/v1
|
||||||
|
PreferredVersion: metav1.GroupVersionForDiscovery{
|
||||||
|
GroupVersion: "apps/v1",
|
||||||
|
Version: "v1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Only apps/v1 resources expected.
|
||||||
|
expectedGVResources: map[schema.GroupVersion]*metav1.APIResourceList{
|
||||||
|
{Group: "apps", Version: "v1"}: {
|
||||||
|
GroupVersion: "apps/v1",
|
||||||
|
APIResources: []metav1.APIResource{
|
||||||
|
{
|
||||||
|
Name: "deployments",
|
||||||
|
Namespaced: true,
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Deployment",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedFailedGVs: map[schema.GroupVersion]error{
|
||||||
|
{Group: "apps", Version: "v2"}: StaleGroupVersionError{gv: schema.GroupVersion{Group: "apps", Version: "v2"}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
apiGroups, resourcesByGV, failedGVs := SplitGroupsAndResourcesV2Beta1(test.agg)
|
||||||
|
assert.Equal(t, test.expectedFailedGVs, failedGVs)
|
||||||
|
assert.Equal(t, test.expectedGroups, *apiGroups)
|
||||||
|
assert.Equal(t, test.expectedGVResources, resourcesByGV)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -30,7 +30,7 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
apidiscovery "k8s.io/api/apidiscovery/v2beta1"
|
apidiscovery "k8s.io/api/apidiscovery/v2"
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
@@ -643,7 +643,7 @@ func TestCachedDiscoveryClientAggregatedServerGroups(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Content-type is "aggregated" discovery format.
|
// Content-type is "aggregated" discovery format.
|
||||||
w.Header().Set("Content-Type", discovery.AcceptV2Beta1)
|
w.Header().Set("Content-Type", discovery.AcceptV2)
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
w.Write(output)
|
w.Write(output)
|
||||||
}))
|
}))
|
||||||
|
@@ -28,7 +28,7 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
apidiscovery "k8s.io/api/apidiscovery/v2beta1"
|
apidiscovery "k8s.io/api/apidiscovery/v2"
|
||||||
errorsutil "k8s.io/apimachinery/pkg/api/errors"
|
errorsutil "k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
@@ -1118,7 +1118,7 @@ func TestAggregatedMemCacheGroupsAndMaybeResources(t *testing.T) {
|
|||||||
output, err := json.Marshal(agg)
|
output, err := json.Marshal(agg)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
// Content-type is "aggregated" discovery format.
|
// Content-type is "aggregated" discovery format.
|
||||||
w.Header().Set("Content-Type", discovery.AcceptV2Beta1)
|
w.Header().Set("Content-Type", discovery.AcceptV2)
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
w.Write(output)
|
w.Write(output)
|
||||||
}))
|
}))
|
||||||
@@ -1161,6 +1161,7 @@ func TestAggregatedMemCacheGroupsAndMaybeResources(t *testing.T) {
|
|||||||
memClient.Invalidate()
|
memClient.Invalidate()
|
||||||
assert.False(t, memClient.Fresh())
|
assert.False(t, memClient.Fresh())
|
||||||
apiGroupList, _, _, err = memClient.GroupsAndMaybeResources()
|
apiGroupList, _, _, err = memClient.GroupsAndMaybeResources()
|
||||||
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
// Test the expected groups are returned for the aggregated format.
|
// Test the expected groups are returned for the aggregated format.
|
||||||
actualGroupNames = sets.NewString(groupNamesFromList(apiGroupList)...)
|
actualGroupNames = sets.NewString(groupNamesFromList(apiGroupList)...)
|
||||||
|
@@ -33,7 +33,8 @@ import (
|
|||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
openapi_v2 "github.com/google/gnostic-models/openapiv2"
|
openapi_v2 "github.com/google/gnostic-models/openapiv2"
|
||||||
|
|
||||||
apidiscovery "k8s.io/api/apidiscovery/v2beta1"
|
apidiscoveryv2 "k8s.io/api/apidiscovery/v2"
|
||||||
|
apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
@@ -64,12 +65,14 @@ const (
|
|||||||
// MUST be ordered (g, v, as) for server in "Accept" header (BUT we are resilient
|
// MUST be ordered (g, v, as) for server in "Accept" header (BUT we are resilient
|
||||||
// to ordering when comparing returned values in "Content-Type" header).
|
// to ordering when comparing returned values in "Content-Type" header).
|
||||||
AcceptV2Beta1 = runtime.ContentTypeJSON + ";" + "g=apidiscovery.k8s.io;v=v2beta1;as=APIGroupDiscoveryList"
|
AcceptV2Beta1 = runtime.ContentTypeJSON + ";" + "g=apidiscovery.k8s.io;v=v2beta1;as=APIGroupDiscoveryList"
|
||||||
|
AcceptV2 = runtime.ContentTypeJSON + ";" + "g=apidiscovery.k8s.io;v=v2;as=APIGroupDiscoveryList"
|
||||||
// Prioritize aggregated discovery by placing first in the order of discovery accept types.
|
// Prioritize aggregated discovery by placing first in the order of discovery accept types.
|
||||||
acceptDiscoveryFormats = AcceptV2Beta1 + "," + AcceptV1
|
acceptDiscoveryFormats = AcceptV2 + "," + AcceptV2Beta1 + "," + AcceptV1
|
||||||
)
|
)
|
||||||
|
|
||||||
// Aggregated discovery content-type GVK.
|
// Aggregated discovery content-type GVK.
|
||||||
var v2Beta1GVK = schema.GroupVersionKind{Group: "apidiscovery.k8s.io", Version: "v2beta1", Kind: "APIGroupDiscoveryList"}
|
var v2Beta1GVK = schema.GroupVersionKind{Group: "apidiscovery.k8s.io", Version: "v2beta1", Kind: "APIGroupDiscoveryList"}
|
||||||
|
var v2GVK = schema.GroupVersionKind{Group: "apidiscovery.k8s.io", Version: "v2", Kind: "APIGroupDiscoveryList"}
|
||||||
|
|
||||||
// DiscoveryInterface holds the methods that discover server-supported API groups,
|
// DiscoveryInterface holds the methods that discover server-supported API groups,
|
||||||
// versions and resources.
|
// versions and resources.
|
||||||
@@ -265,13 +268,20 @@ func (d *DiscoveryClient) downloadLegacy() (
|
|||||||
|
|
||||||
var resourcesByGV map[schema.GroupVersion]*metav1.APIResourceList
|
var resourcesByGV map[schema.GroupVersion]*metav1.APIResourceList
|
||||||
// Based on the content-type server responded with: aggregated or unaggregated.
|
// Based on the content-type server responded with: aggregated or unaggregated.
|
||||||
if isGVK, _ := ContentTypeIsGVK(responseContentType, v2Beta1GVK); isGVK {
|
if isGVK, _ := ContentTypeIsGVK(responseContentType, v2GVK); isGVK {
|
||||||
var aggregatedDiscovery apidiscovery.APIGroupDiscoveryList
|
var aggregatedDiscovery apidiscoveryv2.APIGroupDiscoveryList
|
||||||
err = json.Unmarshal(body, &aggregatedDiscovery)
|
err = json.Unmarshal(body, &aggregatedDiscovery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
apiGroupList, resourcesByGV, failedGVs = SplitGroupsAndResources(aggregatedDiscovery)
|
apiGroupList, resourcesByGV, failedGVs = SplitGroupsAndResources(aggregatedDiscovery)
|
||||||
|
} else if isGVK, _ := ContentTypeIsGVK(responseContentType, v2Beta1GVK); isGVK {
|
||||||
|
var aggregatedDiscovery apidiscoveryv2beta1.APIGroupDiscoveryList
|
||||||
|
err = json.Unmarshal(body, &aggregatedDiscovery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
apiGroupList, resourcesByGV, failedGVs = SplitGroupsAndResourcesV2Beta1(aggregatedDiscovery)
|
||||||
} else {
|
} else {
|
||||||
// Default is unaggregated discovery v1.
|
// Default is unaggregated discovery v1.
|
||||||
var v metav1.APIVersions
|
var v metav1.APIVersions
|
||||||
@@ -317,13 +327,20 @@ func (d *DiscoveryClient) downloadAPIs() (
|
|||||||
failedGVs := map[schema.GroupVersion]error{}
|
failedGVs := map[schema.GroupVersion]error{}
|
||||||
var resourcesByGV map[schema.GroupVersion]*metav1.APIResourceList
|
var resourcesByGV map[schema.GroupVersion]*metav1.APIResourceList
|
||||||
// Based on the content-type server responded with: aggregated or unaggregated.
|
// Based on the content-type server responded with: aggregated or unaggregated.
|
||||||
if isGVK, _ := ContentTypeIsGVK(responseContentType, v2Beta1GVK); isGVK {
|
if isGVK, _ := ContentTypeIsGVK(responseContentType, v2GVK); isGVK {
|
||||||
var aggregatedDiscovery apidiscovery.APIGroupDiscoveryList
|
var aggregatedDiscovery apidiscoveryv2.APIGroupDiscoveryList
|
||||||
err = json.Unmarshal(body, &aggregatedDiscovery)
|
err = json.Unmarshal(body, &aggregatedDiscovery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
apiGroupList, resourcesByGV, failedGVs = SplitGroupsAndResources(aggregatedDiscovery)
|
apiGroupList, resourcesByGV, failedGVs = SplitGroupsAndResources(aggregatedDiscovery)
|
||||||
|
} else if isGVK, _ := ContentTypeIsGVK(responseContentType, v2Beta1GVK); isGVK {
|
||||||
|
var aggregatedDiscovery apidiscoveryv2beta1.APIGroupDiscoveryList
|
||||||
|
err = json.Unmarshal(body, &aggregatedDiscovery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
apiGroupList, resourcesByGV, failedGVs = SplitGroupsAndResourcesV2Beta1(aggregatedDiscovery)
|
||||||
} else {
|
} else {
|
||||||
// Default is unaggregated discovery v1.
|
// Default is unaggregated discovery v1.
|
||||||
err = json.Unmarshal(body, apiGroupList)
|
err = json.Unmarshal(body, apiGroupList)
|
||||||
|
@@ -32,7 +32,8 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
golangproto "google.golang.org/protobuf/proto"
|
golangproto "google.golang.org/protobuf/proto"
|
||||||
apidiscovery "k8s.io/api/apidiscovery/v2beta1"
|
apidiscovery "k8s.io/api/apidiscovery/v2"
|
||||||
|
apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
@@ -58,7 +59,8 @@ func TestGetServerVersion(t *testing.T) {
|
|||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
w.Write(output)
|
_, err = w.Write(output)
|
||||||
|
require.NoError(t, err)
|
||||||
}))
|
}))
|
||||||
defer server.Close()
|
defer server.Close()
|
||||||
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL})
|
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL})
|
||||||
@@ -104,7 +106,8 @@ func TestGetServerGroupsWithV1Server(t *testing.T) {
|
|||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
w.Write(output)
|
_, err = w.Write(output)
|
||||||
|
require.NoError(t, err)
|
||||||
}))
|
}))
|
||||||
defer server.Close()
|
defer server.Close()
|
||||||
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL})
|
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL})
|
||||||
@@ -144,7 +147,8 @@ func TestDiscoveryToleratesMissingCoreGroup(t *testing.T) {
|
|||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
w.Write(output)
|
_, err = w.Write(output)
|
||||||
|
require.NoError(t, err)
|
||||||
}))
|
}))
|
||||||
defer server.Close()
|
defer server.Close()
|
||||||
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL})
|
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL})
|
||||||
@@ -180,7 +184,8 @@ func TestDiscoveryFailsWhenNonCoreGroupsMissing(t *testing.T) {
|
|||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
w.Write(output)
|
_, err = w.Write(output)
|
||||||
|
require.NoError(t, err)
|
||||||
}))
|
}))
|
||||||
defer server.Close()
|
defer server.Close()
|
||||||
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL})
|
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL})
|
||||||
@@ -380,7 +385,8 @@ func TestGetServerResourcesForGroupVersion(t *testing.T) {
|
|||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
w.Write(output)
|
_, err = w.Write(output)
|
||||||
|
require.NoError(t, err)
|
||||||
}))
|
}))
|
||||||
defer server.Close()
|
defer server.Close()
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
@@ -1294,6 +1300,8 @@ func TestAggregatedServerGroups(t *testing.T) {
|
|||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||||
|
var output []byte
|
||||||
|
var err error
|
||||||
var agg *apidiscovery.APIGroupDiscoveryList
|
var agg *apidiscovery.APIGroupDiscoveryList
|
||||||
switch req.URL.Path {
|
switch req.URL.Path {
|
||||||
case "/api":
|
case "/api":
|
||||||
@@ -1304,13 +1312,14 @@ func TestAggregatedServerGroups(t *testing.T) {
|
|||||||
w.WriteHeader(http.StatusNotFound)
|
w.WriteHeader(http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
output, err := json.Marshal(agg)
|
output, err = json.Marshal(agg)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
// Content-Type is "aggregated" discovery format. Add extra parameter
|
// Content-Type is "aggregated" discovery format. Add extra parameter
|
||||||
// to ensure we are resilient to these extra parameters.
|
// to ensure we are resilient to these extra parameters.
|
||||||
w.Header().Set("Content-Type", AcceptV2Beta1+"; charset=utf-8")
|
w.Header().Set("Content-Type", AcceptV2+"; charset=utf-8")
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
w.Write(output)
|
_, err = w.Write(output)
|
||||||
|
require.NoError(t, err)
|
||||||
}))
|
}))
|
||||||
defer server.Close()
|
defer server.Close()
|
||||||
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL})
|
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL})
|
||||||
@@ -1338,7 +1347,9 @@ func TestAggregatedServerGroupsAndResources(t *testing.T) {
|
|||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
corev1 *apidiscovery.APIGroupDiscoveryList
|
corev1 *apidiscovery.APIGroupDiscoveryList
|
||||||
|
corev1DiscoveryBeta *apidiscoveryv2beta1.APIGroupDiscoveryList
|
||||||
apis *apidiscovery.APIGroupDiscoveryList
|
apis *apidiscovery.APIGroupDiscoveryList
|
||||||
|
apisDiscoveryBeta *apidiscoveryv2beta1.APIGroupDiscoveryList
|
||||||
expectedGroupNames []string
|
expectedGroupNames []string
|
||||||
expectedGroupVersions []string
|
expectedGroupVersions []string
|
||||||
expectedGVKs []string
|
expectedGVKs []string
|
||||||
@@ -1368,6 +1379,28 @@ func TestAggregatedServerGroupsAndResources(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
corev1DiscoveryBeta: &apidiscoveryv2beta1.APIGroupDiscoveryList{
|
||||||
|
Items: []apidiscoveryv2beta1.APIGroupDiscovery{
|
||||||
|
{
|
||||||
|
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
||||||
|
{
|
||||||
|
Version: "v1",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
Resource: "pods",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Pod",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
apis: &apidiscovery.APIGroupDiscoveryList{
|
apis: &apidiscovery.APIGroupDiscoveryList{
|
||||||
Items: []apidiscovery.APIGroupDiscovery{
|
Items: []apidiscovery.APIGroupDiscovery{
|
||||||
{
|
{
|
||||||
@@ -1393,6 +1426,31 @@ func TestAggregatedServerGroupsAndResources(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
apisDiscoveryBeta: &apidiscoveryv2beta1.APIGroupDiscoveryList{
|
||||||
|
Items: []apidiscoveryv2beta1.APIGroupDiscovery{
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "apps",
|
||||||
|
},
|
||||||
|
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
||||||
|
{
|
||||||
|
Version: "v1",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
Resource: "deployments",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Deployment",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
expectedGroupNames: []string{"", "apps"},
|
expectedGroupNames: []string{"", "apps"},
|
||||||
expectedGroupVersions: []string{"v1", "apps/v1"},
|
expectedGroupVersions: []string{"v1", "apps/v1"},
|
||||||
expectedGVKs: []string{
|
expectedGVKs: []string{
|
||||||
@@ -1424,6 +1482,28 @@ func TestAggregatedServerGroupsAndResources(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
corev1DiscoveryBeta: &apidiscoveryv2beta1.APIGroupDiscoveryList{
|
||||||
|
Items: []apidiscoveryv2beta1.APIGroupDiscovery{
|
||||||
|
{
|
||||||
|
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
||||||
|
{
|
||||||
|
Version: "v1",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
Resource: "pods",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Pod",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
apis: &apidiscovery.APIGroupDiscoveryList{
|
apis: &apidiscovery.APIGroupDiscoveryList{
|
||||||
Items: []apidiscovery.APIGroupDiscovery{
|
Items: []apidiscovery.APIGroupDiscovery{
|
||||||
{
|
{
|
||||||
@@ -1463,6 +1543,45 @@ func TestAggregatedServerGroupsAndResources(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
apisDiscoveryBeta: &apidiscoveryv2beta1.APIGroupDiscoveryList{
|
||||||
|
Items: []apidiscoveryv2beta1.APIGroupDiscovery{
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "apps",
|
||||||
|
},
|
||||||
|
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
||||||
|
{
|
||||||
|
Version: "v1",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
Resource: "deployments",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Deployment",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Version: "v2",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
Resource: "deployments",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v2",
|
||||||
|
Kind: "Deployment",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
expectedGroupNames: []string{"", "apps"},
|
expectedGroupNames: []string{"", "apps"},
|
||||||
expectedGroupVersions: []string{"v1", "apps/v1", "apps/v2"},
|
expectedGroupVersions: []string{"v1", "apps/v1", "apps/v2"},
|
||||||
expectedGVKs: []string{
|
expectedGVKs: []string{
|
||||||
@@ -1495,6 +1614,28 @@ func TestAggregatedServerGroupsAndResources(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
corev1DiscoveryBeta: &apidiscoveryv2beta1.APIGroupDiscoveryList{
|
||||||
|
Items: []apidiscoveryv2beta1.APIGroupDiscovery{
|
||||||
|
{
|
||||||
|
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
||||||
|
{
|
||||||
|
Version: "v1",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
Resource: "pods",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Pod",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
apis: &apidiscovery.APIGroupDiscoveryList{
|
apis: &apidiscovery.APIGroupDiscoveryList{
|
||||||
Items: []apidiscovery.APIGroupDiscovery{
|
Items: []apidiscovery.APIGroupDiscovery{
|
||||||
{
|
{
|
||||||
@@ -1535,6 +1676,46 @@ func TestAggregatedServerGroupsAndResources(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
apisDiscoveryBeta: &apidiscoveryv2beta1.APIGroupDiscoveryList{
|
||||||
|
Items: []apidiscoveryv2beta1.APIGroupDiscovery{
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "apps",
|
||||||
|
},
|
||||||
|
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
||||||
|
{
|
||||||
|
Version: "v1",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
Resource: "deployments",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Deployment",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Version: "v2",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
Resource: "deployments",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v2",
|
||||||
|
Kind: "Deployment",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Freshness: apidiscoveryv2beta1.DiscoveryFreshnessStale,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
expectedGroupNames: []string{"", "apps"},
|
expectedGroupNames: []string{"", "apps"},
|
||||||
expectedGroupVersions: []string{"v1", "apps/v1"},
|
expectedGroupVersions: []string{"v1", "apps/v1"},
|
||||||
expectedGVKs: []string{
|
expectedGVKs: []string{
|
||||||
@@ -1576,6 +1757,37 @@ func TestAggregatedServerGroupsAndResources(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
corev1DiscoveryBeta: &apidiscoveryv2beta1.APIGroupDiscoveryList{
|
||||||
|
Items: []apidiscoveryv2beta1.APIGroupDiscovery{
|
||||||
|
{
|
||||||
|
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
||||||
|
{
|
||||||
|
Version: "v1",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
Resource: "pods",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Pod",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Resource: "services",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Service",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
apis: &apidiscovery.APIGroupDiscoveryList{
|
apis: &apidiscovery.APIGroupDiscoveryList{
|
||||||
Items: []apidiscovery.APIGroupDiscovery{
|
Items: []apidiscovery.APIGroupDiscovery{
|
||||||
{
|
{
|
||||||
@@ -1635,6 +1847,65 @@ func TestAggregatedServerGroupsAndResources(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
apisDiscoveryBeta: &apidiscoveryv2beta1.APIGroupDiscoveryList{
|
||||||
|
Items: []apidiscoveryv2beta1.APIGroupDiscovery{
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "apps",
|
||||||
|
},
|
||||||
|
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
||||||
|
// Stale "v2" version not included.
|
||||||
|
{
|
||||||
|
Version: "v2",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
Resource: "deployments",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v2",
|
||||||
|
Kind: "Deployment",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Resource: "statefulsets",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v2",
|
||||||
|
Kind: "StatefulSet",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Freshness: apidiscoveryv2beta1.DiscoveryFreshnessStale,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Version: "v1",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
Resource: "deployments",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Deployment",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Resource: "statefulsets",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "StatefulSet",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
expectedGroupNames: []string{"", "apps"},
|
expectedGroupNames: []string{"", "apps"},
|
||||||
expectedGroupVersions: []string{"v1", "apps/v1"},
|
expectedGroupVersions: []string{"v1", "apps/v1"},
|
||||||
expectedGVKs: []string{
|
expectedGVKs: []string{
|
||||||
@@ -1678,6 +1949,37 @@ func TestAggregatedServerGroupsAndResources(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
corev1DiscoveryBeta: &apidiscoveryv2beta1.APIGroupDiscoveryList{
|
||||||
|
Items: []apidiscoveryv2beta1.APIGroupDiscovery{
|
||||||
|
{
|
||||||
|
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
||||||
|
{
|
||||||
|
Version: "v1",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
Resource: "pods",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Pod",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Resource: "services",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Service",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
apis: &apidiscovery.APIGroupDiscoveryList{
|
apis: &apidiscovery.APIGroupDiscoveryList{
|
||||||
Items: []apidiscovery.APIGroupDiscovery{
|
Items: []apidiscovery.APIGroupDiscovery{
|
||||||
{
|
{
|
||||||
@@ -1767,6 +2069,95 @@ func TestAggregatedServerGroupsAndResources(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
apisDiscoveryBeta: &apidiscoveryv2beta1.APIGroupDiscoveryList{
|
||||||
|
Items: []apidiscoveryv2beta1.APIGroupDiscovery{
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "apps",
|
||||||
|
},
|
||||||
|
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
||||||
|
{
|
||||||
|
Version: "v1",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
Resource: "deployments",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Deployment",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Resource: "statefulsets",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "StatefulSet",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "batch",
|
||||||
|
},
|
||||||
|
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
||||||
|
// Stale Group/Version is not included
|
||||||
|
{
|
||||||
|
Version: "v1",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
Resource: "jobs",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "batch",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Job",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Resource: "cronjobs",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "batch",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "CronJob",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Freshness: apidiscoveryv2beta1.DiscoveryFreshnessStale,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Version: "v1beta1",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
Resource: "jobs",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "batch",
|
||||||
|
Version: "v1beta1",
|
||||||
|
Kind: "Job",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Resource: "cronjobs",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "batch",
|
||||||
|
Version: "v1beta1",
|
||||||
|
Kind: "CronJob",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
expectedGroupNames: []string{"", "apps", "batch"},
|
expectedGroupNames: []string{"", "apps", "batch"},
|
||||||
expectedGroupVersions: []string{"v1", "apps/v1", "batch/v1beta1"},
|
expectedGroupVersions: []string{"v1", "apps/v1", "batch/v1beta1"},
|
||||||
expectedGVKs: []string{
|
expectedGVKs: []string{
|
||||||
@@ -1780,8 +2171,9 @@ func TestAggregatedServerGroupsAndResources(t *testing.T) {
|
|||||||
expectedFailedGVs: []string{"batch/v1"},
|
expectedFailedGVs: []string{"batch/v1"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Aggregated discovery: /api returns nothing, 2 groups/2 resources at /apis",
|
name: "Aggregated discovery: /api returns nothing, 2 groups/2 resources at /apis",
|
||||||
corev1: &apidiscovery.APIGroupDiscoveryList{},
|
corev1: &apidiscovery.APIGroupDiscoveryList{},
|
||||||
|
corev1DiscoveryBeta: &apidiscoveryv2beta1.APIGroupDiscoveryList{},
|
||||||
apis: &apidiscovery.APIGroupDiscoveryList{
|
apis: &apidiscovery.APIGroupDiscoveryList{
|
||||||
Items: []apidiscovery.APIGroupDiscovery{
|
Items: []apidiscovery.APIGroupDiscovery{
|
||||||
{
|
{
|
||||||
@@ -1871,6 +2263,95 @@ func TestAggregatedServerGroupsAndResources(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
apisDiscoveryBeta: &apidiscoveryv2beta1.APIGroupDiscoveryList{
|
||||||
|
Items: []apidiscoveryv2beta1.APIGroupDiscovery{
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "apps",
|
||||||
|
},
|
||||||
|
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
||||||
|
{
|
||||||
|
Version: "v1",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
Resource: "deployments",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Deployment",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Resource: "statefulsets",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "apps",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "StatefulSet",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "batch",
|
||||||
|
},
|
||||||
|
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
||||||
|
{
|
||||||
|
Version: "v1",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
Resource: "jobs",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "batch",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "Job",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Resource: "cronjobs",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "batch",
|
||||||
|
Version: "v1",
|
||||||
|
Kind: "CronJob",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Stale "v1beta1" not included.
|
||||||
|
Version: "v1beta1",
|
||||||
|
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
Resource: "jobs",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "batch",
|
||||||
|
Version: "v1beta1",
|
||||||
|
Kind: "Job",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Resource: "cronjobs",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{
|
||||||
|
Group: "batch",
|
||||||
|
Version: "v1beta1",
|
||||||
|
Kind: "CronJob",
|
||||||
|
},
|
||||||
|
Scope: apidiscoveryv2beta1.ScopeNamespace,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Freshness: apidiscoveryv2beta1.DiscoveryFreshnessStale,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
expectedGroupNames: []string{"apps", "batch"},
|
expectedGroupNames: []string{"apps", "batch"},
|
||||||
expectedGroupVersions: []string{"apps/v1", "batch/v1"},
|
expectedGroupVersions: []string{"apps/v1", "batch/v1"},
|
||||||
expectedGVKs: []string{
|
expectedGVKs: []string{
|
||||||
@@ -1883,61 +2364,84 @@ func TestAggregatedServerGroupsAndResources(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure that client can parse both V2Beta1 and V2 types from server
|
||||||
|
serverAccepts := []string{AcceptV2Beta1, AcceptV2}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
for _, accept := range serverAccepts {
|
||||||
var agg *apidiscovery.APIGroupDiscoveryList
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||||
switch req.URL.Path {
|
var output []byte
|
||||||
case "/api":
|
var err error
|
||||||
agg = test.corev1
|
if accept == AcceptV2 {
|
||||||
case "/apis":
|
var agg *apidiscovery.APIGroupDiscoveryList
|
||||||
agg = test.apis
|
switch req.URL.Path {
|
||||||
default:
|
case "/api":
|
||||||
w.WriteHeader(http.StatusNotFound)
|
agg = test.corev1
|
||||||
return
|
case "/apis":
|
||||||
|
agg = test.apis
|
||||||
|
default:
|
||||||
|
w.WriteHeader(http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
output, err = json.Marshal(agg)
|
||||||
|
require.NoError(t, err)
|
||||||
|
} else {
|
||||||
|
var agg *apidiscoveryv2beta1.APIGroupDiscoveryList
|
||||||
|
switch req.URL.Path {
|
||||||
|
case "/api":
|
||||||
|
agg = test.corev1DiscoveryBeta
|
||||||
|
case "/apis":
|
||||||
|
agg = test.apisDiscoveryBeta
|
||||||
|
default:
|
||||||
|
w.WriteHeader(http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
output, err = json.Marshal(&agg)
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
// Content-Type is "aggregated" discovery format. Add extra parameter
|
||||||
|
// to ensure we are resilient to these extra parameters.
|
||||||
|
w.Header().Set("Content-Type", accept+"; charset=utf-8")
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
_, err = w.Write(output)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
}))
|
||||||
|
defer server.Close()
|
||||||
|
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL})
|
||||||
|
apiGroups, resources, err := client.ServerGroupsAndResources()
|
||||||
|
if len(test.expectedFailedGVs) > 0 {
|
||||||
|
require.Error(t, err)
|
||||||
|
expectedFailedGVs := sets.NewString(test.expectedFailedGVs...)
|
||||||
|
actualFailedGVs := sets.NewString(failedGroupVersions(err)...)
|
||||||
|
assert.True(t, expectedFailedGVs.Equal(actualFailedGVs),
|
||||||
|
"%s: Expected Failed GVs (%s), got (%s)", test.name, expectedFailedGVs, actualFailedGVs)
|
||||||
|
} else {
|
||||||
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
output, err := json.Marshal(agg)
|
// Test the expected groups are returned for the aggregated format.
|
||||||
require.NoError(t, err)
|
expectedGroupNames := sets.NewString(test.expectedGroupNames...)
|
||||||
// Content-type is "aggregated" discovery format. Add extra parameter
|
actualGroupNames := sets.NewString(groupNames(apiGroups)...)
|
||||||
// to ensure we are resilient to these extra parameters.
|
assert.True(t, expectedGroupNames.Equal(actualGroupNames),
|
||||||
w.Header().Set("Content-Type", AcceptV2Beta1+"; charset=utf-8")
|
"%s: Expected GVKs (%s), got (%s)", test.name, expectedGroupNames.List(), actualGroupNames.List())
|
||||||
w.WriteHeader(http.StatusOK)
|
// If the core V1 group is returned from /api, it should be the first group.
|
||||||
w.Write(output)
|
if expectedGroupNames.Has("") {
|
||||||
}))
|
assert.True(t, len(apiGroups) > 0)
|
||||||
defer server.Close()
|
actualFirstGroup := apiGroups[0]
|
||||||
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL})
|
assert.True(t, len(actualFirstGroup.Versions) > 0)
|
||||||
apiGroups, resources, err := client.ServerGroupsAndResources()
|
actualFirstGroupVersion := actualFirstGroup.Versions[0].GroupVersion
|
||||||
if len(test.expectedFailedGVs) > 0 {
|
assert.Equal(t, "v1", actualFirstGroupVersion)
|
||||||
require.Error(t, err)
|
}
|
||||||
expectedFailedGVs := sets.NewString(test.expectedFailedGVs...)
|
// Test the expected group/versions are returned from the aggregated discovery.
|
||||||
actualFailedGVs := sets.NewString(failedGroupVersions(err)...)
|
expectedGroupVersions := sets.NewString(test.expectedGroupVersions...)
|
||||||
assert.True(t, expectedFailedGVs.Equal(actualFailedGVs),
|
actualGroupVersions := sets.NewString(groupVersions(resources)...)
|
||||||
"%s: Expected Failed GVs (%s), got (%s)", test.name, expectedFailedGVs, actualFailedGVs)
|
assert.True(t, expectedGroupVersions.Equal(actualGroupVersions),
|
||||||
} else {
|
"%s: Expected GroupVersions(%s), got (%s)", test.name, expectedGroupVersions.List(), actualGroupVersions.List())
|
||||||
require.NoError(t, err)
|
// Test the expected GVKs are returned from the aggregated discovery.
|
||||||
|
expectedGVKs := sets.NewString(test.expectedGVKs...)
|
||||||
|
actualGVKs := sets.NewString(groupVersionKinds(resources)...)
|
||||||
|
assert.True(t, expectedGVKs.Equal(actualGVKs),
|
||||||
|
"%s: Expected GVKs (%s), got (%s)", test.name, expectedGVKs.List(), actualGVKs.List())
|
||||||
}
|
}
|
||||||
// Test the expected groups are returned for the aggregated format.
|
|
||||||
expectedGroupNames := sets.NewString(test.expectedGroupNames...)
|
|
||||||
actualGroupNames := sets.NewString(groupNames(apiGroups)...)
|
|
||||||
assert.True(t, expectedGroupNames.Equal(actualGroupNames),
|
|
||||||
"%s: Expected GVKs (%s), got (%s)", test.name, expectedGroupNames.List(), actualGroupNames.List())
|
|
||||||
// If the core V1 group is returned from /api, it should be the first group.
|
|
||||||
if expectedGroupNames.Has("") {
|
|
||||||
assert.True(t, len(apiGroups) > 0)
|
|
||||||
actualFirstGroup := apiGroups[0]
|
|
||||||
assert.True(t, len(actualFirstGroup.Versions) > 0)
|
|
||||||
actualFirstGroupVersion := actualFirstGroup.Versions[0].GroupVersion
|
|
||||||
assert.Equal(t, "v1", actualFirstGroupVersion)
|
|
||||||
}
|
|
||||||
// Test the expected group/versions are returned from the aggregated discovery.
|
|
||||||
expectedGroupVersions := sets.NewString(test.expectedGroupVersions...)
|
|
||||||
actualGroupVersions := sets.NewString(groupVersions(resources)...)
|
|
||||||
assert.True(t, expectedGroupVersions.Equal(actualGroupVersions),
|
|
||||||
"%s: Expected GroupVersions(%s), got (%s)", test.name, expectedGroupVersions.List(), actualGroupVersions.List())
|
|
||||||
// Test the expected GVKs are returned from the aggregated discovery.
|
|
||||||
expectedGVKs := sets.NewString(test.expectedGVKs...)
|
|
||||||
actualGVKs := sets.NewString(groupVersionKinds(resources)...)
|
|
||||||
assert.True(t, expectedGVKs.Equal(actualGVKs),
|
|
||||||
"%s: Expected GVKs (%s), got (%s)", test.name, expectedGVKs.List(), actualGVKs.List())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2023,8 +2527,10 @@ func TestAggregatedServerGroupsAndResourcesWithErrors(t *testing.T) {
|
|||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||||
var agg *apidiscovery.APIGroupDiscoveryList
|
var output []byte
|
||||||
|
var err error
|
||||||
var status int
|
var status int
|
||||||
|
var agg *apidiscovery.APIGroupDiscoveryList
|
||||||
switch req.URL.Path {
|
switch req.URL.Path {
|
||||||
case "/api":
|
case "/api":
|
||||||
agg = test.corev1
|
agg = test.corev1
|
||||||
@@ -2036,15 +2542,17 @@ func TestAggregatedServerGroupsAndResourcesWithErrors(t *testing.T) {
|
|||||||
w.WriteHeader(http.StatusNotFound)
|
w.WriteHeader(http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
output, err := json.Marshal(agg)
|
output, err = json.Marshal(agg)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
// Content-type is "aggregated" discovery format. Add extra parameter
|
// Content-Type is "aggregated" discovery format. Add extra parameter
|
||||||
// to ensure we are resilient to these extra parameters.
|
// to ensure we are resilient to these extra parameters.
|
||||||
w.Header().Set("Content-Type", AcceptV2Beta1+"; charset=utf-8")
|
w.Header().Set("Content-Type", AcceptV2+"; charset=utf-8")
|
||||||
w.WriteHeader(status)
|
w.WriteHeader(status)
|
||||||
w.Write(output)
|
_, err = w.Write(output)
|
||||||
|
require.NoError(t, err)
|
||||||
}))
|
}))
|
||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL})
|
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL})
|
||||||
apiGroups, resources, err := client.ServerGroupsAndResources()
|
apiGroups, resources, err := client.ServerGroupsAndResources()
|
||||||
if test.expectedErr {
|
if test.expectedErr {
|
||||||
@@ -2635,6 +3143,8 @@ func TestAggregatedServerPreferredResources(t *testing.T) {
|
|||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||||
|
var output []byte
|
||||||
|
var err error
|
||||||
var agg *apidiscovery.APIGroupDiscoveryList
|
var agg *apidiscovery.APIGroupDiscoveryList
|
||||||
switch req.URL.Path {
|
switch req.URL.Path {
|
||||||
case "/api":
|
case "/api":
|
||||||
@@ -2645,13 +3155,14 @@ func TestAggregatedServerPreferredResources(t *testing.T) {
|
|||||||
w.WriteHeader(http.StatusNotFound)
|
w.WriteHeader(http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
output, err := json.Marshal(agg)
|
output, err = json.Marshal(agg)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
// Content-type is "aggregated" discovery format. Add extra parameter
|
// Content-Type is "aggregated" discovery format. Add extra parameter
|
||||||
// to ensure we are resilient to these extra parameters.
|
// to ensure we are resilient to these extra parameters.
|
||||||
w.Header().Set("Content-Type", AcceptV2Beta1+"; charset=utf-8")
|
w.Header().Set("Content-Type", AcceptV2+"; charset=utf-8")
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
w.Write(output)
|
_, err = w.Write(output)
|
||||||
|
require.NoError(t, err)
|
||||||
}))
|
}))
|
||||||
defer server.Close()
|
defer server.Close()
|
||||||
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL})
|
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL})
|
||||||
@@ -2674,7 +3185,7 @@ func TestAggregatedServerPreferredResources(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDiscoveryContentTypeVersion(t *testing.T) {
|
func TestDiscoveryContentTypeVersion(t *testing.T) {
|
||||||
v2beta1 := schema.GroupVersionKind{Group: "apidiscovery.k8s.io", Version: "v2beta1", Kind: "APIGroupDiscoveryList"}
|
v2 := schema.GroupVersionKind{Group: "apidiscovery.k8s.io", Version: "v2", Kind: "APIGroupDiscoveryList"}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
contentType string
|
contentType string
|
||||||
gvk schema.GroupVersionKind
|
gvk schema.GroupVersionKind
|
||||||
@@ -2682,59 +3193,59 @@ func TestDiscoveryContentTypeVersion(t *testing.T) {
|
|||||||
expectErr bool
|
expectErr bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
contentType: "application/json; g=apidiscovery.k8s.io;v=v2beta1;as=APIGroupDiscoveryList",
|
contentType: "application/json; g=apidiscovery.k8s.io;v=v2;as=APIGroupDiscoveryList",
|
||||||
gvk: v2beta1,
|
gvk: v2,
|
||||||
match: true,
|
match: true,
|
||||||
expectErr: false,
|
expectErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// content-type parameters are not in correct order, but comparison ignores order.
|
// content-type parameters are not in correct order, but comparison ignores order.
|
||||||
contentType: "application/json; v=v2beta1;as=APIGroupDiscoveryList;g=apidiscovery.k8s.io",
|
contentType: "application/json; v=v2;as=APIGroupDiscoveryList;g=apidiscovery.k8s.io",
|
||||||
gvk: v2beta1,
|
gvk: v2,
|
||||||
match: true,
|
match: true,
|
||||||
expectErr: false,
|
expectErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// content-type parameters are not in correct order, but comparison ignores order.
|
// content-type parameters are not in correct order, but comparison ignores order.
|
||||||
contentType: "application/json; as=APIGroupDiscoveryList;g=apidiscovery.k8s.io;v=v2beta1",
|
contentType: "application/json; as=APIGroupDiscoveryList;g=apidiscovery.k8s.io;v=v2",
|
||||||
gvk: v2beta1,
|
gvk: v2,
|
||||||
match: true,
|
match: true,
|
||||||
expectErr: false,
|
expectErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Ignores extra parameter "charset=utf-8"
|
// Ignores extra parameter "charset=utf-8"
|
||||||
contentType: "application/json; g=apidiscovery.k8s.io;v=v2beta1;as=APIGroupDiscoveryList;charset=utf-8",
|
contentType: "application/json; g=apidiscovery.k8s.io;v=v2;as=APIGroupDiscoveryList;charset=utf-8",
|
||||||
gvk: v2beta1,
|
gvk: v2,
|
||||||
match: true,
|
match: true,
|
||||||
expectErr: false,
|
expectErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
gvk: v2beta1,
|
gvk: v2,
|
||||||
match: false,
|
match: false,
|
||||||
expectErr: false,
|
expectErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
contentType: "application/json; charset=UTF-8",
|
contentType: "application/json; charset=UTF-8",
|
||||||
gvk: v2beta1,
|
gvk: v2,
|
||||||
match: false,
|
match: false,
|
||||||
expectErr: false,
|
expectErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
contentType: "text/json",
|
contentType: "text/json",
|
||||||
gvk: v2beta1,
|
gvk: v2,
|
||||||
match: false,
|
match: false,
|
||||||
expectErr: false,
|
expectErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
contentType: "text/html",
|
contentType: "text/html",
|
||||||
gvk: v2beta1,
|
gvk: v2,
|
||||||
match: false,
|
match: false,
|
||||||
expectErr: false,
|
expectErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
contentType: "",
|
contentType: "",
|
||||||
gvk: v2beta1,
|
gvk: v2,
|
||||||
match: false,
|
match: false,
|
||||||
expectErr: true,
|
expectErr: true,
|
||||||
},
|
},
|
||||||
|
@@ -23,10 +23,15 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
apidiscoveryv2 "k8s.io/api/apidiscovery/v2"
|
||||||
apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
||||||
|
apidiscoveryv2conversion "k8s.io/apiserver/pkg/apis/apidiscovery/v2"
|
||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
"k8s.io/apiserver/pkg/authentication/user"
|
"k8s.io/apiserver/pkg/authentication/user"
|
||||||
@@ -34,11 +39,11 @@ import (
|
|||||||
discoveryendpoint "k8s.io/apiserver/pkg/endpoints/discovery/aggregated"
|
discoveryendpoint "k8s.io/apiserver/pkg/endpoints/discovery/aggregated"
|
||||||
"k8s.io/apiserver/pkg/endpoints/request"
|
"k8s.io/apiserver/pkg/endpoints/request"
|
||||||
"k8s.io/client-go/discovery"
|
"k8s.io/client-go/discovery"
|
||||||
"k8s.io/client-go/kubernetes/scheme"
|
|
||||||
"k8s.io/client-go/util/workqueue"
|
"k8s.io/client-go/util/workqueue"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
|
apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
|
||||||
"k8s.io/kube-aggregator/pkg/apis/apiregistration/v1/helper"
|
"k8s.io/kube-aggregator/pkg/apis/apiregistration/v1/helper"
|
||||||
|
"k8s.io/kube-aggregator/pkg/apiserver/scheme"
|
||||||
)
|
)
|
||||||
|
|
||||||
var APIRegistrationGroupVersion metav1.GroupVersion = metav1.GroupVersion{Group: "apiregistration.k8s.io", Version: "v1"}
|
var APIRegistrationGroupVersion metav1.GroupVersion = metav1.GroupVersion{Group: "apiregistration.k8s.io", Version: "v1"}
|
||||||
@@ -54,6 +59,12 @@ var v2Beta1GVK = schema.GroupVersionKind{
|
|||||||
Kind: "APIGroupDiscoveryList",
|
Kind: "APIGroupDiscoveryList",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var v2GVK = schema.GroupVersionKind{
|
||||||
|
Group: "apidiscovery.k8s.io",
|
||||||
|
Version: "v2",
|
||||||
|
Kind: "APIGroupDiscoveryList",
|
||||||
|
}
|
||||||
|
|
||||||
// Given a list of APIServices and proxyHandlers for contacting them,
|
// Given a list of APIServices and proxyHandlers for contacting them,
|
||||||
// DiscoveryManager caches a list of discovery documents for each server
|
// DiscoveryManager caches a list of discovery documents for each server
|
||||||
|
|
||||||
@@ -96,6 +107,9 @@ type discoveryManager struct {
|
|||||||
|
|
||||||
// Merged handler which stores all known groupversions
|
// Merged handler which stores all known groupversions
|
||||||
mergedDiscoveryHandler discoveryendpoint.ResourceManager
|
mergedDiscoveryHandler discoveryendpoint.ResourceManager
|
||||||
|
|
||||||
|
// Codecs is the serializer used for decoding aggregated apiserver responses
|
||||||
|
codecs serializer.CodecFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
// Version of Service/Spec with relevant fields for use as a cache key
|
// Version of Service/Spec with relevant fields for use as a cache key
|
||||||
@@ -129,7 +143,7 @@ func newServiceKey(service apiregistrationv1.ServiceReference) serviceKey {
|
|||||||
type cachedResult struct {
|
type cachedResult struct {
|
||||||
// Currently cached discovery document for this service
|
// Currently cached discovery document for this service
|
||||||
// Map from group name to version name to
|
// Map from group name to version name to
|
||||||
discovery map[metav1.GroupVersion]apidiscoveryv2beta1.APIVersionDiscovery
|
discovery map[metav1.GroupVersion]apidiscoveryv2.APIVersionDiscovery
|
||||||
|
|
||||||
// ETag hash of the cached discoveryDocument
|
// ETag hash of the cached discoveryDocument
|
||||||
etag string
|
etag string
|
||||||
@@ -172,11 +186,19 @@ var _ DiscoveryAggregationController = &discoveryManager{}
|
|||||||
func NewDiscoveryManager(
|
func NewDiscoveryManager(
|
||||||
target discoveryendpoint.ResourceManager,
|
target discoveryendpoint.ResourceManager,
|
||||||
) DiscoveryAggregationController {
|
) DiscoveryAggregationController {
|
||||||
|
discoveryScheme := runtime.NewScheme()
|
||||||
|
// Register conversion for apidiscovery
|
||||||
|
apidiscoveryv2.SchemeBuilder.Register(apidiscoveryv2conversion.RegisterConversions)
|
||||||
|
utilruntime.Must(apidiscoveryv2.AddToScheme(discoveryScheme))
|
||||||
|
utilruntime.Must(apidiscoveryv2beta1.AddToScheme(discoveryScheme))
|
||||||
|
codecs := serializer.NewCodecFactory(discoveryScheme)
|
||||||
|
|
||||||
return &discoveryManager{
|
return &discoveryManager{
|
||||||
mergedDiscoveryHandler: target,
|
mergedDiscoveryHandler: target,
|
||||||
apiServices: make(map[string]groupVersionInfo),
|
apiServices: make(map[string]groupVersionInfo),
|
||||||
cachedResults: make(map[serviceKey]cachedResult),
|
cachedResults: make(map[serviceKey]cachedResult),
|
||||||
dirtyAPIServiceQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "discovery-manager"),
|
dirtyAPIServiceQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "discovery-manager"),
|
||||||
|
codecs: codecs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,7 +236,7 @@ func (dm *discoveryManager) fetchFreshDiscoveryForService(gv metav1.GroupVersion
|
|||||||
Path: req.URL.Path,
|
Path: req.URL.Path,
|
||||||
IsResourceRequest: false,
|
IsResourceRequest: false,
|
||||||
}))
|
}))
|
||||||
req.Header.Add("Accept", discovery.AcceptV2Beta1)
|
req.Header.Add("Accept", discovery.AcceptV2+","+discovery.AcceptV2Beta1)
|
||||||
|
|
||||||
if exists && len(cached.etag) > 0 {
|
if exists && len(cached.etag) > 0 {
|
||||||
req.Header.Add("If-None-Match", cached.etag)
|
req.Header.Add("If-None-Match", cached.etag)
|
||||||
@@ -228,6 +250,8 @@ func (dm *discoveryManager) fetchFreshDiscoveryForService(gv metav1.GroupVersion
|
|||||||
handler.ServeHTTP(writer, req)
|
handler.ServeHTTP(writer, req)
|
||||||
|
|
||||||
isV2Beta1GVK, _ := discovery.ContentTypeIsGVK(writer.Header().Get("Content-Type"), v2Beta1GVK)
|
isV2Beta1GVK, _ := discovery.ContentTypeIsGVK(writer.Header().Get("Content-Type"), v2Beta1GVK)
|
||||||
|
isV2GVK, _ := discovery.ContentTypeIsGVK(writer.Header().Get("Content-Type"), v2GVK)
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case writer.respCode == http.StatusNotModified:
|
case writer.respCode == http.StatusNotModified:
|
||||||
// Keep old entry, update timestamp
|
// Keep old entry, update timestamp
|
||||||
@@ -242,16 +266,16 @@ func (dm *discoveryManager) fetchFreshDiscoveryForService(gv metav1.GroupVersion
|
|||||||
case writer.respCode == http.StatusServiceUnavailable:
|
case writer.respCode == http.StatusServiceUnavailable:
|
||||||
return nil, fmt.Errorf("service %s returned non-success response code: %v",
|
return nil, fmt.Errorf("service %s returned non-success response code: %v",
|
||||||
info.service.String(), writer.respCode)
|
info.service.String(), writer.respCode)
|
||||||
case writer.respCode == http.StatusOK && isV2Beta1GVK:
|
case writer.respCode == http.StatusOK && (isV2GVK || isV2Beta1GVK):
|
||||||
parsed := &apidiscoveryv2beta1.APIGroupDiscoveryList{}
|
parsed := &apidiscoveryv2.APIGroupDiscoveryList{}
|
||||||
if err := runtime.DecodeInto(scheme.Codecs.UniversalDecoder(), writer.data, parsed); err != nil {
|
if err := runtime.DecodeInto(dm.codecs.UniversalDecoder(), writer.data, parsed); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
klog.V(3).Infof("DiscoveryManager: Successfully downloaded discovery for %s", info.service.String())
|
klog.V(3).Infof("DiscoveryManager: Successfully downloaded discovery for %s", info.service.String())
|
||||||
|
|
||||||
// Convert discovery info into a map for convenient lookup later
|
// Convert discovery info into a map for convenient lookup later
|
||||||
discoMap := map[metav1.GroupVersion]apidiscoveryv2beta1.APIVersionDiscovery{}
|
discoMap := map[metav1.GroupVersion]apidiscoveryv2.APIVersionDiscovery{}
|
||||||
for _, g := range parsed.Items {
|
for _, g := range parsed.Items {
|
||||||
for _, v := range g.Versions {
|
for _, v := range g.Versions {
|
||||||
discoMap[metav1.GroupVersion{Group: g.Name, Version: v.Version}] = v
|
discoMap[metav1.GroupVersion{Group: g.Name, Version: v.Version}] = v
|
||||||
@@ -330,7 +354,7 @@ func (dm *discoveryManager) fetchFreshDiscoveryForService(gv metav1.GroupVersion
|
|||||||
}
|
}
|
||||||
klog.V(3).Infof("DiscoveryManager: Successfully downloaded legacy discovery for %s", info.service.String())
|
klog.V(3).Infof("DiscoveryManager: Successfully downloaded legacy discovery for %s", info.service.String())
|
||||||
|
|
||||||
discoMap := map[metav1.GroupVersion]apidiscoveryv2beta1.APIVersionDiscovery{
|
discoMap := map[metav1.GroupVersion]apidiscoveryv2.APIVersionDiscovery{
|
||||||
// Convert old-style APIGroupList to new information
|
// Convert old-style APIGroupList to new information
|
||||||
gv: {
|
gv: {
|
||||||
Version: gv.Version,
|
Version: gv.Version,
|
||||||
@@ -366,7 +390,7 @@ func (dm *discoveryManager) syncAPIService(apiServiceName string) error {
|
|||||||
// Lookup last cached result for this apiservice's service.
|
// Lookup last cached result for this apiservice's service.
|
||||||
cached, err := dm.fetchFreshDiscoveryForService(mgv, info)
|
cached, err := dm.fetchFreshDiscoveryForService(mgv, info)
|
||||||
|
|
||||||
var entry apidiscoveryv2beta1.APIVersionDiscovery
|
var entry apidiscoveryv2.APIVersionDiscovery
|
||||||
|
|
||||||
// Extract the APIService's specific resource information from the
|
// Extract the APIService's specific resource information from the
|
||||||
// groupversion
|
// groupversion
|
||||||
@@ -377,7 +401,7 @@ func (dm *discoveryManager) syncAPIService(apiServiceName string) error {
|
|||||||
// Just use empty GV to mark that GV exists, but no resources.
|
// Just use empty GV to mark that GV exists, but no resources.
|
||||||
// Also mark that it is stale to indicate the fetch failed
|
// Also mark that it is stale to indicate the fetch failed
|
||||||
// TODO: Maybe also stick in a status for the version the error?
|
// TODO: Maybe also stick in a status for the version the error?
|
||||||
entry = apidiscoveryv2beta1.APIVersionDiscovery{
|
entry = apidiscoveryv2.APIVersionDiscovery{
|
||||||
Version: gv.Version,
|
Version: gv.Version,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -388,7 +412,7 @@ func (dm *discoveryManager) syncAPIService(apiServiceName string) error {
|
|||||||
} else {
|
} else {
|
||||||
// Successfully fetched discovery information from the server, but
|
// Successfully fetched discovery information from the server, but
|
||||||
// the server did not include this groupversion?
|
// the server did not include this groupversion?
|
||||||
entry = apidiscoveryv2beta1.APIVersionDiscovery{
|
entry = apidiscoveryv2.APIVersionDiscovery{
|
||||||
Version: gv.Version,
|
Version: gv.Version,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -397,9 +421,9 @@ func (dm *discoveryManager) syncAPIService(apiServiceName string) error {
|
|||||||
// The entry's staleness depends upon if `fetchFreshDiscoveryForService`
|
// The entry's staleness depends upon if `fetchFreshDiscoveryForService`
|
||||||
// returned an error or not.
|
// returned an error or not.
|
||||||
if err == nil {
|
if err == nil {
|
||||||
entry.Freshness = apidiscoveryv2beta1.DiscoveryFreshnessCurrent
|
entry.Freshness = apidiscoveryv2.DiscoveryFreshnessCurrent
|
||||||
} else {
|
} else {
|
||||||
entry.Freshness = apidiscoveryv2beta1.DiscoveryFreshnessStale
|
entry.Freshness = apidiscoveryv2.DiscoveryFreshnessStale
|
||||||
}
|
}
|
||||||
|
|
||||||
dm.mergedDiscoveryHandler.AddGroupVersion(gv.Group, entry)
|
dm.mergedDiscoveryHandler.AddGroupVersion(gv.Group, entry)
|
||||||
|
@@ -33,10 +33,12 @@ import (
|
|||||||
fuzz "github.com/google/gofuzz"
|
fuzz "github.com/google/gofuzz"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
apidiscoveryv2 "k8s.io/api/apidiscovery/v2"
|
||||||
apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
apidiscoveryv2scheme "k8s.io/apiserver/pkg/apis/apidiscovery/v2"
|
||||||
"k8s.io/apiserver/pkg/endpoints"
|
"k8s.io/apiserver/pkg/endpoints"
|
||||||
"k8s.io/apiserver/pkg/endpoints/discovery"
|
"k8s.io/apiserver/pkg/endpoints/discovery"
|
||||||
discoveryendpoint "k8s.io/apiserver/pkg/endpoints/discovery/aggregated"
|
discoveryendpoint "k8s.io/apiserver/pkg/endpoints/discovery/aggregated"
|
||||||
@@ -68,31 +70,31 @@ func TestBasic(t *testing.T) {
|
|||||||
service3 := discoveryendpoint.NewResourceManager("apis")
|
service3 := discoveryendpoint.NewResourceManager("apis")
|
||||||
apiGroup1 := fuzzAPIGroups(2, 5, 25)
|
apiGroup1 := fuzzAPIGroups(2, 5, 25)
|
||||||
apiGroup2 := fuzzAPIGroups(2, 5, 50)
|
apiGroup2 := fuzzAPIGroups(2, 5, 50)
|
||||||
apiGroup3 := apidiscoveryv2beta1.APIGroupDiscoveryList{Items: []apidiscoveryv2beta1.APIGroupDiscovery{
|
apiGroup3 := apidiscoveryv2.APIGroupDiscoveryList{Items: []apidiscoveryv2.APIGroupDiscovery{
|
||||||
{
|
{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "weird.example.com"},
|
ObjectMeta: metav1.ObjectMeta{Name: "weird.example.com"},
|
||||||
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
Versions: []apidiscoveryv2.APIVersionDiscovery{
|
||||||
{
|
{
|
||||||
Version: "v1",
|
Version: "v1",
|
||||||
Freshness: "Current",
|
Freshness: "Current",
|
||||||
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
Resources: []apidiscoveryv2.APIResourceDiscovery{
|
||||||
{
|
{
|
||||||
Resource: "parent-missing-kind",
|
Resource: "parent-missing-kind",
|
||||||
Subresources: []apidiscoveryv2beta1.APISubresourceDiscovery{
|
Subresources: []apidiscoveryv2.APISubresourceDiscovery{
|
||||||
{Subresource: "subresource-missing-kind"},
|
{Subresource: "subresource-missing-kind"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Resource: "parent-empty-kind",
|
Resource: "parent-empty-kind",
|
||||||
ResponseKind: &metav1.GroupVersionKind{},
|
ResponseKind: &metav1.GroupVersionKind{},
|
||||||
Subresources: []apidiscoveryv2beta1.APISubresourceDiscovery{
|
Subresources: []apidiscoveryv2.APISubresourceDiscovery{
|
||||||
{Subresource: "subresource-empty-kind", ResponseKind: &metav1.GroupVersionKind{}},
|
{Subresource: "subresource-empty-kind", ResponseKind: &metav1.GroupVersionKind{}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Resource: "parent-with-kind",
|
Resource: "parent-with-kind",
|
||||||
ResponseKind: &metav1.GroupVersionKind{Kind: "ParentWithKind"},
|
ResponseKind: &metav1.GroupVersionKind{Kind: "ParentWithKind"},
|
||||||
Subresources: []apidiscoveryv2beta1.APISubresourceDiscovery{
|
Subresources: []apidiscoveryv2.APISubresourceDiscovery{
|
||||||
{Subresource: "subresource-with-kind", ResponseKind: &metav1.GroupVersionKind{Kind: "SubresourceWithKind"}},
|
{Subresource: "subresource-with-kind", ResponseKind: &metav1.GroupVersionKind{Kind: "SubresourceWithKind"}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -101,32 +103,32 @@ func TestBasic(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
apiGroup3WithFixup := apidiscoveryv2beta1.APIGroupDiscoveryList{Items: []apidiscoveryv2beta1.APIGroupDiscovery{
|
apiGroup3WithFixup := apidiscoveryv2.APIGroupDiscoveryList{Items: []apidiscoveryv2.APIGroupDiscovery{
|
||||||
{
|
{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "weird.example.com"},
|
ObjectMeta: metav1.ObjectMeta{Name: "weird.example.com"},
|
||||||
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
Versions: []apidiscoveryv2.APIVersionDiscovery{
|
||||||
{
|
{
|
||||||
Version: "v1",
|
Version: "v1",
|
||||||
Freshness: "Current",
|
Freshness: "Current",
|
||||||
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
Resources: []apidiscoveryv2.APIResourceDiscovery{
|
||||||
{
|
{
|
||||||
Resource: "parent-missing-kind",
|
Resource: "parent-missing-kind",
|
||||||
ResponseKind: &metav1.GroupVersionKind{}, // defaulted by aggregator
|
ResponseKind: &metav1.GroupVersionKind{}, // defaulted by aggregator
|
||||||
Subresources: []apidiscoveryv2beta1.APISubresourceDiscovery{
|
Subresources: []apidiscoveryv2.APISubresourceDiscovery{
|
||||||
{Subresource: "subresource-missing-kind", ResponseKind: &metav1.GroupVersionKind{}}, // defaulted by aggregator
|
{Subresource: "subresource-missing-kind", ResponseKind: &metav1.GroupVersionKind{}}, // defaulted by aggregator
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Resource: "parent-empty-kind",
|
Resource: "parent-empty-kind",
|
||||||
ResponseKind: &metav1.GroupVersionKind{},
|
ResponseKind: &metav1.GroupVersionKind{},
|
||||||
Subresources: []apidiscoveryv2beta1.APISubresourceDiscovery{
|
Subresources: []apidiscoveryv2.APISubresourceDiscovery{
|
||||||
{Subresource: "subresource-empty-kind", ResponseKind: &metav1.GroupVersionKind{}},
|
{Subresource: "subresource-empty-kind", ResponseKind: &metav1.GroupVersionKind{}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Resource: "parent-with-kind",
|
Resource: "parent-with-kind",
|
||||||
ResponseKind: &metav1.GroupVersionKind{Kind: "ParentWithKind"},
|
ResponseKind: &metav1.GroupVersionKind{Kind: "ParentWithKind"},
|
||||||
Subresources: []apidiscoveryv2beta1.APISubresourceDiscovery{
|
Subresources: []apidiscoveryv2.APISubresourceDiscovery{
|
||||||
{Subresource: "subresource-with-kind", ResponseKind: &metav1.GroupVersionKind{Kind: "SubresourceWithKind"}},
|
{Subresource: "subresource-with-kind", ResponseKind: &metav1.GroupVersionKind{Kind: "SubresourceWithKind"}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -217,7 +219,7 @@ func TestBasic(t *testing.T) {
|
|||||||
checkAPIGroups(t, apiGroup3WithFixup, parsed)
|
checkAPIGroups(t, apiGroup3WithFixup, parsed)
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkAPIGroups(t *testing.T, api apidiscoveryv2beta1.APIGroupDiscoveryList, response *apidiscoveryv2beta1.APIGroupDiscoveryList) {
|
func checkAPIGroups(t *testing.T, api apidiscoveryv2.APIGroupDiscoveryList, response *apidiscoveryv2.APIGroupDiscoveryList) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
if len(response.Items) < len(api.Items) {
|
if len(response.Items) < len(api.Items) {
|
||||||
t.Errorf("expected to check for at least %d groups, only have %d groups in response", len(api.Items), len(response.Items))
|
t.Errorf("expected to check for at least %d groups, only have %d groups in response", len(api.Items), len(response.Items))
|
||||||
@@ -281,10 +283,10 @@ func TestInitialRunHasAllAPIServices(t *testing.T) {
|
|||||||
t.Fatalf("unexpected status code %d", response.StatusCode)
|
t.Fatalf("unexpected status code %d", response.StatusCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
apiGroup := apidiscoveryv2beta1.APIGroupDiscoveryList{Items: []apidiscoveryv2beta1.APIGroupDiscovery{
|
apiGroup := apidiscoveryv2.APIGroupDiscoveryList{Items: []apidiscoveryv2.APIGroupDiscovery{
|
||||||
{
|
{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "stable.example.com"},
|
ObjectMeta: metav1.ObjectMeta{Name: "stable.example.com"},
|
||||||
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
Versions: []apidiscoveryv2.APIVersionDiscovery{
|
||||||
{
|
{
|
||||||
Version: "v1",
|
Version: "v1",
|
||||||
Freshness: "Stale",
|
Freshness: "Stale",
|
||||||
@@ -348,6 +350,71 @@ func TestServiceGC(t *testing.T) {
|
|||||||
require.Equal(t, 1, getCacheLen())
|
require.Equal(t, 1, getCacheLen())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestV2Beta1Skew tests that aggregated apiservers that only serve V2Beta1
|
||||||
|
// are still supported
|
||||||
|
func TestV2Beta1Skew(t *testing.T) {
|
||||||
|
apiGroup := apidiscoveryv2.APIGroupDiscoveryList{Items: []apidiscoveryv2.APIGroupDiscovery{
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "stable.example.com"},
|
||||||
|
Versions: []apidiscoveryv2.APIVersionDiscovery{
|
||||||
|
{
|
||||||
|
Version: "v1",
|
||||||
|
Freshness: "Current",
|
||||||
|
Resources: []apidiscoveryv2.APIResourceDiscovery{
|
||||||
|
{
|
||||||
|
Resource: "parent-with-kind",
|
||||||
|
ResponseKind: &metav1.GroupVersionKind{Kind: "ParentWithKind"},
|
||||||
|
Subresources: []apidiscoveryv2.APISubresourceDiscovery{
|
||||||
|
{Subresource: "subresource-with-kind", ResponseKind: &metav1.GroupVersionKind{Kind: "SubresourceWithKind"}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
|
||||||
|
aggregatedResourceManager := discoveryendpoint.NewResourceManager("apis")
|
||||||
|
|
||||||
|
aggregatedManager := newDiscoveryManager(aggregatedResourceManager)
|
||||||
|
|
||||||
|
aggregatedManager.AddAPIService(&apiregistrationv1.APIService{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "v1.stable.example.com",
|
||||||
|
},
|
||||||
|
Spec: apiregistrationv1.APIServiceSpec{
|
||||||
|
Group: "stable.example.com",
|
||||||
|
Version: "v1",
|
||||||
|
Service: &apiregistrationv1.ServiceReference{
|
||||||
|
Name: "test-service",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// Force a v2beta1 response from the aggregated apiserver
|
||||||
|
v2b := apidiscoveryv2beta1.APIGroupDiscoveryList{}
|
||||||
|
err := apidiscoveryv2scheme.Convertv2APIGroupDiscoveryListTov2beta1APIGroupDiscoveryList(&apiGroup, &v2b, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
converted, err := json.Marshal(v2b)
|
||||||
|
require.NoError(t, err)
|
||||||
|
w.Header().Set("Content-Type", "application/json;"+"g=apidiscovery.k8s.io;v=v2beta1;as=APIGroupDiscoveryList")
|
||||||
|
w.WriteHeader(200)
|
||||||
|
_, err = w.Write(converted)
|
||||||
|
require.NoError(t, err)
|
||||||
|
}))
|
||||||
|
testCtx, cancel := context.WithCancel(context.Background())
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
go aggregatedManager.Run(testCtx.Done(), nil)
|
||||||
|
require.True(t, waitForQueueComplete(testCtx.Done(), aggregatedManager))
|
||||||
|
|
||||||
|
response, _, parsed := fetchPath(aggregatedResourceManager, "")
|
||||||
|
if response.StatusCode != 200 {
|
||||||
|
t.Fatalf("unexpected status code %d", response.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
checkAPIGroups(t, apiGroup, parsed)
|
||||||
|
}
|
||||||
|
|
||||||
// Test that a handler associated with an APIService gets pinged after the
|
// Test that a handler associated with an APIService gets pinged after the
|
||||||
// APIService has been marked as dirty
|
// APIService has been marked as dirty
|
||||||
func TestDirty(t *testing.T) {
|
func TestDirty(t *testing.T) {
|
||||||
@@ -642,34 +709,34 @@ func TestLegacyFallbackNoCache(t *testing.T) {
|
|||||||
// includes the legacy resources
|
// includes the legacy resources
|
||||||
_, _, doc := fetchPath(aggregatedResourceManager, "")
|
_, _, doc := fetchPath(aggregatedResourceManager, "")
|
||||||
|
|
||||||
mustConvert := func(r []metav1.APIResource) []apidiscoveryv2beta1.APIResourceDiscovery {
|
mustConvert := func(r []metav1.APIResource) []apidiscoveryv2.APIResourceDiscovery {
|
||||||
converted, err := endpoints.ConvertGroupVersionIntoToDiscovery(r)
|
converted, err := endpoints.ConvertGroupVersionIntoToDiscovery(r)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
return converted
|
return converted
|
||||||
}
|
}
|
||||||
expectAggregatedDiscovery := []apidiscoveryv2beta1.APIGroupDiscovery{{
|
expectAggregatedDiscovery := []apidiscoveryv2.APIGroupDiscovery{{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "stable.example.com",
|
Name: "stable.example.com",
|
||||||
},
|
},
|
||||||
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
Versions: []apidiscoveryv2.APIVersionDiscovery{
|
||||||
{
|
{
|
||||||
Version: "v1",
|
Version: "v1",
|
||||||
Resources: mustConvert([]metav1.APIResource{resources["v1"]}),
|
Resources: mustConvert([]metav1.APIResource{resources["v1"]}),
|
||||||
Freshness: apidiscoveryv2beta1.DiscoveryFreshnessCurrent,
|
Freshness: apidiscoveryv2.DiscoveryFreshnessCurrent,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Version: "v1beta1",
|
Version: "v1beta1",
|
||||||
Resources: mustConvert([]metav1.APIResource{resources["v1beta1"]}),
|
Resources: mustConvert([]metav1.APIResource{resources["v1beta1"]}),
|
||||||
Freshness: apidiscoveryv2beta1.DiscoveryFreshnessCurrent,
|
Freshness: apidiscoveryv2.DiscoveryFreshnessCurrent,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Version: "v2alpha1",
|
Version: "v2alpha1",
|
||||||
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
Resources: []apidiscoveryv2.APIResourceDiscovery{
|
||||||
{
|
{
|
||||||
Resource: "parent-without-kind",
|
Resource: "parent-without-kind",
|
||||||
ResponseKind: &metav1.GroupVersionKind{}, // defaulted
|
ResponseKind: &metav1.GroupVersionKind{}, // defaulted
|
||||||
Scope: "Cluster",
|
Scope: "Cluster",
|
||||||
Subresources: []apidiscoveryv2beta1.APISubresourceDiscovery{
|
Subresources: []apidiscoveryv2.APISubresourceDiscovery{
|
||||||
{
|
{
|
||||||
Subresource: "subresource",
|
Subresource: "subresource",
|
||||||
ResponseKind: &metav1.GroupVersionKind{Kind: "Subresource"},
|
ResponseKind: &metav1.GroupVersionKind{Kind: "Subresource"},
|
||||||
@@ -684,7 +751,7 @@ func TestLegacyFallbackNoCache(t *testing.T) {
|
|||||||
Resource: "missing-parent",
|
Resource: "missing-parent",
|
||||||
ResponseKind: &metav1.GroupVersionKind{}, // defaulted
|
ResponseKind: &metav1.GroupVersionKind{}, // defaulted
|
||||||
Scope: "Cluster",
|
Scope: "Cluster",
|
||||||
Subresources: []apidiscoveryv2beta1.APISubresourceDiscovery{
|
Subresources: []apidiscoveryv2.APISubresourceDiscovery{
|
||||||
{
|
{
|
||||||
Subresource: "subresource-without-parent",
|
Subresource: "subresource-without-parent",
|
||||||
ResponseKind: &metav1.GroupVersionKind{Kind: "SubresourceWithoutParent"},
|
ResponseKind: &metav1.GroupVersionKind{Kind: "SubresourceWithoutParent"},
|
||||||
@@ -692,12 +759,12 @@ func TestLegacyFallbackNoCache(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Freshness: apidiscoveryv2beta1.DiscoveryFreshnessCurrent,
|
Freshness: apidiscoveryv2.DiscoveryFreshnessCurrent,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Version: "v1alpha1",
|
Version: "v1alpha1",
|
||||||
Resources: mustConvert([]metav1.APIResource{resources["v1alpha1"]}),
|
Resources: mustConvert([]metav1.APIResource{resources["v1alpha1"]}),
|
||||||
Freshness: apidiscoveryv2beta1.DiscoveryFreshnessCurrent,
|
Freshness: apidiscoveryv2.DiscoveryFreshnessCurrent,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
@@ -782,16 +849,16 @@ func testLegacyFallbackWithCustomRootHandler(t *testing.T, rootHandlerFn func(ht
|
|||||||
|
|
||||||
converted, err := endpoints.ConvertGroupVersionIntoToDiscovery([]metav1.APIResource{resource})
|
converted, err := endpoints.ConvertGroupVersionIntoToDiscovery([]metav1.APIResource{resource})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, []apidiscoveryv2beta1.APIGroupDiscovery{
|
require.Equal(t, []apidiscoveryv2.APIGroupDiscovery{
|
||||||
{
|
{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: resource.Group,
|
Name: resource.Group,
|
||||||
},
|
},
|
||||||
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
Versions: []apidiscoveryv2.APIVersionDiscovery{
|
||||||
{
|
{
|
||||||
Version: resource.Version,
|
Version: resource.Version,
|
||||||
Resources: converted,
|
Resources: converted,
|
||||||
Freshness: apidiscoveryv2beta1.DiscoveryFreshnessCurrent,
|
Freshness: apidiscoveryv2.DiscoveryFreshnessCurrent,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -859,15 +926,15 @@ func TestAPIServiceStale(t *testing.T) {
|
|||||||
// At this point external services have synced. Check if discovery document
|
// At this point external services have synced. Check if discovery document
|
||||||
// lists the APIService group version as Stale.
|
// lists the APIService group version as Stale.
|
||||||
_, _, doc := fetchPath(aggregatedResourceManager, "")
|
_, _, doc := fetchPath(aggregatedResourceManager, "")
|
||||||
require.Equal(t, []apidiscoveryv2beta1.APIGroupDiscovery{
|
require.Equal(t, []apidiscoveryv2.APIGroupDiscovery{
|
||||||
{
|
{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "stable.example.com",
|
Name: "stable.example.com",
|
||||||
},
|
},
|
||||||
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
Versions: []apidiscoveryv2.APIVersionDiscovery{
|
||||||
{
|
{
|
||||||
Version: "v1",
|
Version: "v1",
|
||||||
Freshness: apidiscoveryv2beta1.DiscoveryFreshnessStale,
|
Freshness: apidiscoveryv2.DiscoveryFreshnessStale,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -934,16 +1001,16 @@ func TestNotModified(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// copied from staging/src/k8s.io/apiserver/pkg/endpoints/discovery/v2/handler_test.go
|
// copied from staging/src/k8s.io/apiserver/pkg/endpoints/discovery/v2/handler_test.go
|
||||||
func fuzzAPIGroups(atLeastNumGroups, maxNumGroups int, seed int64) apidiscoveryv2beta1.APIGroupDiscoveryList {
|
func fuzzAPIGroups(atLeastNumGroups, maxNumGroups int, seed int64) apidiscoveryv2.APIGroupDiscoveryList {
|
||||||
fuzzer := fuzz.NewWithSeed(seed)
|
fuzzer := fuzz.NewWithSeed(seed)
|
||||||
fuzzer.NumElements(atLeastNumGroups, maxNumGroups)
|
fuzzer.NumElements(atLeastNumGroups, maxNumGroups)
|
||||||
fuzzer.NilChance(0)
|
fuzzer.NilChance(0)
|
||||||
fuzzer.Funcs(func(o *apidiscoveryv2beta1.APIGroupDiscovery, c fuzz.Continue) {
|
fuzzer.Funcs(func(o *apidiscoveryv2.APIGroupDiscovery, c fuzz.Continue) {
|
||||||
c.FuzzNoCustom(o)
|
c.FuzzNoCustom(o)
|
||||||
|
|
||||||
// The ResourceManager will just not serve the group if its versions
|
// The ResourceManager will just not serve the group if its versions
|
||||||
// list is empty
|
// list is empty
|
||||||
atLeastOne := apidiscoveryv2beta1.APIVersionDiscovery{}
|
atLeastOne := apidiscoveryv2.APIVersionDiscovery{}
|
||||||
c.Fuzz(&atLeastOne)
|
c.Fuzz(&atLeastOne)
|
||||||
o.Versions = append(o.Versions, atLeastOne)
|
o.Versions = append(o.Versions, atLeastOne)
|
||||||
|
|
||||||
@@ -958,10 +1025,10 @@ func fuzzAPIGroups(atLeastNumGroups, maxNumGroups int, seed int64) apidiscoveryv
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
var apis []apidiscoveryv2beta1.APIGroupDiscovery
|
var apis []apidiscoveryv2.APIGroupDiscovery
|
||||||
fuzzer.Fuzz(&apis)
|
fuzzer.Fuzz(&apis)
|
||||||
|
|
||||||
return apidiscoveryv2beta1.APIGroupDiscoveryList{
|
return apidiscoveryv2.APIGroupDiscoveryList{
|
||||||
TypeMeta: metav1.TypeMeta{
|
TypeMeta: metav1.TypeMeta{
|
||||||
Kind: "APIGroupDiscoveryList",
|
Kind: "APIGroupDiscoveryList",
|
||||||
APIVersion: "v1",
|
APIVersion: "v1",
|
||||||
@@ -972,13 +1039,13 @@ func fuzzAPIGroups(atLeastNumGroups, maxNumGroups int, seed int64) apidiscoveryv
|
|||||||
}
|
}
|
||||||
|
|
||||||
// copied from staging/src/k8s.io/apiserver/pkg/endpoints/discovery/v2/handler_test.go
|
// copied from staging/src/k8s.io/apiserver/pkg/endpoints/discovery/v2/handler_test.go
|
||||||
func fetchPath(handler http.Handler, etag string) (*http.Response, []byte, *apidiscoveryv2beta1.APIGroupDiscoveryList) {
|
func fetchPath(handler http.Handler, etag string) (*http.Response, []byte, *apidiscoveryv2.APIGroupDiscoveryList) {
|
||||||
// Expect json-formatted apis group list
|
// Expect json-formatted apis group list
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
req := httptest.NewRequest("GET", "/apis", nil)
|
req := httptest.NewRequest("GET", "/apis", nil)
|
||||||
|
|
||||||
// Ask for JSON response
|
// Ask for JSON response
|
||||||
req.Header.Set("Accept", runtime.ContentTypeJSON+";g=apidiscovery.k8s.io;v=v2beta1;as=APIGroupDiscoveryList")
|
req.Header.Set("Accept", runtime.ContentTypeJSON+";g=apidiscovery.k8s.io;v=v2;as=APIGroupDiscoveryList,"+runtime.ContentTypeJSON+";g=apidiscovery.k8s.io;v=v2beta1;as=APIGroupDiscoveryList")
|
||||||
|
|
||||||
if etag != "" {
|
if etag != "" {
|
||||||
// Quote provided etag if unquoted
|
// Quote provided etag if unquoted
|
||||||
@@ -992,9 +1059,9 @@ func fetchPath(handler http.Handler, etag string) (*http.Response, []byte, *apid
|
|||||||
handler.ServeHTTP(w, req)
|
handler.ServeHTTP(w, req)
|
||||||
|
|
||||||
bytes := w.Body.Bytes()
|
bytes := w.Body.Bytes()
|
||||||
var decoded *apidiscoveryv2beta1.APIGroupDiscoveryList
|
var decoded *apidiscoveryv2.APIGroupDiscoveryList
|
||||||
if len(bytes) > 0 {
|
if len(bytes) > 0 {
|
||||||
decoded = &apidiscoveryv2beta1.APIGroupDiscoveryList{}
|
decoded = &apidiscoveryv2.APIGroupDiscoveryList{}
|
||||||
runtime.DecodeInto(scheme.Codecs.UniversalDecoder(), bytes, decoded)
|
runtime.DecodeInto(scheme.Codecs.UniversalDecoder(), bytes, decoded)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -22,7 +22,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
apidiscoveryv2 "k8s.io/api/apidiscovery/v2"
|
||||||
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
apiextensionclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
apiextensionclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||||
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
"k8s.io/apiextensions-apiserver/test/integration/fixtures"
|
||||||
@@ -143,7 +143,7 @@ var _ = SIGDescribe("AggregatedDiscovery", func() {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const aggregatedAccept = "application/json;g=apidiscovery.k8s.io;v=v2beta1;as=APIGroupDiscoveryList"
|
const aggregatedAccept = "application/json;g=apidiscovery.k8s.io;v=v2;as=APIGroupDiscoveryList"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Release : v1.30
|
Release : v1.30
|
||||||
@@ -156,7 +156,7 @@ var _ = SIGDescribe("AggregatedDiscovery", func() {
|
|||||||
framework.Failf("Failed to get raw aggregated discovery document")
|
framework.Failf("Failed to get raw aggregated discovery document")
|
||||||
}
|
}
|
||||||
|
|
||||||
groupList := apidiscoveryv2beta1.APIGroupDiscoveryList{}
|
groupList := apidiscoveryv2.APIGroupDiscoveryList{}
|
||||||
err = json.Unmarshal(d, &groupList)
|
err = json.Unmarshal(d, &groupList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
framework.Failf("Failed to parse discovery: %v", err)
|
framework.Failf("Failed to parse discovery: %v", err)
|
||||||
@@ -174,7 +174,7 @@ var _ = SIGDescribe("AggregatedDiscovery", func() {
|
|||||||
framework.Failf("Failed to get raw aggregated discovery document")
|
framework.Failf("Failed to get raw aggregated discovery document")
|
||||||
}
|
}
|
||||||
|
|
||||||
groupListLegacy := apidiscoveryv2beta1.APIGroupDiscoveryList{}
|
groupListLegacy := apidiscoveryv2.APIGroupDiscoveryList{}
|
||||||
err = json.Unmarshal(d2, &groupListLegacy)
|
err = json.Unmarshal(d2, &groupListLegacy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
framework.Failf("Failed to parse discovery: %v", err)
|
framework.Failf("Failed to parse discovery: %v", err)
|
||||||
@@ -238,7 +238,7 @@ var _ = SIGDescribe("AggregatedDiscovery", func() {
|
|||||||
framework.Failf("Failed to get raw aggregated discovery document")
|
framework.Failf("Failed to get raw aggregated discovery document")
|
||||||
}
|
}
|
||||||
|
|
||||||
groupList := apidiscoveryv2beta1.APIGroupDiscoveryList{}
|
groupList := apidiscoveryv2.APIGroupDiscoveryList{}
|
||||||
err = json.Unmarshal(d, &groupList)
|
err = json.Unmarshal(d, &groupList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
framework.Failf("Failed to parse discovery: %v", err)
|
framework.Failf("Failed to parse discovery: %v", err)
|
||||||
@@ -392,7 +392,7 @@ func isGVPresent(gvs *metav1.APIGroupList, gv schema.GroupVersion) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func isGVRPresentAPIDiscovery(apidiscovery apidiscoveryv2beta1.APIGroupDiscoveryList, gvr schema.GroupVersionResource) bool {
|
func isGVRPresentAPIDiscovery(apidiscovery apidiscoveryv2.APIGroupDiscoveryList, gvr schema.GroupVersionResource) bool {
|
||||||
for _, group := range apidiscovery.Items {
|
for _, group := range apidiscovery.Items {
|
||||||
if gvr.Group == group.Name {
|
if gvr.Group == group.Name {
|
||||||
for _, version := range group.Versions {
|
for _, version := range group.Versions {
|
||||||
|
@@ -28,7 +28,7 @@ import (
|
|||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
apidiscoveryv2 "k8s.io/api/apidiscovery/v2"
|
||||||
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
apiextensions "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
apiextensions "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||||
"k8s.io/apimachinery/pkg/api/meta"
|
"k8s.io/apimachinery/pkg/api/meta"
|
||||||
@@ -79,14 +79,14 @@ var (
|
|||||||
codecs = runtimeserializer.NewCodecFactory(scheme)
|
codecs = runtimeserializer.NewCodecFactory(scheme)
|
||||||
serialize runtime.NegotiatedSerializer
|
serialize runtime.NegotiatedSerializer
|
||||||
|
|
||||||
basicTestGroup = apidiscoveryv2beta1.APIGroupDiscovery{
|
basicTestGroup = apidiscoveryv2.APIGroupDiscovery{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "stable.example.com",
|
Name: "stable.example.com",
|
||||||
},
|
},
|
||||||
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
Versions: []apidiscoveryv2.APIVersionDiscovery{
|
||||||
{
|
{
|
||||||
Version: "v1",
|
Version: "v1",
|
||||||
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
Resources: []apidiscoveryv2.APIResourceDiscovery{
|
||||||
{
|
{
|
||||||
Resource: "jobs",
|
Resource: "jobs",
|
||||||
Verbs: []string{"create", "list", "watch", "delete"},
|
Verbs: []string{"create", "list", "watch", "delete"},
|
||||||
@@ -94,19 +94,19 @@ var (
|
|||||||
Categories: []string{"all"},
|
Categories: []string{"all"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Freshness: apidiscoveryv2beta1.DiscoveryFreshnessCurrent,
|
Freshness: apidiscoveryv2.DiscoveryFreshnessCurrent,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
basicTestGroupWithFixup = apidiscoveryv2beta1.APIGroupDiscovery{
|
basicTestGroupWithFixup = apidiscoveryv2.APIGroupDiscovery{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "stable.example.com",
|
Name: "stable.example.com",
|
||||||
},
|
},
|
||||||
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
Versions: []apidiscoveryv2.APIVersionDiscovery{
|
||||||
{
|
{
|
||||||
Version: "v1",
|
Version: "v1",
|
||||||
Resources: []apidiscoveryv2beta1.APIResourceDiscovery{
|
Resources: []apidiscoveryv2.APIResourceDiscovery{
|
||||||
{
|
{
|
||||||
Resource: "jobs",
|
Resource: "jobs",
|
||||||
Verbs: []string{"create", "list", "watch", "delete"},
|
Verbs: []string{"create", "list", "watch", "delete"},
|
||||||
@@ -116,19 +116,19 @@ var (
|
|||||||
ResponseKind: &metav1.GroupVersionKind{},
|
ResponseKind: &metav1.GroupVersionKind{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Freshness: apidiscoveryv2beta1.DiscoveryFreshnessCurrent,
|
Freshness: apidiscoveryv2.DiscoveryFreshnessCurrent,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
basicTestGroupStale = apidiscoveryv2beta1.APIGroupDiscovery{
|
basicTestGroupStale = apidiscoveryv2.APIGroupDiscovery{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "stable.example.com",
|
Name: "stable.example.com",
|
||||||
},
|
},
|
||||||
Versions: []apidiscoveryv2beta1.APIVersionDiscovery{
|
Versions: []apidiscoveryv2.APIVersionDiscovery{
|
||||||
{
|
{
|
||||||
Version: "v1",
|
Version: "v1",
|
||||||
Freshness: apidiscoveryv2beta1.DiscoveryFreshnessStale,
|
Freshness: apidiscoveryv2.DiscoveryFreshnessStale,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -193,7 +193,7 @@ func TestReadinessAggregatedAPIServiceDiscovery(t *testing.T) {
|
|||||||
|
|
||||||
// Create a resource manager whichs serves our GroupVersion
|
// Create a resource manager whichs serves our GroupVersion
|
||||||
resourceManager := discoveryendpoint.NewResourceManager("apis")
|
resourceManager := discoveryendpoint.NewResourceManager("apis")
|
||||||
resourceManager.SetGroups([]apidiscoveryv2beta1.APIGroupDiscovery{basicTestGroup})
|
resourceManager.SetGroups([]apidiscoveryv2.APIGroupDiscovery{basicTestGroup})
|
||||||
|
|
||||||
apiServiceWaitCh := make(chan struct{})
|
apiServiceWaitCh := make(chan struct{})
|
||||||
|
|
||||||
@@ -290,7 +290,7 @@ func TestAggregatedAPIServiceDiscovery(t *testing.T) {
|
|||||||
|
|
||||||
// Create a resource manager whichs serves our GroupVersion
|
// Create a resource manager whichs serves our GroupVersion
|
||||||
resourceManager := discoveryendpoint.NewResourceManager("apis")
|
resourceManager := discoveryendpoint.NewResourceManager("apis")
|
||||||
resourceManager.SetGroups([]apidiscoveryv2beta1.APIGroupDiscovery{basicTestGroup})
|
resourceManager.SetGroups([]apidiscoveryv2.APIGroupDiscovery{basicTestGroup})
|
||||||
|
|
||||||
// Install our ResourceManager as an Aggregated APIService to the
|
// Install our ResourceManager as an Aggregated APIService to the
|
||||||
// test server
|
// test server
|
||||||
@@ -371,7 +371,7 @@ func runTestCases(t *testing.T, cases []testCase) {
|
|||||||
})
|
})
|
||||||
require.NoError(t, err, "v1 discovery must reset between tests: "+diff)
|
require.NoError(t, err, "v1 discovery must reset between tests: "+diff)
|
||||||
|
|
||||||
err = WaitForResultWithCondition(ctx, client, func(result apidiscoveryv2beta1.APIGroupDiscoveryList) bool {
|
err = WaitForResultWithCondition(ctx, client, func(result apidiscoveryv2.APIGroupDiscoveryList) bool {
|
||||||
diff = cmp.Diff(originalV2, result)
|
diff = cmp.Diff(originalV2, result)
|
||||||
return reflect.DeepEqual(result, originalV2)
|
return reflect.DeepEqual(result, originalV2)
|
||||||
})
|
})
|
||||||
@@ -393,6 +393,7 @@ func TestCRD(t *testing.T) {
|
|||||||
applyCRD(makeCRDSpec(stableGroup, "Foo", false, []string{"v1", "v1alpha1", "v1beta1", "v2"})),
|
applyCRD(makeCRDSpec(stableGroup, "Foo", false, []string{"v1", "v1alpha1", "v1beta1", "v2"})),
|
||||||
waitForGroupVersionsV1([]metav1.GroupVersion{stableV1, stableV1alpha1, stableV1beta1, stableV2}),
|
waitForGroupVersionsV1([]metav1.GroupVersion{stableV1, stableV1alpha1, stableV1beta1, stableV2}),
|
||||||
waitForGroupVersionsV2([]metav1.GroupVersion{stableV1, stableV1alpha1, stableV1beta1, stableV2}),
|
waitForGroupVersionsV2([]metav1.GroupVersion{stableV1, stableV1alpha1, stableV1beta1, stableV2}),
|
||||||
|
waitForGroupVersionsV2Beta1([]metav1.GroupVersion{stableV1, stableV1alpha1, stableV1beta1, stableV2}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -402,6 +403,7 @@ func TestCRD(t *testing.T) {
|
|||||||
applyCRD(makeCRDSpec(stableGroup, "Foo", false, []string{"v1", "v1alpha1", "v1beta1", "v2"})),
|
applyCRD(makeCRDSpec(stableGroup, "Foo", false, []string{"v1", "v1alpha1", "v1beta1", "v2"})),
|
||||||
waitForGroupVersionsV1([]metav1.GroupVersion{stableV1, stableV1alpha1, stableV1beta1, stableV2}),
|
waitForGroupVersionsV1([]metav1.GroupVersion{stableV1, stableV1alpha1, stableV1beta1, stableV2}),
|
||||||
waitForGroupVersionsV2([]metav1.GroupVersion{stableV1, stableV1alpha1, stableV1beta1, stableV2}),
|
waitForGroupVersionsV2([]metav1.GroupVersion{stableV1, stableV1alpha1, stableV1beta1, stableV2}),
|
||||||
|
waitForGroupVersionsV2Beta1([]metav1.GroupVersion{stableV1, stableV1alpha1, stableV1beta1, stableV2}),
|
||||||
deleteObject{
|
deleteObject{
|
||||||
GroupVersionResource: metav1.GroupVersionResource(apiextensionsv1.SchemeGroupVersion.WithResource("customresourcedefinitions")),
|
GroupVersionResource: metav1.GroupVersionResource(apiextensionsv1.SchemeGroupVersion.WithResource("customresourcedefinitions")),
|
||||||
Name: "foos.stable.example.com",
|
Name: "foos.stable.example.com",
|
||||||
@@ -469,6 +471,7 @@ func TestCRD(t *testing.T) {
|
|||||||
// Wait for GV to appear in both discovery documents
|
// Wait for GV to appear in both discovery documents
|
||||||
waitForGroupVersionsV1([]metav1.GroupVersion{stableV2, stableV1alpha1}),
|
waitForGroupVersionsV1([]metav1.GroupVersion{stableV2, stableV1alpha1}),
|
||||||
waitForGroupVersionsV2([]metav1.GroupVersion{stableV2, stableV1alpha1}),
|
waitForGroupVersionsV2([]metav1.GroupVersion{stableV2, stableV1alpha1}),
|
||||||
|
waitForGroupVersionsV2Beta1([]metav1.GroupVersion{stableV2, stableV1alpha1}),
|
||||||
|
|
||||||
applyAPIService(
|
applyAPIService(
|
||||||
apiregistrationv1.APIServiceSpec{
|
apiregistrationv1.APIServiceSpec{
|
||||||
@@ -487,11 +490,13 @@ func TestCRD(t *testing.T) {
|
|||||||
// We should now have stable v1 available
|
// We should now have stable v1 available
|
||||||
waitForGroupVersionsV1([]metav1.GroupVersion{stableV1}),
|
waitForGroupVersionsV1([]metav1.GroupVersion{stableV1}),
|
||||||
waitForGroupVersionsV2([]metav1.GroupVersion{stableV1}),
|
waitForGroupVersionsV2([]metav1.GroupVersion{stableV1}),
|
||||||
|
waitForGroupVersionsV2Beta1([]metav1.GroupVersion{stableV1}),
|
||||||
|
|
||||||
// The CRD group-versions not served by the aggregated
|
// The CRD group-versions not served by the aggregated
|
||||||
// apiservice should still be availablee
|
// apiservice should still be availablee
|
||||||
waitForGroupVersionsV1([]metav1.GroupVersion{stableV2, stableV1alpha1}),
|
waitForGroupVersionsV1([]metav1.GroupVersion{stableV2, stableV1alpha1}),
|
||||||
waitForGroupVersionsV2([]metav1.GroupVersion{stableV2, stableV1alpha1}),
|
waitForGroupVersionsV2([]metav1.GroupVersion{stableV2, stableV1alpha1}),
|
||||||
|
waitForGroupVersionsV2Beta1([]metav1.GroupVersion{stableV2, stableV1alpha1}),
|
||||||
|
|
||||||
// Remove API service. Show we have switched to CRD
|
// Remove API service. Show we have switched to CRD
|
||||||
deleteObject{
|
deleteObject{
|
||||||
@@ -502,9 +507,11 @@ func TestCRD(t *testing.T) {
|
|||||||
// Show that we still have stable v1 since it is in the CRD
|
// Show that we still have stable v1 since it is in the CRD
|
||||||
waitForGroupVersionsV1([]metav1.GroupVersion{stableV2, stableV1alpha1}),
|
waitForGroupVersionsV1([]metav1.GroupVersion{stableV2, stableV1alpha1}),
|
||||||
waitForGroupVersionsV2([]metav1.GroupVersion{stableV2, stableV1alpha1}),
|
waitForGroupVersionsV2([]metav1.GroupVersion{stableV2, stableV1alpha1}),
|
||||||
|
waitForGroupVersionsV2Beta1([]metav1.GroupVersion{stableV2, stableV1alpha1}),
|
||||||
|
|
||||||
waitForAbsentGroupVersionsV1([]metav1.GroupVersion{stableV1}),
|
waitForAbsentGroupVersionsV1([]metav1.GroupVersion{stableV1}),
|
||||||
waitForAbsentGroupVersionsV2([]metav1.GroupVersion{stableV1}),
|
waitForAbsentGroupVersionsV2([]metav1.GroupVersion{stableV1}),
|
||||||
|
waitForAbsentGroupVersionsV2Beta1([]metav1.GroupVersion{stableV1}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -635,9 +642,9 @@ func TestFreshness(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch entry.Freshness {
|
switch entry.Freshness {
|
||||||
case apidiscoveryv2beta1.DiscoveryFreshnessCurrent:
|
case apidiscoveryv2.DiscoveryFreshnessCurrent:
|
||||||
// Skip
|
// Skip
|
||||||
case apidiscoveryv2beta1.DiscoveryFreshnessStale:
|
case apidiscoveryv2.DiscoveryFreshnessStale:
|
||||||
staleGVs = append(staleGVs, targetGv)
|
staleGVs = append(staleGVs, targetGv)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unrecognized freshness '%v' on gv '%v'", entry.Freshness, targetGv)
|
return fmt.Errorf("unrecognized freshness '%v' on gv '%v'", entry.Freshness, targetGv)
|
||||||
@@ -704,7 +711,7 @@ func TestFreshness(t *testing.T) {
|
|||||||
|
|
||||||
// Shows a group for which multiple APIServices specify a GroupPriorityMinimum,
|
// Shows a group for which multiple APIServices specify a GroupPriorityMinimum,
|
||||||
// it is sorted the same in both versions of discovery
|
// it is sorted the same in both versions of discovery
|
||||||
func TestGroupPriorty(t *testing.T) {
|
func TestGroupPriority(t *testing.T) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.AggregatedDiscoveryEndpoint, true)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.AggregatedDiscoveryEndpoint, true)()
|
||||||
|
|
||||||
makeApiServiceSpec := func(gv metav1.GroupVersion, groupPriorityMin, versionPriority int) apiregistrationv1.APIServiceSpec {
|
makeApiServiceSpec := func(gv metav1.GroupVersion, groupPriorityMin, versionPriority int) apiregistrationv1.APIServiceSpec {
|
||||||
|
@@ -36,6 +36,7 @@ import (
|
|||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
aggregator "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset"
|
aggregator "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset"
|
||||||
|
|
||||||
|
apidiscoveryv2 "k8s.io/api/apidiscovery/v2"
|
||||||
apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
apidiscoveryv2beta1 "k8s.io/api/apidiscovery/v2beta1"
|
||||||
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
@@ -43,7 +44,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const acceptV1JSON = "application/json"
|
const acceptV1JSON = "application/json"
|
||||||
const acceptV2JSON = "application/json;g=apidiscovery.k8s.io;v=v2beta1;as=APIGroupDiscoveryList"
|
const acceptV2Beta1JSON = "application/json;g=apidiscovery.k8s.io;v=v2beta1;as=APIGroupDiscoveryList"
|
||||||
|
const acceptV2JSON = "application/json;g=apidiscovery.k8s.io;v=v2;as=APIGroupDiscoveryList"
|
||||||
|
|
||||||
const maxTimeout = 10 * time.Second
|
const maxTimeout = 10 * time.Second
|
||||||
|
|
||||||
@@ -93,9 +95,15 @@ type waitForAbsentGroupVersionsV1 []metav1.GroupVersion
|
|||||||
// Wait for groupversions to appear in v2 discovery
|
// Wait for groupversions to appear in v2 discovery
|
||||||
type waitForGroupVersionsV2 []metav1.GroupVersion
|
type waitForGroupVersionsV2 []metav1.GroupVersion
|
||||||
|
|
||||||
|
// Wait for groupversions to appear in v2beta1 discovery
|
||||||
|
type waitForGroupVersionsV2Beta1 []metav1.GroupVersion
|
||||||
|
|
||||||
// Wait for groupversions to disappear from v2 discovery
|
// Wait for groupversions to disappear from v2 discovery
|
||||||
type waitForAbsentGroupVersionsV2 []metav1.GroupVersion
|
type waitForAbsentGroupVersionsV2 []metav1.GroupVersion
|
||||||
|
|
||||||
|
// Wait for groupversions to disappear from v2beta1 discovery
|
||||||
|
type waitForAbsentGroupVersionsV2Beta1 []metav1.GroupVersion
|
||||||
|
|
||||||
type waitForStaleGroupVersionsV2 []metav1.GroupVersion
|
type waitForStaleGroupVersionsV2 []metav1.GroupVersion
|
||||||
type waitForFreshGroupVersionsV2 []metav1.GroupVersion
|
type waitForFreshGroupVersionsV2 []metav1.GroupVersion
|
||||||
|
|
||||||
@@ -144,10 +152,11 @@ func (a applyAPIService) Cleanup(ctx context.Context, client testClient) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = wait.PollWithContext(
|
err = wait.PollUntilContextTimeout(
|
||||||
ctx,
|
ctx,
|
||||||
250*time.Millisecond,
|
250*time.Millisecond,
|
||||||
maxTimeout,
|
maxTimeout,
|
||||||
|
true,
|
||||||
func(ctx context.Context) (done bool, err error) {
|
func(ctx context.Context) (done bool, err error) {
|
||||||
_, err = client.ApiregistrationV1().APIServices().Get(ctx, name, metav1.GetOptions{})
|
_, err = client.ApiregistrationV1().APIServices().Get(ctx, name, metav1.GetOptions{})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -212,10 +221,11 @@ func (a applyCRD) Cleanup(ctx context.Context, client testClient) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = wait.PollWithContext(
|
err = wait.PollUntilContextTimeout(
|
||||||
ctx,
|
ctx,
|
||||||
250*time.Millisecond,
|
250*time.Millisecond,
|
||||||
maxTimeout,
|
maxTimeout,
|
||||||
|
true,
|
||||||
func(ctx context.Context) (done bool, err error) {
|
func(ctx context.Context) (done bool, err error) {
|
||||||
_, err = client.ApiextensionsV1().CustomResourceDefinitions().Get(ctx, name, metav1.GetOptions{})
|
_, err = client.ApiextensionsV1().CustomResourceDefinitions().Get(ctx, name, metav1.GetOptions{})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -248,9 +258,9 @@ func (d deleteObject) Do(ctx context.Context, client testClient) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w waitForStaleGroupVersionsV2) Do(ctx context.Context, client testClient) error {
|
func (w waitForStaleGroupVersionsV2) Do(ctx context.Context, client testClient) error {
|
||||||
err := WaitForResultWithCondition(ctx, client, func(result apidiscoveryv2beta1.APIGroupDiscoveryList) bool {
|
err := WaitForResultWithCondition(ctx, client, func(result apidiscoveryv2.APIGroupDiscoveryList) bool {
|
||||||
for _, gv := range w {
|
for _, gv := range w {
|
||||||
if info := FindGroupVersionV2(result, gv); info == nil || info.Freshness != apidiscoveryv2beta1.DiscoveryFreshnessStale {
|
if info := FindGroupVersionV2(result, gv); info == nil || info.Freshness != apidiscoveryv2.DiscoveryFreshnessStale {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -265,9 +275,9 @@ func (w waitForStaleGroupVersionsV2) Do(ctx context.Context, client testClient)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w waitForFreshGroupVersionsV2) Do(ctx context.Context, client testClient) error {
|
func (w waitForFreshGroupVersionsV2) Do(ctx context.Context, client testClient) error {
|
||||||
err := WaitForResultWithCondition(ctx, client, func(result apidiscoveryv2beta1.APIGroupDiscoveryList) bool {
|
err := WaitForResultWithCondition(ctx, client, func(result apidiscoveryv2.APIGroupDiscoveryList) bool {
|
||||||
for _, gv := range w {
|
for _, gv := range w {
|
||||||
if info := FindGroupVersionV2(result, gv); info == nil || info.Freshness != apidiscoveryv2beta1.DiscoveryFreshnessCurrent {
|
if info := FindGroupVersionV2(result, gv); info == nil || info.Freshness != apidiscoveryv2.DiscoveryFreshnessCurrent {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -282,7 +292,7 @@ func (w waitForFreshGroupVersionsV2) Do(ctx context.Context, client testClient)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w waitForGroupVersionsV2) Do(ctx context.Context, client testClient) error {
|
func (w waitForGroupVersionsV2) Do(ctx context.Context, client testClient) error {
|
||||||
err := WaitForResultWithCondition(ctx, client, func(result apidiscoveryv2beta1.APIGroupDiscoveryList) bool {
|
err := WaitForResultWithCondition(ctx, client, func(result apidiscoveryv2.APIGroupDiscoveryList) bool {
|
||||||
for _, gv := range w {
|
for _, gv := range w {
|
||||||
if FindGroupVersionV2(result, gv) == nil {
|
if FindGroupVersionV2(result, gv) == nil {
|
||||||
return false
|
return false
|
||||||
@@ -298,8 +308,25 @@ func (w waitForGroupVersionsV2) Do(ctx context.Context, client testClient) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w waitForGroupVersionsV2Beta1) Do(ctx context.Context, client testClient) error {
|
||||||
|
err := WaitForV2Beta1ResultWithCondition(ctx, client, func(result apidiscoveryv2beta1.APIGroupDiscoveryList) bool {
|
||||||
|
for _, gv := range w {
|
||||||
|
if FindGroupVersionV2Beta1(result, gv) == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("waiting for groupversions v2 (%v): %w", w, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (w waitForAbsentGroupVersionsV2) Do(ctx context.Context, client testClient) error {
|
func (w waitForAbsentGroupVersionsV2) Do(ctx context.Context, client testClient) error {
|
||||||
err := WaitForResultWithCondition(ctx, client, func(result apidiscoveryv2beta1.APIGroupDiscoveryList) bool {
|
err := WaitForResultWithCondition(ctx, client, func(result apidiscoveryv2.APIGroupDiscoveryList) bool {
|
||||||
for _, gv := range w {
|
for _, gv := range w {
|
||||||
if FindGroupVersionV2(result, gv) != nil {
|
if FindGroupVersionV2(result, gv) != nil {
|
||||||
return false
|
return false
|
||||||
@@ -315,6 +342,23 @@ func (w waitForAbsentGroupVersionsV2) Do(ctx context.Context, client testClient)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w waitForAbsentGroupVersionsV2Beta1) Do(ctx context.Context, client testClient) error {
|
||||||
|
err := WaitForV2Beta1ResultWithCondition(ctx, client, func(result apidiscoveryv2beta1.APIGroupDiscoveryList) bool {
|
||||||
|
for _, gv := range w {
|
||||||
|
if FindGroupVersionV2Beta1(result, gv) != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("waiting for absent groupversions v2 (%v): %w", w, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (w waitForGroupVersionsV1) Do(ctx context.Context, client testClient) error {
|
func (w waitForGroupVersionsV1) Do(ctx context.Context, client testClient) error {
|
||||||
err := WaitForV1GroupsWithCondition(ctx, client, func(result metav1.APIGroupList) bool {
|
err := WaitForV1GroupsWithCondition(ctx, client, func(result metav1.APIGroupList) bool {
|
||||||
for _, gv := range w {
|
for _, gv := range w {
|
||||||
@@ -429,7 +473,7 @@ func (w waitForResourcesAbsentV1) Do(ctx context.Context, client testClient) err
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w waitForResourcesV2) Do(ctx context.Context, client testClient) error {
|
func (w waitForResourcesV2) Do(ctx context.Context, client testClient) error {
|
||||||
err := WaitForResultWithCondition(ctx, client, func(result apidiscoveryv2beta1.APIGroupDiscoveryList) bool {
|
err := WaitForResultWithCondition(ctx, client, func(result apidiscoveryv2.APIGroupDiscoveryList) bool {
|
||||||
for _, gvr := range w {
|
for _, gvr := range w {
|
||||||
if info := FindGroupVersionV2(result, metav1.GroupVersion{Group: gvr.Group, Version: gvr.Version}); info == nil {
|
if info := FindGroupVersionV2(result, metav1.GroupVersion{Group: gvr.Group, Version: gvr.Version}); info == nil {
|
||||||
return false
|
return false
|
||||||
@@ -458,7 +502,7 @@ func (w waitForResourcesV2) Do(ctx context.Context, client testClient) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w waitForResourcesAbsentV2) Do(ctx context.Context, client testClient) error {
|
func (w waitForResourcesAbsentV2) Do(ctx context.Context, client testClient) error {
|
||||||
err := WaitForResultWithCondition(ctx, client, func(result apidiscoveryv2beta1.APIGroupDiscoveryList) bool {
|
err := WaitForResultWithCondition(ctx, client, func(result apidiscoveryv2.APIGroupDiscoveryList) bool {
|
||||||
for _, gvr := range w {
|
for _, gvr := range w {
|
||||||
if info := FindGroupVersionV2(result, metav1.GroupVersion{Group: gvr.Group, Version: gvr.Version}); info == nil {
|
if info := FindGroupVersionV2(result, metav1.GroupVersion{Group: gvr.Group, Version: gvr.Version}); info == nil {
|
||||||
return false
|
return false
|
||||||
@@ -484,7 +528,7 @@ func (i inlineAction) Do(ctx context.Context, client testClient) error {
|
|||||||
return i(ctx, client)
|
return i(ctx, client)
|
||||||
}
|
}
|
||||||
|
|
||||||
func FetchV2Discovery(ctx context.Context, client testClient) (apidiscoveryv2beta1.APIGroupDiscoveryList, error) {
|
func FetchV2Discovery(ctx context.Context, client testClient) (apidiscoveryv2.APIGroupDiscoveryList, error) {
|
||||||
result, err := client.
|
result, err := client.
|
||||||
Discovery().
|
Discovery().
|
||||||
RESTClient().
|
RESTClient().
|
||||||
@@ -494,6 +538,29 @@ func FetchV2Discovery(ctx context.Context, client testClient) (apidiscoveryv2bet
|
|||||||
Do(ctx).
|
Do(ctx).
|
||||||
Raw()
|
Raw()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return apidiscoveryv2.APIGroupDiscoveryList{}, fmt.Errorf("failed to fetch v2 discovery: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
groupList := apidiscoveryv2.APIGroupDiscoveryList{}
|
||||||
|
err = json.Unmarshal(result, &groupList)
|
||||||
|
if err != nil {
|
||||||
|
return apidiscoveryv2.APIGroupDiscoveryList{}, fmt.Errorf("failed to parse v2 discovery: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return groupList, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func FetchV2Beta1Discovery(ctx context.Context, client testClient) (apidiscoveryv2beta1.APIGroupDiscoveryList, error) {
|
||||||
|
result, err := client.
|
||||||
|
Discovery().
|
||||||
|
RESTClient().
|
||||||
|
Get().
|
||||||
|
AbsPath("/apis").
|
||||||
|
SetHeader("Accept", acceptV2Beta1JSON).
|
||||||
|
Do(ctx).
|
||||||
|
Raw()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return apidiscoveryv2beta1.APIGroupDiscoveryList{}, fmt.Errorf("failed to fetch v2 discovery: %w", err)
|
return apidiscoveryv2beta1.APIGroupDiscoveryList{}, fmt.Errorf("failed to fetch v2 discovery: %w", err)
|
||||||
}
|
}
|
||||||
@@ -562,7 +629,7 @@ func FetchV1DiscoveryResource(ctx context.Context, client testClient, gv metav1.
|
|||||||
}
|
}
|
||||||
|
|
||||||
func WaitForGroupsAbsent(ctx context.Context, client testClient, groups ...string) error {
|
func WaitForGroupsAbsent(ctx context.Context, client testClient, groups ...string) error {
|
||||||
return WaitForResultWithCondition(ctx, client, func(groupList apidiscoveryv2beta1.APIGroupDiscoveryList) bool {
|
return WaitForResultWithCondition(ctx, client, func(groupList apidiscoveryv2.APIGroupDiscoveryList) bool {
|
||||||
for _, searchGroup := range groups {
|
for _, searchGroup := range groups {
|
||||||
for _, docGroup := range groupList.Items {
|
for _, docGroup := range groupList.Items {
|
||||||
if docGroup.Name == searchGroup {
|
if docGroup.Name == searchGroup {
|
||||||
@@ -598,8 +665,8 @@ func WaitForRootPaths(t *testing.T, ctx context.Context, client testClient, requ
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func WaitForGroups(ctx context.Context, client testClient, groups ...apidiscoveryv2beta1.APIGroupDiscovery) error {
|
func WaitForGroups(ctx context.Context, client testClient, groups ...apidiscoveryv2.APIGroupDiscovery) error {
|
||||||
return WaitForResultWithCondition(ctx, client, func(groupList apidiscoveryv2beta1.APIGroupDiscoveryList) bool {
|
return WaitForResultWithCondition(ctx, client, func(groupList apidiscoveryv2.APIGroupDiscoveryList) bool {
|
||||||
for _, searchGroup := range groups {
|
for _, searchGroup := range groups {
|
||||||
found := false
|
found := false
|
||||||
for _, docGroup := range groupList.Items {
|
for _, docGroup := range groupList.Items {
|
||||||
@@ -616,13 +683,14 @@ func WaitForGroups(ctx context.Context, client testClient, groups ...apidiscover
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func WaitForResultWithCondition(ctx context.Context, client testClient, condition func(result apidiscoveryv2beta1.APIGroupDiscoveryList) bool) error {
|
func WaitForResultWithCondition(ctx context.Context, client testClient, condition func(result apidiscoveryv2.APIGroupDiscoveryList) bool) error {
|
||||||
// Keep repeatedly fetching document from aggregator.
|
// Keep repeatedly fetching document from aggregator.
|
||||||
// Check to see if it contains our service within a reasonable amount of time
|
// Check to see if it contains our service within a reasonable amount of time
|
||||||
return wait.PollWithContext(
|
return wait.PollUntilContextTimeout(
|
||||||
ctx,
|
ctx,
|
||||||
250*time.Millisecond,
|
250*time.Millisecond,
|
||||||
maxTimeout,
|
maxTimeout,
|
||||||
|
true,
|
||||||
func(ctx context.Context) (done bool, err error) {
|
func(ctx context.Context) (done bool, err error) {
|
||||||
groupList, err := FetchV2Discovery(ctx, client)
|
groupList, err := FetchV2Discovery(ctx, client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -637,13 +705,36 @@ func WaitForResultWithCondition(ctx context.Context, client testClient, conditio
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func WaitForV2Beta1ResultWithCondition(ctx context.Context, client testClient, condition func(result apidiscoveryv2beta1.APIGroupDiscoveryList) bool) error {
|
||||||
|
// Keep repeatedly fetching document from aggregator.
|
||||||
|
// Check to see if it contains our service within a reasonable amount of time
|
||||||
|
return wait.PollUntilContextTimeout(
|
||||||
|
ctx,
|
||||||
|
250*time.Millisecond,
|
||||||
|
maxTimeout,
|
||||||
|
true,
|
||||||
|
func(ctx context.Context) (done bool, err error) {
|
||||||
|
groupList, err := FetchV2Beta1Discovery(ctx, client)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if condition(groupList) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func WaitForV1GroupsWithCondition(ctx context.Context, client testClient, condition func(result metav1.APIGroupList) bool) error {
|
func WaitForV1GroupsWithCondition(ctx context.Context, client testClient, condition func(result metav1.APIGroupList) bool) error {
|
||||||
// Keep repeatedly fetching document from aggregator.
|
// Keep repeatedly fetching document from aggregator.
|
||||||
// Check to see if it contains our service within a reasonable amount of time
|
// Check to see if it contains our service within a reasonable amount of time
|
||||||
return wait.PollWithContext(
|
return wait.PollUntilContextTimeout(
|
||||||
ctx,
|
ctx,
|
||||||
250*time.Millisecond,
|
250*time.Millisecond,
|
||||||
maxTimeout,
|
maxTimeout,
|
||||||
|
true,
|
||||||
func(ctx context.Context) (done bool, err error) {
|
func(ctx context.Context) (done bool, err error) {
|
||||||
groupList, err := FetchV1DiscoveryGroups(ctx, client)
|
groupList, err := FetchV1DiscoveryGroups(ctx, client)
|
||||||
|
|
||||||
@@ -662,10 +753,11 @@ func WaitForV1GroupsWithCondition(ctx context.Context, client testClient, condit
|
|||||||
func WaitForV1ResourcesWithCondition(ctx context.Context, client testClient, gv metav1.GroupVersion, condition func(result metav1.APIResourceList) bool) error {
|
func WaitForV1ResourcesWithCondition(ctx context.Context, client testClient, gv metav1.GroupVersion, condition func(result metav1.APIResourceList) bool) error {
|
||||||
// Keep repeatedly fetching document from aggregator.
|
// Keep repeatedly fetching document from aggregator.
|
||||||
// Check to see if it contains our service within a reasonable amount of time
|
// Check to see if it contains our service within a reasonable amount of time
|
||||||
return wait.PollWithContext(
|
return wait.PollUntilContextTimeout(
|
||||||
ctx,
|
ctx,
|
||||||
250*time.Millisecond,
|
250*time.Millisecond,
|
||||||
maxTimeout,
|
maxTimeout,
|
||||||
|
true,
|
||||||
func(ctx context.Context) (done bool, err error) {
|
func(ctx context.Context) (done bool, err error) {
|
||||||
resourceList, err := FetchV1DiscoveryResource(ctx, client, gv)
|
resourceList, err := FetchV1DiscoveryResource(ctx, client, gv)
|
||||||
|
|
||||||
@@ -697,7 +789,23 @@ func FindGroupVersionV1(discovery metav1.APIGroupList, gv metav1.GroupVersion) b
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func FindGroupVersionV2(discovery apidiscoveryv2beta1.APIGroupDiscoveryList, gv metav1.GroupVersion) *apidiscoveryv2beta1.APIVersionDiscovery {
|
func FindGroupVersionV2(discovery apidiscoveryv2.APIGroupDiscoveryList, gv metav1.GroupVersion) *apidiscoveryv2.APIVersionDiscovery {
|
||||||
|
for _, documentGroup := range discovery.Items {
|
||||||
|
if documentGroup.Name != gv.Group {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, documentVersion := range documentGroup.Versions {
|
||||||
|
if documentVersion.Version == gv.Version {
|
||||||
|
return &documentVersion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func FindGroupVersionV2Beta1(discovery apidiscoveryv2beta1.APIGroupDiscoveryList, gv metav1.GroupVersion) *apidiscoveryv2beta1.APIVersionDiscovery {
|
||||||
for _, documentGroup := range discovery.Items {
|
for _, documentGroup := range discovery.Items {
|
||||||
if documentGroup.Name != gv.Group {
|
if documentGroup.Name != gv.Group {
|
||||||
continue
|
continue
|
||||||
|
Reference in New Issue
Block a user