Unverified Commit 08d358e3 authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #62881 from juanvallejo/jvallejo/wire-print-flags-get-cmd

Automatic merge from submit-queue (batch tested with PRs 61601, 62881, 63159). 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>. wire print flags through get.go **Release note**: ```release-note NONE ``` Adds the PrintFlags pattern to `get.go`. Prerequisite to ongoing server-side printing work. cc @soltysh @deads2k
parents 30101be0 191a48f4
......@@ -150,6 +150,13 @@ package_group(
)
package_group(
name = "pkg_kubectl_cmd_get_CONSUMERS",
packages = [
"//pkg/kubectl/cmd",
],
)
package_group(
name = "pkg_kubectl_cmd_rollout_CONSUMERS",
packages = [
"//pkg/kubectl/cmd",
......@@ -177,7 +184,7 @@ package_group(
"//pkg/kubectl/cmd/auth",
"//pkg/kubectl/cmd/config",
"//pkg/kubectl/cmd/create",
"//pkg/kubectl/cmd/resource",
"//pkg/kubectl/cmd/get",
"//pkg/kubectl/cmd/rollout",
"//pkg/kubectl/cmd/set",
"//pkg/kubectl/cmd/templates",
......@@ -199,7 +206,7 @@ package_group(
"//pkg/kubectl/cmd",
"//pkg/kubectl/cmd/auth",
"//pkg/kubectl/cmd/create",
"//pkg/kubectl/cmd/resource",
"//pkg/kubectl/cmd/get",
"//pkg/kubectl/cmd/rollout",
"//pkg/kubectl/cmd/set",
"//pkg/kubectl/explain",
......@@ -233,7 +240,7 @@ package_group(
"//pkg/kubectl/cmd/auth",
"//pkg/kubectl/cmd/config",
"//pkg/kubectl/cmd/create",
"//pkg/kubectl/cmd/resource",
"//pkg/kubectl/cmd/get",
"//pkg/kubectl/cmd/rollout",
"//pkg/kubectl/cmd/set",
"//pkg/kubectl/cmd/testing",
......@@ -303,7 +310,7 @@ package_group(
"//pkg/kubectl/cmd/auth",
"//pkg/kubectl/cmd/config",
"//pkg/kubectl/cmd/create",
"//pkg/kubectl/cmd/resource",
"//pkg/kubectl/cmd/get",
"//pkg/kubectl/cmd/rollout",
"//pkg/kubectl/cmd/set",
"//pkg/kubectl/cmd/testing",
......
......@@ -139,6 +139,7 @@ pkg/kubectl/cmd
pkg/kubectl/cmd/auth
pkg/kubectl/cmd/config
pkg/kubectl/cmd/create
pkg/kubectl/cmd/get
pkg/kubectl/cmd/rollout
pkg/kubectl/cmd/set
pkg/kubectl/cmd/templates
......
......@@ -227,7 +227,7 @@ function wait-for-pods-with-label()
{
local i
for i in $(seq 1 10); do
kubeout=`kubectl get po -l $1 --template '{{range.items}}{{.metadata.name}}{{end}}' --sort-by metadata.name "${kube_flags[@]}"`
kubeout=`kubectl get po -l $1 --output=go-template --template='{{range.items}}{{.metadata.name}}{{end}}' --sort-by metadata.name "${kube_flags[@]}"`
if [[ $kubeout = $2 ]]; then
return
fi
......
......@@ -69,7 +69,7 @@ go_library(
"//pkg/kubectl/cmd/auth:go_default_library",
"//pkg/kubectl/cmd/config:go_default_library",
"//pkg/kubectl/cmd/create:go_default_library",
"//pkg/kubectl/cmd/resource:go_default_library",
"//pkg/kubectl/cmd/get:go_default_library",
"//pkg/kubectl/cmd/rollout:go_default_library",
"//pkg/kubectl/cmd/scalejob:go_default_library",
"//pkg/kubectl/cmd/set:go_default_library",
......@@ -190,7 +190,6 @@ go_test(
"//pkg/apis/extensions:go_default_library",
"//pkg/kubectl:go_default_library",
"//pkg/kubectl/cmd/create:go_default_library",
"//pkg/kubectl/cmd/resource:go_default_library",
"//pkg/kubectl/cmd/testing:go_default_library",
"//pkg/kubectl/cmd/util:go_default_library",
"//pkg/kubectl/cmd/util/openapi:go_default_library",
......@@ -201,7 +200,6 @@ go_test(
"//pkg/kubectl/util/i18n:go_default_library",
"//pkg/kubectl/util/term:go_default_library",
"//pkg/printers:go_default_library",
"//pkg/util/strings:go_default_library",
"//vendor/github.com/googleapis/gnostic/OpenAPIv2:go_default_library",
"//vendor/github.com/spf13/cobra:go_default_library",
"//vendor/gopkg.in/yaml.v2:go_default_library",
......@@ -249,7 +247,7 @@ filegroup(
"//pkg/kubectl/cmd/auth:all-srcs",
"//pkg/kubectl/cmd/config:all-srcs",
"//pkg/kubectl/cmd/create:all-srcs",
"//pkg/kubectl/cmd/resource:all-srcs",
"//pkg/kubectl/cmd/get:all-srcs",
"//pkg/kubectl/cmd/rollout:all-srcs",
"//pkg/kubectl/cmd/scalejob:all-srcs",
"//pkg/kubectl/cmd/set:all-srcs",
......
......@@ -27,7 +27,7 @@ import (
"k8s.io/kubernetes/pkg/kubectl/cmd/auth"
cmdconfig "k8s.io/kubernetes/pkg/kubectl/cmd/config"
"k8s.io/kubernetes/pkg/kubectl/cmd/create"
"k8s.io/kubernetes/pkg/kubectl/cmd/resource"
"k8s.io/kubernetes/pkg/kubectl/cmd/get"
"k8s.io/kubernetes/pkg/kubectl/cmd/rollout"
"k8s.io/kubernetes/pkg/kubectl/cmd/set"
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
......@@ -264,8 +264,8 @@ func NewKubectlCommand(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cob
{
Message: "Basic Commands (Intermediate):",
Commands: []*cobra.Command{
resource.NewCmdGet(f, ioStreams),
NewCmdExplain(f, ioStreams),
get.NewCmdGet(f, ioStreams),
NewCmdEdit(f, ioStreams),
NewCmdDelete(f, out, err),
},
......
......@@ -19,7 +19,6 @@ package cmd
import (
"bytes"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
......@@ -35,18 +34,12 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
restclient "k8s.io/client-go/rest"
"k8s.io/client-go/rest/fake"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/api/testapi"
apitesting "k8s.io/kubernetes/pkg/api/testing"
api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/kubectl/cmd/resource"
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
"k8s.io/kubernetes/pkg/kubectl/scheme"
"k8s.io/kubernetes/pkg/printers"
"k8s.io/kubernetes/pkg/util/strings"
)
// This init should be removed after switching this command and its tests to user external types.
......@@ -244,78 +237,6 @@ func newAllPhasePodList() *api.PodList {
}
}
func Example_printServiceWithLabels() {
tf := cmdtesting.NewTestFactory()
defer tf.Cleanup()
ns := legacyscheme.Codecs
tf.Client = &fake.RESTClient{
NegotiatedSerializer: ns,
Client: nil,
}
cmd := resource.NewCmdGet(tf, genericclioptions.NewTestIOStreamsDiscard())
svc := &api.ServiceList{
Items: []api.Service{
{
ObjectMeta: metav1.ObjectMeta{
Name: "svc1",
Namespace: "ns1",
CreationTimestamp: metav1.Time{Time: time.Now().AddDate(-10, 0, 0)},
Labels: map[string]string{
"l1": "value",
},
},
Spec: api.ServiceSpec{
Ports: []api.ServicePort{
{Protocol: "UDP", Port: 53},
{Protocol: "TCP", Port: 53},
},
Selector: map[string]string{
"s": "magic",
},
ClusterIP: "10.1.1.1",
Type: api.ServiceTypeClusterIP,
},
Status: api.ServiceStatus{},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "svc2",
Namespace: "ns2",
CreationTimestamp: metav1.Time{Time: time.Now().AddDate(-10, 0, 0)},
Labels: map[string]string{
"l1": "dolla-bill-yall",
},
},
Spec: api.ServiceSpec{
Ports: []api.ServicePort{
{Protocol: "TCP", Port: 80},
{Protocol: "TCP", Port: 8080},
},
Selector: map[string]string{
"s": "kazam",
},
ClusterIP: "10.1.1.2",
Type: api.ServiceTypeClusterIP,
},
Status: api.ServiceStatus{},
}},
}
ld := strings.NewLineDelimiter(os.Stdout, "|")
defer ld.Flush()
cmd.Flags().Set("label-columns", "l1")
err := cmdutil.PrintObject(cmd, svc, ld)
if err != nil {
fmt.Printf("Unexpected error: %v", err)
}
// Output:
// |NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE L1|
// |svc1 ClusterIP 10.1.1.1 <none> 53/UDP,53/TCP 10y value|
// |svc2 ClusterIP 10.1.1.2 <none> 80/TCP,8080/TCP 10y dolla-bill-yall|
// ||
}
func TestNormalizationFuncGlobalExistence(t *testing.T) {
// This test can be safely deleted when we will not support multiple flag formats
root := NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, os.Stdout, os.Stderr)
......
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_library(
name = "go_default_library",
srcs = ["get.go"],
importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/resource",
srcs = [
"get.go",
"get_flags.go",
"humanreadable_flags.go",
],
importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/get",
visibility = ["//visibility:public"],
deps = [
"//pkg/apis/core:go_default_library",
......@@ -13,8 +31,10 @@ go_library(
"//pkg/kubectl/cmd/util/openapi:go_default_library",
"//pkg/kubectl/genericclioptions:go_default_library",
"//pkg/kubectl/resource:go_default_library",
"//pkg/kubectl/scheme:go_default_library",
"//pkg/kubectl/util/i18n:go_default_library",
"//pkg/printers:go_default_library",
"//pkg/printers/internalversion:go_default_library",
"//pkg/util/interrupt:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/github.com/spf13/cobra:go_default_library",
......@@ -34,7 +54,10 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["get_test.go"],
srcs = [
"get_test.go",
"humanreadable_flags_test.go",
],
data = [
"//api/openapi-spec:swagger-spec",
"//test/e2e/testing-manifests:all-srcs",
......@@ -53,6 +76,7 @@ go_test(
"//pkg/kubectl/cmd/util/openapi/testing:go_default_library",
"//pkg/kubectl/genericclioptions:go_default_library",
"//pkg/kubectl/scheme:go_default_library",
"//pkg/printers:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
......@@ -68,17 +92,3 @@ go_test(
"//vendor/k8s.io/kube-openapi/pkg/util/proto:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package get
import (
"strings"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi"
"k8s.io/kubernetes/pkg/printers"
)
// PrintFlags composes common printer flag structs
// used in the Get command.
type PrintFlags struct {
JSONYamlPrintFlags *printers.JSONYamlPrintFlags
NamePrintFlags *printers.NamePrintFlags
TemplateFlags *printers.KubeTemplatePrintFlags
CustomColumnsFlags *printers.CustomColumnsPrintFlags
HumanReadableFlags *HumanPrintFlags
NoHeaders *bool
OutputFormat *string
}
// EnsureWithNamespace ensures that humanreadable flags return
// a printer capable of printing with a "namespace" column.
func (f *PrintFlags) EnsureWithNamespace() error {
return f.HumanReadableFlags.EnsureWithNamespace()
}
// EnsureWithKind ensures that humanreadable flags return
// a printer capable of including resource kinds.
func (f *PrintFlags) EnsureWithKind(kind schema.GroupKind) error {
return f.HumanReadableFlags.EnsureWithKind(kind)
}
// Copy returns a copy of PrintFlags for mutation
func (f *PrintFlags) Copy() PrintFlags {
printFlags := *f
return printFlags
}
// UseOpenAPIColumns modifies the output format, as well as the
// "allowMissingKeys" option for template printers, to values
// defined in the OpenAPI schema of a resource.
func (f *PrintFlags) UseOpenAPIColumns(api openapi.Resources, mapping *meta.RESTMapping) error {
// Found openapi metadata for this resource
schema := api.LookupResource(mapping.GroupVersionKind)
if schema == nil {
// Schema not found, return empty columns
return nil
}
columns, found := openapi.GetPrintColumns(schema.GetExtensions())
if !found {
// Extension not found, return empty columns
return nil
}
parts := strings.SplitN(columns, "=", 2)
if len(parts) < 2 {
return nil
}
allowMissingKeys := true
f.OutputFormat = &parts[0]
f.TemplateFlags.TemplateArgument = &parts[1]
f.TemplateFlags.AllowMissingKeys = &allowMissingKeys
return nil
}
// ToPrinter attempts to find a composed set of PrintFlags suitable for
// returning a printer based on current flag values.
func (f *PrintFlags) ToPrinter() (printers.ResourcePrinter, error) {
outputFormat := ""
if f.OutputFormat != nil {
outputFormat = *f.OutputFormat
}
noHeaders := false
if f.NoHeaders != nil {
noHeaders = *f.NoHeaders
}
f.HumanReadableFlags.NoHeaders = noHeaders
f.CustomColumnsFlags.NoHeaders = noHeaders
if f.TemplateFlags.TemplateArgument != nil {
f.CustomColumnsFlags.TemplateArgument = *f.TemplateFlags.TemplateArgument
}
if p, err := f.JSONYamlPrintFlags.ToPrinter(outputFormat); !printers.IsNoCompatiblePrinterError(err) {
return p, err
}
if p, err := f.HumanReadableFlags.ToPrinter(outputFormat); !printers.IsNoCompatiblePrinterError(err) {
return p, err
}
if p, err := f.TemplateFlags.ToPrinter(outputFormat); !printers.IsNoCompatiblePrinterError(err) {
return p, err
}
if p, err := f.CustomColumnsFlags.ToPrinter(outputFormat); !printers.IsNoCompatiblePrinterError(err) {
return p, err
}
if p, err := f.NamePrintFlags.ToPrinter(outputFormat); !printers.IsNoCompatiblePrinterError(err) {
return p, err
}
return nil, printers.NoCompatiblePrinterError{Options: f}
}
// AddFlags receives a *cobra.Command reference and binds
// flags related to humanreadable and template printing.
func (f *PrintFlags) AddFlags(cmd *cobra.Command) {
f.JSONYamlPrintFlags.AddFlags(cmd)
f.NamePrintFlags.AddFlags(cmd)
f.TemplateFlags.AddFlags(cmd)
f.HumanReadableFlags.AddFlags(cmd)
f.CustomColumnsFlags.AddFlags(cmd)
if f.OutputFormat != nil {
cmd.Flags().StringVarP(f.OutputFormat, "output", "o", *f.OutputFormat, "Output format. One of: json|yaml|wide|name|custom-columns=...|custom-columns-file=...|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=... See custom columns [http://kubernetes.io/docs/user-guide/kubectl-overview/#custom-columns], golang template [http://golang.org/pkg/text/template/#pkg-overview] and jsonpath template [http://kubernetes.io/docs/user-guide/jsonpath].")
}
if f.NoHeaders != nil {
cmd.Flags().BoolVar(f.NoHeaders, "no-headers", *f.NoHeaders, "When using the default or custom-column output format, don't print headers (default print headers).")
}
// TODO(juanvallejo): This is deprecated - remove
cmd.Flags().BoolP("show-all", "a", true, "When printing, show all resources (default show all pods including terminated one.)")
cmd.Flags().MarkDeprecated("show-all", "will be removed in an upcoming release")
}
// NewGetPrintFlags returns flags associated with humanreadable,
// template, and "name" printing, with default values set.
func NewGetPrintFlags() *PrintFlags {
outputFormat := ""
noHeaders := false
return &PrintFlags{
OutputFormat: &outputFormat,
NoHeaders: &noHeaders,
JSONYamlPrintFlags: printers.NewJSONYamlPrintFlags(),
NamePrintFlags: printers.NewNamePrintFlags(""),
TemplateFlags: printers.NewKubeTemplatePrintFlags(),
HumanReadableFlags: NewHumanPrintFlags(),
CustomColumnsFlags: printers.NewCustomColumnsPrintFlags(),
}
}
......@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package resource
package get
import (
"bytes"
......@@ -513,7 +513,6 @@ func TestGetAllListObjects(t *testing.T) {
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdGet(tf, streams)
cmd.SetOutput(buf)
cmd.Flags().Set("show-all", "true")
cmd.Run(cmd, []string{"pods"})
expected := `NAME READY STATUS RESTARTS AGE
......@@ -889,32 +888,6 @@ node/foo Unknown <none> <unknown>
}
}
func TestGetByFormatForcesFlag(t *testing.T) {
pods, _, _ := testData()
tf := cmdtesting.NewTestFactory()
defer tf.Cleanup()
codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...)
tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer,
Resp: &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])},
}
tf.Namespace = "test"
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdGet(tf, streams)
cmd.SetOutput(buf)
cmd.Flags().Lookup("output").Value.Set("yaml")
cmd.Flags().Set("show-all", "false")
cmd.Run(cmd, []string{"pods"})
showAllFlag, _ := cmd.Flags().GetBool("show-all")
if showAllFlag {
t.Error("expected showAll to not be true when getting resource")
}
}
func watchTestData() ([]api.Pod, []watch.Event) {
pods := []api.Pod{
{
......
......@@ -14,13 +14,15 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package printers
package get
import (
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/kubernetes/pkg/kubectl/scheme"
"k8s.io/kubernetes/pkg/printers"
printersinternal "k8s.io/kubernetes/pkg/printers/internalversion"
)
// HumanPrintFlags provides default flags necessary for printing.
......@@ -40,11 +42,28 @@ type HumanPrintFlags struct {
WithNamespace bool
}
// EnsureWithKind sets the provided GroupKind humanreadable value.
// If the kind received is non-empty, the "showKind" humanreadable
// printer option is set to true.
func (f *HumanPrintFlags) EnsureWithKind(kind schema.GroupKind) error {
showKind := !kind.Empty()
f.Kind = kind
f.ShowKind = &showKind
return nil
}
// EnsureWithNamespace sets the "WithNamespace" humanreadable option to true.
func (f *HumanPrintFlags) EnsureWithNamespace() error {
f.WithNamespace = true
return nil
}
// ToPrinter receives an outputFormat and returns a printer capable of
// handling human-readable output.
func (f *HumanPrintFlags) ToPrinter(outputFormat string) (ResourcePrinter, bool, error) {
func (f *HumanPrintFlags) ToPrinter(outputFormat string) (printers.ResourcePrinter, error) {
if len(outputFormat) > 0 && outputFormat != "wide" {
return nil, false, nil
return nil, printers.NoCompatiblePrinterError{Options: f}
}
encoder := scheme.Codecs.LegacyCodec(scheme.Registry.RegisteredGroupVersions()...)
......@@ -65,7 +84,7 @@ func (f *HumanPrintFlags) ToPrinter(outputFormat string) (ResourcePrinter, bool,
columnLabels = *f.ColumnLabels
}
p := NewHumanReadablePrinter(encoder, decoder, PrintOptions{
p := printers.NewHumanReadablePrinter(encoder, decoder, printers.PrintOptions{
Kind: f.Kind,
WithKind: showKind,
NoHeaders: f.NoHeaders,
......@@ -74,14 +93,11 @@ func (f *HumanPrintFlags) ToPrinter(outputFormat string) (ResourcePrinter, bool,
ColumnLabels: columnLabels,
ShowLabels: showLabels,
})
// TODO(juanvallejo): enable this here once we wire commands to instantiate PrintFlags directly.
// PrintHandlers are currently added through cmd/util/printing.go#PrinterForOptions
//printersinternal.AddHandlers(p)
printersinternal.AddHandlers(p)
// TODO(juanvallejo): handle sorting here
return p, true, nil
return p, nil
}
// AddFlags receives a *cobra.Command reference and binds
......@@ -103,19 +119,19 @@ func (f *HumanPrintFlags) AddFlags(c *cobra.Command) {
// NewHumanPrintFlags returns flags associated with
// human-readable printing, with default values set.
func NewHumanPrintFlags(kind schema.GroupKind, noHeaders, withNamespace, absoluteTimestamps bool) *HumanPrintFlags {
func NewHumanPrintFlags() *HumanPrintFlags {
showLabels := false
sortBy := ""
showKind := false
columnLabels := []string{}
return &HumanPrintFlags{
NoHeaders: noHeaders,
WithNamespace: withNamespace,
AbsoluteTimestamps: absoluteTimestamps,
NoHeaders: false,
WithNamespace: false,
AbsoluteTimestamps: false,
ColumnLabels: &columnLabels,
Kind: kind,
Kind: schema.GroupKind{},
ShowLabels: &showLabels,
SortBy: &sortBy,
ShowKind: &showKind,
......
......@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package printers_test
package get
import (
"bytes"
......@@ -26,11 +26,15 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/printers"
printersinternal "k8s.io/kubernetes/pkg/printers/internalversion"
)
func TestHumanReadablePrinterSupportsExpectedOptions(t *testing.T) {
testObject := &api.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}
testObject := &api.Pod{ObjectMeta: metav1.ObjectMeta{
Name: "foo",
Labels: map[string]string{
"l1": "value",
},
}}
testCases := []struct {
name string
......@@ -76,6 +80,11 @@ func TestHumanReadablePrinterSupportsExpectedOptions(t *testing.T) {
expectedOutput: "NAME\\ +READY\\ +STATUS\\ +RESTARTS\\ +AGE\npod/foo\\ +0/0\\ +0\\ +<unknown>\n",
},
{
name: "label-columns prints specified label values in new column",
columnLabels: []string{"l1"},
expectedOutput: "NAME\\ +READY\\ +STATUS\\ +RESTARTS\\ +AGE\\ +L1\nfoo\\ +0/0\\ +0\\ +<unknown>\\ +value\n",
},
{
name: "withNamespace displays an additional NAMESPACE column",
withNamespace: true,
expectedOutput: "NAMESPACE\\ +NAME\\ +READY\\ +STATUS\\ +RESTARTS\\ +AGE\n\\ +foo\\ +0/0\\ +0\\ +<unknown>\n",
......@@ -94,7 +103,7 @@ func TestHumanReadablePrinterSupportsExpectedOptions(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
printFlags := printers.HumanPrintFlags{
printFlags := HumanPrintFlags{
ShowKind: &tc.showKind,
ShowLabels: &tc.showLabels,
SortBy: &tc.sortBy,
......@@ -108,14 +117,14 @@ func TestHumanReadablePrinterSupportsExpectedOptions(t *testing.T) {
printFlags.Kind = schema.GroupKind{Kind: "pod"}
}
p, matched, err := printFlags.ToPrinter(tc.outputFormat)
p, err := printFlags.ToPrinter(tc.outputFormat)
if tc.expectNoMatch {
if matched {
if !printers.IsNoCompatiblePrinterError(err) {
t.Fatalf("expected no printer matches for output format %q", tc.outputFormat)
}
return
}
if !matched {
if printers.IsNoCompatiblePrinterError(err) {
t.Fatalf("expected to match template printer for output format %q", tc.outputFormat)
}
......@@ -129,10 +138,6 @@ func TestHumanReadablePrinterSupportsExpectedOptions(t *testing.T) {
t.Fatalf("unexpected error: %v", err)
}
// TODO(juanvallejo): remove this once we wire PrintFlags at the command level.
// handlers should be attached to the printer inside of the ToPrinter method.
printersinternal.AddHandlers(p.(*printers.HumanReadablePrinter))
out := bytes.NewBuffer([]byte{})
err = p.PrintObj(testObject, out)
if err != nil {
......
......@@ -13,7 +13,6 @@ go_library(
"customcolumn_flags.go",
"flags.go",
"humanreadable.go",
"humanreadable_flags.go",
"interface.go",
"json.go",
"json_yaml_flags.go",
......@@ -53,7 +52,6 @@ go_test(
srcs = [
"customcolumn_flags_test.go",
"customcolumn_test.go",
"humanreadable_flags_test.go",
"json_yaml_flags_test.go",
"jsonpath_flags_test.go",
"name_flags_test.go",
......@@ -63,11 +61,9 @@ go_test(
":go_default_library",
"//pkg/api/legacyscheme:go_default_library",
"//pkg/apis/core:go_default_library",
"//pkg/printers/internalversion:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
],
)
......
......@@ -23,6 +23,7 @@ import (
"github.com/spf13/cobra"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/kubectl/scheme"
)
......@@ -37,9 +38,9 @@ type CustomColumnsPrintFlags struct {
// handling custom-column printing.
// Returns false if the specified templateFormat does not match a supported format.
// Supported format types can be found in pkg/printers/printers.go
func (f *CustomColumnsPrintFlags) ToPrinter(templateFormat string) (ResourcePrinter, bool, error) {
func (f *CustomColumnsPrintFlags) ToPrinter(templateFormat string) (ResourcePrinter, error) {
if len(templateFormat) == 0 {
return nil, false, fmt.Errorf("missing output format")
return nil, NoCompatiblePrinterError{}
}
templateValue := ""
......@@ -63,11 +64,11 @@ func (f *CustomColumnsPrintFlags) ToPrinter(templateFormat string) (ResourcePrin
}
if _, supportedFormat := supportedFormats[templateFormat]; !supportedFormat {
return nil, false, nil
return nil, NoCompatiblePrinterError{}
}
if len(templateValue) == 0 {
return nil, true, fmt.Errorf("custom-columns format specified but no custom columns given")
return nil, fmt.Errorf("custom-columns format specified but no custom columns given")
}
decoder := scheme.Codecs.UniversalDecoder()
......@@ -75,15 +76,15 @@ func (f *CustomColumnsPrintFlags) ToPrinter(templateFormat string) (ResourcePrin
if templateFormat == "custom-columns-file" {
file, err := os.Open(templateValue)
if err != nil {
return nil, true, fmt.Errorf("error reading template %s, %v\n", templateValue, err)
return nil, fmt.Errorf("error reading template %s, %v\n", templateValue, err)
}
defer file.Close()
p, err := NewCustomColumnsPrinterFromTemplate(file, decoder)
return p, true, err
return p, err
}
p, err := NewCustomColumnsPrinterFromSpec(templateValue, decoder, f.NoHeaders)
return p, true, err
return NewVersionedPrinter(p, legacyscheme.Scheme, legacyscheme.Scheme, scheme.Versions...), err
}
// AddFlags receives a *cobra.Command reference and binds
......@@ -93,9 +94,9 @@ func (f *CustomColumnsPrintFlags) AddFlags(c *cobra.Command) {}
// NewCustomColumnsPrintFlags returns flags associated with
// custom-column printing, with default values set.
// NoHeaders and TemplateArgument should be set by callers.
func NewCustomColumnsPrintFlags(noHeaders bool, templateValue string) *CustomColumnsPrintFlags {
func NewCustomColumnsPrintFlags() *CustomColumnsPrintFlags {
return &CustomColumnsPrintFlags{
NoHeaders: noHeaders,
TemplateArgument: templateValue,
NoHeaders: false,
TemplateArgument: "",
}
}
......@@ -98,14 +98,14 @@ func TestPrinterSupportsExpectedCustomColumnFormats(t *testing.T) {
TemplateArgument: tc.templateArg,
}
p, matched, err := printFlags.ToPrinter(tc.outputFormat)
p, err := printFlags.ToPrinter(tc.outputFormat)
if tc.expectNoMatch {
if matched {
if !printers.IsNoCompatiblePrinterError(err) {
t.Fatalf("expected no printer matches for output format %q", tc.outputFormat)
}
return
}
if !matched {
if printers.IsNoCompatiblePrinterError(err) {
t.Fatalf("expected to match template printer for output format %q", tc.outputFormat)
}
......
......@@ -99,26 +99,6 @@ func TestVersionedPrinter(t *testing.T) {
}
}
func TestPrintDefault(t *testing.T) {
printerTests := []struct {
Name string
Format string
}{
{"test wide", "wide"},
{"test blank format", ""},
}
for _, test := range printerTests {
printer, err := printers.GetStandardPrinter(nil, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.RegisteredGroupVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, printers.PrintOptions{AllowMissingKeys: false})
if err != nil {
t.Errorf("in %s, unexpected error: %#v", test.Name, err)
}
if printer.IsGeneric() {
t.Errorf("in %s, printer should not be generic: %#v", test.Name, printer)
}
}
}
func TestPrintUnstructuredObject(t *testing.T) {
obj := &unstructured.Unstructured{
Object: map[string]interface{}{
......
......@@ -75,37 +75,13 @@ func GetStandardPrinter(typer runtime.ObjectTyper, encoder runtime.Encoder, deco
NoHeaders: options.NoHeaders,
TemplateArgument: formatArgument,
}
customColumnsPrinter, matched, err := customColumnsFlags.ToPrinter(format)
if !matched {
return nil, fmt.Errorf("unable to match a name printer to handle current print options")
}
customColumnsPrinter, err := customColumnsFlags.ToPrinter(format)
if err != nil {
return nil, err
}
printer = customColumnsPrinter
case "wide":
fallthrough
case "":
humanPrintFlags := NewHumanPrintFlags(options.Kind, options.NoHeaders, options.WithNamespace, options.AbsoluteTimestamps)
// TODO: these should be bound through a call to humanPrintFlags#AddFlags(cmd) once we instantiate PrintFlags at the command level
humanPrintFlags.ShowKind = &options.WithKind
humanPrintFlags.ShowLabels = &options.ShowLabels
humanPrintFlags.ColumnLabels = &options.ColumnLabels
humanPrintFlags.SortBy = &options.SortBy
humanPrinter, matches, err := humanPrintFlags.ToPrinter(format)
if !matches {
return nil, fmt.Errorf("unable to match a printer to handle current print options")
}
if err != nil {
return nil, err
}
printer = humanPrinter
default:
return nil, fmt.Errorf("output format %q not recognized", format)
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment