mirror of https://github.com/k3s-io/k3s
Merge pull request #61985 from liggitt/show-kind
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. Restore show-kind function when printing multiple kinds Fixes #61979 * Makes the human readable printer work off the options given to it for displaying kind * Simplifies get.go to pass showkind/kind options into the printer rather than doing conditional fixup afterward ```release-note kubectl: restore the ability to show resource kinds when displaying multiple objects ```pull/8/head
commit
d3bed1e5c9
|
@ -388,6 +388,11 @@ func (options *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []str
|
|||
updatePrintOptionsForOpenAPI(f, mapping, printOpts)
|
||||
}
|
||||
|
||||
if showKind && mapping != nil {
|
||||
printOpts.WithKind = true
|
||||
printOpts.Kind = mapping.GroupVersionKind.GroupKind()
|
||||
}
|
||||
|
||||
printer, err = cmdutil.PrinterForOptions(printOpts)
|
||||
if err != nil {
|
||||
if !errs.Has(err.Error()) {
|
||||
|
@ -409,33 +414,6 @@ func (options *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []str
|
|||
|
||||
typedObj := info.AsInternal()
|
||||
|
||||
if resourcePrinter, found := printer.(*printers.HumanReadablePrinter); found {
|
||||
resourceName := resourcePrinter.GetResourceKind()
|
||||
if mapping != nil {
|
||||
if resourceName == "" {
|
||||
resourceName = mapping.Resource
|
||||
}
|
||||
if alias, ok := kubectl.ResourceShortFormFor(mapping.Resource); ok {
|
||||
resourceName = alias
|
||||
} else if resourceName == "" {
|
||||
resourceName = "none"
|
||||
}
|
||||
} else {
|
||||
resourceName = "none"
|
||||
}
|
||||
|
||||
if showKind {
|
||||
resourcePrinter.EnsurePrintWithKind(resourceName)
|
||||
}
|
||||
|
||||
if err := printer.PrintObj(typedObj, w); err != nil {
|
||||
if !errs.Has(err.Error()) {
|
||||
errs.Insert(err.Error())
|
||||
allErrs = append(allErrs, err)
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
objToPrint := typedObj
|
||||
if printer.IsGeneric() {
|
||||
// use raw object as received from the builder when using generic
|
||||
|
|
|
@ -658,10 +658,10 @@ func TestGetMultipleTypeObjects(t *testing.T) {
|
|||
cmd.Run(cmd, []string{"pods,services"})
|
||||
|
||||
expected := `NAME READY STATUS RESTARTS AGE
|
||||
foo 0/0 0 <unknown>
|
||||
bar 0/0 0 <unknown>
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
baz ClusterIP <none> <none> <none> <unknown>
|
||||
pod/foo 0/0 0 <unknown>
|
||||
pod/bar 0/0 0 <unknown>
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
service/baz ClusterIP <none> <none> <none> <unknown>
|
||||
`
|
||||
if e, a := expected, buf.String(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
|
@ -806,10 +806,10 @@ func TestGetMultipleTypeObjectsWithLabelSelector(t *testing.T) {
|
|||
cmd.Run(cmd, []string{"pods,services"})
|
||||
|
||||
expected := `NAME READY STATUS RESTARTS AGE
|
||||
foo 0/0 0 <unknown>
|
||||
bar 0/0 0 <unknown>
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
baz ClusterIP <none> <none> <none> <unknown>
|
||||
pod/foo 0/0 0 <unknown>
|
||||
pod/bar 0/0 0 <unknown>
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
service/baz ClusterIP <none> <none> <none> <unknown>
|
||||
`
|
||||
if e, a := expected, buf.String(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
|
@ -851,10 +851,10 @@ func TestGetMultipleTypeObjectsWithFieldSelector(t *testing.T) {
|
|||
cmd.Run(cmd, []string{"pods,services"})
|
||||
|
||||
expected := `NAME READY STATUS RESTARTS AGE
|
||||
foo 0/0 0 <unknown>
|
||||
bar 0/0 0 <unknown>
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
baz ClusterIP <none> <none> <none> <unknown>
|
||||
pod/foo 0/0 0 <unknown>
|
||||
pod/bar 0/0 0 <unknown>
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
service/baz ClusterIP <none> <none> <none> <unknown>
|
||||
`
|
||||
if e, a := expected, buf.String(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
|
@ -899,10 +899,10 @@ func TestGetMultipleTypeObjectsWithDirectReference(t *testing.T) {
|
|||
|
||||
cmd.Run(cmd, []string{"services/bar", "node/foo"})
|
||||
|
||||
expected := `NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
baz ClusterIP <none> <none> <none> <unknown>
|
||||
NAME STATUS ROLES AGE VERSION
|
||||
foo Unknown <none> <unknown>
|
||||
expected := `NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
service/baz ClusterIP <none> <none> <none> <unknown>
|
||||
NAME STATUS ROLES AGE VERSION
|
||||
node/foo Unknown <none> <unknown>
|
||||
`
|
||||
if e, a := expected, buf.String(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
|
|
|
@ -101,19 +101,6 @@ func (a *HumanReadablePrinter) With(fns ...func(PrintHandler)) *HumanReadablePri
|
|||
return a
|
||||
}
|
||||
|
||||
// GetResourceKind returns the type currently set for a resource
|
||||
func (h *HumanReadablePrinter) GetResourceKind() string {
|
||||
return h.options.Kind
|
||||
}
|
||||
|
||||
// EnsurePrintWithKind sets HumanReadablePrinter options "WithKind" to true
|
||||
// and "Kind" to the string arg it receives, pre-pending this string
|
||||
// to the "NAME" column in an output of resources.
|
||||
func (h *HumanReadablePrinter) EnsurePrintWithKind(kind string) {
|
||||
h.options.WithKind = true
|
||||
h.options.Kind = kind
|
||||
}
|
||||
|
||||
// EnsurePrintHeaders sets the HumanReadablePrinter option "NoHeaders" to false
|
||||
// and removes the .lastType that was printed, which forces headers to be
|
||||
// printed in cases where multiple lists of the same resource are printed
|
||||
|
@ -411,7 +398,7 @@ func DecorateTable(table *metav1beta1.Table, options PrintOptions) error {
|
|||
columns := table.ColumnDefinitions
|
||||
|
||||
nameColumn := -1
|
||||
if options.WithKind && len(options.Kind) > 0 {
|
||||
if options.WithKind && !options.Kind.Empty() {
|
||||
for i := range columns {
|
||||
if columns[i].Format == "name" && columns[i].Type == "string" {
|
||||
nameColumn = i
|
||||
|
@ -451,7 +438,7 @@ func DecorateTable(table *metav1beta1.Table, options PrintOptions) error {
|
|||
row := rows[i]
|
||||
|
||||
if nameColumn != -1 {
|
||||
row.Cells[nameColumn] = fmt.Sprintf("%s/%s", options.Kind, row.Cells[nameColumn])
|
||||
row.Cells[nameColumn] = fmt.Sprintf("%s/%s", strings.ToLower(options.Kind.String()), row.Cells[nameColumn])
|
||||
}
|
||||
|
||||
var m metav1.Object
|
||||
|
@ -607,8 +594,8 @@ func printRows(output io.Writer, rows []metav1beta1.TableRow, options PrintOptio
|
|||
fmt.Fprint(output, "\t")
|
||||
} else {
|
||||
// TODO: remove this once we drop the legacy printers
|
||||
if options.WithKind && len(options.Kind) > 0 {
|
||||
fmt.Fprintf(output, "%s/%s", options.Kind, cell)
|
||||
if options.WithKind && !options.Kind.Empty() {
|
||||
fmt.Fprintf(output, "%s/%s", strings.ToLower(options.Kind.String()), cell)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
@ -785,12 +772,12 @@ func appendLabelCells(values []interface{}, itemLabels map[string]string, opts P
|
|||
|
||||
// FormatResourceName receives a resource kind, name, and boolean specifying
|
||||
// whether or not to update the current name to "kind/name"
|
||||
func FormatResourceName(kind, name string, withKind bool) string {
|
||||
if !withKind || kind == "" {
|
||||
func FormatResourceName(kind schema.GroupKind, name string, withKind bool) string {
|
||||
if !withKind || kind.Empty() {
|
||||
return name
|
||||
}
|
||||
|
||||
return kind + "/" + name
|
||||
return strings.ToLower(kind.String()) + "/" + name
|
||||
}
|
||||
|
||||
func AppendLabels(itemLabels map[string]string, columnLabels []string) string {
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
"io"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
// ResourcePrinter is an interface that knows how to print runtime objects.
|
||||
|
@ -68,7 +69,7 @@ type PrintOptions struct {
|
|||
ShowAll bool
|
||||
ShowLabels bool
|
||||
AbsoluteTimestamps bool
|
||||
Kind string
|
||||
Kind schema.GroupKind
|
||||
ColumnLabels []string
|
||||
|
||||
SortBy string
|
||||
|
|
|
@ -40,6 +40,7 @@ import (
|
|||
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/duration"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/kubernetes/pkg/api/events"
|
||||
|
@ -1759,7 +1760,12 @@ func printControllerRevision(obj *apps.ControllerRevision, options printers.Prin
|
|||
controllerName := "<none>"
|
||||
if controllerRef != nil {
|
||||
withKind := true
|
||||
controllerName = printers.FormatResourceName(controllerRef.Kind, controllerRef.Name, withKind)
|
||||
gv, err := schema.ParseGroupVersion(controllerRef.APIVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gvk := gv.WithKind(controllerRef.Kind)
|
||||
controllerName = printers.FormatResourceName(gvk.GroupKind(), controllerRef.Name, withKind)
|
||||
}
|
||||
revision := obj.Revision
|
||||
age := translateTimestamp(obj.CreationTimestamp)
|
||||
|
|
|
@ -375,13 +375,15 @@ func TestJSONPrinter(t *testing.T) {
|
|||
|
||||
func TestFormatResourceName(t *testing.T) {
|
||||
tests := []struct {
|
||||
kind, name string
|
||||
want string
|
||||
kind schema.GroupKind
|
||||
name string
|
||||
want string
|
||||
}{
|
||||
{"", "", ""},
|
||||
{"", "name", "name"},
|
||||
{"kind", "", "kind/"}, // should not happen in practice
|
||||
{"kind", "name", "kind/name"},
|
||||
{schema.GroupKind{}, "", ""},
|
||||
{schema.GroupKind{}, "name", "name"},
|
||||
{schema.GroupKind{Kind: "Kind"}, "", "kind/"}, // should not happen in practice
|
||||
{schema.GroupKind{Kind: "Kind"}, "name", "kind/name"},
|
||||
{schema.GroupKind{Group: "group", Kind: "Kind"}, "name", "kind.group/name"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
if got := printers.FormatResourceName(tt.kind, tt.name, true); got != tt.want {
|
||||
|
@ -394,7 +396,7 @@ func PrintCustomType(obj *TestPrintType, w io.Writer, options printers.PrintOpti
|
|||
data := obj.Data
|
||||
kind := options.Kind
|
||||
if options.WithKind {
|
||||
data = kind + "/" + data
|
||||
data = kind.String() + "/" + data
|
||||
}
|
||||
_, err := fmt.Fprintf(w, "%s", data)
|
||||
return err
|
||||
|
@ -421,24 +423,6 @@ func TestCustomTypePrinting(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestCustomTypePrintingWithKind(t *testing.T) {
|
||||
columns := []string{"Data"}
|
||||
printer := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{})
|
||||
printer.Handler(columns, nil, PrintCustomType)
|
||||
printer.EnsurePrintWithKind("test")
|
||||
|
||||
obj := TestPrintType{"test object"}
|
||||
buffer := &bytes.Buffer{}
|
||||
err := printer.PrintObj(&obj, buffer)
|
||||
if err != nil {
|
||||
t.Fatalf("An error occurred printing the custom type: %#v", err)
|
||||
}
|
||||
expectedOutput := "DATA\ntest/test object"
|
||||
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, nil, printers.PrintOptions{})
|
||||
|
@ -1582,8 +1566,8 @@ func TestPrintPodTable(t *testing.T) {
|
|||
expect: "NAME\tREADY\tSTATUS\tRESTARTS\tAGE\ntest1\t1/2\tRunning\t6\t<unknown>\n",
|
||||
},
|
||||
{
|
||||
obj: runningPod, opts: printers.PrintOptions{WithKind: true, Kind: "pods"},
|
||||
expect: "NAME\tREADY\tSTATUS\tRESTARTS\tAGE\npods/test1\t1/2\tRunning\t6\t<unknown>\n",
|
||||
obj: runningPod, opts: printers.PrintOptions{WithKind: true, Kind: schema.GroupKind{Kind: "Pod"}},
|
||||
expect: "NAME\tREADY\tSTATUS\tRESTARTS\tAGE\npod/test1\t1/2\tRunning\t6\t<unknown>\n",
|
||||
},
|
||||
{
|
||||
obj: runningPod, opts: printers.PrintOptions{ShowLabels: true},
|
||||
|
@ -3058,6 +3042,7 @@ func TestPrintControllerRevision(t *testing.T) {
|
|||
OwnerReferences: []metav1.OwnerReference{
|
||||
{
|
||||
Controller: boolP(true),
|
||||
APIVersion: "apps/v1",
|
||||
Kind: "DaemonSet",
|
||||
Name: "foo",
|
||||
},
|
||||
|
@ -3065,7 +3050,7 @@ func TestPrintControllerRevision(t *testing.T) {
|
|||
},
|
||||
Revision: 1,
|
||||
},
|
||||
"test1\tDaemonSet/foo\t1\t0s\n",
|
||||
"test1\tdaemonset.apps/foo\t1\t0s\n",
|
||||
},
|
||||
{
|
||||
apps.ControllerRevision{
|
||||
|
|
Loading…
Reference in New Issue