File: prepared_query.go

package info (click to toggle)
consul 1.5.2+dfsg1-12
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 41,656 kB
  • sloc: sh: 2,887; makefile: 127; ruby: 75; cpp: 58; xml: 36
file content (217 lines) | stat: -rw-r--r-- 7,287 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
package api

// QueryDatacenterOptions sets options about how we fail over if there are no
// healthy nodes in the local datacenter.
type QueryDatacenterOptions struct {
	// NearestN is set to the number of remote datacenters to try, based on
	// network coordinates.
	NearestN int

	// Datacenters is a fixed list of datacenters to try after NearestN. We
	// never try a datacenter multiple times, so those are subtracted from
	// this list before proceeding.
	Datacenters []string
}

// QueryDNSOptions controls settings when query results are served over DNS.
type QueryDNSOptions struct {
	// TTL is the time to live for the served DNS results.
	TTL string
}

// ServiceQuery is used to query for a set of healthy nodes offering a specific
// service.
type ServiceQuery struct {
	// Service is the service to query.
	Service string

	// Near allows baking in the name of a node to automatically distance-
	// sort from. The magic "_agent" value is supported, which sorts near
	// the agent which initiated the request by default.
	Near string

	// Failover controls what we do if there are no healthy nodes in the
	// local datacenter.
	Failover QueryDatacenterOptions

	// IgnoreCheckIDs is an optional list of health check IDs to ignore when
	// considering which nodes are healthy. It is useful as an emergency measure
	// to temporarily override some health check that is producing false negatives
	// for example.
	IgnoreCheckIDs []string

	// If OnlyPassing is true then we will only include nodes with passing
	// health checks (critical AND warning checks will cause a node to be
	// discarded)
	OnlyPassing bool

	// Tags are a set of required and/or disallowed tags. If a tag is in
	// this list it must be present. If the tag is preceded with "!" then
	// it is disallowed.
	Tags []string

	// NodeMeta is a map of required node metadata fields. If a key/value
	// pair is in this map it must be present on the node in order for the
	// service entry to be returned.
	NodeMeta map[string]string

	// ServiceMeta is a map of required service metadata fields. If a key/value
	// pair is in this map it must be present on the node in order for the
	// service entry to be returned.
	ServiceMeta map[string]string

	// Connect if true will filter the prepared query results to only
	// include Connect-capable services. These include both native services
	// and proxies for matching services. Note that if a proxy matches,
	// the constraints in the query above (Near, OnlyPassing, etc.) apply
	// to the _proxy_ and not the service being proxied. In practice, proxies
	// should be directly next to their services so this isn't an issue.
	Connect bool
}

// QueryTemplate carries the arguments for creating a templated query.
type QueryTemplate struct {
	// Type specifies the type of the query template. Currently only
	// "name_prefix_match" is supported. This field is required.
	Type string

	// Regexp allows specifying a regex pattern to match against the name
	// of the query being executed.
	Regexp string
}

// PreparedQueryDefinition defines a complete prepared query.
type PreparedQueryDefinition struct {
	// ID is this UUID-based ID for the query, always generated by Consul.
	ID string

	// Name is an optional friendly name for the query supplied by the
	// user. NOTE - if this feature is used then it will reduce the security
	// of any read ACL associated with this query/service since this name
	// can be used to locate nodes with supplying any ACL.
	Name string

	// Session is an optional session to tie this query's lifetime to. If
	// this is omitted then the query will not expire.
	Session string

	// Token is the ACL token used when the query was created, and it is
	// used when a query is subsequently executed. This token, or a token
	// with management privileges, must be used to change the query later.
	Token string

	// Service defines a service query (leaving things open for other types
	// later).
	Service ServiceQuery

	// DNS has options that control how the results of this query are
	// served over DNS.
	DNS QueryDNSOptions

	// Template is used to pass through the arguments for creating a
	// prepared query with an attached template. If a template is given,
	// interpolations are possible in other struct fields.
	Template QueryTemplate
}

// PreparedQueryExecuteResponse has the results of executing a query.
type PreparedQueryExecuteResponse struct {
	// Service is the service that was queried.
	Service string

	// Nodes has the nodes that were output by the query.
	Nodes []ServiceEntry

	// DNS has the options for serving these results over DNS.
	DNS QueryDNSOptions

	// Datacenter is the datacenter that these results came from.
	Datacenter string

	// Failovers is a count of how many times we had to query a remote
	// datacenter.
	Failovers int
}

// PreparedQuery can be used to query the prepared query endpoints.
type PreparedQuery struct {
	c *Client
}

// PreparedQuery returns a handle to the prepared query endpoints.
func (c *Client) PreparedQuery() *PreparedQuery {
	return &PreparedQuery{c}
}

// Create makes a new prepared query. The ID of the new query is returned.
func (c *PreparedQuery) Create(query *PreparedQueryDefinition, q *WriteOptions) (string, *WriteMeta, error) {
	r := c.c.newRequest("POST", "/v1/query")
	r.setWriteOptions(q)
	r.obj = query
	rtt, resp, err := requireOK(c.c.doRequest(r))
	if err != nil {
		return "", nil, err
	}
	defer resp.Body.Close()

	wm := &WriteMeta{}
	wm.RequestTime = rtt

	var out struct{ ID string }
	if err := decodeBody(resp, &out); err != nil {
		return "", nil, err
	}
	return out.ID, wm, nil
}

// Update makes updates to an existing prepared query.
func (c *PreparedQuery) Update(query *PreparedQueryDefinition, q *WriteOptions) (*WriteMeta, error) {
	return c.c.write("/v1/query/"+query.ID, query, nil, q)
}

// List is used to fetch all the prepared queries (always requires a management
// token).
func (c *PreparedQuery) List(q *QueryOptions) ([]*PreparedQueryDefinition, *QueryMeta, error) {
	var out []*PreparedQueryDefinition
	qm, err := c.c.query("/v1/query", &out, q)
	if err != nil {
		return nil, nil, err
	}
	return out, qm, nil
}

// Get is used to fetch a specific prepared query.
func (c *PreparedQuery) Get(queryID string, q *QueryOptions) ([]*PreparedQueryDefinition, *QueryMeta, error) {
	var out []*PreparedQueryDefinition
	qm, err := c.c.query("/v1/query/"+queryID, &out, q)
	if err != nil {
		return nil, nil, err
	}
	return out, qm, nil
}

// Delete is used to delete a specific prepared query.
func (c *PreparedQuery) Delete(queryID string, q *WriteOptions) (*WriteMeta, error) {
	r := c.c.newRequest("DELETE", "/v1/query/"+queryID)
	r.setWriteOptions(q)
	rtt, resp, err := requireOK(c.c.doRequest(r))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	wm := &WriteMeta{}
	wm.RequestTime = rtt
	return wm, nil
}

// Execute is used to execute a specific prepared query. You can execute using
// a query ID or name.
func (c *PreparedQuery) Execute(queryIDOrName string, q *QueryOptions) (*PreparedQueryExecuteResponse, *QueryMeta, error) {
	var out *PreparedQueryExecuteResponse
	qm, err := c.c.query("/v1/query/"+queryIDOrName+"/execute", &out, q)
	if err != nil {
		return nil, nil, err
	}
	return out, qm, nil
}