Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
absolutelightning committed Jun 6, 2023
1 parent 091925b commit 2f94024
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 5 deletions.
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
}
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",
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

0 comments on commit 2f94024

Please sign in to comment.