mirror of
https://github.com/kemko/nomad.git
synced 2026-01-05 09:55:44 +03:00
Display task information
This commit is contained in:
@@ -2,7 +2,11 @@ package command
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/nomad/api"
|
||||
)
|
||||
|
||||
type AllocStatusCommand struct {
|
||||
@@ -13,14 +17,21 @@ func (c *AllocStatusCommand) Help() string {
|
||||
helpText := `
|
||||
Usage: nomad alloc-status [options] <allocation>
|
||||
|
||||
Display information about existing allocations. This command can
|
||||
be used to inspect the current status of all allocation,
|
||||
including its running status, metadata, and verbose failure
|
||||
messages reported by internal subsystems.
|
||||
Display information about existing allocations and its tasks. This command can
|
||||
be used to inspect the current status of all allocation, including its running
|
||||
status, metadata, and verbose failure messages reported by internal
|
||||
subsystems.
|
||||
|
||||
General Options:
|
||||
|
||||
` + generalOptionsUsage()
|
||||
` + generalOptionsUsage() + `
|
||||
|
||||
Alloc Status Options:
|
||||
|
||||
-short
|
||||
Display short output, showing only the most recent task event.
|
||||
`
|
||||
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
||||
@@ -29,15 +40,19 @@ func (c *AllocStatusCommand) Synopsis() string {
|
||||
}
|
||||
|
||||
func (c *AllocStatusCommand) Run(args []string) int {
|
||||
var short bool
|
||||
|
||||
flags := c.Meta.FlagSet("alloc-status", FlagSetClient)
|
||||
flags.Usage = func() { c.Ui.Output(c.Help()) }
|
||||
flags.BoolVar(&short, "short", false, "")
|
||||
|
||||
if err := flags.Parse(args); err != nil {
|
||||
return 1
|
||||
}
|
||||
|
||||
// Check that we got exactly one allocation ID
|
||||
args = flags.Args()
|
||||
if len(args) != 1 {
|
||||
if len(args) == 0 || len(args) > 2 {
|
||||
c.Ui.Error(c.Help())
|
||||
return 1
|
||||
}
|
||||
@@ -65,7 +80,6 @@ func (c *AllocStatusCommand) Run(args []string) int {
|
||||
fmt.Sprintf("NodeID|%s", alloc.NodeID),
|
||||
fmt.Sprintf("JobID|%s", alloc.JobID),
|
||||
fmt.Sprintf("ClientStatus|%s", alloc.ClientStatus),
|
||||
fmt.Sprintf("ClientDescription|%s", alloc.ClientDescription),
|
||||
fmt.Sprintf("NodesEvaluated|%d", alloc.Metrics.NodesEvaluated),
|
||||
fmt.Sprintf("NodesFiltered|%d", alloc.Metrics.NodesFiltered),
|
||||
fmt.Sprintf("NodesExhausted|%d", alloc.Metrics.NodesExhausted),
|
||||
@@ -74,9 +88,108 @@ func (c *AllocStatusCommand) Run(args []string) int {
|
||||
}
|
||||
c.Ui.Output(formatKV(basic))
|
||||
|
||||
// Print the state of each task.
|
||||
if short {
|
||||
c.shortTaskStatus(alloc)
|
||||
} else {
|
||||
c.taskStatus(alloc)
|
||||
}
|
||||
|
||||
// Format the detailed status
|
||||
c.Ui.Output("\n==> Status")
|
||||
dumpAllocStatus(c.Ui, alloc)
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
// shortTaskStatus prints out the current state of each task.
|
||||
func (c *AllocStatusCommand) shortTaskStatus(alloc *api.Allocation) {
|
||||
tasks := make([]string, 0, len(alloc.TaskStates)+1)
|
||||
tasks = append(tasks, "Name|State|LastEvent|Time")
|
||||
for task := range c.sortedTaskStateIterator(alloc.TaskStates) {
|
||||
fmt.Println(task)
|
||||
state := alloc.TaskStates[task]
|
||||
lastState := state.State
|
||||
var lastEvent, lastTime string
|
||||
|
||||
l := len(state.Events)
|
||||
if l != 0 {
|
||||
last := state.Events[l-1]
|
||||
lastEvent = last.Type
|
||||
lastTime = c.formatUnixNonoTime(last.Time)
|
||||
}
|
||||
|
||||
tasks = append(tasks, fmt.Sprintf("%s|%s|%s|%s",
|
||||
task, lastState, lastEvent, lastTime))
|
||||
}
|
||||
|
||||
c.Ui.Output("\n==> Tasks")
|
||||
c.Ui.Output(formatList(tasks))
|
||||
}
|
||||
|
||||
// taskStatus prints out the most recent events for each task.
|
||||
func (c *AllocStatusCommand) taskStatus(alloc *api.Allocation) {
|
||||
for task := range c.sortedTaskStateIterator(alloc.TaskStates) {
|
||||
state := alloc.TaskStates[task]
|
||||
events := make([]string, len(state.Events)+1)
|
||||
events[0] = "Time|Type|Description"
|
||||
|
||||
size := len(state.Events)
|
||||
for i, event := range state.Events {
|
||||
formatedTime := c.formatUnixNonoTime(event.Time)
|
||||
|
||||
// Build up the description based on the event type.
|
||||
var desc string
|
||||
switch event.Type {
|
||||
case api.TaskDriverFailure:
|
||||
desc = event.DriverError
|
||||
case api.TaskKilled:
|
||||
desc = event.KillError
|
||||
case api.TaskTerminated:
|
||||
var parts []string
|
||||
parts = append(parts, fmt.Sprintf("Exit Code: %d", event.ExitCode))
|
||||
|
||||
if event.Signal != 0 {
|
||||
parts = append(parts, fmt.Sprintf("Signal: %d", event.Signal))
|
||||
}
|
||||
|
||||
if event.Message != "" {
|
||||
parts = append(parts, fmt.Sprintf("Exit Message: %q", event.Message))
|
||||
}
|
||||
desc = strings.Join(parts, ", ")
|
||||
}
|
||||
|
||||
// Reverse order so we are sorted by time
|
||||
events[size-i] = fmt.Sprintf("%s|%s|%s", formatedTime, event.Type, desc)
|
||||
}
|
||||
|
||||
c.Ui.Output(fmt.Sprintf("\n==> Task %q is %q\nRecent Events:", task, state.State))
|
||||
c.Ui.Output(formatList(events))
|
||||
}
|
||||
}
|
||||
|
||||
// formatUnixNonoTime is a helper for formating time for output.
|
||||
func (c *AllocStatusCommand) formatUnixNonoTime(nano int64) string {
|
||||
t := time.Unix(0, nano)
|
||||
return t.Format("15:04:05 01/02/06")
|
||||
}
|
||||
|
||||
// sortedTaskStateIterator is a helper that takes the task state map and returns a
|
||||
// channel that returns the keys in a sorted order.
|
||||
func (c *AllocStatusCommand) sortedTaskStateIterator(m map[string]*api.TaskState) <-chan string {
|
||||
output := make(chan string, len(m))
|
||||
keys := make([]string, len(m))
|
||||
i := 0
|
||||
for k, _ := range m {
|
||||
keys[i] = k
|
||||
i++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
for _, key := range keys {
|
||||
output <- key
|
||||
}
|
||||
|
||||
close(output)
|
||||
return output
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user