Repository: kubernetes/kubernetes (language: go)

Issue:
[client-go] FakeDiscovery.ServerResourcesForGroupVersion does not return errors other than NotFound
### What happened?

I'm writing a UT for the following function:
```go
func isResourceRegistered(discoveryClient discovery.DiscoveryInterface, gvk schema.GroupVersionKind) (bool, error) {
	apiResourceLists, err := discoveryClient.ServerResourcesForGroupVersion(gvk.GroupVersion().String())
	if err != nil {
		if errors.IsNotFound(err) {
			return false, nil
		}
		return false, err
	}
	for _, apiResource := range apiResourceLists.APIResources {
		if apiResource.Kind == gvk.Kind {
			return true, nil
		}
	}
	return false, nil
}
```
The code branch where the server returns an error other than `NotFound` could not be tested using `client-go`'s `FakeDiscovery`. This is because `FakeDiscovery.ServerResourcesForGroupVersion` does not handle the error returned by `c.Invokes` and therefore could not return errors other than `NotFound`:
```go
func (c *FakeDiscovery) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) {
	action := testing.ActionImpl{
		Verb:     "get",
		Resource: schema.GroupVersionResource{Resource: "resource"},
	}
	c.Invokes(action, nil)
	for _, resourceList := range c.Resources {
		if resourceList.GroupVersion == groupVersion {
			return resourceList, nil
		}
	}
	return nil, &errors.StatusError{
		ErrStatus: metav1.Status{
			Status:  metav1.StatusFailure,
			Code:    http.StatusNotFound,
			Reason:  metav1.StatusReasonNotFound,
			Message: fmt.Sprintf("the server could not find the requested resource, GroupVersion %q not found", groupVersion),
		}}
}
```
Ref: https://github.com/kubernetes/client-go/blob/ab86e03da476bd58948f318b4f73d67d0801fcbd/discovery/fake/discovery.go#L45-L63

### What did you expect to happen?

Add a `Reactor` to `Fake.ReactionChain` so simulate errors other than `NotFound`. 

### How can we reproduce it (as minimally and precisely as possible)?

Run the following UT (should fail):
```go
func TestIsResourceRegistered(t *testing.T) {
	fakeDiscoveryClient := &fakediscovery.FakeDiscovery{Fake: &clientgotesting.Fake{}}
	fakeDiscoveryClient.PrependReactor("get", "*", func(action clientgotesting.Action) (bool, runtime.Object, error) {
		return true, nil, apierrors.NewTooManyRequests("too many requests", 1)
	})
	t.Run("Server returns errors other than NotFound", func(t *testing.T) {
		_, err := isResourceRegistered(fakeDiscoveryClient, schema.GroupVersionKind{Group: "foo", Version: "bar", Kind: "baz"})
		if err == nil {
			t.Errorf("Error must be non-nil")
		}
	})
}
```


Discussion / hints:
This issue is currently awaiting triage.

If a SIG or subproject determines this is a relevant issue, they will accept it by applying the `triage/accepted` label and provide further guidance.

The `triage/accepted` label can be added by org members by writing `/triage accepted` in a comment.


<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository.
</details>
/sig api-machinery
Same issue for some other methods of `FakeDiscovery`:
- `ServerGroupsAndResources`
- `ServerGroups`
I'll submit a PR shortly to address this issue. 

/assign

Fix patch:
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 f8a78e1ef43ee..e5d9e7f8007e0 100644
--- a/staging/src/k8s.io/client-go/discovery/fake/discovery.go
+++ b/staging/src/k8s.io/client-go/discovery/fake/discovery.go
@@ -47,7 +47,9 @@ func (c *FakeDiscovery) ServerResourcesForGroupVersion(groupVersion string) (*me
 		Verb:     "get",
 		Resource: schema.GroupVersionResource{Resource: "resource"},
 	}
