2015-11-14 02:07:35 +00:00
|
|
|
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
|
2015-11-17 16:29:20 +00:00
|
|
|
// this list it must be present. If the tag is preceded with "!" then
|
2015-11-14 02:07:35 +00:00
|
|
|
// 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) {
|
2015-11-17 07:12:44 +00:00
|
|
|
return c.c.write("/v1/query/"+query.ID, query, nil, q)
|
2015-11-14 02:07:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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
|
2015-11-17 07:12:44 +00:00
|
|
|
qm, err := c.c.query("/v1/query", &out, q)
|
|
|
|
if err != nil {
|
2015-11-14 02:07:35 +00:00
|
|
|
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
|
2015-11-17 07:12:44 +00:00
|
|
|
qm, err := c.c.query("/v1/query/"+queryID, &out, q)
|
|
|
|
if err != nil {
|
2015-11-14 02:07:35 +00:00
|
|
|
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
|
2015-11-17 07:12:44 +00:00
|
|
|
qm, err := c.c.query("/v1/query/"+queryIDOrName+"/execute", &out, q)
|
|
|
|
if err != nil {
|
2015-11-14 02:07:35 +00:00
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
return out, qm, nil
|
|
|
|
}
|