cli: display Raft version in `server members` (#12317)

The previous output of the `nomad server members` command would output a
column named `Protocol` that displayed the Serf protocol being currently
used by servers.

This is not a configurable option, so it holds very little value to
operators. It is also easy to confuse it with the Raft Protocol version,
which is configurable and highly relevant to operators.

This commit replaces the previous `Protocol` column with the new `Raft
Version`. It also updates the `-detailed` flag to be called `-verbose`
so it matches other commands. The detailed output now also outputs the
same information as the standard output with the addition of the
previous `Protocol` column and `Tags`.
This commit is contained in:
Luiz Aoqui 2022-03-17 14:15:10 -04:00 committed by GitHub
parent 15089f055f
commit 68e5b58007
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 78 additions and 37 deletions

7
.changelog/12317.txt Normal file
View File

@ -0,0 +1,7 @@
```release-note:improvement
cli: display the Raft version instead of the Serf protocol in the `nomad server members` command
```
```release-note:improvement
cli: rename the `nomad server members` `-detailed` flag to `-verbose` so it matches other commands
```

View File

@ -32,10 +32,9 @@ General Options:
Server Members Options: Server Members Options:
-detailed -verbose
Show detailed information about each member. This dumps Show detailed information about each member. This dumps a raw set of tags
a raw set of tags which shows more information than the which shows more information than the default output format.
default output format.
` `
return strings.TrimSpace(helpText) return strings.TrimSpace(helpText)
} }
@ -58,11 +57,12 @@ func (c *ServerMembersCommand) Synopsis() string {
func (c *ServerMembersCommand) Name() string { return "server members" } func (c *ServerMembersCommand) Name() string { return "server members" }
func (c *ServerMembersCommand) Run(args []string) int { func (c *ServerMembersCommand) Run(args []string) int {
var detailed bool var detailed, verbose bool
flags := c.Meta.FlagSet(c.Name(), FlagSetClient) flags := c.Meta.FlagSet(c.Name(), FlagSetClient)
flags.Usage = func() { c.Ui.Output(c.Help()) } flags.Usage = func() { c.Ui.Output(c.Help()) }
flags.BoolVar(&detailed, "detailed", false, "Show detailed output") flags.BoolVar(&detailed, "detailed", false, "Show detailed output")
flags.BoolVar(&verbose, "verbose", false, "Show detailed output")
if err := flags.Parse(args); err != nil { if err := flags.Parse(args); err != nil {
return 1 return 1
@ -76,6 +76,11 @@ func (c *ServerMembersCommand) Run(args []string) int {
return 1 return 1
} }
// Keep support for previous flag name
if detailed {
verbose = true
}
// Get the HTTP client // Get the HTTP client
client, err := c.Meta.Client() client, err := c.Meta.Client()
if err != nil { if err != nil {
@ -103,8 +108,8 @@ func (c *ServerMembersCommand) Run(args []string) int {
// Format the list // Format the list
var out []string var out []string
if detailed { if verbose {
out = detailedOutput(srvMembers.Members) out = verboseOutput(srvMembers.Members, leaders)
} else { } else {
out = standardOutput(srvMembers.Members, leaders) out = standardOutput(srvMembers.Members, leaders)
} }
@ -125,25 +130,15 @@ func (c *ServerMembersCommand) Run(args []string) int {
func standardOutput(mem []*api.AgentMember, leaders map[string]string) []string { func standardOutput(mem []*api.AgentMember, leaders map[string]string) []string {
// Format the members list // Format the members list
members := make([]string, len(mem)+1) members := make([]string, len(mem)+1)
members[0] = "Name|Address|Port|Status|Leader|Protocol|Build|Datacenter|Region" members[0] = "Name|Address|Port|Status|Leader|Raft Version|Build|Datacenter|Region"
for i, member := range mem { for i, member := range mem {
reg := member.Tags["region"] members[i+1] = fmt.Sprintf("%s|%s|%d|%s|%t|%s|%s|%s|%s",
regLeader, ok := leaders[reg]
isLeader := false
if ok {
if regLeader == net.JoinHostPort(member.Addr, member.Tags["port"]) {
isLeader = true
}
}
members[i+1] = fmt.Sprintf("%s|%s|%d|%s|%t|%d|%s|%s|%s",
member.Name, member.Name,
member.Addr, member.Addr,
member.Port, member.Port,
member.Status, member.Status,
isLeader, isLeader(member, leaders),
member.ProtocolCur, member.Tags["raft_vsn"],
member.Tags["build"], member.Tags["build"],
member.Tags["dc"], member.Tags["dc"],
member.Tags["region"]) member.Tags["region"])
@ -151,10 +146,10 @@ func standardOutput(mem []*api.AgentMember, leaders map[string]string) []string
return members return members
} }
func detailedOutput(mem []*api.AgentMember) []string { func verboseOutput(mem []*api.AgentMember, leaders map[string]string) []string {
// Format the members list // Format the members list
members := make([]string, len(mem)+1) members := make([]string, len(mem)+1)
members[0] = "Name|Address|Port|Tags" members[0] = "Name|Address|Port|Status|Leader|Protocol|Raft Version|Build|Datacenter|Region|Tags"
for i, member := range mem { for i, member := range mem {
// Format the tags // Format the tags
tagPairs := make([]string, 0, len(member.Tags)) tagPairs := make([]string, 0, len(member.Tags))
@ -163,11 +158,19 @@ func detailedOutput(mem []*api.AgentMember) []string {
} }
tags := strings.Join(tagPairs, ",") tags := strings.Join(tagPairs, ",")
members[i+1] = fmt.Sprintf("%s|%s|%d|%s", members[i+1] = fmt.Sprintf("%s|%s|%d|%s|%t|%d|%s|%s|%s|%s|%s",
member.Name, member.Name,
member.Addr, member.Addr,
member.Port, member.Port,
tags) member.Status,
isLeader(member, leaders),
member.ProtocolCur,
member.Tags["raft_vsn"],
member.Tags["build"],
member.Tags["dc"],
member.Tags["region"],
tags,
)
} }
return members return members
} }
@ -206,3 +209,10 @@ func regionLeaders(client *api.Client, mem []*api.AgentMember) (map[string]strin
return leaders, mErr.ErrorOrNil() return leaders, mErr.ErrorOrNil()
} }
func isLeader(member *api.AgentMember, leaders map[string]string) bool {
addr := net.JoinHostPort(member.Addr, member.Tags["port"])
reg := member.Tags["region"]
regLeader, ok := leaders[reg]
return ok && regLeader == addr
}

View File

@ -38,7 +38,11 @@ func TestServerMembersCommand_Run(t *testing.T) {
} }
ui.OutputWriter.Reset() ui.OutputWriter.Reset()
// Query members with detailed output // Query members with verbose output
if code := cmd.Run([]string{"-address=" + url, "-verbose"}); code != 0 {
t.Fatalf("expected exit 0, got: %d", code)
}
// Still support previous detailed flag
if code := cmd.Run([]string{"-address=" + url, "-detailed"}); code != 0 { if code := cmd.Run([]string{"-address=" + url, "-detailed"}); code != 0 {
t.Fatalf("expected exit 0, got: %d", code) t.Fatalf("expected exit 0, got: %d", code)
} }

View File

@ -27,9 +27,14 @@ capability.
## Server Members Options ## Server Members Options
- `-detailed`: Dump the basic member information as well as the raw set of tags - `-detailed` (<code>_deprecated_</code> use `-verbose` instead): Dump the
for each member. This mode reveals additional information not displayed in the basic member information as well as the raw set of tags for each member. This
standard output format. mode reveals additional information not displayed in the standard output
format.
- `-verbose`: Dump the basic member information as well as the raw set of tags
for each member. This mode reveals additional information not displayed in
the standard output format.
## Examples ## Examples
@ -37,16 +42,18 @@ Default view:
```shell-session ```shell-session
$ nomad server members $ nomad server members
Name Addr Port Status Proto Build DC Region Name Address Port Status Leader Raft Version Build Datacenter Region
node1.global 10.0.0.8 4648 alive 2 0.1.0dev dc1 global server-1.global 10.0.0.8 4648 alive true 3 1.3.0 dc1 global
node2.global 10.0.0.9 4648 alive 2 0.1.0dev dc1 global server-2.global 10.0.0.9 4648 alive false 3 1.3.0 dc1 global
server-3.global 10.0.0.10 4648 alive false 3 1.3.0 dc1 global
``` ```
Detailed view: Verbose view:
```shell-session ```shell-session
$ nomad server members -detailed $ nomad server members -verbose
Name Addr Port Tags Name Address Port Status Leader Protocol Raft Version Build Datacenter Region Tags
node1 10.0.0.8 4648 bootstrap=1,build=0.1.0dev,vsn=1,vsn_max=1,dc=dc1,port=4647,region=global,role=nomad,vsn_min=1 server-1.global 10.0.0.8 4648 alive true 2 3 1.3.0 dc1 global id=46122039-7c4d-4647-673a-81786bce2c23,rpc_addr=10.0.0.8,role=nomad,region=global,raft_vsn=3,expect=3,dc=dc1,build=1.3.0,port=4647
node2 10.0.0.9 4648 bootstrap=0,build=0.1.0dev,vsn=1,vsn_max=1,dc=dc1,port=4647,region=global,role=nomad,vsn_min=1 server-2.global 10.0.0.9 4648 alive false 2 3 1.3.0 dc1 global id=04594bee-fec9-4cec-f308-eebe82025ae7,dc=dc1,expect=3,rpc_addr=10.0.0.9,raft_vsn=3,port=4647,role=nomad,region=global,build=1.3.0
server-3.global 10.0.0.10 4648 alive false 2 3 1.3.0 dc1 global region=global,dc=dc1,rpc_addr=10.0.0.10,raft_vsn=3,build=1.3.0,expect=3,id=59542f6c-fb0e-50f1-4c9f-98bb593e9fe8,role=nomad,port=4647
``` ```

View File

@ -81,6 +81,19 @@ server {
} }
``` ```
#### Changes to the `nomad server members` command
The standard output of the `nomad server members` command replaces the previous
`Protocol` column that indicated the Serf protocol version with a new column
named `Raft Version` which outputs the Raft protocol version defined in each
server.
The `-detailed` flag is now called `-verbose` and outputs the standard values
in addition to extra information. The previous name is still supported but may
be removed in future releases.
The previous `Protocol` value can be viewed using the `-verbose` flag.
## Nomad 1.2.6, 1.1.12, and 1.0.18 ## Nomad 1.2.6, 1.1.12, and 1.0.18
#### ACL requirement for the job parse endpoint #### ACL requirement for the job parse endpoint