From 5432ef5c4557fc47c97f631ac3b23738bbd27115 Mon Sep 17 00:00:00 2001 From: David Eads Date: Fri, 27 Apr 2018 09:27:19 -0400 Subject: [PATCH] divide statically known typer from dynamically derive restmapper --- pkg/kubectl/cmd/apply_set_last_applied.go | 3 +-- pkg/kubectl/cmd/auth/BUILD | 1 + pkg/kubectl/cmd/auth/cani.go | 2 +- pkg/kubectl/cmd/autoscale.go | 4 +-- pkg/kubectl/cmd/create/create.go | 5 ++-- .../cmd/create/create_clusterrole_test.go | 2 +- pkg/kubectl/cmd/create/create_role.go | 2 +- pkg/kubectl/cmd/create/create_role_test.go | 2 +- pkg/kubectl/cmd/drain_test.go | 2 +- pkg/kubectl/cmd/explain.go | 2 +- pkg/kubectl/cmd/expose.go | 3 +-- pkg/kubectl/cmd/rollout/BUILD | 2 +- pkg/kubectl/cmd/rollout/rollout_pause.go | 4 +-- pkg/kubectl/cmd/rollout/rollout_resume.go | 4 +-- pkg/kubectl/cmd/rollout/rollout_undo.go | 4 +-- pkg/kubectl/cmd/run.go | 5 ++-- pkg/kubectl/cmd/set/set_selector.go | 2 +- pkg/kubectl/cmd/testing/fake.go | 7 +++--- pkg/kubectl/cmd/util/factory.go | 2 +- pkg/kubectl/cmd/util/factory_builder.go | 4 +-- .../cmd/util/factory_object_mapping.go | 21 ++++------------ pkg/kubectl/resource/BUILD | 3 +++ pkg/kubectl/resource/builder.go | 5 ++++ pkg/kubectl/resource/visitor.go | 2 +- .../k8s.io/apimachinery/pkg/api/meta/lazy.go | 25 +++---------------- test/integration/apiserver/print_test.go | 2 +- .../etcd/etcd_storage_path_test.go | 2 +- 27 files changed, 47 insertions(+), 75 deletions(-) diff --git a/pkg/kubectl/cmd/apply_set_last_applied.go b/pkg/kubectl/cmd/apply_set_last_applied.go index aa2b3cbd00..5f91266d1e 100644 --- a/pkg/kubectl/cmd/apply_set_last_applied.go +++ b/pkg/kubectl/cmd/apply_set_last_applied.go @@ -46,7 +46,6 @@ type SetLastAppliedOptions struct { Selector string InfoList []*resource.Info Mapper meta.RESTMapper - Typer runtime.ObjectTyper Namespace string EnforceNamespace bool DryRun bool @@ -117,7 +116,7 @@ func (o *SetLastAppliedOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) o.Output = cmdutil.GetFlagString(cmd, "output") o.ShortOutput = o.Output == "name" - o.Mapper, o.Typer = f.Object() + o.Mapper = f.RESTMapper() var err error o.Namespace, o.EnforceNamespace, err = f.DefaultNamespace() diff --git a/pkg/kubectl/cmd/auth/BUILD b/pkg/kubectl/cmd/auth/BUILD index 5aa487c498..987683660a 100644 --- a/pkg/kubectl/cmd/auth/BUILD +++ b/pkg/kubectl/cmd/auth/BUILD @@ -16,6 +16,7 @@ go_library( "//build/visible_to:pkg_kubectl_cmd_auth_CONSUMERS", ], deps = [ + "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/authorization:go_default_library", "//pkg/apis/rbac:go_default_library", "//pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion:go_default_library", diff --git a/pkg/kubectl/cmd/auth/cani.go b/pkg/kubectl/cmd/auth/cani.go index 2622addaf6..7640a473f4 100644 --- a/pkg/kubectl/cmd/auth/cani.go +++ b/pkg/kubectl/cmd/auth/cani.go @@ -127,7 +127,7 @@ func (o *CanIOptions) Complete(f cmdutil.Factory, args []string) error { break } resourceTokens := strings.SplitN(args[1], "/", 2) - restMapper, _ := f.Object() + restMapper := f.RESTMapper() o.Resource = o.resourceFor(restMapper, resourceTokens[0]) if len(resourceTokens) > 1 { o.ResourceName = resourceTokens[1] diff --git a/pkg/kubectl/cmd/autoscale.go b/pkg/kubectl/cmd/autoscale.go index 03c01350ba..a6452977cf 100644 --- a/pkg/kubectl/cmd/autoscale.go +++ b/pkg/kubectl/cmd/autoscale.go @@ -23,7 +23,6 @@ import ( "github.com/spf13/cobra" "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/kubernetes/pkg/api/legacyscheme" @@ -68,7 +67,6 @@ type AutoscaleOptions struct { EnforceNamespace bool Mapper meta.RESTMapper - Typer runtime.ObjectTyper ClientForMapping func(mapping *meta.RESTMapping) (resource.RESTClient, error) GeneratorFunc func(string, *meta.RESTMapping) (kubectl.StructuredGenerator, error) @@ -133,7 +131,7 @@ func (o *AutoscaleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args o.CreateAnnotation = cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag) o.Builder = f.NewBuilder() o.CanBeAutoscaled = f.CanBeAutoscaled - o.Mapper, o.Typer = f.Object() + o.Mapper = f.RESTMapper() o.ClientForMapping = f.ClientForMapping o.BuilderArgs = args o.RecordFlags.Complete(f.Command(cmd, false)) diff --git a/pkg/kubectl/cmd/create/create.go b/pkg/kubectl/cmd/create/create.go index dc028de11b..d4524e3979 100644 --- a/pkg/kubectl/cmd/create/create.go +++ b/pkg/kubectl/cmd/create/create.go @@ -389,9 +389,10 @@ func RunCreateSubcommand(f cmdutil.Factory, options *CreateSubcommandOptions) er if err != nil { return err } - mapper, typer := f.Object() + mapper := f.RESTMapper() if !options.DryRun { - gvks, _, err := typer.ObjectKinds(obj) + // create subcommands have compiled knowledge of things they create, so type them directly + gvks, _, err := legacyscheme.Scheme.ObjectKinds(obj) if err != nil { return err } diff --git a/pkg/kubectl/cmd/create/create_clusterrole_test.go b/pkg/kubectl/cmd/create/create_clusterrole_test.go index 69ea254e75..caddc639e1 100644 --- a/pkg/kubectl/cmd/create/create_clusterrole_test.go +++ b/pkg/kubectl/cmd/create/create_clusterrole_test.go @@ -437,7 +437,7 @@ func TestClusterRoleValidate(t *testing.T) { for name, test := range tests { t.Run(name, func(t *testing.T) { - test.clusterRoleOptions.Mapper, _ = tf.Object() + test.clusterRoleOptions.Mapper = tf.RESTMapper() err := test.clusterRoleOptions.Validate() if test.expectErr && err == nil { t.Errorf("%s: expect error happens, but validate passes.", name) diff --git a/pkg/kubectl/cmd/create/create_role.go b/pkg/kubectl/cmd/create/create_role.go index f3271e4c5f..29895d5182 100644 --- a/pkg/kubectl/cmd/create/create_role.go +++ b/pkg/kubectl/cmd/create/create_role.go @@ -205,7 +205,7 @@ func (o *CreateRoleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args o.ResourceNames = resourceNames // Complete other options for Run. - o.Mapper, _ = f.Object() + o.Mapper = f.RESTMapper() o.DryRun = cmdutil.GetDryRunFlag(cmd) o.OutputFormat = cmdutil.GetFlagString(cmd, "output") diff --git a/pkg/kubectl/cmd/create/create_role_test.go b/pkg/kubectl/cmd/create/create_role_test.go index e7937197f9..c1a75a3770 100644 --- a/pkg/kubectl/cmd/create/create_role_test.go +++ b/pkg/kubectl/cmd/create/create_role_test.go @@ -339,7 +339,7 @@ func TestValidate(t *testing.T) { } for name, test := range tests { - test.roleOptions.Mapper, _ = tf.Object() + test.roleOptions.Mapper = tf.RESTMapper() err := test.roleOptions.Validate() if test.expectErr && err == nil { t.Errorf("%s: expect error happens but validate passes.", name) diff --git a/pkg/kubectl/cmd/drain_test.go b/pkg/kubectl/cmd/drain_test.go index 86885aa1f0..34670e488d 100644 --- a/pkg/kubectl/cmd/drain_test.go +++ b/pkg/kubectl/cmd/drain_test.go @@ -836,7 +836,7 @@ func TestDeletePods(t *testing.T) { o := DrainOptions{ PrintFlags: printers.NewPrintFlags("drained"), } - o.mapper, _ = tf.Object() + o.mapper = tf.RESTMapper() o.Out = os.Stdout o.ToPrinter = func(operation string) (printers.ResourcePrinterFunc, error) { diff --git a/pkg/kubectl/cmd/explain.go b/pkg/kubectl/cmd/explain.go index 58e10c5922..cf4793fee6 100644 --- a/pkg/kubectl/cmd/explain.go +++ b/pkg/kubectl/cmd/explain.go @@ -94,7 +94,7 @@ func (o *ExplainOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error { o.Recursive = cmdutil.GetFlagBool(cmd, "recursive") o.ApiVersion = cmdutil.GetFlagString(cmd, "api-version") - o.Mapper, _ = f.Object() + o.Mapper = f.RESTMapper() var err error o.Schema, err = f.OpenAPISchema() diff --git a/pkg/kubectl/cmd/expose.go b/pkg/kubectl/cmd/expose.go index d1fada8b5a..a5d64a9589 100644 --- a/pkg/kubectl/cmd/expose.go +++ b/pkg/kubectl/cmd/expose.go @@ -96,7 +96,6 @@ type ExposeServiceOptions struct { Namespace string Mapper meta.RESTMapper - Typer runtime.ObjectTyper Builder *resource.Builder @@ -188,7 +187,7 @@ func (o *ExposeServiceOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) e o.MapBasedSelectorForObject = f.MapBasedSelectorForObject o.PortsForObject = f.PortsForObject o.ProtocolsForObject = f.ProtocolsForObject - o.Mapper, o.Typer = f.Object() + o.Mapper = f.RESTMapper() o.LabelsForObject = f.LabelsForObject o.Namespace, o.EnforceNamespace, err = f.DefaultNamespace() diff --git a/pkg/kubectl/cmd/rollout/BUILD b/pkg/kubectl/cmd/rollout/BUILD index ed141fe1be..df24db8989 100644 --- a/pkg/kubectl/cmd/rollout/BUILD +++ b/pkg/kubectl/cmd/rollout/BUILD @@ -19,6 +19,7 @@ go_library( "//build/visible_to:pkg_kubectl_cmd_rollout_CONSUMERS", ], deps = [ + "//pkg/api/legacyscheme:go_default_library", "//pkg/kubectl:go_default_library", "//pkg/kubectl/cmd/set:go_default_library", "//pkg/kubectl/cmd/templates:go_default_library", @@ -29,7 +30,6 @@ go_library( "//vendor/github.com/renstrom/dedent:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", diff --git a/pkg/kubectl/cmd/rollout/rollout_pause.go b/pkg/kubectl/cmd/rollout/rollout_pause.go index abb61ba69a..8071623622 100644 --- a/pkg/kubectl/cmd/rollout/rollout_pause.go +++ b/pkg/kubectl/cmd/rollout/rollout_pause.go @@ -23,7 +23,6 @@ import ( "github.com/spf13/cobra" "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/kubernetes/pkg/api/legacyscheme" @@ -42,7 +41,6 @@ type PauseConfig struct { Pauser func(info *resource.Info) ([]byte, error) Mapper meta.RESTMapper - Typer runtime.ObjectTyper Infos []*resource.Info Out io.Writer @@ -101,7 +99,7 @@ func (o *PauseConfig) CompletePause(f cmdutil.Factory, cmd *cobra.Command, out i return cmdutil.UsageErrorf(cmd, "%s", cmd.Use) } - o.Mapper, o.Typer = f.Object() + o.Mapper = f.RESTMapper() o.Pauser = f.Pauser o.Out = out diff --git a/pkg/kubectl/cmd/rollout/rollout_resume.go b/pkg/kubectl/cmd/rollout/rollout_resume.go index 77fd9d8700..65ee72765b 100644 --- a/pkg/kubectl/cmd/rollout/rollout_resume.go +++ b/pkg/kubectl/cmd/rollout/rollout_resume.go @@ -23,7 +23,6 @@ import ( "github.com/spf13/cobra" "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/kubernetes/pkg/api/legacyscheme" @@ -42,7 +41,6 @@ type ResumeConfig struct { Resumer func(object *resource.Info) ([]byte, error) Mapper meta.RESTMapper - Typer runtime.ObjectTyper Infos []*resource.Info Out io.Writer @@ -99,7 +97,7 @@ func (o *ResumeConfig) CompleteResume(f cmdutil.Factory, cmd *cobra.Command, out return cmdutil.UsageErrorf(cmd, "%s", cmd.Use) } - o.Mapper, o.Typer = f.Object() + o.Mapper = f.RESTMapper() o.Resumer = f.Resumer o.Out = out diff --git a/pkg/kubectl/cmd/rollout/rollout_undo.go b/pkg/kubectl/cmd/rollout/rollout_undo.go index d56247e3ad..903ad1e328 100644 --- a/pkg/kubectl/cmd/rollout/rollout_undo.go +++ b/pkg/kubectl/cmd/rollout/rollout_undo.go @@ -20,7 +20,6 @@ import ( "io" "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/runtime" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/kubectl" @@ -39,7 +38,6 @@ type UndoOptions struct { Rollbackers []kubectl.Rollbacker Mapper meta.RESTMapper - Typer runtime.ObjectTyper Infos []*resource.Info ToRevision int64 DryRun bool @@ -103,7 +101,7 @@ func (o *UndoOptions) CompleteUndo(f cmdutil.Factory, cmd *cobra.Command, out io } o.ToRevision = cmdutil.GetFlagInt64(cmd, "to-revision") - o.Mapper, o.Typer = f.Object() + o.Mapper = f.RESTMapper() o.Out = out o.DryRun = cmdutil.GetDryRunFlag(cmd) diff --git a/pkg/kubectl/cmd/run.go b/pkg/kubectl/cmd/run.go index 30153dc913..a544b4290f 100644 --- a/pkg/kubectl/cmd/run.go +++ b/pkg/kubectl/cmd/run.go @@ -643,8 +643,9 @@ func (o *RunOptions) createGeneratedObject(f cmdutil.Factory, cmd *cobra.Command return nil, err } - mapper, typer := f.Object() - groupVersionKinds, _, err := typer.ObjectKinds(obj) + mapper := f.RESTMapper() + // run has compiled knowledge of the thing is is creating + groupVersionKinds, _, err := legacyscheme.Scheme.ObjectKinds(obj) if err != nil { return nil, err } diff --git a/pkg/kubectl/cmd/set/set_selector.go b/pkg/kubectl/cmd/set/set_selector.go index e9f473a107..ad181a452a 100644 --- a/pkg/kubectl/cmd/set/set_selector.go +++ b/pkg/kubectl/cmd/set/set_selector.go @@ -140,7 +140,7 @@ func (o *SetSelectorOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, arg return err } - mapper, _ := f.Object() + mapper := f.RESTMapper() o.mapper = mapper o.resources, o.selector, err = getResourcesAndSelector(args) diff --git a/pkg/kubectl/cmd/testing/fake.go b/pkg/kubectl/cmd/testing/fake.go index ff27f173c8..ad7c9fa7c0 100644 --- a/pkg/kubectl/cmd/testing/fake.go +++ b/pkg/kubectl/cmd/testing/fake.go @@ -342,7 +342,7 @@ func (f *TestFactory) Command(*cobra.Command, bool) string { } func (f *TestFactory) NewBuilder() *resource.Builder { - mapper, _ := f.Object() + mapper := f.RESTMapper() return resource.NewBuilder( &resource.Mapper{ @@ -430,7 +430,7 @@ func (f *TestFactory) ClientSetForVersion(requiredVersion *schema.GroupVersion) return f.ClientSet() } -func (f *TestFactory) Object() (meta.RESTMapper, runtime.ObjectTyper) { +func (f *TestFactory) RESTMapper() meta.RESTMapper { groupResources := testDynamicResources() mapper := discovery.NewRESTMapper( groupResources, @@ -457,10 +457,9 @@ func (f *TestFactory) Object() (meta.RESTMapper, runtime.ObjectTyper) { } // TODO: should probably be the external scheme - typer := discovery.NewUnstructuredObjectTyper(groupResources, legacyscheme.Scheme) fakeDs := &fakeCachedDiscoveryClient{} expander := cmdutil.NewShortcutExpander(mapper, fakeDs) - return expander, typer + return expander } func (f *TestFactory) LogsForObject(object, options runtime.Object, timeout time.Duration) (*restclient.Request, error) { diff --git a/pkg/kubectl/cmd/util/factory.go b/pkg/kubectl/cmd/util/factory.go index 167f9f2cef..87da23dba8 100644 --- a/pkg/kubectl/cmd/util/factory.go +++ b/pkg/kubectl/cmd/util/factory.go @@ -164,7 +164,7 @@ type ClientAccessFactory interface { // 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. - Object() (meta.RESTMapper, runtime.ObjectTyper) + RESTMapper() meta.RESTMapper // 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 8847203282..c5363e2551 100644 --- a/pkg/kubectl/cmd/util/factory_builder.go +++ b/pkg/kubectl/cmd/util/factory_builder.go @@ -47,7 +47,7 @@ func NewBuilderFactory(clientAccessFactory ClientAccessFactory, objectMappingFac // NewBuilder returns a new resource builder for structured api objects. func (f *ring2Factory) NewBuilder() *resource.Builder { clientMapperFunc := resource.ClientMapperFunc(f.objectMappingFactory.ClientForMapping) - mapper, _ := f.objectMappingFactory.Object() + mapper := f.objectMappingFactory.RESTMapper() unstructuredClientMapperFunc := resource.ClientMapperFunc(f.objectMappingFactory.UnstructuredClientForMapping) @@ -97,7 +97,7 @@ func (f *ring2Factory) ScaleClient() (scaleclient.ScalesGetter, error) { return nil, err } resolver := scaleclient.NewDiscoveryScaleKindResolver(discoClient) - mapper, _ := f.objectMappingFactory.Object() + mapper := f.objectMappingFactory.RESTMapper() return scaleclient.New(restClient, mapper, dynamic.LegacyAPIPathResolverFunc, resolver), nil } diff --git a/pkg/kubectl/cmd/util/factory_object_mapping.go b/pkg/kubectl/cmd/util/factory_object_mapping.go index b40f75a123..b47340fe90 100644 --- a/pkg/kubectl/cmd/util/factory_object_mapping.go +++ b/pkg/kubectl/cmd/util/factory_object_mapping.go @@ -76,34 +76,23 @@ func NewObjectMappingFactory(clientAccessFactory ClientAccessFactory) ObjectMapp // the built in mapper if necessary. It supports unstructured objects either way, since // the underlying Scheme supports Unstructured. The mapper will return converters that can // convert versioned types to unstructured and back. -func (f *ring1Factory) objectLoader() (meta.RESTMapper, runtime.ObjectTyper, error) { +func (f *ring1Factory) restMapper() (meta.RESTMapper, error) { discoveryClient, err := f.clientAccessFactory.DiscoveryClient() if err != nil { glog.V(3).Infof("Unable to get a discovery client to find server resources, falling back to hardcoded types: %v", err) - return legacyscheme.Registry.RESTMapper(), legacyscheme.Scheme, nil - } - - groupResources, err := discovery.GetAPIGroupResources(discoveryClient) - if err != nil && !discoveryClient.Fresh() { - discoveryClient.Invalidate() - groupResources, err = discovery.GetAPIGroupResources(discoveryClient) - } - if err != nil { - glog.V(3).Infof("Unable to retrieve API resources, falling back to hardcoded types: %v", err) - return legacyscheme.Registry.RESTMapper(), legacyscheme.Scheme, nil + return legacyscheme.Registry.RESTMapper(), nil } // allow conversion between typed and unstructured objects interfaces := meta.InterfacesForUnstructuredConversion(legacyscheme.Registry.InterfacesFor) mapper := discovery.NewDeferredDiscoveryRESTMapper(discoveryClient, meta.VersionInterfacesFunc(interfaces)) // TODO: should this also indicate it recognizes typed objects? - typer := discovery.NewUnstructuredObjectTyper(groupResources, legacyscheme.Scheme) expander := NewShortcutExpander(mapper, discoveryClient) - return expander, typer, err + return expander, err } -func (f *ring1Factory) Object() (meta.RESTMapper, runtime.ObjectTyper) { - return meta.NewLazyObjectLoader(f.objectLoader) +func (f *ring1Factory) RESTMapper() meta.RESTMapper { + return meta.NewLazyRESTMapperLoader(f.restMapper) } func (f *ring1Factory) CategoryExpander() categories.CategoryExpander { diff --git a/pkg/kubectl/resource/BUILD b/pkg/kubectl/resource/BUILD index 1253463daa..cf64478931 100644 --- a/pkg/kubectl/resource/BUILD +++ b/pkg/kubectl/resource/BUILD @@ -29,6 +29,7 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructuredscheme:go_default_library", "//vendor/k8s.io/apimachinery/pkg/fields:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", @@ -55,6 +56,8 @@ go_test( ], embed = [":go_default_library"], deps = [ + "//pkg/api/legacyscheme:go_default_library", + "//pkg/apis/core/install:go_default_library", "//pkg/kubectl/categories:go_default_library", "//pkg/kubectl/scheme:go_default_library", "//vendor/github.com/ghodss/yaml:go_default_library", diff --git a/pkg/kubectl/resource/builder.go b/pkg/kubectl/resource/builder.go index b6979d7afe..a2de3ca686 100644 --- a/pkg/kubectl/resource/builder.go +++ b/pkg/kubectl/resource/builder.go @@ -644,6 +644,11 @@ func (b *Builder) mappingFor(resourceOrKindArg string) (*meta.RESTMapping, error // if we error out here, it is because we could not match a resource or a kind // for the given argument. To maintain consistency with previous behavior, // announce that a resource type could not be found. + // if the error is a URL error, then we had trouble doing discovery, so we should return the original + // error since it may help a user diagnose what is actually wrong + if _, ok := err.(*url.Error); ok { + return nil, err + } return nil, fmt.Errorf("the server doesn't have a resource type %q", groupResource.Resource) } diff --git a/pkg/kubectl/resource/visitor.go b/pkg/kubectl/resource/visitor.go index cd6721f8dc..8824171299 100644 --- a/pkg/kubectl/resource/visitor.go +++ b/pkg/kubectl/resource/visitor.go @@ -188,7 +188,7 @@ func (i *Info) versioned(convertor runtime.ObjectConvertor) (runtime.Object, err // AsVersioned returns the object as a Go object in the external form if possible (matching the // group version kind of the mapping, or i.Object if it cannot be converted. // Deprecated this function will be removed once calling code is updated to indicate the correct -// negoticatedserializers during contruction of the builder +// negoticatedserializers during construction of the builder func (i *Info) AsVersioned(convertor runtime.ObjectConvertor) runtime.Object { if obj, err := i.versioned(convertor); err == nil { return obj diff --git a/staging/src/k8s.io/apimachinery/pkg/api/meta/lazy.go b/staging/src/k8s.io/apimachinery/pkg/api/meta/lazy.go index 7f92f39a43..431a0a6353 100644 --- a/staging/src/k8s.io/apimachinery/pkg/api/meta/lazy.go +++ b/staging/src/k8s.io/apimachinery/pkg/api/meta/lazy.go @@ -19,27 +19,25 @@ package meta import ( "sync" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" ) // lazyObject defers loading the mapper and typer until necessary. type lazyObject struct { - loader func() (RESTMapper, runtime.ObjectTyper, error) + loader func() (RESTMapper, error) lock sync.Mutex loaded bool err error mapper RESTMapper - typer runtime.ObjectTyper } // NewLazyObjectLoader handles unrecoverable errors when creating a RESTMapper / ObjectTyper by // returning those initialization errors when the interface methods are invoked. This defers the // initialization and any server calls until a client actually needs to perform the action. -func NewLazyObjectLoader(fn func() (RESTMapper, runtime.ObjectTyper, error)) (RESTMapper, runtime.ObjectTyper) { +func NewLazyRESTMapperLoader(fn func() (RESTMapper, error)) RESTMapper { obj := &lazyObject{loader: fn} - return obj, obj + return obj } // init lazily loads the mapper and typer, returning an error if initialization has failed. @@ -49,13 +47,12 @@ func (o *lazyObject) init() error { if o.loaded { return o.err } - o.mapper, o.typer, o.err = o.loader() + o.mapper, o.err = o.loader() o.loaded = true return o.err } var _ RESTMapper = &lazyObject{} -var _ runtime.ObjectTyper = &lazyObject{} func (o *lazyObject) KindFor(resource schema.GroupVersionResource) (schema.GroupVersionKind, error) { if err := o.init(); err != nil { @@ -105,17 +102,3 @@ func (o *lazyObject) ResourceSingularizer(resource string) (singular string, err } return o.mapper.ResourceSingularizer(resource) } - -func (o *lazyObject) ObjectKinds(obj runtime.Object) ([]schema.GroupVersionKind, bool, error) { - if err := o.init(); err != nil { - return nil, false, err - } - return o.typer.ObjectKinds(obj) -} - -func (o *lazyObject) Recognizes(gvk schema.GroupVersionKind) bool { - if err := o.init(); err != nil { - return false - } - return o.typer.Recognizes(gvk) -} diff --git a/test/integration/apiserver/print_test.go b/test/integration/apiserver/print_test.go index 3eeb3afde4..e6e19fdcfd 100644 --- a/test/integration/apiserver/print_test.go +++ b/test/integration/apiserver/print_test.go @@ -147,7 +147,7 @@ func TestServerSidePrint(t *testing.T) { printer := newFakePrinter(printersinternal.AddHandlers) factory := util.NewFactory(clientcmd.NewDefaultClientConfig(*createKubeConfig(s.URL), &clientcmd.ConfigOverrides{})) - mapper, _ := factory.Object() + mapper := factory.RESTMapper() for gvk, apiType := range legacyscheme.Scheme.AllKnownTypes() { // we do not care about internal objects or lists // TODO make sure this is always true diff --git a/test/integration/etcd/etcd_storage_path_test.go b/test/integration/etcd/etcd_storage_path_test.go index 2f62c5b9ff..0756210ea4 100644 --- a/test/integration/etcd/etcd_storage_path_test.go +++ b/test/integration/etcd/etcd_storage_path_test.go @@ -811,7 +811,7 @@ func startRealMasterOrDie(t *testing.T, certDir string) (*allClient, clientv3.KV t.Fatal(err) } - mapper, _ := util.NewFactory(clientcmd.NewDefaultClientConfig(*clientcmdapi.NewConfig(), &clientcmd.ConfigOverrides{})).Object() + mapper := util.NewFactory(clientcmd.NewDefaultClientConfig(*clientcmdapi.NewConfig(), &clientcmd.ConfigOverrides{})).RESTMapper() return client, kvClient, mapper }