1package structs 2 3import ( 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. 13type 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. 25type 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. 32type 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 // EnterpriseMeta is the embedded enterprise metadata 81 EnterpriseMeta `hcl:",squash" mapstructure:",squash"` 82} 83 84const ( 85 // QueryTemplateTypeNamePrefixMatch uses the Name field of the query as 86 // a prefix to select the template. 87 QueryTemplateTypeNamePrefixMatch = "name_prefix_match" 88) 89 90// QueryTemplateOptions controls settings if this query is a template. 91type QueryTemplateOptions struct { 92 // Type, if non-empty, means that this query is a template. This is 93 // set to one of the QueryTemplateType* constants above. 94 Type string 95 96 // Regexp is an optional regular expression to use to parse the full 97 // name, once the prefix match has selected a template. This can be 98 // used to extract parts of the name and choose a service name, set 99 // tags, etc. 100 Regexp string 101 102 // RemoveEmptyTags, if true, removes empty tags from matched tag list 103 RemoveEmptyTags bool 104} 105 106// PreparedQuery defines a complete prepared query, and is the structure we 107// maintain in the state store. 108type PreparedQuery struct { 109 // ID is this UUID-based ID for the query, always generated by Consul. 110 ID string 111 112 // Name is an optional friendly name for the query supplied by the 113 // user. NOTE - if this feature is used then it will reduce the security 114 // of any read ACL associated with this query/service since this name 115 // can be used to locate nodes with supplying any ACL. 116 Name string 117 118 // Session is an optional session to tie this query's lifetime to. If 119 // this is omitted then the query will not expire. 120 Session string 121 122 // Token is the ACL token used when the query was created, and it is 123 // used when a query is subsequently executed. This token, or a token 124 // with management privileges, must be used to change the query later. 125 Token string 126 127 // Template is used to configure this query as a template, which will 128 // respond to queries based on the Name, and then will be rendered 129 // before it is executed. 130 Template QueryTemplateOptions 131 132 // Service defines a service query (leaving things open for other types 133 // later). 134 Service ServiceQuery 135 136 // DNS has options that control how the results of this query are 137 // served over DNS. 138 DNS QueryDNSOptions 139 140 RaftIndex 141} 142 143// GetACLPrefix returns the prefix to look up the prepared_query ACL policy for 144// this query, and whether the prefix applies to this query. You always need to 145// check the ok value before using the prefix. 146func (pq *PreparedQuery) GetACLPrefix() (string, bool) { 147 if pq.Name != "" || pq.Template.Type != "" { 148 return pq.Name, true 149 } 150 151 return "", false 152} 153 154type PreparedQueries []*PreparedQuery 155 156type IndexedPreparedQueries struct { 157 Queries PreparedQueries 158 QueryMeta 159} 160 161type PreparedQueryOp string 162 163const ( 164 PreparedQueryCreate PreparedQueryOp = "create" 165 PreparedQueryUpdate PreparedQueryOp = "update" 166 PreparedQueryDelete PreparedQueryOp = "delete" 167) 168 169// QueryRequest is used to create or change prepared queries. 170type PreparedQueryRequest struct { 171 // Datacenter is the target this request is intended for. 172 Datacenter string 173 174 // Op is the operation to apply. 175 Op PreparedQueryOp 176 177 // Query is the query itself. 178 Query *PreparedQuery 179 180 // WriteRequest holds the ACL token to go along with this request. 181 WriteRequest 182} 183 184// RequestDatacenter returns the datacenter for a given request. 185func (q *PreparedQueryRequest) RequestDatacenter() string { 186 return q.Datacenter 187} 188 189// PreparedQuerySpecificRequest is used to get information about a prepared 190// query. 191type PreparedQuerySpecificRequest struct { 192 // Datacenter is the target this request is intended for. 193 Datacenter string 194 195 // QueryID is the ID of a query. 196 QueryID string 197 198 // QueryOptions (unfortunately named here) controls the consistency 199 // settings for the query lookup itself, as well as the service lookups. 200 QueryOptions 201} 202 203// RequestDatacenter returns the datacenter for a given request. 204func (q *PreparedQuerySpecificRequest) RequestDatacenter() string { 205 return q.Datacenter 206} 207 208// PreparedQueryExecuteRequest is used to execute a prepared query. 209type PreparedQueryExecuteRequest struct { 210 // Datacenter is the target this request is intended for. 211 Datacenter string 212 213 // QueryIDOrName is the ID of a query _or_ the name of one, either can 214 // be provided. 215 QueryIDOrName string 216 217 // Limit will trim the resulting list down to the given limit. 218 Limit int 219 220 // Connect will force results to be Connect-enabled nodes for the 221 // matching services. This is equivalent in semantics exactly to 222 // setting "Connect" in the query template itself, but allows callers 223 // to use any prepared query in a Connect setting. 224 Connect bool 225 226 // Source is used to sort the results relative to a given node using 227 // network coordinates. 228 Source QuerySource 229 230 // Agent is used to carry around a reference to the agent which initiated 231 // the execute request. Used to distance-sort relative to the local node. 232 Agent QuerySource 233 234 // QueryOptions (unfortunately named here) controls the consistency 235 // settings for the query lookup itself, as well as the service lookups. 236 QueryOptions 237} 238 239// RequestDatacenter returns the datacenter for a given request. 240func (q *PreparedQueryExecuteRequest) RequestDatacenter() string { 241 return q.Datacenter 242} 243 244// CacheInfo implements cache.Request allowing requests to be cached on agent. 245func (q *PreparedQueryExecuteRequest) CacheInfo() cache.RequestInfo { 246 info := cache.RequestInfo{ 247 Token: q.Token, 248 Datacenter: q.Datacenter, 249 MinIndex: q.MinQueryIndex, 250 Timeout: q.MaxQueryTime, 251 MaxAge: q.MaxAge, 252 MustRevalidate: q.MustRevalidate, 253 } 254 255 // To calculate the cache key we hash over all the fields that affect the 256 // output other than Datacenter and Token which are dealt with in the cache 257 // framework already. Note the order here is important for the outcome - if we 258 // ever care about cache-invalidation on updates e.g. because we persist 259 // cached results, we need to be careful we maintain the same order of fields 260 // here. We could alternatively use `hash:set` struct tag on an anonymous 261 // struct to make it more robust if it becomes significant. 262 v, err := hashstructure.Hash([]interface{}{ 263 q.QueryIDOrName, 264 q.Limit, 265 q.Connect, 266 }, nil) 267 if err == nil { 268 // If there is an error, we don't set the key. A blank key forces 269 // no cache for this request so the request is forwarded directly 270 // to the server. 271 info.Key = strconv.FormatUint(v, 10) 272 } 273 274 return info 275} 276 277// PreparedQueryExecuteRemoteRequest is used when running a local query in a 278// remote datacenter. 279type PreparedQueryExecuteRemoteRequest struct { 280 // Datacenter is the target this request is intended for. 281 Datacenter string 282 283 // Query is a copy of the query to execute. We have to ship the entire 284 // query over since it won't be present in the remote state store. 285 Query PreparedQuery 286 287 // Limit will trim the resulting list down to the given limit. 288 Limit int 289 290 // Connect is the same as ExecuteRequest. 291 Connect bool 292 293 // QueryOptions (unfortunately named here) controls the consistency 294 // settings for the the service lookups. 295 QueryOptions 296} 297 298// RequestDatacenter returns the datacenter for a given request. 299func (q *PreparedQueryExecuteRemoteRequest) RequestDatacenter() string { 300 return q.Datacenter 301} 302 303// PreparedQueryExecuteResponse has the results of executing a query. 304type PreparedQueryExecuteResponse struct { 305 // Service is the service that was queried. 306 Service string 307 308 // EnterpriseMeta of the service that was queried. 309 EnterpriseMeta 310 311 // Nodes has the nodes that were output by the query. 312 Nodes CheckServiceNodes 313 314 // DNS has the options for serving these results over DNS. 315 DNS QueryDNSOptions 316 317 // Datacenter is the datacenter that these results came from. 318 Datacenter string 319 320 // Failovers is a count of how many times we had to query a remote 321 // datacenter. 322 Failovers int 323 324 // QueryMeta has freshness information about the query. 325 QueryMeta 326} 327 328// PreparedQueryExplainResponse has the results when explaining a query/ 329type PreparedQueryExplainResponse struct { 330 // Query has the fully-rendered query. 331 Query PreparedQuery 332 333 // QueryMeta has freshness information about the query. 334 QueryMeta 335} 336