Merge pull request #60057 from deads2k/cli-07-printer

Automatic merge from submit-queue (batch tested with PRs 59391, 58097, 60057, 60090). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

cleanup printers some more

This cleans up some more dead printer flags and unnecessary arguments for various methods.  We're getting closer.  Still need to clean up some ugly around `PrintSuccess` and then its time to start trimming layers.

@kubernetes/sig-cli-maintainers 

```release-note
NONE
```
This commit is contained in:
Kubernetes Submit Queue 2018-02-20 13:51:35 -08:00 committed by GitHub
commit 370540f90d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 169 additions and 150 deletions

View File

@ -266,9 +266,8 @@ func (o AnnotateOptions) RunAnnotate(f cmdutil.Factory, cmd *cobra.Command) erro
} }
} }
mapper := r.Mapper().RESTMapper
if len(o.outputFormat) > 0 { if len(o.outputFormat) > 0 {
return f.PrintObject(cmd, o.local, mapper, outputObj, o.out) return f.PrintObject(cmd, outputObj, o.out)
} }
f.PrintSuccess(false, o.out, info.Mapping.Resource, info.Name, o.dryrun, "annotated") f.PrintSuccess(false, o.out, info.Mapping.Resource, info.Name, o.dryrun, "annotated")
return nil return nil

View File

@ -156,7 +156,7 @@ func RunAutoscale(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []s
object = hpa.Object object = hpa.Object
} }
if cmdutil.GetDryRunFlag(cmd) { if cmdutil.GetDryRunFlag(cmd) {
return f.PrintObject(cmd, false, mapper, object, out) return f.PrintObject(cmd, object, out)
} }
if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), hpa, f.JSONEncoder()); err != nil { if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), hpa, f.JSONEncoder()); err != nil {
@ -170,7 +170,7 @@ func RunAutoscale(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []s
count++ count++
if len(cmdutil.GetFlagString(cmd, "output")) > 0 { if len(cmdutil.GetFlagString(cmd, "output")) > 0 {
return f.PrintObject(cmd, false, mapper, object, out) return f.PrintObject(cmd, object, out)
} }
f.PrintSuccess(false, out, info.Mapping.Resource, info.Name, cmdutil.GetDryRunFlag(cmd), "autoscaled") f.PrintSuccess(false, out, info.Mapping.Resource, info.Name, cmdutil.GetDryRunFlag(cmd), "autoscaled")

View File

@ -237,8 +237,7 @@ func Example_printReplicationControllerWithNamespace() {
ReadyReplicas: 1, ReadyReplicas: 1,
}, },
} }
mapper, _ := f.Object() err := f.PrintObject(cmd, ctrl, os.Stdout)
err := f.PrintObject(cmd, false, mapper, ctrl, os.Stdout)
if err != nil { if err != nil {
fmt.Printf("Unexpected error: %v", err) fmt.Printf("Unexpected error: %v", err)
} }
@ -291,8 +290,7 @@ func Example_printMultiContainersReplicationControllerWithWide() {
Replicas: 1, Replicas: 1,
}, },
} }
mapper, _ := f.Object() err := f.PrintObject(cmd, ctrl, os.Stdout)
err := f.PrintObject(cmd, false, mapper, ctrl, os.Stdout)
if err != nil { if err != nil {
fmt.Printf("Unexpected error: %v", err) fmt.Printf("Unexpected error: %v", err)
} }
@ -344,8 +342,7 @@ func Example_printReplicationController() {
Replicas: 1, Replicas: 1,
}, },
} }
mapper, _ := f.Object() err := f.PrintObject(cmd, ctrl, os.Stdout)
err := f.PrintObject(cmd, false, mapper, ctrl, os.Stdout)
if err != nil { if err != nil {
fmt.Printf("Unexpected error: %v", err) fmt.Printf("Unexpected error: %v", err)
} }
@ -386,8 +383,7 @@ func Example_printPodWithWideFormat() {
PodIP: "10.1.1.3", PodIP: "10.1.1.3",
}, },
} }
mapper, _ := f.Object() err := f.PrintObject(cmd, pod, os.Stdout)
err := f.PrintObject(cmd, false, mapper, pod, os.Stdout)
if err != nil { if err != nil {
fmt.Printf("Unexpected error: %v", err) fmt.Printf("Unexpected error: %v", err)
} }
@ -431,8 +427,7 @@ func Example_printPodWithShowLabels() {
}, },
}, },
} }
mapper, _ := f.Object() err := f.PrintObject(cmd, pod, os.Stdout)
err := f.PrintObject(cmd, false, mapper, pod, os.Stdout)
if err != nil { if err != nil {
fmt.Printf("Unexpected error: %v", err) fmt.Printf("Unexpected error: %v", err)
} }
@ -554,8 +549,7 @@ func Example_printPodHideTerminated() {
fmt.Printf("Unexpected filter error: %v\n", errs) fmt.Printf("Unexpected filter error: %v\n", errs)
} }
for _, pod := range filteredPodList { for _, pod := range filteredPodList {
mapper, _ := f.Object() err := f.PrintObject(cmd, pod, os.Stdout)
err := f.PrintObject(cmd, false, mapper, pod, os.Stdout)
if err != nil { if err != nil {
fmt.Printf("Unexpected error: %v", err) fmt.Printf("Unexpected error: %v", err)
} }
@ -581,8 +575,7 @@ func Example_printPodShowAll() {
} }
cmd := NewCmdRun(f, os.Stdin, os.Stdout, os.Stderr) cmd := NewCmdRun(f, os.Stdin, os.Stdout, os.Stderr)
podList := newAllPhasePodList() podList := newAllPhasePodList()
mapper, _ := f.Object() err := f.PrintObject(cmd, podList, os.Stdout)
err := f.PrintObject(cmd, false, mapper, podList, os.Stdout)
if err != nil { if err != nil {
fmt.Printf("Unexpected error: %v", err) fmt.Printf("Unexpected error: %v", err)
} }
@ -657,8 +650,7 @@ func Example_printServiceWithNamespacesAndLabels() {
} }
ld := strings.NewLineDelimiter(os.Stdout, "|") ld := strings.NewLineDelimiter(os.Stdout, "|")
defer ld.Flush() defer ld.Flush()
mapper, _ := f.Object() err := f.PrintObject(cmd, svc, ld)
err := f.PrintObject(cmd, false, mapper, svc, ld)
if err != nil { if err != nil {
fmt.Printf("Unexpected error: %v", err) fmt.Printf("Unexpected error: %v", err)
} }

View File

@ -82,7 +82,6 @@ func NewCmdConfigView(f cmdutil.Factory, out, errOut io.Writer, ConfigAccess cli
printOpts := cmdutil.ExtractCmdPrintOptions(cmd, false) printOpts := cmdutil.ExtractCmdPrintOptions(cmd, false)
printer, err := f.PrinterForOptions(printOpts) printer, err := f.PrinterForOptions(printOpts)
cmdutil.CheckErr(err) cmdutil.CheckErr(err)
printer = printers.NewVersionedPrinter(printer, latest.Scheme, latest.ExternalVersion)
cmdutil.CheckErr(options.Run(out, printer)) cmdutil.CheckErr(options.Run(out, printer))
}, },
@ -120,7 +119,12 @@ func (o ViewOptions) Run(out io.Writer, printer printers.ResourcePrinter) error
clientcmdapi.ShortenConfig(config) clientcmdapi.ShortenConfig(config)
} }
err = printer.PrintObj(config, out) convertedObj, err := latest.Scheme.ConvertToVersion(config, latest.ExternalVersion)
if err != nil {
return err
}
err = printer.PrintObj(convertedObj, out)
if err != nil { if err != nil {
return err return err
} }

View File

@ -360,5 +360,5 @@ func RunCreateSubcommand(f cmdutil.Factory, cmd *cobra.Command, out io.Writer, o
return nil return nil
} }
return f.PrintObject(cmd, false, mapper, obj, out) return f.PrintObject(cmd, obj, out)
} }

View File

@ -206,7 +206,7 @@ func (c *CreateRoleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args
} }
c.PrintObject = func(obj runtime.Object) error { c.PrintObject = func(obj runtime.Object) error {
return f.PrintObject(cmd, false, c.Mapper, obj, c.Out) return f.PrintObject(cmd, obj, c.Out)
} }
clientset, err := f.KubernetesClientSet() clientset, err := f.KubernetesClientSet()

