-
Notifications
You must be signed in to change notification settings - Fork 4.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consul prepared queries #1389
Merged
Merged
Consul prepared queries #1389
Changes from all commits
Commits
Show all changes
55 commits
Select commit
Hold shift + click to select a range
ce0881a
Adds a new management ACL for prepared queries.
7babcef
Changes structs and state store for prepared queries.
989619c
Moves DNS over to new shuffle and filter functions.
1f87480
Adds a better shuffle test (similar to DNS).
1d1865d
Factors code for pulling the sorted list of DCs into a common place.
b736bc4
Adds basic structure for prepared queries (needs tests).
81bb397
Adds prefix "prepared" to everything prepared query-related.
c41a3d6
Changes "not" prefix from "~" to "!".
7ca3f0a
Adds an explicit ACL check that will fail vs. trying other DCs.
2f34b51
Moves sort to a query-time decision and adds back the limit.
666619d
Skips unknown DCs during queries and chugs along in the face of errors.
0bd7e82
Clarifies comment about name vs. ID.
58bb6e8
Checks for valid UUIDs before calling in to index function.
333da2a
Adds lookup and list endpoints and basic end-to-end apply test.
8222d3f
Completes non-ACL version of apply test.
d4d866c
Adds ACL cases for apply.
519666a
Adds query parsing unit tests.
fa414a2
Adds tests for query lookup and list endpoints.
7ded6c7
Adds a leader forwarding case for prepared queries.
a9e9d5e
Adds execute leader forward test for prepared queries.
86ead89
Removes unused ACL filter.
30a1822
Adds status information about failovers to query results.
1417053
Adds execute tests for prepared queries.
eefdb56
Adds tag filter tests.
bbc5185
Adds a test for the server wrapper.
d06e2a5
Adds test for remote datacenter selection and query logic.
a57d642
Always increments the failovers counter, even for error-ed DCs.
7af41ed
Changes Lookup to Get since we don't need it (only Execute does).
5d06a87
Adds an RPC endpoint injection method for testing.
57be551
Adds an HTTP endpoint for prepared queries.
8e1bea0
Completes FSM support for prepared queries.
34b685c
Adds a unit test for the new RTT getDatacentersByDistance fn.
c955799
Makes an empty prepared query list an empty slice, not a nil one.
6634cd6
Adds query metadata to prepared query execute response.
da20e66
Adds a note about obfuscating query name/ID from the logs.
5e7523e
Adds a slightly more flexible mock system so we can test DNS.
4a0a60a
Adds DNS support for prepared queries (needs tests).
81b4313
Adds unit tests for prepared queries and DNS, using existing tests fo…
e9480ec
Plumbs the service name back and uses agent-specific TTL settings as …
67fd4fa
Returns a 404 from a get or execute of a nonexistent query.
4715c04
Adds a test to make sure a stale retry terminates.
f60fc87
Gets rid of some unused constants.
712a3db
Adds API client support for prepared queries.
800e946
Adds and updates docs for prepared queries.
162c6ba
Updates the changelog.
46d5afa
Adds a test to ensure we don't return a nil slice.
b8ddb21
Adds a paranoia set of the nodes slice to nil.
e1ce1a3
Moves conversion of nil slices up to HTTP layer for prepared queries.
06b918e
Makes UUID regex case-insensitive.
8fc6a6a
Switches to helpers for prepared query API wrappers.
1059a8b
Removes a useless empty import and fixes some stale comments.
cd6be4a
Avoids taking the length again when parsing DNS queries.
049da2c
Breaks up huge HTTP endpoint functions.
533e6fc
Returns a zero index for a lookup error case.
e3ef204
Makes all the query ops the correct type.
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
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 | ||
|
||
// Failover controls what we do if there are no healthy nodes in the | ||
// local datacenter. | ||
Failover QueryDatacenterOptions | ||
|
||
// 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 | ||
} | ||
|
||
// PrepatedQueryDefinition 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 | ||
} | ||
|
||
// 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 *QueryOptions) (*QueryMeta, error) { | ||
r := c.c.newRequest("DELETE", "/v1/query/"+queryID) | ||
r.setQueryOptions(q) | ||
rtt, resp, err := requireOK(c.c.doRequest(r)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
defer resp.Body.Close() | ||
|
||
qm := &QueryMeta{} | ||
parseQueryMeta(resp, qm) | ||
qm.RequestTime = rtt | ||
return qm, 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 | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I may find the answer to this as I get further in, but the user should be required to pass a valid token with privileges to modify at modification/removal time as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep - this should be enforced down in
PreparedQuery.Apply()
.