summaryrefslogtreecommitdiff
path: root/vendor/k8s.io/client-go/discovery
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/k8s.io/client-go/discovery')
-rw-r--r--vendor/k8s.io/client-go/discovery/discovery_client.go86
-rw-r--r--vendor/k8s.io/client-go/discovery/restmapper.go31
-rw-r--r--vendor/k8s.io/client-go/discovery/unstructured.go66
3 files changed, 80 insertions, 103 deletions
diff --git a/vendor/k8s.io/client-go/discovery/discovery_client.go b/vendor/k8s.io/client-go/discovery/discovery_client.go
index 011dd9ecf..24c11f33b 100644
--- a/vendor/k8s.io/client-go/discovery/discovery_client.go
+++ b/vendor/k8s.io/client-go/discovery/discovery_client.go
@@ -23,10 +23,9 @@ import (
"sort"
"strings"
- "github.com/emicklei/go-restful-swagger12"
+ "github.com/golang/protobuf/proto"
+ "github.com/googleapis/gnostic/OpenAPIv2"
- "github.com/go-openapi/loads"
- "github.com/go-openapi/spec"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
@@ -34,7 +33,6 @@ import (
"k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/apimachinery/pkg/version"
"k8s.io/client-go/kubernetes/scheme"
- "k8s.io/client-go/pkg/api/v1"
restclient "k8s.io/client-go/rest"
)
@@ -48,14 +46,17 @@ type DiscoveryInterface interface {
ServerGroupsInterface
ServerResourcesInterface
ServerVersionInterface
- SwaggerSchemaInterface
OpenAPISchemaInterface
}
// CachedDiscoveryInterface is a DiscoveryInterface with cache invalidation and freshness.
type CachedDiscoveryInterface interface {
DiscoveryInterface
- // Fresh returns true if no cached data was used that had been retrieved before the instantiation.
+ // Fresh is supposed to tell the caller whether or not to retry if the cache
+ // fails to find something (false = retry, true = no need to retry).
+ //
+ // TODO: this needs to be revisited, this interface can't be locked properly
+ // and doesn't make a lot of sense.
Fresh() bool
// Invalidate enforces that no cached data is used in the future that is older than the current time.
Invalidate()
@@ -88,16 +89,10 @@ type ServerVersionInterface interface {
ServerVersion() (*version.Info, error)
}
-// SwaggerSchemaInterface has a method to retrieve the swagger schema.
-type SwaggerSchemaInterface interface {
- // SwaggerSchema retrieves and parses the swagger API schema the server supports.
- SwaggerSchema(version schema.GroupVersion) (*swagger.ApiDeclaration, error)
-}
-
// OpenAPISchemaInterface has a method to retrieve the open API schema.
type OpenAPISchemaInterface interface {
// OpenAPISchema retrieves and parses the swagger API schema the server supports.
- OpenAPISchema() (*spec.Swagger, error)
+ OpenAPISchema() (*openapi_v2.Document, error)
}
// DiscoveryClient implements the functions that discover server-supported API groups,
@@ -150,9 +145,9 @@ func (d *DiscoveryClient) ServerGroups() (apiGroupList *metav1.APIGroupList, err
apiGroupList = &metav1.APIGroupList{}
}
- // append the group retrieved from /api to the list if not empty
+ // prepend the group retrieved from /api to the list if not empty
if len(v.Versions) != 0 {
- apiGroupList.Groups = append(apiGroupList.Groups, apiGroup)
+ apiGroupList.Groups = append([]metav1.APIGroup{apiGroup}, apiGroupList.Groups...)
}
return apiGroupList, nil
}
@@ -332,54 +327,18 @@ func (d *DiscoveryClient) ServerVersion() (*version.Info, error) {
return &info, nil
}
-// SwaggerSchema retrieves and parses the swagger API schema the server supports.
-// TODO: Replace usages with Open API. Tracked in https://github.com/kubernetes/kubernetes/issues/44589
-func (d *DiscoveryClient) SwaggerSchema(version schema.GroupVersion) (*swagger.ApiDeclaration, error) {
- if version.Empty() {
- return nil, fmt.Errorf("groupVersion cannot be empty")
- }
-
- groupList, err := d.ServerGroups()
+// OpenAPISchema fetches the open api schema using a rest client and parses the proto.
+func (d *DiscoveryClient) OpenAPISchema() (*openapi_v2.Document, error) {
+ data, err := d.restClient.Get().AbsPath("/swagger-2.0.0.pb-v1").Do().Raw()
if err != nil {
return nil, err
}
- groupVersions := metav1.ExtractGroupVersions(groupList)
- // This check also takes care the case that kubectl is newer than the running endpoint
- if stringDoesntExistIn(version.String(), groupVersions) {
- return nil, fmt.Errorf("API version: %v is not supported by the server. Use one of: %v", version, groupVersions)
- }
- var path string
- if len(d.LegacyPrefix) > 0 && version == v1.SchemeGroupVersion {
- path = "/swaggerapi" + d.LegacyPrefix + "/" + version.Version
- } else {
- path = "/swaggerapi/apis/" + version.Group + "/" + version.Version
- }
-
- body, err := d.restClient.Get().AbsPath(path).Do().Raw()
+ document := &openapi_v2.Document{}
+ err = proto.Unmarshal(data, document)
if err != nil {
return nil, err
}
- var schema swagger.ApiDeclaration
- err = json.Unmarshal(body, &schema)
- if err != nil {
- return nil, fmt.Errorf("got '%s': %v", string(body), err)
- }
- return &schema, nil
-}
-
-// OpenAPISchema fetches the open api schema using a rest client and parses the json.
-// Warning: this is very expensive (~1.2s)
-func (d *DiscoveryClient) OpenAPISchema() (*spec.Swagger, error) {
- data, err := d.restClient.Get().AbsPath("/swagger.json").Do().Raw()
- if err != nil {
- return nil, err
- }
- msg := json.RawMessage(data)
- doc, err := loads.Analyzed(msg, "")
- if err != nil {
- return nil, err
- }
- return doc.Spec(), err
+ return document, nil
}
// withRetries retries the given recovery function in case the groups supported by the server change after ServerGroup() returns.
@@ -420,7 +379,7 @@ func NewDiscoveryClientForConfig(c *restclient.Config) (*DiscoveryClient, error)
return &DiscoveryClient{restClient: client, LegacyPrefix: "/api"}, err
}
-// NewDiscoveryClientForConfig creates a new DiscoveryClient for the given config. If
+// NewDiscoveryClientForConfigOrDie creates a new DiscoveryClient for the given config. If
// there is an error, it panics.
func NewDiscoveryClientForConfigOrDie(c *restclient.Config) *DiscoveryClient {
client, err := NewDiscoveryClientForConfig(c)
@@ -431,20 +390,11 @@ func NewDiscoveryClientForConfigOrDie(c *restclient.Config) *DiscoveryClient {
}
-// New creates a new DiscoveryClient for the given RESTClient.
+// NewDiscoveryClient returns a new DiscoveryClient for the given RESTClient.
func NewDiscoveryClient(c restclient.Interface) *DiscoveryClient {
return &DiscoveryClient{restClient: c, LegacyPrefix: "/api"}
}
-func stringDoesntExistIn(str string, slice []string) bool {
- for _, s := range slice {
- if s == str {
- return false
- }
- }
- return true
-}
-
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *DiscoveryClient) RESTClient() restclient.Interface {
diff --git a/vendor/k8s.io/client-go/discovery/restmapper.go b/vendor/k8s.io/client-go/discovery/restmapper.go
index 756669001..6d1de8c1b 100644
--- a/vendor/k8s.io/client-go/discovery/restmapper.go
+++ b/vendor/k8s.io/client-go/discovery/restmapper.go
@@ -49,6 +49,7 @@ func NewRESTMapper(groupResources []*APIGroupResources, versionInterfaces meta.V
for _, group := range groupResources {
groupPriority = append(groupPriority, group.Group.Name)
+ // Make sure the preferred version comes first
if len(group.Group.PreferredVersion.Version) != 0 {
preferred := group.Group.PreferredVersion.Version
if _, ok := group.VersionedResources[preferred]; ok {
@@ -72,6 +73,21 @@ func NewRESTMapper(groupResources []*APIGroupResources, versionInterfaces meta.V
continue
}
+ // Add non-preferred versions after the preferred version, in case there are resources that only exist in those versions
+ if discoveryVersion.Version != group.Group.PreferredVersion.Version {
+ resourcePriority = append(resourcePriority, schema.GroupVersionResource{
+ Group: group.Group.Name,
+ Version: discoveryVersion.Version,
+ Resource: meta.AnyResource,
+ })
+
+ kindPriority = append(kindPriority, schema.GroupVersionKind{
+ Group: group.Group.Name,
+ Version: discoveryVersion.Version,
+ Kind: meta.AnyKind,
+ })
+ }
+
gv := schema.GroupVersion{Group: group.Group.Name, Version: discoveryVersion.Version}
versionMapper := meta.NewDefaultRESTMapper([]schema.GroupVersion{gv}, versionInterfaces)
@@ -80,8 +96,19 @@ func NewRESTMapper(groupResources []*APIGroupResources, versionInterfaces meta.V
if !resource.Namespaced {
scope = meta.RESTScopeRoot
}
- versionMapper.Add(gv.WithKind(resource.Kind), scope)
- // TODO only do this if it supports listing
+
+ // this is for legacy resources and servers which don't list singular forms. For those we must still guess.
+ if len(resource.SingularName) == 0 {
+ versionMapper.Add(gv.WithKind(resource.Kind), scope)
+ // TODO this is producing unsafe guesses that don't actually work, but it matches previous behavior
+ versionMapper.Add(gv.WithKind(resource.Kind+"List"), scope)
+ continue
+ }
+
+ plural := gv.WithResource(resource.Name)
+ singular := gv.WithResource(resource.SingularName)
+ versionMapper.AddSpecific(gv.WithKind(resource.Kind), plural, singular, scope)
+ // TODO this is producing unsafe guesses that don't actually work, but it matches previous behavior
versionMapper.Add(gv.WithKind(resource.Kind+"List"), scope)
}
// TODO why is this type not in discovery (at least for "v1")
diff --git a/vendor/k8s.io/client-go/discovery/unstructured.go b/vendor/k8s.io/client-go/discovery/unstructured.go
index ee72d668b..fa7f2ec06 100644
--- a/vendor/k8s.io/client-go/discovery/unstructured.go
+++ b/vendor/k8s.io/client-go/discovery/unstructured.go
@@ -17,22 +17,28 @@ limitations under the License.
package discovery
import (
- "fmt"
+ "reflect"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
-// UnstructuredObjectTyper provides a runtime.ObjectTyper implmentation for
+// UnstructuredObjectTyper provides a runtime.ObjectTyper implementation for
// runtime.Unstructured object based on discovery information.
type UnstructuredObjectTyper struct {
registered map[schema.GroupVersionKind]bool
+ typers []runtime.ObjectTyper
}
// NewUnstructuredObjectTyper returns a runtime.ObjectTyper for
-// unstructred objects based on discovery information.
-func NewUnstructuredObjectTyper(groupResources []*APIGroupResources) *UnstructuredObjectTyper {
- dot := &UnstructuredObjectTyper{registered: make(map[schema.GroupVersionKind]bool)}
+// unstructured objects based on discovery information. It accepts a list of fallback typers
+// for handling objects that are not runtime.Unstructured. It does not delegate the Recognizes
+// check, only ObjectKinds.
+func NewUnstructuredObjectTyper(groupResources []*APIGroupResources, typers ...runtime.ObjectTyper) *UnstructuredObjectTyper {
+ dot := &UnstructuredObjectTyper{
+ registered: make(map[schema.GroupVersionKind]bool),
+ typers: typers,
+ }
for _, group := range groupResources {
for _, discoveryVersion := range group.Group.Versions {
resources, ok := group.VersionedResources[discoveryVersion.Version]
@@ -49,29 +55,35 @@ func NewUnstructuredObjectTyper(groupResources []*APIGroupResources) *Unstructur
return dot
}
-// ObjectKind returns the group,version,kind of the provided object, or an error
-// if the object in not runtime.Unstructured or has no group,version,kind
-// information.
-func (d *UnstructuredObjectTyper) ObjectKind(obj runtime.Object) (schema.GroupVersionKind, error) {
- if _, ok := obj.(runtime.Unstructured); !ok {
- return schema.GroupVersionKind{}, fmt.Errorf("type %T is invalid for dynamic object typer", obj)
- }
-
- return obj.GetObjectKind().GroupVersionKind(), nil
-}
-
// ObjectKinds returns a slice of one element with the group,version,kind of the
// provided object, or an error if the object is not runtime.Unstructured or
// has no group,version,kind information. unversionedType will always be false
// because runtime.Unstructured object should always have group,version,kind
// information set.
func (d *UnstructuredObjectTyper) ObjectKinds(obj runtime.Object) (gvks []schema.GroupVersionKind, unversionedType bool, err error) {
- gvk, err := d.ObjectKind(obj)
- if err != nil {
- return nil, false, err
+ if _, ok := obj.(runtime.Unstructured); ok {
+ gvk := obj.GetObjectKind().GroupVersionKind()
+ if len(gvk.Kind) == 0 {
+ return nil, false, runtime.NewMissingKindErr("object has no kind field ")
+ }
+ if len(gvk.Version) == 0 {
+ return nil, false, runtime.NewMissingVersionErr("object has no apiVersion field")
+ }
+ return []schema.GroupVersionKind{gvk}, false, nil
}
-
- return []schema.GroupVersionKind{gvk}, false, nil
+ var lastErr error
+ for _, typer := range d.typers {
+ gvks, unversioned, err := typer.ObjectKinds(obj)
+ if err != nil {
+ lastErr = err
+ continue
+ }
+ return gvks, unversioned, nil
+ }
+ if lastErr == nil {
+ lastErr = runtime.NewNotRegisteredErrForType(reflect.TypeOf(obj))
+ }
+ return nil, false, lastErr
}
// Recognizes returns true if the provided group,version,kind was in the
@@ -80,16 +92,4 @@ func (d *UnstructuredObjectTyper) Recognizes(gvk schema.GroupVersionKind) bool {
return d.registered[gvk]
}
-// IsUnversioned returns false always because runtime.Unstructured objects
-// should always have group,version,kind information set. ok will be true if the
-// object's group,version,kind is api.Registry.
-func (d *UnstructuredObjectTyper) IsUnversioned(obj runtime.Object) (unversioned bool, ok bool) {
- gvk, err := d.ObjectKind(obj)
- if err != nil {
- return false, false
- }
-
- return false, d.registered[gvk]
-}
-
var _ runtime.ObjectTyper = &UnstructuredObjectTyper{}