github.com/outbrain/consul@v1.4.5/agent/structs/prepared_query.go (about) 1 package structs 2 3 import ( 4 "strconv" 5 6 "github.com/hashicorp/consul/agent/cache" 7 "github.com/hashicorp/consul/types" 8 "github.com/mitchellh/hashstructure" 9 ) 10 11 // QueryDatacenterOptions sets options about how we fail over if there are no 12 // healthy nodes in the local datacenter. 13 type QueryDatacenterOptions struct { 14 // NearestN is set to the number of remote datacenters to try, based on 15 // network coordinates. 16 NearestN int 17 18 // Datacenters is a fixed list of datacenters to try after NearestN. We 19 // never try a datacenter multiple times, so those are subtracted from 20 // this list before proceeding. 21 Datacenters []string 22 } 23 24 // QueryDNSOptions controls settings when query results are served over DNS. 25 type QueryDNSOptions struct { 26 // TTL is the time to live for the served DNS results. 27 TTL string 28 } 29 30 // ServiceQuery is used to query for a set of healthy nodes offering a specific 31 // service. 32 type ServiceQuery struct { 33 // Service is the service to query. 34 Service string 35 36 // Failover controls what we do if there are no healthy nodes in the 37 // local datacenter. 38 Failover QueryDatacenterOptions 39 40 // If OnlyPassing is true then we will only include nodes with passing 41 // health checks (critical AND warning checks will cause a node to be 42 // discarded) 43 OnlyPassing bool 44 45 // IgnoreCheckIDs is an optional list of health check IDs to ignore when 46 // considering which nodes are healthy. It is useful as an emergency measure 47 // to temporarily override some health check that is producing false negatives 48 // for example. 49 IgnoreCheckIDs []types.CheckID 50 51 // Near allows the query to always prefer the node nearest the given 52 // node. If the node does not exist, results are returned in their 53 // normal randomly-shuffled order. Supplying the magic "_agent" value 54 // is supported to sort near the agent which initiated the request. 55 Near string 56 57 // Tags are a set of required and/or disallowed tags. If a tag is in 58 // this list it must be present. If the tag is preceded with "!" then 59 // it is disallowed. 60 Tags []string 61 62 // NodeMeta is a map of required node metadata fields. If a key/value 63 // pair is in this map it must be present on the node in order for the 64 // service entry to be returned. 65 NodeMeta map[string]string 66 67 // ServiceMeta is a map of required service metadata fields. If a key/value 68 // pair is in this map it must be present on the node in order for the 69 // service entry to be returned. 70 ServiceMeta map[string]string 71 72 // Connect if true will filter the prepared query results to only 73 // include Connect-capable services. These include both native services 74 // and proxies for matching services. Note that if a proxy matches, 75 // the constraints in the query above (Near, OnlyPassing, etc.) apply 76 // to the _proxy_ and not the service being proxied. In practice, proxies 77 // should be directly next to their services so this isn't an issue. 78 Connect bool 79 } 80 81 const ( 82 // QueryTemplateTypeNamePrefixMatch uses the Name field of the query as 83 // a prefix to select the template. 84 QueryTemplateTypeNamePrefixMatch = "name_prefix_match" 85 ) 86 87 // QueryTemplateOptions controls settings if this query is a template. 88 type QueryTemplateOptions struct { 89 // Type, if non-empty, means that this query is a template. This is 90 // set to one of the QueryTemplateType* constants above. 91 Type string 92 93 // Regexp is an optional regular expression to use to parse the full 94 // name, once the prefix match has selected a template. This can be 95 // used to extract parts of the name and choose a service name, set 96 // tags, etc. 97 Regexp string 98 99 // RemoveEmptyTags, if true, removes empty tags from matched tag list 100 RemoveEmptyTags bool 101 } 102 103 // PreparedQuery defines a complete prepared query, and is the structure we 104 // maintain in the state store. 105 type PreparedQuery struct { 106 // ID is this UUID-based ID for the query, always generated by Consul. 107 ID string 108 109 // Name is an optional friendly name for the query supplied by the 110 // user. NOTE - if this feature is used then it will reduce the security 111 // of any read ACL associated with this query/service since this name 112 // can be used to locate nodes with supplying any ACL. 113 Name string 114 115 // Session is an optional session to tie this query's lifetime to. If 116 // this is omitted then the query will not expire. 117 Session string 118 119 // Token is the ACL token used when the query was created, and it is 120 // used when a query is subsequently executed. This token, or a token 121 // with management privileges, must be used to change the query later. 122 Token string 123 124 // Template is used to configure this query as a template, which will 125 // respond to queries based on the Name, and then will be rendered 126 // before it is executed. 127 Template QueryTemplateOptions 128 129 // Service defines a service query (leaving things open for other types 130 // later). 131 Service ServiceQuery 132 133 // DNS has options that control how the results of this query are 134 // served over DNS. 135 DNS QueryDNSOptions 136 137 RaftIndex 138 } 139 140 // GetACLPrefix returns the prefix to look up the prepared_query ACL policy for 141 // this query, and whether the prefix applies to this query. You always need to 142 // check the ok value before using the prefix. 143 func (pq *PreparedQuery) GetACLPrefix() (string, bool) { 144 if pq.Name != "" || pq.Template.Type != "" { 145 return pq.Name, true 146 } 147 148 return "", false 149 } 150 151 type PreparedQueries []*PreparedQuery 152 153 type IndexedPreparedQueries struct { 154 Queries PreparedQueries 155 QueryMeta 156 } 157 158 type PreparedQueryOp string 159 160 const ( 161 PreparedQueryCreate PreparedQueryOp = "create" 162 PreparedQueryUpdate PreparedQueryOp = "update" 163 PreparedQueryDelete PreparedQueryOp = "delete" 164 ) 165 166 // QueryRequest is used to create or change prepared queries. 167 type PreparedQueryRequest struct { 168 // Datacenter is the target this request is intended for. 169 Datacenter string 170 171 // Op is the operation to apply. 172 Op PreparedQueryOp 173 174 // Query is the query itself. 175 Query *PreparedQuery 176 177 // WriteRequest holds the ACL token to go along with this request. 178 WriteRequest 179 } 180 181 // RequestDatacenter returns the datacenter for a given request. 182 func (q *PreparedQueryRequest) RequestDatacenter() string { 183 return q.Datacenter 184 } 185 186 // PreparedQuerySpecificRequest is used to get information about a prepared 187 // query. 188 type PreparedQuerySpecificRequest struct { 189 // Datacenter is the target this request is intended for. 190 Datacenter string 191 192 // QueryID is the ID of a query. 193 QueryID string 194 195 // QueryOptions (unfortunately named here) controls the consistency 196 // settings for the query lookup itself, as well as the service lookups. 197 QueryOptions 198 } 199 200 // RequestDatacenter returns the datacenter for a given request. 201 func (q *PreparedQuerySpecificRequest) RequestDatacenter() string { 202 return q.Datacenter 203 } 204 205 // PreparedQueryExecuteRequest is used to execute a prepared query. 206 type PreparedQueryExecuteRequest struct { 207 // Datacenter is the target this request is intended for. 208 Datacenter string 209 210 // QueryIDOrName is the ID of a query _or_ the name of one, either can 211 // be provided. 212 QueryIDOrName string 213 214 // Limit will trim the resulting list down to the given limit. 215 Limit int 216 217 // Connect will force results to be Connect-enabled nodes for the 218 // matching services. This is equivalent in semantics exactly to 219 // setting "Connect" in the query template itself, but allows callers 220 // to use any prepared query in a Connect setting. 221 Connect bool 222 223 // Source is used to sort the results relative to a given node using 224 // network coordinates. 225 Source QuerySource 226 227 // Agent is used to carry around a reference to the agent which initiated 228 // the execute request. Used to distance-sort relative to the local node. 229 Agent QuerySource 230 231 // QueryOptions (unfortunately named here) controls the consistency 232 // settings for the query lookup itself, as well as the service lookups. 233 QueryOptions 234 } 235 236 // RequestDatacenter returns the datacenter for a given request. 237 func (q *PreparedQueryExecuteRequest) RequestDatacenter() string { 238 return q.Datacenter 239 } 240 241 // CacheInfo implements cache.Request allowing requests to be cached on agent. 242 func (q *PreparedQueryExecuteRequest) CacheInfo() cache.RequestInfo { 243 info := cache.RequestInfo{ 244 Token: q.Token, 245 Datacenter: q.Datacenter, 246 MinIndex: q.MinQueryIndex, 247 Timeout: q.MaxQueryTime, 248 MaxAge: q.MaxAge, 249 MustRevalidate: q.MustRevalidate, 250 } 251 252 // To calculate the cache key we hash over all the fields that affect the 253 // output other than Datacenter and Token which are dealt with in the cache 254 // framework already. Note the order here is important for the outcome - if we 255 // ever care about cache-invalidation on updates e.g. because we persist 256 // cached results, we need to be careful we maintain the same order of fields 257 // here. We could alternatively use `hash:set` struct tag on an anonymous 258 // struct to make it more robust if it becomes significant. 259 v, err := hashstructure.Hash([]interface{}{ 260 q.QueryIDOrName, 261 q.Limit, 262 q.Connect, 263 }, nil) 264 if err == nil { 265 // If there is an error, we don't set the key. A blank key forces 266 // no cache for this request so the request is forwarded directly 267 // to the server. 268 info.Key = strconv.FormatUint(v, 10) 269 } 270 271 return info 272 } 273 274 // PreparedQueryExecuteRemoteRequest is used when running a local query in a 275 // remote datacenter. 276 type PreparedQueryExecuteRemoteRequest struct { 277 // Datacenter is the target this request is intended for. 278 Datacenter string 279 280 // Query is a copy of the query to execute. We have to ship the entire 281 // query over since it won't be present in the remote state store. 282 Query PreparedQuery 283 284 // Limit will trim the resulting list down to the given limit. 285 Limit int 286 287 // Connect is the same as ExecuteRequest. 288 Connect bool 289 290 // QueryOptions (unfortunately named here) controls the consistency 291 // settings for the the service lookups. 292 QueryOptions 293 } 294 295 // RequestDatacenter returns the datacenter for a given request. 296 func (q *PreparedQueryExecuteRemoteRequest) RequestDatacenter() string { 297 return q.Datacenter 298 } 299 300 // PreparedQueryExecuteResponse has the results of executing a query. 301 type PreparedQueryExecuteResponse struct { 302 // Service is the service that was queried. 303 Service string 304 305 // Nodes has the nodes that were output by the query. 306 Nodes CheckServiceNodes 307 308 // DNS has the options for serving these results over DNS. 309 DNS QueryDNSOptions 310 311 // Datacenter is the datacenter that these results came from. 312 Datacenter string 313 314 // Failovers is a count of how many times we had to query a remote 315 // datacenter. 316 Failovers int 317 318 // QueryMeta has freshness information about the query. 319 QueryMeta 320 } 321 322 // PreparedQueryExplainResponse has the results when explaining a query/ 323 type PreparedQueryExplainResponse struct { 324 // Query has the fully-rendered query. 325 Query PreparedQuery 326 327 // QueryMeta has freshness information about the query. 328 QueryMeta 329 }