Return AgentSelf struct from Agent.Self() instead of map

api.AgentSelf mirrors command.agent.agentSelf, and makes it easier to
work with the results of a call to Agent.Self()
This commit is contained in:
Ben Barnard 2017-03-08 15:50:54 +01:00
parent fa413b66f9
commit 372303f4c6
5 changed files with 36 additions and 42 deletions

View File

@ -37,8 +37,8 @@ func (c *Client) Agent() *Agent {
// Self is used to query the /v1/agent/self endpoint and
// returns information specific to the running agent.
func (a *Agent) Self() (map[string]map[string]interface{}, error) {
var out map[string]map[string]interface{}
func (a *Agent) Self() (*AgentSelf, error) {
var out *AgentSelf
// Query the self endpoint on the agent
_, err := a.client.query("/v1/agent/self", &out, nil)
@ -55,17 +55,15 @@ func (a *Agent) Self() (map[string]map[string]interface{}, error) {
// populateCache is used to insert various pieces of static
// data into the agent handle. This is used during subsequent
// lookups for the same data later on to save the round trip.
func (a *Agent) populateCache(info map[string]map[string]interface{}) {
func (a *Agent) populateCache(self *AgentSelf) {
if a.nodeName == "" {
a.nodeName, _ = info["member"]["Name"].(string)
a.nodeName = self.Member.Name
}
if tags, ok := info["member"]["Tags"].(map[string]interface{}); ok {
if a.datacenter == "" {
a.datacenter, _ = tags["dc"].(string)
}
if a.region == "" {
a.region, _ = tags["region"].(string)
}
if a.datacenter == "" {
a.datacenter, _ = self.Member.Tags["dc"]
}
if a.region == "" {
a.region, _ = self.Member.Tags["region"]
}
}
@ -218,10 +216,16 @@ type joinResponse struct {
}
type ServerMembers struct {
ServerName string
Region string
DC string
Members []*AgentMember
ServerName string
ServerRegion string
ServerDC string
Members []*AgentMember
}
type AgentSelf struct {
Config map[string]interface{} `json:"config"`
Member AgentMember `json:"member"`
Stats map[string]map[string]string `json:"stats"`
}
// AgentMember represents a cluster member known to the agent

View File

@ -22,7 +22,7 @@ func TestAgent_Self(t *testing.T) {
}
// Check that we got a valid response
if name, ok := res["member"]["Name"]; !ok || name == "" {
if res.Member.Name == "" {
t.Fatalf("bad member name in response: %#v", res)
}

View File

@ -55,17 +55,15 @@ func (c *AgentInfoCommand) Run(args []string) int {
}
// Sort and output agent info
var stats map[string]interface{}
stats, _ = info["stats"]
statsKeys := make([]string, 0, len(stats))
for key := range stats {
statsKeys := make([]string, 0, len(info.Stats))
for key := range info.Stats {
statsKeys = append(statsKeys, key)
}
sort.Strings(statsKeys)
for _, key := range statsKeys {
c.Ui.Output(key)
statsData, _ := stats[key].(map[string]interface{})
statsData, _ := info.Stats[key]
statsDataKeys := make([]string, len(statsData))
i := 0
for key := range statsData {

View File

@ -2,7 +2,6 @@ package command
import (
"fmt"
"reflect"
"strconv"
"strings"
"time"
@ -69,25 +68,21 @@ func (c *AgentCheckCommand) Run(args []string) int {
c.Ui.Output(fmt.Sprintf("unable to query agent info: %v", err))
return HealthCritical
}
if stats, ok := info["stats"]; !ok && (reflect.TypeOf(stats).Kind() == reflect.Map) {
c.Ui.Error("error getting stats from the agent api")
return 1
}
if _, ok := info["stats"]["nomad"]; ok {
return c.checkServerHealth(info["stats"], minPeers)
if _, ok := info.Stats["nomad"]; ok {
return c.checkServerHealth(info.Stats, minPeers)
}
if _, ok := info["stats"]["client"]; ok {
return c.checkClientHealth(info["stats"], minServers)
if clientStats, ok := info.Stats["client"]; ok {
return c.checkClientHealth(clientStats, minServers)
}
return HealthWarn
}
// checkServerHealth returns the health of a server.
// TODO Add more rules for determining server health
func (c *AgentCheckCommand) checkServerHealth(info map[string]interface{}, minPeers int) int {
raft := info["raft"].(map[string]interface{})
knownPeers, err := strconv.Atoi(raft["num_peers"].(string))
func (c *AgentCheckCommand) checkServerHealth(info map[string]map[string]string, minPeers int) int {
raft := info["raft"]
knownPeers, err := strconv.Atoi(raft["num_peers"])
if err != nil {
c.Ui.Output(fmt.Sprintf("unable to get known peers: %v", err))
return HealthCritical
@ -101,21 +96,20 @@ func (c *AgentCheckCommand) checkServerHealth(info map[string]interface{}, minPe
}
// checkClientHealth returns the health of a client
func (c *AgentCheckCommand) checkClientHealth(info map[string]interface{}, minServers int) int {
clientStats := info["client"].(map[string]interface{})
knownServers, err := strconv.Atoi(clientStats["known_servers"].(string))
func (c *AgentCheckCommand) checkClientHealth(clientStats map[string]string, minServers int) int {
knownServers, err := strconv.Atoi(clientStats["known_servers"])
if err != nil {
c.Ui.Output(fmt.Sprintf("unable to get known servers: %v", err))
return HealthCritical
}
heartbeatTTL, err := time.ParseDuration(clientStats["heartbeat_ttl"].(string))
heartbeatTTL, err := time.ParseDuration(clientStats["heartbeat_ttl"])
if err != nil {
c.Ui.Output(fmt.Sprintf("unable to parse heartbeat TTL: %v", err))
return HealthCritical
}
lastHeartbeat, err := time.ParseDuration(clientStats["last_heartbeat"].(string))
lastHeartbeat, err := time.ParseDuration(clientStats["last_heartbeat"])
if err != nil {
c.Ui.Output(fmt.Sprintf("unable to parse last heartbeat: %v", err))
return HealthCritical

View File

@ -76,14 +76,12 @@ func getLocalNodeID(client *api.Client) (string, error) {
if err != nil {
return "", fmt.Errorf("Error querying agent info: %s", err)
}
var stats map[string]interface{}
stats, _ = info["stats"]
clientStats, ok := stats["client"].(map[string]interface{})
clientStats, ok := info.Stats["client"]
if !ok {
return "", fmt.Errorf("Nomad not running in client mode")
}
nodeID, ok := clientStats["node_id"].(string)
nodeID, ok := clientStats["node_id"]
if !ok {
return "", fmt.Errorf("Failed to determine node ID")
}