Aggregated discovery resilient to nil GVK

Kubernetes-commit: 26bf8a7ceb51bac357d8a02fd3e62b84363716db
This commit is contained in:
Sean Sullivan 2023-03-14 17:59:19 +00:00 committed by Kubernetes Publisher
parent 48d97c09db
commit 2bd557faec
2 changed files with 108 additions and 19 deletions

View File

@ -92,12 +92,18 @@ func convertAPIGroup(g apidiscovery.APIGroupDiscovery) (
resourceList := &metav1.APIResourceList{} resourceList := &metav1.APIResourceList{}
resourceList.GroupVersion = gv.String() resourceList.GroupVersion = gv.String()
for _, r := range v.Resources { for _, r := range v.Resources {
resource := convertAPIResource(r) resource, err := convertAPIResource(r)
resourceList.APIResources = append(resourceList.APIResources, resource) if err == nil {
resourceList.APIResources = append(resourceList.APIResources, resource)
}
// Subresources field in new format get transformed into full APIResources. // 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 { for _, subresource := range r.Subresources {
sr := convertAPISubresource(resource, subresource) sr, err := convertAPISubresource(resource, subresource)
resourceList.APIResources = append(resourceList.APIResources, sr) if err == nil {
resourceList.APIResources = append(resourceList.APIResources, sr)
}
} }
} }
gvResources[gv] = resourceList gvResources[gv] = resourceList
@ -105,30 +111,44 @@ func convertAPIGroup(g apidiscovery.APIGroupDiscovery) (
return group, gvResources, failedGVs return group, gvResources, failedGVs
} }
// convertAPIResource tranforms a APIResourceDiscovery to an APIResource. // convertAPIResource tranforms a APIResourceDiscovery to an APIResource. We are
func convertAPIResource(in apidiscovery.APIResourceDiscovery) metav1.APIResource { // resilient to missing GVK, since this resource might be the parent resource
return metav1.APIResource{ // for a subresource. If the parent is missing a GVK, it is not returned in
// discovery, and the subresource MUST have the GVK.
func convertAPIResource(in apidiscovery.APIResourceDiscovery) (metav1.APIResource, error) {
result := metav1.APIResource{
Name: in.Resource, Name: in.Resource,
SingularName: in.SingularResource, SingularName: in.SingularResource,
Namespaced: in.Scope == apidiscovery.ScopeNamespace, Namespaced: in.Scope == apidiscovery.ScopeNamespace,
Group: in.ResponseKind.Group,
Version: in.ResponseKind.Version,
Kind: in.ResponseKind.Kind,
Verbs: in.Verbs, Verbs: in.Verbs,
ShortNames: in.ShortNames, ShortNames: in.ShortNames,
Categories: in.Categories, Categories: in.Categories,
} }
var err error
if in.ResponseKind != nil {
result.Group = in.ResponseKind.Group
result.Version = in.ResponseKind.Version
result.Kind = in.ResponseKind.Kind
} else {
err = fmt.Errorf("discovery resource %s missing GVK", in.Resource)
}
// Can return partial result with error, which can be the parent for a
// subresource. Do not add this result to the returned discovery resources.
return result, err
} }
// convertAPISubresource tranforms a APISubresourceDiscovery to an APIResource. // convertAPISubresource tranforms a APISubresourceDiscovery to an APIResource.
func convertAPISubresource(parent metav1.APIResource, in apidiscovery.APISubresourceDiscovery) metav1.APIResource { func convertAPISubresource(parent metav1.APIResource, in apidiscovery.APISubresourceDiscovery) (metav1.APIResource, error) {
return metav1.APIResource{ result := metav1.APIResource{}
Name: fmt.Sprintf("%s/%s", parent.Name, in.Subresource), if in.ResponseKind == nil {
SingularName: parent.SingularName, return result, fmt.Errorf("subresource %s/%s missing GVK", parent.Name, in.Subresource)
Namespaced: parent.Namespaced,
Group: in.ResponseKind.Group,
Version: in.ResponseKind.Version,
Kind: in.ResponseKind.Kind,
Verbs: in.Verbs,
} }
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
} }

View File

@ -541,6 +541,75 @@ func TestSplitGroupsAndResources(t *testing.T) {
}, },
expectedFailedGVs: map[schema.GroupVersion]error{}, expectedFailedGVs: map[schema.GroupVersion]error{},
}, },
{
name: "Aggregated discovery with single subresource and parent missing GVK",
agg: apidiscovery.APIGroupDiscoveryList{
Items: []apidiscovery.APIGroupDiscovery{
{
ObjectMeta: metav1.ObjectMeta{
Name: "external.metrics.k8s.io",
},
Versions: []apidiscovery.APIVersionDiscovery{
{
Version: "v1beta1",
Resources: []apidiscovery.APIResourceDiscovery{
{
// resilient to nil GVK for parent
Resource: "*",
Scope: apidiscovery.ScopeNamespace,
SingularResource: "",
Subresources: []apidiscovery.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", name: "Aggregated discovery with multiple subresources",
agg: apidiscovery.APIGroupDiscoveryList{ agg: apidiscovery.APIGroupDiscoveryList{