github.com/hernad/nomad@v1.6.112/command/operator_raft_list.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package command 5 6 import ( 7 "fmt" 8 "sort" 9 "strings" 10 11 "github.com/hernad/nomad/api" 12 "github.com/posener/complete" 13 "github.com/ryanuber/columnize" 14 ) 15 16 type OperatorRaftListCommand struct { 17 Meta 18 } 19 20 func (c *OperatorRaftListCommand) Help() string { 21 helpText := ` 22 Usage: nomad operator raft list-peers [options] 23 24 Displays the current Raft peer configuration. 25 26 If ACLs are enabled, this command requires a management token. 27 28 General Options: 29 30 ` + generalOptionsUsage(usageOptsDefault|usageOptsNoNamespace) + ` 31 32 List Peers Options: 33 34 -stale=[true|false] 35 The -stale argument defaults to "false" which means the leader provides the 36 result. If the cluster is in an outage state without a leader, you may need 37 to set -stale to "true" to get the configuration from a non-leader server. 38 ` 39 return strings.TrimSpace(helpText) 40 } 41 42 func (c *OperatorRaftListCommand) AutocompleteFlags() complete.Flags { 43 return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient), 44 complete.Flags{ 45 "-stale": complete.PredictAnything, 46 }) 47 } 48 49 func (c *OperatorRaftListCommand) AutocompleteArgs() complete.Predictor { 50 return complete.PredictNothing 51 } 52 53 func (c *OperatorRaftListCommand) Synopsis() string { 54 return "Display the current Raft peer configuration" 55 } 56 57 func (c *OperatorRaftListCommand) Name() string { return "operator raft list-peers" } 58 59 func (c *OperatorRaftListCommand) Run(args []string) int { 60 var stale bool 61 62 flags := c.Meta.FlagSet("raft", FlagSetClient) 63 flags.Usage = func() { c.Ui.Output(c.Help()) } 64 65 flags.BoolVar(&stale, "stale", false, "") 66 if err := flags.Parse(args); err != nil { 67 c.Ui.Error(fmt.Sprintf("Failed to parse args: %v", err)) 68 return 1 69 } 70 71 // Set up a client. 72 client, err := c.Meta.Client() 73 if err != nil { 74 c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err)) 75 return 1 76 } 77 operator := client.Operator() 78 79 // Fetch the current configuration. 80 q := &api.QueryOptions{ 81 AllowStale: stale, 82 } 83 reply, err := operator.RaftGetConfiguration(q) 84 if err != nil { 85 c.Ui.Error(fmt.Sprintf("Failed to retrieve raft configuration: %v", err)) 86 return 1 87 } 88 89 // Format it as a nice table. 90 result := []string{"Node|ID|Address|State|Voter|RaftProtocol"} 91 sort.Slice(reply.Servers, func(i, j int) bool { 92 return reply.Servers[i].Node < reply.Servers[j].Node 93 }) 94 95 for _, s := range reply.Servers { 96 state := "follower" 97 if s.Leader { 98 state = "leader" 99 } 100 result = append(result, fmt.Sprintf("%s|%s|%s|%s|%v|%s", 101 s.Node, s.ID, s.Address, state, s.Voter, s.RaftProtocol)) 102 } 103 c.Ui.Output(columnize.SimpleFormat(result)) 104 105 return 0 106 }