Merge pull request #28352 from vefimova/fix_22986-1

Automatic merge from submit-queue

Added warning msg for `kubectl get`

- added warning description regarding terminated pods to `get` long help message
  - added printing of warning message in case of `get pods` if there are hidden pods

Fixes #22986  (initiall PR and discussion are here #26417)

## **Output examples:**
### # kubectl get pods
```
NAME                       READY     STATUS             RESTARTS   AGE
dapi-test-pod1             0/1       Terminating        0          22h
liveness-http              0/1       CrashLoopBackOff   11245      22d
ubuntu1-1206318548-oh9tc   0/1       CrashLoopBackOff   2336       8d
  info: 1 completed object(s) was(were) not shown in pods list. Pass --show-all to see all objects.

```

### #  kubectl get pods,namespaces
```
NAME                          READY     STATUS             RESTARTS   AGE
po/dapi-test-pod1             0/1       Terminating        0          22h
po/liveness-http              1/1       Running            11242      22d
po/ubuntu1-1206318548-oh9tc   0/1       CrashLoopBackOff   2335       8d
 info: 1 completed object(s) was(were) not shown in pods list. Pass --show-all to see all objects.

NAME             STATUS    AGE
ns/default       Active    89d
ns/kube-system   Active    41d
```

### # kubectl get pods -a
```
NAME                       READY     STATUS             RESTARTS   AGE
busybox                    0/1       Error              0          27d
dapi-test-pod1             0/1       Terminating        0          22h
liveness-http              0/1       CrashLoopBackOff   11245      22d
ubuntu1-1206318548-oh9tc   0/1       CrashLoopBackOff   2336       8d
```

### # kubectl get -h
```
Display one or many resources.

Possible resource types include (case insensitive): pods (aka 'po'), services (aka 'svc'), deployments (aka 'deploy'),
replicasets (aka 'rs'), replicationcontrollers (aka 'rc'), nodes (aka 'no'), events (aka 'ev'), limitranges (aka 'limits'),
persistentvolumes (aka 'pv'), persistentvolumeclaims (aka 'pvc'), resourcequotas (aka 'quota'), namespaces (aka 'ns'),
serviceaccounts (aka 'sa'), ingresses (aka 'ing'), horizontalpodautoscalers (aka 'hpa'), daemonsets (aka 'ds'), configmaps (aka 'cm'),
componentstatuses (aka 'cs), endpoints (aka 'ep'), petsets (alpha feature, may be unstable) and secrets.

This command will hide resources that have completed. For instance, pods that are in the Succeeded or Failed phases.
You can see the full results for any resource by providing the '--show-all' flag.

By specifying the output as 'template' and providing a Go template as the value
of the --template flag, you can filter the attributes of the fetched resource(s).

Examples:

.........
````
This commit is contained in:
Kubernetes Submit Queue 2016-08-17 05:11:50 -07:00 committed by GitHub
commit aedeccda95
8 changed files with 177 additions and 53 deletions

View File

@ -233,7 +233,7 @@ Find more information at https://github.com/kubernetes/kubernetes.`,
// From this point and forward we get warnings on flags that contain "_" separators
cmds.SetGlobalNormalizationFunc(flag.WarnWordSepNormalizeFunc)
cmds.AddCommand(NewCmdGet(f, out))
cmds.AddCommand(NewCmdGet(f, out, err))
cmds.AddCommand(set.NewCmdSet(f, out))
cmds.AddCommand(NewCmdDescribe(f, out))
cmds.AddCommand(NewCmdCreate(f, out))

View File

