Skip to content

Commit

Permalink
rpk: brokers list exposing Host/Port/Rack/UUID
Browse files Browse the repository at this point in the history
Expose each broker's host, port, rack, and UUID
in the 'rpk redpanda admin brokers list' command.
Also add a new flag '--include-decommissioned'
to list decommissioned brokers with their UUIDs.
  • Loading branch information
daisukebe committed Oct 8, 2024
1 parent 7c33888 commit 0739f23
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 15 deletions.
2 changes: 1 addition & 1 deletion src/go/rpk/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ require (
github.com/pkg/errors v0.9.1
github.com/prometheus/client_model v0.6.1
github.com/prometheus/common v0.59.1
github.com/redpanda-data/common-go/rpadmin v0.1.6
github.com/redpanda-data/common-go/rpadmin v0.1.7
github.com/rs/xid v1.6.0
github.com/safchain/ethtool v0.4.1
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1
Expand Down
4 changes: 2 additions & 2 deletions src/go/rpk/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,8 @@ github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJ
github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0=
github.com/redpanda-data/common-go/net v0.1.0 h1:JnJioRJuL961r1QXiJQ1tW9+yEaJfu8FpXnUmvQbwNM=
github.com/redpanda-data/common-go/net v0.1.0/go.mod h1:iOdNkjxM7a1T8F3cYHTaKIPFCHzzp/ia6TN+Z+7Tt5w=
github.com/redpanda-data/common-go/rpadmin v0.1.6 h1:OpKO0h5unnZq8n1RJ3G6Hr8HT8ff/Ma0or5X1BNIMcM=
github.com/redpanda-data/common-go/rpadmin v0.1.6/go.mod h1:I7umqhnMhIOSEnIA3fvLtdQU7QO/SbWGCwFfFDs3De4=
github.com/redpanda-data/common-go/rpadmin v0.1.7 h1:zj3HiZuvAdOvOdi7oyTn4FYOPulO7BhvhLx9acOy810=
github.com/redpanda-data/common-go/rpadmin v0.1.7/go.mod h1:I7umqhnMhIOSEnIA3fvLtdQU7QO/SbWGCwFfFDs3De4=
github.com/redpanda-data/go-avro/v2 v2.0.0-20240405204525-77b1144dc525 h1:vskZrV6q8W8flL0Ud23AJUYAd8ZgTadO45+loFnG2G0=
github.com/redpanda-data/go-avro/v2 v2.0.0-20240405204525-77b1144dc525/go.mod h1:3YqAM7pgS5vW/EH7naCjFqnAajSgi0f0CfMe1HGhLxQ=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
Expand Down
103 changes: 91 additions & 12 deletions src/go/rpk/pkg/cli/redpanda/admin/brokers/list.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,44 @@
package brokers

import (
"fmt"
"strings"

"github.com/redpanda-data/common-go/rpadmin"
"github.com/redpanda-data/redpanda/src/go/rpk/pkg/adminapi"
"github.com/redpanda-data/redpanda/src/go/rpk/pkg/config"
"github.com/redpanda-data/redpanda/src/go/rpk/pkg/out"
"github.com/redpanda-data/redpanda/src/go/rpk/pkg/redpanda"
"github.com/spf13/afero"
"github.com/spf13/cobra"
)

func newListCommand(fs afero.Fs, p *config.Params) *cobra.Command {
return &cobra.Command{
var decom bool
cmd := &cobra.Command{
Use: "list",
Aliases: []string{"ls"},
Short: "List the brokers in your cluster",
Args: cobra.ExactArgs(0),
Long: `List the brokers in your cluster.
This command lists all brokers in the cluster, active and inactive, unless they have been decommissioned.
Using the "--all" flag, it lists decommissioned brokers with associated UUIDs too.
The output table contains the following columns:
ID Node ID, an exclusive identifier for a broker
HOST Internal RPC address for communication between brokers
PORT Internal RPC port for communication between brokers
RACK Assigned rack ID
CORES Number of cores (shards) on a broker
MEMBERSHIP Whether a broker is decommissioned or not
IS-ALIVE Whether a broker is alive or offline
VERSION Broker version
UUID (Optional) Additional exclusive identifier for a broker
NOTE: The UUID column is hidden when the cluster doesn't expose the UUID in the Admin API, or the API call fails to retrieve UUIDs.
`,
Args: cobra.ExactArgs(0),
Run: func(cmd *cobra.Command, _ []string) {
p, err := p.LoadVirtualProfile(fs)
out.MaybeDie(err, "rpk unable to load config: %v", err)
Expand All @@ -26,27 +50,82 @@ func newListCommand(fs afero.Fs, p *config.Params) *cobra.Command {
bs, err := cl.Brokers(cmd.Context())
out.MaybeDie(err, "unable to request brokers: %v", err)

headers := []string{"Node-ID", "Num-Cores", "Membership-Status"}
headers := []string{"ID", "Host", "Port", "Rack", "Cores", "Membership", "Is-Alive", "Version"}

args := func(b *rpadmin.Broker) []interface{} {
ret := []interface{}{b.NodeID, b.NumCores, b.MembershipStatus}
version, _ := redpanda.VersionFromString(b.Version)
ret := []interface{}{b.NodeID, b.InternalRPCAddress, b.InternalRPCPort, formatOutput(b.Rack), b.NumCores, b.MembershipStatus, *b.IsAlive, formatOutput(version.String())}
return ret
}
for _, b := range bs {
if b.IsAlive != nil {
headers = append(headers, "Is-Alive", "Broker-Version")
orig := args
args = func(b *rpadmin.Broker) []interface{} {
return append(orig(b), *b.IsAlive, b.Version)
}
break

idUUIDMapping, err := cl.GetBrokerUuids(cmd.Context())
if err != nil {
fmt.Printf("unable to retrieve node UUIDs: %v", err)
}
if idUUIDMapping != nil {
headers = append(headers, "UUID")
org := args
args = func(b *rpadmin.Broker) []interface{} {
return append(org(b), mapUUID(b.NodeID, idUUIDMapping))
}
}

tw := out.NewTable(headers...)
defer tw.Flush()
for _, b := range bs {
tw.Print(args(&b)...)
}

if decom && idUUIDMapping != nil {
decomNodes := extractDecomNodes(bs, idUUIDMapping)
for _, b := range decomNodes {
tw.Print(b.NodeID, "-", "-", "-", "-", "-", "-", "-", b.UUID)
}
}
},
}
cmd.Flags().BoolVarP(&decom, "include-decommissioned", "d", false, "If true, include decommissioned brokers")
return cmd
}

// mapUUID returns a UUID from "mapping" which node ID maps to "nodeID".
func mapUUID(nodeID int, mapping []rpadmin.BrokerUuids) string {
var UUIDs []string
for _, node := range mapping {
if nodeID == node.NodeID {
UUIDs = append(UUIDs, node.UUID)
}
}
if len(UUIDs) == 0 {
return "-"
}
return strings.Join(UUIDs, ", ")
}

// extractDecomNodes compares and returns nodes in brokerUUIDs (with UUIDs) not in brokers.
func extractDecomNodes(brokers []rpadmin.Broker, brokerUUIDs []rpadmin.BrokerUuids) []rpadmin.BrokerUuids {
activeNodeMap := make(map[int]bool)

for _, br := range brokers {
activeNodeMap[br.NodeID] = true
}

var decomNodes []rpadmin.BrokerUuids
for _, bu := range brokerUUIDs {
if !activeNodeMap[bu.NodeID] {
decomNodes = append(decomNodes, rpadmin.BrokerUuids{
NodeID: bu.NodeID,
UUID: bu.UUID,
})
}
}

return decomNodes
}

func formatOutput(s string) string {
if s == "" || s == "0.0.0" {
return "-"
}
return s
}

0 comments on commit 0739f23

Please sign in to comment.