1package api
2
3// QueryDatacenterOptions sets options about how we fail over if there are no
4// healthy nodes in the local datacenter.
5type QueryDatacenterOptions struct {
6	// NearestN is set to the number of remote datacenters to try, based on
7	// network coordinates.
8	NearestN int
9
10	// Datacenters is a fixed list of datacenters to try after NearestN. We
11	// never try a datacenter multiple times, so those are subtracted from
12	// this list before proceeding.
13	Datacenters []string
14}
15
16// QueryDNSOptions controls settings when query results are served over DNS.
17type QueryDNSOptions struct {
18	// TTL is the time to live for the served DNS results.
19	TTL string
20}
21
22// ServiceQuery is used to query for a set of healthy nodes offering a specific
23// service.
24type ServiceQuery struct {
25	// Service is the service to query.
26	Service string
27
28	// Near allows baking in the name of a node to automatically distance-
29	// sort from. The magic "_agent" value is supported, which sorts near
30	// the agent which initiated the request by default.
31	Near string
32
33	// Failover controls what we do if there are no healthy nodes in the
34	// local datacenter.
35	Failover QueryDatacenterOptions
36
37	// If OnlyPassing is true then we will only include nodes with passing
38	// health checks (critical AND warning checks will cause a node to be
39	// discarded)
40	OnlyPassing bool
41
42	// Tags are a set of required and/or disallowed tags. If a tag is in
43	// this list it must be present. If the tag is preceded with "!" then
44	// it is disallowed.
45	Tags []string
46
47	// NodeMeta is a map of required node metadata fields. If a key/value
48	// pair is in this map it must be present on the node in order for the
49	// service entry to be returned.
50	NodeMeta map[string]string
51}
52
53// QueryTemplate carries the arguments for creating a templated query.
54type QueryTemplate struct {
55	// Type specifies the type of the query template. Currently only
56	// "name_prefix_match" is supported. This field is required.
57	Type string
58
59	// Regexp allows specifying a regex pattern to match against the name
60	// of the query being executed.
61	Regexp string
62}
63
64// PrepatedQueryDefinition defines a complete prepared query.
65type PreparedQueryDefinition struct {
66	// ID is this UUID-based ID for the query, always generated by Consul.
67	ID string
68
69	// Name is an optional friendly name for the query supplied by the
70	// user. NOTE - if this feature is used then it will reduce the security
71	// of any read ACL associated with this query/service since this name
72	// can be used to locate nodes with supplying any ACL.
73	Name string
74
75	// Session is an optional session to tie this query's lifetime to. If
76	// this is omitted then the query will not expire.
77	Session string
78
79	// Token is the ACL token used when the query was created, and it is
80	// used when a query is subsequently executed. This token, or a token
81	// with management privileges, must be used to change the query later.
82	Token string
83
84	// Service defines a service query (leaving things open for other types
85	// later).
86	Service ServiceQuery
87
88	// DNS has options that control how the results of this query are
89	// served over DNS.
90	DNS QueryDNSOptions
91
92	// Template is used to pass through the arguments for creating a
93	// prepared query with an attached template. If a template is given,
94	// interpolations are possible in other struct fields.
95	Template QueryTemplate
96}
97
98// PreparedQueryExecuteResponse has the results of executing a query.
99type PreparedQueryExecuteResponse struct {
100	// Service is the service that was queried.
101	Service string
102
103	// Nodes has the nodes that were output by the query.
104	Nodes []ServiceEntry
105
106	// DNS has the options for serving these results over DNS.
107	DNS QueryDNSOptions
108
109	// Datacenter is the datacenter that these results came from.
110	Datacenter string
111
112	// Failovers is a count of how many times we had to query a remote
113	// datacenter.
114	Failovers int
115}
116
117// PreparedQuery can be used to query the prepared query endpoints.
118type PreparedQuery struct {
119	c *Client
120}
121
122// PreparedQuery returns a handle to the prepared query endpoints.
123func (c *Client) PreparedQuery() *PreparedQuery {
124	return &PreparedQuery{c}
125}
126
127// Create makes a new prepared query. The ID of the new query is returned.
128func (c *PreparedQuery) Create(query *PreparedQueryDefinition, q *WriteOptions) (string, *WriteMeta, error) {
129	r := c.c.newRequest("POST", "/v1/query")
130	r.setWriteOptions(q)
131	r.obj = query
132	rtt, resp, err := requireOK(c.c.doRequest(r))
133	if err != nil {
134		return "", nil, err
135	}
136	defer resp.Body.Close()
137
138	wm := &WriteMeta{}
139	wm.RequestTime = rtt
140
141	var out struct{ ID string }
142	if err := decodeBody(resp, &out); err != nil {
143		return "", nil, err
144	}
145	return out.ID, wm, nil
146}
147
148// Update makes updates to an existing prepared query.
149func (c *PreparedQuery) Update(query *PreparedQueryDefinition, q *WriteOptions) (*WriteMeta, error) {
150	return c.c.write("/v1/query/"+query.ID, query, nil, q)
151}
152
153// List is used to fetch all the prepared queries (always requires a management
154// token).
155func (c *PreparedQuery) List(q *QueryOptions) ([]*PreparedQueryDefinition, *QueryMeta, error) {
156	var out []*PreparedQueryDefinition
157	qm, err := c.c.query("/v1/query", &out, q)
158	if err != nil {
159		return nil, nil, err
160	}
161	return out, qm, nil
162}
163
164// Get is used to fetch a specific prepared query.
165func (c *PreparedQuery) Get(queryID string, q *QueryOptions) ([]*PreparedQueryDefinition, *QueryMeta, error) {
166	var out []*PreparedQueryDefinition
167	qm, err := c.c.query("/v1/query/"+queryID, &out, q)
168	if err != nil {
169		return nil, nil, err
170	}
171	return out, qm, nil
172}
173
174// Delete is used to delete a specific prepared query.
175func (c *PreparedQuery) Delete(queryID string, q *WriteOptions) (*WriteMeta, error) {
176	r := c.c.newRequest("DELETE", "/v1/query/"+queryID)
177	r.setWriteOptions(q)
178	rtt, resp, err := requireOK(c.c.doRequest(r))
179	if err != nil {
180		return nil, err
181	}
182	defer resp.Body.Close()
183
184	wm := &WriteMeta{}
185	wm.RequestTime = rtt
186	return wm, nil
187}
188
189// Execute is used to execute a specific prepared query. You can execute using
190// a query ID or name.
191func (c *PreparedQuery) Execute(queryIDOrName string, q *QueryOptions) (*PreparedQueryExecuteResponse, *QueryMeta, error) {
192	var out *PreparedQueryExecuteResponse
193	qm, err := c.c.query("/v1/query/"+queryIDOrName+"/execute", &out, q)
194	if err != nil {
195		return nil, nil, err
196	}
197	return out, qm, nil
198}
199