Defaults second node to agent if not given. Removes -short option and tweaks output formatting.

This commit is contained in:
James Phillips 2015-10-16 12:45:25 -07:00
parent a51e170eef
commit c48e3e1179
3 changed files with 58 additions and 48 deletions

View File

@ -18,27 +18,27 @@ type RttCommand struct {
func (c *RttCommand) Help() string { func (c *RttCommand) Help() string {
helpText := ` helpText := `
Usage: consul rtt [options] node1 node2 Usage: consul rtt [options] node1 [node2]
Estimates the round trip time between two nodes using Consul's network Estimates the round trip time between two nodes using Consul's network
coordinate model of the cluster. coordinate model of the cluster.
At least one node name is required. If the second node name isn't given, it
is set to the agent's node name. Note that these are node names as known to
Consul as "consul members" would show, not IP addresses.
By default, the two nodes are assumed to be nodes in the local datacenter By default, the two nodes are assumed to be nodes in the local datacenter
and the LAN coordinates are used. If the -wan option is given, then the WAN and the LAN coordinates are used. If the -wan option is given, then the WAN
coordinates are used, and the node names must be prefixed by the datacenter coordinates are used, and the node names must be suffixed by a period and
and a period (eg. "dc1.sever"). the datacenter (eg. "myserver.dc1").
It is not possible to measure between LAN coordinates and WAN coordinates It is not possible to measure between LAN coordinates and WAN coordinates
because they are maintained by independent Serf gossip pools, so they are because they are maintained by independent Serf gossip pools, so they are
not compatible. not compatible.
The two node names are required. Note that these are node names as known to
Consul as "consul members" would show, not IP addresses.
Options: Options:
-wan Use WAN coordinates instead of LAN coordinates. -wan Use WAN coordinates instead of LAN coordinates.
-short Print just the round trip time (eg. "1.234 ms").
-http-addr=127.0.0.1:8500 HTTP address of the Consul agent. -http-addr=127.0.0.1:8500 HTTP address of the Consul agent.
` `
return strings.TrimSpace(helpText) return strings.TrimSpace(helpText)
@ -46,13 +46,11 @@ Options:
func (c *RttCommand) Run(args []string) int { func (c *RttCommand) Run(args []string) int {
var wan bool var wan bool
var short bool
cmdFlags := flag.NewFlagSet("rtt", flag.ContinueOnError) cmdFlags := flag.NewFlagSet("rtt", flag.ContinueOnError)
cmdFlags.Usage = func() { c.Ui.Output(c.Help()) } cmdFlags.Usage = func() { c.Ui.Output(c.Help()) }
cmdFlags.BoolVar(&wan, "wan", false, "wan") cmdFlags.BoolVar(&wan, "wan", false, "wan")
cmdFlags.BoolVar(&short, "short", false, "short")
httpAddr := HTTPAddrFlag(cmdFlags) httpAddr := HTTPAddrFlag(cmdFlags)
if err := cmdFlags.Parse(args); err != nil { if err := cmdFlags.Parse(args); err != nil {
return 1 return 1
@ -60,8 +58,8 @@ func (c *RttCommand) Run(args []string) int {
// They must provide a pair of nodes. // They must provide a pair of nodes.
nodes := cmdFlags.Args() nodes := cmdFlags.Args()
if len(nodes) != 2 { if len(nodes) < 1 || len(nodes) > 2 {
c.Ui.Error("Two node names must be specified") c.Ui.Error("One or two node names must be specified")
c.Ui.Error("") c.Ui.Error("")
c.Ui.Error(c.Help()) c.Ui.Error(c.Help())
return 1 return 1
@ -82,6 +80,19 @@ func (c *RttCommand) Run(args []string) int {
if wan { if wan {
source = "WAN" source = "WAN"
// Default the second node to the agent if none was given.
if len(nodes) < 2 {
agent := client.Agent()
self, err := agent.Self()
if err != nil {
c.Ui.Error(fmt.Sprintf("Unable to look up agent info: %s", err))
return 1
}
node, dc := self["Config"]["NodeName"], self["Config"]["Datacenter"]
nodes = append(nodes, fmt.Sprintf("%s.%s", node, dc))
}
// Parse the input nodes. // Parse the input nodes.
parts1 := strings.Split(nodes[0], ".") parts1 := strings.Split(nodes[0], ".")
parts2 := strings.Split(nodes[1], ".") parts2 := strings.Split(nodes[1], ".")
@ -89,8 +100,8 @@ func (c *RttCommand) Run(args []string) int {
c.Ui.Error("Node names must be specified as <datacenter>.<node name> with -wan") c.Ui.Error("Node names must be specified as <datacenter>.<node name> with -wan")
return 1 return 1
} }
dc1, node1 := parts1[0], parts1[1] node1, dc1 := parts1[0], parts1[1]
dc2, node2 := parts2[0], parts2[1] node2, dc2 := parts2[0], parts2[1]
// Pull all the WAN coordinates. // Pull all the WAN coordinates.
dcs, err := coordClient.Datacenters() dcs, err := coordClient.Datacenters()
@ -117,6 +128,17 @@ func (c *RttCommand) Run(args []string) int {
} else { } else {
source = "LAN" source = "LAN"
// Default the second node to the agent if none was given.
if len(nodes) < 2 {
agent := client.Agent()
node, err := agent.NodeName()
if err != nil {
c.Ui.Error(fmt.Sprintf("Unable to look up agent info: %s", err))
return 1
}
nodes = append(nodes, node)
}
// Pull all the LAN coordinates. // Pull all the LAN coordinates.
entries, _, err := coordClient.Nodes(nil) entries, _, err := coordClient.Nodes(nil)
if err != nil { if err != nil {
@ -153,11 +175,7 @@ SHOW_RTT:
// Report the round trip time. // Report the round trip time.
dist := fmt.Sprintf("%.3f ms", coord1.DistanceTo(coord2).Seconds()*1000.0) dist := fmt.Sprintf("%.3f ms", coord1.DistanceTo(coord2).Seconds()*1000.0)
if short { c.Ui.Output(fmt.Sprintf("Estimated %s <-> %s rtt: %s (using %s coordinates)", nodes[0], nodes[1], dist, source))
c.Ui.Output(dist)
} else {
c.Ui.Output(fmt.Sprintf("Estimated %s <-> %s rtt=%s (using %s coordinates)", nodes[0], nodes[1], dist, source))
}
return 0 return 0
} }

View File

@ -24,10 +24,6 @@ func TestRttCommand_Run_BadArgs(t *testing.T) {
t.Fatalf("expected return code 1, got %d", code) t.Fatalf("expected return code 1, got %d", code)
} }
if code := c.Run([]string{"node1"}); code != 1 {
t.Fatalf("expected return code 1, got %d", code)
}
if code := c.Run([]string{"node1", "node2", "node3"}); code != 1 { if code := c.Run([]string{"node1", "node2", "node3"}); code != 1 {
t.Fatalf("expected return code 1, got %d", code) t.Fatalf("expected return code 1, got %d", code)
} }
@ -36,11 +32,11 @@ func TestRttCommand_Run_BadArgs(t *testing.T) {
t.Fatalf("expected return code 1, got %d", code) t.Fatalf("expected return code 1, got %d", code)
} }
if code := c.Run([]string{"-wan", "dc1.node1", "node2"}); code != 1 { if code := c.Run([]string{"-wan", "node1.dc1", "node2"}); code != 1 {
t.Fatalf("expected return code 1, got %d", code) t.Fatalf("expected return code 1, got %d", code)
} }
if code := c.Run([]string{"-wan", "node1", "dc1.node2"}); code != 1 { if code := c.Run([]string{"-wan", "node1", "node2.dc1"}); code != 1 {
t.Fatalf("expected return code 1, got %d", code) t.Fatalf("expected return code 1, got %d", code)
} }
} }
@ -96,20 +92,18 @@ func TestRttCommand_Run_LAN(t *testing.T) {
} }
// Make sure the proper RTT was reported in the output. // Make sure the proper RTT was reported in the output.
expected := fmt.Sprintf("rtt=%s", dist_str) expected := fmt.Sprintf("rtt: %s", dist_str)
if !strings.Contains(ui.OutputWriter.String(), expected) { if !strings.Contains(ui.OutputWriter.String(), expected) {
t.Fatalf("bad: %#v", ui.OutputWriter.String()) t.Fatalf("bad: %#v", ui.OutputWriter.String())
} }
} }
// Try the short mode. // Default to the agent's node.
{ {
ui := new(cli.MockUi) ui := new(cli.MockUi)
c := &RttCommand{Ui: ui} c := &RttCommand{Ui: ui}
args := []string{ args := []string{
"-short",
"-http-addr=" + a.httpAddr, "-http-addr=" + a.httpAddr,
a.config.NodeName,
"dogs", "dogs",
} }
code := c.Run(args) code := c.Run(args)
@ -118,8 +112,8 @@ func TestRttCommand_Run_LAN(t *testing.T) {
} }
// Make sure the proper RTT was reported in the output. // Make sure the proper RTT was reported in the output.
expected := fmt.Sprintf("%s\n", dist_str) expected := fmt.Sprintf("rtt: %s", dist_str)
if ui.OutputWriter.String() != expected { if !strings.Contains(ui.OutputWriter.String(), expected) {
t.Fatalf("bad: %#v", ui.OutputWriter.String()) t.Fatalf("bad: %#v", ui.OutputWriter.String())
} }
} }
@ -145,7 +139,7 @@ func TestRttCommand_Run_WAN(t *testing.T) {
defer a.Shutdown() defer a.Shutdown()
waitForLeader(t, a.httpAddr) waitForLeader(t, a.httpAddr)
node := fmt.Sprintf("%s.%s", a.config.Datacenter, a.config.NodeName) node := fmt.Sprintf("%s.%s", a.config.NodeName, a.config.Datacenter)
// We can't easily inject WAN coordinates, so we will just query the // We can't easily inject WAN coordinates, so we will just query the
// node with itself. // node with itself.
@ -164,21 +158,19 @@ func TestRttCommand_Run_WAN(t *testing.T) {
} }
// Make sure there was some kind of RTT reported in the output. // Make sure there was some kind of RTT reported in the output.
if !strings.Contains(ui.OutputWriter.String(), "rtt=") { if !strings.Contains(ui.OutputWriter.String(), "rtt: ") {
t.Fatalf("bad: %#v", ui.OutputWriter.String()) t.Fatalf("bad: %#v", ui.OutputWriter.String())
} }
} }
// Try the short mode. // Default to the agent's node.
{ {
ui := new(cli.MockUi) ui := new(cli.MockUi)
c := &RttCommand{Ui: ui} c := &RttCommand{Ui: ui}
args := []string{ args := []string{
"-wan", "-wan",
"-short",
"-http-addr=" + a.httpAddr, "-http-addr=" + a.httpAddr,
node, node,
node,
} }
code := c.Run(args) code := c.Run(args)
if code != 0 { if code != 0 {
@ -186,7 +178,7 @@ func TestRttCommand_Run_WAN(t *testing.T) {
} }
// Make sure there was some kind of RTT reported in the output. // Make sure there was some kind of RTT reported in the output.
if !strings.Contains(ui.OutputWriter.String(), " ms\n") { if !strings.Contains(ui.OutputWriter.String(), "rtt: ") {
t.Fatalf("bad: %#v", ui.OutputWriter.String()) t.Fatalf("bad: %#v", ui.OutputWriter.String())
} }
} }

View File

@ -24,19 +24,19 @@ not compatible.
## Usage ## Usage
Usage: `consul rtt [options] node1 node2` Usage: `consul rtt [options] node1 [node2]`
The two node names are required. Note that these are node names as known to At least one node name is required. If the second node name isn't given, it
is set to the agent's node name. Note that these are node names as known to
Consul as `consul members` would show, not IP addresses. Consul as `consul members` would show, not IP addresses.
The list of available flags are: The list of available flags are:
* `-wan` - Instructs the command to use WAN coordinates instead of LAN * `-wan` - Instructs the command to use WAN coordinates instead of LAN
coordinates. If the -wan option is given, then the node names must be prefixed coordinates. By default, the two nodes are assumed to be nodes in the local
by the datacenter and a period (eg. "dc1.sever"). By default, the two nodes are datacenter and the LAN coordinates are used. If the -wan option is given,
assumed to be nodes in the local datacenter the LAN coordinates are used. then the WAN coordinates are used, and the node names must be suffixed by a period
and the datacenter (eg. "myserver.dc1").
* `-short` - Abbreviates the output to just the round trip time (eg. "1.234 ms").
* `-http-addr` - Address to the HTTP server of the agent you want to contact * `-http-addr` - Address to the HTTP server of the agent you want to contact
to send this command. If this isn't specified, the command will contact to send this command. If this isn't specified, the command will contact
@ -49,11 +49,11 @@ time between the given nodes:
``` ```
$ consul rtt n1 n2 $ consul rtt n1 n2
Estimated n1 <-> n2 rtt=0.610 ms (using LAN coordinates) Estimated n1 <-> n2 rtt: 0.610 ms (using LAN coordinates)
$ consul rtt -short n1 n2 $ consul rtt n2 # Running from n1
0.610 ms Estimated n1 <-> n2 rtt: 0.610 ms (using LAN coordinates)
$ consul rtt -wan dc1.n1 dc2.n2 $ consul rtt -wan n1.dc1 n2.dc2
Estimated dc1.n1 <-> dc2.n2 rtt=1.275 ms (using WAN coordinates) Estimated n1.dc1 <-> n2.dc2 rtt: 1.275 ms (using WAN coordinates)
``` ```