Skip to content

Commit

Permalink
Merge pull request #1947 from hashicorp/f-server-members-rpc
Browse files Browse the repository at this point in the history
Add an RPC endpoint for server members
  • Loading branch information
diptanu committed Nov 7, 2016
2 parents 6e62e55 + af4f984 commit 82b2e45
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 16 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ IMPROVEMENTS:
* driver/lxc: Support for LXC containers [GH-1699]
* driver/rkt: Support network configurations [GH-1862]
* driver/rkt: Support rkt volumes (rkt >= 1.0.0 required) [GH-1812]
* server/rpc: Added an RPC endpoint for retreiving server members [GH-1947]

BUG FIXES:
* core: Fix case where dead nodes were not properly handled by System
Expand Down
11 changes: 9 additions & 2 deletions api/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@ func (a *Agent) Join(addrs ...string) (int, error) {
}

// Members is used to query all of the known server members
func (a *Agent) Members() ([]*AgentMember, error) {
var resp []*AgentMember
func (a *Agent) Members() (*ServerMembers, error) {
var resp *ServerMembers

// Query the known members
_, err := a.client.query("/v1/agent/members", &resp, nil)
Expand Down Expand Up @@ -217,6 +217,13 @@ type joinResponse struct {
Error string `json:"error"`
}

type ServerMembers struct {
ServerName string
Region string
DC string
Members []*AgentMember
}

// AgentMember represents a cluster member known to the agent
type AgentMember struct {
Name string
Expand Down
14 changes: 5 additions & 9 deletions command/agent/agent_endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,17 +88,13 @@ func (s *HTTPServer) AgentMembersRequest(resp http.ResponseWriter, req *http.Req
if req.Method != "GET" {
return nil, CodedError(405, ErrInvalidMethod)
}
srv := s.agent.Server()
if srv == nil {
return nil, CodedError(501, ErrInvalidMethod)
args := &structs.GenericRequest{}
var out structs.ServerMembersResponse
if err := s.agent.RPC("Status.Members", args, &out); err != nil {
return nil, err
}

serfMembers := srv.Members()
members := make([]Member, len(serfMembers))
for i, mem := range serfMembers {
members[i] = nomadMember(mem)
}
return members, nil
return out, nil
}

func (s *HTTPServer) AgentForceLeaveRequest(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
Expand Down
15 changes: 10 additions & 5 deletions command/server_members.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,17 +64,22 @@ func (c *ServerMembersCommand) Run(args []string) int {
}

// Query the members
mem, err := client.Agent().Members()
srvMembers, err := client.Agent().Members()
if err != nil {
c.Ui.Error(fmt.Sprintf("Error querying servers: %s", err))
return 1
}

if srvMembers == nil {
c.Ui.Error("Agent doesn't know about server members")
return 0
}

// Sort the members
sort.Sort(api.AgentMembersNameSort(mem))
sort.Sort(api.AgentMembersNameSort(srvMembers.Members))

// Determine the leaders per region.
leaders, err := regionLeaders(client, mem)
leaders, err := regionLeaders(client, srvMembers.Members)
if err != nil {
c.Ui.Error(fmt.Sprintf("Error determining leaders: %s", err))
return 1
Expand All @@ -83,9 +88,9 @@ func (c *ServerMembersCommand) Run(args []string) int {
// Format the list
var out []string
if detailed {
out = detailedOutput(mem)
out = detailedOutput(srvMembers.Members)
} else {
out = standardOutput(mem, leaders)
out = standardOutput(srvMembers.Members, leaders)
}

// Dump the list
Expand Down
29 changes: 29 additions & 0 deletions nomad/status_endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,32 @@ func (s *Status) Peers(args *structs.GenericRequest, reply *[]string) error {
*reply = peers
return nil
}

// Members return the list of servers in a cluster that a particular server is
// aware of
func (s *Status) Members(args *structs.GenericRequest, reply *structs.ServerMembersResponse) error {
serfMembers := s.srv.Members()
members := make([]*structs.ServerMember, len(serfMembers))
for i, mem := range serfMembers {
members[i] = &structs.ServerMember{
Name: mem.Name,
Addr: mem.Addr,
Port: mem.Port,
Tags: mem.Tags,
Status: mem.Status.String(),
ProtocolMin: mem.ProtocolMin,
ProtocolMax: mem.ProtocolMax,
ProtocolCur: mem.ProtocolCur,
DelegateMin: mem.DelegateMin,
DelegateMax: mem.DelegateMax,
DelegateCur: mem.DelegateCur,
}
}
*reply = structs.ServerMembersResponse{
ServerName: s.srv.config.NodeName,
ServerRegion: s.srv.config.Region,
ServerDC: s.srv.config.Datacenter,
Members: members,
}
return nil
}
25 changes: 25 additions & 0 deletions nomad/structs/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"errors"
"fmt"
"io"
"net"
"os"
"path/filepath"
"reflect"
Expand Down Expand Up @@ -359,6 +360,30 @@ type PeriodicForceRequest struct {
WriteRequest
}

// ServerMembersResponse has the list of servers in a cluster
type ServerMembersResponse struct {
ServerName string
ServerRegion string
ServerDC string
Members []*ServerMember
QueryMeta
}

// ServerMember holds information about a Nomad server agent in a cluster
type ServerMember struct {
Name string
Addr net.IP
Port uint16
Tags map[string]string
Status string
ProtocolMin uint8
ProtocolMax uint8
ProtocolCur uint8
DelegateMin uint8
DelegateMax uint8
DelegateCur uint8
}

// DeriveVaultTokenRequest is used to request wrapped Vault tokens for the
// following tasks in the given allocation
type DeriveVaultTokenRequest struct {
Expand Down

0 comments on commit 82b2e45

Please sign in to comment.