mirror of https://github.com/hashicorp/consul
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
223 lines
5.2 KiB
223 lines
5.2 KiB
package command |
|
|
|
import ( |
|
"fmt" |
|
"strings" |
|
"testing" |
|
"time" |
|
|
|
"github.com/hashicorp/consul/command/agent" |
|
"github.com/hashicorp/consul/command/base" |
|
"github.com/hashicorp/consul/consul/structs" |
|
"github.com/hashicorp/consul/testutil" |
|
"github.com/hashicorp/serf/coordinate" |
|
"github.com/mitchellh/cli" |
|
) |
|
|
|
func testRTTCommand(t *testing.T) (*cli.MockUi, *RTTCommand) { |
|
ui := new(cli.MockUi) |
|
return ui, &RTTCommand{ |
|
Command: base.Command{ |
|
Ui: ui, |
|
Flags: base.FlagSetClientHTTP, |
|
}, |
|
} |
|
} |
|
|
|
func TestRTTCommand_Implements(t *testing.T) { |
|
var _ cli.Command = &RTTCommand{} |
|
} |
|
|
|
func TestRTTCommand_Run_BadArgs(t *testing.T) { |
|
_, c := testRTTCommand(t) |
|
|
|
if code := c.Run([]string{}); code != 1 { |
|
t.Fatalf("expected return code 1, got %d", code) |
|
} |
|
|
|
if code := c.Run([]string{"node1", "node2", "node3"}); code != 1 { |
|
t.Fatalf("expected return code 1, got %d", code) |
|
} |
|
|
|
if code := c.Run([]string{"-wan", "node1", "node2"}); code != 1 { |
|
t.Fatalf("expected return code 1, got %d", code) |
|
} |
|
|
|
if code := c.Run([]string{"-wan", "node1.dc1", "node2"}); code != 1 { |
|
t.Fatalf("expected return code 1, got %d", code) |
|
} |
|
|
|
if code := c.Run([]string{"-wan", "node1", "node2.dc1"}); code != 1 { |
|
t.Fatalf("expected return code 1, got %d", code) |
|
} |
|
} |
|
|
|
func TestRTTCommand_Run_LAN(t *testing.T) { |
|
updatePeriod := 10 * time.Millisecond |
|
a := testAgentWithConfig(t, func(c *agent.Config) { |
|
c.ConsulConfig.CoordinateUpdatePeriod = updatePeriod |
|
}) |
|
defer a.Shutdown() |
|
waitForLeader(t, a.httpAddr) |
|
|
|
// Inject some known coordinates. |
|
c1 := coordinate.NewCoordinate(coordinate.DefaultConfig()) |
|
c2 := c1.Clone() |
|
c2.Vec[0] = 0.123 |
|
dist_str := fmt.Sprintf("%.3f ms", c1.DistanceTo(c2).Seconds()*1000.0) |
|
{ |
|
req := structs.CoordinateUpdateRequest{ |
|
Datacenter: a.config.Datacenter, |
|
Node: a.config.NodeName, |
|
Coord: c1, |
|
} |
|
var reply struct{} |
|
if err := a.agent.RPC("Coordinate.Update", &req, &reply); err != nil { |
|
t.Fatalf("err: %s", err) |
|
} |
|
} |
|
{ |
|
req := structs.RegisterRequest{ |
|
Datacenter: a.config.Datacenter, |
|
Node: "dogs", |
|
Address: "127.0.0.2", |
|
} |
|
var reply struct{} |
|
if err := a.agent.RPC("Catalog.Register", &req, &reply); err != nil { |
|
t.Fatalf("err: %s", err) |
|
} |
|
} |
|
{ |
|
var reply struct{} |
|
req := structs.CoordinateUpdateRequest{ |
|
Datacenter: a.config.Datacenter, |
|
Node: "dogs", |
|
Coord: c2, |
|
} |
|
if err := a.agent.RPC("Coordinate.Update", &req, &reply); err != nil { |
|
t.Fatalf("err: %s", err) |
|
} |
|
} |
|
|
|
// Ask for the RTT of two known nodes |
|
ui, c := testRTTCommand(t) |
|
args := []string{ |
|
"-http-addr=" + a.httpAddr, |
|
a.config.NodeName, |
|
"dogs", |
|
} |
|
|
|
// Wait for the updates to get flushed to the data store. |
|
testutil.WaitForResult(func() (bool, error) { |
|
code := c.Run(args) |
|
if code != 0 { |
|
return false, fmt.Errorf("bad: %d: %#v", code, ui.ErrorWriter.String()) |
|
} |
|
|
|
// Make sure the proper RTT was reported in the output. |
|
expected := fmt.Sprintf("rtt: %s", dist_str) |
|
if !strings.Contains(ui.OutputWriter.String(), expected) { |
|
return false, fmt.Errorf("bad: %#v", ui.OutputWriter.String()) |
|
} |
|
|
|
return true, nil |
|
}, func(err error) { |
|
t.Fatalf("failed to get proper RTT output: %v", err) |
|
}) |
|
|
|
// Default to the agent's node. |
|
{ |
|
ui, c := testRTTCommand(t) |
|
args := []string{ |
|
"-http-addr=" + a.httpAddr, |
|
"dogs", |
|
} |
|
code := c.Run(args) |
|
if code != 0 { |
|
t.Fatalf("bad: %d: %#v", code, ui.ErrorWriter.String()) |
|
} |
|
|
|
// Make sure the proper RTT was reported in the output. |
|
expected := fmt.Sprintf("rtt: %s", dist_str) |
|
if !strings.Contains(ui.OutputWriter.String(), expected) { |
|
t.Fatalf("bad: %#v", ui.OutputWriter.String()) |
|
} |
|
} |
|
|
|
// Try an unknown node. |
|
{ |
|
ui, c := testRTTCommand(t) |
|
args := []string{ |
|
"-http-addr=" + a.httpAddr, |
|
a.config.NodeName, |
|
"nope", |
|
} |
|
code := c.Run(args) |
|
if code != 1 { |
|
t.Fatalf("bad: %d: %#v", code, ui.ErrorWriter.String()) |
|
} |
|
} |
|
} |
|
|
|
func TestRTTCommand_Run_WAN(t *testing.T) { |
|
a := testAgent(t) |
|
defer a.Shutdown() |
|
waitForLeader(t, a.httpAddr) |
|
|
|
node := fmt.Sprintf("%s.%s", a.config.NodeName, a.config.Datacenter) |
|
|
|
// We can't easily inject WAN coordinates, so we will just query the |
|
// node with itself. |
|
{ |
|
ui, c := testRTTCommand(t) |
|
args := []string{ |
|
"-wan", |
|
"-http-addr=" + a.httpAddr, |
|
node, |
|
node, |
|
} |
|
code := c.Run(args) |
|
if code != 0 { |
|
t.Fatalf("bad: %d: %#v", code, ui.ErrorWriter.String()) |
|
} |
|
|
|
// Make sure there was some kind of RTT reported in the output. |
|
if !strings.Contains(ui.OutputWriter.String(), "rtt: ") { |
|
t.Fatalf("bad: %#v", ui.OutputWriter.String()) |
|
} |
|
} |
|
|
|
// Default to the agent's node. |
|
{ |
|
ui, c := testRTTCommand(t) |
|
args := []string{ |
|
"-wan", |
|
"-http-addr=" + a.httpAddr, |
|
node, |
|
} |
|
code := c.Run(args) |
|
if code != 0 { |
|
t.Fatalf("bad: %d: %#v", code, ui.ErrorWriter.String()) |
|
} |
|
|
|
// Make sure there was some kind of RTT reported in the output. |
|
if !strings.Contains(ui.OutputWriter.String(), "rtt: ") { |
|
t.Fatalf("bad: %#v", ui.OutputWriter.String()) |
|
} |
|
} |
|
|
|
// Try an unknown node. |
|
{ |
|
ui, c := testRTTCommand(t) |
|
args := []string{ |
|
"-wan", |
|
"-http-addr=" + a.httpAddr, |
|
node, |
|
"dc1.nope", |
|
} |
|
code := c.Run(args) |
|
if code != 1 { |
|
t.Fatalf("bad: %d: %#v", code, ui.ErrorWriter.String()) |
|
} |
|
} |
|
}
|
|
|