func (d *DiscoveryClient) ServerPreferredNamespacedResources() ([]unversioned.GroupVersionResource, error) {
	return d.serverPreferredResources(true)
}
ServerPreferredNamespacedResources returns the supported namespaced resources with the
version preferred by the server.
package discovery
import (
	"encoding/json"
	"fmt"
	"net/url"
	"sort"
	"strings"
	"github.com/emicklei/go-restful/swagger"
	"k8s.io/client-go/pkg/api"
	"k8s.io/client-go/pkg/api/errors"
	"k8s.io/client-go/pkg/api/unversioned"
	"k8s.io/client-go/pkg/api/v1"
	"k8s.io/client-go/pkg/runtime"
	"k8s.io/client-go/pkg/runtime/serializer"
	"k8s.io/client-go/pkg/version"
	"k8s.io/client-go/rest"
)
type DiscoveryInterface interface {
	RESTClient() rest.Interface
	ServerGroupsInterface
	ServerResourcesInterface
	ServerVersionInterface
	SwaggerSchemaInterface
}
type ServerGroupsInterface interface {
	ServerGroups() (*unversioned.APIGroupList, error)
}
type ServerResourcesInterface interface {
	ServerResourcesForGroupVersion(groupVersion string) (*unversioned.APIResourceList, error)
	ServerResources() (map[string]*unversioned.APIResourceList, error)
	ServerPreferredResources() ([]unversioned.GroupVersionResource, error)
	ServerPreferredNamespacedResources() ([]unversioned.GroupVersionResource, error)
}
type ServerVersionInterface interface {
	ServerVersion() (*version.Info, error)
}
type SwaggerSchemaInterface interface {
	SwaggerSchema(version unversioned.GroupVersion) (*swagger.ApiDeclaration, error)
}
type DiscoveryClient struct {
	restClient rest.Interface
	LegacyPrefix string
}
func apiVersionsToAPIGroup(apiVersions *unversioned.APIVersions) (apiGroup unversioned.APIGroup) {
	groupVersions := []unversioned.GroupVersionForDiscovery{}
	for _, version := range apiVersions.Versions {
		groupVersion := unversioned.GroupVersionForDiscovery{
			GroupVersion: version,
			Version:      version,
		}
		groupVersions = append(groupVersions, groupVersion)
	}
	apiGroup.Versions = groupVersions
	apiGroup.PreferredVersion = groupVersions[0]
	return
}
func (d *DiscoveryClient) ServerGroups() (apiGroupList *unversioned.APIGroupList, err error) {
	v := &unversioned.APIVersions{}
	err = d.restClient.Get().AbsPath(d.LegacyPrefix).Do().Into(v)
	apiGroup := unversioned.APIGroup{}
	if err == nil {
		apiGroup = apiVersionsToAPIGroup(v)
	}
	if err != nil && !errors.IsNotFound(err) && !errors.IsForbidden(err) {
		return nil, err
	}
	apiGroupList = &unversioned.APIGroupList{}
	err = d.restClient.Get().AbsPath("/apis").Do().Into(apiGroupList)
	if err != nil && !errors.IsNotFound(err) && !errors.IsForbidden(err) {
		return nil, err
	}
	if err != nil && (errors.IsNotFound(err) || errors.IsForbidden(err)) {
		apiGroupList = &unversioned.APIGroupList{}
	}
	apiGroupList.Groups = append(apiGroupList.Groups, apiGroup)
	return apiGroupList, nil
}
func (d *DiscoveryClient) ServerResourcesForGroupVersion(groupVersion string) (resources *unversioned.APIResourceList, err error) {
	url := url.URL{}
	if len(groupVersion) == 0 {
		return nil, fmt.Errorf("groupVersion shouldn't be empty")
	}
	if len(d.LegacyPrefix) > 0 && groupVersion == "v1" {
		url.Path = d.LegacyPrefix + "/" + groupVersion
	} else {
		url.Path = "/apis/" + groupVersion
	}
	resources = &unversioned.APIResourceList{}
	err = d.restClient.Get().AbsPath(url.String()).Do().Into(resources)
	if err != nil {
		if groupVersion == "v1" && (errors.IsNotFound(err) || errors.IsForbidden(err)) {
			return resources, nil
		}
		return nil, err
	}
	return resources, nil
}
func (d *DiscoveryClient) ServerResources() (map[string]*unversioned.APIResourceList, error) {
	apiGroups, err := d.ServerGroups()
	if err != nil {
		return nil, err
	}
	groupVersions := unversioned.ExtractGroupVersions(apiGroups)
	result := map[string]*unversioned.APIResourceList{}
	for _, groupVersion := range groupVersions {
		resources, err := d.ServerResourcesForGroupVersion(groupVersion)
		if err != nil {
			return nil, err
		}
		result[groupVersion] = resources
	}
	return result, nil
}
type ErrGroupDiscoveryFailed struct {
	Groups map[unversioned.GroupVersion]error
}
func (e *ErrGroupDiscoveryFailed) Error() string {
	var groups []string
	for k, v := range e.Groups {
		groups = append(groups, fmt.Sprintf("%s: %v", k, v))
	}
	sort.Strings(groups)
	return fmt.Sprintf("unable to retrieve the complete list of server APIs: %s", strings.Join(groups, ", "))
}
func IsGroupDiscoveryFailedError(err error) bool {
	_, ok := err.(*ErrGroupDiscoveryFailed)
	return err != nil && ok
}
func (d *DiscoveryClient) serverPreferredResources(namespaced bool) ([]unversioned.GroupVersionResource, error) {
	const maxRetries = 2
	var failedGroups map[unversioned.GroupVersion]error
	var results []unversioned.GroupVersionResource
RetrieveGroups:
	for i := 0; i < maxRetries; i++ {
		results = []unversioned.GroupVersionResource{}
		failedGroups = make(map[unversioned.GroupVersion]error)
		serverGroupList, err := d.ServerGroups()
		if err != nil {
			return results, err
		}
		for _, apiGroup := range serverGroupList.Groups {
			preferredVersion := apiGroup.PreferredVersion
			groupVersion := unversioned.GroupVersion{Group: apiGroup.Name, Version: preferredVersion.Version}
			apiResourceList, err := d.ServerResourcesForGroupVersion(preferredVersion.GroupVersion)
			if err != nil {
				if i < maxRetries-1 {
					continue RetrieveGroups
				}
				failedGroups[groupVersion] = err
				continue
			}
			for _, apiResource := range apiResourceList.APIResources {
				if namespaced && !apiResource.Namespaced {
					continue
				}
				if strings.Contains(apiResource.Name, "/") {
					continue
				}
				results = append(results, groupVersion.WithResource(apiResource.Name))
			}
		}
		if len(failedGroups) == 0 {
			return results, nil
		}
	}
	return results, &ErrGroupDiscoveryFailed{Groups: failedGroups}
}
func (d *DiscoveryClient) ServerPreferredResources() ([]unversioned.GroupVersionResource, error) {
	return d.serverPreferredResources(false)
}