From 8b8a0ecb730d807322fcb6f2fe4dff57e44ad286 Mon Sep 17 00:00:00 2001 From: Ryan Uber Date: Fri, 18 Sep 2015 12:06:51 -0700 Subject: [PATCH] command: start alloc-status command --- api/allocations.go | 2 +- command/alloc_status.go | 105 ++++++++++++++++++++++++++++++++++++++++ commands.go | 6 +++ 3 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 command/alloc_status.go diff --git a/api/allocations.go b/api/allocations.go index fe362a779..829c1030f 100644 --- a/api/allocations.go +++ b/api/allocations.go @@ -64,7 +64,7 @@ type AllocationMetric struct { ConstraintFiltered map[string]int NodesExhausted int ClassExhausted map[string]int - DimensionExhaused map[string]int + DimensionExhausted map[string]int Scores map[string]float64 AllocationTime time.Duration CoalescedFailures int diff --git a/command/alloc_status.go b/command/alloc_status.go new file mode 100644 index 000000000..4b6c127b3 --- /dev/null +++ b/command/alloc_status.go @@ -0,0 +1,105 @@ +package command + +import ( + "fmt" + "strings" +) + +type AllocStatusCommand struct { + Meta +} + +func (c *AllocStatusCommand) Help() string { + helpText := ` +Usage: nomad alloc-status [options] + + Display status and diagnostic information about an allocation. + +General Options: + + ` + generalOptionsUsage() + return strings.TrimSpace(helpText) +} + +func (c *AllocStatusCommand) Synopsis() string { + return "Display allocation status information and metrics" +} + +func (c *AllocStatusCommand) Run(args []string) int { + flags := c.Meta.FlagSet("alloc-status", FlagSetClient) + flags.Usage = func() { c.Ui.Output(c.Help()) } + if err := flags.Parse(args); err != nil { + return 1 + } + + // Check that we either got no jobs or exactly one. + args = flags.Args() + if len(args) != 1 { + c.Ui.Error(c.Help()) + return 1 + } + allocID := args[0] + + // Get the HTTP client + client, err := c.Meta.Client() + if err != nil { + c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err)) + return 1 + } + + // Query the allocation + alloc, _, err := client.Allocations().Info(allocID, nil) + if err != nil { + c.Ui.Error(fmt.Sprintf("Error querying allocation: %s", err)) + return 1 + } + + // Format the allocation + basic := []string{ + fmt.Sprintf("ID|%s", alloc.ID), + fmt.Sprintf("EvalID|%s", alloc.EvalID), + fmt.Sprintf("Name|%s", alloc.Name), + fmt.Sprintf("NodeID|%s", alloc.NodeID), + fmt.Sprintf("JobID|%s", alloc.JobID), + fmt.Sprintf("TaskGroup|%s", alloc.TaskGroup), + fmt.Sprintf("DesiredStatus|%s", alloc.DesiredStatus), + fmt.Sprintf("DesiredDescription|%s", alloc.DesiredDescription), + 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), + } + + // Format exhaustion info + var exInfo []string + if ne := alloc.Metrics.NodesExhausted; ne > 0 { + exInfo = append(exInfo, fmt.Sprintf("Node resources (exhausted %d)", ne)) + } + for class, num := range alloc.Metrics.ClassExhausted { + exInfo = append(exInfo, fmt.Sprintf("Class %q (exhausted %d)", class, num)) + } + for dim, num := range alloc.Metrics.DimensionExhausted { + exInfo = append(exInfo, fmt.Sprintf("Dimension %q (exhausted %d)", dim, num)) + } + + // Format the filter info + var filterInfo []string + for class, num := range alloc.Metrics.ClassFiltered { + filterInfo = append(filterInfo, fmt.Sprintf("Class %q (filtered %d)", class, num)) + } + for cs, num := range alloc.Metrics.ConstraintFiltered { + filterInfo = append(filterInfo, fmt.Sprintf("Constraint %q (filtered %d)", cs, num)) + } + + // Dump the output + c.Ui.Output(formatKV(basic)) + if len(exInfo) > 0 { + c.Ui.Output("\n==> Nodes Exhausted") + c.Ui.Output(strings.Join(exInfo, "\n")) + } + if len(filterInfo) > 0 { + c.Ui.Output("\n==> Filters Applied") + c.Ui.Output(strings.Join(filterInfo, "\n")) + } + return 0 +} diff --git a/commands.go b/commands.go index 921606307..71fab0f78 100644 --- a/commands.go +++ b/commands.go @@ -24,6 +24,12 @@ func Commands(metaPtr *command.Meta) map[string]cli.CommandFactory { } return map[string]cli.CommandFactory{ + "alloc-status": func() (cli.Command, error) { + return &command.AllocStatusCommand{ + Meta: meta, + }, nil + }, + "agent": func() (cli.Command, error) { return &agent.Command{ Revision: GitCommit,