View File

@ -255,7 +255,7 @@ func RunExpose(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri
info.Refresh(object, true) info.Refresh(object, true)
if cmdutil.GetDryRunFlag(cmd) { if cmdutil.GetDryRunFlag(cmd) {
if len(cmdutil.GetFlagString(cmd, "output")) > 0 { if len(cmdutil.GetFlagString(cmd, "output")) > 0 {
return f.PrintObject(cmd, false, mapper, object, out) return f.PrintObject(cmd, object, out)
} }
f.PrintSuccess(false, out, info.Mapping.Resource, info.Name, true, "exposed") f.PrintSuccess(false, out, info.Mapping.Resource, info.Name, true, "exposed")
return nil return nil
@ -271,7 +271,7 @@ func RunExpose(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri
} }
if len(cmdutil.GetFlagString(cmd, "output")) > 0 { if len(cmdutil.GetFlagString(cmd, "output")) > 0 {
return f.PrintObject(cmd, false, mapper, object, out) return f.PrintObject(cmd, object, out)
} }
f.PrintSuccess(false, out, info.Mapping.Resource, info.Name, false, "exposed") f.PrintSuccess(false, out, info.Mapping.Resource, info.Name, false, "exposed")

View File

@ -288,7 +288,7 @@ func (o *LabelOptions) RunLabel(f cmdutil.Factory, cmd *cobra.Command) error {
} }
if len(o.outputFormat) > 0 { if len(o.outputFormat) > 0 {
return f.PrintObject(cmd, o.local, r.Mapper().RESTMapper, outputObj, o.out) return f.PrintObject(cmd, outputObj, o.out)
} }
f.PrintSuccess(false, o.out, info.Mapping.Resource, info.Name, o.dryrun, dataChangeMsg) f.PrintSuccess(false, o.out, info.Mapping.Resource, info.Name, o.dryrun, dataChangeMsg)
return nil return nil

View File

@ -22,6 +22,7 @@ go_library(
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",

View File

@ -32,6 +32,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
utilerrors "k8s.io/apimachinery/pkg/util/errors" utilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/watch" "k8s.io/apimachinery/pkg/watch"
@ -340,7 +341,7 @@ func (options *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []str
updatePrintOptionsForOpenAPI(f, mapping, printOpts) updatePrintOptionsForOpenAPI(f, mapping, printOpts)
} }
printer, err = f.PrinterForMapping(printOpts, mapping) printer, err = f.PrinterForMapping(printOpts)
if err != nil { if err != nil {
if !errs.Has(err.Error()) { if !errs.Has(err.Error()) {
errs.Insert(err.Error()) errs.Insert(err.Error())
@ -493,7 +494,7 @@ func (options *GetOptions) watch(f cmdutil.Factory, cmd *cobra.Command, args []s
info := infos[0] info := infos[0]
mapping := info.ResourceMapping() mapping := info.ResourceMapping()
printOpts := cmdutil.ExtractCmdPrintOptions(cmd, options.AllNamespaces) printOpts := cmdutil.ExtractCmdPrintOptions(cmd, options.AllNamespaces)
printer, err := f.PrinterForMapping(printOpts, mapping) printer, err := f.PrinterForMapping(printOpts)
if err != nil { if err != nil {
return err return err
} }
@ -531,7 +532,13 @@ func (options *GetOptions) watch(f cmdutil.Factory, cmd *cobra.Command, args []s
if isFiltered, err := filterFuncs.Filter(objToPrint, filterOpts); !isFiltered { if isFiltered, err := filterFuncs.Filter(objToPrint, filterOpts); !isFiltered {
if err != nil { if err != nil {
glog.V(2).Infof("Unable to filter resource: %v", err) glog.V(2).Infof("Unable to filter resource: %v", err)
} else if err := printer.PrintObj(objToPrint, writer); err != nil { continue
}
// printing always takes the internal version, but the watch event uses externals
// TODO fix printing to use server-side or be version agnostic
internalGV := mapping.GroupVersionKind.GroupKind().WithVersion(runtime.APIVersionInternal).GroupVersion()
if err := printer.PrintObj(attemptToConvertToInternal(objToPrint, mapping, internalGV), writer); err != nil {
return fmt.Errorf("unable to output the provided object: %v", err) return fmt.Errorf("unable to output the provided object: %v", err)
} }
} }
@ -558,7 +565,13 @@ func (options *GetOptions) watch(f cmdutil.Factory, cmd *cobra.Command, args []s
if isFiltered, err := filterFuncs.Filter(e.Object, filterOpts); !isFiltered { if isFiltered, err := filterFuncs.Filter(e.Object, filterOpts); !isFiltered {
if err != nil { if err != nil {
glog.V(2).Infof("Unable to filter resource: %v", err) glog.V(2).Infof("Unable to filter resource: %v", err)
} else if err := printer.PrintObj(e.Object, options.Out); err != nil { return false, nil
}
// printing always takes the internal version, but the watch event uses externals
// TODO fix printing to use server-side or be version agnostic
internalGV := mapping.GroupVersionKind.GroupKind().WithVersion(runtime.APIVersionInternal).GroupVersion()
if err := printer.PrintObj(attemptToConvertToInternal(e.Object, mapping, internalGV), options.Out); err != nil {
return false, err return false, err
} }
} }
@ -569,6 +582,16 @@ func (options *GetOptions) watch(f cmdutil.Factory, cmd *cobra.Command, args []s
return nil return nil
} }
// attemptToConvertToInternal tries to convert to an internal type, but returns the original if it can't
func attemptToConvertToInternal(obj runtime.Object, converter runtime.ObjectConvertor, targetVersion schema.GroupVersion) runtime.Object {
internalObject, err := converter.ConvertToVersion(obj, targetVersion)
if err != nil {
glog.V(1).Infof("Unable to convert %T to %v: err", obj, targetVersion, err)
return obj
}
return internalObject
}
func (options *GetOptions) printGeneric(printer printers.ResourcePrinter, r *resource.Result, filterFuncs kubectl.Filters, filterOpts *printers.PrintOptions) error { func (options *GetOptions) printGeneric(printer printers.ResourcePrinter, r *resource.Result, filterFuncs kubectl.Filters, filterOpts *printers.PrintOptions) error {
// we flattened the data from the builder, so we have individual items, but now we'd like to either: // we flattened the data from the builder, so we have individual items, but now we'd like to either:
// 1. if there is more than one item, combine them all into a single list // 1. if there is more than one item, combine them all into a single list

View File

@ -191,8 +191,6 @@ func RunRollingUpdate(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args
var keepOldName bool var keepOldName bool
var replicasDefaulted bool var replicasDefaulted bool
mapper, _ := f.Object()
if len(filename) != 0 { if len(filename) != 0 {
schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate")) schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate"))
if err != nil { if err != nil {
@ -322,10 +320,10 @@ func RunRollingUpdate(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args
oldRcData.WriteString(oldRc.Name) oldRcData.WriteString(oldRc.Name)
newRcData.WriteString(newRc.Name) newRcData.WriteString(newRc.Name)
} else { } else {
if err := f.PrintObject(cmd, false, mapper, oldRc, oldRcData); err != nil { if err := f.PrintObject(cmd, oldRc, oldRcData); err != nil {
return err return err
} }
if err := f.PrintObject(cmd, false, mapper, newRc, newRcData); err != nil { if err := f.PrintObject(cmd, newRc, newRcData); err != nil {
return err return err
} }
} }
@ -370,7 +368,7 @@ func RunRollingUpdate(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args
return err return err
} }
if outputFormat != "" { if outputFormat != "" {
return f.PrintObject(cmd, false, mapper, newRc, out) return f.PrintObject(cmd, newRc, out)
} }
f.PrintSuccess(false, out, "replicationcontrollers", oldName, dryrun, message) f.PrintSuccess(false, out, "replicationcontrollers", oldName, dryrun, message)
return nil return nil

View File

@ -407,7 +407,7 @@ func RunRun(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *c
if runObject != nil { if runObject != nil {
outputFormat := cmdutil.GetFlagString(cmd, "output") outputFormat := cmdutil.GetFlagString(cmd, "output")
if outputFormat != "" || cmdutil.GetDryRunFlag(cmd) { if outputFormat != "" || cmdutil.GetDryRunFlag(cmd) {
return f.PrintObject(cmd, false, runObject.Mapper, runObject.Object, cmdOut) return f.PrintObject(cmd, runObject.Object, cmdOut)
} }
f.PrintSuccess(false, cmdOut, runObject.Mapping.Resource, args[0], cmdutil.GetDryRunFlag(cmd), "created") f.PrintSuccess(false, cmdOut, runObject.Mapping.Resource, args[0], cmdutil.GetDryRunFlag(cmd), "created")
} }
@ -557,7 +557,7 @@ func generateService(f cmdutil.Factory, cmd *cobra.Command, args []string, servi
} }
if cmdutil.GetFlagString(cmd, "output") != "" || cmdutil.GetDryRunFlag(cmd) { if cmdutil.GetFlagString(cmd, "output") != "" || cmdutil.GetDryRunFlag(cmd) {
err := f.PrintObject(cmd, false, runObject.Mapper, runObject.Object, out) err := f.PrintObject(cmd, runObject.Object, out)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -58,6 +58,7 @@ go_test(
], ],
embed = [":go_default_library"], embed = [":go_default_library"],
deps = [ deps = [
"//pkg/api/legacyscheme:go_default_library",
"//pkg/api/testapi:go_default_library", "//pkg/api/testapi:go_default_library",
"//pkg/apis/rbac:go_default_library", "//pkg/apis/rbac:go_default_library",
"//pkg/kubectl/categories:go_default_library", "//pkg/kubectl/categories:go_default_library",

View File

@ -26,7 +26,6 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
@ -116,7 +115,6 @@ type EnvOptions struct {
From string From string
Prefix string Prefix string
Mapper meta.RESTMapper
Builder *resource.Builder Builder *resource.Builder
Infos []*resource.Info Infos []*resource.Info
Encoder runtime.Encoder Encoder runtime.Encoder
@ -124,7 +122,7 @@ type EnvOptions struct {
Cmd *cobra.Command Cmd *cobra.Command
UpdatePodSpecForObject func(obj runtime.Object, fn func(*v1.PodSpec) error) (bool, error) UpdatePodSpecForObject func(obj runtime.Object, fn func(*v1.PodSpec) error) (bool, error)
PrintObject func(cmd *cobra.Command, isLocal bool, mapper meta.RESTMapper, obj runtime.Object, out io.Writer) error PrintObject func(cmd *cobra.Command, obj runtime.Object, out io.Writer) error
} }
// NewCmdEnv implements the OpenShift cli env command // NewCmdEnv implements the OpenShift cli env command
@ -189,7 +187,6 @@ func (o *EnvOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []stri
return cmdutil.UsageErrorf(cmd, "one or more resources must be specified as <resource> <name> or <resource>/<name>") return cmdutil.UsageErrorf(cmd, "one or more resources must be specified as <resource> <name> or <resource>/<name>")
} }
o.Mapper, _ = f.Object()
o.UpdatePodSpecForObject = f.UpdatePodSpecForObject o.UpdatePodSpecForObject = f.UpdatePodSpecForObject
o.Encoder = f.JSONEncoder() o.Encoder = f.JSONEncoder()
o.ContainerSelector = cmdutil.GetFlagString(cmd, "containers") o.ContainerSelector = cmdutil.GetFlagString(cmd, "containers")
@ -417,7 +414,7 @@ func (o *EnvOptions) RunEnv(f cmdutil.Factory) error {
} }
if o.PrintObject != nil && (o.Local || o.DryRun) { if o.PrintObject != nil && (o.Local || o.DryRun) {
if err := o.PrintObject(o.Cmd, o.Local, o.Mapper, patch.Info.AsVersioned(), o.Out); err != nil { if err := o.PrintObject(o.Cmd, patch.Info.AsVersioned(), o.Out); err != nil {
return err return err
} }
continue continue
@ -437,7 +434,7 @@ func (o *EnvOptions) RunEnv(f cmdutil.Factory) error {
} }
if len(o.Output) > 0 { if len(o.Output) > 0 {
if err := o.PrintObject(o.Cmd, o.Local, o.Mapper, info.AsVersioned(), o.Out); err != nil { if err := o.PrintObject(o.Cmd, info.AsVersioned(), o.Out); err != nil {
return err return err
} }
continue continue

View File

@ -38,6 +38,7 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
"k8s.io/client-go/rest/fake" "k8s.io/client-go/rest/fake"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/api/testapi"
"k8s.io/kubernetes/pkg/kubectl/categories" "k8s.io/kubernetes/pkg/kubectl/categories"
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
@ -435,7 +436,7 @@ func TestSetEnvRemote(t *testing.T) {
testapi.Default = testapi.Groups[input.testAPIGroup] testapi.Default = testapi.Groups[input.testAPIGroup]
f, tf, _, ns := cmdtesting.NewAPIFactory() f, tf, _, ns := cmdtesting.NewAPIFactory()
codec := scheme.Codecs.CodecForVersions(scheme.Codecs.LegacyCodec(groupVersion), scheme.Codecs.UniversalDecoder(groupVersion), groupVersion, groupVersion) codec := scheme.Codecs.CodecForVersions(scheme.Codecs.LegacyCodec(groupVersion), scheme.Codecs.UniversalDecoder(groupVersion), groupVersion, groupVersion)
tf.Printer = printers.NewVersionedPrinter(&printers.YAMLPrinter{}, testapi.Default.Converter(), *testapi.Default.GroupVersion()) tf.Printer = printers.NewVersionedPrinter(&printers.YAMLPrinter{}, legacyscheme.Scheme, legacyscheme.Scheme, scheme.Versions...)
tf.Namespace = "test" tf.Namespace = "test"
tf.CategoryExpander = categories.LegacyCategoryExpander tf.CategoryExpander = categories.LegacyCategoryExpander
tf.Client = &fake.RESTClient{ tf.Client = &fake.RESTClient{

View File

@ -22,7 +22,6 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
utilerrors "k8s.io/apimachinery/pkg/util/errors" utilerrors "k8s.io/apimachinery/pkg/util/errors"
@ -37,7 +36,6 @@ import (
type ImageOptions struct { type ImageOptions struct {
resource.FilenameOptions resource.FilenameOptions
Mapper meta.RESTMapper
Infos []*resource.Info Infos []*resource.Info
Encoder runtime.Encoder Encoder runtime.Encoder
Decoder runtime.Decoder Decoder runtime.Decoder
@ -55,7 +53,7 @@ type ImageOptions struct {
ResolveImage func(in string) (string, error) ResolveImage func(in string) (string, error)
PrintSuccess func(shortOutput bool, out io.Writer, resource, name string, dryRun bool, operation string) PrintSuccess func(shortOutput bool, out io.Writer, resource, name string, dryRun bool, operation string)
PrintObject func(cmd *cobra.Command, isLocal bool, mapper meta.RESTMapper, obj runtime.Object, out io.Writer) error PrintObject func(cmd *cobra.Command, obj runtime.Object, out io.Writer) error
UpdatePodSpecForObject func(obj runtime.Object, fn func(*v1.PodSpec) error) (bool, error) UpdatePodSpecForObject func(obj runtime.Object, fn func(*v1.PodSpec) error) (bool, error)
Resources []string Resources []string
ContainerImages map[string]string ContainerImages map[string]string
@ -117,7 +115,6 @@ func NewCmdImage(f cmdutil.Factory, out, err io.Writer) *cobra.Command {
} }
func (o *ImageOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { func (o *ImageOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
o.Mapper, _ = f.Object()
o.PrintSuccess = f.PrintSuccess o.PrintSuccess = f.PrintSuccess
o.UpdatePodSpecForObject = f.UpdatePodSpecForObject o.UpdatePodSpecForObject = f.UpdatePodSpecForObject
o.Encoder = f.JSONEncoder() o.Encoder = f.JSONEncoder()
@ -249,7 +246,7 @@ func (o *ImageOptions) Run() error {
} }
if o.PrintObject != nil && (o.Local || o.DryRun) { if o.PrintObject != nil && (o.Local || o.DryRun) {
if err := o.PrintObject(o.Cmd, o.Local, o.Mapper, patch.Info.AsVersioned(), o.Out); err != nil { if err := o.PrintObject(o.Cmd, patch.Info.AsVersioned(), o.Out); err != nil {
return err return err
} }
continue continue
@ -275,7 +272,7 @@ func (o *ImageOptions) Run() error {
info.Refresh(obj, true) info.Refresh(obj, true)
if len(o.Output) > 0 { if len(o.Output) > 0 {
if err := o.PrintObject(o.Cmd, o.Local, o.Mapper, info.AsVersioned(), o.Out); err != nil { if err := o.PrintObject(o.Cmd, info.AsVersioned(), o.Out); err != nil {
return err return err
} }
continue continue

View File

@ -37,6 +37,7 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
"k8s.io/client-go/rest/fake" "k8s.io/client-go/rest/fake"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/api/testapi"
"k8s.io/kubernetes/pkg/kubectl/categories" "k8s.io/kubernetes/pkg/kubectl/categories"
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
@ -502,7 +503,7 @@ func TestSetImageRemote(t *testing.T) {
testapi.Default = testapi.Groups[input.testAPIGroup] testapi.Default = testapi.Groups[input.testAPIGroup]
f, tf, _, ns := cmdtesting.NewAPIFactory() f, tf, _, ns := cmdtesting.NewAPIFactory()
codec := scheme.Codecs.CodecForVersions(scheme.Codecs.LegacyCodec(groupVersion), scheme.Codecs.UniversalDecoder(groupVersion), groupVersion, groupVersion) codec := scheme.Codecs.CodecForVersions(scheme.Codecs.LegacyCodec(groupVersion), scheme.Codecs.UniversalDecoder(groupVersion), groupVersion, groupVersion)
tf.Printer = printers.NewVersionedPrinter(&printers.YAMLPrinter{}, testapi.Default.Converter(), *testapi.Default.GroupVersion()) tf.Printer = printers.NewVersionedPrinter(&printers.YAMLPrinter{}, legacyscheme.Scheme, legacyscheme.Scheme, scheme.Versions...)
tf.Namespace = "test" tf.Namespace = "test"
tf.CategoryExpander = categories.LegacyCategoryExpander tf.CategoryExpander = categories.LegacyCategoryExpander
tf.Client = &fake.RESTClient{ tf.Client = &fake.RESTClient{

View File

@ -23,7 +23,6 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
@ -62,7 +61,6 @@ var (
type ResourcesOptions struct { type ResourcesOptions struct {
resource.FilenameOptions resource.FilenameOptions
Mapper meta.RESTMapper
Infos []*resource.Info Infos []*resource.Info
Encoder runtime.Encoder Encoder runtime.Encoder
Out io.Writer Out io.Writer
@ -81,7 +79,7 @@ type ResourcesOptions struct {
ResourceRequirements v1.ResourceRequirements ResourceRequirements v1.ResourceRequirements
PrintSuccess func(shortOutput bool, out io.Writer, resource, name string, dryRun bool, operation string) PrintSuccess func(shortOutput bool, out io.Writer, resource, name string, dryRun bool, operation string)
PrintObject func(cmd *cobra.Command, isLocal bool, mapper meta.RESTMapper, obj runtime.Object, out io.Writer) error PrintObject func(cmd *cobra.Command, obj runtime.Object, out io.Writer) error
UpdatePodSpecForObject func(obj runtime.Object, fn func(*v1.PodSpec) error) (bool, error) UpdatePodSpecForObject func(obj runtime.Object, fn func(*v1.PodSpec) error) (bool, error)
Resources []string Resources []string
} }
@ -128,7 +126,6 @@ func NewCmdResources(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.
} }
func (o *ResourcesOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { func (o *ResourcesOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
o.Mapper, _ = f.Object()
o.PrintSuccess = f.PrintSuccess o.PrintSuccess = f.PrintSuccess
o.UpdatePodSpecForObject = f.UpdatePodSpecForObject o.UpdatePodSpecForObject = f.UpdatePodSpecForObject
o.Encoder = f.JSONEncoder() o.Encoder = f.JSONEncoder()
@ -241,7 +238,7 @@ func (o *ResourcesOptions) Run() error {
} }
if o.Local || cmdutil.GetDryRunFlag(o.Cmd) { if o.Local || cmdutil.GetDryRunFlag(o.Cmd) {
if err := o.PrintObject(o.Cmd, o.Local, o.Mapper, patch.Info.AsVersioned(), o.Out); err != nil { if err := o.PrintObject(o.Cmd, patch.Info.AsVersioned(), o.Out); err != nil {
return err return err
} }
continue continue
@ -266,7 +263,7 @@ func (o *ResourcesOptions) Run() error {
shortOutput := o.Output == "name" shortOutput := o.Output == "name"
if len(o.Output) > 0 && !shortOutput { if len(o.Output) > 0 && !shortOutput {
if err := o.PrintObject(o.Cmd, o.Local, o.Mapper, info.AsVersioned(), o.Out); err != nil { if err := o.PrintObject(o.Cmd, info.AsVersioned(), o.Out); err != nil {
return err return err
} }
continue continue

View File

@ -152,7 +152,7 @@ func (o *SelectorOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [
} }
o.PrintObject = func(obj runtime.Object) error { o.PrintObject = func(obj runtime.Object) error {
return f.PrintObject(cmd, o.local, mapper, obj, o.out) return f.PrintObject(cmd, obj, o.out)
} }
o.ClientForMapping = func(mapping *meta.RESTMapping) (resource.RESTClient, error) { o.ClientForMapping = func(mapping *meta.RESTMapping) (resource.RESTClient, error) {
return f.ClientForMapping(mapping) return f.ClientForMapping(mapping)

View File

@ -24,7 +24,6 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
utilerrors "k8s.io/apimachinery/pkg/util/errors" utilerrors "k8s.io/apimachinery/pkg/util/errors"
@ -56,7 +55,6 @@ var (
// serviceAccountConfig encapsulates the data required to perform the operation. // serviceAccountConfig encapsulates the data required to perform the operation.
type serviceAccountConfig struct { type serviceAccountConfig struct {
fileNameOptions resource.FilenameOptions fileNameOptions resource.FilenameOptions
mapper meta.RESTMapper
encoder runtime.Encoder encoder runtime.Encoder
out io.Writer out io.Writer
err io.Writer err io.Writer
@ -68,7 +66,7 @@ type serviceAccountConfig struct {
output string output string
changeCause string changeCause string
local bool local bool
PrintObject func(cmd *cobra.Command, isLocal bool, mapper meta.RESTMapper, obj runtime.Object, out io.Writer) error PrintObject func(cmd *cobra.Command, obj runtime.Object, out io.Writer) error
updatePodSpecForObject func(runtime.Object, func(*v1.PodSpec) error) (bool, error) updatePodSpecForObject func(runtime.Object, func(*v1.PodSpec) error) (bool, error)
printSuccess func(shortOutput bool, out io.Writer, resource, name string, dryRun bool, operation string) printSuccess func(shortOutput bool, out io.Writer, resource, name string, dryRun bool, operation string)
infos []*resource.Info infos []*resource.Info
@ -108,7 +106,6 @@ func NewCmdServiceAccount(f cmdutil.Factory, out, err io.Writer) *cobra.Command
// Complete configures serviceAccountConfig from command line args. // Complete configures serviceAccountConfig from command line args.
func (saConfig *serviceAccountConfig) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { func (saConfig *serviceAccountConfig) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
saConfig.mapper, _ = f.Object()
saConfig.encoder = f.JSONEncoder() saConfig.encoder = f.JSONEncoder()
saConfig.shortOutput = cmdutil.GetFlagString(cmd, "output") == "name" saConfig.shortOutput = cmdutil.GetFlagString(cmd, "output") == "name"
saConfig.record = cmdutil.GetRecordFlag(cmd) saConfig.record = cmdutil.GetRecordFlag(cmd)
@ -168,7 +165,7 @@ func (saConfig *serviceAccountConfig) Run() error {
continue continue
} }
if saConfig.local || saConfig.dryRun { if saConfig.local || saConfig.dryRun {
if err := saConfig.PrintObject(saConfig.cmd, saConfig.local, saConfig.mapper, patch.Info.AsVersioned(), saConfig.out); err != nil { if err := saConfig.PrintObject(saConfig.cmd, patch.Info.AsVersioned(), saConfig.out); err != nil {
return err return err
} }
continue continue
@ -187,7 +184,7 @@ func (saConfig *serviceAccountConfig) Run() error {
} }
} }
if len(saConfig.output) > 0 { if len(saConfig.output) > 0 {
if err := saConfig.PrintObject(saConfig.cmd, saConfig.local, saConfig.mapper, info.AsVersioned(), saConfig.out); err != nil { if err := saConfig.PrintObject(saConfig.cmd, info.AsVersioned(), saConfig.out); err != nil {
return err return err
} }
continue continue

View File

@ -37,6 +37,7 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
"k8s.io/client-go/rest/fake" "k8s.io/client-go/rest/fake"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/api/testapi"
"k8s.io/kubernetes/pkg/kubectl/categories" "k8s.io/kubernetes/pkg/kubectl/categories"
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
@ -83,7 +84,7 @@ func TestSetServiceAccountLocal(t *testing.T) {
cmd.Flags().Set("output", "yaml") cmd.Flags().Set("output", "yaml")
cmd.Flags().Set("local", "true") cmd.Flags().Set("local", "true")
testapi.Default = testapi.Groups[input.apiGroup] testapi.Default = testapi.Groups[input.apiGroup]
tf.Printer = printers.NewVersionedPrinter(&printers.YAMLPrinter{}, testapi.Default.Converter(), *testapi.Default.GroupVersion()) tf.Printer = printers.NewVersionedPrinter(&printers.YAMLPrinter{}, legacyscheme.Scheme, legacyscheme.Scheme, scheme.Versions...)
saConfig := serviceAccountConfig{fileNameOptions: resource.FilenameOptions{ saConfig := serviceAccountConfig{fileNameOptions: resource.FilenameOptions{
Filenames: []string{input.yaml}}, Filenames: []string{input.yaml}},
out: out, out: out,
@ -317,7 +318,7 @@ func TestSetServiceAccountRemote(t *testing.T) {
testapi.Default = testapi.Groups[input.testAPIGroup] testapi.Default = testapi.Groups[input.testAPIGroup]
f, tf, _, ns := cmdtesting.NewAPIFactory() f, tf, _, ns := cmdtesting.NewAPIFactory()
codec := scheme.Codecs.CodecForVersions(scheme.Codecs.LegacyCodec(groupVersion), scheme.Codecs.UniversalDecoder(groupVersion), groupVersion, groupVersion) codec := scheme.Codecs.CodecForVersions(scheme.Codecs.LegacyCodec(groupVersion), scheme.Codecs.UniversalDecoder(groupVersion), groupVersion, groupVersion)
tf.Printer = printers.NewVersionedPrinter(&printers.YAMLPrinter{}, testapi.Default.Converter(), *testapi.Default.GroupVersion()) tf.Printer = printers.NewVersionedPrinter(&printers.YAMLPrinter{}, legacyscheme.Scheme, legacyscheme.Scheme, scheme.Versions...)
tf.Namespace = "test" tf.Namespace = "test"
tf.CategoryExpander = categories.LegacyCategoryExpander tf.CategoryExpander = categories.LegacyCategoryExpander
tf.Client = &fake.RESTClient{ tf.Client = &fake.RESTClient{

View File

@ -23,7 +23,6 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
utilerrors "k8s.io/apimachinery/pkg/util/errors" utilerrors "k8s.io/apimachinery/pkg/util/errors"
@ -57,8 +56,6 @@ type updateSubjects func(existings []rbac.Subject, targets []rbac.Subject) (bool
type SubjectOptions struct { type SubjectOptions struct {
resource.FilenameOptions resource.FilenameOptions
Mapper meta.RESTMapper
Typer runtime.ObjectTyper
Infos []*resource.Info Infos []*resource.Info
Encoder runtime.Encoder Encoder runtime.Encoder
Out io.Writer Out io.Writer
@ -74,7 +71,7 @@ type SubjectOptions struct {
Groups []string Groups []string
ServiceAccounts []string ServiceAccounts []string
PrintObject func(mapper meta.RESTMapper, obj runtime.Object, out io.Writer) error PrintObject func(obj runtime.Object, out io.Writer) error
} }
func NewCmdSubject(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command { func NewCmdSubject(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
@ -111,12 +108,11 @@ func NewCmdSubject(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Co
} }
func (o *SubjectOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { func (o *SubjectOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
o.Mapper, o.Typer = f.Object()
o.Encoder = f.JSONEncoder() o.Encoder = f.JSONEncoder()
o.Output = cmdutil.GetFlagString(cmd, "output") o.Output = cmdutil.GetFlagString(cmd, "output")
o.DryRun = cmdutil.GetDryRunFlag(cmd) o.DryRun = cmdutil.GetDryRunFlag(cmd)
o.PrintObject = func(mapper meta.RESTMapper, obj runtime.Object, out io.Writer) error { o.PrintObject = func(obj runtime.Object, out io.Writer) error {
return f.PrintObject(cmd, o.Local, mapper, obj, out) return f.PrintObject(cmd, obj, out)
} }
cmdNamespace, enforceNamespace, err := f.DefaultNamespace() cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
@ -242,7 +238,7 @@ func (o *SubjectOptions) Run(f cmdutil.Factory, fn updateSubjects) error {
} }
if o.Local || o.DryRun { if o.Local || o.DryRun {
if err := o.PrintObject(o.Mapper, info.Object, o.Out); err != nil { if err := o.PrintObject(info.Object, o.Out); err != nil {
return err return err
} }
continue continue
@ -257,7 +253,7 @@ func (o *SubjectOptions) Run(f cmdutil.Factory, fn updateSubjects) error {
shortOutput := o.Output == "name" shortOutput := o.Output == "name"
if len(o.Output) > 0 && !shortOutput { if len(o.Output) > 0 && !shortOutput {
return o.PrintObject(o.Mapper, info.AsVersioned(), o.Out) return o.PrintObject(info.AsVersioned(), o.Out)
} }
f.PrintSuccess(shortOutput, o.Out, info.Mapping.Resource, info.Name, false, "subjects updated") f.PrintSuccess(shortOutput, o.Out, info.Mapping.Resource, info.Name, false, "subjects updated")
} }

View File

@ -28,7 +28,7 @@ import (
) )
func TestValidate(t *testing.T) { func TestValidate(t *testing.T) {
f, tf, _, _ := cmdtesting.NewAPIFactory() _, tf, _, _ := cmdtesting.NewAPIFactory()
tf.Namespace = "test" tf.Namespace = "test"
tests := map[string]struct { tests := map[string]struct {
@ -107,7 +107,6 @@ func TestValidate(t *testing.T) {
} }
for name, test := range tests { for name, test := range tests {
test.options.Mapper, _ = f.Object()
err := test.options.Validate() err := test.options.Validate()
if test.expectErr && err != nil { if test.expectErr && err != nil {
continue continue

View File

@ -274,10 +274,9 @@ func (o TaintOptions) RunTaint() error {
return err return err
} }
mapper, _ := o.f.Object()
outputFormat := cmdutil.GetFlagString(o.cmd, "output") outputFormat := cmdutil.GetFlagString(o.cmd, "output")
if outputFormat != "" { if outputFormat != "" {
return o.f.PrintObject(o.cmd, false, mapper, outputObj, o.out) return o.f.PrintObject(o.cmd, outputObj, o.out)
} }
o.f.PrintSuccess(false, o.out, info.Mapping.Resource, info.Name, false, operation) o.f.PrintSuccess(false, o.out, info.Mapping.Resource, info.Name, false, operation)

View File

@ -368,7 +368,7 @@ func (f *FakeFactory) PrintResourceInfoForCommand(cmd *cobra.Command, info *reso
return err return err
} }
if !printer.IsGeneric() { if !printer.IsGeneric() {
printer, err = f.PrinterForMapping(&printers.PrintOptions{}, nil) printer, err = f.PrinterForMapping(&printers.PrintOptions{})
if err != nil { if err != nil {
return err return err
} }
@ -514,11 +514,11 @@ func (f *FakeFactory) BindFlags(flags *pflag.FlagSet) {
func (f *FakeFactory) BindExternalFlags(flags *pflag.FlagSet) { func (f *FakeFactory) BindExternalFlags(flags *pflag.FlagSet) {
} }
func (f *FakeFactory) PrintObject(cmd *cobra.Command, isLocal bool, mapper meta.RESTMapper, obj runtime.Object, out io.Writer) error { func (f *FakeFactory) PrintObject(cmd *cobra.Command, obj runtime.Object, out io.Writer) error {
return nil return nil
} }
func (f *FakeFactory) PrinterForMapping(printOpts *printers.PrintOptions, mapping *meta.RESTMapping) (printers.ResourcePrinter, error) { func (f *FakeFactory) PrinterForMapping(printOpts *printers.PrintOptions) (printers.ResourcePrinter, error) {
return f.tf.Printer, f.tf.Err return f.tf.Printer, f.tf.Err
} }
@ -763,7 +763,7 @@ func (f *fakeAPIFactory) PrintResourceInfoForCommand(cmd *cobra.Command, info *r
return err return err
} }
if !printer.IsGeneric() { if !printer.IsGeneric() {
printer, err = f.PrinterForMapping(&printers.PrintOptions{}, nil) printer, err = f.PrinterForMapping(&printers.PrintOptions{})
if err != nil { if err != nil {
return err return err
} }
@ -848,25 +848,15 @@ func (f *fakeAPIFactory) Generators(cmdName string) map[string]kubectl.Generator
return cmdutil.DefaultGenerators(cmdName) return cmdutil.DefaultGenerators(cmdName)
} }
func (f *fakeAPIFactory) PrintObject(cmd *cobra.Command, isLocal bool, mapper meta.RESTMapper, obj runtime.Object, out io.Writer) error { func (f *fakeAPIFactory) PrintObject(cmd *cobra.Command, obj runtime.Object, out io.Writer) error {
gvks, _, err := legacyscheme.Scheme.ObjectKinds(obj) printer, err := f.PrinterForMapping(&printers.PrintOptions{})
if err != nil {
return err
}
mapping, err := mapper.RESTMapping(gvks[0].GroupKind())
if err != nil {
return err
}
printer, err := f.PrinterForMapping(&printers.PrintOptions{}, mapping)
if err != nil { if err != nil {
return err return err
} }
return printer.PrintObj(obj, out) return printer.PrintObj(obj, out)
} }
func (f *fakeAPIFactory) PrinterForMapping(outputOpts *printers.PrintOptions, mapping *meta.RESTMapping) (printers.ResourcePrinter, error) { func (f *fakeAPIFactory) PrinterForMapping(outputOpts *printers.PrintOptions) (printers.ResourcePrinter, error) {
return f.tf.Printer, f.tf.Err return f.tf.Printer, f.tf.Err
} }

View File

@ -239,9 +239,9 @@ type BuilderFactory interface {
// Requires that printer flags have been added to cmd (see AddPrinterFlags). // Requires that printer flags have been added to cmd (see AddPrinterFlags).
// Returns a printer, true if the printer is generic (is not internal), or // Returns a printer, true if the printer is generic (is not internal), or
// an error if a printer could not be found. // an error if a printer could not be found.
PrinterForMapping(options *printers.PrintOptions, mapping *meta.RESTMapping) (printers.ResourcePrinter, error) PrinterForMapping(options *printers.PrintOptions) (printers.ResourcePrinter, error)
// PrintObject prints an api object given command line flags to modify the output format // PrintObject prints an api object given command line flags to modify the output format
PrintObject(cmd *cobra.Command, isLocal bool, mapper meta.RESTMapper, obj runtime.Object, out io.Writer) error PrintObject(cmd *cobra.Command, obj runtime.Object, out io.Writer) error
// PrintResourceInfoForCommand receives a *cobra.Command and a *resource.Info and // PrintResourceInfoForCommand receives a *cobra.Command and a *resource.Info and
// attempts to print an info object based on the specified output format. If the // attempts to print an info object based on the specified output format. If the
// object passed is non-generic, it attempts to print the object using a HumanReadablePrinter. // object passed is non-generic, it attempts to print the object using a HumanReadablePrinter.

View File

@ -25,11 +25,12 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/kubectl/plugins" "k8s.io/kubernetes/pkg/kubectl/plugins"
"k8s.io/kubernetes/pkg/kubectl/resource" "k8s.io/kubernetes/pkg/kubectl/resource"
kubectlscheme "k8s.io/kubernetes/pkg/kubectl/scheme"
"k8s.io/kubernetes/pkg/printers" "k8s.io/kubernetes/pkg/printers"
) )
@ -48,34 +49,17 @@ func NewBuilderFactory(clientAccessFactory ClientAccessFactory, objectMappingFac
} }
func (f *ring2Factory) PrinterForOptions(options *printers.PrintOptions) (printers.ResourcePrinter, error) { func (f *ring2Factory) PrinterForOptions(options *printers.PrintOptions) (printers.ResourcePrinter, error) {
_, typer := f.objectMappingFactory.Object() return printerForOptions(options)
// TODO: used by the custom column implementation and the name implementation, break this dependency
decoders := []runtime.Decoder{f.clientAccessFactory.Decoder(true), unstructured.UnstructuredJSONScheme}
encoder := f.clientAccessFactory.JSONEncoder()
return printerForOptions(typer, encoder, decoders, options)
} }
func (f *ring2Factory) PrinterForMapping(options *printers.PrintOptions, mapping *meta.RESTMapping) (printers.ResourcePrinter, error) { func (f *ring2Factory) PrinterForMapping(options *printers.PrintOptions) (printers.ResourcePrinter, error) {
printer, err := f.PrinterForOptions(options) printer, err := f.PrinterForOptions(options)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Make sure we output versioned data for generic printers // wrap the printer in a versioning printer that understands when to convert and when not to convert
if printer.IsGeneric() { printer = printers.NewVersionedPrinter(printer, legacyscheme.Scheme, legacyscheme.Scheme, kubectlscheme.Versions...)
if mapping == nil {
return nil, fmt.Errorf("no serialization format found")
}
version := mapping.GroupVersionKind.GroupVersion()
if version.Empty() {
return nil, fmt.Errorf("no serialization format found")
}
printer = printers.NewVersionedPrinter(printer, mapping.ObjectConvertor, version, mapping.GroupVersionKind.GroupVersion())
}
return printer, nil return printer, nil
} }
@ -101,26 +85,8 @@ func (f *ring2Factory) PrintSuccess(shortOutput bool, out io.Writer, resource, n
} }
} }
func (f *ring2Factory) PrintObject(cmd *cobra.Command, isLocal bool, mapper meta.RESTMapper, obj runtime.Object, out io.Writer) error { func (f *ring2Factory) PrintObject(cmd *cobra.Command, obj runtime.Object, out io.Writer) error {
// try to get a typed object printer, err := f.PrinterForMapping(ExtractCmdPrintOptions(cmd, false))
_, typer := f.objectMappingFactory.Object()
gvks, _, err := typer.ObjectKinds(obj)
if err != nil {
return err
}
// Prefer the existing external version if specified
var preferredVersion []string
if gvks[0].Version != "" && gvks[0].Version != runtime.APIVersionInternal {
preferredVersion = []string{gvks[0].Version}
}
mapping, err := mapper.RESTMapping(gvks[0].GroupKind(), preferredVersion...)
if err != nil {
return err
}
printer, err := f.PrinterForMapping(ExtractCmdPrintOptions(cmd, false), mapping)
if err != nil { if err != nil {
return err return err
} }
@ -134,7 +100,7 @@ func (f *ring2Factory) PrintResourceInfoForCommand(cmd *cobra.Command, info *res
return err return err
} }
if !printer.IsGeneric() { if !printer.IsGeneric() {
printer, err = f.PrinterForMapping(printOpts, nil) printer, err = f.PrinterForMapping(printOpts)
if err != nil { if err != nil {
return err return err
} }

View File

@ -23,10 +23,12 @@ import (
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl"
"k8s.io/kubernetes/pkg/kubectl/cmd/templates" "k8s.io/kubernetes/pkg/kubectl/cmd/templates"
kubectlscheme "k8s.io/kubernetes/pkg/kubectl/scheme"
"k8s.io/kubernetes/pkg/printers" "k8s.io/kubernetes/pkg/printers"
printersinternal "k8s.io/kubernetes/pkg/printers/internalversion" printersinternal "k8s.io/kubernetes/pkg/printers/internalversion"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
) )
// AddPrinterFlags adds printing related flags to a command (e.g. output format, no headers, template path) // AddPrinterFlags adds printing related flags to a command (e.g. output format, no headers, template path)
@ -83,8 +85,12 @@ func ValidateOutputArgs(cmd *cobra.Command) error {
// printerForOptions returns the printer for the outputOptions (if given) or // printerForOptions returns the printer for the outputOptions (if given) or
// returns the default printer for the command. Requires that printer flags have // returns the default printer for the command. Requires that printer flags have
// been added to cmd (see AddPrinterFlags). // been added to cmd (see AddPrinterFlags).
func printerForOptions(typer runtime.ObjectTyper, encoder runtime.Encoder, decoders []runtime.Decoder, options *printers.PrintOptions) (printers.ResourcePrinter, error) { func printerForOptions(options *printers.PrintOptions) (printers.ResourcePrinter, error) {
printer, err := printers.GetStandardPrinter(typer, encoder, decoders, *options) // TODO: used by the custom column implementation and the name implementation, break this dependency
decoders := []runtime.Decoder{kubectlscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}
encoder := kubectlscheme.Codecs.LegacyCodec(kubectlscheme.Registry.EnabledVersions()...)
printer, err := printers.GetStandardPrinter(kubectlscheme.Scheme, encoder, decoders, *options)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -60,6 +60,7 @@ func init() {
scheme.AddToScheme(Scheme) scheme.AddToScheme(Scheme)
// Register external types for Registry // Register external types for Registry
Versions = append(Versions, corev1.SchemeGroupVersion)
if err := announced.NewGroupMetaFactory( if err := announced.NewGroupMetaFactory(
&announced.GroupMetaFactoryArgs{ &announced.GroupMetaFactoryArgs{
GroupName: corev1.GroupName, GroupName: corev1.GroupName,
@ -90,6 +91,7 @@ func init() {
panic(err) panic(err)
} }
Versions = append(Versions, admissionv1alpha1.SchemeGroupVersion)
if err := announced.NewGroupMetaFactory( if err := announced.NewGroupMetaFactory(
&announced.GroupMetaFactoryArgs{ &announced.GroupMetaFactoryArgs{
GroupName: admissionv1alpha1.GroupName, GroupName: admissionv1alpha1.GroupName,
@ -103,6 +105,7 @@ func init() {
panic(err) panic(err)
} }
Versions = append(Versions, admissionregistrationv1alpha1.SchemeGroupVersion)
if err := announced.NewGroupMetaFactory( if err := announced.NewGroupMetaFactory(
&announced.GroupMetaFactoryArgs{ &announced.GroupMetaFactoryArgs{
GroupName: admissionregistrationv1alpha1.GroupName, GroupName: admissionregistrationv1alpha1.GroupName,
@ -116,6 +119,7 @@ func init() {
panic(err) panic(err)
} }
Versions = append(Versions, appsv1.SchemeGroupVersion, appsv1beta2.SchemeGroupVersion, appsv1beta1.SchemeGroupVersion)
if err := announced.NewGroupMetaFactory( if err := announced.NewGroupMetaFactory(
&announced.GroupMetaFactoryArgs{ &announced.GroupMetaFactoryArgs{
GroupName: appsv1.GroupName, GroupName: appsv1.GroupName,
@ -130,6 +134,7 @@ func init() {
panic(err) panic(err)
} }
Versions = append(Versions, authenticationv1.SchemeGroupVersion, authenticationv1beta1.SchemeGroupVersion)
if err := announced.NewGroupMetaFactory( if err := announced.NewGroupMetaFactory(
&announced.GroupMetaFactoryArgs{ &announced.GroupMetaFactoryArgs{
GroupName: authenticationv1beta1.GroupName, GroupName: authenticationv1beta1.GroupName,
@ -144,6 +149,7 @@ func init() {
panic(err) panic(err)
} }
Versions = append(Versions, authorizationv1.SchemeGroupVersion, authorizationv1beta1.SchemeGroupVersion)
if err := announced.NewGroupMetaFactory( if err := announced.NewGroupMetaFactory(
&announced.GroupMetaFactoryArgs{ &announced.GroupMetaFactoryArgs{
GroupName: authorizationv1.GroupName, GroupName: authorizationv1.GroupName,
@ -158,6 +164,7 @@ func init() {
panic(err) panic(err)
} }
Versions = append(Versions, autoscalingv1.SchemeGroupVersion, autoscalingv2beta1.SchemeGroupVersion)
if err := announced.NewGroupMetaFactory( if err := announced.NewGroupMetaFactory(
&announced.GroupMetaFactoryArgs{ &announced.GroupMetaFactoryArgs{
GroupName: autoscalingv1.GroupName, GroupName: autoscalingv1.GroupName,
@ -171,6 +178,7 @@ func init() {
panic(err) panic(err)
} }
Versions = append(Versions, batchv1.SchemeGroupVersion, batchv1beta1.SchemeGroupVersion, batchv2alpha1.SchemeGroupVersion)
if err := announced.NewGroupMetaFactory( if err := announced.NewGroupMetaFactory(
&announced.GroupMetaFactoryArgs{ &announced.GroupMetaFactoryArgs{
GroupName: batchv1.GroupName, GroupName: batchv1.GroupName,
@ -185,6 +193,7 @@ func init() {
panic(err) panic(err)
} }
Versions = append(Versions, certificatesv1beta1.SchemeGroupVersion)
if err := announced.NewGroupMetaFactory( if err := announced.NewGroupMetaFactory(
&announced.GroupMetaFactoryArgs{ &announced.GroupMetaFactoryArgs{
GroupName: certificatesv1beta1.GroupName, GroupName: certificatesv1beta1.GroupName,
@ -198,6 +207,7 @@ func init() {
panic(err) panic(err)
} }
Versions = append(Versions, extensionsv1beta1.SchemeGroupVersion)
if err := announced.NewGroupMetaFactory( if err := announced.NewGroupMetaFactory(
&announced.GroupMetaFactoryArgs{ &announced.GroupMetaFactoryArgs{
GroupName: extensionsv1beta1.GroupName, GroupName: extensionsv1beta1.GroupName,
@ -211,6 +221,7 @@ func init() {
panic(err) panic(err)
} }
Versions = append(Versions, imagepolicyv1alpha1.SchemeGroupVersion)
if err := announced.NewGroupMetaFactory( if err := announced.NewGroupMetaFactory(
&announced.GroupMetaFactoryArgs{ &announced.GroupMetaFactoryArgs{
GroupName: imagepolicyv1alpha1.GroupName, GroupName: imagepolicyv1alpha1.GroupName,
@ -224,6 +235,7 @@ func init() {
panic(err) panic(err)
} }
Versions = append(Versions, networkingv1.SchemeGroupVersion)
if err := announced.NewGroupMetaFactory( if err := announced.NewGroupMetaFactory(
&announced.GroupMetaFactoryArgs{ &announced.GroupMetaFactoryArgs{
GroupName: networkingv1.GroupName, GroupName: networkingv1.GroupName,
@ -236,6 +248,7 @@ func init() {
panic(err) panic(err)
} }
Versions = append(Versions, policyv1beta1.SchemeGroupVersion)
if err := announced.NewGroupMetaFactory( if err := announced.NewGroupMetaFactory(
&announced.GroupMetaFactoryArgs{ &announced.GroupMetaFactoryArgs{
GroupName: policyv1beta1.GroupName, GroupName: policyv1beta1.GroupName,
@ -248,6 +261,7 @@ func init() {
panic(err) panic(err)
} }
Versions = append(Versions, rbacv1.SchemeGroupVersion, rbacv1beta1.SchemeGroupVersion, rbacv1alpha1.SchemeGroupVersion)
if err := announced.NewGroupMetaFactory( if err := announced.NewGroupMetaFactory(
&announced.GroupMetaFactoryArgs{ &announced.GroupMetaFactoryArgs{
GroupName: rbacv1.GroupName, GroupName: rbacv1.GroupName,
@ -263,6 +277,7 @@ func init() {
panic(err) panic(err)
} }
Versions = append(Versions, schedulingv1alpha1.SchemeGroupVersion)
if err := announced.NewGroupMetaFactory( if err := announced.NewGroupMetaFactory(
&announced.GroupMetaFactoryArgs{ &announced.GroupMetaFactoryArgs{
GroupName: schedulingv1alpha1.GroupName, GroupName: schedulingv1alpha1.GroupName,
@ -276,6 +291,7 @@ func init() {
panic(err) panic(err)
} }
Versions = append(Versions, settingsv1alpha1.SchemeGroupVersion)
if err := announced.NewGroupMetaFactory( if err := announced.NewGroupMetaFactory(
&announced.GroupMetaFactoryArgs{ &announced.GroupMetaFactoryArgs{
GroupName: settingsv1alpha1.GroupName, GroupName: settingsv1alpha1.GroupName,
@ -288,6 +304,7 @@ func init() {
panic(err) panic(err)
} }
Versions = append(Versions, storagev1.SchemeGroupVersion, storagev1beta1.SchemeGroupVersion)
if err := announced.NewGroupMetaFactory( if err := announced.NewGroupMetaFactory(
&announced.GroupMetaFactoryArgs{ &announced.GroupMetaFactoryArgs{
GroupName: storagev1.GroupName, GroupName: storagev1.GroupName,

View File

@ -22,6 +22,7 @@ import (
"k8s.io/apimachinery/pkg/apimachinery/announced" "k8s.io/apimachinery/pkg/apimachinery/announced"
"k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/apimachinery/registered"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/apimachinery/pkg/runtime/serializer"
) )
@ -41,3 +42,8 @@ var Codecs = serializer.NewCodecFactory(Scheme)
// ParameterCodec handles versioning of objects that are converted to query parameters. // ParameterCodec handles versioning of objects that are converted to query parameters.
var ParameterCodec = runtime.NewParameterCodec(Scheme) var ParameterCodec = runtime.NewParameterCodec(Scheme)
// Versions is a list of group versions in order of preferred serialization. This used to be discovered dynamically,
// from the server for use in the client, but that gives conflicting lists of non-existent versions. This only needs to
// live until we stop attempting to perform any conversion client-side and is only valid for items existent in our scheme.
var Versions = []schema.GroupVersion{}

View File

@ -91,6 +91,7 @@ func TestVersionedPrinter(t *testing.T) {
return nil return nil
}), }),
legacyscheme.Scheme, legacyscheme.Scheme,
legacyscheme.Scheme,
legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion, legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion,
) )
if err := p.PrintObj(original, nil); err != nil { if err := p.PrintObj(original, nil); err != nil {
@ -288,7 +289,7 @@ func TestPrinter(t *testing.T) {
t.Errorf("in %s, unexpected error: %#v", test.Name, err) t.Errorf("in %s, unexpected error: %#v", test.Name, err)
} }
if printer.IsGeneric() && len(test.OutputVersions) > 0 { if printer.IsGeneric() && len(test.OutputVersions) > 0 {
printer = printers.NewVersionedPrinter(printer, legacyscheme.Scheme, test.OutputVersions...) printer = printers.NewVersionedPrinter(printer, legacyscheme.Scheme, legacyscheme.Scheme, test.OutputVersions...)
} }
if err := printer.PrintObj(test.Input, buf); err != nil { if err := printer.PrintObj(test.Input, buf); err != nil {
t.Errorf("in %s, unexpected error: %#v", test.Name, err) t.Errorf("in %s, unexpected error: %#v", test.Name, err)
@ -622,7 +623,7 @@ func TestTemplateStrings(t *testing.T) {
t.Fatalf("tmpl fail: %v", err) t.Fatalf("tmpl fail: %v", err)
} }
printer := printers.NewVersionedPrinter(p, legacyscheme.Scheme, legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion) printer := printers.NewVersionedPrinter(p, legacyscheme.Scheme, legacyscheme.Scheme, legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion)
for name, item := range table { for name, item := range table {
buffer := &bytes.Buffer{} buffer := &bytes.Buffer{}
@ -655,19 +656,19 @@ func TestPrinters(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
templatePrinter = printers.NewVersionedPrinter(templatePrinter, legacyscheme.Scheme, v1.SchemeGroupVersion) templatePrinter = printers.NewVersionedPrinter(templatePrinter, legacyscheme.Scheme, legacyscheme.Scheme, v1.SchemeGroupVersion)
templatePrinter2, err = printers.NewTemplatePrinter([]byte("{{len .items}}")) templatePrinter2, err = printers.NewTemplatePrinter([]byte("{{len .items}}"))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
templatePrinter2 = printers.NewVersionedPrinter(templatePrinter2, legacyscheme.Scheme, v1.SchemeGroupVersion) templatePrinter2 = printers.NewVersionedPrinter(templatePrinter2, legacyscheme.Scheme, legacyscheme.Scheme, v1.SchemeGroupVersion)
jsonpathPrinter, err = printers.NewJSONPathPrinter("{.metadata.name}") jsonpathPrinter, err = printers.NewJSONPathPrinter("{.metadata.name}")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
jsonpathPrinter = printers.NewVersionedPrinter(jsonpathPrinter, legacyscheme.Scheme, v1.SchemeGroupVersion) jsonpathPrinter = printers.NewVersionedPrinter(jsonpathPrinter, legacyscheme.Scheme, legacyscheme.Scheme, v1.SchemeGroupVersion)
allPrinters := map[string]printers.ResourcePrinter{ allPrinters := map[string]printers.ResourcePrinter{
"humanReadable": printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{ "humanReadable": printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{

View File

@ -20,6 +20,7 @@ import (
"fmt" "fmt"
"io" "io"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
) )
@ -29,14 +30,16 @@ import (
type VersionedPrinter struct { type VersionedPrinter struct {
printer ResourcePrinter printer ResourcePrinter
converter runtime.ObjectConvertor converter runtime.ObjectConvertor
typer runtime.ObjectTyper
versions []schema.GroupVersion versions []schema.GroupVersion
} }
// NewVersionedPrinter wraps a printer to convert objects to a known API version prior to printing. // NewVersionedPrinter wraps a printer to convert objects to a known API version prior to printing.
func NewVersionedPrinter(printer ResourcePrinter, converter runtime.ObjectConvertor, versions ...schema.GroupVersion) ResourcePrinter { func NewVersionedPrinter(printer ResourcePrinter, converter runtime.ObjectConvertor, typer runtime.ObjectTyper, versions ...schema.GroupVersion) ResourcePrinter {
return &VersionedPrinter{ return &VersionedPrinter{
printer: printer, printer: printer,
converter: converter, converter: converter,
typer: typer,
versions: versions, versions: versions,
} }
} }
@ -47,6 +50,33 @@ func (p *VersionedPrinter) AfterPrint(w io.Writer, res string) error {
// PrintObj implements ResourcePrinter // PrintObj implements ResourcePrinter
func (p *VersionedPrinter) PrintObj(obj runtime.Object, w io.Writer) error { func (p *VersionedPrinter) PrintObj(obj runtime.Object, w io.Writer) error {
gvks, _, err := p.typer.ObjectKinds(obj)
if err != nil {
return err
}
needsConversion := false
for _, gvk := range gvks {
if len(gvk.Version) == 0 || gvk.Version == runtime.APIVersionInternal {
needsConversion = true
}
}
// if we're unstructured, no conversion necessary
if _, ok := obj.(*unstructured.Unstructured); ok {
return p.printer.PrintObj(obj, w)
}
// if we aren't a generic printer, we don't convert. This means the printer must be aware of what it is getting.
// The default printers fall into this category.
// TODO eventually, all printers must be generic
if !p.IsGeneric() {
return p.printer.PrintObj(obj, w)
}
// if we're already external, no conversion necessary
if !needsConversion {
return p.printer.PrintObj(obj, w)
}
if len(p.versions) == 0 { if len(p.versions) == 0 {
return fmt.Errorf("no version specified, object cannot be converted") return fmt.Errorf("no version specified, object cannot be converted")
} }