mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 21:47:07 +00:00
Merge pull request #26696 from gitfred/no-header-custom-column
Automatic merge from submit-queue --no-header available now for custom-column Change `CustomColumnsPrinter` to have `noHeader` boolean, also changed `GetPrinter` to receive this bool and pass it through. One test `TestNewColumnPrinterFromSpecWithNoHeaders` added for checking if there is no headers in output for sure fixes #24133
This commit is contained in:
commit
30c43e63af
@ -91,7 +91,7 @@ func dumpClusterInfo(f *cmdutil.Factory, cmd *cobra.Command, args []string, out
|
|||||||
if c, err = f.Client(); err != nil {
|
if c, err = f.Client(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
printer, _, err := kubectl.GetPrinter("json", "")
|
printer, _, err := kubectl.GetPrinter("json", "", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -150,7 +150,7 @@ func (o *ConvertOptions) Complete(f *cmdutil.Factory, out io.Writer, cmd *cobra.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
o.encoder = f.JSONEncoder()
|
o.encoder = f.JSONEncoder()
|
||||||
o.printer, _, err = kubectl.GetPrinter(outputFormat, templateFile)
|
o.printer, _, err = kubectl.GetPrinter(outputFormat, templateFile, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ func AddOutputFlags(cmd *cobra.Command) {
|
|||||||
|
|
||||||
// AddNoHeadersFlags adds no-headers flags to a command.
|
// AddNoHeadersFlags adds no-headers flags to a command.
|
||||||
func AddNoHeadersFlags(cmd *cobra.Command) {
|
func AddNoHeadersFlags(cmd *cobra.Command) {
|
||||||
cmd.Flags().Bool("no-headers", false, "When using the default output, don't print headers.")
|
cmd.Flags().Bool("no-headers", false, "When using the default or custom-column output format, don't print headers.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrintSuccess prints message after finishing mutating operations
|
// PrintSuccess prints message after finishing mutating operations
|
||||||
@ -121,7 +121,7 @@ func PrinterForCommand(cmd *cobra.Command) (kubectl.ResourcePrinter, bool, error
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printer, generic, err := kubectl.GetPrinter(outputFormat, templateFile)
|
printer, generic, err := kubectl.GetPrinter(outputFormat, templateFile, GetFlagBool(cmd, "no-headers"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, generic, err
|
return nil, generic, err
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ func massageJSONPath(pathExpression string) (string, error) {
|
|||||||
//
|
//
|
||||||
// NAME API_VERSION
|
// NAME API_VERSION
|
||||||
// foo bar
|
// foo bar
|
||||||
func NewCustomColumnsPrinterFromSpec(spec string, decoder runtime.Decoder) (*CustomColumnsPrinter, error) {
|
func NewCustomColumnsPrinterFromSpec(spec string, decoder runtime.Decoder, noHeaders bool) (*CustomColumnsPrinter, error) {
|
||||||
if len(spec) == 0 {
|
if len(spec) == 0 {
|
||||||
return nil, fmt.Errorf("custom-columns format specified but no custom columns given")
|
return nil, fmt.Errorf("custom-columns format specified but no custom columns given")
|
||||||
}
|
}
|
||||||
@ -90,7 +90,7 @@ func NewCustomColumnsPrinterFromSpec(spec string, decoder runtime.Decoder) (*Cus
|
|||||||
}
|
}
|
||||||
columns[ix] = Column{Header: colSpec[0], FieldSpec: spec}
|
columns[ix] = Column{Header: colSpec[0], FieldSpec: spec}
|
||||||
}
|
}
|
||||||
return &CustomColumnsPrinter{Columns: columns, Decoder: decoder}, nil
|
return &CustomColumnsPrinter{Columns: columns, Decoder: decoder, NoHeaders: noHeaders}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func splitOnWhitespace(line string) []string {
|
func splitOnWhitespace(line string) []string {
|
||||||
@ -135,7 +135,7 @@ func NewCustomColumnsPrinterFromTemplate(templateReader io.Reader, decoder runti
|
|||||||
FieldSpec: spec,
|
FieldSpec: spec,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &CustomColumnsPrinter{Columns: columns, Decoder: decoder}, nil
|
return &CustomColumnsPrinter{Columns: columns, Decoder: decoder, NoHeaders: false}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Column represents a user specified column
|
// Column represents a user specified column
|
||||||
@ -152,15 +152,19 @@ type Column struct {
|
|||||||
type CustomColumnsPrinter struct {
|
type CustomColumnsPrinter struct {
|
||||||
Columns []Column
|
Columns []Column
|
||||||
Decoder runtime.Decoder
|
Decoder runtime.Decoder
|
||||||
|
NoHeaders bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *CustomColumnsPrinter) PrintObj(obj runtime.Object, out io.Writer) error {
|
func (s *CustomColumnsPrinter) PrintObj(obj runtime.Object, out io.Writer) error {
|
||||||
w := tabwriter.NewWriter(out, columnwidth, tabwidth, padding, padding_character, flags)
|
w := tabwriter.NewWriter(out, columnwidth, tabwidth, padding, padding_character, flags)
|
||||||
|
|
||||||
|
if !s.NoHeaders {
|
||||||
headers := make([]string, len(s.Columns))
|
headers := make([]string, len(s.Columns))
|
||||||
for ix := range s.Columns {
|
for ix := range s.Columns {
|
||||||
headers[ix] = s.Columns[ix].Header
|
headers[ix] = s.Columns[ix].Header
|
||||||
}
|
}
|
||||||
fmt.Fprintln(w, strings.Join(headers, "\t"))
|
fmt.Fprintln(w, strings.Join(headers, "\t"))
|
||||||
|
}
|
||||||
parsers := make([]*jsonpath.JSONPath, len(s.Columns))
|
parsers := make([]*jsonpath.JSONPath, len(s.Columns))
|
||||||
for ix := range s.Columns {
|
for ix := range s.Columns {
|
||||||
parsers[ix] = jsonpath.New(fmt.Sprintf("column%d", ix))
|
parsers[ix] = jsonpath.New(fmt.Sprintf("column%d", ix))
|
||||||
|
@ -19,6 +19,7 @@ package kubectl
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
@ -67,6 +68,7 @@ func TestNewColumnPrinterFromSpec(t *testing.T) {
|
|||||||
expectedColumns []Column
|
expectedColumns []Column
|
||||||
expectErr bool
|
expectErr bool
|
||||||
name string
|
name string
|
||||||
|
noHeaders bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
spec: "",
|
spec: "",
|
||||||
@ -102,9 +104,14 @@ func TestNewColumnPrinterFromSpec(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
spec: "API_VERSION:apiVersion",
|
||||||
|
name: "no-headers",
|
||||||
|
noHeaders: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
printer, err := NewCustomColumnsPrinterFromSpec(test.spec, api.Codecs.UniversalDecoder())
|
printer, err := NewCustomColumnsPrinterFromSpec(test.spec, api.Codecs.UniversalDecoder(), test.noHeaders)
|
||||||
if test.expectErr {
|
if test.expectErr {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("[%s] unexpected non-error", test.name)
|
t.Errorf("[%s] unexpected non-error", test.name)
|
||||||
@ -115,8 +122,19 @@ func TestNewColumnPrinterFromSpec(t *testing.T) {
|
|||||||
t.Errorf("[%s] unexpected error: %v", test.name, err)
|
t.Errorf("[%s] unexpected error: %v", test.name, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if test.noHeaders {
|
||||||
|
buffer := &bytes.Buffer{}
|
||||||
|
|
||||||
if !reflect.DeepEqual(test.expectedColumns, printer.Columns) {
|
printer.PrintObj(&api.Pod{}, buffer)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("An error occurred printing Pod: %#v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if contains(strings.Fields(buffer.String()), "API_VERSION") {
|
||||||
|
t.Errorf("unexpected header API_VERSION")
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if !reflect.DeepEqual(test.expectedColumns, printer.Columns) {
|
||||||
t.Errorf("[%s]\nexpected:\n%v\nsaw:\n%v\n", test.name, test.expectedColumns, printer.Columns)
|
t.Errorf("[%s]\nexpected:\n%v\nsaw:\n%v\n", test.name, test.expectedColumns, printer.Columns)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ const (
|
|||||||
// is agnostic to schema versions, so you must send arguments to PrintObj in the
|
// is agnostic to schema versions, so you must send arguments to PrintObj in the
|
||||||
// version you wish them to be shown using a VersionedPrinter (typically when
|
// version you wish them to be shown using a VersionedPrinter (typically when
|
||||||
// generic is true).
|
// generic is true).
|
||||||
func GetPrinter(format, formatArgument string) (ResourcePrinter, bool, error) {
|
func GetPrinter(format, formatArgument string, noHeaders bool) (ResourcePrinter, bool, error) {
|
||||||
var printer ResourcePrinter
|
var printer ResourcePrinter
|
||||||
switch format {
|
switch format {
|
||||||
case "json":
|
case "json":
|
||||||
@ -119,7 +119,7 @@ func GetPrinter(format, formatArgument string) (ResourcePrinter, bool, error) {
|
|||||||
}
|
}
|
||||||
case "custom-columns":
|
case "custom-columns":
|
||||||
var err error
|
var err error
|
||||||
if printer, err = NewCustomColumnsPrinterFromSpec(formatArgument, api.Codecs.UniversalDecoder()); err != nil {
|
if printer, err = NewCustomColumnsPrinterFromSpec(formatArgument, api.Codecs.UniversalDecoder(), noHeaders); err != nil {
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
case "custom-columns-file":
|
case "custom-columns-file":
|
||||||
|
@ -75,7 +75,7 @@ func TestVersionedPrinter(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestPrintDefault(t *testing.T) {
|
func TestPrintDefault(t *testing.T) {
|
||||||
printer, found, err := GetPrinter("", "")
|
printer, found, err := GetPrinter("", "", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %#v", err)
|
t.Fatalf("unexpected error: %#v", err)
|
||||||
}
|
}
|
||||||
@ -129,7 +129,7 @@ func TestPrinter(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, test := range printerTests {
|
for _, test := range printerTests {
|
||||||
buf := bytes.NewBuffer([]byte{})
|
buf := bytes.NewBuffer([]byte{})
|
||||||
printer, found, err := GetPrinter(test.Format, test.FormatArgument)
|
printer, found, err := GetPrinter(test.Format, test.FormatArgument, false)
|
||||||
if err != nil || !found {
|
if err != nil || !found {
|
||||||
t.Errorf("in %s, unexpected error: %#v", test.Name, err)
|
t.Errorf("in %s, unexpected error: %#v", test.Name, err)
|
||||||
}
|
}
|
||||||
@ -156,7 +156,7 @@ func TestBadPrinter(t *testing.T) {
|
|||||||
{"bad jsonpath", "jsonpath", "{.Name", fmt.Errorf("error parsing jsonpath {.Name, unclosed action\n")},
|
{"bad jsonpath", "jsonpath", "{.Name", fmt.Errorf("error parsing jsonpath {.Name, unclosed action\n")},
|
||||||
}
|
}
|
||||||
for _, test := range badPrinterTests {
|
for _, test := range badPrinterTests {
|
||||||
_, _, err := GetPrinter(test.Format, test.FormatArgument)
|
_, _, err := GetPrinter(test.Format, test.FormatArgument, false)
|
||||||
if err == nil || err.Error() != test.Error.Error() {
|
if err == nil || err.Error() != test.Error.Error() {
|
||||||
t.Errorf("in %s, expect %s, got %s", test.Name, test.Error, err)
|
t.Errorf("in %s, expect %s, got %s", test.Name, test.Error, err)
|
||||||
}
|
}
|
||||||
@ -333,7 +333,7 @@ func TestNamePrinter(t *testing.T) {
|
|||||||
},
|
},
|
||||||
"pod/foo\npod/bar\n"},
|
"pod/foo\npod/bar\n"},
|
||||||
}
|
}
|
||||||
printer, _, _ := GetPrinter("name", "")
|
printer, _, _ := GetPrinter("name", "", false)
|
||||||
for name, item := range tests {
|
for name, item := range tests {
|
||||||
buff := &bytes.Buffer{}
|
buff := &bytes.Buffer{}
|
||||||
err := printer.PrintObj(item.obj, buff)
|
err := printer.PrintObj(item.obj, buff)
|
||||||
|
Loading…
Reference in New Issue
Block a user