1package api
2
3import (
4	"github.com/hashicorp/serf/coordinate"
5)
6
7// CoordinateEntry represents a node and its associated network coordinate.
8type CoordinateEntry struct {
9	Node    string
10	Segment string
11	Coord   *coordinate.Coordinate
12}
13
14// CoordinateDatacenterMap has the coordinates for servers in a given datacenter
15// and area. Network coordinates are only compatible within the same area.
16type CoordinateDatacenterMap struct {
17	Datacenter  string
18	AreaID      string
19	Coordinates []CoordinateEntry
20}
21
22// Coordinate can be used to query the coordinate endpoints
23type Coordinate struct {
24	c *Client
25}
26
27// Coordinate returns a handle to the coordinate endpoints
28func (c *Client) Coordinate() *Coordinate {
29	return &Coordinate{c}
30}
31
32// Datacenters is used to return the coordinates of all the servers in the WAN
33// pool.
34func (c *Coordinate) Datacenters() ([]*CoordinateDatacenterMap, error) {
35	r := c.c.newRequest("GET", "/v1/coordinate/datacenters")
36	_, resp, err := requireOK(c.c.doRequest(r))
37	if err != nil {
38		return nil, err
39	}
40	defer closeResponseBody(resp)
41
42	var out []*CoordinateDatacenterMap
43	if err := decodeBody(resp, &out); err != nil {
44		return nil, err
45	}
46	return out, nil
47}
48
49// Nodes is used to return the coordinates of all the nodes in the LAN pool.
50func (c *Coordinate) Nodes(q *QueryOptions) ([]*CoordinateEntry, *QueryMeta, error) {
51	r := c.c.newRequest("GET", "/v1/coordinate/nodes")
52	r.setQueryOptions(q)
53	rtt, resp, err := requireOK(c.c.doRequest(r))
54	if err != nil {
55		return nil, nil, err
56	}
57	defer closeResponseBody(resp)
58
59	qm := &QueryMeta{}
60	parseQueryMeta(resp, qm)
61	qm.RequestTime = rtt
62
63	var out []*CoordinateEntry
64	if err := decodeBody(resp, &out); err != nil {
65		return nil, nil, err
66	}
67	return out, qm, nil
68}
69
70// Update inserts or updates the LAN coordinate of a node.
71func (c *Coordinate) Update(coord *CoordinateEntry, q *WriteOptions) (*WriteMeta, error) {
72	r := c.c.newRequest("PUT", "/v1/coordinate/update")
73	r.setWriteOptions(q)
74	r.obj = coord
75	rtt, resp, err := requireOK(c.c.doRequest(r))
76	if err != nil {
77		return nil, err
78	}
79	defer closeResponseBody(resp)
80
81	wm := &WriteMeta{}
82	wm.RequestTime = rtt
83
84	return wm, nil
85}
86
87// Node is used to return the coordinates of a single node in the LAN pool.
88func (c *Coordinate) Node(node string, q *QueryOptions) ([]*CoordinateEntry, *QueryMeta, error) {
89	r := c.c.newRequest("GET", "/v1/coordinate/node/"+node)
90	r.setQueryOptions(q)
91	rtt, resp, err := requireOK(c.c.doRequest(r))
92	if err != nil {
93		return nil, nil, err
94	}
95	defer closeResponseBody(resp)
96
97	qm := &QueryMeta{}
98	parseQueryMeta(resp, qm)
99	qm.RequestTime = rtt
100
101	var out []*CoordinateEntry
102	if err := decodeBody(resp, &out); err != nil {
103		return nil, nil, err
104	}
105	return out, qm, nil
106}
107