Show raft protocol in list-peers command (#2929)

This commit is contained in:
Kyle Havlovitz 2017-04-19 15:01:40 -07:00 committed by GitHub
parent 1bbe835707
commit 72ee7c2501
4 changed files with 43 additions and 17 deletions

View File

@ -77,17 +77,16 @@ func (c *OperatorRaftCommand) raft(args []string) error {
if err != nil {
return fmt.Errorf("error connecting to Consul agent: %s", err)
}
operator := client.Operator()
// Dispatch based on the verb argument.
if listPeers {
result, err := raftListPeers(operator, c.Command.HTTPStale())
result, err := raftListPeers(client, c.Command.HTTPStale())
if err != nil {
c.Ui.Error(fmt.Sprintf("Error getting peers: %v", err))
}
c.Ui.Output(result)
} else if removePeer {
if err := raftRemovePeers(address, "", operator); err != nil {
if err := raftRemovePeers(address, "", client.Operator()); err != nil {
return fmt.Errorf("Error removing peer: %v", err)
}
c.Ui.Output(fmt.Sprintf("Removed peer with address %q", address))

View File

@ -7,6 +7,7 @@ import (
"github.com/hashicorp/consul/api"
"github.com/hashicorp/consul/command/base"
"github.com/hashicorp/serf/serf"
"github.com/ryanuber/columnize"
)
@ -48,7 +49,7 @@ func (c *OperatorRaftListCommand) Run(args []string) int {
}
// Fetch the current configuration.
result, err := raftListPeers(client.Operator(), c.Command.HTTPStale())
result, err := raftListPeers(client, c.Command.HTTPStale())
if err != nil {
c.Ui.Error(fmt.Sprintf("Error getting peers: %v", err))
}
@ -57,24 +58,46 @@ func (c *OperatorRaftListCommand) Run(args []string) int {
return 0
}
func raftListPeers(operator *api.Operator, stale bool) (string, error) {
func raftListPeers(client *api.Client, stale bool) (string, error) {
raftProtocols := make(map[string]string)
members, err := client.Agent().Members(false)
if err != nil {
return "", err
}
for _, member := range members {
if serf.MemberStatus(member.Status) == serf.StatusLeft {
continue
}
if member.Tags["role"] != "consul" {
continue
}
raftProtocols[member.Name] = member.Tags["raft_vsn"]
}
q := &api.QueryOptions{
AllowStale: stale,
}
reply, err := operator.RaftGetConfiguration(q)
reply, err := client.Operator().RaftGetConfiguration(q)
if err != nil {
return "", fmt.Errorf("Failed to retrieve raft configuration: %v", err)
}
// Format it as a nice table.
result := []string{"Node|ID|Address|State|Voter"}
result := []string{"Node|ID|Address|State|Voter|RaftProtocol"}
for _, s := range reply.Servers {
raftProtocol := raftProtocols[s.Node]
if raftProtocol == "" {
raftProtocol = "<=1"
}
state := "follower"
if s.Leader {
state = "leader"
}
result = append(result, fmt.Sprintf("%s|%s|%s|%s|%v",
s.Node, s.ID, s.Address, state, s.Voter))
result = append(result, fmt.Sprintf("%s|%s|%s|%s|%v|%s",
s.Node, s.ID, s.Address, state, s.Voter, raftProtocol))
}
return columnize.SimpleFormat(result), nil

View File

@ -1,6 +1,7 @@
package command
import (
"fmt"
"strings"
"testing"
@ -17,6 +18,9 @@ func TestOperator_Raft_ListPeers(t *testing.T) {
defer a1.Shutdown()
waitForLeader(t, a1.httpAddr)
expected := fmt.Sprintf("%s 127.0.0.1:%d 127.0.0.1:%d leader true 2",
a1.config.NodeName, a1.config.Ports.Server, a1.config.Ports.Server)
// Test the legacy mode with 'consul operator raft -list-peers'
{
ui, c := testOperatorRaftCommand(t)
@ -27,8 +31,8 @@ func TestOperator_Raft_ListPeers(t *testing.T) {
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
}
output := strings.TrimSpace(ui.OutputWriter.String())
if !strings.Contains(output, "leader") {
t.Fatalf("bad: %s", output)
if !strings.Contains(output, expected) {
t.Fatalf("bad: %q, %q", output, expected)
}
}
@ -48,8 +52,8 @@ func TestOperator_Raft_ListPeers(t *testing.T) {
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
}
output := strings.TrimSpace(ui.OutputWriter.String())
if !strings.Contains(output, "leader") {
t.Fatalf("bad: %s", output)
if !strings.Contains(output, expected) {
t.Fatalf("bad: %q, %q", output, expected)
}
}
}

View File

@ -40,10 +40,10 @@ to set this to "true" to get the configuration from a non-leader server.
The output looks like this:
```
Node ID Address State Voter
alice 127.0.0.1:8300 127.0.0.1:8300 follower true
bob 127.0.0.2:8300 127.0.0.2:8300 leader true
carol 127.0.0.3:8300 127.0.0.3:8300 follower true
Node ID Address State Voter RaftProtocol
alice 127.0.0.1:8300 127.0.0.1:8300 follower true 2
bob 127.0.0.2:8300 127.0.0.2:8300 leader true 3
carol 127.0.0.3:8300 127.0.0.3:8300 follower true 2
```
`Node` is the node name of the server, as known to Consul, or "(unknown)" if