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
This commit is contained in:
Kubernetes Submit Queue 2018-04-25 14:03:21 -07:00 committed by GitHub
commit 08d358e3d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 425 additions and 379 deletions

View File

@ -149,6 +149,13 @@ package_group(
], ],
) )
package_group(
name = "pkg_kubectl_cmd_get_CONSUMERS",
packages = [
"//pkg/kubectl/cmd",
],
)
package_group( package_group(
name = "pkg_kubectl_cmd_rollout_CONSUMERS", name = "pkg_kubectl_cmd_rollout_CONSUMERS",
packages = [ packages = [
@ -177,7 +184,7 @@ package_group(
"//pkg/kubectl/cmd/auth", "//pkg/kubectl/cmd/auth",
"//pkg/kubectl/cmd/config", "//pkg/kubectl/cmd/config",
"//pkg/kubectl/cmd/create", "//pkg/kubectl/cmd/create",
"//pkg/kubectl/cmd/resource", "//pkg/kubectl/cmd/get",
"//pkg/kubectl/cmd/rollout", "//pkg/kubectl/cmd/rollout",
"//pkg/kubectl/cmd/set", "//pkg/kubectl/cmd/set",
"//pkg/kubectl/cmd/templates", "//pkg/kubectl/cmd/templates",
@ -199,7 +206,7 @@ package_group(
"//pkg/kubectl/cmd", "//pkg/kubectl/cmd",
"//pkg/kubectl/cmd/auth", "//pkg/kubectl/cmd/auth",
"//pkg/kubectl/cmd/create", "//pkg/kubectl/cmd/create",
"//pkg/kubectl/cmd/resource", "//pkg/kubectl/cmd/get",
"//pkg/kubectl/cmd/rollout", "//pkg/kubectl/cmd/rollout",
"//pkg/kubectl/cmd/set", "//pkg/kubectl/cmd/set",
"//pkg/kubectl/explain", "//pkg/kubectl/explain",
@ -233,7 +240,7 @@ package_group(
"//pkg/kubectl/cmd/auth", "//pkg/kubectl/cmd/auth",
"//pkg/kubectl/cmd/config", "//pkg/kubectl/cmd/config",
"//pkg/kubectl/cmd/create", "//pkg/kubectl/cmd/create",
"//pkg/kubectl/cmd/resource", "//pkg/kubectl/cmd/get",
"//pkg/kubectl/cmd/rollout", "//pkg/kubectl/cmd/rollout",
"//pkg/kubectl/cmd/set", "//pkg/kubectl/cmd/set",
"//pkg/kubectl/cmd/testing", "//pkg/kubectl/cmd/testing",
@ -303,7 +310,7 @@ package_group(
"//pkg/kubectl/cmd/auth", "//pkg/kubectl/cmd/auth",
"//pkg/kubectl/cmd/config", "//pkg/kubectl/cmd/config",
"//pkg/kubectl/cmd/create", "//pkg/kubectl/cmd/create",
"//pkg/kubectl/cmd/resource", "//pkg/kubectl/cmd/get",
"//pkg/kubectl/cmd/rollout", "//pkg/kubectl/cmd/rollout",
"//pkg/kubectl/cmd/set", "//pkg/kubectl/cmd/set",
"//pkg/kubectl/cmd/testing", "//pkg/kubectl/cmd/testing",

View File

@ -139,6 +139,7 @@ pkg/kubectl/cmd
pkg/kubectl/cmd/auth pkg/kubectl/cmd/auth
pkg/kubectl/cmd/config pkg/kubectl/cmd/config
pkg/kubectl/cmd/create pkg/kubectl/cmd/create
pkg/kubectl/cmd/get
pkg/kubectl/cmd/rollout pkg/kubectl/cmd/rollout
pkg/kubectl/cmd/set pkg/kubectl/cmd/set
pkg/kubectl/cmd/templates pkg/kubectl/cmd/templates

View File

@ -227,7 +227,7 @@ function wait-for-pods-with-label()
{ {
local i local i
for i in $(seq 1 10); do 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 if [[ $kubeout = $2 ]]; then
return return
fi fi

View File

@ -69,7 +69,7 @@ go_library(
"//pkg/kubectl/cmd/auth:go_default_library", "//pkg/kubectl/cmd/auth:go_default_library",
"//pkg/kubectl/cmd/config:go_default_library", "//pkg/kubectl/cmd/config:go_default_library",
"//pkg/kubectl/cmd/create: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/rollout:go_default_library",
"//pkg/kubectl/cmd/scalejob:go_default_library", "//pkg/kubectl/cmd/scalejob:go_default_library",
"//pkg/kubectl/cmd/set:go_default_library", "//pkg/kubectl/cmd/set:go_default_library",
@ -190,7 +190,6 @@ go_test(
"//pkg/apis/extensions:go_default_library", "//pkg/apis/extensions:go_default_library",
"//pkg/kubectl:go_default_library", "//pkg/kubectl:go_default_library",
"//pkg/kubectl/cmd/create: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/testing:go_default_library",
"//pkg/kubectl/cmd/util:go_default_library", "//pkg/kubectl/cmd/util:go_default_library",
"//pkg/kubectl/cmd/util/openapi: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/i18n:go_default_library",
"//pkg/kubectl/util/term:go_default_library", "//pkg/kubectl/util/term:go_default_library",
"//pkg/printers: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/googleapis/gnostic/OpenAPIv2:go_default_library",
"//vendor/github.com/spf13/cobra:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library",
"//vendor/gopkg.in/yaml.v2: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/auth:all-srcs",
"//pkg/kubectl/cmd/config:all-srcs", "//pkg/kubectl/cmd/config:all-srcs",
"//pkg/kubectl/cmd/create: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/rollout:all-srcs",
"//pkg/kubectl/cmd/scalejob:all-srcs", "//pkg/kubectl/cmd/scalejob:all-srcs",
"//pkg/kubectl/cmd/set:all-srcs", "//pkg/kubectl/cmd/set:all-srcs",

View File

@ -27,7 +27,7 @@ import (
"k8s.io/kubernetes/pkg/kubectl/cmd/auth" "k8s.io/kubernetes/pkg/kubectl/cmd/auth"
cmdconfig "k8s.io/kubernetes/pkg/kubectl/cmd/config" cmdconfig "k8s.io/kubernetes/pkg/kubectl/cmd/config"
"k8s.io/kubernetes/pkg/kubectl/cmd/create" "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/rollout"
"k8s.io/kubernetes/pkg/kubectl/cmd/set" "k8s.io/kubernetes/pkg/kubectl/cmd/set"
"k8s.io/kubernetes/pkg/kubectl/cmd/templates" "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):", Message: "Basic Commands (Intermediate):",
Commands: []*cobra.Command{ Commands: []*cobra.Command{
resource.NewCmdGet(f, ioStreams),
NewCmdExplain(f, ioStreams), NewCmdExplain(f, ioStreams),
get.NewCmdGet(f, ioStreams),
NewCmdEdit(f, ioStreams), NewCmdEdit(f, ioStreams),
NewCmdDelete(f, out, err), NewCmdDelete(f, out, err),
}, },

View File

@ -19,7 +19,6 @@ package cmd
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
@ -35,18 +34,12 @@ import (
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
"k8s.io/client-go/rest/fake"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/api/testapi"
apitesting "k8s.io/kubernetes/pkg/api/testing" apitesting "k8s.io/kubernetes/pkg/api/testing"
api "k8s.io/kubernetes/pkg/apis/core" 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" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
"k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/scheme"
"k8s.io/kubernetes/pkg/printers" "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. // 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) { func TestNormalizationFuncGlobalExistence(t *testing.T) {
// This test can be safely deleted when we will not support multiple flag formats // 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) root := NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, os.Stdout, os.Stderr)

View File

@ -1,9 +1,27 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") 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( go_library(
name = "go_default_library", name = "go_default_library",
srcs = ["get.go"], srcs = [
importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/resource", "get.go",
"get_flags.go",
"humanreadable_flags.go",
],
importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/get",
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [ deps = [
"//pkg/apis/core:go_default_library", "//pkg/apis/core:go_default_library",
@ -13,8 +31,10 @@ go_library(
"//pkg/kubectl/cmd/util/openapi:go_default_library", "//pkg/kubectl/cmd/util/openapi:go_default_library",
"//pkg/kubectl/genericclioptions:go_default_library", "//pkg/kubectl/genericclioptions:go_default_library",
"//pkg/kubectl/resource:go_default_library", "//pkg/kubectl/resource:go_default_library",
"//pkg/kubectl/scheme:go_default_library",
"//pkg/kubectl/util/i18n:go_default_library", "//pkg/kubectl/util/i18n:go_default_library",
"//pkg/printers:go_default_library", "//pkg/printers:go_default_library",
"//pkg/printers/internalversion:go_default_library",
"//pkg/util/interrupt:go_default_library", "//pkg/util/interrupt:go_default_library",
"//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/golang/glog:go_default_library",
"//vendor/github.com/spf13/cobra:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library",
@ -34,7 +54,10 @@ go_library(
go_test( go_test(
name = "go_default_test", name = "go_default_test",
srcs = ["get_test.go"], srcs = [
"get_test.go",
"humanreadable_flags_test.go",
],
data = [ data = [
"//api/openapi-spec:swagger-spec", "//api/openapi-spec:swagger-spec",
"//test/e2e/testing-manifests:all-srcs", "//test/e2e/testing-manifests:all-srcs",
@ -53,6 +76,7 @@ go_test(
"//pkg/kubectl/cmd/util/openapi/testing:go_default_library", "//pkg/kubectl/cmd/util/openapi/testing:go_default_library",
"//pkg/kubectl/genericclioptions:go_default_library", "//pkg/kubectl/genericclioptions:go_default_library",
"//pkg/kubectl/scheme: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:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime: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", "//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"],
)

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package resource package get
import ( import (
"encoding/json" "encoding/json"
@ -52,6 +52,11 @@ import (
// GetOptions contains the input to the get command. // GetOptions contains the input to the get command.
type GetOptions struct { type GetOptions struct {
PrintFlags *PrintFlags
ToPrinter func(*meta.RESTMapping, bool) (printers.ResourcePrinterFunc, error)
IsGeneric bool
PrintWithOpenAPICols bool
resource.FilenameOptions resource.FilenameOptions
Raw string Raw string
@ -67,10 +72,9 @@ type GetOptions struct {
ServerPrint bool ServerPrint bool
NoHeaders bool
Sort bool Sort bool
IgnoreNotFound bool IgnoreNotFound bool
ShowKind bool
LabelColumns []string
Export bool Export bool
IncludeUninitialized bool IncludeUninitialized bool
@ -129,7 +133,8 @@ const (
// NewGetOptions returns a GetOptions with default chunk size 500. // NewGetOptions returns a GetOptions with default chunk size 500.
func NewGetOptions(streams genericclioptions.IOStreams) *GetOptions { func NewGetOptions(streams genericclioptions.IOStreams) *GetOptions {
return &GetOptions{ return &GetOptions{
ChunkSize: 500, PrintFlags: NewGetPrintFlags(),
ChunkSize: 500,
IOStreams: streams, IOStreams: streams,
} }
@ -138,7 +143,7 @@ func NewGetOptions(streams genericclioptions.IOStreams) *GetOptions {
// NewCmdGet creates a command object for the generic "get" action, which // NewCmdGet creates a command object for the generic "get" action, which
// retrieves one or more resources from a server. // retrieves one or more resources from a server.
func NewCmdGet(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { func NewCmdGet(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
options := NewGetOptions(streams) o := NewGetOptions(streams)
validArgs := cmdutil.ValidArgList(f) validArgs := cmdutil.ValidArgList(f)
cmd := &cobra.Command{ cmd := &cobra.Command{
@ -148,77 +153,112 @@ func NewCmdGet(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Co
Long: getLong + "\n\n" + cmdutil.ValidResourceTypeList(f), Long: getLong + "\n\n" + cmdutil.ValidResourceTypeList(f),
Example: getExample, Example: getExample,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
cmdutil.CheckErr(options.Complete(f, cmd, args)) cmdutil.CheckErr(o.Complete(f, cmd, args))
cmdutil.CheckErr(options.Validate(cmd)) cmdutil.CheckErr(o.Validate(cmd))
cmdutil.CheckErr(options.Run(f, cmd, args)) cmdutil.CheckErr(o.Run(f, cmd, args))
}, },
SuggestFor: []string{"list", "ps"}, SuggestFor: []string{"list", "ps"},
ValidArgs: validArgs, ValidArgs: validArgs,
ArgAliases: kubectl.ResourceAliases(validArgs), ArgAliases: kubectl.ResourceAliases(validArgs),
} }
cmd.Flags().StringVar(&options.Raw, "raw", options.Raw, "Raw URI to request from the server. Uses the transport specified by the kubeconfig file.") o.PrintFlags.AddFlags(cmd)
cmd.Flags().BoolVarP(&options.Watch, "watch", "w", options.Watch, "After listing/getting the requested object, watch for changes. Uninitialized objects are excluded if no object name is provided.")
cmd.Flags().BoolVar(&options.WatchOnly, "watch-only", options.WatchOnly, "Watch for changes to the requested object(s), without listing/getting first.") cmd.Flags().StringVar(&o.Raw, "raw", o.Raw, "Raw URI to request from the server. Uses the transport specified by the kubeconfig file.")
cmd.Flags().Int64Var(&options.ChunkSize, "chunk-size", options.ChunkSize, "Return large lists in chunks rather than all at once. Pass 0 to disable. This flag is beta and may change in the future.") cmd.Flags().BoolVarP(&o.Watch, "watch", "w", o.Watch, "After listing/getting the requested object, watch for changes. Uninitialized objects are excluded if no object name is provided.")
cmd.Flags().BoolVar(&options.IgnoreNotFound, "ignore-not-found", options.IgnoreNotFound, "If the requested object does not exist the command will return exit code 0.") cmd.Flags().BoolVar(&o.WatchOnly, "watch-only", o.WatchOnly, "Watch for changes to the requested object(s), without listing/getting first.")
cmd.Flags().StringVarP(&options.LabelSelector, "selector", "l", options.LabelSelector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") cmd.Flags().Int64Var(&o.ChunkSize, "chunk-size", o.ChunkSize, "Return large lists in chunks rather than all at once. Pass 0 to disable. This flag is beta and may change in the future.")
cmd.Flags().StringVar(&options.FieldSelector, "field-selector", options.FieldSelector, "Selector (field query) to filter on, supports '=', '==', and '!='.(e.g. --field-selector key1=value1,key2=value2). The server only supports a limited number of field queries per type.") cmd.Flags().BoolVar(&o.IgnoreNotFound, "ignore-not-found", o.IgnoreNotFound, "If the requested object does not exist the command will return exit code 0.")
cmd.Flags().BoolVar(&options.AllNamespaces, "all-namespaces", options.AllNamespaces, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.") cmd.Flags().StringVarP(&o.LabelSelector, "selector", "l", o.LabelSelector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)")
cmd.Flags().StringVar(&o.FieldSelector, "field-selector", o.FieldSelector, "Selector (field query) to filter on, supports '=', '==', and '!='.(e.g. --field-selector key1=value1,key2=value2). The server only supports a limited number of field queries per type.")
cmd.Flags().BoolVar(&o.AllNamespaces, "all-namespaces", o.AllNamespaces, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.")
cmdutil.AddIncludeUninitializedFlag(cmd) cmdutil.AddIncludeUninitializedFlag(cmd)
cmdutil.AddPrinterFlags(cmd)
addOpenAPIPrintColumnFlags(cmd) addOpenAPIPrintColumnFlags(cmd)
addServerPrintColumnFlags(cmd) addServerPrintColumnFlags(cmd)
cmd.Flags().BoolVar(&options.ShowKind, "show-kind", options.ShowKind, "If present, list the resource type for the requested object(s).") cmd.Flags().BoolVar(&o.Export, "export", o.Export, "If true, use 'export' for the resources. Exported resources are stripped of cluster-specific information.")
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...") cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, "identifying the resource to get from a server.")
cmd.Flags().BoolVar(&options.Export, "export", options.Export, "If true, use 'export' for the resources. Exported resources are stripped of cluster-specific information.")
cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, "identifying the resource to get from a server.")
return cmd return cmd
} }
// Complete takes the command arguments and factory and infers any remaining options. // Complete takes the command arguments and factory and infers any remaining options.
func (options *GetOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { func (o *GetOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
if len(options.Raw) > 0 { if len(o.Raw) > 0 {
if len(args) > 0 { if len(args) > 0 {
return fmt.Errorf("arguments may not be passed when --raw is specified") return fmt.Errorf("arguments may not be passed when --raw is specified")
} }
return nil return nil
} }
options.ServerPrint = cmdutil.GetFlagBool(cmd, useServerPrintColumns) o.ServerPrint = cmdutil.GetFlagBool(cmd, useServerPrintColumns)
var err error var err error
options.Namespace, options.ExplicitNamespace, err = f.DefaultNamespace() o.Namespace, o.ExplicitNamespace, err = f.DefaultNamespace()
if err != nil { if err != nil {
return err return err
} }
if options.AllNamespaces { if o.AllNamespaces {
options.ExplicitNamespace = false o.ExplicitNamespace = false
} }
isSorting, err := cmd.Flags().GetString("sort-by") isSorting, err := cmd.Flags().GetString("sort-by")
if err != nil { if err != nil {
return err return err
} }
options.Sort = len(isSorting) > 0 o.Sort = len(isSorting) > 0
o.NoHeaders = cmdutil.GetFlagBool(cmd, "no-headers")
// TODO (soltysh): currently we don't support sorting and custom columns // TODO (soltysh): currently we don't support sorting and custom columns
// with server side print. So in these cases force the old behavior. // with server side print. So in these cases force the old behavior.
outputOption := cmd.Flags().Lookup("output").Value.String() outputOption := cmd.Flags().Lookup("output").Value.String()
if options.Sort && outputOption == "custom-columns" { if o.Sort && outputOption == "custom-columns" {
options.ServerPrint = false o.ServerPrint = false
} }
options.IncludeUninitialized = cmdutil.ShouldIncludeUninitialized(cmd, false) // obtain printer here in order to determine if we are
// printing humanreadable or generic output.
printer, err := o.PrintFlags.ToPrinter()
if err != nil {
return err
}
o.IsGeneric = printer.IsGeneric()
o.IncludeUninitialized = cmdutil.ShouldIncludeUninitialized(cmd, false)
o.PrintWithOpenAPICols = cmdutil.GetFlagBool(cmd, useOpenAPIPrintColumnFlagLabel)
o.ToPrinter = func(mapping *meta.RESTMapping, withNamespace bool) (printers.ResourcePrinterFunc, error) {
// make a new copy of current flags / opts before mutating
printFlags := o.PrintFlags.Copy()
if mapping != nil {
if !cmdSpecifiesOutputFmt(cmd) && o.PrintWithOpenAPICols {
if apiSchema, err := f.OpenAPISchema(); err == nil {
printFlags.UseOpenAPIColumns(apiSchema, mapping)
}
}
if resource.MultipleTypesRequested(args) {
printFlags.EnsureWithKind(mapping.GroupVersionKind.GroupKind())
}
}
if withNamespace {
printFlags.EnsureWithNamespace()
}
printer, err := printFlags.ToPrinter()
if err != nil {
return nil, err
}
return printer.PrintObj, nil
}
switch { switch {
case options.Watch || options.WatchOnly: case o.Watch || o.WatchOnly:
// include uninitialized objects when watching on a single object // include uninitialized objects when watching on a single object
// unless explicitly set --include-uninitialized=false // unless explicitly set --include-uninitialized=false
options.IncludeUninitialized = cmdutil.ShouldIncludeUninitialized(cmd, len(args) == 2) o.IncludeUninitialized = cmdutil.ShouldIncludeUninitialized(cmd, len(args) == 2)
default: default:
if len(args) == 0 && cmdutil.IsFilenameSliceEmpty(options.Filenames) { if len(args) == 0 && cmdutil.IsFilenameSliceEmpty(o.Filenames) {
fmt.Fprintf(options.ErrOut, "You must specify the type of resource to get. %s\n\n", cmdutil.ValidResourceTypeList(f)) fmt.Fprintf(o.ErrOut, "You must specify the type of resource to get. %s\n\n", cmdutil.ValidResourceTypeList(f))
fullCmdName := cmd.Parent().CommandPath() fullCmdName := cmd.Parent().CommandPath()
usageString := "Required resource not specified." usageString := "Required resource not specified."
if len(fullCmdName) > 0 && cmdutil.IsSiblingCommandExists(cmd, "explain") { if len(fullCmdName) > 0 && cmdutil.IsSiblingCommandExists(cmd, "explain") {
@ -232,15 +272,15 @@ func (options *GetOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args
} }
// Validate checks the set of flags provided by the user. // Validate checks the set of flags provided by the user.
func (options *GetOptions) Validate(cmd *cobra.Command) error { func (o *GetOptions) Validate(cmd *cobra.Command) error {
if len(options.Raw) > 0 { if len(o.Raw) > 0 {
if options.Watch || options.WatchOnly || len(options.LabelSelector) > 0 || options.Export { if o.Watch || o.WatchOnly || len(o.LabelSelector) > 0 || o.Export {
return fmt.Errorf("--raw may not be specified with other flags that filter the server request or alter the output") return fmt.Errorf("--raw may not be specified with other flags that filter the server request or alter the output")
} }
if len(cmdutil.GetFlagString(cmd, "output")) > 0 { if len(cmdutil.GetFlagString(cmd, "output")) > 0 {
return cmdutil.UsageErrorf(cmd, "--raw and --output are mutually exclusive") return cmdutil.UsageErrorf(cmd, "--raw and --output are mutually exclusive")
} }
if _, err := url.ParseRequestURI(options.Raw); err != nil { if _, err := url.ParseRequestURI(o.Raw); err != nil {
return cmdutil.UsageErrorf(cmd, "--raw must be a valid URL path: %v", err) return cmdutil.UsageErrorf(cmd, "--raw must be a valid URL path: %v", err)
} }
} }
@ -255,35 +295,29 @@ func (options *GetOptions) Validate(cmd *cobra.Command) error {
// Run performs the get operation. // Run performs the get operation.
// TODO: remove the need to pass these arguments, like other commands. // TODO: remove the need to pass these arguments, like other commands.
func (options *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []string) error { func (o *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
if len(options.Raw) > 0 { if len(o.Raw) > 0 {
return options.raw(f) return o.raw(f)
} }
if options.Watch || options.WatchOnly { if o.Watch || o.WatchOnly {
return options.watch(f, cmd, args) return o.watch(f, cmd, args)
}
printOpts := cmdutil.ExtractCmdPrintOptions(cmd, options.AllNamespaces)
printer, err := cmdutil.PrinterForOptions(printOpts)
if err != nil {
return err
} }
r := f.NewBuilder(). r := f.NewBuilder().
Unstructured(). Unstructured().
NamespaceParam(options.Namespace).DefaultNamespace().AllNamespaces(options.AllNamespaces). NamespaceParam(o.Namespace).DefaultNamespace().AllNamespaces(o.AllNamespaces).
FilenameParam(options.ExplicitNamespace, &options.FilenameOptions). FilenameParam(o.ExplicitNamespace, &o.FilenameOptions).
LabelSelectorParam(options.LabelSelector). LabelSelectorParam(o.LabelSelector).
FieldSelectorParam(options.FieldSelector). FieldSelectorParam(o.FieldSelector).
ExportParam(options.Export). ExportParam(o.Export).
RequestChunksOf(options.ChunkSize). RequestChunksOf(o.ChunkSize).
IncludeUninitialized(options.IncludeUninitialized). IncludeUninitialized(o.IncludeUninitialized).
ResourceTypeOrNameArgs(true, args...). ResourceTypeOrNameArgs(true, args...).
ContinueOnError(). ContinueOnError().
Latest(). Latest().
Flatten(). Flatten().
TransformRequests(func(req *rest.Request) { TransformRequests(func(req *rest.Request) {
if options.ServerPrint && !printer.IsGeneric() && !options.Sort { if o.ServerPrint && !o.IsGeneric && !o.Sort {
group := metav1beta1.GroupName group := metav1beta1.GroupName
version := metav1beta1.SchemeGroupVersion.Version version := metav1beta1.SchemeGroupVersion.Version
@ -293,15 +327,15 @@ func (options *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []str
}). }).
Do() Do()
if options.IgnoreNotFound { if o.IgnoreNotFound {
r.IgnoreErrors(kapierrors.IsNotFound) r.IgnoreErrors(kapierrors.IsNotFound)
} }
if err := r.Err(); err != nil { if err := r.Err(); err != nil {
return err return err
} }
if printer.IsGeneric() { if o.IsGeneric {
return options.printGeneric(printer, r) return o.printGeneric(r)
} }
allErrs := []error{} allErrs := []error{}
@ -313,8 +347,8 @@ func (options *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []str
objs := make([]runtime.Object, len(infos)) objs := make([]runtime.Object, len(infos))
for ix := range infos { for ix := range infos {
if options.ServerPrint { if o.ServerPrint {
table, err := options.decodeIntoTable(cmdutil.InternalVersionJSONEncoder(), infos[ix].Object) table, err := o.decodeIntoTable(cmdutil.InternalVersionJSONEncoder(), infos[ix].Object)
if err == nil { if err == nil {
infos[ix].Object = table infos[ix].Object = table
} else { } else {
@ -332,35 +366,26 @@ func (options *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []str
return err return err
} }
var sorter *kubectl.RuntimeSort var sorter *kubectl.RuntimeSort
if options.Sort && len(objs) > 1 { if o.Sort && len(objs) > 1 {
// TODO: questionable // TODO: questionable
if sorter, err = kubectl.SortObjects(cmdutil.InternalVersionDecoder(), objs, sorting); err != nil { if sorter, err = kubectl.SortObjects(cmdutil.InternalVersionDecoder(), objs, sorting); err != nil {
return err return err
} }
} }
// use the default printer for each object var printer printers.ResourcePrinter
printer = nil
var lastMapping *meta.RESTMapping var lastMapping *meta.RESTMapping
w := printers.GetNewTabWriter(options.Out) nonEmptyObjCount := 0
w := printers.GetNewTabWriter(o.Out)
useOpenAPIPrintColumns := cmdutil.GetFlagBool(cmd, useOpenAPIPrintColumnFlagLabel)
showKind := options.ShowKind || resource.MultipleTypesRequested(args) || cmdutil.MustPrintWithKinds(objs, infos, sorter)
noHeaders := cmdutil.GetFlagBool(cmd, "no-headers")
for ix := range objs { for ix := range objs {
var mapping *meta.RESTMapping var mapping *meta.RESTMapping
var original runtime.Object
var info *resource.Info var info *resource.Info
if sorter != nil { if sorter != nil {
info = infos[sorter.OriginalPosition(ix)] info = infos[sorter.OriginalPosition(ix)]
mapping = info.Mapping mapping = info.Mapping
original = info.Object
} else { } else {
info = infos[ix] info = infos[ix]
mapping = info.Mapping mapping = info.Mapping
original = info.Object
} }
// if dealing with a table that has no rows, skip remaining steps // if dealing with a table that has no rows, skip remaining steps
@ -371,29 +396,24 @@ func (options *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []str
} }
} }
nonEmptyObjCount++
printWithNamespace := o.AllNamespaces
if mapping != nil && mapping.Scope.Name() == meta.RESTScopeNameRoot {
printWithNamespace = false
}
if shouldGetNewPrinterForMapping(printer, lastMapping, mapping) { if shouldGetNewPrinterForMapping(printer, lastMapping, mapping) {
if printer != nil { w.Flush()
w.Flush()
// TODO: this doesn't belong here
// add linebreak between resource groups (if there is more than one)
// skip linebreak above first resource group
if lastMapping != nil && !o.NoHeaders {
fmt.Fprintln(o.ErrOut)
} }
printWithNamespace := options.AllNamespaces printer, err = o.ToPrinter(mapping, printWithNamespace)
if mapping != nil && mapping.Scope.Name() == meta.RESTScopeNameRoot {
printWithNamespace = false
}
printOpts := cmdutil.ExtractCmdPrintOptions(cmd, printWithNamespace)
// if cmd does not specify output format and useOpenAPIPrintColumnFlagLabel flag is true,
// then get the default output options for this mapping from OpenAPI schema.
if !cmdSpecifiesOutputFmt(cmd) && useOpenAPIPrintColumns {
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 err != nil {
if !errs.Has(err.Error()) { if !errs.Has(err.Error()) {
errs.Insert(err.Error()) errs.Insert(err.Error())
@ -402,66 +422,33 @@ func (options *GetOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []str
continue continue
} }
// TODO: this doesn't belong here
// add linebreak between resource groups (if there is more than one)
// skip linebreak above first resource group
if lastMapping != nil && !noHeaders {
fmt.Fprintf(options.ErrOut, "%s\n", "")
}
lastMapping = mapping lastMapping = mapping
} }
typedObj := info.AsInternal() printer.PrintObj(info.AsInternal(), w)
objToPrint := typedObj
if printer.IsGeneric() {
// use raw object as received from the builder when using generic
// printer instead of decodedObj
objToPrint = original
}
if err := printer.PrintObj(objToPrint, w); err != nil {
if !errs.Has(err.Error()) {
errs.Insert(err.Error())
allErrs = append(allErrs, err)
}
continue
}
} }
w.Flush() w.Flush()
nonEmptyObjCount := 0 if nonEmptyObjCount == 0 && !o.IgnoreNotFound {
for _, obj := range objs { fmt.Fprintln(o.ErrOut, "No resources found.")
if table, ok := obj.(*metav1beta1.Table); ok {
// exclude any Table objects with empty rows from our total object count
if len(table.Rows) == 0 {
continue
}
}
nonEmptyObjCount++
}
if nonEmptyObjCount == 0 && !options.IgnoreNotFound {
fmt.Fprintln(options.ErrOut, "No resources found.")
} }
return utilerrors.NewAggregate(allErrs) return utilerrors.NewAggregate(allErrs)
} }
// raw makes a simple HTTP request to the provided path on the server using the default // raw makes a simple HTTP request to the provided path on the server using the default
// credentials. // credentials.
func (options *GetOptions) raw(f cmdutil.Factory) error { func (o *GetOptions) raw(f cmdutil.Factory) error {
restClient, err := f.RESTClient() restClient, err := f.RESTClient()
if err != nil { if err != nil {
return err return err
} }
stream, err := restClient.Get().RequestURI(options.Raw).Stream() stream, err := restClient.Get().RequestURI(o.Raw).Stream()
if err != nil { if err != nil {
return err return err
} }
defer stream.Close() defer stream.Close()
_, err = io.Copy(options.Out, stream) _, err = io.Copy(o.Out, stream)
if err != nil && err != io.EOF { if err != nil && err != io.EOF {
return err return err
} }
@ -470,16 +457,16 @@ func (options *GetOptions) raw(f cmdutil.Factory) error {
// watch starts a client-side watch of one or more resources. // watch starts a client-side watch of one or more resources.
// TODO: remove the need for arguments here. // TODO: remove the need for arguments here.
func (options *GetOptions) watch(f cmdutil.Factory, cmd *cobra.Command, args []string) error { func (o *GetOptions) watch(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
r := f.NewBuilder(). r := f.NewBuilder().
Unstructured(). Unstructured().
NamespaceParam(options.Namespace).DefaultNamespace().AllNamespaces(options.AllNamespaces). NamespaceParam(o.Namespace).DefaultNamespace().AllNamespaces(o.AllNamespaces).
FilenameParam(options.ExplicitNamespace, &options.FilenameOptions). FilenameParam(o.ExplicitNamespace, &o.FilenameOptions).
LabelSelectorParam(options.LabelSelector). LabelSelectorParam(o.LabelSelector).
FieldSelectorParam(options.FieldSelector). FieldSelectorParam(o.FieldSelector).
ExportParam(options.Export). ExportParam(o.Export).
RequestChunksOf(options.ChunkSize). RequestChunksOf(o.ChunkSize).
IncludeUninitialized(options.IncludeUninitialized). IncludeUninitialized(o.IncludeUninitialized).
ResourceTypeOrNameArgs(true, args...). ResourceTypeOrNameArgs(true, args...).
SingleResourceType(). SingleResourceType().
Latest(). Latest().
@ -514,8 +501,7 @@ func (options *GetOptions) watch(f cmdutil.Factory, cmd *cobra.Command, args []s
info := infos[0] info := infos[0]
mapping := info.ResourceMapping() mapping := info.ResourceMapping()
printOpts := cmdutil.ExtractCmdPrintOptions(cmd, options.AllNamespaces) printer, err := o.ToPrinter(mapping, o.AllNamespaces)
printer, err := cmdutil.PrinterForOptions(printOpts)
if err != nil { if err != nil {
return err return err
} }
@ -540,9 +526,9 @@ func (options *GetOptions) watch(f cmdutil.Factory, cmd *cobra.Command, args []s
} }
// print the current object // print the current object
if !options.WatchOnly { if !o.WatchOnly {
var objsToPrint []runtime.Object var objsToPrint []runtime.Object
writer := printers.GetNewTabWriter(options.Out) writer := printers.GetNewTabWriter(o.Out)
if isList { if isList {
objsToPrint, _ = meta.ExtractList(obj) objsToPrint, _ = meta.ExtractList(obj)
@ -550,10 +536,12 @@ func (options *GetOptions) watch(f cmdutil.Factory, cmd *cobra.Command, args []s
objsToPrint = append(objsToPrint, obj) objsToPrint = append(objsToPrint, obj)
} }
for _, objToPrint := range objsToPrint { for _, objToPrint := range objsToPrint {
// printing always takes the internal version, but the watch event uses externals if !o.IsGeneric {
// TODO fix printing to use server-side or be version agnostic // printing always takes the internal version, but the watch event uses externals
internalGV := mapping.GroupVersionKind.GroupKind().WithVersion(runtime.APIVersionInternal).GroupVersion() internalGV := mapping.GroupVersionKind.GroupKind().WithVersion(runtime.APIVersionInternal).GroupVersion()
if err := printer.PrintObj(attemptToConvertToInternal(objToPrint, mapping, internalGV), writer); err != nil { objToPrint = attemptToConvertToInternal(objToPrint, mapping, internalGV)
}
if err := printer.PrintObj(objToPrint, writer); err != nil {
return fmt.Errorf("unable to output the provided object: %v", err) return fmt.Errorf("unable to output the provided object: %v", err)
} }
} }
@ -579,7 +567,7 @@ func (options *GetOptions) watch(f cmdutil.Factory, cmd *cobra.Command, args []s
// printing always takes the internal version, but the watch event uses externals // printing always takes the internal version, but the watch event uses externals
// TODO fix printing to use server-side or be version agnostic // TODO fix printing to use server-side or be version agnostic
internalGV := mapping.GroupVersionKind.GroupKind().WithVersion(runtime.APIVersionInternal).GroupVersion() internalGV := mapping.GroupVersionKind.GroupKind().WithVersion(runtime.APIVersionInternal).GroupVersion()
if err := printer.PrintObj(attemptToConvertToInternal(e.Object, mapping, internalGV), options.Out); err != nil { if err := printer.PrintObj(attemptToConvertToInternal(e.Object, mapping, internalGV), o.Out); err != nil {
return false, err return false, err
} }
return false, nil return false, nil
@ -599,7 +587,7 @@ func attemptToConvertToInternal(obj runtime.Object, converter runtime.ObjectConv
return internalObject return internalObject
} }
func (options *GetOptions) decodeIntoTable(encoder runtime.Encoder, obj runtime.Object) (runtime.Object, error) { func (o *GetOptions) decodeIntoTable(encoder runtime.Encoder, obj runtime.Object) (runtime.Object, error) {
if obj.GetObjectKind().GroupVersionKind().Kind != "Table" { if obj.GetObjectKind().GroupVersionKind().Kind != "Table" {
return nil, fmt.Errorf("attempt to decode non-Table object into a v1beta1.Table") return nil, fmt.Errorf("attempt to decode non-Table object into a v1beta1.Table")
} }
@ -618,7 +606,7 @@ func (options *GetOptions) decodeIntoTable(encoder runtime.Encoder, obj runtime.
return table, nil return table, nil
} }
func (options *GetOptions) printGeneric(printer printers.ResourcePrinter, r *resource.Result) error { func (o *GetOptions) printGeneric(r *resource.Result) error {
// we flattened the data from the builder, so we have individual items, but now we'd like to either: // we flattened the data from the builder, so we have individual items, but now we'd like to either:
// 1. if there is more than one item, combine them all into a single list // 1. if there is more than one item, combine them all into a single list
// 2. if there is a single item and that item is a list, leave it as its specific list // 2. if there is a single item and that item is a list, leave it as its specific list
@ -633,10 +621,15 @@ func (options *GetOptions) printGeneric(printer printers.ResourcePrinter, r *res
errs = append(errs, err) errs = append(errs, err)
} }
if len(infos) == 0 && options.IgnoreNotFound { if len(infos) == 0 && o.IgnoreNotFound {
return utilerrors.Reduce(utilerrors.Flatten(utilerrors.NewAggregate(errs))) return utilerrors.Reduce(utilerrors.Flatten(utilerrors.NewAggregate(errs)))
} }
printer, err := o.ToPrinter(nil, false)
if err != nil {
return err
}
var obj runtime.Object var obj runtime.Object
if !singleItemImplied || len(infos) > 1 { if !singleItemImplied || len(infos) > 1 {
// we have more than one item, so coerce all items into a list. // we have more than one item, so coerce all items into a list.
@ -694,13 +687,13 @@ func (options *GetOptions) printGeneric(printer printers.ResourcePrinter, r *res
for _, item := range items { for _, item := range items {
list.Items = append(list.Items, *item.(*unstructured.Unstructured)) list.Items = append(list.Items, *item.(*unstructured.Unstructured))
} }
if err := printer.PrintObj(list, options.Out); err != nil { if err := printer.PrintObj(list, o.Out); err != nil {
errs = append(errs, err) errs = append(errs, err)
} }
return utilerrors.Reduce(utilerrors.Flatten(utilerrors.NewAggregate(errs))) return utilerrors.Reduce(utilerrors.Flatten(utilerrors.NewAggregate(errs)))
} }
if printErr := printer.PrintObj(obj, options.Out); printErr != nil { if printErr := printer.PrintObj(obj, o.Out); printErr != nil {
errs = append(errs, printErr) errs = append(errs, printErr)
} }

View File

@ -0,0 +1,169 @@
/*
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(),
}
}

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package resource package get
import ( import (
"bytes" "bytes"
@ -513,7 +513,6 @@ func TestGetAllListObjects(t *testing.T) {
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdGet(tf, streams) cmd := NewCmdGet(tf, streams)
cmd.SetOutput(buf) cmd.SetOutput(buf)
cmd.Flags().Set("show-all", "true")
cmd.Run(cmd, []string{"pods"}) cmd.Run(cmd, []string{"pods"})
expected := `NAME READY STATUS RESTARTS AGE 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) { func watchTestData() ([]api.Pod, []watch.Event) {
pods := []api.Pod{ pods := []api.Pod{
{ {

View File

@ -14,13 +14,15 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package printers package get
import ( import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/kubernetes/pkg/kubectl/scheme" "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. // HumanPrintFlags provides default flags necessary for printing.
@ -40,11 +42,28 @@ type HumanPrintFlags struct {
WithNamespace bool 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 // ToPrinter receives an outputFormat and returns a printer capable of
// handling human-readable output. // 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" { if len(outputFormat) > 0 && outputFormat != "wide" {
return nil, false, nil return nil, printers.NoCompatiblePrinterError{Options: f}
} }
encoder := scheme.Codecs.LegacyCodec(scheme.Registry.RegisteredGroupVersions()...) encoder := scheme.Codecs.LegacyCodec(scheme.Registry.RegisteredGroupVersions()...)
@ -65,7 +84,7 @@ func (f *HumanPrintFlags) ToPrinter(outputFormat string) (ResourcePrinter, bool,
columnLabels = *f.ColumnLabels columnLabels = *f.ColumnLabels
} }
p := NewHumanReadablePrinter(encoder, decoder, PrintOptions{ p := printers.NewHumanReadablePrinter(encoder, decoder, printers.PrintOptions{
Kind: f.Kind, Kind: f.Kind,
WithKind: showKind, WithKind: showKind,
NoHeaders: f.NoHeaders, NoHeaders: f.NoHeaders,
@ -74,14 +93,11 @@ func (f *HumanPrintFlags) ToPrinter(outputFormat string) (ResourcePrinter, bool,
ColumnLabels: columnLabels, ColumnLabels: columnLabels,
ShowLabels: showLabels, ShowLabels: showLabels,
}) })
printersinternal.AddHandlers(p)
// 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)
// TODO(juanvallejo): handle sorting here // TODO(juanvallejo): handle sorting here
return p, true, nil return p, nil
} }
// AddFlags receives a *cobra.Command reference and binds // AddFlags receives a *cobra.Command reference and binds
@ -103,19 +119,19 @@ func (f *HumanPrintFlags) AddFlags(c *cobra.Command) {
// NewHumanPrintFlags returns flags associated with // NewHumanPrintFlags returns flags associated with
// human-readable printing, with default values set. // human-readable printing, with default values set.
func NewHumanPrintFlags(kind schema.GroupKind, noHeaders, withNamespace, absoluteTimestamps bool) *HumanPrintFlags { func NewHumanPrintFlags() *HumanPrintFlags {
showLabels := false showLabels := false
sortBy := "" sortBy := ""
showKind := false showKind := false
columnLabels := []string{} columnLabels := []string{}
return &HumanPrintFlags{ return &HumanPrintFlags{
NoHeaders: noHeaders, NoHeaders: false,
WithNamespace: withNamespace, WithNamespace: false,
AbsoluteTimestamps: absoluteTimestamps, AbsoluteTimestamps: false,
ColumnLabels: &columnLabels, ColumnLabels: &columnLabels,
Kind: kind, Kind: schema.GroupKind{},
ShowLabels: &showLabels, ShowLabels: &showLabels,
SortBy: &sortBy, SortBy: &sortBy,
ShowKind: &showKind, ShowKind: &showKind,

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package printers_test package get
import ( import (
"bytes" "bytes"
@ -26,11 +26,15 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
api "k8s.io/kubernetes/pkg/apis/core" api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/printers" "k8s.io/kubernetes/pkg/printers"
printersinternal "k8s.io/kubernetes/pkg/printers/internalversion"
) )
func TestHumanReadablePrinterSupportsExpectedOptions(t *testing.T) { 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 { testCases := []struct {
name string name string
@ -75,6 +79,11 @@ func TestHumanReadablePrinterSupportsExpectedOptions(t *testing.T) {
showKind: true, showKind: true,
expectedOutput: "NAME\\ +READY\\ +STATUS\\ +RESTARTS\\ +AGE\npod/foo\\ +0/0\\ +0\\ +<unknown>\n", 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", name: "withNamespace displays an additional NAMESPACE column",
withNamespace: true, withNamespace: true,
@ -94,7 +103,7 @@ func TestHumanReadablePrinterSupportsExpectedOptions(t *testing.T) {
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
printFlags := printers.HumanPrintFlags{ printFlags := HumanPrintFlags{
ShowKind: &tc.showKind, ShowKind: &tc.showKind,
ShowLabels: &tc.showLabels, ShowLabels: &tc.showLabels,
SortBy: &tc.sortBy, SortBy: &tc.sortBy,
@ -108,14 +117,14 @@ func TestHumanReadablePrinterSupportsExpectedOptions(t *testing.T) {
printFlags.Kind = schema.GroupKind{Kind: "pod"} printFlags.Kind = schema.GroupKind{Kind: "pod"}
} }
p, matched, err := printFlags.ToPrinter(tc.outputFormat) p, err := printFlags.ToPrinter(tc.outputFormat)
if tc.expectNoMatch { if tc.expectNoMatch {
if matched { if !printers.IsNoCompatiblePrinterError(err) {
t.Fatalf("expected no printer matches for output format %q", tc.outputFormat) t.Fatalf("expected no printer matches for output format %q", tc.outputFormat)
} }
return return
} }
if !matched { if printers.IsNoCompatiblePrinterError(err) {
t.Fatalf("expected to match template printer for output format %q", tc.outputFormat) 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) 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{}) out := bytes.NewBuffer([]byte{})
err = p.PrintObj(testObject, out) err = p.PrintObj(testObject, out)
if err != nil { if err != nil {

View File

@ -13,7 +13,6 @@ go_library(
"customcolumn_flags.go", "customcolumn_flags.go",
"flags.go", "flags.go",
"humanreadable.go", "humanreadable.go",
"humanreadable_flags.go",
"interface.go", "interface.go",
"json.go", "json.go",
"json_yaml_flags.go", "json_yaml_flags.go",
@ -53,7 +52,6 @@ go_test(
srcs = [ srcs = [
"customcolumn_flags_test.go", "customcolumn_flags_test.go",
"customcolumn_test.go", "customcolumn_test.go",
"humanreadable_flags_test.go",
"json_yaml_flags_test.go", "json_yaml_flags_test.go",
"jsonpath_flags_test.go", "jsonpath_flags_test.go",
"name_flags_test.go", "name_flags_test.go",
@ -63,11 +61,9 @@ go_test(
":go_default_library", ":go_default_library",
"//pkg/api/legacyscheme:go_default_library", "//pkg/api/legacyscheme:go_default_library",
"//pkg/apis/core: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/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/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:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
], ],
) )

View File

@ -23,6 +23,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/scheme"
) )
@ -37,9 +38,9 @@ type CustomColumnsPrintFlags struct {
// handling custom-column printing. // handling custom-column printing.
// Returns false if the specified templateFormat does not match a supported format. // Returns false if the specified templateFormat does not match a supported format.
// Supported format types can be found in pkg/printers/printers.go // 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 { if len(templateFormat) == 0 {
return nil, false, fmt.Errorf("missing output format") return nil, NoCompatiblePrinterError{}
} }
templateValue := "" templateValue := ""
@ -63,11 +64,11 @@ func (f *CustomColumnsPrintFlags) ToPrinter(templateFormat string) (ResourcePrin
} }
if _, supportedFormat := supportedFormats[templateFormat]; !supportedFormat { if _, supportedFormat := supportedFormats[templateFormat]; !supportedFormat {
return nil, false, nil return nil, NoCompatiblePrinterError{}
} }
if len(templateValue) == 0 { 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() decoder := scheme.Codecs.UniversalDecoder()
@ -75,15 +76,15 @@ func (f *CustomColumnsPrintFlags) ToPrinter(templateFormat string) (ResourcePrin
if templateFormat == "custom-columns-file" { if templateFormat == "custom-columns-file" {
file, err := os.Open(templateValue) file, err := os.Open(templateValue)
if err != nil { 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() defer file.Close()
p, err := NewCustomColumnsPrinterFromTemplate(file, decoder) p, err := NewCustomColumnsPrinterFromTemplate(file, decoder)
return p, true, err return p, err
} }
p, err := NewCustomColumnsPrinterFromSpec(templateValue, decoder, f.NoHeaders) 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 // AddFlags receives a *cobra.Command reference and binds
@ -93,9 +94,9 @@ func (f *CustomColumnsPrintFlags) AddFlags(c *cobra.Command) {}
// NewCustomColumnsPrintFlags returns flags associated with // NewCustomColumnsPrintFlags returns flags associated with
// custom-column printing, with default values set. // custom-column printing, with default values set.
// NoHeaders and TemplateArgument should be set by callers. // NoHeaders and TemplateArgument should be set by callers.
func NewCustomColumnsPrintFlags(noHeaders bool, templateValue string) *CustomColumnsPrintFlags { func NewCustomColumnsPrintFlags() *CustomColumnsPrintFlags {
return &CustomColumnsPrintFlags{ return &CustomColumnsPrintFlags{
NoHeaders: noHeaders, NoHeaders: false,
TemplateArgument: templateValue, TemplateArgument: "",
} }
} }

View File

@ -98,14 +98,14 @@ func TestPrinterSupportsExpectedCustomColumnFormats(t *testing.T) {
TemplateArgument: tc.templateArg, TemplateArgument: tc.templateArg,
} }
p, matched, err := printFlags.ToPrinter(tc.outputFormat) p, err := printFlags.ToPrinter(tc.outputFormat)
if tc.expectNoMatch { if tc.expectNoMatch {
if matched { if !printers.IsNoCompatiblePrinterError(err) {
t.Fatalf("expected no printer matches for output format %q", tc.outputFormat) t.Fatalf("expected no printer matches for output format %q", tc.outputFormat)
} }
return return
} }
if !matched { if printers.IsNoCompatiblePrinterError(err) {
t.Fatalf("expected to match template printer for output format %q", tc.outputFormat) t.Fatalf("expected to match template printer for output format %q", tc.outputFormat)
} }

View File

@ -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) { func TestPrintUnstructuredObject(t *testing.T) {
obj := &unstructured.Unstructured{ obj := &unstructured.Unstructured{
Object: map[string]interface{}{ Object: map[string]interface{}{

View File

@ -75,37 +75,13 @@ func GetStandardPrinter(typer runtime.ObjectTyper, encoder runtime.Encoder, deco
NoHeaders: options.NoHeaders, NoHeaders: options.NoHeaders,
TemplateArgument: formatArgument, TemplateArgument: formatArgument,
} }
customColumnsPrinter, matched, err := customColumnsFlags.ToPrinter(format) customColumnsPrinter, err := customColumnsFlags.ToPrinter(format)
if !matched {
return nil, fmt.Errorf("unable to match a name printer to handle current print options")
}
if err != nil { if err != nil {
return nil, err return nil, err
} }
printer = customColumnsPrinter 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: default:
return nil, fmt.Errorf("output format %q not recognized", format) return nil, fmt.Errorf("output format %q not recognized", format)
} }