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

pull/2932/head
Kyle Havlovitz 8 years ago committed by GitHub
parent 7332d663fb
commit f25cac4c8f

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

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

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

@ -40,10 +40,10 @@ to set this to "true" to get the configuration from a non-leader server.
The output looks like this: The output looks like this:
``` ```
Node ID Address State Voter Node ID Address State Voter RaftProtocol
alice 127.0.0.1:8300 127.0.0.1:8300 follower true 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 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 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 `Node` is the node name of the server, as known to Consul, or "(unknown)" if

Loading…
Cancel
Save