diff --git a/pkg/kubectl/cmd/annotate.go b/pkg/kubectl/cmd/annotate.go index cfe9b9f4495..e056e55466b 100644 --- a/pkg/kubectl/cmd/annotate.go +++ b/pkg/kubectl/cmd/annotate.go @@ -266,9 +266,8 @@ func (o AnnotateOptions) RunAnnotate(f cmdutil.Factory, cmd *cobra.Command) erro } } - mapper := r.Mapper().RESTMapper 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") return nil diff --git a/pkg/kubectl/cmd/autoscale.go b/pkg/kubectl/cmd/autoscale.go index 6a13bb71679..4dd45f3fb9e 100644 --- a/pkg/kubectl/cmd/autoscale.go +++ b/pkg/kubectl/cmd/autoscale.go @@ -156,7 +156,7 @@ func RunAutoscale(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []s object = hpa.Object } 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 { @@ -170,7 +170,7 @@ func RunAutoscale(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []s count++ 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") diff --git a/pkg/kubectl/cmd/cmd_test.go b/pkg/kubectl/cmd/cmd_test.go index dcfe0d490df..03e0fa63394 100644 --- a/pkg/kubectl/cmd/cmd_test.go +++ b/pkg/kubectl/cmd/cmd_test.go @@ -237,8 +237,7 @@ func Example_printReplicationControllerWithNamespace() { ReadyReplicas: 1, }, } - mapper, _ := f.Object() - err := f.PrintObject(cmd, false, mapper, ctrl, os.Stdout) + err := f.PrintObject(cmd, ctrl, os.Stdout) if err != nil { fmt.Printf("Unexpected error: %v", err) } @@ -291,8 +290,7 @@ func Example_printMultiContainersReplicationControllerWithWide() { Replicas: 1, }, } - mapper, _ := f.Object() - err := f.PrintObject(cmd, false, mapper, ctrl, os.Stdout) + err := f.PrintObject(cmd, ctrl, os.Stdout) if err != nil { fmt.Printf("Unexpected error: %v", err) } @@ -344,8 +342,7 @@ func Example_printReplicationController() { Replicas: 1, }, } - mapper, _ := f.Object() - err := f.PrintObject(cmd, false, mapper, ctrl, os.Stdout) + err := f.PrintObject(cmd, ctrl, os.Stdout) if err != nil { fmt.Printf("Unexpected error: %v", err) } @@ -386,8 +383,7 @@ func Example_printPodWithWideFormat() { PodIP: "10.1.1.3", }, } - mapper, _ := f.Object() - err := f.PrintObject(cmd, false, mapper, pod, os.Stdout) + err := f.PrintObject(cmd, pod, os.Stdout) if err != nil { fmt.Printf("Unexpected error: %v", err) } @@ -431,8 +427,7 @@ func Example_printPodWithShowLabels() { }, }, } - mapper, _ := f.Object() - err := f.PrintObject(cmd, false, mapper, pod, os.Stdout) + err := f.PrintObject(cmd, pod, os.Stdout) if err != nil { fmt.Printf("Unexpected error: %v", err) } @@ -554,8 +549,7 @@ func Example_printPodHideTerminated() { fmt.Printf("Unexpected filter error: %v\n", errs) } for _, pod := range filteredPodList { - mapper, _ := f.Object() - err := f.PrintObject(cmd, false, mapper, pod, os.Stdout) + err := f.PrintObject(cmd, pod, os.Stdout) if err != nil { fmt.Printf("Unexpected error: %v", err) } @@ -581,8 +575,7 @@ func Example_printPodShowAll() { } cmd := NewCmdRun(f, os.Stdin, os.Stdout, os.Stderr) podList := newAllPhasePodList() - mapper, _ := f.Object() - err := f.PrintObject(cmd, false, mapper, podList, os.Stdout) + err := f.PrintObject(cmd, podList, os.Stdout) if err != nil { fmt.Printf("Unexpected error: %v", err) } @@ -657,8 +650,7 @@ func Example_printServiceWithNamespacesAndLabels() { } ld := strings.NewLineDelimiter(os.Stdout, "|") defer ld.Flush() - mapper, _ := f.Object() - err := f.PrintObject(cmd, false, mapper, svc, ld) + err := f.PrintObject(cmd, svc, ld) if err != nil { fmt.Printf("Unexpected error: %v", err) } diff --git a/pkg/kubectl/cmd/config/view.go b/pkg/kubectl/cmd/config/view.go index d6b9de100dc..17e4468c2b6 100644 --- a/pkg/kubectl/cmd/config/view.go +++ b/pkg/kubectl/cmd/config/view.go @@ -82,7 +82,6 @@ func NewCmdConfigView(f cmdutil.Factory, out, errOut io.Writer, ConfigAccess cli printOpts := cmdutil.ExtractCmdPrintOptions(cmd, false) printer, err := f.PrinterForOptions(printOpts) cmdutil.CheckErr(err) - printer = printers.NewVersionedPrinter(printer, latest.Scheme, latest.ExternalVersion) cmdutil.CheckErr(options.Run(out, printer)) }, @@ -120,7 +119,12 @@ func (o ViewOptions) Run(out io.Writer, printer printers.ResourcePrinter) error 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 { return err } diff --git a/pkg/kubectl/cmd/create.go b/pkg/kubectl/cmd/create.go index 3b809eff9b1..0e982a70572 100644 --- a/pkg/kubectl/cmd/create.go +++ b/pkg/kubectl/cmd/create.go @@ -360,5 +360,5 @@ func RunCreateSubcommand(f cmdutil.Factory, cmd *cobra.Command, out io.Writer, o return nil } - return f.PrintObject(cmd, false, mapper, obj, out) + return f.PrintObject(cmd, obj, out) } diff --git a/pkg/kubectl/cmd/create_role.go b/pkg/kubectl/cmd/create_role.go index 6677e3bb010..e332acc905a 100644 --- a/pkg/kubectl/cmd/create_role.go +++ b/pkg/kubectl/cmd/create_role.go @@ -206,7 +206,7 @@ func (c *CreateRoleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args } 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() diff --git a/pkg/kubectl/cmd/expose.go b/pkg/kubectl/cmd/expose.go index 772951c1f7f..3a99079ed5a 100644 --- a/pkg/kubectl/cmd/expose.go +++ b/pkg/kubectl/cmd/expose.go @@ -255,7 +255,7 @@ func RunExpose(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri info.Refresh(object, true) if cmdutil.GetDryRunFlag(cmd) { 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") 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 { - 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") diff --git a/pkg/kubectl/cmd/label.go b/pkg/kubectl/cmd/label.go index 03dc331aa90..68b77df42e5 100644 --- a/pkg/kubectl/cmd/label.go +++ b/pkg/kubectl/cmd/label.go @@ -288,7 +288,7 @@ func (o *LabelOptions) RunLabel(f cmdutil.Factory, cmd *cobra.Command) error { } 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) return nil diff --git a/pkg/kubectl/cmd/resource/BUILD b/pkg/kubectl/cmd/resource/BUILD index cea1a70a4d8..f16becbd663 100644 --- a/pkg/kubectl/cmd/resource/BUILD +++ b/pkg/kubectl/cmd/resource/BUILD @@ -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/unstructured: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/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", diff --git a/pkg/kubectl/cmd/resource/get.go b/pkg/kubectl/cmd/resource/get.go index 234c413c3a9..c4be5f711f4 100644 --- a/pkg/kubectl/cmd/resource/get.go +++ b/pkg/kubectl/cmd/resource/get.go @@ -32,6 +32,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/sets" "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) } - printer, err = f.PrinterForMapping(printOpts, mapping) + printer, err = f.PrinterForMapping(printOpts) if err != nil { if !errs.Has(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] mapping := info.ResourceMapping() printOpts := cmdutil.ExtractCmdPrintOptions(cmd, options.AllNamespaces) - printer, err := f.PrinterForMapping(printOpts, mapping) + printer, err := f.PrinterForMapping(printOpts) if err != nil { 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 err != nil { 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) } } @@ -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 err != nil { 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 } } @@ -569,6 +582,16 @@ func (options *GetOptions) watch(f cmdutil.Factory, cmd *cobra.Command, args []s 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 { // 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 diff --git a/pkg/kubectl/cmd/rollingupdate.go b/pkg/kubectl/cmd/rollingupdate.go index 96c12fcf6f5..d829543acbc 100644 --- a/pkg/kubectl/cmd/rollingupdate.go +++ b/pkg/kubectl/cmd/rollingupdate.go @@ -191,8 +191,6 @@ func RunRollingUpdate(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args var keepOldName bool var replicasDefaulted bool - mapper, _ := f.Object() - if len(filename) != 0 { schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate")) if err != nil { @@ -322,10 +320,10 @@ func RunRollingUpdate(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args oldRcData.WriteString(oldRc.Name) newRcData.WriteString(newRc.Name) } else { - if err := f.PrintObject(cmd, false, mapper, oldRc, oldRcData); err != nil { + if err := f.PrintObject(cmd, oldRc, oldRcData); err != nil { return err } - if err := f.PrintObject(cmd, false, mapper, newRc, newRcData); err != nil { + if err := f.PrintObject(cmd, newRc, newRcData); err != nil { return err } } @@ -370,7 +368,7 @@ func RunRollingUpdate(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args return err } if outputFormat != "" { - return f.PrintObject(cmd, false, mapper, newRc, out) + return f.PrintObject(cmd, newRc, out) } f.PrintSuccess(false, out, "replicationcontrollers", oldName, dryrun, message) return nil diff --git a/pkg/kubectl/cmd/run.go b/pkg/kubectl/cmd/run.go index 25941cb6154..08a6c0ef56e 100644 --- a/pkg/kubectl/cmd/run.go +++ b/pkg/kubectl/cmd/run.go @@ -407,7 +407,7 @@ func RunRun(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *c if runObject != nil { outputFormat := cmdutil.GetFlagString(cmd, "output") 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") } @@ -557,7 +557,7 @@ func generateService(f cmdutil.Factory, cmd *cobra.Command, args []string, servi } 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 { return nil, err } diff --git a/pkg/kubectl/cmd/set/BUILD b/pkg/kubectl/cmd/set/BUILD index 64f1e6dc7d8..a3513d85515 100644 --- a/pkg/kubectl/cmd/set/BUILD +++ b/pkg/kubectl/cmd/set/BUILD @@ -59,6 +59,7 @@ go_test( embed = [":go_default_library"], importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/set", deps = [ + "//pkg/api/legacyscheme:go_default_library", "//pkg/api/testapi:go_default_library", "//pkg/apis/rbac:go_default_library", "//pkg/kubectl/categories:go_default_library", diff --git a/pkg/kubectl/cmd/set/set_env.go b/pkg/kubectl/cmd/set/set_env.go index 1e27b77dea9..5311dcbea35 100644 --- a/pkg/kubectl/cmd/set/set_env.go +++ b/pkg/kubectl/cmd/set/set_env.go @@ -26,7 +26,6 @@ import ( "github.com/spf13/cobra" "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/kubernetes" @@ -116,7 +115,6 @@ type EnvOptions struct { From string Prefix string - Mapper meta.RESTMapper Builder *resource.Builder Infos []*resource.Info Encoder runtime.Encoder @@ -124,7 +122,7 @@ type EnvOptions struct { Cmd *cobra.Command 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 @@ -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 or /") } - o.Mapper, _ = f.Object() o.UpdatePodSpecForObject = f.UpdatePodSpecForObject o.Encoder = f.JSONEncoder() 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 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 } continue @@ -437,7 +434,7 @@ func (o *EnvOptions) RunEnv(f cmdutil.Factory) error { } 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 } continue diff --git a/pkg/kubectl/cmd/set/set_env_test.go b/pkg/kubectl/cmd/set/set_env_test.go index 2004fdf84c3..64ec338fba2 100644 --- a/pkg/kubectl/cmd/set/set_env_test.go +++ b/pkg/kubectl/cmd/set/set_env_test.go @@ -38,6 +38,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" restclient "k8s.io/client-go/rest" "k8s.io/client-go/rest/fake" + "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/kubectl/categories" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" @@ -435,7 +436,7 @@ func TestSetEnvRemote(t *testing.T) { testapi.Default = testapi.Groups[input.testAPIGroup] f, tf, _, ns := cmdtesting.NewAPIFactory() 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.CategoryExpander = categories.LegacyCategoryExpander tf.Client = &fake.RESTClient{ diff --git a/pkg/kubectl/cmd/set/set_image.go b/pkg/kubectl/cmd/set/set_image.go index 09a12d038ec..e46cf43383e 100644 --- a/pkg/kubectl/cmd/set/set_image.go +++ b/pkg/kubectl/cmd/set/set_image.go @@ -22,7 +22,6 @@ import ( "github.com/spf13/cobra" "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" @@ -37,7 +36,6 @@ import ( type ImageOptions struct { resource.FilenameOptions - Mapper meta.RESTMapper Infos []*resource.Info Encoder runtime.Encoder Decoder runtime.Decoder @@ -55,7 +53,7 @@ type ImageOptions struct { ResolveImage func(in string) (string, error) 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) Resources []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 { - o.Mapper, _ = f.Object() o.PrintSuccess = f.PrintSuccess o.UpdatePodSpecForObject = f.UpdatePodSpecForObject o.Encoder = f.JSONEncoder() @@ -249,7 +246,7 @@ func (o *ImageOptions) Run() error { } 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 } continue @@ -275,7 +272,7 @@ func (o *ImageOptions) Run() error { info.Refresh(obj, true) 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 } continue diff --git a/pkg/kubectl/cmd/set/set_image_test.go b/pkg/kubectl/cmd/set/set_image_test.go index 05ee7d99fbd..d63aee55226 100644 --- a/pkg/kubectl/cmd/set/set_image_test.go +++ b/pkg/kubectl/cmd/set/set_image_test.go @@ -37,6 +37,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" restclient "k8s.io/client-go/rest" "k8s.io/client-go/rest/fake" + "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/kubectl/categories" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" @@ -502,7 +503,7 @@ func TestSetImageRemote(t *testing.T) { testapi.Default = testapi.Groups[input.testAPIGroup] f, tf, _, ns := cmdtesting.NewAPIFactory() 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.CategoryExpander = categories.LegacyCategoryExpander tf.Client = &fake.RESTClient{ diff --git a/pkg/kubectl/cmd/set/set_resources.go b/pkg/kubectl/cmd/set/set_resources.go index e1a65e2355b..636f0eb2aac 100644 --- a/pkg/kubectl/cmd/set/set_resources.go +++ b/pkg/kubectl/cmd/set/set_resources.go @@ -23,7 +23,6 @@ import ( "github.com/spf13/cobra" "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" @@ -62,7 +61,6 @@ var ( type ResourcesOptions struct { resource.FilenameOptions - Mapper meta.RESTMapper Infos []*resource.Info Encoder runtime.Encoder Out io.Writer @@ -81,7 +79,7 @@ type ResourcesOptions struct { ResourceRequirements v1.ResourceRequirements 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) 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 { - o.Mapper, _ = f.Object() o.PrintSuccess = f.PrintSuccess o.UpdatePodSpecForObject = f.UpdatePodSpecForObject o.Encoder = f.JSONEncoder() @@ -241,7 +238,7 @@ func (o *ResourcesOptions) Run() error { } 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 } continue @@ -266,7 +263,7 @@ func (o *ResourcesOptions) Run() error { shortOutput := o.Output == "name" 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 } continue diff --git a/pkg/kubectl/cmd/set/set_selector.go b/pkg/kubectl/cmd/set/set_selector.go index 37664d8f378..bfda43b4945 100644 --- a/pkg/kubectl/cmd/set/set_selector.go +++ b/pkg/kubectl/cmd/set/set_selector.go @@ -152,7 +152,7 @@ func (o *SelectorOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [ } 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) { return f.ClientForMapping(mapping) diff --git a/pkg/kubectl/cmd/set/set_serviceaccount.go b/pkg/kubectl/cmd/set/set_serviceaccount.go index a3781e0ab73..3de2764d9bc 100644 --- a/pkg/kubectl/cmd/set/set_serviceaccount.go +++ b/pkg/kubectl/cmd/set/set_serviceaccount.go @@ -24,7 +24,6 @@ import ( "github.com/spf13/cobra" "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" @@ -56,7 +55,6 @@ var ( // serviceAccountConfig encapsulates the data required to perform the operation. type serviceAccountConfig struct { fileNameOptions resource.FilenameOptions - mapper meta.RESTMapper encoder runtime.Encoder out io.Writer err io.Writer @@ -68,7 +66,7 @@ type serviceAccountConfig struct { output string changeCause string 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) printSuccess func(shortOutput bool, out io.Writer, resource, name string, dryRun bool, operation string) 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. func (saConfig *serviceAccountConfig) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { - saConfig.mapper, _ = f.Object() saConfig.encoder = f.JSONEncoder() saConfig.shortOutput = cmdutil.GetFlagString(cmd, "output") == "name" saConfig.record = cmdutil.GetRecordFlag(cmd) @@ -168,7 +165,7 @@ func (saConfig *serviceAccountConfig) Run() error { continue } 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 } continue @@ -187,7 +184,7 @@ func (saConfig *serviceAccountConfig) Run() error { } } 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 } continue diff --git a/pkg/kubectl/cmd/set/set_serviceaccount_test.go b/pkg/kubectl/cmd/set/set_serviceaccount_test.go index eacce264da0..6c07ffbff8e 100644 --- a/pkg/kubectl/cmd/set/set_serviceaccount_test.go +++ b/pkg/kubectl/cmd/set/set_serviceaccount_test.go @@ -37,6 +37,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" restclient "k8s.io/client-go/rest" "k8s.io/client-go/rest/fake" + "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/kubectl/categories" 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("local", "true") 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{ Filenames: []string{input.yaml}}, out: out, @@ -317,7 +318,7 @@ func TestSetServiceAccountRemote(t *testing.T) { testapi.Default = testapi.Groups[input.testAPIGroup] f, tf, _, ns := cmdtesting.NewAPIFactory() 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.CategoryExpander = categories.LegacyCategoryExpander tf.Client = &fake.RESTClient{ diff --git a/pkg/kubectl/cmd/set/set_subject.go b/pkg/kubectl/cmd/set/set_subject.go index d2abe622f80..bf337bb98ea 100644 --- a/pkg/kubectl/cmd/set/set_subject.go +++ b/pkg/kubectl/cmd/set/set_subject.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" @@ -57,8 +56,6 @@ type updateSubjects func(existings []rbac.Subject, targets []rbac.Subject) (bool type SubjectOptions struct { resource.FilenameOptions - Mapper meta.RESTMapper - Typer runtime.ObjectTyper Infos []*resource.Info Encoder runtime.Encoder Out io.Writer @@ -74,7 +71,7 @@ type SubjectOptions struct { Groups []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 { @@ -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 { - o.Mapper, o.Typer = f.Object() o.Encoder = f.JSONEncoder() o.Output = cmdutil.GetFlagString(cmd, "output") o.DryRun = cmdutil.GetDryRunFlag(cmd) - o.PrintObject = func(mapper meta.RESTMapper, obj runtime.Object, out io.Writer) error { - return f.PrintObject(cmd, o.Local, mapper, obj, out) + o.PrintObject = func(obj runtime.Object, out io.Writer) error { + return f.PrintObject(cmd, obj, out) } 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 err := o.PrintObject(o.Mapper, info.Object, o.Out); err != nil { + if err := o.PrintObject(info.Object, o.Out); err != nil { return err } continue @@ -257,7 +253,7 @@ func (o *SubjectOptions) Run(f cmdutil.Factory, fn updateSubjects) error { shortOutput := o.Output == "name" 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") } diff --git a/pkg/kubectl/cmd/set/set_subject_test.go b/pkg/kubectl/cmd/set/set_subject_test.go index 484a0dfac95..a303e75c2d0 100644 --- a/pkg/kubectl/cmd/set/set_subject_test.go +++ b/pkg/kubectl/cmd/set/set_subject_test.go @@ -28,7 +28,7 @@ import ( ) func TestValidate(t *testing.T) { - f, tf, _, _ := cmdtesting.NewAPIFactory() + _, tf, _, _ := cmdtesting.NewAPIFactory() tf.Namespace = "test" tests := map[string]struct { @@ -107,7 +107,6 @@ func TestValidate(t *testing.T) { } for name, test := range tests { - test.options.Mapper, _ = f.Object() err := test.options.Validate() if test.expectErr && err != nil { continue diff --git a/pkg/kubectl/cmd/taint.go b/pkg/kubectl/cmd/taint.go index 5e0f5bc71c3..173d08be223 100644 --- a/pkg/kubectl/cmd/taint.go +++ b/pkg/kubectl/cmd/taint.go @@ -274,10 +274,9 @@ func (o TaintOptions) RunTaint() error { return err } - mapper, _ := o.f.Object() outputFormat := cmdutil.GetFlagString(o.cmd, "output") 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) diff --git a/pkg/kubectl/cmd/testing/fake.go b/pkg/kubectl/cmd/testing/fake.go index f014362dd38..c2e0d7f9e42 100644 --- a/pkg/kubectl/cmd/testing/fake.go +++ b/pkg/kubectl/cmd/testing/fake.go @@ -368,7 +368,7 @@ func (f *FakeFactory) PrintResourceInfoForCommand(cmd *cobra.Command, info *reso return err } if !printer.IsGeneric() { - printer, err = f.PrinterForMapping(&printers.PrintOptions{}, nil) + printer, err = f.PrinterForMapping(&printers.PrintOptions{}) if err != nil { return err } @@ -514,11 +514,11 @@ func (f *FakeFactory) BindFlags(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 } -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 } @@ -763,7 +763,7 @@ func (f *fakeAPIFactory) PrintResourceInfoForCommand(cmd *cobra.Command, info *r return err } if !printer.IsGeneric() { - printer, err = f.PrinterForMapping(&printers.PrintOptions{}, nil) + printer, err = f.PrinterForMapping(&printers.PrintOptions{}) if err != nil { return err } @@ -848,25 +848,15 @@ func (f *fakeAPIFactory) Generators(cmdName string) map[string]kubectl.Generator return cmdutil.DefaultGenerators(cmdName) } -func (f *fakeAPIFactory) PrintObject(cmd *cobra.Command, isLocal bool, mapper meta.RESTMapper, obj runtime.Object, out io.Writer) error { - gvks, _, err := legacyscheme.Scheme.ObjectKinds(obj) - if err != nil { - return err - } - - mapping, err := mapper.RESTMapping(gvks[0].GroupKind()) - if err != nil { - return err - } - - printer, err := f.PrinterForMapping(&printers.PrintOptions{}, mapping) +func (f *fakeAPIFactory) PrintObject(cmd *cobra.Command, obj runtime.Object, out io.Writer) error { + printer, err := f.PrinterForMapping(&printers.PrintOptions{}) if err != nil { return err } 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 } diff --git a/pkg/kubectl/cmd/util/factory.go b/pkg/kubectl/cmd/util/factory.go index ad62bee1b12..06b2f364d35 100644 --- a/pkg/kubectl/cmd/util/factory.go +++ b/pkg/kubectl/cmd/util/factory.go @@ -239,9 +239,9 @@ type BuilderFactory interface { // Requires that printer flags have been added to cmd (see AddPrinterFlags). // Returns a printer, true if the printer is generic (is not internal), or // 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(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 // 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. diff --git a/pkg/kubectl/cmd/util/factory_builder.go b/pkg/kubectl/cmd/util/factory_builder.go index d772772c833..faddb070098 100644 --- a/pkg/kubectl/cmd/util/factory_builder.go +++ b/pkg/kubectl/cmd/util/factory_builder.go @@ -25,11 +25,12 @@ import ( "github.com/spf13/cobra" - "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/kubectl/plugins" "k8s.io/kubernetes/pkg/kubectl/resource" + kubectlscheme "k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/printers" ) @@ -48,34 +49,17 @@ func NewBuilderFactory(clientAccessFactory ClientAccessFactory, objectMappingFac } func (f *ring2Factory) PrinterForOptions(options *printers.PrintOptions) (printers.ResourcePrinter, error) { - _, typer := f.objectMappingFactory.Object() - - // 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) + return printerForOptions(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) if err != nil { return nil, err } - // Make sure we output versioned data for generic printers - if printer.IsGeneric() { - 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()) - - } - + // wrap the printer in a versioning printer that understands when to convert and when not to convert + printer = printers.NewVersionedPrinter(printer, legacyscheme.Scheme, legacyscheme.Scheme, kubectlscheme.Versions...) 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 { - // try to get a typed object - _, 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) +func (f *ring2Factory) PrintObject(cmd *cobra.Command, obj runtime.Object, out io.Writer) error { + printer, err := f.PrinterForMapping(ExtractCmdPrintOptions(cmd, false)) if err != nil { return err } @@ -134,7 +100,7 @@ func (f *ring2Factory) PrintResourceInfoForCommand(cmd *cobra.Command, info *res return err } if !printer.IsGeneric() { - printer, err = f.PrinterForMapping(printOpts, nil) + printer, err = f.PrinterForMapping(printOpts) if err != nil { return err } diff --git a/pkg/kubectl/cmd/util/printing.go b/pkg/kubectl/cmd/util/printing.go index 2939e0e74ae..214f495d2b5 100644 --- a/pkg/kubectl/cmd/util/printing.go +++ b/pkg/kubectl/cmd/util/printing.go @@ -23,10 +23,12 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" + kubectlscheme "k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/printers" printersinternal "k8s.io/kubernetes/pkg/printers/internalversion" "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) @@ -83,8 +85,12 @@ func ValidateOutputArgs(cmd *cobra.Command) error { // printerForOptions returns the printer for the outputOptions (if given) or // returns the default printer for the command. Requires that printer flags have // been added to cmd (see AddPrinterFlags). -func printerForOptions(typer runtime.ObjectTyper, encoder runtime.Encoder, decoders []runtime.Decoder, options *printers.PrintOptions) (printers.ResourcePrinter, error) { - printer, err := printers.GetStandardPrinter(typer, encoder, decoders, *options) +func printerForOptions(options *printers.PrintOptions) (printers.ResourcePrinter, error) { + // 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 { return nil, err } diff --git a/pkg/kubectl/scheme/install.go b/pkg/kubectl/scheme/install.go index 51d4e16f18a..95838f55703 100644 --- a/pkg/kubectl/scheme/install.go +++ b/pkg/kubectl/scheme/install.go @@ -60,6 +60,7 @@ func init() { scheme.AddToScheme(Scheme) // Register external types for Registry + Versions = append(Versions, corev1.SchemeGroupVersion) if err := announced.NewGroupMetaFactory( &announced.GroupMetaFactoryArgs{ GroupName: corev1.GroupName, @@ -90,6 +91,7 @@ func init() { panic(err) } + Versions = append(Versions, admissionv1alpha1.SchemeGroupVersion) if err := announced.NewGroupMetaFactory( &announced.GroupMetaFactoryArgs{ GroupName: admissionv1alpha1.GroupName, @@ -103,6 +105,7 @@ func init() { panic(err) } + Versions = append(Versions, admissionregistrationv1alpha1.SchemeGroupVersion) if err := announced.NewGroupMetaFactory( &announced.GroupMetaFactoryArgs{ GroupName: admissionregistrationv1alpha1.GroupName, @@ -116,6 +119,7 @@ func init() { panic(err) } + Versions = append(Versions, appsv1.SchemeGroupVersion, appsv1beta2.SchemeGroupVersion, appsv1beta1.SchemeGroupVersion) if err := announced.NewGroupMetaFactory( &announced.GroupMetaFactoryArgs{ GroupName: appsv1.GroupName, @@ -130,6 +134,7 @@ func init() { panic(err) } + Versions = append(Versions, authenticationv1.SchemeGroupVersion, authenticationv1beta1.SchemeGroupVersion) if err := announced.NewGroupMetaFactory( &announced.GroupMetaFactoryArgs{ GroupName: authenticationv1beta1.GroupName, @@ -144,6 +149,7 @@ func init() { panic(err) } + Versions = append(Versions, authorizationv1.SchemeGroupVersion, authorizationv1beta1.SchemeGroupVersion) if err := announced.NewGroupMetaFactory( &announced.GroupMetaFactoryArgs{ GroupName: authorizationv1.GroupName, @@ -158,6 +164,7 @@ func init() { panic(err) } + Versions = append(Versions, autoscalingv1.SchemeGroupVersion, autoscalingv2beta1.SchemeGroupVersion) if err := announced.NewGroupMetaFactory( &announced.GroupMetaFactoryArgs{ GroupName: autoscalingv1.GroupName, @@ -171,6 +178,7 @@ func init() { panic(err) } + Versions = append(Versions, batchv1.SchemeGroupVersion, batchv1beta1.SchemeGroupVersion, batchv2alpha1.SchemeGroupVersion) if err := announced.NewGroupMetaFactory( &announced.GroupMetaFactoryArgs{ GroupName: batchv1.GroupName, @@ -185,6 +193,7 @@ func init() { panic(err) } + Versions = append(Versions, certificatesv1beta1.SchemeGroupVersion) if err := announced.NewGroupMetaFactory( &announced.GroupMetaFactoryArgs{ GroupName: certificatesv1beta1.GroupName, @@ -198,6 +207,7 @@ func init() { panic(err) } + Versions = append(Versions, extensionsv1beta1.SchemeGroupVersion) if err := announced.NewGroupMetaFactory( &announced.GroupMetaFactoryArgs{ GroupName: extensionsv1beta1.GroupName, @@ -211,6 +221,7 @@ func init() { panic(err) } + Versions = append(Versions, imagepolicyv1alpha1.SchemeGroupVersion) if err := announced.NewGroupMetaFactory( &announced.GroupMetaFactoryArgs{ GroupName: imagepolicyv1alpha1.GroupName, @@ -224,6 +235,7 @@ func init() { panic(err) } + Versions = append(Versions, networkingv1.SchemeGroupVersion) if err := announced.NewGroupMetaFactory( &announced.GroupMetaFactoryArgs{ GroupName: networkingv1.GroupName, @@ -236,6 +248,7 @@ func init() { panic(err) } + Versions = append(Versions, policyv1beta1.SchemeGroupVersion) if err := announced.NewGroupMetaFactory( &announced.GroupMetaFactoryArgs{ GroupName: policyv1beta1.GroupName, @@ -248,6 +261,7 @@ func init() { panic(err) } + Versions = append(Versions, rbacv1.SchemeGroupVersion, rbacv1beta1.SchemeGroupVersion, rbacv1alpha1.SchemeGroupVersion) if err := announced.NewGroupMetaFactory( &announced.GroupMetaFactoryArgs{ GroupName: rbacv1.GroupName, @@ -263,6 +277,7 @@ func init() { panic(err) } + Versions = append(Versions, schedulingv1alpha1.SchemeGroupVersion) if err := announced.NewGroupMetaFactory( &announced.GroupMetaFactoryArgs{ GroupName: schedulingv1alpha1.GroupName, @@ -276,6 +291,7 @@ func init() { panic(err) } + Versions = append(Versions, settingsv1alpha1.SchemeGroupVersion) if err := announced.NewGroupMetaFactory( &announced.GroupMetaFactoryArgs{ GroupName: settingsv1alpha1.GroupName, @@ -288,6 +304,7 @@ func init() { panic(err) } + Versions = append(Versions, storagev1.SchemeGroupVersion, storagev1beta1.SchemeGroupVersion) if err := announced.NewGroupMetaFactory( &announced.GroupMetaFactoryArgs{ GroupName: storagev1.GroupName, diff --git a/pkg/kubectl/scheme/scheme.go b/pkg/kubectl/scheme/scheme.go index cd38d22a183..c69c5465f4d 100644 --- a/pkg/kubectl/scheme/scheme.go +++ b/pkg/kubectl/scheme/scheme.go @@ -22,6 +22,7 @@ import ( "k8s.io/apimachinery/pkg/apimachinery/announced" "k8s.io/apimachinery/pkg/apimachinery/registered" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" "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. 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{} diff --git a/pkg/printers/internalversion/printers_test.go b/pkg/printers/internalversion/printers_test.go index 531ee5849b7..140544b4d7c 100644 --- a/pkg/printers/internalversion/printers_test.go +++ b/pkg/printers/internalversion/printers_test.go @@ -91,6 +91,7 @@ func TestVersionedPrinter(t *testing.T) { return nil }), legacyscheme.Scheme, + legacyscheme.Scheme, legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion, ) 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) } 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 { 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) } - 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 { buffer := &bytes.Buffer{} @@ -655,19 +656,19 @@ func TestPrinters(t *testing.T) { if err != nil { 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}}")) if err != nil { 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}") if err != nil { 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{ "humanReadable": printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{ diff --git a/pkg/printers/versioned.go b/pkg/printers/versioned.go index 5e3a6cdac29..1907ffb5850 100644 --- a/pkg/printers/versioned.go +++ b/pkg/printers/versioned.go @@ -20,6 +20,7 @@ import ( "fmt" "io" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" ) @@ -29,14 +30,16 @@ import ( type VersionedPrinter struct { printer ResourcePrinter converter runtime.ObjectConvertor + typer runtime.ObjectTyper versions []schema.GroupVersion } // 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{ printer: printer, converter: converter, + typer: typer, versions: versions, } } @@ -47,6 +50,33 @@ func (p *VersionedPrinter) AfterPrint(w io.Writer, res string) error { // PrintObj implements ResourcePrinter 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 { return fmt.Errorf("no version specified, object cannot be converted") }