@ -165,6 +165,10 @@ func (t *testPrinter) HandledResources() []string {
return []string{}
}
func (t *testPrinter) FinishPrint(output io.Writer, res string) error {
return nil
}
type testDescriber struct {
Name, Namespace string
Settings kubectl.DescriberSettings

View File

@ -44,6 +44,9 @@ var (
`) + kubectl.PossibleResourceTypes + dedent.Dedent(`
This command will hide resources that have completed. For instance, pods that are in the Succeeded or Failed phases.
You can see the full results for any resource by providing the '--show-all' flag.
By specifying the output as 'template' and providing a Go template as the value
of the --template flag, you can filter the attributes of the fetched resource(s).`)
get_example = dedent.Dedent(`
@ -74,7 +77,7 @@ var (
// NewCmdGet creates a command object for the generic "get" action, which
// retrieves one or more resources from a server.
func NewCmdGet(f *cmdutil.Factory, out io.Writer) *cobra.Command {
func NewCmdGet(f *cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
options := &GetOptions{}
// retrieve a list of handled resources from printer as valid args
@ -94,7 +97,7 @@ func NewCmdGet(f *cmdutil.Factory, out io.Writer) *cobra.Command {
Long: get_long,
Example: get_example,
Run: func(cmd *cobra.Command, args []string) {
err := RunGet(f, out, cmd, args, options)
err := RunGet(f, out, errOut, cmd, args, options)
cmdutil.CheckErr(err)
},
SuggestFor: []string{"list", "ps"},
@ -118,7 +121,7 @@ func NewCmdGet(f *cmdutil.Factory, out io.Writer) *cobra.Command {
// RunGet implements the generic Get command
// TODO: convert all direct flag accessors to a struct and pass that instead of cmd
func RunGet(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *GetOptions) error {
func RunGet(f *cmdutil.Factory, out io.Writer, errOut io.Writer, cmd *cobra.Command, args []string, options *GetOptions) error {
selector := cmdutil.GetFlagString(cmd, "selector")
allNamespaces := cmdutil.GetFlagBool(cmd, "all-namespaces")
showKind := cmdutil.GetFlagBool(cmd, "show-kind")
@ -177,7 +180,6 @@ func RunGet(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string
if err != nil {
return err
}
obj, err := r.Object()
if err != nil {
return err
@ -203,6 +205,7 @@ func RunGet(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string
if err := printer.PrintObj(obj, out); err != nil {
return fmt.Errorf("unable to output the provided object: %v", err)
}
printer.FinishPrint(errOut, mapping.Resource)
}
// print watched changes
@ -218,7 +221,11 @@ func RunGet(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string
first = false
return nil
}
return printer.PrintObj(e.Object, out)
err := printer.PrintObj(e.Object, out)
if err == nil {
printer.FinishPrint(errOut, mapping.Resource)
}
return err
})
return nil
}
@ -265,6 +272,10 @@ func RunGet(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string
if err != nil {
return err
}
res := ""
if len(infos) > 0 {
res = infos[0].ResourceMapping().Resource
}
obj, err := resource.AsVersionedObject(infos, !singular, version, f.JSONEncoder())
if err != nil {
@ -274,6 +285,7 @@ func RunGet(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string
if err := printer.PrintObj(obj, out); err != nil {
allErrs = append(allErrs, err)
}
printer.FinishPrint(errOut, res)
return utilerrors.NewAggregate(allErrs)
}
@ -322,7 +334,6 @@ func RunGet(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string
printer = nil
var lastMapping *meta.RESTMapping
w := kubectl.GetNewTabWriter(out)
defer w.Flush()
if mustPrintWithKinds(objs, infos, sorter) {
showKind = true
@ -339,6 +350,10 @@ func RunGet(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string
original = infos[ix].Object
}
if printer == nil || lastMapping == nil || mapping == nil || mapping.Resource != lastMapping.Resource {
if printer != nil {
w.Flush()
printer.FinishPrint(errOut, lastMapping.Resource)
}
printer, err = f.PrinterForMapping(cmd, mapping, allNamespaces)
if err != nil {
allErrs = append(allErrs, err)
@ -375,6 +390,10 @@ func RunGet(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string
continue
}
}
w.Flush()
if printer != nil {
printer.FinishPrint(errOut, lastMapping.Resource)
}
return utilerrors.NewAggregate(allErrs)
}

View File

@ -127,8 +127,9 @@ func TestGetUnknownSchemaObject(t *testing.T) {
tf.Namespace = "test"
tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}
buf := bytes.NewBuffer([]byte{})
errBuf := bytes.NewBuffer([]byte{})
cmd := NewCmdGet(f, buf)
cmd := NewCmdGet(f, buf, errBuf)
cmd.SetOutput(buf)
cmd.Run(cmd, []string{"type", "foo"})
@ -203,12 +204,13 @@ func TestGetUnknownSchemaObjectListGeneric(t *testing.T) {
tf.Namespace = "test"
tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}
buf := bytes.NewBuffer([]byte{})
cmd := NewCmdGet(f, buf)
errBuf := bytes.NewBuffer([]byte{})
cmd := NewCmdGet(f, buf, errBuf)
cmd.SetOutput(buf)
cmd.Flags().Set("output", "json")
cmd.Flags().Set("output-version", test.outputVersion)
err := RunGet(f, buf, cmd, []string{"type/foo", "replicationcontrollers/foo"}, &GetOptions{})
err := RunGet(f, buf, errBuf, cmd, []string{"type/foo", "replicationcontrollers/foo"}, &GetOptions{})
if err != nil {
t.Errorf("%s: unexpected error: %v", k, err)
continue
@ -246,8 +248,9 @@ func TestGetSchemaObject(t *testing.T) {
tf.Namespace = "test"
tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &unversioned.GroupVersion{Version: "v1"}}}
buf := bytes.NewBuffer([]byte{})
errBuf := bytes.NewBuffer([]byte{})
cmd := NewCmdGet(f, buf)
cmd := NewCmdGet(f, buf, errBuf)
cmd.Run(cmd, []string{"replicationcontrollers", "foo"})
if !strings.Contains(buf.String(), "\"foo\"") {
@ -266,8 +269,9 @@ func TestGetObjects(t *testing.T) {
}
tf.Namespace = "test"
buf := bytes.NewBuffer([]byte{})
errBuf := bytes.NewBuffer([]byte{})
cmd := NewCmdGet(f, buf)
cmd := NewCmdGet(f, buf, errBuf)
cmd.SetOutput(buf)
cmd.Run(cmd, []string{"pods", "foo"})
@ -312,7 +316,9 @@ func TestGetSortedObjects(t *testing.T) {
tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &unversioned.GroupVersion{Version: "v1"}}}
buf := bytes.NewBuffer([]byte{})
cmd := NewCmdGet(f, buf)
errBuf := bytes.NewBuffer([]byte{})
cmd := NewCmdGet(f, buf, errBuf)
cmd.SetOutput(buf)
// sorting with metedata.name
@ -342,8 +348,9 @@ func TestGetObjectsIdentifiedByFile(t *testing.T) {
}
tf.Namespace = "test"
buf := bytes.NewBuffer([]byte{})
errBuf := bytes.NewBuffer([]byte{})
cmd := NewCmdGet(f, buf)
cmd := NewCmdGet(f, buf, errBuf)
cmd.SetOutput(buf)
cmd.Flags().Set("filename", "../../../examples/storage/cassandra/cassandra-controller.yaml")
cmd.Run(cmd, []string{})
@ -369,8 +376,9 @@ func TestGetListObjects(t *testing.T) {
}
tf.Namespace = "test"
buf := bytes.NewBuffer([]byte{})
errBuf := bytes.NewBuffer([]byte{})
cmd := NewCmdGet(f, buf)
cmd := NewCmdGet(f, buf, errBuf)
cmd.SetOutput(buf)
cmd.Run(cmd, []string{"pods"})
@ -412,8 +420,9 @@ func TestGetAllListObjects(t *testing.T) {
}
tf.Namespace = "test"
buf := bytes.NewBuffer([]byte{})
errBuf := bytes.NewBuffer([]byte{})
cmd := NewCmdGet(f, buf)
cmd := NewCmdGet(f, buf, errBuf)
cmd.SetOutput(buf)
cmd.Flags().Set("show-all", "true")
cmd.Run(cmd, []string{"pods"})
@ -442,8 +451,9 @@ func TestGetListComponentStatus(t *testing.T) {
}
tf.Namespace = "test"
buf := bytes.NewBuffer([]byte{})
errBuf := bytes.NewBuffer([]byte{})
cmd := NewCmdGet(f, buf)
cmd := NewCmdGet(f, buf, errBuf)
cmd.SetOutput(buf)
cmd.Run(cmd, []string{"componentstatuses"})
@ -481,8 +491,9 @@ func TestGetMultipleTypeObjects(t *testing.T) {
}
tf.Namespace = "test"
buf := bytes.NewBuffer([]byte{})
errBuf := bytes.NewBuffer([]byte{})
cmd := NewCmdGet(f, buf)
cmd := NewCmdGet(f, buf, errBuf)
cmd.SetOutput(buf)
cmd.Run(cmd, []string{"pods,services"})
@ -521,8 +532,9 @@ func TestGetMultipleTypeObjectsAsList(t *testing.T) {
tf.Namespace = "test"
tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}
buf := bytes.NewBuffer([]byte{})
errBuf := bytes.NewBuffer([]byte{})
cmd := NewCmdGet(f, buf)
cmd := NewCmdGet(f, buf, errBuf)
cmd.SetOutput(buf)
cmd.Flags().Set("output", "json")
@ -583,8 +595,9 @@ func TestGetMultipleTypeObjectsWithSelector(t *testing.T) {
}
tf.Namespace = "test"
buf := bytes.NewBuffer([]byte{})
errBuf := bytes.NewBuffer([]byte{})
cmd := NewCmdGet(f, buf)
cmd := NewCmdGet(f, buf, errBuf)
cmd.SetOutput(buf)
cmd.Flags().Set("selector", "a=b")
@ -632,8 +645,9 @@ func TestGetMultipleTypeObjectsWithDirectReference(t *testing.T) {
}
tf.Namespace = "test"
buf := bytes.NewBuffer([]byte{})
errBuf := bytes.NewBuffer([]byte{})
cmd := NewCmdGet(f, buf)
cmd := NewCmdGet(f, buf, errBuf)
cmd.SetOutput(buf)
cmd.Run(cmd, []string{"services/bar", "node/foo"})
@ -659,8 +673,9 @@ func TestGetByNameForcesFlag(t *testing.T) {
}
tf.Namespace = "test"
buf := bytes.NewBuffer([]byte{})
errBuf := bytes.NewBuffer([]byte{})
cmd := NewCmdGet(f, buf)
cmd := NewCmdGet(f, buf, errBuf)
cmd.SetOutput(buf)
cmd.Run(cmd, []string{"pods", "foo"})
@ -770,8 +785,9 @@ func TestWatchSelector(t *testing.T) {
}
tf.Namespace = "test"
buf := bytes.NewBuffer([]byte{})
errBuf := bytes.NewBuffer([]byte{})
cmd := NewCmdGet(f, buf)
cmd := NewCmdGet(f, buf, errBuf)
cmd.SetOutput(buf)
cmd.Flags().Set("watch", "true")
@ -809,8 +825,9 @@ func TestWatchResource(t *testing.T) {
}
tf.Namespace = "test"
buf := bytes.NewBuffer([]byte{})
errBuf := bytes.NewBuffer([]byte{})
cmd := NewCmdGet(f, buf)
cmd := NewCmdGet(f, buf, errBuf)
cmd.SetOutput(buf)
cmd.Flags().Set("watch", "true")
@ -847,7 +864,9 @@ func TestWatchResourceIdentifiedByFile(t *testing.T) {
}
tf.Namespace = "test"
buf := bytes.NewBuffer([]byte{})
cmd := NewCmdGet(f, buf)
errBuf := bytes.NewBuffer([]byte{})
cmd := NewCmdGet(f, buf, errBuf)
cmd.SetOutput(buf)
cmd.Flags().Set("watch", "true")
@ -886,8 +905,9 @@ func TestWatchOnlyResource(t *testing.T) {
}
tf.Namespace = "test"
buf := bytes.NewBuffer([]byte{})
errBuf := bytes.NewBuffer([]byte{})
cmd := NewCmdGet(f, buf)
cmd := NewCmdGet(f, buf, errBuf)
cmd.SetOutput(buf)
cmd.Flags().Set("watch-only", "true")
@ -930,8 +950,9 @@ func TestWatchOnlyList(t *testing.T) {
}
tf.Namespace = "test"
buf := bytes.NewBuffer([]byte{})
errBuf := bytes.NewBuffer([]byte{})
cmd := NewCmdGet(f, buf)
cmd := NewCmdGet(f, buf, errBuf)
cmd.SetOutput(buf)
cmd.Flags().Set("watch-only", "true")

View File

@ -155,6 +155,10 @@ type CustomColumnsPrinter struct {
NoHeaders bool
}
func (s *CustomColumnsPrinter) FinishPrint(w io.Writer, res string) error {
return nil
}
func (s *CustomColumnsPrinter) PrintObj(obj runtime.Object, out io.Writer) error {
w := tabwriter.NewWriter(out, columnwidth, tabwidth, padding, padding_character, flags)

View File

@ -147,6 +147,9 @@ type ResourcePrinter interface {
// Print receives a runtime object, formats it and prints it to a writer.
PrintObj(runtime.Object, io.Writer) error
HandledResources() []string
//Can be used to print out warning/clarifications if needed
//after all objects were printed
FinishPrint(io.Writer, string) error
}
// ResourcePrinterFunc is a function that can print objects
@ -162,6 +165,10 @@ func (fn ResourcePrinterFunc) HandledResources() []string {
return []string{}
}
func (fn ResourcePrinterFunc) FinishPrint(io.Writer, string) error {
return nil
}
// VersionedPrinter takes runtime objects and ensures they are converted to a given API version
// prior to being passed to a nested printer.
type VersionedPrinter struct {
@ -179,6 +186,10 @@ func NewVersionedPrinter(printer ResourcePrinter, converter runtime.ObjectConver
}
}
func (p *VersionedPrinter) FinishPrint(w io.Writer, res string) error {
return nil
}
// PrintObj implements ResourcePrinter
func (p *VersionedPrinter) PrintObj(obj runtime.Object, w io.Writer) error {
if len(p.versions) == 0 {
@ -211,6 +222,10 @@ type NamePrinter struct {
Typer runtime.ObjectTyper
}
func (p *NamePrinter) FinishPrint(w io.Writer, res string) error {
return nil
}
// PrintObj is an implementation of ResourcePrinter.PrintObj which decodes the object
// and print "resource/name" pair. If the object is a List, print all items in it.
func (p *NamePrinter) PrintObj(obj runtime.Object, w io.Writer) error {
@ -259,6 +274,10 @@ func (p *NamePrinter) HandledResources() []string {
type JSONPrinter struct {
}
func (p *JSONPrinter) FinishPrint(w io.Writer, res string) error {
return nil
}
// PrintObj is an implementation of ResourcePrinter.PrintObj which simply writes the object to the Writer.
func (p *JSONPrinter) PrintObj(obj runtime.Object, w io.Writer) error {
switch obj := obj.(type) {
@ -291,6 +310,10 @@ type YAMLPrinter struct {
converter runtime.ObjectConvertor
}
func (p *YAMLPrinter) FinishPrint(w io.Writer, res string) error {
return nil
}
// PrintObj prints the data as YAML.
func (p *YAMLPrinter) PrintObj(obj runtime.Object, w io.Writer) error {
switch obj := obj.(type) {
@ -319,6 +342,7 @@ func (p *YAMLPrinter) HandledResources() []string {
type handlerEntry struct {
columns []string
printFunc reflect.Value
args []reflect.Value
}
type PrintOptions struct {
@ -338,9 +362,10 @@ type PrintOptions struct {
// will only be printed if the object type changes. This makes it useful for printing items
// received from watches.
type HumanReadablePrinter struct {
handlerMap map[reflect.Type]*handlerEntry
options PrintOptions
lastType reflect.Type
handlerMap map[reflect.Type]*handlerEntry
options PrintOptions
lastType reflect.Type
hiddenObjNum int
}
// NewHumanReadablePrinter creates a HumanReadablePrinter.
@ -384,6 +409,7 @@ func (h *HumanReadablePrinter) Handler(columns []string, printFunc interface{})
glog.Errorf("Unable to add print handler: %v", err)
return err
}
objType := printFuncValue.Type().In(0)
h.handlerMap[objType] = &handlerEntry{
columns: columns,
@ -431,6 +457,14 @@ func (h *HumanReadablePrinter) HandledResources() []string {
return keys
}
func (h *HumanReadablePrinter) FinishPrint(output io.Writer, res string) error {
if !h.options.NoHeaders && !h.options.ShowAll && h.hiddenObjNum > 0 {
_, err := fmt.Fprintf(output, " info: %d completed object(s) was(were) not shown in %s list. Pass --show-all to see all objects.\n\n", h.hiddenObjNum, res)
return err
}
return nil
}
// NOTE: When adding a new resource type here, please update the list
// pkg/kubectl/cmd/get.go to reflect the new resource type.
var podColumns = []string{"NAME", "READY", "STATUS", "RESTARTS", "AGE"}
@ -471,10 +505,40 @@ var clusterColumns = []string{"NAME", "STATUS", "VERSION", "AGE"}
var networkPolicyColumns = []string{"NAME", "POD-SELECTOR", "AGE"}
var certificateSigningRequestColumns = []string{"NAME", "AGE", "REQUESTOR", "CONDITION"}
func (h *HumanReadablePrinter) printPod(pod *api.Pod, w io.Writer, options PrintOptions) error {
reason := string(pod.Status.Phase)
// if not printing all pods, skip terminated pods (default)
if !options.ShowAll && (reason == string(api.PodSucceeded) || reason == string(api.PodFailed)) {
h.hiddenObjNum++
return nil
}
if err := printPodBase(pod, w, options); err != nil {
return err
}
return nil
}
func (h *HumanReadablePrinter) printPodList(podList *api.PodList, w io.Writer, options PrintOptions) error {
for _, pod := range podList.Items {
reason := string(pod.Status.Phase)
// if not printing all pods, skip terminated pods (default)
if !options.ShowAll && (reason == string(api.PodSucceeded) || reason == string(api.PodFailed)) {
h.hiddenObjNum++
continue
}
if err := printPodBase(&pod, w, options); err != nil {
return err
}
}
return nil
}
// addDefaultHandlers adds print handlers for default Kubernetes types.
func (h *HumanReadablePrinter) addDefaultHandlers() {
h.Handler(podColumns, printPod)
h.Handler(podColumns, printPodList)
h.Handler(podColumns, h.printPodList)
h.Handler(podColumns, h.printPod)
h.Handler(podTemplateColumns, printPodTemplate)
h.Handler(podTemplateColumns, printPodTemplateList)
h.Handler(replicationControllerColumns, printReplicationController)
@ -617,10 +681,6 @@ func translateTimestamp(timestamp unversioned.Time) string {
return shortHumanDuration(time.Now().Sub(timestamp.Time))
}
func printPod(pod *api.Pod, w io.Writer, options PrintOptions) error {
return printPodBase(pod, w, options)
}
func printPodBase(pod *api.Pod, w io.Writer, options PrintOptions) error {
name := formatResourceName(options.Kind, pod.Name, options.WithKind)
namespace := pod.Namespace
@ -630,10 +690,6 @@ func printPodBase(pod *api.Pod, w io.Writer, options PrintOptions) error {
readyContainers := 0
reason := string(pod.Status.Phase)
// if not printing all pods, skip terminated pods (default)
if !options.ShowAll && (reason == string(api.PodSucceeded) || reason == string(api.PodFailed)) {
return nil
}
if pod.Status.Reason != "" {
reason = pod.Status.Reason
}
@ -731,15 +787,6 @@ func printPodBase(pod *api.Pod, w io.Writer, options PrintOptions) error {
return nil
}
func printPodList(podList *api.PodList, w io.Writer, options PrintOptions) error {
for _, pod := range podList.Items {
if err := printPodBase(&pod, w, options); err != nil {
return err
}
}
return nil
}
func printPodTemplate(pod *api.PodTemplate, w io.Writer, options PrintOptions) error {
name := formatResourceName(options.Kind, pod.Name, options.WithKind)
@ -2183,6 +2230,10 @@ func NewTemplatePrinter(tmpl []byte) (*TemplatePrinter, error) {
}, nil
}
func (p *TemplatePrinter) FinishPrint(w io.Writer, res string) error {
return nil
}
// PrintObj formats the obj with the Go Template.
func (p *TemplatePrinter) PrintObj(obj runtime.Object, w io.Writer) error {
data, err := json.Marshal(obj)
@ -2330,6 +2381,10 @@ func NewJSONPathPrinter(tmpl string) (*JSONPathPrinter, error) {
return &JSONPathPrinter{tmpl, j}, nil
}
func (j *JSONPathPrinter) FinishPrint(w io.Writer, res string) error {
return nil
}
// PrintObj formats the obj with the JSONPath Template.
func (j *JSONPathPrinter) PrintObj(obj runtime.Object, w io.Writer) error {
var queryObj interface{} = obj

View File

@ -1148,14 +1148,18 @@ func TestPrintPod(t *testing.T) {
}
buf := bytes.NewBuffer([]byte{})
printer := HumanReadablePrinter{hiddenObjNum: 0}
for _, test := range tests {
printPod(&test.pod, buf, PrintOptions{false, false, false, false, true, false, false, "", []string{}})
printer.printPod(&test.pod, buf, PrintOptions{false, false, false, false, true, false, false, "", []string{}})
// We ignore time
if !strings.HasPrefix(buf.String(), test.expect) {
t.Fatalf("Expected: %s, got: %s", test.expect, buf.String())
}
buf.Reset()
}
if printer.hiddenObjNum > 0 {
t.Fatalf("Expected hidden pods: 0, got: %d", printer.hiddenObjNum)
}
}
func TestPrintNonTerminatedPod(t *testing.T) {
@ -1241,14 +1245,18 @@ func TestPrintNonTerminatedPod(t *testing.T) {
}
buf := bytes.NewBuffer([]byte{})
printer := HumanReadablePrinter{hiddenObjNum: 0}
for _, test := range tests {
printPod(&test.pod, buf, PrintOptions{false, false, false, false, false, false, false, "", []string{}})
printer.printPod(&test.pod, buf, PrintOptions{false, false, false, false, false, false, false, "", []string{}})
// We ignore time
if !strings.HasPrefix(buf.String(), test.expect) {
t.Fatalf("Expected: %s, got: %s", test.expect, buf.String())
}
buf.Reset()
}
if printer.hiddenObjNum != 2 {
t.Fatalf("Expected hidden pods: 2, got: %d", printer.hiddenObjNum)
}
}
func TestPrintPodWithLabels(t *testing.T) {
@ -1301,14 +1309,18 @@ func TestPrintPodWithLabels(t *testing.T) {
}
buf := bytes.NewBuffer([]byte{})
printer := HumanReadablePrinter{hiddenObjNum: 0}
for _, test := range tests {
printPod(&test.pod, buf, PrintOptions{false, false, false, false, false, false, false, "", test.labelColumns})
printer.printPod(&test.pod, buf, PrintOptions{false, false, false, false, false, false, false, "", test.labelColumns})
// We ignore time
if !strings.HasPrefix(buf.String(), test.startsWith) || !strings.HasSuffix(buf.String(), test.endsWith) {
t.Fatalf("Expected to start with: %s and end with: %s, but got: %s", test.startsWith, test.endsWith, buf.String())
}
buf.Reset()
}
if printer.hiddenObjNum > 0 {
t.Fatalf("Expected hidden pods: 0, got: %d", printer.hiddenObjNum)
}
}
type stringTestList []struct {
@ -1507,12 +1519,17 @@ func TestPrintPodShowLabels(t *testing.T) {
}
buf := bytes.NewBuffer([]byte{})
printer := HumanReadablePrinter{hiddenObjNum: 0}
for _, test := range tests {
printPod(&test.pod, buf, PrintOptions{false, false, false, false, false, test.showLabels, false, "", []string{}})
printer.printPod(&test.pod, buf, PrintOptions{false, false, false, false, false, test.showLabels, false, "", []string{}})
// We ignore time
if !strings.HasPrefix(buf.String(), test.startsWith) || !strings.HasSuffix(buf.String(), test.endsWith) {
t.Fatalf("Expected to start with: %s and end with: %s, but got: %s", test.startsWith, test.endsWith, buf.String())
}
buf.Reset()
}
if printer.hiddenObjNum > 0 {
t.Fatalf("Expected hidden pods: 0, got: %d", printer.hiddenObjNum)
}
}

View File

@ -40,6 +40,10 @@ type SortingPrinter struct {
Decoder runtime.Decoder
}
func (s *SortingPrinter) FinishPrint(w io.Writer, res string) error {
return nil
}
func (s *SortingPrinter) PrintObj(obj runtime.Object, out io.Writer) error {
if !meta.IsListType(obj) {
return s.Delegate.PrintObj(obj, out)