rs_consul/types.rs
1/*
2MIT License
3
4Copyright (c) 2023 Roblox
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23 */
24
25use std::collections::HashMap;
26use std::time::Duration;
27
28use serde::{self, Deserialize, Serialize, Serializer};
29use smart_default::SmartDefault;
30
31// TODO retrofit other get APIs to use this struct
32/// Query options for Consul endpoints.
33#[derive(Debug, Clone)]
34pub struct QueryOptions {
35 /// Specifies the namespace to use.
36 /// If not provided, the namespace will be inferred from the request's ACL token, or will default to the default namespace.
37 /// This is specified as part of the URL as a query parameter. Added in Consul 1.7.0.
38 /// NOTE: usage of this query parameter requires Consul enterprise.
39 pub namespace: Option<String>,
40 /// Specifies the datacenter to query.
41 /// This will default to the datacenter of the agent being queried.
42 /// This is specified as part of the URL as a query parameter.
43 pub datacenter: Option<String>,
44 /// The timeout to apply to the query, if any, defaults to 5s.
45 pub timeout: Option<Duration>,
46 /// The index to supply as a query parameter, if the endpoint supports blocking queries.
47 pub index: Option<u64>,
48 /// The time to block for, when used in association with an index, if the endpoint supports blocking queries.
49 /// Server side default of 5 minute is applied if not specified, with a limit of 10 minutes and maximum granularity of seconds.
50 pub wait: Option<Duration>,
51}
52impl Default for QueryOptions {
53 fn default() -> Self {
54 Self {
55 namespace: None,
56 datacenter: None,
57 timeout: Some(Duration::from_secs(5)),
58 index: None,
59 wait: None,
60 }
61 }
62}
63
64/// Encapsulates a consul query response and the returned metadata, if any.
65#[derive(Debug)]
66pub struct ResponseMeta<T> {
67 /// Query response.
68 pub response: T,
69 /// The index returned from the consul query via the X-Consul-Index header.
70 pub index: u64,
71}
72
73/// Represents a request to delete a key or all keys sharing a prefix from Consul's Key Value store.
74#[derive(Clone, Debug, SmartDefault, Serialize, Deserialize, PartialEq, bon::Builder)]
75pub struct DeleteKeyRequest<'a> {
76 /// Specifies the path of the key to delete.
77 pub key: &'a str,
78 /// Specifies the datacenter to query. This will default to the datacenter of the agent being queried.
79 #[builder(default)]
80 pub datacenter: &'a str,
81 /// Specifies to delete all keys which have the specified prefix.
82 /// Without this, only a key with an exact match will be deleted.
83 #[builder(default)]
84 pub recurse: bool,
85 /// Specifies to use a Check-And-Set operation.
86 /// This is very useful as a building block for more complex synchronization primitives.
87 /// The index must be greater than 0 for Consul to take any action: a 0 index will not delete the key.
88 /// If the index is non-zero, the key is only deleted if the index matches the ModifyIndex of that key.
89 #[builder(default)]
90 pub check_and_set: u32,
91 /// Specifies the namespace to query.
92 /// If not provided, the namespace will be inferred from the request's ACL token, or will default to the default namespace.
93 #[builder(default)]
94 pub namespace: &'a str,
95}
96
97/// Represents a request to read a key from Consul's Key Value store.
98#[derive(Clone, Debug, SmartDefault, Serialize, Deserialize, PartialEq, bon::Builder)]
99pub struct ReadKeyRequest<'a> {
100 /// Specifies the path of the key to read.
101 pub key: &'a str,
102 /// Specifies the namespace to query.
103 /// If not provided, the namespace will be inferred from the request's ACL token, or will default to the default namespace.
104 /// For recursive lookups, the namespace may be specified as '*' and then results will be returned for all namespaces. Added in Consul 1.7.0.
105 #[builder(default)]
106 pub namespace: &'a str,
107 /// Specifies the datacenter to query.
108 /// This will default to the datacenter of the agent being queried.
109 #[builder(default)]
110 pub datacenter: &'a str,
111 /// Specifies if the lookup should be recursive and key treated as a prefix instead of a literal match.
112 #[builder(default)]
113 pub recurse: bool,
114 /// Specifies the string to use as a separator for recursive key lookups.
115 /// This option is only used when paired with the keys parameter to limit the prefix of keys returned, only up to the given separator.
116 #[builder(default)]
117 pub separator: &'a str,
118 /// The consistency mode for reads. See also [ConsistencyMode](consul::types::ConsistencyMode)
119 #[builder(default)]
120 pub consistency: ConsistencyMode,
121 /// Endpoints that support blocking queries return an HTTP header named X-Consul-Index.
122 /// This is a unique identifier representing the current state of the requested resource.
123 /// On subsequent requests for this resource, the client can set the index query string parameter to the value of X-Consul-Index, indicating that the client wishes to wait for any changes subsequent to that index.
124 pub index: Option<u64>,
125 /// The time to wait for watching a lock in a blocking fashion.
126 #[builder(default)]
127 pub wait: Duration,
128}
129
130/// Represents a request to read a key from Consul's Key Value store.
131#[derive(Clone, Debug, SmartDefault, Serialize, Deserialize, PartialEq, bon::Builder)]
132pub struct LockWatchRequest<'a> {
133 /// Specifies the path of the key to read.
134 pub key: &'a str,
135 /// Specifies the datacenter to query.
136 /// This will default to the datacenter of the agent being queried.
137 #[builder(default)]
138 pub datacenter: &'a str,
139 /// Specifies the namespace to query.
140 /// If not provided, the namespace will be inferred from the request's ACL token, or will default to the default namespace.
141 /// For recursive lookups, the namespace may be specified as '*' and then results will be returned for all namespaces. Added in Consul 1.7.0.
142 #[builder(default)]
143 pub namespace: &'a str,
144 /// The consistency mode for reads. See also [ConsistencyMode](consul::types::ConsistencyMode)
145 #[builder(default)]
146 pub consistency: ConsistencyMode,
147 /// Endpoints that support blocking queries return an HTTP header named X-Consul-Index.
148 /// This is a unique identifier representing the current state of the requested resource.
149 /// On subsequent requests for this resource, the client can set the index query string parameter to the value of X-Consul-Index, indicating that the client wishes to wait for any changes subsequent to that index.
150 pub index: Option<u64>,
151 /// The time to wait for watching a lock in a blocking fashion.
152 #[builder(default)]
153 pub wait: Duration,
154}
155
156/// Represents a request to read a key from Consul Key Value store.
157#[derive(Clone, Debug, SmartDefault, Serialize, Deserialize, PartialEq, bon::Builder)]
158pub struct CreateOrUpdateKeyRequest<'a> {
159 /// Specifies the path of the key.
160 pub key: &'a str,
161 /// Specifies the namespace to query.
162 /// If not provided, the namespace will be inferred from the request's ACL token, or will default to the default namespace.
163 /// This is specified as part of the URL as a query parameter. Added in Consul 1.7.0.
164 #[builder(default)]
165 pub namespace: &'a str,
166 /// Specifies the datacenter to query.
167 /// This will default to the datacenter of the agent being queried.
168 #[builder(default)]
169 pub datacenter: &'a str,
170 /// Specifies an unsigned value between 0 and (2^64)-1.
171 /// Clients can choose to use this however makes sense for their application.
172 #[builder(default)]
173 pub flags: u64,
174 /// Specifies to use a Check-And-Set operation.
175 /// This is very useful as a building block for more complex synchronization primitives.
176 /// If the index is 0, Consul will only put the key if it does not already exist.
177 /// If the index is non-zero, the key is only set if the index matches the ModifyIndex of that key.
178 pub check_and_set: Option<i64>,
179 /// Supply a session ID to use in a lock acquisition operation.
180 /// This is useful as it allows leader election to be built on top of Consul.
181 /// If the lock is not held and the session is valid, this increments the LockIndex and sets the Session value of the key in addition to updating the key contents.
182 /// A key does not need to exist to be acquired. If the lock is already held by the given session, then the LockIndex is not incremented but the key contents are updated.
183 /// This lets the current lock holder update the key contents without having to give up the lock and reacquire it.
184 /// Note that an update that does not include the acquire parameter will proceed normally even if another session has locked the key.
185 #[builder(default)]
186 pub acquire: &'a str,
187 /// Supply a session ID to use in a release operation.
188 /// This is useful when paired with ?acquire= as it allows clients to yield a lock.
189 /// This will leave the LockIndex unmodified but will clear the associated Session of the key.
190 /// The key must be held by this session to be unlocked.
191 #[builder(default)]
192 pub release: &'a str,
193}
194
195/// Represents a request to read a key from Consul Key Value store.
196#[derive(Clone, Debug, SmartDefault, Serialize, Deserialize, PartialEq)]
197#[serde(rename_all = "PascalCase")]
198pub struct ReadKeyResponse {
199 /// CreateIndex is the internal index value that represents when the entry was created.
200 pub create_index: i64,
201 /// ModifyIndex is the last index that modified this key.
202 /// It can be used to establish blocking queries by setting the ?index query parameter.
203 /// You can even perform blocking queries against entire subtrees of the KV store: if ?recurse is provided, the returned X-Consul-Index corresponds to the latest ModifyIndex within the prefix, and a blocking query using that ?index will wait until any key within that prefix is updated.
204 pub modify_index: i64,
205 /// LockIndex is the number of times this key has successfully been acquired in a lock.
206 /// If the lock is held, the Session key provides the session that owns the lock.
207 pub lock_index: i64,
208 /// Key is simply the full path of the entry.
209 pub key: String,
210 /// Flags is an opaque unsigned integer that can be attached to each entry.
211 /// Clients can choose to use this however makes sense for their application.
212 pub flags: u64,
213 /// Value is a base64-encoded blob of data.
214 pub value: Option<String>,
215 /// If a lock is held, the Session key provides the session that owns the lock.
216 pub session: Option<String>,
217}
218
219/// Represents a request to create a lock .
220#[derive(Clone, Debug, SmartDefault, Serialize, Deserialize, PartialEq, Copy, bon::Builder)]
221#[serde(rename_all = "PascalCase")]
222pub struct LockRequest<'a> {
223 /// The key to use for locking.
224 pub key: &'a str,
225 /// The name of the session to use.
226 #[builder(default)]
227 pub session_id: &'a str,
228 /// Specifies the namespace to use.
229 /// If not provided, the namespace will be inferred from the request's ACL token, or will default to the default namespace.
230 /// This is specified as part of the URL as a query parameter. Added in Consul 1.7.0.
231 #[builder(default)]
232 pub namespace: &'a str,
233 /// Specifies the datacenter to query.
234 /// This will default to the datacenter of the agent being queried.
235 /// This is specified as part of the URL as a query parameter.
236 #[builder(default)]
237 pub datacenter: &'a str,
238 /// Specifies the duration of a session (between 10s and 86400s).
239 /// If provided, the session is invalidated if it is not renewed before the TTL expires.
240 /// The lowest practical TTL should be used to keep the number of managed sessions low.
241 /// When locks are forcibly expired, such as when following the leader election pattern in an application, sessions may not be reaped for up to double this TTL, so long TTL values (> 1 hour) should be avoided.
242 /// Defaults to 10 seconds.
243 #[default(_code = "Duration::from_secs(10)")]
244 #[builder(default = Duration::from_secs(10))]
245 pub timeout: Duration,
246 /// Controls the behavior to take when a session is invalidated. See also [LockExpirationBehavior](consul::types::LockExpirationBehavior)
247 #[builder(default)]
248 pub behavior: LockExpirationBehavior,
249 /// Specifies the duration for the lock delay.
250 /// Defaults to 1 second.
251 #[default(_code = "Duration::from_secs(1)")]
252 #[builder(default = Duration::from_secs(1))]
253 pub lock_delay: Duration,
254}
255
256/// Controls the behavior of locks when a session is invalidated. See [consul docs](https://www.consul.io/api-docs/session#behavior) for more information.
257#[derive(Clone, Debug, SmartDefault, Serialize, Deserialize, PartialEq, Copy)]
258#[serde(rename_all = "snake_case")]
259pub enum LockExpirationBehavior {
260 #[default]
261 /// Causes any locks that are held to be released when a session is invalidated.
262 Release,
263 /// Causes any locks that are held to be deleted when a session is invalidated.
264 Delete,
265}
266
267/// Most of the read query endpoints support multiple levels of consistency.
268/// Since no policy will suit all clients' needs, these consistency modes allow the user to have the ultimate say in how to balance the trade-offs inherent in a distributed system.
269#[derive(Clone, Debug, SmartDefault, Serialize, Deserialize, PartialEq)]
270#[serde(rename_all = "PascalCase")]
271pub enum ConsistencyMode {
272 /// If not specified, the default is strongly consistent in almost all cases.
273 /// However, there is a small window in which a new leader may be elected during which the old leader may service stale values.
274 /// The trade-off is fast reads but potentially stale values.
275 /// The condition resulting in stale reads is hard to trigger, and most clients should not need to worry about this case.
276 /// Also, note that this race condition only applies to reads, not writes.
277 #[default]
278 Default,
279 /// This mode is strongly consistent without caveats.
280 /// It requires that a leader verify with a quorum of peers that it is still leader.
281 /// This introduces an additional round-trip to all server nodes. The trade-off is increased latency due to an extra round trip.
282 /// Most clients should not use this unless they cannot tolerate a stale read.
283 Consistent,
284 /// This mode allows any server to service the read regardless of whether it is the leader.
285 /// This means reads can be arbitrarily stale; however, results are generally consistent to within 50 milliseconds of the leader.
286 /// The trade-off is very fast and scalable reads with a higher likelihood of stale values.
287 /// Since this mode allows reads without a leader, a cluster that is unavailable will still be able to respond to queries.
288 Stale,
289}
290
291#[derive(Clone, Debug, SmartDefault, Serialize, Deserialize, PartialEq, bon::Builder)]
292pub(crate) struct SessionResponse {
293 #[serde(rename = "ID")]
294 pub(crate) id: String,
295}
296
297#[derive(Clone, Debug, SmartDefault, Serialize, Deserialize, PartialEq)]
298#[serde(rename_all = "PascalCase")]
299pub(crate) struct CreateSessionRequest {
300 #[default(_code = "Duration::from_secs(0)")]
301 #[serde(serialize_with = "serialize_duration_as_string")]
302 pub(crate) lock_delay: Duration,
303 #[serde(skip_serializing_if = "std::string::String::is_empty")]
304 pub(crate) name: String,
305 #[serde(skip_serializing_if = "std::string::String::is_empty")]
306 pub(crate) node: String,
307 #[serde(skip_serializing_if = "std::vec::Vec::is_empty")]
308 pub(crate) checks: Vec<String>,
309 pub(crate) behavior: LockExpirationBehavior,
310 #[serde(rename = "TTL")]
311 #[default(_code = "Duration::from_secs(10)")]
312 #[serde(serialize_with = "serialize_duration_as_string")]
313 pub(crate) ttl: Duration,
314}
315
316/// Payload struct to register or update entries in consul's catalog.
317/// See https://www.consul.io/api-docs/catalog#register-entity for more information.
318#[allow(non_snake_case)]
319#[derive(Clone, Debug, Serialize, Deserialize, bon::Builder)]
320pub struct RegisterEntityPayload {
321 /// Optional UUID to assign to the node. This string is required to be 36-characters and UUID formatted.
322 #[serde(skip_serializing_if = "Option::is_none")]
323 pub ID: Option<String>,
324 /// Node ID to register.
325 pub Node: String,
326 /// The address to register.
327 pub Address: String,
328 /// The datacenter to register in, defaults to the agent's datacenter.
329 #[serde(skip_serializing_if = "Option::is_none")]
330 pub Datacenter: Option<String>,
331 /// Tagged addressed to register with.
332 #[serde(skip_serializing_if = "HashMap::is_empty")]
333 #[builder(default)]
334 pub TaggedAddresses: HashMap<String, String>,
335 /// KV metadata paris to register with.
336 #[serde(skip_serializing_if = "HashMap::is_empty")]
337 #[builder(default)]
338 pub NodeMeta: HashMap<String, String>,
339 /// Optional service to register.
340 #[serde(skip_serializing_if = "Option::is_none")]
341 pub Service: Option<RegisterEntityService>,
342 /// Checks to register.
343 #[serde(skip_serializing_if = "Vec::is_empty")]
344 #[builder(default)]
345 pub Checks: Vec<RegisterEntityCheck>,
346 /// Whether to skip updating the nodes information in the registration.
347 #[serde(skip_serializing_if = "Option::is_none")]
348 pub SkipNodeUpdate: Option<bool>,
349}
350
351/// The service to deregister with consul's global catalog.
352/// See https://www.consul.io/api/agent/service for more information.
353#[allow(non_snake_case)]
354#[derive(Clone, Debug, Serialize, Deserialize, bon::Builder)]
355pub struct DeregisterEntityPayload {
356 /// The node to execute the check on.
357 #[serde(skip_serializing_if = "Option::is_none")]
358 pub Node: Option<String>,
359 /// The datacenter to register in, defaults to the agent's datacenter.
360 #[serde(skip_serializing_if = "Option::is_none")]
361 pub Datacenter: Option<String>,
362 /// Specifies the ID of the check to remove.
363 #[serde(skip_serializing_if = "Option::is_none")]
364 pub CheckID: Option<String>,
365 /// Specifies the ID of the service to remove. The service and all associated checks will be removed.
366 #[serde(skip_serializing_if = "Option::is_none")]
367 pub ServiceID: Option<String>,
368 /// Specifies the namespace of the service and checks you deregister.
369 #[serde(skip_serializing_if = "Option::is_none")]
370 pub Namespace: Option<String>,
371}
372
373/// The service to register with consul's global catalog.
374/// See https://www.consul.io/api/agent/service for more information.
375#[allow(non_snake_case)]
376#[derive(Clone, Debug, Serialize, Deserialize, bon::Builder)]
377pub struct RegisterEntityService {
378 /// ID to register service will, defaults to Service.Service property.
379 #[serde(skip_serializing_if = "Option::is_none")]
380 pub ID: Option<String>,
381 /// The name of the service.
382 pub Service: String,
383 /// Optional tags associated with the service.
384 #[serde(skip_serializing_if = "Vec::is_empty")]
385 #[builder(default)]
386 pub Tags: Vec<String>,
387 /// Optional map of explicit LAN and WAN addresses for the service.
388 #[serde(skip_serializing_if = "HashMap::is_empty")]
389 #[builder(default)]
390 pub TaggedAddresses: HashMap<String, String>,
391 /// Optional key value meta associated with the service.
392 #[serde(skip_serializing_if = "HashMap::is_empty")]
393 #[builder(default)]
394 pub Meta: HashMap<String, String>,
395 /// The port of the service
396 #[serde(skip_serializing_if = "Option::is_none")]
397 pub Port: Option<u16>,
398 /// The consul namespace to register the service in.
399 #[serde(skip_serializing_if = "Option::is_none")]
400 pub Namespace: Option<String>,
401}
402
403/// Information related to registering a check.
404/// See https://www.consul.io/docs/discovery/checks for more information.
405#[allow(non_snake_case)]
406#[derive(Clone, Debug, Serialize, Deserialize, bon::Builder)]
407pub struct RegisterEntityCheck {
408 /// The node to execute the check on.
409 #[serde(skip_serializing_if = "Option::is_none")]
410 pub Node: Option<String>,
411 /// Optional check id, defaults to the name of the check.
412 #[serde(skip_serializing_if = "Option::is_none")]
413 pub CheckID: Option<String>,
414 /// The name associated with the check
415 pub Name: String,
416 /// Opaque field encapsulating human-readable text.
417 #[serde(skip_serializing_if = "Option::is_none")]
418 pub Notes: Option<String>,
419 /// The status of the check. Must be one of 'passing', 'warning', or 'critical'.
420 #[serde(skip_serializing_if = "Option::is_none")]
421 pub Status: Option<String>,
422 /// ID of the service this check is for. If no ID of a service running on the node is provided,
423 /// the check is treated as a node level check
424 #[serde(skip_serializing_if = "Option::is_none")]
425 pub ServiceID: Option<String>,
426 /// Details for a TCP or HTTP health check.
427 #[serde(skip_serializing_if = "HashMap::is_empty")]
428 #[builder(default)]
429 pub Definition: HashMap<String, String>,
430}
431
432/// Request for the nodes providing a specified service registered in Consul.
433/// See https://developer.hashicorp.com/consul/api-docs/catalog#list-nodes for more information.
434#[derive(Clone, Debug, SmartDefault, Serialize, Deserialize, PartialEq, bon::Builder)]
435pub struct GetNodesRequest<'a> {
436 /// Specifies a node name to sort the node list in ascending order based on the estimated round trip time from that node.
437 /// Passing `?near=_agent` will use the agent's node for the sort. This is specified as part of the URL as a query parameter.
438 /// Note that using `near` will ignore `use_streaming_backend` and always use blocking queries, because the data required to
439 /// sort the results is not available to the streaming backend.
440 pub near: Option<&'a str>,
441 /// (string: "") Specifies the expression used to filter the queries results prior to returning the data.
442 pub filter: Option<&'a str>,
443}
444
445#[allow(non_snake_case)]
446#[derive(Clone, Debug, SmartDefault, Serialize, Deserialize, PartialEq)]
447#[serde(rename_all = "PascalCase")]
448/// The node information of an instance providing a Consul service.
449pub struct CatalogNode {
450 /// The ID of the service node.
451 #[serde(rename = "ID")]
452 pub id: String,
453 /// The name of the Consul node on which the service is registered
454 pub node: String,
455 /// The IP address of the Consul node on which the service is registered.
456 pub address: String,
457 /// The datacenter where this node is running on.
458 pub datacenter: String,
459 /// Tagged addressed to register with.
460 #[serde(skip_serializing_if = "Option::is_none")]
461 pub TaggedAddresses: Option<HashMap<String, String>>,
462 /// Optional key value meta associated with the service.
463 #[serde(skip_serializing_if = "Option::is_none")]
464 pub Meta: Option<HashMap<String, String>>,
465}
466
467pub(crate) type GetNodesResponse = Vec<CatalogNode>;
468
469/// Request to retrieve information about nodes int the Consul catalog.
470#[derive(Clone, Debug, SmartDefault, Serialize, Deserialize, PartialEq, bon::Builder)]
471pub struct GetServiceNodesRequest<'a> {
472 /// Specifies the service to list services for. This is provided as part of the URL.
473 pub service: &'a str,
474 /// Specifies a node name to sort the node list in ascending order based on the estimated round trip time from that node.
475 /// Passing `?near=_agent` will use the agent's node for the sort. This is specified as part of the URL as a query parameter.
476 /// Note that using `near` will ignore `use_streaming_backend` and always use blocking queries, because the data required to
477 /// sort the results is not available to the streaming backend.
478 pub near: Option<&'a str>,
479 /// (bool: false) Specifies that the server should return only nodes with all checks in the passing state.
480 /// This can be used to avoid additional filtering on the client side.
481 #[builder(default)]
482 pub passing: bool,
483 /// (string: "") Specifies the expression used to filter the queries results prior to returning the data.
484 pub filter: Option<&'a str>,
485}
486
487pub(crate) type GetServiceNodesResponse = Vec<ServiceNode>;
488
489#[derive(Clone, Debug, SmartDefault, Serialize, Deserialize, PartialEq)]
490#[serde(rename_all = "PascalCase")]
491/// An instance of a node providing a Consul service.
492pub struct ServiceNode {
493 /// The Node information for this service
494 pub node: Node,
495 /// The Service information
496 pub service: Service,
497}
498
499#[derive(Clone, Debug, SmartDefault, Serialize, Deserialize, PartialEq)]
500#[serde(rename_all = "PascalCase")]
501/// The node information of an instance providing a Consul service.
502pub struct Node {
503 /// The ID of the service node.
504 #[serde(rename = "ID")]
505 pub id: String,
506 /// The name of the Consul node on which the service is registered
507 pub node: String,
508 /// The IP address of the Consul node on which the service is registered.
509 pub address: String,
510 /// The datacenter where this node is running on.
511 pub datacenter: String,
512}
513
514#[derive(Clone, Debug, SmartDefault, Serialize, Deserialize, PartialEq)]
515#[serde(rename_all = "PascalCase")]
516/// The service information of an instance providing a Consul service.
517pub struct Service {
518 /// The ID of the service instance, i.e. redis-1.
519 #[serde(rename = "ID")]
520 pub id: String,
521 /// The name of the service, i.e. redis.
522 pub service: String,
523 /// The address of the instance.
524 pub address: String,
525 /// The port of the instance.
526 pub port: u16,
527 /// Tags assigned to the service instance.
528 pub tags: Vec<String>,
529}
530
531pub(crate) fn serialize_duration_as_string<S>(
532 duration: &Duration,
533 serializer: S,
534) -> std::result::Result<S::Ok, S::Error>
535where
536 S: Serializer,
537{
538 let mut res = duration.as_secs().to_string();
539 res.push('s');
540 serializer.serialize_str(&res)
541}
542
543pub(crate) fn duration_as_string(duration: &Duration) -> String {
544 let mut res = duration.as_secs().to_string();
545 res.push('s');
546 res
547}