Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add -self flag to node-drain #1068

Merged
merged 1 commit into from
Apr 12, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions command/helpers.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package command

import (
"fmt"
"time"

"github.com/hashicorp/nomad/api"
"github.com/ryanuber/columnize"
)

Expand Down Expand Up @@ -45,3 +47,25 @@ func limit(s string, length int) string {
func formatTime(t time.Time) string {
return t.Format("02/01/06 15:04:05 MST")
}

// getLocalNodeID returns the node ID of the local Nomad Client and an error if
// it couldn't be determined or the Agent is not running in Client mode.
func getLocalNodeID(client *api.Client) (string, error) {
info, err := client.Agent().Self()
if err != nil {
return "", fmt.Errorf("Error querying agent info: %s", err)
}
var stats map[string]interface{}
stats, _ = info["stats"]
clientStats, ok := stats["client"].(map[string]interface{})
if !ok {
return "", fmt.Errorf("Nomad not running in client mode")
}

nodeID, ok := clientStats["node_id"].(string)
if !ok {
return "", fmt.Errorf("Failed to determine node ID")
}

return nodeID, nil
}
18 changes: 18 additions & 0 deletions command/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package command

import (
"testing"

"github.com/mitchellh/cli"
)

func TestHelpers_FormatKV(t *testing.T) {
Expand All @@ -27,3 +29,19 @@ func TestHelpers_FormatList(t *testing.T) {
t.Fatalf("expect: %s, got: %s", expect, out)
}
}

func TestHelpers_NodeID(t *testing.T) {
srv, _, _ := testServer(t, nil)
defer srv.Stop()

meta := Meta{Ui: new(cli.MockUi)}
client, err := meta.Client()
if err != nil {
t.FailNow()
}

// This is because there is no client
if _, err := getLocalNodeID(client); err == nil {
t.Fatalf("getLocalNodeID() should fail")
}
}
23 changes: 19 additions & 4 deletions command/node_drain.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Usage: nomad node-drain [options] <node>

Toggles node draining on a specified node. It is required
that either -enable or -disable is specified, but not both.
The -self flag is useful to drain the local node.

General Options:

Expand All @@ -28,6 +29,9 @@ Node Drain Options:
-enable
Enable draining for the specified node.

-self
Query the status of the local node.

-yes
Automatic yes to prompts.
`
Expand All @@ -39,12 +43,13 @@ func (c *NodeDrainCommand) Synopsis() string {
}

func (c *NodeDrainCommand) Run(args []string) int {
var enable, disable, autoYes bool
var enable, disable, self, autoYes bool

flags := c.Meta.FlagSet("node-drain", FlagSetClient)
flags.Usage = func() { c.Ui.Output(c.Help()) }
flags.BoolVar(&enable, "enable", false, "Enable drain mode")
flags.BoolVar(&disable, "disable", false, "Disable drain mode")
flags.BoolVar(&self, "self", false, "")
flags.BoolVar(&autoYes, "yes", false, "Automatic yes to prompts.")

if err := flags.Parse(args); err != nil {
Expand All @@ -59,11 +64,10 @@ func (c *NodeDrainCommand) Run(args []string) int {

// Check that we got a node ID
args = flags.Args()
if len(args) != 1 {
if l := len(args); self && l != 0 || !self && l != 1 {
c.Ui.Error(c.Help())
return 1
}
nodeID := args[0]

// Get the HTTP client
client, err := c.Meta.Client()
Expand All @@ -72,6 +76,18 @@ func (c *NodeDrainCommand) Run(args []string) int {
return 1
}

// If -self flag is set then determine the current node.
nodeID := ""
if !self {
nodeID = args[0]
} else {
var err error
if nodeID, err = getLocalNodeID(client); err != nil {
c.Ui.Error(err.Error())
return 1
}
}

// Check if node exists
if len(nodeID) == 1 {
c.Ui.Error(fmt.Sprintf("Identifier must contain at least two characters."))
Expand All @@ -83,7 +99,6 @@ func (c *NodeDrainCommand) Run(args []string) int {
nodeID = nodeID[:len(nodeID)-1]
}

// Exact lookup failed, try with prefix based search
nodes, _, err := client.Nodes().PrefixList(nodeID)
if err != nil {
c.Ui.Error(fmt.Sprintf("Error toggling drain mode: %s", err))
Expand Down
32 changes: 7 additions & 25 deletions command/node_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,30 +85,6 @@ 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 && !self {
// Query the node info
Expand Down Expand Up @@ -162,8 +138,15 @@ func (c *NodeStatusCommand) Run(args []string) int {
}

// Query the specific node
nodeID := ""
if !self {
nodeID = args[0]
} else {
var err error
if nodeID, err = getLocalNodeID(client); err != nil {
c.Ui.Error(err.Error())
return 1
}
}
if len(nodeID) == 1 {
c.Ui.Error(fmt.Sprintf("Identifier must contain at least two characters."))
Expand All @@ -175,7 +158,6 @@ func (c *NodeStatusCommand) Run(args []string) int {
nodeID = nodeID[:len(nodeID)-1]
}

// Exact lookup failed, try with prefix based search
nodes, _, err := client.Nodes().PrefixList(nodeID)
if err != nil {
c.Ui.Error(fmt.Sprintf("Error querying node info: %s", err))
Expand Down
19 changes: 14 additions & 5 deletions website/source/docs/commands/node-drain.html.md.erb
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ nicely by providing the current drain status of a given node.
nomad node-drain [options] <node>
```

A node ID or prefix must be provided. If there is an exact match, the
drain mode will be adjusted for that node. Otherwise, a list of matching
nodes and information will be displayed.
A `-self` flag can be used to drain the local node. If this is not supplied, a
node ID or prefix must be provided. If there is an exact match, the drain mode
will be adjusted for that node. Otherwise, a list of matching nodes and
information will be displayed.

It is also required to pass one of `-enable` or `-disable`, depending on which
operation is desired.
Expand All @@ -36,11 +37,19 @@ operation is desired.

* `-enable`: Enable node drain mode.
* `-disable`: Disable node drain mode.
* `-self`: Drain the local node.
* `-yes`: Automtic yes to prompts.

## Examples

Enable drain mode on node1:
Enable drain mode on node with ID prefix "4d2ba53b":

```
$ nomad node-drain -enable node1
$ nomad node-drain -enable 4d2ba53b
```

Enable drain mode on the local node:

```
$ nomad node-drain -enable -self
```