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 // Namespace of the service to query 29 Namespace string `json:",omitempty"` 30 31 // Near allows baking in the name of a node to automatically distance- 32 // sort from. The magic "_agent" value is supported, which sorts near 33 // the agent which initiated the request by default. 34 Near string 35 36 // Failover controls what we do if there are no healthy nodes in the 37 // local datacenter. 38 Failover QueryDatacenterOptions 39 40 // IgnoreCheckIDs is an optional list of health check IDs to ignore when 41 // considering which nodes are healthy. It is useful as an emergency measure 42 // to temporarily override some health check that is producing false negatives 43 // for example. 44 IgnoreCheckIDs []string 45 46 // If OnlyPassing is true then we will only include nodes with passing 47 // health checks (critical AND warning checks will cause a node to be 48 // discarded) 49 OnlyPassing bool 50 51 // Tags are a set of required and/or disallowed tags. If a tag is in 52 // this list it must be present. If the tag is preceded with "!" then 53 // it is disallowed. 54 Tags []string 55 56 // NodeMeta is a map of required node metadata fields. If a key/value 57 // pair is in this map it must be present on the node in order for the 58 // service entry to be returned. 59 NodeMeta map[string]string 60 61 // ServiceMeta is a map of required service metadata fields. If a key/value 62 // pair is in this map it must be present on the node in order for the 63 // service entry to be returned. 64 ServiceMeta map[string]string 65 66 // Connect if true will filter the prepared query results to only 67 // include Connect-capable services. These include both native services 68 // and proxies for matching services. Note that if a proxy matches, 69 // the constraints in the query above (Near, OnlyPassing, etc.) apply 70 // to the _proxy_ and not the service being proxied. In practice, proxies 71 // should be directly next to their services so this isn't an issue. 72 Connect bool 73} 74 75// QueryTemplate carries the arguments for creating a templated query. 76type QueryTemplate struct { 77 // Type specifies the type of the query template. Currently only 78 // "name_prefix_match" is supported. This field is required. 79 Type string 80 81 // Regexp allows specifying a regex pattern to match against the name 82 // of the query being executed. 83 Regexp string 84} 85 86// PreparedQueryDefinition defines a complete prepared query. 87type PreparedQueryDefinition struct { 88 // ID is this UUID-based ID for the query, always generated by Consul. 89 ID string 90 91 // Name is an optional friendly name for the query supplied by the 92 // user. NOTE - if this feature is used then it will reduce the security 93 // of any read ACL associated with this query/service since this name 94 // can be used to locate nodes with supplying any ACL. 95 Name string 96 97 // Session is an optional session to tie this query's lifetime to. If 98 // this is omitted then the query will not expire. 99 Session string 100 101 // Token is the ACL token used when the query was created, and it is 102 // used when a query is subsequently executed. This token, or a token 103 // with management privileges, must be used to change the query later. 104 Token string 105 106 // Service defines a service query (leaving things open for other types 107 // later). 108 Service ServiceQuery 109 110 // DNS has options that control how the results of this query are 111 // served over DNS. 112 DNS QueryDNSOptions 113 114 // Template is used to pass through the arguments for creating a 115 // prepared query with an attached template. If a template is given, 116 // interpolations are possible in other struct fields. 117 Template QueryTemplate 118} 119 120// PreparedQueryExecuteResponse has the results of executing a query. 121type PreparedQueryExecuteResponse struct { 122 // Service is the service that was queried. 123 Service string 124 125 // Namespace of the service that was queried 126 Namespace string `json:",omitempty"` 127 128 // Nodes has the nodes that were output by the query. 129 Nodes []ServiceEntry 130 131 // DNS has the options for serving these results over DNS. 132 DNS QueryDNSOptions 133 134 // Datacenter is the datacenter that these results came from. 135 Datacenter string 136 137 // Failovers is a count of how many times we had to query a remote 138 // datacenter. 139 Failovers int 140} 141 142// PreparedQuery can be used to query the prepared query endpoints. 143type PreparedQuery struct { 144 c *Client 145} 146 147// PreparedQuery returns a handle to the prepared query endpoints. 148func (c *Client) PreparedQuery() *PreparedQuery { 149 return &PreparedQuery{c} 150} 151 152// Create makes a new prepared query. The ID of the new query is returned. 153func (c *PreparedQuery) Create(query *PreparedQueryDefinition, q *WriteOptions) (string, *WriteMeta, error) { 154 r := c.c.newRequest("POST", "/v1/query") 155 r.setWriteOptions(q) 156 r.obj = query 157 rtt, resp, err := requireOK(c.c.doRequest(r)) 158 if err != nil { 159 return "", nil, err 160 } 161 defer closeResponseBody(resp) 162 163 wm := &WriteMeta{} 164 wm.RequestTime = rtt 165 166 var out struct{ ID string } 167 if err := decodeBody(resp, &out); err != nil { 168 return "", nil, err 169 } 170 return out.ID, wm, nil 171} 172 173// Update makes updates to an existing prepared query. 174func (c *PreparedQuery) Update(query *PreparedQueryDefinition, q *WriteOptions) (*WriteMeta, error) { 175 return c.c.write("/v1/query/"+query.ID, query, nil, q) 176} 177 178// List is used to fetch all the prepared queries (always requires a management 179// token). 180func (c *PreparedQuery) List(q *QueryOptions) ([]*PreparedQueryDefinition, *QueryMeta, error) { 181 var out []*PreparedQueryDefinition 182 qm, err := c.c.query("/v1/query", &out, q) 183 if err != nil { 184 return nil, nil, err 185 } 186 return out, qm, nil 187} 188 189// Get is used to fetch a specific prepared query. 190func (c *PreparedQuery) Get(queryID string, q *QueryOptions) ([]*PreparedQueryDefinition, *QueryMeta, error) { 191 var out []*PreparedQueryDefinition 192 qm, err := c.c.query("/v1/query/"+queryID, &out, q) 193 if err != nil { 194 return nil, nil, err 195 } 196 return out, qm, nil 197} 198 199// Delete is used to delete a specific prepared query. 200func (c *PreparedQuery) Delete(queryID string, q *WriteOptions) (*WriteMeta, error) { 201 r := c.c.newRequest("DELETE", "/v1/query/"+queryID) 202 r.setWriteOptions(q) 203 rtt, resp, err := requireOK(c.c.doRequest(r)) 204 if err != nil { 205 return nil, err 206 } 207 defer closeResponseBody(resp) 208 209 wm := &WriteMeta{} 210 wm.RequestTime = rtt 211 return wm, nil 212} 213 214// Execute is used to execute a specific prepared query. You can execute using 215// a query ID or name. 216func (c *PreparedQuery) Execute(queryIDOrName string, q *QueryOptions) (*PreparedQueryExecuteResponse, *QueryMeta, error) { 217 var out *PreparedQueryExecuteResponse 218 qm, err := c.c.query("/v1/query/"+queryIDOrName+"/execute", &out, q) 219 if err != nil { 220 return nil, nil, err 221 } 222 return out, qm, nil 223} 224