diff --git a/pkg/kubectl/cmd/testing/fake.go b/pkg/kubectl/cmd/testing/fake.go index 64e3f8c7703..9a1bbf86a37 100644 --- a/pkg/kubectl/cmd/testing/fake.go +++ b/pkg/kubectl/cmd/testing/fake.go @@ -269,7 +269,8 @@ func NewTestFactory() *TestFactory { clientConfig := clientcmd.NewInteractiveDeferredLoadingClientConfig(loadingRules, overrides, fallbackReader) configFlags := cmdutil.NewTestConfigFlags(). - WithClientConfig(clientConfig) + WithClientConfig(clientConfig). + WithRESTMapper(testRESTMapper()) return &TestFactory{ Factory: cmdutil.NewFactory(configFlags), @@ -428,7 +429,7 @@ func (f *TestFactory) ClientSetForVersion(requiredVersion *schema.GroupVersion) return f.ClientSet() } -func (f *TestFactory) RESTMapper() (meta.RESTMapper, error) { +func testRESTMapper() meta.RESTMapper { groupResources := testDynamicResources() mapper := restmapper.NewDiscoveryRESTMapper(groupResources) // for backwards compatibility with existing tests, allow rest mappings from the scheme to show up @@ -440,10 +441,9 @@ func (f *TestFactory) RESTMapper() (meta.RESTMapper, error) { }, } - // TODO: should probably be the external scheme fakeDs := &fakeCachedDiscoveryClient{} expander := restmapper.NewShortcutExpander(mapper, fakeDs) - return expander, nil + return expander } func (f *TestFactory) LogsForObject(object, options runtime.Object, timeout time.Duration) (*restclient.Request, error) { diff --git a/pkg/kubectl/cmd/util/config_flags.go b/pkg/kubectl/cmd/util/config_flags.go index 6c413ad39e4..59f89697d5a 100644 --- a/pkg/kubectl/cmd/util/config_flags.go +++ b/pkg/kubectl/cmd/util/config_flags.go @@ -24,12 +24,16 @@ import ( "github.com/spf13/pflag" + "k8s.io/apimachinery/pkg/api/meta" utilflag "k8s.io/apiserver/pkg/util/flag" "k8s.io/client-go/discovery" "k8s.io/client-go/rest" + "k8s.io/client-go/restmapper" "k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/util/homedir" + "fmt" + "k8s.io/kubernetes/pkg/kubectl/cmd/util/transport" ) @@ -198,6 +202,18 @@ func (f *ConfigFlags) ToDiscoveryClient() (discovery.CachedDiscoveryInterface, e return NewCachedDiscoveryClient(discoveryClient, cacheDir, time.Duration(10*time.Minute)), nil } +// RESTMapper returns a mapper. +func (f *ConfigFlags) ToRESTMapper() (meta.RESTMapper, error) { + discoveryClient, err := f.ToDiscoveryClient() + if err != nil { + return nil, err + } + + mapper := restmapper.NewDeferredDiscoveryRESTMapper(discoveryClient) + expander := restmapper.NewShortcutExpander(mapper, discoveryClient) + return expander, nil +} + func (f *ConfigFlags) AddFlags(flags *pflag.FlagSet) { flags.SetNormalizeFunc(utilflag.WarnWordSepNormalizeFunc) // Warn for "_" flags @@ -300,6 +316,7 @@ func stringptr(val string) *string { type TestConfigFlags struct { clientConfig clientcmd.ClientConfig discoveryClient discovery.CachedDiscoveryInterface + restMapper meta.RESTMapper } func (f *TestConfigFlags) ToRawKubeConfigLoader() clientcmd.ClientConfig { @@ -317,11 +334,28 @@ func (f *TestConfigFlags) ToDiscoveryClient() (discovery.CachedDiscoveryInterfac return f.discoveryClient, nil } +func (f *TestConfigFlags) ToRESTMapper() (meta.RESTMapper, error) { + if f.restMapper != nil { + return f.restMapper, nil + } + if f.discoveryClient != nil { + mapper := restmapper.NewDeferredDiscoveryRESTMapper(f.discoveryClient) + expander := restmapper.NewShortcutExpander(mapper, f.discoveryClient) + return expander, nil + } + return nil, fmt.Errorf("no restmapper") +} + func (f *TestConfigFlags) WithClientConfig(clientConfig clientcmd.ClientConfig) *TestConfigFlags { f.clientConfig = clientConfig return f } +func (f *TestConfigFlags) WithRESTMapper(mapper meta.RESTMapper) *TestConfigFlags { + f.restMapper = mapper + return f +} + func (f *TestConfigFlags) WithDiscoveryClient(c discovery.CachedDiscoveryInterface) *TestConfigFlags { f.discoveryClient = c return f diff --git a/pkg/kubectl/cmd/util/factory.go b/pkg/kubectl/cmd/util/factory.go index 049b5b8ecfe..d54b4fc72ce 100644 --- a/pkg/kubectl/cmd/util/factory.go +++ b/pkg/kubectl/cmd/util/factory.go @@ -98,6 +98,9 @@ type ClientAccessFactory interface { // KubernetesClientSet gives you back an external clientset KubernetesClientSet() (*kubernetes.Clientset, error) + // Returns interfaces for dealing with arbitrary runtime.Objects. + RESTMapper() (meta.RESTMapper, error) + // Returns a RESTClient for accessing Kubernetes resources or an error. RESTClient() (*restclient.RESTClient, error) // Returns a client.Config for accessing the Kubernetes server. @@ -165,8 +168,6 @@ type ClientAccessFactory interface { // ObjectMappingFactory holds the second level of factory methods. These functions depend upon ClientAccessFactory methods. // Generally they provide object typing and functions that build requests based on the negotiated clients. type ObjectMappingFactory interface { - // Returns interfaces for dealing with arbitrary runtime.Objects. - RESTMapper() (meta.RESTMapper, error) // Returns interface for expanding categories like `all`. CategoryExpander() categories.CategoryExpander // Returns a RESTClient for working with the specified RESTMapping or an error. This is intended diff --git a/pkg/kubectl/cmd/util/factory_builder.go b/pkg/kubectl/cmd/util/factory_builder.go index 166659470db..6e9eedacd32 100644 --- a/pkg/kubectl/cmd/util/factory_builder.go +++ b/pkg/kubectl/cmd/util/factory_builder.go @@ -45,7 +45,7 @@ func NewBuilderFactory(clientAccessFactory ClientAccessFactory, objectMappingFac // NewBuilder returns a new resource builder for structured api objects. func (f *ring2Factory) NewBuilder() *resource.Builder { - mapper, mapperErr := f.objectMappingFactory.RESTMapper() + mapper, mapperErr := f.clientAccessFactory.RESTMapper() categoryExpander := f.objectMappingFactory.CategoryExpander() return resource.NewBuilder( @@ -84,7 +84,7 @@ func (f *ring2Factory) ScaleClient() (scaleclient.ScalesGetter, error) { return nil, err } resolver := scaleclient.NewDiscoveryScaleKindResolver(discoClient) - mapper, err := f.objectMappingFactory.RESTMapper() + mapper, err := f.clientAccessFactory.RESTMapper() if err != nil { return nil, err } diff --git a/pkg/kubectl/cmd/util/factory_client_access.go b/pkg/kubectl/cmd/util/factory_client_access.go index e7be0ab13d6..e2c2118caa8 100644 --- a/pkg/kubectl/cmd/util/factory_client_access.go +++ b/pkg/kubectl/cmd/util/factory_client_access.go @@ -64,6 +64,7 @@ import ( type RESTClientGetter interface { ToRESTConfig() (*restclient.Config, error) ToDiscoveryClient() (discovery.CachedDiscoveryInterface, error) + ToRESTMapper() (meta.RESTMapper, error) ToRawKubeConfigLoader() clientcmd.ClientConfig } @@ -141,6 +142,11 @@ func (f *ring0Factory) ClientConfig() (*restclient.Config, error) { setKubernetesDefaults(clientConfig) return clientConfig, nil } + +func (f *ring0Factory) RESTMapper() (meta.RESTMapper, error) { + return f.clientGetter.ToRESTMapper() +} + func (f *ring0Factory) BareClientConfig() (*restclient.Config, error) { return f.clientGetter.ToRESTConfig() } diff --git a/pkg/kubectl/cmd/util/factory_object_mapping.go b/pkg/kubectl/cmd/util/factory_object_mapping.go index bfbf9c1799b..758c578a5f6 100644 --- a/pkg/kubectl/cmd/util/factory_object_mapping.go +++ b/pkg/kubectl/cmd/util/factory_object_mapping.go @@ -40,7 +40,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/dynamic" restclient "k8s.io/client-go/rest" - "k8s.io/client-go/restmapper" "k8s.io/kubernetes/pkg/apis/apps" "k8s.io/kubernetes/pkg/apis/batch" api "k8s.io/kubernetes/pkg/apis/core" @@ -76,20 +75,6 @@ func NewObjectMappingFactory(clientAccessFactory ClientAccessFactory) ObjectMapp return f } -// RESTMapper returns a mapper. -func (f *ring1Factory) RESTMapper() (meta.RESTMapper, error) { - discoveryClient, err := f.clientAccessFactory.DiscoveryClient() - if err != nil { - return nil, err - } - - // allow conversion between typed and unstructured objects - mapper := restmapper.NewDeferredDiscoveryRESTMapper(discoveryClient) - // TODO: should this also indicate it recognizes typed objects? - expander := restmapper.NewShortcutExpander(mapper, discoveryClient) - return expander, nil -} - func (f *ring1Factory) CategoryExpander() categories.CategoryExpander { legacyExpander := categories.LegacyCategoryExpander