diff --git a/pkg/kubectl/cmd/get.go b/pkg/kubectl/cmd/get.go index 514699b01e9..4a4ea3d5e7e 100644 --- a/pkg/kubectl/cmd/get.go +++ b/pkg/kubectl/cmd/get.go @@ -301,22 +301,23 @@ func RunGet(f *cmdutil.Factory, out io.Writer, errOut io.Writer, cmd *cobra.Comm return err } - allErrs := []error{} - singular := false - infos, err := r.IntoSingular(&singular).Infos() - if err != nil { - if singular { - return err - } - allErrs = append(allErrs, err) - } - // the outermost object will be converted to the output-version, but inner // objects can use their mappings version, err := cmdutil.OutputVersion(cmd, clientConfig.GroupVersion) if err != nil { return err } + + var errs []error + singular := false + infos, err := r.IntoSingular(&singular).Infos() + if err != nil { + if singular { + return err + } + errs = append(errs, err) + } + res := "" if len(infos) > 0 { res = infos[0].ResourceMapping().Resource @@ -329,20 +330,20 @@ func RunGet(f *cmdutil.Factory, out io.Writer, errOut io.Writer, cmd *cobra.Comm isList := meta.IsListType(obj) if isList { - filteredResourceCount, items, errs := cmdutil.FilterResourceList(obj, filterFuncs, filterOpts) - if errs != nil { - return errs + filteredResourceCount, items, err := cmdutil.FilterResourceList(obj, filterFuncs, filterOpts) + if err != nil { + return err } filteredObj, err := cmdutil.ObjectListToVersionedObject(items, version) if err != nil { return err } if err := printer.PrintObj(filteredObj, out); err != nil { - allErrs = append(allErrs, err) + errs = append(errs, err) } cmdutil.PrintFilterCount(filteredResourceCount, res, errOut, filterOpts) - return utilerrors.NewAggregate(allErrs) + return utilerrors.Reduce(utilerrors.Flatten(utilerrors.NewAggregate(errs))) } filteredResourceCount := 0 @@ -350,14 +351,14 @@ func RunGet(f *cmdutil.Factory, out io.Writer, errOut io.Writer, cmd *cobra.Comm if err != nil { glog.V(2).Infof("Unable to filter resource: %v", err) } else if err := printer.PrintObj(obj, out); err != nil { - allErrs = append(allErrs, err) + errs = append(errs, err) } } else if isFiltered { filteredResourceCount++ } cmdutil.PrintFilterCount(filteredResourceCount, res, errOut, filterOpts) - return utilerrors.NewAggregate(allErrs) + return utilerrors.Reduce(utilerrors.Flatten(utilerrors.NewAggregate(errs))) } allErrs := []error{} diff --git a/pkg/kubectl/cmd/util/helpers.go b/pkg/kubectl/cmd/util/helpers.go index ec50d80be94..89358abc64f 100644 --- a/pkg/kubectl/cmd/util/helpers.go +++ b/pkg/kubectl/cmd/util/helpers.go @@ -122,6 +122,11 @@ func checkErrWithPrefix(prefix string, err error) { // checkErr formats a given error as a string and calls the passed handleErr // func with that string and an kubectl exit code. func checkErr(prefix string, err error, handleErr func(string, int)) { + // unwrap aggregates of 1 + if agg, ok := err.(utilerrors.Aggregate); ok && len(agg.Errors()) == 1 { + err = agg.Errors()[0] + } + switch { case err == nil: return diff --git a/pkg/util/errors/errors.go b/pkg/util/errors/errors.go index 42631f21622..de62fe39973 100644 --- a/pkg/util/errors/errors.go +++ b/pkg/util/errors/errors.go @@ -147,6 +147,20 @@ func Flatten(agg Aggregate) Aggregate { return NewAggregate(result) } +// Reduce will return err or, if err is an Aggregate and only has one item, +// the first item in the aggregate. +func Reduce(err error) error { + if agg, ok := err.(Aggregate); ok && err != nil { + switch len(agg.Errors()) { + case 1: + return agg.Errors()[0] + case 0: + return nil + } + } + return err +} + // AggregateGoroutines runs the provided functions in parallel, stuffing all // non-nil errors into the returned Aggregate. // Returns nil if all the functions complete successfully.