@@ -31,11 +31,13 @@ import (
3131 "k8s.io/apimachinery/pkg/api/meta"
3232 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3333 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
34+ metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
3435 "k8s.io/apimachinery/pkg/runtime"
3536 "k8s.io/apimachinery/pkg/runtime/schema"
3637 utilerrors "k8s.io/apimachinery/pkg/util/errors"
3738 "k8s.io/apimachinery/pkg/util/sets"
3839 "k8s.io/apimachinery/pkg/watch"
40+ "k8s.io/client-go/rest"
3941 api "k8s.io/kubernetes/pkg/apis/core"
4042 "k8s.io/kubernetes/pkg/kubectl"
4143 "k8s.io/kubernetes/pkg/kubectl/cmd/templates"
@@ -64,6 +66,9 @@ type GetOptions struct {
6466 Namespace string
6567 ExplicitNamespace bool
6668
69+ ServerPrint bool
70+
71+ Sort bool
6772 IgnoreNotFound bool
6873 ShowKind bool
6974 LabelColumns []string
@@ -120,6 +125,7 @@ var (
120125
121126const (
122127 useOpenAPIPrintColumnFlagLabel = "use-openapi-print-columns"
128+ useServerPrintColumns = "experimental-server-print"
123129)
124130
125131// NewCmdGet creates a command object for the generic "get" action, which
@@ -158,6 +164,7 @@ func NewCmdGet(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Comman
158164 cmdutil .AddIncludeUninitializedFlag (cmd )
159165 cmdutil .AddPrinterFlags (cmd )
160166 addOpenAPIPrintColumnFlags (cmd )
167+ addServerPrintColumnFlags (cmd )
161168 cmd .Flags ().BoolVar (& options .ShowKind , "show-kind" , options .ShowKind , "If present, list the resource type for the requested object(s)." )
162169 cmd .Flags ().StringSliceVarP (& options .LabelColumns , "label-columns" , "L" , options .LabelColumns , "Accepts a comma separated list of labels that are going to be presented as columns. Names are case-sensitive. You can also use multiple flag options like -L label1 -L label2..." )
163170 cmd .Flags ().BoolVar (& options .Export , "export" , options .Export , "If true, use 'export' for the resources. Exported resources are stripped of cluster-specific information." )
@@ -175,6 +182,8 @@ func (options *GetOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args
175182 return nil
176183 }
177184
185+ options .ServerPrint = cmdutil .GetFlagBool (cmd , useServerPrintColumns )
186+
178187 var err error
179188 options .Namespace , options .ExplicitNamespace , err = f .DefaultNamespace ()
180189 if err != nil {
@@ -184,6 +193,12 @@ func (options *GetOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args
184193 options .ExplicitNamespace = false
185194 }
186195
196+ isSorting , err := cmd .Flags ().GetString ("sort-by" )
197+ if err != nil {
198+ return err
199+ }
200+ options .Sort = len (isSorting ) > 0
201+
187202 options .IncludeUninitialized = cmdutil .ShouldIncludeUninitialized (cmd , false )
188203
189204 switch {
@@ -238,6 +253,12 @@ func (options *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []str
238253 return options .watch (f , cmd , args )
239254 }
240255
256+ printOpts := cmdutil .ExtractCmdPrintOptions (cmd , options .AllNamespaces )
257+ printer , err := cmdutil .PrinterForOptions (printOpts )
258+ if err != nil {
259+ return err
260+ }
261+
241262 r := f .NewBuilder ().
242263 Unstructured ().
243264 NamespaceParam (options .Namespace ).DefaultNamespace ().AllNamespaces (options .AllNamespaces ).
@@ -251,6 +272,15 @@ func (options *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []str
251272 ContinueOnError ().
252273 Latest ().
253274 Flatten ().
275+ TransformRequests (func (req * rest.Request ) {
276+ if options .ServerPrint && ! printer .IsGeneric () && ! options .Sort {
277+ group := metav1beta1 .GroupName
278+ version := metav1beta1 .SchemeGroupVersion .Version
279+
280+ tableParam := fmt .Sprintf ("application/json;as=Table;v=%s;g=%s, application/json" , version , group )
281+ req .SetHeader ("Accept" , tableParam )
282+ }
283+ }).
254284 Do ()
255285
256286 if options .IgnoreNotFound {
@@ -260,12 +290,6 @@ func (options *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []str
260290 return err
261291 }
262292
263- printOpts := cmdutil .ExtractCmdPrintOptions (cmd , options .AllNamespaces )
264- printer , err := cmdutil .PrinterForOptions (printOpts )
265- if err != nil {
266- return err
267- }
268-
269293 filterOpts := cmdutil .ExtractCmdPrintOptions (cmd , options .AllNamespaces )
270294 filterFuncs := f .DefaultResourceFilterFunc ()
271295 if r .TargetsSingleItems () {
@@ -285,6 +309,17 @@ func (options *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []str
285309
286310 objs := make ([]runtime.Object , len (infos ))
287311 for ix := range infos {
312+ if options .ServerPrint {
313+ table , err := options .decodeIntoTable (cmdutil .InternalVersionJSONEncoder (), infos [ix ].Object )
314+ if err == nil {
315+ infos [ix ].Object = table
316+ } else {
317+ // if we are unable to decode server response into a v1beta1.Table,
318+ // fallback to client-side printing with whatever info the server returned.
319+ glog .V (2 ).Infof ("Unable to decode server response into a Table. Falling back to hardcoded types: %v" , err )
320+ }
321+ }
322+
288323 objs [ix ] = infos [ix ].Object
289324 }
290325
@@ -293,7 +328,7 @@ func (options *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []str
293328 return err
294329 }
295330 var sorter * kubectl.RuntimeSort
296- if len ( sorting ) > 0 && len (objs ) > 1 {
331+ if options . Sort && len (objs ) > 1 {
297332 // TODO: questionable
298333 if sorter , err = kubectl .SortObjects (cmdutil .InternalVersionDecoder (), objs , sorting ); err != nil {
299334 return err
@@ -324,6 +359,15 @@ func (options *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []str
324359 mapping = info .Mapping
325360 original = info .Object
326361 }
362+
363+ // if dealing with a table that has no rows, skip remaining steps
364+ // and avoid printing an unnecessary newline
365+ if table , isTable := info .Object .(* metav1beta1.Table ); isTable {
366+ if len (table .Rows ) == 0 {
367+ continue
368+ }
369+ }
370+
327371 if shouldGetNewPrinterForMapping (printer , lastMapping , mapping ) {
328372 if printer != nil {
329373 w .Flush ()
@@ -416,7 +460,19 @@ func (options *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []str
416460 }
417461 }
418462 w .Flush ()
419- cmdutil .PrintFilterCount (options .ErrOut , len (objs ), filteredResourceCount , len (allErrs ), filterOpts , options .IgnoreNotFound )
463+ nonEmptyObjCount := 0
464+ for _ , obj := range objs {
465+ if table , ok := obj .(* metav1beta1.Table ); ok {
466+ // exclude any Table objects with empty rows from our total object count
467+ if len (table .Rows ) == 0 {
468+ continue
469+ }
470+ }
471+
472+ nonEmptyObjCount ++
473+ }
474+
475+ cmdutil .PrintFilterCount (options .ErrOut , nonEmptyObjCount , filteredResourceCount , len (allErrs ), filterOpts , options .IgnoreNotFound )
420476 return utilerrors .NewAggregate (allErrs )
421477}
422478
@@ -592,6 +648,25 @@ func attemptToConvertToInternal(obj runtime.Object, converter runtime.ObjectConv
592648 return internalObject
593649}
594650
651+ func (options * GetOptions ) decodeIntoTable (encoder runtime.Encoder , obj runtime.Object ) (runtime.Object , error ) {
652+ if obj .GetObjectKind ().GroupVersionKind ().Kind != "Table" {
653+ return nil , fmt .Errorf ("attempt to decode non-Table object into a v1beta1.Table" )
654+ }
655+
656+ b , err := runtime .Encode (encoder , obj )
657+ if err != nil {
658+ return nil , err
659+ }
660+
661+ table := & metav1beta1.Table {}
662+ err = json .Unmarshal (b , table )
663+ if err != nil {
664+ return nil , err
665+ }
666+
667+ return table , nil
668+ }
669+
595670func (options * GetOptions ) printGeneric (printer printers.ResourcePrinter , r * resource.Result , filterFuncs kubectl.Filters , filterOpts * printers.PrintOptions ) error {
596671 // we flattened the data from the builder, so we have individual items, but now we'd like to either:
597672 // 1. if there is more than one item, combine them all into a single list
@@ -689,6 +764,10 @@ func addOpenAPIPrintColumnFlags(cmd *cobra.Command) {
689764 cmd .Flags ().Bool (useOpenAPIPrintColumnFlagLabel , true , "If true, use x-kubernetes-print-column metadata (if present) from the OpenAPI schema for displaying a resource." )
690765}
691766
767+ func addServerPrintColumnFlags (cmd * cobra.Command ) {
768+ cmd .Flags ().Bool (useServerPrintColumns , false , "If true, have the server return the appropriate table output. Supports extension APIs and CRD. Experimental." )
769+ }
770+
692771func shouldGetNewPrinterForMapping (printer printers.ResourcePrinter , lastMapping , mapping * meta.RESTMapping ) bool {
693772 return printer == nil || lastMapping == nil || mapping == nil || mapping .Resource != lastMapping .Resource
694773}
0 commit comments