diff --git a/agent/consul/operator_raft_endpoint.go b/agent/consul/operator_raft_endpoint.go index d15cf8625..418836b91 100644 --- a/agent/consul/operator_raft_endpoint.go +++ b/agent/consul/operator_raft_endpoint.go @@ -50,16 +50,19 @@ func (op *Operator) RaftGetConfiguration(args *structs.DCSpecificRequest, reply reply.Index = future.Index() for _, server := range future.Configuration().Servers { node := "(unknown)" + raftProtocolVersion := "unknown" if member, ok := serverMap[server.Address]; ok { node = member.Name + raftProtocolVersion = member.Tags["raft_vsn"] } entry := &structs.RaftServer{ - ID: server.ID, - Node: node, - Address: server.Address, - Leader: server.Address == leader, - Voter: server.Suffrage == raft.Voter, + ID: server.ID, + Node: node, + Address: server.Address, + Leader: server.Address == leader, + Voter: server.Suffrage == raft.Voter, + ProtocolVersion: raftProtocolVersion, } reply.Servers = append(reply.Servers, entry) } diff --git a/agent/consul/operator_raft_endpoint_test.go b/agent/consul/operator_raft_endpoint_test.go index e7ba78dbe..9bb84bc09 100644 --- a/agent/consul/operator_raft_endpoint_test.go +++ b/agent/consul/operator_raft_endpoint_test.go @@ -3,7 +3,6 @@ package consul import ( "fmt" "os" - "reflect" "strings" "testing" "time" @@ -13,6 +12,7 @@ import ( "github.com/hashicorp/consul/testrpc" "github.com/hashicorp/net-rpc-msgpackrpc" "github.com/hashicorp/raft" + "github.com/pascaldekloe/goe/verify" ) func TestOperator_RaftGetConfiguration(t *testing.T) { @@ -44,18 +44,17 @@ func TestOperator_RaftGetConfiguration(t *testing.T) { expected := structs.RaftConfigurationResponse{ Servers: []*structs.RaftServer{ &structs.RaftServer{ - ID: me.ID, - Node: s1.config.NodeName, - Address: me.Address, - Leader: true, - Voter: true, + ID: me.ID, + Node: s1.config.NodeName, + Address: me.Address, + Leader: true, + Voter: true, + ProtocolVersion: "3", }, }, Index: future.Index(), } - if !reflect.DeepEqual(reply, expected) { - t.Fatalf("bad: %v", reply) - } + verify.Values(t, "", reply, expected) } func TestOperator_RaftGetConfiguration_ACLDeny(t *testing.T) { @@ -121,18 +120,17 @@ func TestOperator_RaftGetConfiguration_ACLDeny(t *testing.T) { expected := structs.RaftConfigurationResponse{ Servers: []*structs.RaftServer{ &structs.RaftServer{ - ID: me.ID, - Node: s1.config.NodeName, - Address: me.Address, - Leader: true, - Voter: true, + ID: me.ID, + Node: s1.config.NodeName, + Address: me.Address, + Leader: true, + Voter: true, + ProtocolVersion: "3", }, }, Index: future.Index(), } - if !reflect.DeepEqual(reply, expected) { - t.Fatalf("bad: %v", reply) - } + verify.Values(t, "", reply, expected) } func TestOperator_RaftRemovePeerByAddress(t *testing.T) { diff --git a/agent/structs/operator.go b/agent/structs/operator.go index a3eadb060..5fb1c4da1 100644 --- a/agent/structs/operator.go +++ b/agent/structs/operator.go @@ -61,6 +61,9 @@ type RaftServer struct { // Leader is true if this server is the current cluster leader. Leader bool + // Protocol version is the raft protocol version used by the server + ProtocolVersion string + // Voter is true if this server has a vote in the cluster. This might // be false if the server is staging and still coming online, or if // it's a non-voting server, which will be added in a future release of @@ -68,7 +71,7 @@ type RaftServer struct { Voter bool } -// RaftConfigrationResponse is returned when querying for the current Raft +// RaftConfigurationResponse is returned when querying for the current Raft // configuration. type RaftConfigurationResponse struct { // Servers has the list of servers in the Raft configuration. diff --git a/api/operator_raft.go b/api/operator_raft.go index 5f3c25b13..a9844df2d 100644 --- a/api/operator_raft.go +++ b/api/operator_raft.go @@ -17,6 +17,9 @@ type RaftServer struct { // Leader is true if this server is the current cluster leader. Leader bool + // Protocol version is the raft protocol version used by the server + ProtocolVersion string + // Voter is true if this server has a vote in the cluster. This might // be false if the server is staging and still coming online, or if // it's a non-voting server, which will be added in a future release of @@ -24,7 +27,7 @@ type RaftServer struct { Voter bool } -// RaftConfigration is returned when querying for the current Raft configuration. +// RaftConfiguration is returned when querying for the current Raft configuration. type RaftConfiguration struct { // Servers has the list of servers in the Raft configuration. Servers []*RaftServer diff --git a/command/operator_raft_list.go b/command/operator_raft_list.go index 7459f54e6..737220bcb 100644 --- a/command/operator_raft_list.go +++ b/command/operator_raft_list.go @@ -6,7 +6,6 @@ import ( "strings" "github.com/hashicorp/consul/api" - "github.com/hashicorp/serf/serf" "github.com/ryanuber/columnize" ) @@ -58,23 +57,6 @@ func (c *OperatorRaftListCommand) Run(args []string) int { } 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, @@ -87,7 +69,8 @@ func raftListPeers(client *api.Client, stale bool) (string, error) { // Format it as a nice table. result := []string{"Node|ID|Address|State|Voter|RaftProtocol"} for _, s := range reply.Servers { - raftProtocol := raftProtocols[s.Node] + raftProtocol := s.ProtocolVersion + if raftProtocol == "" { raftProtocol = "<=1" }