2015-09-11 23:51:18 +00:00
|
|
|
package api
|
|
|
|
|
2015-09-12 00:20:33 +00:00
|
|
|
import (
|
2016-05-22 03:05:51 +00:00
|
|
|
"fmt"
|
2015-09-17 19:40:51 +00:00
|
|
|
"sort"
|
2015-09-12 00:20:33 +00:00
|
|
|
"strconv"
|
2016-05-26 08:21:39 +00:00
|
|
|
|
|
|
|
"github.com/hashicorp/go-cleanhttp"
|
2015-09-12 00:20:33 +00:00
|
|
|
)
|
|
|
|
|
2015-09-11 23:51:18 +00:00
|
|
|
// Nodes is used to query node-related API endpoints
|
|
|
|
type Nodes struct {
|
|
|
|
client *Client
|
|
|
|
}
|
|
|
|
|
|
|
|
// Nodes returns a handle on the node endpoints.
|
|
|
|
func (c *Client) Nodes() *Nodes {
|
|
|
|
return &Nodes{client: c}
|
|
|
|
}
|
|
|
|
|
|
|
|
// List is used to list out all of the nodes
|
2015-09-14 02:55:47 +00:00
|
|
|
func (n *Nodes) List(q *QueryOptions) ([]*NodeListStub, *QueryMeta, error) {
|
2015-09-17 19:40:51 +00:00
|
|
|
var resp NodeIndexSort
|
2015-09-11 23:51:18 +00:00
|
|
|
qm, err := n.client.query("/v1/nodes", &resp, q)
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
2015-09-17 19:40:51 +00:00
|
|
|
sort.Sort(NodeIndexSort(resp))
|
2015-09-11 23:51:18 +00:00
|
|
|
return resp, qm, nil
|
|
|
|
}
|
|
|
|
|
2015-12-24 10:46:59 +00:00
|
|
|
func (n *Nodes) PrefixList(prefix string) ([]*NodeListStub, *QueryMeta, error) {
|
|
|
|
return n.List(&QueryOptions{Prefix: prefix})
|
|
|
|
}
|
|
|
|
|
2015-09-11 23:51:18 +00:00
|
|
|
// Info is used to query a specific node by its ID.
|
|
|
|
func (n *Nodes) Info(nodeID string, q *QueryOptions) (*Node, *QueryMeta, error) {
|
|
|
|
var resp Node
|
|
|
|
qm, err := n.client.query("/v1/node/"+nodeID, &resp, q)
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
return &resp, qm, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ToggleDrain is used to toggle drain mode on/off for a given node.
|
|
|
|
func (n *Nodes) ToggleDrain(nodeID string, drain bool, q *WriteOptions) (*WriteMeta, error) {
|
2015-09-12 00:20:33 +00:00
|
|
|
drainArg := strconv.FormatBool(drain)
|
2015-09-11 23:51:18 +00:00
|
|
|
wm, err := n.client.write("/v1/node/"+nodeID+"/drain?enable="+drainArg, nil, nil, q)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return wm, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Allocations is used to return the allocations associated with a node.
|
2015-11-09 16:54:18 +00:00
|
|
|
func (n *Nodes) Allocations(nodeID string, q *QueryOptions) ([]*Allocation, *QueryMeta, error) {
|
|
|
|
var resp []*Allocation
|
2015-09-11 23:51:18 +00:00
|
|
|
qm, err := n.client.query("/v1/node/"+nodeID+"/allocations", &resp, q)
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
2015-11-09 16:54:18 +00:00
|
|
|
sort.Sort(AllocationSort(resp))
|
2015-09-11 23:51:18 +00:00
|
|
|
return resp, qm, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ForceEvaluate is used to force-evaluate an existing node.
|
|
|
|
func (n *Nodes) ForceEvaluate(nodeID string, q *WriteOptions) (string, *WriteMeta, error) {
|
|
|
|
var resp nodeEvalResponse
|
|
|
|
wm, err := n.client.write("/v1/node/"+nodeID+"/evaluate", nil, &resp, q)
|
|
|
|
if err != nil {
|
|
|
|
return "", nil, err
|
|
|
|
}
|
|
|
|
return resp.EvalID, wm, nil
|
|
|
|
}
|
|
|
|
|
2016-05-22 03:05:51 +00:00
|
|
|
func (n *Nodes) Stats(nodeID string, q *QueryOptions) (*HostStats, error) {
|
|
|
|
node, _, err := n.client.Nodes().Info(nodeID, q)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if node.HTTPAddr == "" {
|
|
|
|
return nil, fmt.Errorf("http addr of the node %q is running is not advertised", nodeID)
|
|
|
|
}
|
2016-05-26 08:21:39 +00:00
|
|
|
client, err := NewClient(&Config{
|
|
|
|
Address: fmt.Sprintf("http://%s", node.HTTPAddr),
|
|
|
|
HttpClient: cleanhttp.DefaultClient(),
|
|
|
|
})
|
2016-05-22 03:05:51 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2016-05-26 08:21:39 +00:00
|
|
|
var hostStats HostStats
|
|
|
|
if _, err := client.query("/v1/client/stats/", &hostStats, nil); err != nil {
|
2016-05-22 03:05:51 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
2016-05-26 08:21:39 +00:00
|
|
|
return &hostStats, nil
|
2016-05-22 03:05:51 +00:00
|
|
|
}
|
|
|
|
|
2015-09-11 23:51:18 +00:00
|
|
|
// Node is used to deserialize a node entry.
|
|
|
|
type Node struct {
|
2015-09-14 02:55:47 +00:00
|
|
|
ID string
|
|
|
|
Datacenter string
|
|
|
|
Name string
|
2016-01-26 22:31:52 +00:00
|
|
|
HTTPAddr string
|
2015-09-14 02:55:47 +00:00
|
|
|
Attributes map[string]string
|
|
|
|
Resources *Resources
|
|
|
|
Reserved *Resources
|
|
|
|
Links map[string]string
|
2015-12-08 05:41:57 +00:00
|
|
|
Meta map[string]string
|
2015-09-14 02:55:47 +00:00
|
|
|
NodeClass string
|
|
|
|
Drain bool
|
|
|
|
Status string
|
|
|
|
StatusDescription string
|
|
|
|
CreateIndex uint64
|
|
|
|
ModifyIndex uint64
|
|
|
|
}
|
|
|
|
|
2016-05-22 03:05:51 +00:00
|
|
|
// HostStats represents resource usage stats of the host running a Nomad client
|
|
|
|
type HostStats struct {
|
2016-05-22 10:46:49 +00:00
|
|
|
Memory *HostMemoryStats
|
|
|
|
CPU []*HostCPUStats
|
|
|
|
DiskStats []*HostDiskStats
|
|
|
|
Uptime uint64
|
2016-05-22 03:05:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type HostMemoryStats struct {
|
|
|
|
Total uint64
|
|
|
|
Available uint64
|
|
|
|
Used uint64
|
|
|
|
Free uint64
|
|
|
|
}
|
|
|
|
|
|
|
|
type HostCPUStats struct {
|
|
|
|
CPU string
|
|
|
|
User float64
|
|
|
|
System float64
|
|
|
|
Idle float64
|
|
|
|
}
|
|
|
|
|
2016-05-22 10:46:49 +00:00
|
|
|
type HostDiskStats struct {
|
|
|
|
Device string
|
|
|
|
Mountpoint string
|
|
|
|
Size uint64
|
|
|
|
Used uint64
|
|
|
|
Available uint64
|
|
|
|
UsedPercent float64
|
|
|
|
InodesUsedPercent float64
|
|
|
|
}
|
|
|
|
|
2015-09-14 02:55:47 +00:00
|
|
|
// NodeListStub is a subset of information returned during
|
|
|
|
// node list operations.
|
|
|
|
type NodeListStub struct {
|
2015-09-11 23:51:18 +00:00
|
|
|
ID string
|
|
|
|
Datacenter string
|
|
|
|
Name string
|
|
|
|
NodeClass string
|
|
|
|
Drain bool
|
|
|
|
Status string
|
|
|
|
StatusDescription string
|
|
|
|
CreateIndex uint64
|
|
|
|
ModifyIndex uint64
|
|
|
|
}
|
|
|
|
|
2015-09-17 19:40:51 +00:00
|
|
|
// NodeIndexSort reverse sorts nodes by CreateIndex
|
|
|
|
type NodeIndexSort []*NodeListStub
|
|
|
|
|
|
|
|
func (n NodeIndexSort) Len() int {
|
|
|
|
return len(n)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n NodeIndexSort) Less(i, j int) bool {
|
|
|
|
return n[i].CreateIndex > n[j].CreateIndex
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n NodeIndexSort) Swap(i, j int) {
|
|
|
|
n[i], n[j] = n[j], n[i]
|
|
|
|
}
|
|
|
|
|
2015-09-11 23:51:18 +00:00
|
|
|
// nodeEvalResponse is used to decode a force-eval.
|
|
|
|
type nodeEvalResponse struct {
|
|
|
|
EvalID string
|
|
|
|
}
|
2015-11-09 16:54:18 +00:00
|
|
|
|
|
|
|
// AllocationSort reverse sorts allocs by CreateIndex.
|
|
|
|
type AllocationSort []*Allocation
|
|
|
|
|
|
|
|
func (a AllocationSort) Len() int {
|
|
|
|
return len(a)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a AllocationSort) Less(i, j int) bool {
|
|
|
|
return a[i].CreateIndex > a[j].CreateIndex
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a AllocationSort) Swap(i, j int) {
|
|
|
|
a[i], a[j] = a[j], a[i]
|
|
|
|
}
|