1package api
2
3// The /v1/operator/area endpoints are available only in Consul Enterprise and
4// interact with its network area subsystem. Network areas are used to link
5// together Consul servers in different Consul datacenters. With network areas,
6// Consul datacenters can be linked together in ways other than a fully-connected
7// mesh, as is required for Consul's WAN.
8
9import (
10	"net"
11	"time"
12)
13
14// Area defines a network area.
15type Area struct {
16	// ID is this identifier for an area (a UUID). This must be left empty
17	// when creating a new area.
18	ID string
19
20	// PeerDatacenter is the peer Consul datacenter that will make up the
21	// other side of this network area. Network areas always involve a pair
22	// of datacenters: the datacenter where the area was created, and the
23	// peer datacenter. This is required.
24	PeerDatacenter string
25
26	// RetryJoin specifies the address of Consul servers to join to, such as
27	// an IPs or hostnames with an optional port number. This is optional.
28	RetryJoin []string
29
30	// UseTLS specifies whether gossip over this area should be encrypted with TLS
31	// if possible.
32	UseTLS bool
33}
34
35// AreaJoinResponse is returned when a join occurs and gives the result for each
36// address.
37type AreaJoinResponse struct {
38	// The address that was joined.
39	Address string
40
41	// Whether or not the join was a success.
42	Joined bool
43
44	// If we couldn't join, this is the message with information.
45	Error string
46}
47
48// SerfMember is a generic structure for reporting information about members in
49// a Serf cluster. This is only used by the area endpoints right now, but this
50// could be expanded to other endpoints in the future.
51type SerfMember struct {
52	// ID is the node identifier (a UUID).
53	ID string
54
55	// Name is the node name.
56	Name string
57
58	// Addr has the IP address.
59	Addr net.IP
60
61	// Port is the RPC port.
62	Port uint16
63
64	// Datacenter is the DC name.
65	Datacenter string
66
67	// Role is "client", "server", or "unknown".
68	Role string
69
70	// Build has the version of the Consul agent.
71	Build string
72
73	// Protocol is the protocol of the Consul agent.
74	Protocol int
75
76	// Status is the Serf health status "none", "alive", "leaving", "left",
77	// or "failed".
78	Status string
79
80	// RTT is the estimated round trip time from the server handling the
81	// request to the this member. This will be negative if no RTT estimate
82	// is available.
83	RTT time.Duration
84}
85
86// AreaCreate will create a new network area. The ID in the given structure must
87// be empty and a generated ID will be returned on success.
88func (op *Operator) AreaCreate(area *Area, q *WriteOptions) (string, *WriteMeta, error) {
89	r := op.c.newRequest("POST", "/v1/operator/area")
90	r.setWriteOptions(q)
91	r.obj = area
92	rtt, resp, err := requireOK(op.c.doRequest(r))
93	if err != nil {
94		return "", nil, err
95	}
96	defer closeResponseBody(resp)
97
98	wm := &WriteMeta{}
99	wm.RequestTime = rtt
100
101	var out struct{ ID string }
102	if err := decodeBody(resp, &out); err != nil {
103		return "", nil, err
104	}
105	return out.ID, wm, nil
106}
107
108// AreaUpdate will update the configuration of the network area with the given ID.
109func (op *Operator) AreaUpdate(areaID string, area *Area, q *WriteOptions) (string, *WriteMeta, error) {
110	r := op.c.newRequest("PUT", "/v1/operator/area/"+areaID)
111	r.setWriteOptions(q)
112	r.obj = area
113	rtt, resp, err := requireOK(op.c.doRequest(r))
114	if err != nil {
115		return "", nil, err
116	}
117	defer closeResponseBody(resp)
118
119	wm := &WriteMeta{}
120	wm.RequestTime = rtt
121
122	var out struct{ ID string }
123	if err := decodeBody(resp, &out); err != nil {
124		return "", nil, err
125	}
126	return out.ID, wm, nil
127}
128
129// AreaGet returns a single network area.
130func (op *Operator) AreaGet(areaID string, q *QueryOptions) ([]*Area, *QueryMeta, error) {
131	var out []*Area
132	qm, err := op.c.query("/v1/operator/area/"+areaID, &out, q)
133	if err != nil {
134		return nil, nil, err
135	}
136	return out, qm, nil
137}
138
139// AreaList returns all the available network areas.
140func (op *Operator) AreaList(q *QueryOptions) ([]*Area, *QueryMeta, error) {
141	var out []*Area
142	qm, err := op.c.query("/v1/operator/area", &out, q)
143	if err != nil {
144		return nil, nil, err
145	}
146	return out, qm, nil
147}
148
149// AreaDelete deletes the given network area.
150func (op *Operator) AreaDelete(areaID string, q *WriteOptions) (*WriteMeta, error) {
151	r := op.c.newRequest("DELETE", "/v1/operator/area/"+areaID)
152	r.setWriteOptions(q)
153	rtt, resp, err := requireOK(op.c.doRequest(r))
154	if err != nil {
155		return nil, err
156	}
157	defer closeResponseBody(resp)
158
159	wm := &WriteMeta{}
160	wm.RequestTime = rtt
161	return wm, nil
162}
163
164// AreaJoin attempts to join the given set of join addresses to the given
165// network area. See the Area structure for details about join addresses.
166func (op *Operator) AreaJoin(areaID string, addresses []string, q *WriteOptions) ([]*AreaJoinResponse, *WriteMeta, error) {
167	r := op.c.newRequest("PUT", "/v1/operator/area/"+areaID+"/join")
168	r.setWriteOptions(q)
169	r.obj = addresses
170	rtt, resp, err := requireOK(op.c.doRequest(r))
171	if err != nil {
172		return nil, nil, err
173	}
174	defer closeResponseBody(resp)
175
176	wm := &WriteMeta{}
177	wm.RequestTime = rtt
178
179	var out []*AreaJoinResponse
180	if err := decodeBody(resp, &out); err != nil {
181		return nil, nil, err
182	}
183	return out, wm, nil
184}
185
186// AreaMembers lists the Serf information about the members in the given area.
187func (op *Operator) AreaMembers(areaID string, q *QueryOptions) ([]*SerfMember, *QueryMeta, error) {
188	var out []*SerfMember
189	qm, err := op.c.query("/v1/operator/area/"+areaID+"/members", &out, q)
190	if err != nil {
191		return nil, nil, err
192	}
193	return out, qm, nil
194}
195