-	c.Invokes(action, nil)
+	if _, err := c.Invokes(action, nil); err != nil {
+		return nil, err
+	}
 	for _, resourceList := range c.Resources {
 		if resourceList.GroupVersion == groupVersion {
 			return resourceList, nil
@@ -77,7 +79,9 @@ func (c *FakeDiscovery) ServerGroupsAndResources() ([]*metav1.APIGroup, []*metav
 		Verb:     "get",
 		Resource: schema.GroupVersionResource{Resource: "resource"},
 	}
-	c.Invokes(action, nil)
+	if _, err = c.Invokes(action, nil); err != nil {
+		return resultGroups, c.Resources, err
+	}
 	return resultGroups, c.Resources, nil
 }
 
@@ -100,7 +104,9 @@ func (c *FakeDiscovery) ServerGroups() (*metav1.APIGroupList, error) {
 		Verb:     "get",
 		Resource: schema.GroupVersionResource{Resource: "group"},
 	}
-	c.Invokes(action, nil)
+	if _, err := c.Invokes(action, nil); err != nil {
+		return nil, err
+	}
 
 	groups := map[string]*metav1.APIGroup{}
 


Test patch:
diff --git a/staging/src/k8s.io/client-go/discovery/fake/discovery_test.go b/staging/src/k8s.io/client-go/discovery/fake/discovery_test.go
index 946b484fabf05..44c5d74419856 100644
--- a/staging/src/k8s.io/client-go/discovery/fake/discovery_test.go
+++ b/staging/src/k8s.io/client-go/discovery/fake/discovery_test.go
@@ -63,3 +63,48 @@ func TestFakingServerVersionWithError(t *testing.T) {
 		t.Fatal("ServerVersion should return expected error, returned different error instead")
 	}
 }
+
+func TestFakingServerResourcesForGroupVersionWithError(t *testing.T) {
+	expectedError := errors.New("an error occurred")
+	fakeClient := fakeclientset.NewClientset()
+	fakeClient.Discovery().(*fakediscovery.FakeDiscovery).PrependReactor("*", "*", func(action kubetesting.Action) (handled bool, ret runtime.Object, err error) {
+		return true, nil, expectedError
+	})
+
+	result, err := fakeClient.Discovery().ServerResourcesForGroupVersion("dummy.group.io/v1beta2")
+	if result != nil {
+		t.Errorf(`expect result to be nil but got "%v" instead`, result)
+	}
+	if !errors.Is(err, expectedError) {
+		t.Errorf(`expect error to be "%v" but got "%v" instead`, expectedError, err)
+	}
+}
+
+func TestFakingServerGroupsWithError(t *testing.T) {
+	expectedError := errors.New("an error occurred")
+	fakeClient := fakeclientset.NewClientset()
+	fakeClient.Discovery().(*fakediscovery.FakeDiscovery).PrependReactor("*", "*", func(action kubetesting.Action) (handled bool, ret runtime.Object, err error) {
+		return true, nil, expectedError
+	})
+
+	result, err := fakeClient.Discovery().ServerGroups()
+	if result != nil {
+		t.Errorf(`expect result to be nil but got "%v" instead`, result)
+	}
+	if !errors.Is(err, expectedError) {
+		t.Errorf(`expect error to be "%v" but got "%v" instead`, expectedError, err)
+	}
+}
+
+func TestFakingServerGroupsAndResourcesWithError(t *testing.T) {
+	expectedError := errors.New("an error occurred")
+	fakeClient := fakeclientset.NewClientset()
+	fakeClient.Discovery().(*fakediscovery.FakeDiscovery).PrependReactor("get", "resource", func(action kubetesting.Action) (handled bool, ret runtime.Object, err error) {
+		return true, nil, expectedError
+	})
+
+	_, _, err := fakeClient.Discovery().ServerGroupsAndResources()
+	if !errors.Is(err, expectedError) {
+		t.Errorf(`expect error to be "%v" but got "%v" instead`, expectedError, err)
+	}
+}