Simplify describe events table

The describe table for events is not easy to read and violates other
output guidelines. Change to use spaces (we don't use tabs in formal
output for tables). Remove columns that are not normally needed or
available on events.

Example for pods:

```
...
QoS Class:       BestEffort
Node-Selectors:  role=app
Tolerations:     <none>
Events:
  Type     Reason      Age                 From                         Message
  ----     ------      ----                ----                         -------
  Normal   Pulling     1h (x51 over 5h)    kubelet, origin-ci-ig-n-gj0x pulling image "registry.svc.ci.openshift.org/experiment/commenter:latest"
  Normal   BackOff     8m (x1274 over 5h)  kubelet, origin-ci-ig-n-gj0x Back-off pulling image "registry.svc.ci.openshift.org/experiment/commenter:latest"
  Warning  FailedSync  3m (x1359 over 5h)  kubelet, origin-ci-ig-n-gj0x Error syncing pod
```

Puts the type first (separate important from not), then reason (which is
the most impactful scanning field). Collapses first seen, last seen, and
times into a single field, since most of the time you care about the
last time the event happened, not the first time.
pull/6/head
Clayton Coleman 2017-08-31 19:08:14 -04:00
parent 6597f1ed4a
commit 824f04f86a
No known key found for this signature in database
GPG Key ID: 3D16906B4F1C5CB3
3 changed files with 43 additions and 26 deletions

View File

@ -335,7 +335,7 @@ func applyHistory(ds *extensionsv1beta1.DaemonSet, history *appsv1beta1.Controll
func tabbedString(f func(io.Writer) error) (string, error) { func tabbedString(f func(io.Writer) error) (string, error) {
out := new(tabwriter.Writer) out := new(tabwriter.Writer)
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
out.Init(buf, 0, 8, 1, '\t', 0) out.Init(buf, 0, 8, 2, ' ', 0)
err := f(out) err := f(out)
if err != nil { if err != nil {

View File

@ -89,6 +89,8 @@ type PrefixWriter interface {
Write(level int, format string, a ...interface{}) Write(level int, format string, a ...interface{})
// WriteLine writes an entire line with no indentation level. // WriteLine writes an entire line with no indentation level.
WriteLine(a ...interface{}) WriteLine(a ...interface{})
// Flush forces indendation to be reset.
Flush()
} }
// prefixWriter implements PrefixWriter // prefixWriter implements PrefixWriter
@ -116,6 +118,12 @@ func (pw *prefixWriter) WriteLine(a ...interface{}) {
fmt.Fprintln(pw.out, a...) fmt.Fprintln(pw.out, a...)
} }
func (pw *prefixWriter) Flush() {
if f, ok := pw.out.(flusher); ok {
f.Flush()
}
}
func describerMap(c clientset.Interface) map[schema.GroupKind]printers.Describer { func describerMap(c clientset.Interface) map[schema.GroupKind]printers.Describer {
m := map[schema.GroupKind]printers.Describer{ m := map[schema.GroupKind]printers.Describer{
api.Kind("Pod"): &PodDescriber{c}, api.Kind("Pod"): &PodDescriber{c},
@ -2853,19 +2861,24 @@ func DescribeEvents(el *api.EventList, w PrefixWriter) {
w.Write(LEVEL_0, "Events:\t<none>\n") w.Write(LEVEL_0, "Events:\t<none>\n")
return return
} }
w.Flush()
sort.Sort(events.SortableEvents(el.Items)) sort.Sort(events.SortableEvents(el.Items))
w.Write(LEVEL_0, "Events:\n FirstSeen\tLastSeen\tCount\tFrom\tSubObjectPath\tType\tReason\tMessage\n") w.Write(LEVEL_0, "Events:\n Type\tReason\tAge\tFrom\tMessage\n")
w.Write(LEVEL_1, "---------\t--------\t-----\t----\t-------------\t--------\t------\t-------\n") w.Write(LEVEL_1, "----\t------\t----\t----\t-------\n")
for _, e := range el.Items { for _, e := range el.Items {
w.Write(LEVEL_1, "%s\t%s\t%d\t%v\t%v\t%v\t%v\t%v\n", var interval string
translateTimestamp(e.FirstTimestamp), if e.Count > 1 {
translateTimestamp(e.LastTimestamp), interval = fmt.Sprintf("%s (x%d over %s)", translateTimestamp(e.LastTimestamp), e.Count, translateTimestamp(e.FirstTimestamp))
e.Count, } else {
formatEventSource(e.Source), interval = translateTimestamp(e.FirstTimestamp)
e.InvolvedObject.FieldPath, }
w.Write(LEVEL_1, "%v\t%v\t%s\t%v\t%v\n",
e.Type, e.Type,
e.Reason, e.Reason,
e.Message) interval,
formatEventSource(e.Source),
strings.TrimSpace(e.Message),
)
} }
} }
@ -3591,10 +3604,14 @@ func printTolerationsMultilineWithIndent(w PrefixWriter, initialIndent, title, i
} }
} }
type flusher interface {
Flush()
}
func tabbedString(f func(io.Writer) error) (string, error) { func tabbedString(f func(io.Writer) error) (string, error) {
out := new(tabwriter.Writer) out := new(tabwriter.Writer)
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
out.Init(buf, 0, 8, 1, '\t', 0) out.Init(buf, 0, 8, 2, ' ', 0)
err := f(out) err := f(out)
if err != nil { if err != nil {

View File

@ -1499,22 +1499,22 @@ URL: http://localhost
func TestDescribePodSecurityPolicy(t *testing.T) { func TestDescribePodSecurityPolicy(t *testing.T) {
expected := []string{ expected := []string{
"Name:\t*mypsp", "Name:\\s*mypsp",
"Allow Privileged:\t*false", "Allow Privileged:\\s*false",
"Default Add Capabilities:\t*<none>", "Default Add Capabilities:\\s*<none>",
"Required Drop Capabilities:\t*<none>", "Required Drop Capabilities:\\s*<none>",
"Allowed Capabilities:\t*<none>", "Allowed Capabilities:\\s*<none>",
"Allowed Volume Types:\t*<none>", "Allowed Volume Types:\\s*<none>",
"Allow Host Network:\t*false", "Allow Host Network:\\s*false",
"Allow Host Ports:\t*<none>", "Allow Host Ports:\\s*<none>",
"Allow Host PID:\t*false", "Allow Host PID:\\s*false",
"Allow Host IPC:\t*false", "Allow Host IPC:\\s*false",
"Read Only Root Filesystem:\t*false", "Read Only Root Filesystem:\\s*false",
"SELinux Context Strategy: RunAsAny", "SELinux Context Strategy: RunAsAny",
"User:\t*<none>", "User:\\s*<none>",
"Role:\t*<none>", "Role:\\s*<none>",
"Type:\t*<none>", "Type:\\s*<none>",
"Level:\t*<none>", "Level:\\s*<none>",
"Run As User Strategy: RunAsAny", "Run As User Strategy: RunAsAny",
"FSGroup Strategy: RunAsAny", "FSGroup Strategy: RunAsAny",
"Supplemental Groups Strategy: RunAsAny", "Supplemental Groups Strategy: RunAsAny",