Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NET-3865] [Supportability] Additional Information in the output of 'consul operator raft list-peers' #17582

Merged
merged 30 commits into from
Jun 14, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
2f94024
init
absolutelightning Jun 6, 2023
7626d09
fix tests
absolutelightning Jun 6, 2023
79aabc9
added -detailed in docs
absolutelightning Jun 6, 2023
44eee41
added change log
absolutelightning Jun 6, 2023
1390353
Merge branch 'main' into asheshvidyut/NET-3865
absolutelightning Jun 6, 2023
d118518
fix doc
absolutelightning Jun 6, 2023
d46a074
checking for entry in map
absolutelightning Jun 7, 2023
539dbc7
fix tests
absolutelightning Jun 7, 2023
604b616
removed detailed flag
absolutelightning Jun 7, 2023
3a63b3d
removed detailed flag
absolutelightning Jun 7, 2023
008946c
revert unwanted changes
absolutelightning Jun 7, 2023
509062e
removed unwanted changes
absolutelightning Jun 7, 2023
cf22ea5
updated change log
absolutelightning Jun 7, 2023
eb69358
Merge branch 'main' into asheshvidyut/NET-3865
absolutelightning Jun 7, 2023
5c2a587
pr review comment changes
absolutelightning Jun 8, 2023
8e1f728
pr comment changes single API instead of two
absolutelightning Jun 8, 2023
360ab9e
Merge branch 'asheshvidyut/NET-3865' of github.com:hashicorp/consul i…
absolutelightning Jun 8, 2023
dc25344
fix change log
absolutelightning Jun 8, 2023
c461f59
Merge branch 'main' into asheshvidyut/NET-3865
absolutelightning Jun 8, 2023
3631708
fix tests
absolutelightning Jun 8, 2023
5d479e8
Merge branch 'asheshvidyut/NET-3865' of github.com:hashicorp/consul i…
absolutelightning Jun 8, 2023
40dc1e1
fix tests
absolutelightning Jun 8, 2023
e7afa34
fix test operator raft endpoint test
absolutelightning Jun 9, 2023
8c1bab4
Update .changelog/17582.txt
absolutelightning Jun 9, 2023
6b76d59
nits
absolutelightning Jun 9, 2023
c001e59
Merge branch 'asheshvidyut/NET-3865' of github.com:hashicorp/consul i…
absolutelightning Jun 9, 2023
64e3b0a
Merge branch 'main' into asheshvidyut/NET-3865
absolutelightning Jun 14, 2023
7f8d9d8
updated docs
absolutelightning Jun 14, 2023
fdad3bb
Merge branch 'asheshvidyut/NET-3865' of github.com:hashicorp/consul i…
absolutelightning Jun 14, 2023
1adcb15
Merge branch 'main' into asheshvidyut/NET-3865
absolutelightning Jun 14, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/17582.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:feature
improved consul operator raft list-peers command added -detailed flag which will print CommitIndex in the table in response
```
17 changes: 17 additions & 0 deletions api/operator_raft.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,3 +122,20 @@ func (op *Operator) RaftRemovePeerByID(id string, q *WriteOptions) error {
}
return nil
}

// GetAutoPilotHealth is used to query the autopilot health.
func (op *Operator) GetAutoPilotHealth(q *QueryOptions) (*OperatorHealthReply, error) {
r := op.c.newRequest("GET", "/v1/operator/autopilot/health")
r.setQueryOptions(q)
_, resp, err := op.c.doRequest(r)
if err != nil {
return nil, err
}
defer closeResponseBody(resp)

var out OperatorHealthReply
if err := decodeBody(resp, &out); err != nil {
return nil, err
}
return &out, nil
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason you're duplicating the code for AutoPilotServerHealth instead of calling it directly?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I did not see the code before. Thanks!

19 changes: 19 additions & 0 deletions api/operator_raft_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,22 @@ func TestAPI_OperatorRaftLeaderTransfer(t *testing.T) {
t.Fatalf("err:%v", transfer)
}
}

func TestAPI_GetAutoPilotHealth(t *testing.T) {
t.Parallel()
c, s := makeClient(t)
defer s.Stop()

operator := c.Operator()
out, err := operator.GetAutoPilotHealth(nil)
if err != nil {
t.Fatalf("err: %v", err)
}

if len(out.Servers) != 1 ||
!out.Servers[0].Leader ||
!out.Servers[0].Voter ||
out.Servers[0].LastIndex <= 0 {
t.Fatalf("bad: %v", out)
}
}
71 changes: 66 additions & 5 deletions command/operator/raft/listpeers/operator_raft_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,16 @@ type cmd struct {
flags *flag.FlagSet
http *flags.HTTPFlags
help string

// flags
detailed bool
}

func (c *cmd) init() {
c.flags = flag.NewFlagSet("", flag.ContinueOnError)
c.flags.BoolVar(&c.detailed, "detailed", false,
"Outputs additional information 'commit_index' which is "+
"the index of the server's last committed Raft log entry.")
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
Expand All @@ -51,13 +57,22 @@ func (c *cmd) Run(args []string) int {
}

// Fetch the current configuration.
result, err := raftListPeers(client, c.http.Stale())
if err != nil {
c.UI.Error(fmt.Sprintf("Error getting peers: %v", err))
return 1
if c.detailed {
result, err := raftListPeersDetailed(client, c.http.Stale())
if err != nil {
c.UI.Error(fmt.Sprintf("Error getting peers: %v", err))
return 1
}
c.UI.Output(result)
} else {
result, err := raftListPeers(client, c.http.Stale())
if err != nil {
c.UI.Error(fmt.Sprintf("Error getting peers: %v", err))
return 1
}
c.UI.Output(result)
}

c.UI.Output(result)
return 0
}

Expand Down Expand Up @@ -89,6 +104,52 @@ func raftListPeers(client *api.Client, stale bool) (string, error) {
return columnize.Format(result, &columnize.Config{Delim: string([]byte{0x1f})}), nil
}

func raftListPeersDetailed(client *api.Client, stale bool) (string, error) {
q := &api.QueryOptions{
AllowStale: stale,
}
reply, err := client.Operator().RaftGetConfiguration(q)
if err != nil {
return "", fmt.Errorf("Failed to retrieve raft configuration: %v", err)
}

autoPilotReply, err := client.Operator().GetAutoPilotHealth(q)
if err != nil {
return "", fmt.Errorf("Failed to retrieve autopilot health: %v", err)
}

serverHealthDataMap := make(map[string]api.ServerHealth)

for _, serverHealthData := range autoPilotReply.Servers {
serverHealthDataMap[serverHealthData.ID] = serverHealthData
}

// Format it as a nice table.
result := []string{"Node\x1fID\x1fAddress\x1fState\x1fVoter\x1fRaftProtocol\x1fCommitIndex"}
for _, s := range reply.Servers {
raftProtocol := s.ProtocolVersion

if raftProtocol == "" {
raftProtocol = "<=1"
}
state := "follower"
if s.Leader {
state = "leader"
}

serverHealthData, ok := serverHealthDataMap[s.ID]
if ok {
result = append(result, fmt.Sprintf("%s\x1f%s\x1f%s\x1f%s\x1f%v\x1f%s\x1f%v",
s.Node, s.ID, s.Address, state, s.Voter, raftProtocol, serverHealthData.LastIndex))
} else {
result = append(result, fmt.Sprintf("%s\x1f%s\x1f%s\x1f%s\x1f%v\x1f%s\x1f%v",
s.Node, s.ID, s.Address, state, s.Voter, raftProtocol, ""))
}
}

return columnize.Format(result, &columnize.Config{Delim: string([]byte{0x1f})}), nil
}

func (c *cmd) Synopsis() string {
return synopsis
}
Expand Down
27 changes: 27 additions & 0 deletions command/operator/raft/listpeers/operator_raft_list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,33 @@ func TestOperatorRaftListPeersCommand(t *testing.T) {
}
}

func TestOperatorRaftListPeersCommandDetailed(t *testing.T) {
if testing.Short() {
t.Skip("too slow for testing.Short")
}

t.Parallel()
a := agent.NewTestAgent(t, ``)
defer a.Shutdown()

expected := fmt.Sprintf("%s %s 127.0.0.1:%d leader true 3 1",
a.Config.NodeName, a.Config.NodeID, a.Config.ServerPort)

// Test the list-peers subcommand directly
ui := cli.NewMockUi()
c := New(ui)
args := []string{"-http-addr=" + a.HTTPAddr(), "-detailed"}

code := c.Run(args)
if code != 0 {
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
}
output := strings.TrimSpace(ui.OutputWriter.String())
if !strings.Contains(output, expected) {
t.Fatalf("bad: %q, %q", output, expected)
}
}

func TestOperatorRaftListPeersCommand_verticalBar(t *testing.T) {
if testing.Short() {
t.Skip("too slow for testing.Short")
Expand Down
6 changes: 5 additions & 1 deletion website/content/commands/operator/raft.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,13 @@ configuration.

- `-stale` - Enables non-leader servers to provide cluster state information.
If the cluster is in an outage state without a leader,
we recommend setting this option to `true.
we recommend setting this option to `true`.
Default is `false`.

- `-detailed` - Outputs additional information 'commit_index' which is
the index of the server's last committed Raft log entry.
Default is `false`.

## remove-peer

Corresponding HTTP API Endpoint: [\[DELETE\] /v1/operator/raft/peer](/consul/api-docs/operator/raft#delete-raft-peer)
Expand Down