diff --git a/pkg/kubectl/cmd/get/humanreadable_flags.go b/pkg/kubectl/cmd/get/humanreadable_flags.go index efd597c4598..494ffdfc656 100644 --- a/pkg/kubectl/cmd/get/humanreadable_flags.go +++ b/pkg/kubectl/cmd/get/humanreadable_flags.go @@ -21,7 +21,6 @@ import ( "k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/printers" printersinternal "k8s.io/kubernetes/pkg/printers/internalversion" ) @@ -73,8 +72,6 @@ func (f *HumanPrintFlags) ToPrinter(outputFormat string) (printers.ResourcePrint return nil, genericclioptions.NoCompatiblePrinterError{Options: f, AllowedFormats: f.AllowedFormats()} } - decoder := scheme.Codecs.UniversalDecoder() - showKind := false if f.ShowKind != nil { showKind = *f.ShowKind @@ -90,7 +87,7 @@ func (f *HumanPrintFlags) ToPrinter(outputFormat string) (printers.ResourcePrint columnLabels = *f.ColumnLabels } - p := printers.NewHumanReadablePrinter(decoder, printers.PrintOptions{ + p := printers.NewHumanReadablePrinter(printers.PrintOptions{ Kind: f.Kind, WithKind: showKind, NoHeaders: f.NoHeaders, diff --git a/pkg/printers/BUILD b/pkg/printers/BUILD index 3f1134b1b08..dea653133f2 100644 --- a/pkg/printers/BUILD +++ b/pkg/printers/BUILD @@ -17,7 +17,6 @@ go_library( deps = [ "//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", diff --git a/pkg/printers/humanreadable.go b/pkg/printers/humanreadable.go index e5cdceddac3..aba9660e81c 100644 --- a/pkg/printers/humanreadable.go +++ b/pkg/printers/humanreadable.go @@ -27,7 +27,6 @@ import ( "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" @@ -40,7 +39,6 @@ type TablePrinter interface { } type PrintHandler interface { - Handler(columns, columnsWithWide []string, printFunc interface{}) error TableHandler(columns []metav1beta1.TableColumnDefinition, printFunc interface{}) error DefaultTableHandler(columns []metav1beta1.TableColumnDefinition, printFunc interface{}) error } @@ -49,7 +47,6 @@ var withNamespacePrefixColumns = []string{"NAMESPACE"} // TODO(erictune): print type handlerEntry struct { columnDefinitions []metav1beta1.TableColumnDefinition - printRows bool printFunc reflect.Value args []reflect.Value } @@ -65,19 +62,15 @@ type HumanReadablePrinter struct { lastType interface{} lastColumns []metav1beta1.TableColumnDefinition skipTabWriter bool - encoder runtime.Encoder - decoder runtime.Decoder } var _ PrintHandler = &HumanReadablePrinter{} // NewHumanReadablePrinter creates a HumanReadablePrinter. -// If encoder and decoder are provided, an attempt to convert unstructured types to internal types is made. -func NewHumanReadablePrinter(decoder runtime.Decoder, options PrintOptions) *HumanReadablePrinter { +func NewHumanReadablePrinter(options PrintOptions) *HumanReadablePrinter { printer := &HumanReadablePrinter{ handlerMap: make(map[reflect.Type]*handlerEntry), options: options, - decoder: decoder, } return printer } @@ -112,53 +105,6 @@ func (h *HumanReadablePrinter) EnsurePrintHeaders() { h.lastType = nil } -// Handler adds a print handler with a given set of columns to HumanReadablePrinter instance. -// See ValidatePrintHandlerFunc for required method signature. -func (h *HumanReadablePrinter) Handler(columns, columnsWithWide []string, printFunc interface{}) error { - var columnDefinitions []metav1beta1.TableColumnDefinition - for i, column := range columns { - format := "" - if i == 0 && strings.EqualFold(column, "name") { - format = "name" - } - - columnDefinitions = append(columnDefinitions, metav1beta1.TableColumnDefinition{ - Name: column, - Description: column, - Type: "string", - Format: format, - }) - } - for _, column := range columnsWithWide { - columnDefinitions = append(columnDefinitions, metav1beta1.TableColumnDefinition{ - Name: column, - Description: column, - Type: "string", - Priority: 1, - }) - } - - printFuncValue := reflect.ValueOf(printFunc) - if err := ValidatePrintHandlerFunc(printFuncValue); err != nil { - utilruntime.HandleError(fmt.Errorf("unable to register print function: %v", err)) - return err - } - - entry := &handlerEntry{ - columnDefinitions: columnDefinitions, - printFunc: printFuncValue, - } - - objType := printFuncValue.Type().In(0) - if _, ok := h.handlerMap[objType]; ok { - err := fmt.Errorf("registered duplicate printer for %v", objType) - utilruntime.HandleError(err) - return err - } - h.handlerMap[objType] = entry - return nil -} - // TableHandler adds a print handler with a given set of columns to HumanReadablePrinter instance. // See ValidateRowPrintHandlerFunc for required method signature. func (h *HumanReadablePrinter) TableHandler(columnDefinitions []metav1beta1.TableColumnDefinition, printFunc interface{}) error { @@ -169,7 +115,6 @@ func (h *HumanReadablePrinter) TableHandler(columnDefinitions []metav1beta1.Tabl } entry := &handlerEntry{ columnDefinitions: columnDefinitions, - printRows: true, printFunc: printFuncValue, } @@ -194,7 +139,6 @@ func (h *HumanReadablePrinter) DefaultTableHandler(columnDefinitions []metav1bet } entry := &handlerEntry{ columnDefinitions: columnDefinitions, - printRows: true, printFunc: printFuncValue, } @@ -312,12 +256,6 @@ func (h *HumanReadablePrinter) PrintObj(obj runtime.Object, output io.Writer) er return PrintTable(table, output, localOptions) } - // check if the object is unstructured. If so, let's attempt to convert it to a type we can understand before - // trying to print, since the printers are keyed by type. This is extremely expensive. - if h.decoder != nil { - obj, _ = decodeUnknownObject(obj, h.decoder) - } - // print with a registered handler t := reflect.TypeOf(obj) if handler := h.handlerMap[t]; handler != nil { @@ -516,9 +454,6 @@ func (h *HumanReadablePrinter) PrintTable(obj runtime.Object, options PrintOptio if !ok { return nil, fmt.Errorf("no table handler registered for this type %v", t) } - if !handler.printRows { - return h.legacyPrinterToTable(obj, handler) - } args := []reflect.Value{reflect.ValueOf(obj), reflect.ValueOf(options)} results := handler.printFunc.Call(args) @@ -567,12 +502,11 @@ func (h *HumanReadablePrinter) PrintTable(obj runtime.Object, options PrintOptio // or an error, if any. func printRowsForHandlerEntry(output io.Writer, handler *handlerEntry, obj runtime.Object, options PrintOptions, includeHeaders bool) error { var results []reflect.Value - if handler.printRows { - args := []reflect.Value{reflect.ValueOf(obj), reflect.ValueOf(options)} - results = handler.printFunc.Call(args) - if !results[1].IsNil() { - return results[1].Interface().(error) - } + + args := []reflect.Value{reflect.ValueOf(obj), reflect.ValueOf(options)} + results = handler.printFunc.Call(args) + if !results[1].IsNil() { + return results[1].Interface().(error) } if includeHeaders { @@ -592,16 +526,6 @@ func printRowsForHandlerEntry(output io.Writer, handler *handlerEntry, obj runti printHeader(headers, output) } - if !handler.printRows { - // TODO: this code path is deprecated and will be removed when all handlers are row printers - args := []reflect.Value{reflect.ValueOf(obj), reflect.ValueOf(output), reflect.ValueOf(options)} - resultValue := handler.printFunc.Call(args)[0] - if resultValue.IsNil() { - return nil - } - return resultValue.Interface().(error) - } - if results[1].IsNil() { rows := results[0].Interface().([]metav1beta1.TableRow) printRows(output, rows, options) @@ -649,67 +573,6 @@ func printRows(output io.Writer, rows []metav1beta1.TableRow, options PrintOptio } } -// legacyPrinterToTable uses the old printFunc with tabbed writer to generate a table. -// TODO: remove when all legacy printers are removed. -func (h *HumanReadablePrinter) legacyPrinterToTable(obj runtime.Object, handler *handlerEntry) (*metav1beta1.Table, error) { - printFunc := handler.printFunc - table := &metav1beta1.Table{ - ColumnDefinitions: handler.columnDefinitions, - } - - options := PrintOptions{ - NoHeaders: true, - Wide: true, - } - buf := &bytes.Buffer{} - args := []reflect.Value{reflect.ValueOf(obj), reflect.ValueOf(buf), reflect.ValueOf(options)} - - if meta.IsListType(obj) { - listInterface, ok := obj.(metav1.ListInterface) - if ok { - table.ListMeta.SelfLink = listInterface.GetSelfLink() - table.ListMeta.ResourceVersion = listInterface.GetResourceVersion() - table.ListMeta.Continue = listInterface.GetContinue() - } - - // TODO: this uses more memory than it has to, as we refactor printers we should remove the need - // for this. - args[0] = reflect.ValueOf(obj) - resultValue := printFunc.Call(args)[0] - if !resultValue.IsNil() { - return nil, resultValue.Interface().(error) - } - data := buf.Bytes() - i := 0 - items, err := meta.ExtractList(obj) - if err != nil { - return nil, err - } - for len(data) > 0 { - cells, remainder := tabbedLineToCells(data, len(table.ColumnDefinitions)) - table.Rows = append(table.Rows, metav1beta1.TableRow{ - Cells: cells, - Object: runtime.RawExtension{Object: items[i]}, - }) - data = remainder - i++ - } - } else { - args[0] = reflect.ValueOf(obj) - resultValue := printFunc.Call(args)[0] - if !resultValue.IsNil() { - return nil, resultValue.Interface().(error) - } - data := buf.Bytes() - cells, _ := tabbedLineToCells(data, len(table.ColumnDefinitions)) - table.Rows = append(table.Rows, metav1beta1.TableRow{ - Cells: cells, - Object: runtime.RawExtension{Object: obj}, - }) - } - return table, nil -} - // TODO: this method assumes the meta/v1 server API, so should be refactored out of this package func printUnstructured(unstructured runtime.Unstructured, w io.Writer, additionalFields []string, options PrintOptions) error { metadata, err := meta.Accessor(unstructured) @@ -848,46 +711,3 @@ func AppendAllLabels(showLabels bool, itemLabels map[string]string) string { return buffer.String() } - -// check if the object is unstructured. If so, attempt to convert it to a type we can understand. -func decodeUnknownObject(obj runtime.Object, decoder runtime.Decoder) (runtime.Object, error) { - var err error - switch t := obj.(type) { - case runtime.Unstructured: - if objBytes, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj); err == nil { - if decodedObj, err := runtime.Decode(decoder, objBytes); err == nil { - obj = decodedObj - } - } - case *runtime.Unknown: - if decodedObj, err := runtime.Decode(decoder, t.Raw); err == nil { - obj = decodedObj - } - } - - return obj, err -} - -func tabbedLineToCells(data []byte, expected int) ([]interface{}, []byte) { - var remainder []byte - max := bytes.Index(data, []byte("\n")) - if max != -1 { - remainder = data[max+1:] - data = data[:max] - } - cells := make([]interface{}, expected) - for i := 0; i < expected; i++ { - next := bytes.Index(data, []byte("\t")) - if next == -1 { - cells[i] = string(data) - // fill the remainder with empty strings, this indicates a printer bug - for j := i + 1; j < expected; j++ { - cells[j] = "" - } - break - } - cells[i] = string(data[:next]) - data = data[next+1:] - } - return cells, remainder -} diff --git a/pkg/printers/humanreadable_test.go b/pkg/printers/humanreadable_test.go index 1a86bb6710c..9d3bc1bdd8d 100644 --- a/pkg/printers/humanreadable_test.go +++ b/pkg/printers/humanreadable_test.go @@ -61,7 +61,6 @@ func TestPrintRowsForHandlerEntry(t *testing.T) { name: "no tablecolumndefinition and includeheader flase", h: &handlerEntry{ columnDefinitions: []metav1beta1.TableColumnDefinition{}, - printRows: true, printFunc: printFunc, }, opt: PrintOptions{}, @@ -75,7 +74,6 @@ func TestPrintRowsForHandlerEntry(t *testing.T) { name: "no tablecolumndefinition and includeheader true", h: &handlerEntry{ columnDefinitions: []metav1beta1.TableColumnDefinition{}, - printRows: true, printFunc: printFunc, }, opt: PrintOptions{}, @@ -89,7 +87,6 @@ func TestPrintRowsForHandlerEntry(t *testing.T) { name: "have tablecolumndefinition and includeheader true", h: &handlerEntry{ columnDefinitions: testNamespaceColumnDefinitions, - printRows: true, printFunc: printFunc, }, opt: PrintOptions{}, @@ -103,7 +100,6 @@ func TestPrintRowsForHandlerEntry(t *testing.T) { name: "print namespace and withnamespace true, should not print header", h: &handlerEntry{ columnDefinitions: testNamespaceColumnDefinitions, - printRows: true, printFunc: printFunc, }, opt: PrintOptions{ diff --git a/pkg/printers/internalversion/printers_test.go b/pkg/printers/internalversion/printers_test.go index 2c900bafc60..03d2d8ed39e 100644 --- a/pkg/printers/internalversion/printers_test.go +++ b/pkg/printers/internalversion/printers_test.go @@ -20,7 +20,6 @@ import ( "bytes" "encoding/json" "fmt" - "io" "reflect" "regexp" "strconv" @@ -30,7 +29,7 @@ import ( "sigs.k8s.io/yaml" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" @@ -172,7 +171,7 @@ func TestPrintUnstructuredObject(t *testing.T) { for _, test := range tests { out.Reset() - printer := printers.NewHumanReadablePrinter(nil, test.options).With(AddDefaultHandlers) + printer := printers.NewHumanReadablePrinter(test.options).With(AddDefaultHandlers) printer.PrintObj(test.object, out) matches, err := regexp.MatchString(test.expected, out.String()) @@ -285,24 +284,23 @@ func TestFormatResourceName(t *testing.T) { } } -func PrintCustomType(obj *TestPrintType, w io.Writer, options printers.PrintOptions) error { +func PrintCustomType(obj *TestPrintType, options printers.PrintOptions) ([]metav1beta1.TableRow, error) { data := obj.Data kind := options.Kind if options.WithKind { data = kind.String() + "/" + data } - _, err := fmt.Fprintf(w, "%s", data) - return err + return []metav1beta1.TableRow{{Cells: []interface{}{data}}}, nil } -func ErrorPrintHandler(obj *TestPrintType, w io.Writer, options printers.PrintOptions) error { - return fmt.Errorf("ErrorPrintHandler error") +func ErrorPrintHandler(obj *TestPrintType, options printers.PrintOptions) ([]metav1beta1.TableRow, error) { + return nil, fmt.Errorf("ErrorPrintHandler error") } func TestCustomTypePrinting(t *testing.T) { - columns := []string{"Data"} - printer := printers.NewHumanReadablePrinter(nil, printers.PrintOptions{}) - printer.Handler(columns, nil, PrintCustomType) + columns := []metav1beta1.TableColumnDefinition{{Name: "Data"}} + printer := printers.NewHumanReadablePrinter(printers.PrintOptions{}) + printer.TableHandler(columns, PrintCustomType) obj := TestPrintType{"test object"} buffer := &bytes.Buffer{} @@ -310,16 +308,16 @@ func TestCustomTypePrinting(t *testing.T) { if err != nil { t.Fatalf("An error occurred printing the custom type: %#v", err) } - expectedOutput := "DATA\ntest object" + expectedOutput := "DATA\ntest object\n" if buffer.String() != expectedOutput { t.Errorf("The data was not printed as expected. Expected:\n%s\nGot:\n%s", expectedOutput, buffer.String()) } } func TestPrintHandlerError(t *testing.T) { - columns := []string{"Data"} - printer := printers.NewHumanReadablePrinter(nil, printers.PrintOptions{}) - printer.Handler(columns, nil, ErrorPrintHandler) + columns := []metav1beta1.TableColumnDefinition{{Name: "Data"}} + printer := printers.NewHumanReadablePrinter(printers.PrintOptions{}) + printer.TableHandler(columns, ErrorPrintHandler) obj := TestPrintType{"test object"} buffer := &bytes.Buffer{} err := printer.PrintObj(&obj, buffer) @@ -329,7 +327,7 @@ func TestPrintHandlerError(t *testing.T) { } func TestUnknownTypePrinting(t *testing.T) { - printer := printers.NewHumanReadablePrinter(nil, printers.PrintOptions{}) + printer := printers.NewHumanReadablePrinter(printers.PrintOptions{}) buffer := &bytes.Buffer{} err := printer.PrintObj(&TestUnknownType{}, buffer) if err == nil { @@ -590,10 +588,10 @@ func TestPrinters(t *testing.T) { // a humanreadable printer deals with internal-versioned objects humanReadablePrinter := map[string]printers.ResourcePrinter{ - "humanReadable": printers.NewHumanReadablePrinter(nil, printers.PrintOptions{ + "humanReadable": printers.NewHumanReadablePrinter(printers.PrintOptions{ NoHeaders: true, }), - "humanReadableHeaders": printers.NewHumanReadablePrinter(nil, printers.PrintOptions{}), + "humanReadableHeaders": printers.NewHumanReadablePrinter(printers.PrintOptions{}), } AddHandlers((humanReadablePrinter["humanReadable"]).(*printers.HumanReadablePrinter)) AddHandlers((humanReadablePrinter["humanReadableHeaders"]).(*printers.HumanReadablePrinter)) @@ -613,7 +611,7 @@ func TestPrinters(t *testing.T) { func TestPrintEventsResultSorted(t *testing.T) { // Arrange - printer := printers.NewHumanReadablePrinter(nil, printers.PrintOptions{}) + printer := printers.NewHumanReadablePrinter(printers.PrintOptions{}) AddHandlers(printer) obj := api.EventList{ @@ -658,7 +656,7 @@ func TestPrintEventsResultSorted(t *testing.T) { } func TestPrintNodeStatus(t *testing.T) { - printer := printers.NewHumanReadablePrinter(nil, printers.PrintOptions{}) + printer := printers.NewHumanReadablePrinter(printers.PrintOptions{}) AddHandlers(printer) table := []struct { node api.Node @@ -748,7 +746,7 @@ func TestPrintNodeStatus(t *testing.T) { } func TestPrintNodeRole(t *testing.T) { - printer := printers.NewHumanReadablePrinter(nil, printers.PrintOptions{}) + printer := printers.NewHumanReadablePrinter(printers.PrintOptions{}) AddHandlers(printer) table := []struct { node api.Node @@ -793,7 +791,7 @@ func TestPrintNodeRole(t *testing.T) { } func TestPrintNodeOSImage(t *testing.T) { - printer := printers.NewHumanReadablePrinter(nil, printers.PrintOptions{ + printer := printers.NewHumanReadablePrinter(printers.PrintOptions{ ColumnLabels: []string{}, Wide: true, }) @@ -838,7 +836,7 @@ func TestPrintNodeOSImage(t *testing.T) { } func TestPrintNodeKernelVersion(t *testing.T) { - printer := printers.NewHumanReadablePrinter(nil, printers.PrintOptions{ + printer := printers.NewHumanReadablePrinter(printers.PrintOptions{ ColumnLabels: []string{}, Wide: true, }) @@ -883,7 +881,7 @@ func TestPrintNodeKernelVersion(t *testing.T) { } func TestPrintNodeContainerRuntimeVersion(t *testing.T) { - printer := printers.NewHumanReadablePrinter(nil, printers.PrintOptions{ + printer := printers.NewHumanReadablePrinter(printers.PrintOptions{ ColumnLabels: []string{}, Wide: true, }) @@ -928,7 +926,7 @@ func TestPrintNodeContainerRuntimeVersion(t *testing.T) { } func TestPrintNodeName(t *testing.T) { - printer := printers.NewHumanReadablePrinter(nil, printers.PrintOptions{ + printer := printers.NewHumanReadablePrinter(printers.PrintOptions{ Wide: true, }) AddHandlers(printer) @@ -965,7 +963,7 @@ func TestPrintNodeName(t *testing.T) { } func TestPrintNodeExternalIP(t *testing.T) { - printer := printers.NewHumanReadablePrinter(nil, printers.PrintOptions{ + printer := printers.NewHumanReadablePrinter(printers.PrintOptions{ Wide: true, }) AddHandlers(printer) @@ -1013,7 +1011,7 @@ func TestPrintNodeExternalIP(t *testing.T) { } func TestPrintNodeInternalIP(t *testing.T) { - printer := printers.NewHumanReadablePrinter(nil, printers.PrintOptions{ + printer := printers.NewHumanReadablePrinter(printers.PrintOptions{ Wide: true, }) AddHandlers(printer) @@ -1421,7 +1419,7 @@ func TestPrintHumanReadableWithNamespace(t *testing.T) { for i, test := range table { if test.isNamespaced { // Expect output to include namespace when requested. - printer := printers.NewHumanReadablePrinter(nil, printers.PrintOptions{ + printer := printers.NewHumanReadablePrinter(printers.PrintOptions{ WithNamespace: true, }) AddHandlers(printer) @@ -1436,7 +1434,7 @@ func TestPrintHumanReadableWithNamespace(t *testing.T) { } } else { // Expect error when trying to get all namespaces for un-namespaced object. - printer := printers.NewHumanReadablePrinter(nil, printers.PrintOptions{ + printer := printers.NewHumanReadablePrinter(printers.PrintOptions{ WithNamespace: true, }) buffer := &bytes.Buffer{} @@ -1515,7 +1513,7 @@ func TestPrintPodTable(t *testing.T) { } verifyTable(t, table) buf := &bytes.Buffer{} - p := printers.NewHumanReadablePrinter(nil, test.opts).With(AddHandlers).AddTabWriter(false) + p := printers.NewHumanReadablePrinter(test.opts).With(AddHandlers).AddTabWriter(false) if err := p.PrintObj(table, buf); err != nil { t.Fatal(err) }