Skip to content

Commit

Permalink
Merge pull request #1004 from hashicorp/f-node-status-self
Browse files Browse the repository at this point in the history
node-status -self command and docs
  • Loading branch information
dadgar committed Mar 29, 2016
2 parents c24dfb0 + 3fbe8a1 commit 63c3070
Show file tree
Hide file tree
Showing 5 changed files with 257 additions and 71 deletions.
1 change: 0 additions & 1 deletion command/alloc_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,6 @@ func (c *AllocStatusCommand) shortTaskStatus(alloc *api.Allocation) {
tasks := make([]string, 0, len(alloc.TaskStates)+1)
tasks = append(tasks, "Name|State|Last Event|Time")
for task := range c.sortedTaskStateIterator(alloc.TaskStates) {
fmt.Println(task)
state := alloc.TaskStates[task]
lastState := state.State
var lastEvent, lastTime string
Expand Down
39 changes: 35 additions & 4 deletions command/node_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ Usage: nomad node-status [options] <node>
If a node ID is passed, information for that specific node will
be displayed. If no node ID's are passed, then a short-hand
list of all nodes will be displayed.
list of all nodes will be displayed. The -self flag is useful to
quickly access the status of the local node.
General Options:
Expand All @@ -37,6 +38,9 @@ Node Status Options:
-verbose
Display full information.
-self
Query the status of the local node.
-allocs
Display a count of running allocations for each node.
`
Expand All @@ -48,13 +52,14 @@ func (c *NodeStatusCommand) Synopsis() string {
}

func (c *NodeStatusCommand) Run(args []string) int {
var short, verbose, list_allocs bool
var short, verbose, list_allocs, self bool

flags := c.Meta.FlagSet("node-status", FlagSetClient)
flags.Usage = func() { c.Ui.Output(c.Help()) }
flags.BoolVar(&short, "short", false, "")
flags.BoolVar(&verbose, "verbose", false, "")
flags.BoolVar(&list_allocs, "allocs", false, "")
flags.BoolVar(&self, "self", false, "")

if err := flags.Parse(args); err != nil {
return 1
Expand All @@ -80,8 +85,32 @@ func (c *NodeStatusCommand) Run(args []string) int {
return 1
}

// If -self flag is set then determine the current node.
nodeID := ""
if self {
info, err := client.Agent().Self()
if err != nil {
c.Ui.Error(fmt.Sprintf("Error querying agent info: %s", err))
return 1
}
var stats map[string]interface{}
stats, _ = info["stats"]
clientStats, ok := stats["client"].(map[string]interface{})
if !ok {
c.Ui.Error("Nomad not running in client mode")
return 1
}

nodeID, ok = clientStats["node_id"].(string)
if !ok {
c.Ui.Error("Failed to determine node ID")
return 1
}

}

// Use list mode if no node name was provided
if len(args) == 0 {
if len(args) == 0 && !self {
// Query the node info
nodes, _, err := client.Nodes().List(nil)
if err != nil {
Expand Down Expand Up @@ -133,7 +162,9 @@ func (c *NodeStatusCommand) Run(args []string) int {
}

// Query the specific node
nodeID := args[0]
if !self {
nodeID = args[0]
}
if len(nodeID) == 1 {
c.Ui.Error(fmt.Sprintf("Identifier must contain at least two characters."))
return 1
Expand Down
51 changes: 51 additions & 0 deletions command/node_status_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,57 @@ func TestNodeStatusCommand_Implements(t *testing.T) {
var _ cli.Command = &NodeStatusCommand{}
}

func TestNodeStatusCommand_Self(t *testing.T) {
// Start in dev mode so we get a node registration
srv, client, url := testServer(t, func(c *testutil.TestServerConfig) {
c.DevMode = true
c.NodeName = "mynode"
})
defer srv.Stop()

ui := new(cli.MockUi)
cmd := &NodeStatusCommand{Meta: Meta{Ui: ui}}

// Wait for a node to appear
var nodeID string
testutil.WaitForResult(func() (bool, error) {
nodes, _, err := client.Nodes().List(nil)
if err != nil {
return false, err
}
if len(nodes) == 0 {
return false, fmt.Errorf("missing node")
}
nodeID = nodes[0].ID
return true, nil
}, func(err error) {
t.Fatalf("err: %s", err)
})

// Query self node
if code := cmd.Run([]string{"-address=" + url, "-self"}); code != 0 {
t.Fatalf("expected exit 0, got: %d", code)
}
out := ui.OutputWriter.String()
if !strings.Contains(out, "mynode") {
t.Fatalf("expect to find mynode, got: %s", out)
}
if strings.Contains(out, "Allocations") {
t.Fatalf("should not dump allocations")
}
ui.OutputWriter.Reset()

// Request full id output
if code := cmd.Run([]string{"-address=" + url, "-self", "-verbose"}); code != 0 {
t.Fatalf("expected exit 0, got: %d", code)
}
out = ui.OutputWriter.String()
if !strings.Contains(out, nodeID) {
t.Fatalf("expected full node id %q, got: %s", nodeID, out)
}
ui.OutputWriter.Reset()
}

func TestNodeStatusCommand_Run(t *testing.T) {
// Start in dev mode so we get a node registration
srv, client, url := testServer(t, func(c *testutil.TestServerConfig) {
Expand Down
118 changes: 72 additions & 46 deletions website/source/docs/commands/alloc-status.html.md.erb
Original file line number Diff line number Diff line change
Expand Up @@ -37,70 +37,96 @@ allocations and information will be displayed.
Short status of an alloc:

```
$ nomad alloc-status --short a7365fe4
ID = a7365fe4
EvalID = 44c2d9ed
Name = example.cache[0]
NodeID = e55859b1
JobID = example
ClientStatus = running
NodesEvaluated = 1
NodesFiltered = 0
NodesExhausted = 0
AllocationTime = 911.026µs
CoalescedFailures = 0
redis
web
$ nomad alloc-status --short 13901f26
ID = 13901f26
Eval ID = c3c9a1db
Name = example.cache[0]
Node ID = 1f029d38
Job ID = example
Client Status = running

==> Tasks
Name State LastEvent Time
redis running Started 02:29:40 11/17/15
web running Started 02:30:41 11/17/15

==> Status
Allocation "a7365fe4" status "running" (0/1 nodes filtered)
* Score "e55859b1.binpack" = 10.334026
Name State Last Event Time
redis running Started 29/03/16 03:04:53 UTC
web running Started 29/03/16 03:04:53 UTC
```

Full status of an alloc, which shows one of the tasks dying and then being restarted:

```
$ nomad alloc-status a7365fe4
ID = a7365fe4
EvalID = 44c2d9ed
Name = example.cache[0]
NodeID = e55859b1
JobID = example
ClientStatus = running
NodesEvaluated = 1
NodesFiltered = 0
NodesExhausted = 0
AllocationTime = 911.026µs
CoalescedFailures = 0
ID = a7365fe4
Eval ID = c3c9a1db
Name = example.cache[0]
Node ID = 1f029d38
Job ID = example
Client Status = running

==> Task Resources
Task: "redis"
CPU Memory MB Disk MB IOPS Addresses
500 256 300 0 db: 127.0.0.1:46321

Task: "web"
CPU Memory MB Disk MB IOPS Addresses
500 256 300 0 db: 127.0.0.1:38537

==> Task "redis" is "running"
Recent Events:
Time Type Description
02:29:40 11/17/15 Started <none>
Time Type Description
29/03/16 03:04:53 UTC Started Task started by client
29/03/16 03:04:51 UTC Received Task received by client

==> Task "web" is "running"
==> Task "web" is "pending"
Recent Events:
Time Type Description
02:30:41 11/17/15 Started <none>
02:30:02 11/17/15 Terminated Exit Code: 137, Exit Message: "Docker container exited with non-zero exit code: 137"
02:29:40 11/17/15 Started <none>
Time Type Description
29/03/16 03:07:18 UTC Restarting Task restarting in 18.580059474s
29/03/16 03:07:18 UTC Terminated Exit Code: 137, Exit Message: "Docker container exited with non-zero exit code: 137"
29/03/16 03:04:53 UTC Started Task started by client
29/03/16 03:04:51 UTC Received Task received by client
```

==> Status
Allocation "a7365fe4" status "running" (0/1 nodes filtered)
* Score "e55859b1.binpack" = 10.334026
Verbose status can also be accessed:

```
$ nomad alloc-status a7365fe4
ID = a7365fe4-cb28-a6e9-f3d4-f99e49c89776
Eval ID = c3c9a1db-dbeb-8afa-0a83-4f1b8b5a03f5
Name = example.cache[0]
Node ID = 1f029d38-8d4b-a552-261f-e457b60f9b4b
Job ID = example
Client Status = running
Evaluated Nodes = 1
Filtered Nodes = 0
Exhausted Nodes = 0
Allocation Time = 1.085001ms
Failures = 0

==> Task Resources
Task: "redis"
Task: "web"
CPU Memory MB Disk MB IOPS Addresses
500 256 300 0 db: 127.0.0.1:52004
500 256 300 0 db: 127.0.0.1:38537

Task: "web"
Task: "redis"
CPU Memory MB Disk MB IOPS Addresses
500 256 300 0 http: 127.0.0.1:52007
500 256 300 0 db: 127.0.0.1:46321

==> Task "redis" is "running"
Recent Events:
Time Type Description
29/03/16 03:04:53 UTC Started Task started by client
29/03/16 03:04:51 UTC Received Task received by client

==> Task "web" is "running"
Recent Events:
Time Type Description
29/03/16 03:07:38 UTC Started Task started by client
29/03/16 03:07:18 UTC Restarting Task restarting in 18.580059474s
29/03/16 03:07:18 UTC Terminated Exit Code: 137, Exit Message: "Docker container exited with non-zero exit code: 137"
29/03/16 03:04:53 UTC Started Task started by client
29/03/16 03:04:51 UTC Received Task received by client

==> Status
Allocation "13901f26-cb28-a6e9-f3d4-f99e49c89776" status "running" (0/1 nodes filtered)
* Score "1f029d38-8d4b-a552-261f-e457b60f9b4b.binpack" = 10.334026
```
Loading

0 comments on commit 63c3070

Please sign in to comment.