mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	Add discovery mapper and dynamic typer to kubectl
This commit is contained in:
		
							
								
								
									
										31
									
								
								pkg/api/meta/unstructured.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								pkg/api/meta/unstructured.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2016 The Kubernetes Authors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					limitations under the License.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package meta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/api/unversioned"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/runtime"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// InterfacesForUnstructured returns VersionInterfaces suitable for
 | 
				
			||||||
 | 
					// dealing with runtime.Unstructured objects.
 | 
				
			||||||
 | 
					func InterfacesForUnstructured(unversioned.GroupVersion) (*VersionInterfaces, error) {
 | 
				
			||||||
 | 
						return &VersionInterfaces{
 | 
				
			||||||
 | 
							ObjectConvertor:  &runtime.UnstructuredObjectConverter{},
 | 
				
			||||||
 | 
							MetadataAccessor: NewAccessor(),
 | 
				
			||||||
 | 
						}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										95
									
								
								pkg/client/typed/discovery/unstructured.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								pkg/client/typed/discovery/unstructured.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,95 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2016 The Kubernetes Authors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					limitations under the License.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package discovery
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/api/unversioned"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/runtime"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// UnstructuredObjectTyper provides a runtime.ObjectTyper implmentation for
 | 
				
			||||||
 | 
					// runtime.Unstructured object based on discovery information.
 | 
				
			||||||
 | 
					type UnstructuredObjectTyper struct {
 | 
				
			||||||
 | 
						registered map[unversioned.GroupVersionKind]bool
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewUnstructuredObjectTyper returns a runtime.ObjectTyper for
 | 
				
			||||||
 | 
					// unstructred objects based on discovery information.
 | 
				
			||||||
 | 
					func NewUnstructuredObjectTyper(groupResources []*APIGroupResources) *UnstructuredObjectTyper {
 | 
				
			||||||
 | 
						dot := &UnstructuredObjectTyper{registered: make(map[unversioned.GroupVersionKind]bool)}
 | 
				
			||||||
 | 
						for _, group := range groupResources {
 | 
				
			||||||
 | 
							for _, discoveryVersion := range group.Group.Versions {
 | 
				
			||||||
 | 
								resources, ok := group.VersionedResources[discoveryVersion.Version]
 | 
				
			||||||
 | 
								if !ok {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								gv := unversioned.GroupVersion{Group: group.Group.Name, Version: discoveryVersion.Version}
 | 
				
			||||||
 | 
								for _, resource := range resources {
 | 
				
			||||||
 | 
									dot.registered[gv.WithKind(resource.Kind)] = true
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						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) (unversioned.GroupVersionKind, error) {
 | 
				
			||||||
 | 
						if _, ok := obj.(*runtime.Unstructured); !ok {
 | 
				
			||||||
 | 
							return unversioned.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 []unversioned.GroupVersionKind, unversionedType bool, err error) {
 | 
				
			||||||
 | 
						gvk, err := d.ObjectKind(obj)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, false, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return []unversioned.GroupVersionKind{gvk}, false, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Recognizes returns true if the provided group,version,kind was in the
 | 
				
			||||||
 | 
					// discovery information.
 | 
				
			||||||
 | 
					func (d *UnstructuredObjectTyper) Recognizes(gvk unversioned.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 registered.
 | 
				
			||||||
 | 
					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{}
 | 
				
			||||||
@@ -34,6 +34,7 @@ import (
 | 
				
			|||||||
	"k8s.io/kubernetes/pkg/api/unversioned"
 | 
						"k8s.io/kubernetes/pkg/api/unversioned"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/api/validation"
 | 
						"k8s.io/kubernetes/pkg/api/validation"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/client/restclient"
 | 
						"k8s.io/kubernetes/pkg/client/restclient"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/client/typed/discovery"
 | 
				
			||||||
	client "k8s.io/kubernetes/pkg/client/unversioned"
 | 
						client "k8s.io/kubernetes/pkg/client/unversioned"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/client/unversioned/fake"
 | 
						"k8s.io/kubernetes/pkg/client/unversioned/fake"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/kubectl"
 | 
						"k8s.io/kubernetes/pkg/kubectl"
 | 
				
			||||||
@@ -275,6 +276,13 @@ func NewAPIFactory() (*cmdutil.Factory, *testFactory, runtime.Codec, runtime.Neg
 | 
				
			|||||||
		Object: func(discovery bool) (meta.RESTMapper, runtime.ObjectTyper) {
 | 
							Object: func(discovery bool) (meta.RESTMapper, runtime.ObjectTyper) {
 | 
				
			||||||
			return testapi.Default.RESTMapper(), api.Scheme
 | 
								return testapi.Default.RESTMapper(), api.Scheme
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							UnstructuredObject: func() (meta.RESTMapper, runtime.ObjectTyper, error) {
 | 
				
			||||||
 | 
								groupResources := testDynamicResources()
 | 
				
			||||||
 | 
								mapper := discovery.NewRESTMapper(groupResources, meta.InterfacesForUnstructured)
 | 
				
			||||||
 | 
								typer := discovery.NewUnstructuredObjectTyper(groupResources)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return kubectl.ShortcutExpander{RESTMapper: mapper}, typer, nil
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
		Client: func() (*client.Client, error) {
 | 
							Client: func() (*client.Client, error) {
 | 
				
			||||||
			// Swap out the HTTP client out of the client with the fake's version.
 | 
								// Swap out the HTTP client out of the client with the fake's version.
 | 
				
			||||||
			fakeClient := t.Client.(*fake.RESTClient)
 | 
								fakeClient := t.Client.(*fake.RESTClient)
 | 
				
			||||||
@@ -286,6 +294,9 @@ func NewAPIFactory() (*cmdutil.Factory, *testFactory, runtime.Codec, runtime.Neg
 | 
				
			|||||||
		ClientForMapping: func(*meta.RESTMapping) (resource.RESTClient, error) {
 | 
							ClientForMapping: func(*meta.RESTMapping) (resource.RESTClient, error) {
 | 
				
			||||||
			return t.Client, t.Err
 | 
								return t.Client, t.Err
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							UnstructuredClientForMapping: func(*meta.RESTMapping) (resource.RESTClient, error) {
 | 
				
			||||||
 | 
								return t.Client, t.Err
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
		Decoder: func(bool) runtime.Decoder {
 | 
							Decoder: func(bool) runtime.Decoder {
 | 
				
			||||||
			return testapi.Default.Codec()
 | 
								return testapi.Default.Codec()
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -53,6 +53,8 @@ import (
 | 
				
			|||||||
	"k8s.io/kubernetes/pkg/apis/policy"
 | 
						"k8s.io/kubernetes/pkg/apis/policy"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/apis/rbac"
 | 
						"k8s.io/kubernetes/pkg/apis/rbac"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/client/restclient"
 | 
						"k8s.io/kubernetes/pkg/client/restclient"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/client/typed/discovery"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/client/typed/dynamic"
 | 
				
			||||||
	client "k8s.io/kubernetes/pkg/client/unversioned"
 | 
						client "k8s.io/kubernetes/pkg/client/unversioned"
 | 
				
			||||||
	clientset "k8s.io/kubernetes/pkg/client/unversioned/adapters/internalclientset"
 | 
						clientset "k8s.io/kubernetes/pkg/client/unversioned/adapters/internalclientset"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
 | 
						"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
 | 
				
			||||||
@@ -83,6 +85,9 @@ type Factory struct {
 | 
				
			|||||||
	// Returns interfaces for dealing with arbitrary runtime.Objects. If thirdPartyDiscovery is true, performs API calls
 | 
						// Returns interfaces for dealing with arbitrary runtime.Objects. If thirdPartyDiscovery is true, performs API calls
 | 
				
			||||||
	// to discovery dynamic API objects registered by third parties.
 | 
						// to discovery dynamic API objects registered by third parties.
 | 
				
			||||||
	Object func(thirdPartyDiscovery bool) (meta.RESTMapper, runtime.ObjectTyper)
 | 
						Object func(thirdPartyDiscovery bool) (meta.RESTMapper, runtime.ObjectTyper)
 | 
				
			||||||
 | 
						// Returns interfaces for dealing with arbitrary
 | 
				
			||||||
 | 
						// runtime.Unstructured. This performs API calls to discover types.
 | 
				
			||||||
 | 
						UnstructuredObject func() (meta.RESTMapper, runtime.ObjectTyper, error)
 | 
				
			||||||
	// Returns interfaces for decoding objects - if toInternal is set, decoded objects will be converted
 | 
						// Returns interfaces for decoding objects - if toInternal is set, decoded objects will be converted
 | 
				
			||||||
	// into their internal form (if possible). Eventually the internal form will be removed as an option,
 | 
						// into their internal form (if possible). Eventually the internal form will be removed as an option,
 | 
				
			||||||
	// and only versioned objects will be returned.
 | 
						// and only versioned objects will be returned.
 | 
				
			||||||
@@ -96,6 +101,8 @@ type Factory struct {
 | 
				
			|||||||
	// Returns a RESTClient for working with the specified RESTMapping or an error. This is intended
 | 
						// Returns a RESTClient for working with the specified RESTMapping or an error. This is intended
 | 
				
			||||||
	// for working with arbitrary resources and is not guaranteed to point to a Kubernetes APIServer.
 | 
						// for working with arbitrary resources and is not guaranteed to point to a Kubernetes APIServer.
 | 
				
			||||||
	ClientForMapping func(mapping *meta.RESTMapping) (resource.RESTClient, error)
 | 
						ClientForMapping func(mapping *meta.RESTMapping) (resource.RESTClient, error)
 | 
				
			||||||
 | 
						// Returns a RESTClient for working with Unstructured objects.
 | 
				
			||||||
 | 
						UnstructuredClientForMapping func(mapping *meta.RESTMapping) (resource.RESTClient, error)
 | 
				
			||||||
	// Returns a Describer for displaying the specified RESTMapping type or an error.
 | 
						// Returns a Describer for displaying the specified RESTMapping type or an error.
 | 
				
			||||||
	Describer func(mapping *meta.RESTMapping) (kubectl.Describer, error)
 | 
						Describer func(mapping *meta.RESTMapping) (kubectl.Describer, error)
 | 
				
			||||||
	// Returns a Printer for formatting objects of the given type or an error.
 | 
						// Returns a Printer for formatting objects of the given type or an error.
 | 
				
			||||||
@@ -360,6 +367,40 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			return priorityRESTMapper, api.Scheme
 | 
								return priorityRESTMapper, api.Scheme
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							UnstructuredObject: func() (meta.RESTMapper, runtime.ObjectTyper, error) {
 | 
				
			||||||
 | 
								cfg, err := clients.ClientConfigForVersion(nil)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return nil, nil, err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								dc, err := discovery.NewDiscoveryClientForConfig(cfg)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return nil, nil, err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								groupResources, err := discovery.GetAPIGroupResources(dc)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return nil, nil, err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Register unknown APIs as third party for now to make
 | 
				
			||||||
 | 
								// validation happy. TODO perhaps make a dynamic schema
 | 
				
			||||||
 | 
								// validator to avoid this.
 | 
				
			||||||
 | 
								for _, group := range groupResources {
 | 
				
			||||||
 | 
									for _, version := range group.Group.Versions {
 | 
				
			||||||
 | 
										gv := unversioned.GroupVersion{Group: group.Group.Name, Version: version.Version}
 | 
				
			||||||
 | 
										if !registered.IsRegisteredVersion(gv) {
 | 
				
			||||||
 | 
											registered.AddThirdPartyAPIGroupVersions(gv)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								mapper := discovery.NewRESTMapper(groupResources, meta.InterfacesForUnstructured)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								typer := discovery.NewUnstructuredObjectTyper(groupResources)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return kubectl.ShortcutExpander{RESTMapper: mapper}, typer, nil
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
		Client: func() (*client.Client, error) {
 | 
							Client: func() (*client.Client, error) {
 | 
				
			||||||
			return clients.ClientForVersion(nil)
 | 
								return clients.ClientForVersion(nil)
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
@@ -391,6 +432,23 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			return restclient.RESTClientFor(cfg)
 | 
								return restclient.RESTClientFor(cfg)
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							UnstructuredClientForMapping: func(mapping *meta.RESTMapping) (resource.RESTClient, error) {
 | 
				
			||||||
 | 
								cfg, err := clientConfig.ClientConfig()
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return nil, err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if err := restclient.SetKubernetesDefaults(cfg); err != nil {
 | 
				
			||||||
 | 
									return nil, err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								cfg.APIPath = "/apis"
 | 
				
			||||||
 | 
								if mapping.GroupVersionKind.Group == api.GroupName {
 | 
				
			||||||
 | 
									cfg.APIPath = "/api"
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								gv := mapping.GroupVersionKind.GroupVersion()
 | 
				
			||||||
 | 
								cfg.ContentConfig = dynamic.ContentConfig()
 | 
				
			||||||
 | 
								cfg.GroupVersion = &gv
 | 
				
			||||||
 | 
								return restclient.RESTClientFor(cfg)
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
		Describer: func(mapping *meta.RESTMapping) (kubectl.Describer, error) {
 | 
							Describer: func(mapping *meta.RESTMapping) (kubectl.Describer, error) {
 | 
				
			||||||
			mappingVersion := mapping.GroupVersionKind.GroupVersion()
 | 
								mappingVersion := mapping.GroupVersionKind.GroupVersion()
 | 
				
			||||||
			if mapping.GroupVersionKind.Group == federation.GroupName {
 | 
								if mapping.GroupVersionKind.Group == federation.GroupName {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user