diff --git a/pkg/controller/garbagecollector/garbagecollector_test.go b/pkg/controller/garbagecollector/garbagecollector_test.go index 0543a5d6fbb..2f4c98487c4 100644 --- a/pkg/controller/garbagecollector/garbagecollector_test.go +++ b/pkg/controller/garbagecollector/garbagecollector_test.go @@ -948,10 +948,15 @@ func (_ *fakeServerResources) ServerResourcesForGroupVersion(groupVersion string return nil, nil } +// Deprecated: use ServerGroupsAndResources instead. func (_ *fakeServerResources) ServerResources() ([]*metav1.APIResourceList, error) { return nil, nil } +func (_ *fakeServerResources) ServerGroupsAndResources() ([]*metav1.APIGroup, []*metav1.APIResourceList, error) { + return nil, nil, nil +} + func (f *fakeServerResources) ServerPreferredResources() ([]*metav1.APIResourceList, error) { f.Lock.Lock() defer f.Lock.Unlock() diff --git a/pkg/kubectl/cmd/testing/fake.go b/pkg/kubectl/cmd/testing/fake.go index ac116373db6..c2de01d4e65 100644 --- a/pkg/kubectl/cmd/testing/fake.go +++ b/pkg/kubectl/cmd/testing/fake.go @@ -275,10 +275,15 @@ func (d *fakeCachedDiscoveryClient) Fresh() bool { func (d *fakeCachedDiscoveryClient) Invalidate() { } +// Deprecated: use ServerGroupsAndResources instead. func (d *fakeCachedDiscoveryClient) ServerResources() ([]*metav1.APIResourceList, error) { return []*metav1.APIResourceList{}, nil } +func (d *fakeCachedDiscoveryClient) ServerGroupsAndResources() ([]*metav1.APIGroup, []*metav1.APIResourceList, error) { + return []*metav1.APIGroup{}, []*metav1.APIResourceList{}, nil +} + // TestFactory extends cmdutil.Factory type TestFactory struct { cmdutil.Factory diff --git a/pkg/kubectl/cmd/top/top_pod_test.go b/pkg/kubectl/cmd/top/top_pod_test.go index 1d28b4c6a5d..61d1ed4a6f9 100644 --- a/pkg/kubectl/cmd/top/top_pod_test.go +++ b/pkg/kubectl/cmd/top/top_pod_test.go @@ -405,10 +405,16 @@ func (d *fakeDiscovery) ServerResourcesForGroupVersion(groupVersion string) (*me } // ServerResources returns the supported resources for all groups and versions. +// Deprecated: use ServerGroupsAndResources instead. func (d *fakeDiscovery) ServerResources() ([]*metav1.APIResourceList, error) { return nil, nil } +// ServerGroupsAndResources returns the supported groups and resources for all groups and versions. +func (d *fakeDiscovery) ServerGroupsAndResources() ([]*metav1.APIGroup, []*metav1.APIResourceList, error) { + return nil, nil, nil +} + // ServerPreferredResources returns the supported resources with the version preferred by the // server. func (d *fakeDiscovery) ServerPreferredResources() ([]*metav1.APIResourceList, error) { diff --git a/staging/src/k8s.io/client-go/discovery/cached/memcache.go b/staging/src/k8s.io/client-go/discovery/cached/memcache.go index bd6b478c908..92fdaaf997e 100644 --- a/staging/src/k8s.io/client-go/discovery/cached/memcache.go +++ b/staging/src/k8s.io/client-go/discovery/cached/memcache.go @@ -118,10 +118,16 @@ func (d *memCacheClient) ServerResourcesForGroupVersion(groupVersion string) (*m } // ServerResources returns the supported resources for all groups and versions. +// Deprecated: use ServerGroupsAndResources instead. func (d *memCacheClient) ServerResources() ([]*metav1.APIResourceList, error) { return discovery.ServerResources(d) } +// ServerGroupsAndResources returns the groups and supported resources for all groups and versions. +func (d *memCacheClient) ServerGroupsAndResources() ([]*metav1.APIGroup, []*metav1.APIResourceList, error) { + return discovery.ServerGroupsAndResources(d) +} + func (d *memCacheClient) ServerGroups() (*metav1.APIGroupList, error) { d.lock.Lock() defer d.lock.Unlock() diff --git a/staging/src/k8s.io/client-go/discovery/cached_discovery.go b/staging/src/k8s.io/client-go/discovery/cached_discovery.go index 61a758c0125..d5cc7806f26 100644 --- a/staging/src/k8s.io/client-go/discovery/cached_discovery.go +++ b/staging/src/k8s.io/client-go/discovery/cached_discovery.go @@ -90,8 +90,15 @@ func (d *CachedDiscoveryClient) ServerResourcesForGroupVersion(groupVersion stri } // ServerResources returns the supported resources for all groups and versions. +// Deprecated: use ServerGroupsAndResources instead. func (d *CachedDiscoveryClient) ServerResources() ([]*metav1.APIResourceList, error) { - return ServerResources(d) + _, rs, err := ServerGroupsAndResources(d) + return rs, err +} + +// ServerGroupsAndResources returns the supported groups and resources for all groups and versions. +func (d *CachedDiscoveryClient) ServerGroupsAndResources() ([]*metav1.APIGroup, []*metav1.APIResourceList, error) { + return ServerGroupsAndResources(d) } // ServerGroups returns the supported groups, with information like supported versions and the diff --git a/staging/src/k8s.io/client-go/discovery/cached_discovery_test.go b/staging/src/k8s.io/client-go/discovery/cached_discovery_test.go index 278931c2d09..7dd704cb866 100644 --- a/staging/src/k8s.io/client-go/discovery/cached_discovery_test.go +++ b/staging/src/k8s.io/client-go/discovery/cached_discovery_test.go @@ -112,6 +112,10 @@ func (c *fakeDiscoveryClient) RESTClient() restclient.Interface { func (c *fakeDiscoveryClient) ServerGroups() (*metav1.APIGroupList, error) { c.groupCalls = c.groupCalls + 1 + return c.serverGroups() +} + +func (c *fakeDiscoveryClient) serverGroups() (*metav1.APIGroupList, error) { return &metav1.APIGroupList{ Groups: []metav1.APIGroup{ { @@ -140,12 +144,26 @@ func (c *fakeDiscoveryClient) ServerResourcesForGroupVersion(groupVersion string return nil, errors.NewNotFound(schema.GroupResource{}, "") } +// Deprecated: use ServerGroupsAndResources instead. func (c *fakeDiscoveryClient) ServerResources() ([]*metav1.APIResourceList, error) { + _, rs, err := c.ServerGroupsAndResources() + return rs, err +} + +func (c *fakeDiscoveryClient) ServerGroupsAndResources() ([]*metav1.APIGroup, []*metav1.APIResourceList, error) { c.resourceCalls = c.resourceCalls + 1 - if c.serverResourcesHandler != nil { - return c.serverResourcesHandler() + + gs, _ := c.serverGroups() + resultGroups := []*metav1.APIGroup{} + for i := range gs.Groups { + resultGroups = append(resultGroups, &gs.Groups[i]) } - return []*metav1.APIResourceList{}, nil + + if c.serverResourcesHandler != nil { + rs, err := c.serverResourcesHandler() + return resultGroups, rs, err + } + return resultGroups, []*metav1.APIResourceList{}, nil } func (c *fakeDiscoveryClient) ServerPreferredResources() ([]*metav1.APIResourceList, error) { diff --git a/staging/src/k8s.io/client-go/discovery/discovery_client.go b/staging/src/k8s.io/client-go/discovery/discovery_client.go index 627375aa047..61b9c4481bc 100644 --- a/staging/src/k8s.io/client-go/discovery/discovery_client.go +++ b/staging/src/k8s.io/client-go/discovery/discovery_client.go @@ -88,12 +88,28 @@ type ServerResourcesInterface interface { // ServerResourcesForGroupVersion returns the supported resources for a group and version. ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) // ServerResources returns the supported resources for all groups and versions. + // + // The returned resource list might be non-nil with partial results even in the case of + // non-nil error. + // + // Deprecated: use ServerGroupsAndResources instead. ServerResources() ([]*metav1.APIResourceList, error) + // ServerResources returns the supported groups and resources for all groups and versions. + // + // The returned group and resource lists might be non-nil with partial results even in the + // case of non-nil error. + ServerGroupsAndResources() ([]*metav1.APIGroup, []*metav1.APIResourceList, error) // ServerPreferredResources returns the supported resources with the version preferred by the // server. + // + // The returned group and resource lists might be non-nil with partial results even in the + // case of non-nil error. ServerPreferredResources() ([]*metav1.APIResourceList, error) // ServerPreferredNamespacedResources returns the supported namespaced resources with the // version preferred by the server. + // + // The returned resource list might be non-nil with partial results even in the case of + // non-nil error. ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) } @@ -191,14 +207,18 @@ func (d *DiscoveryClient) ServerResourcesForGroupVersion(groupVersion string) (r return resources, nil } -// serverResources returns the supported resources for all groups and versions. -func (d *DiscoveryClient) serverResources() ([]*metav1.APIResourceList, error) { - return ServerResources(d) +// ServerResources returns the supported resources for all groups and versions. +// Deprecated: use ServerGroupsAndResources instead. +func (d *DiscoveryClient) ServerResources() ([]*metav1.APIResourceList, error) { + _, rs, err := d.ServerGroupsAndResources() + return rs, err } -// ServerResources returns the supported resources for all groups and versions. -func (d *DiscoveryClient) ServerResources() ([]*metav1.APIResourceList, error) { - return withRetries(defaultRetries, d.serverResources) +// ServerGroupsAndResources returns the supported resources for all groups and versions. +func (d *DiscoveryClient) ServerGroupsAndResources() ([]*metav1.APIGroup, []*metav1.APIResourceList, error) { + return withRetries(defaultRetries, func() ([]*metav1.APIGroup, []*metav1.APIResourceList, error) { + return ServerGroupsAndResources(d) + }) } // ErrGroupDiscoveryFailed is returned if one or more API groups fail to load. @@ -224,23 +244,28 @@ func IsGroupDiscoveryFailedError(err error) bool { return err != nil && ok } -// serverPreferredResources returns the supported resources with the version preferred by the server. -func (d *DiscoveryClient) serverPreferredResources() ([]*metav1.APIResourceList, error) { - return ServerPreferredResources(d) +// ServerResources uses the provided discovery interface to look up supported resources for all groups and versions. +// Deprecated: use ServerGroupsAndResources instead. +func ServerResources(d DiscoveryInterface) ([]*metav1.APIResourceList, error) { + _, rs, err := ServerGroupsAndResources(d) + return rs, err } -// ServerResources uses the provided discovery interface to look up supported resources for all groups and versions. -func ServerResources(d DiscoveryInterface) ([]*metav1.APIResourceList, error) { - apiGroups, err := d.ServerGroups() - if err != nil { - return nil, err +func ServerGroupsAndResources(d DiscoveryInterface) ([]*metav1.APIGroup, []*metav1.APIResourceList, error) { + sgs, err := d.ServerGroups() + if sgs == nil { + return nil, nil, err + } + resultGroups := []*metav1.APIGroup{} + for i := range sgs.Groups { + resultGroups = append(resultGroups, &sgs.Groups[i]) } - groupVersionResources, failedGroups := fetchGroupVersionResources(d, apiGroups) + groupVersionResources, failedGroups := fetchGroupVersionResources(d, sgs) // order results by group/version discovery order result := []*metav1.APIResourceList{} - for _, apiGroup := range apiGroups.Groups { + for _, apiGroup := range sgs.Groups { for _, version := range apiGroup.Versions { gv := schema.GroupVersion{Group: apiGroup.Name, Version: version.Version} if resources, ok := groupVersionResources[gv]; ok { @@ -250,10 +275,10 @@ func ServerResources(d DiscoveryInterface) ([]*metav1.APIResourceList, error) { } if len(failedGroups) == 0 { - return result, nil + return resultGroups, result, nil } - return result, &ErrGroupDiscoveryFailed{Groups: failedGroups} + return resultGroups, result, &ErrGroupDiscoveryFailed{Groups: failedGroups} } // ServerPreferredResources uses the provided discovery interface to look up preferred resources @@ -317,7 +342,7 @@ func ServerPreferredResources(d DiscoveryInterface) ([]*metav1.APIResourceList, return result, &ErrGroupDiscoveryFailed{Groups: failedGroups} } -// fetchServerResourcesForGroupVersions uses the discovery client to fetch the resources for the specified groups in parallel +// fetchServerResourcesForGroupVersions uses the discovery client to fetch the resources for the specified groups in parallel. func fetchGroupVersionResources(d DiscoveryInterface, apiGroups *metav1.APIGroupList) (map[schema.GroupVersion]*metav1.APIResourceList, map[schema.GroupVersion]error) { groupVersionResources := make(map[schema.GroupVersion]*metav1.APIResourceList) failedGroups := make(map[schema.GroupVersion]error) @@ -341,7 +366,9 @@ func fetchGroupVersionResources(d DiscoveryInterface, apiGroups *metav1.APIGroup if err != nil { // TODO: maybe restrict this to NotFound errors failedGroups[groupVersion] = err - } else { + } + if apiResourceList != nil { + // even in case of error, some fallback might have been returned groupVersionResources[groupVersion] = apiResourceList } }() @@ -355,7 +382,11 @@ func fetchGroupVersionResources(d DiscoveryInterface, apiGroups *metav1.APIGroup // ServerPreferredResources returns the supported resources with the version preferred by the // server. func (d *DiscoveryClient) ServerPreferredResources() ([]*metav1.APIResourceList, error) { - return withRetries(defaultRetries, d.serverPreferredResources) + _, rs, err := withRetries(defaultRetries, func() ([]*metav1.APIGroup, []*metav1.APIResourceList, error) { + rs, err := ServerPreferredResources(d) + return nil, rs, err + }) + return rs, err } // ServerPreferredNamespacedResources returns the supported namespaced resources with the @@ -410,19 +441,20 @@ func (d *DiscoveryClient) OpenAPISchema() (*openapi_v2.Document, error) { } // withRetries retries the given recovery function in case the groups supported by the server change after ServerGroup() returns. -func withRetries(maxRetries int, f func() ([]*metav1.APIResourceList, error)) ([]*metav1.APIResourceList, error) { +func withRetries(maxRetries int, f func() ([]*metav1.APIGroup, []*metav1.APIResourceList, error)) ([]*metav1.APIGroup, []*metav1.APIResourceList, error) { var result []*metav1.APIResourceList + var resultGroups []*metav1.APIGroup var err error for i := 0; i < maxRetries; i++ { - result, err = f() + resultGroups, result, err = f() if err == nil { - return result, nil + return resultGroups, result, nil } if _, ok := err.(*ErrGroupDiscoveryFailed); !ok { - return nil, err + return nil, nil, err } } - return result, err + return resultGroups, result, err } func setDiscoveryDefaults(config *restclient.Config) error { diff --git a/staging/src/k8s.io/client-go/discovery/fake/discovery.go b/staging/src/k8s.io/client-go/discovery/fake/discovery.go index 9565fa46c5e..335473dd199 100644 --- a/staging/src/k8s.io/client-go/discovery/fake/discovery.go +++ b/staging/src/k8s.io/client-go/discovery/fake/discovery.go @@ -53,13 +53,29 @@ func (c *FakeDiscovery) ServerResourcesForGroupVersion(groupVersion string) (*me } // ServerResources returns the supported resources for all groups and versions. +// Deprecated: use ServerGroupsAndResources instead. func (c *FakeDiscovery) ServerResources() ([]*metav1.APIResourceList, error) { + _, rs, err := c.ServerGroupsAndResources() + return rs, err +} + +// ServerGroupsAndResources returns the supported groups and resources for all groups and versions. +func (c *FakeDiscovery) ServerGroupsAndResources() ([]*metav1.APIGroup, []*metav1.APIResourceList, error) { + sgs, err := c.ServerGroups() + if err != nil { + return nil, nil, err + } + resultGroups := []*metav1.APIGroup{} + for i := range sgs.Groups { + resultGroups = append(resultGroups, &sgs.Groups[i]) + } + action := testing.ActionImpl{ Verb: "get", Resource: schema.GroupVersionResource{Resource: "resource"}, } c.Invokes(action, nil) - return c.Resources, nil + return resultGroups, c.Resources, nil } // ServerPreferredResources returns the supported resources with the version diff --git a/staging/src/k8s.io/client-go/restmapper/BUILD b/staging/src/k8s.io/client-go/restmapper/BUILD index ed8006f0318..4d3169b655a 100644 --- a/staging/src/k8s.io/client-go/restmapper/BUILD +++ b/staging/src/k8s.io/client-go/restmapper/BUILD @@ -36,6 +36,7 @@ go_test( "//staging/src/k8s.io/client-go/discovery:go_default_library", "//staging/src/k8s.io/client-go/rest:go_default_library", "//staging/src/k8s.io/client-go/rest/fake:go_default_library", + "//vendor/github.com/davecgh/go-spew/spew:go_default_library", "//vendor/github.com/googleapis/gnostic/OpenAPIv2:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library", ], diff --git a/staging/src/k8s.io/client-go/restmapper/discovery.go b/staging/src/k8s.io/client-go/restmapper/discovery.go index 84491f4c5d1..f8d7080d49e 100644 --- a/staging/src/k8s.io/client-go/restmapper/discovery.go +++ b/staging/src/k8s.io/client-go/restmapper/discovery.go @@ -145,27 +145,26 @@ func NewDiscoveryRESTMapper(groupResources []*APIGroupResources) meta.RESTMapper // GetAPIGroupResources uses the provided discovery client to gather // discovery information and populate a slice of APIGroupResources. func GetAPIGroupResources(cl discovery.DiscoveryInterface) ([]*APIGroupResources, error) { - apiGroups, err := cl.ServerGroups() - if err != nil { - if apiGroups == nil || len(apiGroups.Groups) == 0 { - return nil, err - } + gs, rs, err := cl.ServerGroupsAndResources() + if rs == nil || gs == nil { + return nil, err // TODO track the errors and update callers to handle partial errors. } + rsm := map[string]*metav1.APIResourceList{} + for _, r := range rs { + rsm[r.GroupVersion] = r + } + var result []*APIGroupResources - for _, group := range apiGroups.Groups { + for _, group := range gs { groupResources := &APIGroupResources{ - Group: group, + Group: *group, VersionedResources: make(map[string][]metav1.APIResource), } for _, version := range group.Versions { - resources, err := cl.ServerResourcesForGroupVersion(version.GroupVersion) - if err != nil { - // continue as best we can - // TODO track the errors and update callers to handle partial errors. - if resources == nil || len(resources.APIResources) == 0 { - continue - } + resources, ok := rsm[version.GroupVersion] + if !ok { + continue } groupResources.VersionedResources[version.Version] = resources.APIResources } diff --git a/staging/src/k8s.io/client-go/restmapper/discovery_test.go b/staging/src/k8s.io/client-go/restmapper/discovery_test.go index 1b8e7c4f056..77a16c481e3 100644 --- a/staging/src/k8s.io/client-go/restmapper/discovery_test.go +++ b/staging/src/k8s.io/client-go/restmapper/discovery_test.go @@ -17,9 +17,11 @@ limitations under the License. package restmapper import ( + "fmt" "reflect" "testing" + "github.com/davecgh/go-spew/spew" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -283,10 +285,146 @@ func TestDeferredDiscoveryRESTMapper_CacheMiss(t *testing.T) { assert.Equal(cdc.invalidateCalls, 2, "should HAVE called Invalidate() again after another cache-miss, but with fresh==false") } +func TestGetAPIGroupResources(t *testing.T) { + type Test struct { + name string + + discovery DiscoveryInterface + + expected []*APIGroupResources + expectedError error + } + + for _, test := range []Test{ + {"nil", &fakeFailingDiscovery{nil, nil, nil, nil}, nil, nil}, + {"normal", + &fakeFailingDiscovery{ + []metav1.APIGroup{aGroup, bGroup}, nil, + map[string]*metav1.APIResourceList{"a/v1": &aResources, "b/v1": &bResources}, nil, + }, + []*APIGroupResources{ + {aGroup, map[string][]metav1.APIResource{"v1": {aFoo}}}, + {bGroup, map[string][]metav1.APIResource{"v1": {bBar}}}, + }, nil, + }, + {"groups failed, but has fallback with a only", + &fakeFailingDiscovery{ + []metav1.APIGroup{aGroup}, fmt.Errorf("error fetching groups"), + map[string]*metav1.APIResourceList{"a/v1": &aResources, "b/v1": &bResources}, nil, + }, + []*APIGroupResources{ + {aGroup, map[string][]metav1.APIResource{"v1": {aFoo}}}, + }, nil, + }, + {"groups failed, but has no fallback", + &fakeFailingDiscovery{ + nil, fmt.Errorf("error fetching groups"), + map[string]*metav1.APIResourceList{"a/v1": &aResources, "b/v1": &bResources}, nil, + }, + nil, fmt.Errorf("error fetching groups"), + }, + {"a failed, but has fallback", + &fakeFailingDiscovery{ + []metav1.APIGroup{aGroup, bGroup}, nil, + map[string]*metav1.APIResourceList{"a/v1": &aResources, "b/v1": &bResources}, map[string]error{"a/v1": fmt.Errorf("a failed")}, + }, + []*APIGroupResources{ + {aGroup, map[string][]metav1.APIResource{"v1": {aFoo}}}, + {bGroup, map[string][]metav1.APIResource{"v1": {bBar}}}, + }, nil, // TODO: do we want this? + }, + {"a failed, but has no fallback", + &fakeFailingDiscovery{ + []metav1.APIGroup{aGroup, bGroup}, nil, + map[string]*metav1.APIResourceList{"b/v1": &bResources}, map[string]error{"a/v1": fmt.Errorf("a failed")}, + }, + []*APIGroupResources{ + {aGroup, map[string][]metav1.APIResource{}}, + {bGroup, map[string][]metav1.APIResource{"v1": {bBar}}}, + }, nil, // TODO: do we want this? + }, + {"a and b failed, but have fallbacks", + &fakeFailingDiscovery{ + []metav1.APIGroup{aGroup, bGroup}, nil, + map[string]*metav1.APIResourceList{"a/v1": &aResources, "b/v1": &bResources}, // TODO: both fallbacks are ignored + map[string]error{"a/v1": fmt.Errorf("a failed"), "b/v1": fmt.Errorf("b failed")}, + }, + []*APIGroupResources{ + {aGroup, map[string][]metav1.APIResource{"v1": {aFoo}}}, + {bGroup, map[string][]metav1.APIResource{"v1": {bBar}}}, + }, nil, // TODO: do we want this? + }, + } { + t.Run(test.name, func(t *testing.T) { + got, err := GetAPIGroupResources(test.discovery) + if err == nil && test.expectedError != nil { + t.Fatalf("expected error %q, but got none", test.expectedError) + } else if err != nil && test.expectedError == nil { + t.Fatalf("unexpected error: %v", err) + } + if !reflect.DeepEqual(test.expected, got) { + t.Errorf("unexpected result:\nexpected = %s\ngot = %s", spew.Sdump(test.expected), spew.Sdump(got)) + } + }) + } + +} + +var _ DiscoveryInterface = &fakeFailingDiscovery{} + +type fakeFailingDiscovery struct { + groups []metav1.APIGroup + groupsErr error + + resourcesForGroupVersion map[string]*metav1.APIResourceList + resourcesForGroupVersionErr map[string]error +} + +func (*fakeFailingDiscovery) RESTClient() restclient.Interface { + return nil +} + +func (d *fakeFailingDiscovery) ServerGroups() (*metav1.APIGroupList, error) { + if d.groups == nil && d.groupsErr != nil { + return nil, d.groupsErr + } + return &metav1.APIGroupList{Groups: d.groups}, d.groupsErr +} + +func (d *fakeFailingDiscovery) ServerGroupsAndResources() ([]*metav1.APIGroup, []*metav1.APIResourceList, error) { + return ServerGroupsAndResources(d) +} +func (d *fakeFailingDiscovery) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) { + if rs, found := d.resourcesForGroupVersion[groupVersion]; found { + return rs, d.resourcesForGroupVersionErr[groupVersion] + } + return nil, fmt.Errorf("not found") +} + +func (d *fakeFailingDiscovery) ServerResources() ([]*metav1.APIResourceList, error) { + return ServerResources(d) +} + +func (d *fakeFailingDiscovery) ServerPreferredResources() ([]*metav1.APIResourceList, error) { + return ServerPreferredResources(d) +} + +func (d *fakeFailingDiscovery) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) { + return ServerPreferredNamespacedResources(d) +} + +func (*fakeFailingDiscovery) ServerVersion() (*version.Info, error) { + return &version.Info{}, nil +} + +func (*fakeFailingDiscovery) OpenAPISchema() (*openapi_v2.Document, error) { + panic("implement me") +} + type fakeCachedDiscoveryInterface struct { invalidateCalls int fresh bool - enabledA bool + enabledGroupA bool } var _ CachedDiscoveryInterface = &fakeCachedDiscoveryInterface{} @@ -298,7 +436,7 @@ func (c *fakeCachedDiscoveryInterface) Fresh() bool { func (c *fakeCachedDiscoveryInterface) Invalidate() { c.invalidateCalls = c.invalidateCalls + 1 c.fresh = true - c.enabledA = true + c.enabledGroupA = true } func (c *fakeCachedDiscoveryInterface) RESTClient() restclient.Interface { @@ -306,55 +444,33 @@ func (c *fakeCachedDiscoveryInterface) RESTClient() restclient.Interface { } func (c *fakeCachedDiscoveryInterface) ServerGroups() (*metav1.APIGroupList, error) { - if c.enabledA { + if c.enabledGroupA { return &metav1.APIGroupList{ - Groups: []metav1.APIGroup{ - { - Name: "a", - Versions: []metav1.GroupVersionForDiscovery{ - { - GroupVersion: "a/v1", - Version: "v1", - }, - }, - PreferredVersion: metav1.GroupVersionForDiscovery{ - GroupVersion: "a/v1", - Version: "v1", - }, - }, - }, + Groups: []metav1.APIGroup{aGroup}, }, nil } return &metav1.APIGroupList{}, nil } +func (c *fakeCachedDiscoveryInterface) ServerGroupsAndResources() ([]*metav1.APIGroup, []*metav1.APIResourceList, error) { + return ServerGroupsAndResources(c) +} + func (c *fakeCachedDiscoveryInterface) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) { - if c.enabledA && groupVersion == "a/v1" { - return &metav1.APIResourceList{ - GroupVersion: "a/v1", - APIResources: []metav1.APIResource{ - { - Name: "foo", - Kind: "Foo", - Namespaced: false, - }, - }, - }, nil + if c.enabledGroupA && groupVersion == "a/v1" { + return &aResources, nil } return nil, errors.NewNotFound(schema.GroupResource{}, "") } +// Deprecated: use ServerGroupsAndResources instead. func (c *fakeCachedDiscoveryInterface) ServerResources() ([]*metav1.APIResourceList, error) { - if c.enabledA { - av1, _ := c.ServerResourcesForGroupVersion("a/v1") - return []*metav1.APIResourceList{av1}, nil - } - return []*metav1.APIResourceList{}, nil + return ServerResources(c) } func (c *fakeCachedDiscoveryInterface) ServerPreferredResources() ([]*metav1.APIResourceList, error) { - if c.enabledA { + if c.enabledGroupA { return []*metav1.APIResourceList{ { GroupVersion: "a/v1", @@ -382,3 +498,50 @@ func (c *fakeCachedDiscoveryInterface) ServerVersion() (*version.Info, error) { func (c *fakeCachedDiscoveryInterface) OpenAPISchema() (*openapi_v2.Document, error) { return &openapi_v2.Document{}, nil } + +var ( + aGroup = metav1.APIGroup{ + Name: "a", + Versions: []metav1.GroupVersionForDiscovery{ + { + GroupVersion: "a/v1", + Version: "v1", + }, + }, + PreferredVersion: metav1.GroupVersionForDiscovery{ + GroupVersion: "a/v1", + Version: "v1", + }, + } + bGroup = metav1.APIGroup{ + Name: "b", + Versions: []metav1.GroupVersionForDiscovery{ + { + GroupVersion: "b/v1", + Version: "v1", + }, + }, + PreferredVersion: metav1.GroupVersionForDiscovery{ + GroupVersion: "b/v1", + Version: "v1", + }, + } + aResources = metav1.APIResourceList{ + GroupVersion: "a/v1", + APIResources: []metav1.APIResource{aFoo}, + } + aFoo = metav1.APIResource{ + Name: "foo", + Kind: "Foo", + Namespaced: false, + } + bResources = metav1.APIResourceList{ + GroupVersion: "b/v1", + APIResources: []metav1.APIResource{bBar}, + } + bBar = metav1.APIResource{ + Name: "bar", + Kind: "Bar", + Namespaced: true, + } +) diff --git a/staging/src/k8s.io/client-go/restmapper/shortcut_test.go b/staging/src/k8s.io/client-go/restmapper/shortcut_test.go index dbc288fadff..3a4a99ea88f 100644 --- a/staging/src/k8s.io/client-go/restmapper/shortcut_test.go +++ b/staging/src/k8s.io/client-go/restmapper/shortcut_test.go @@ -265,11 +265,26 @@ func (c *fakeDiscoveryClient) ServerResourcesForGroupVersion(groupVersion string return nil, errors.NewNotFound(schema.GroupResource{}, "") } +// Deprecated: use ServerGroupsAndResources instead. func (c *fakeDiscoveryClient) ServerResources() ([]*metav1.APIResourceList, error) { - if c.serverResourcesHandler != nil { - return c.serverResourcesHandler() + _, rs, err := c.ServerGroupsAndResources() + return rs, err +} + +func (c *fakeDiscoveryClient) ServerGroupsAndResources() ([]*metav1.APIGroup, []*metav1.APIResourceList, error) { + sgs, err := c.ServerGroups() + if err != nil { + return nil, nil, err } - return []*metav1.APIResourceList{}, nil + resultGroups := []*metav1.APIGroup{} + for i := range sgs.Groups { + resultGroups = append(resultGroups, &sgs.Groups[i]) + } + if c.serverResourcesHandler != nil { + rs, err := c.serverResourcesHandler() + return resultGroups, rs, err + } + return resultGroups, []*metav1.APIResourceList{}, nil } func (c *fakeDiscoveryClient) ServerPreferredResources() ([]*metav1.APIResourceList, error) {