@@ -31,11 +31,13 @@ import (
31
31
"k8s.io/apimachinery/pkg/api/meta"
32
32
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
33
33
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
34
+ metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
34
35
"k8s.io/apimachinery/pkg/runtime"
35
36
"k8s.io/apimachinery/pkg/runtime/schema"
36
37
utilerrors "k8s.io/apimachinery/pkg/util/errors"
37
38
"k8s.io/apimachinery/pkg/util/sets"
38
39
"k8s.io/apimachinery/pkg/watch"
40
+ "k8s.io/client-go/rest"
39
41
api "k8s.io/kubernetes/pkg/apis/core"
40
42
"k8s.io/kubernetes/pkg/kubectl"
41
43
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
@@ -64,6 +66,9 @@ type GetOptions struct {
64
66
Namespace string
65
67
ExplicitNamespace bool
66
68
69
+ ServerPrint bool
70
+
71
+ Sort bool
67
72
IgnoreNotFound bool
68
73
ShowKind bool
69
74
LabelColumns []string
@@ -120,6 +125,7 @@ var (
120
125
121
126
const (
122
127
useOpenAPIPrintColumnFlagLabel = "use-openapi-print-columns"
128
+ useServerPrintColumns = "experimental-server-print"
123
129
)
124
130
125
131
// 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
158
164
cmdutil .AddIncludeUninitializedFlag (cmd )
159
165
cmdutil .AddPrinterFlags (cmd )
160
166
addOpenAPIPrintColumnFlags (cmd )
167
+ addServerPrintColumnFlags (cmd )
161
168
cmd .Flags ().BoolVar (& options .ShowKind , "show-kind" , options .ShowKind , "If present, list the resource type for the requested object(s)." )
162
169
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..." )
163
170
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
175
182
return nil
176
183
}
177
184
185
+ options .ServerPrint = cmdutil .GetFlagBool (cmd , useServerPrintColumns )
186
+
178
187
var err error
179
188
options .Namespace , options .ExplicitNamespace , err = f .DefaultNamespace ()
180
189
if err != nil {
@@ -184,6 +193,12 @@ func (options *GetOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args
184
193
options .ExplicitNamespace = false
185
194
}
186
195
196
+ isSorting , err := cmd .Flags ().GetString ("sort-by" )
197
+ if err != nil {
198
+ return err
199
+ }
200
+ options .Sort = len (isSorting ) > 0
201
+
187
202
options .IncludeUninitialized = cmdutil .ShouldIncludeUninitialized (cmd , false )
188
203
189
204
switch {
@@ -238,6 +253,12 @@ func (options *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []str
238
253
return options .watch (f , cmd , args )
239
254
}
240
255
256
+ printOpts := cmdutil .ExtractCmdPrintOptions (cmd , options .AllNamespaces )
257
+ printer , err := cmdutil .PrinterForOptions (printOpts )
258
+ if err != nil {
259
+ return err
260
+ }
261
+
241
262
r := f .NewBuilder ().
242
263
Unstructured ().
243
264
NamespaceParam (options .Namespace ).DefaultNamespace ().AllNamespaces (options .AllNamespaces ).
@@ -251,6 +272,15 @@ func (options *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []str
251
272
ContinueOnError ().
252
273
Latest ().
253
274
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
+ }).
254
284
Do ()
255
285
256
286
if options .IgnoreNotFound {
@@ -260,12 +290,6 @@ func (options *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []str
260
290
return err
261
291
}
262
292
263
- printOpts := cmdutil .ExtractCmdPrintOptions (cmd , options .AllNamespaces )
264
- printer , err := cmdutil .PrinterForOptions (printOpts )
265
- if err != nil {
266
- return err
267
- }
268
-
269
293
filterOpts := cmdutil .ExtractCmdPrintOptions (cmd , options .AllNamespaces )
270
294
filterFuncs := f .DefaultResourceFilterFunc ()
271
295
if r .TargetsSingleItems () {
@@ -285,6 +309,17 @@ func (options *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []str
285
309
286
310
objs := make ([]runtime.Object , len (infos ))
287
311
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
+
288
323
objs [ix ] = infos [ix ].Object
289
324
}
290
325
@@ -293,7 +328,7 @@ func (options *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []str
293
328
return err
294
329
}
295
330
var sorter * kubectl.RuntimeSort
296
- if len ( sorting ) > 0 && len (objs ) > 1 {
331
+ if options . Sort && len (objs ) > 1 {
297
332
// TODO: questionable
298
333
if sorter , err = kubectl .SortObjects (cmdutil .InternalVersionDecoder (), objs , sorting ); err != nil {
299
334
return err
@@ -324,6 +359,15 @@ func (options *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []str
324
359
mapping = info .Mapping
325
360
original = info .Object
326
361
}
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
+
327
371
if shouldGetNewPrinterForMapping (printer , lastMapping , mapping ) {
328
372
if printer != nil {
329
373
w .Flush ()
@@ -416,7 +460,19 @@ func (options *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []str
416
460
}
417
461
}
418
462
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 )
420
476
return utilerrors .NewAggregate (allErrs )
421
477
}
422
478
@@ -592,6 +648,25 @@ func attemptToConvertToInternal(obj runtime.Object, converter runtime.ObjectConv
592
648
return internalObject
593
649
}
594
650
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
+
595
670
func (options * GetOptions ) printGeneric (printer printers.ResourcePrinter , r * resource.Result , filterFuncs kubectl.Filters , filterOpts * printers.PrintOptions ) error {
596
671
// we flattened the data from the builder, so we have individual items, but now we'd like to either:
597
672
// 1. if there is more than one item, combine them all into a single list
@@ -689,6 +764,10 @@ func addOpenAPIPrintColumnFlags(cmd *cobra.Command) {
689
764
cmd .Flags ().Bool (useOpenAPIPrintColumnFlagLabel , true , "If true, use x-kubernetes-print-column metadata (if present) from the OpenAPI schema for displaying a resource." )
690
765
}
691
766
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
+
692
771
func shouldGetNewPrinterForMapping (printer printers.ResourcePrinter , lastMapping , mapping * meta.RESTMapping ) bool {
693
772
return printer == nil || lastMapping == nil || mapping == nil || mapping .Resource != lastMapping .Resource
694
773
}
0 commit comments