Skip to content

Commit 49f29b5

Browse files
authored
Merge pull request #57 from x0rw/general-enhancements
Refactor project structure, separate concerns, and enhance usage documentation
2 parents ed6b451 + 1fedbdd commit 49f29b5

10 files changed

Lines changed: 818 additions & 636 deletions

File tree

Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,13 @@ hyper = { version = "1", features = ["full"] }
2424
hyper-rustls = { version = "0.27", default-features = false, features = ["webpki-roots", "ring", "http1"] }
2525
hyper-util = { version = "0.1", features = ["client", "client-legacy", "tokio", "http2"] }
2626
opentelemetry = { version = "0.28", optional = true }
27-
quick-error = "2"
2827
serde = { version = "1.0", features = ["derive"] }
2928
serde_json = "1.0"
3029
slog-scope = "4"
3130
smart-default = "0.7"
31+
thiserror = "2"
3232
tokio = { version = "1", features = ["full"] }
3333
ureq = { version = "3", features = ["json"] }
34+
35+
[dev-dependencies]
36+
tokio-test = "0.4" # Explicitly add if missing

README.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,69 @@ Simply include the rs-consul in your Cargo dependencies.
1515
[dependencies]
1616
rs-consul = "0.9.0"
1717
```
18+
## Usage
19+
Check [/examples](/examples) for more detailed usage
20+
### Initialize the client
21+
#### Environment Configuration (Recommended)
22+
The client can be configured automatically using environment variables:
23+
```rust
24+
use rs_consul::{types::*, Config, Consul};
25+
26+
let consul_config = Config::from_env();
27+
let consul = Consul::new(consul_config);
28+
```
29+
#### Manual Configuration
30+
Alternatively, you can configure the client manually:
31+
```rust
32+
let consul_config = Config {
33+
address: "http://localhost:8500".to_string(),
34+
token: None, // No token required in development mode
35+
..Default::default() // Uses default values for other settings
36+
};
37+
38+
let consul = Consul::new(consul_config);
39+
```
40+
### Register a Service
41+
```rust
42+
let node_id = "root-node"; //node name
43+
let service_name = "new-service-1"; //service name
44+
45+
let payload = RegisterEntityPayload {
46+
ID: None,
47+
Node: node_id.to_string(),
48+
Address: "127.0.0.1".to_string(), //server address
49+
Datacenter: None,
50+
TaggedAddresses: Default::default(),
51+
NodeMeta: Default::default(),
52+
Service: Some(RegisterEntityService {
53+
ID: None,
54+
Service: service_name.to_string(),
55+
Tags: vec![],
56+
TaggedAddresses: Default::default(),
57+
Meta: Default::default(),
58+
Port: Some(42424),
59+
Namespace: None,
60+
}),
61+
Check: None,
62+
SkipNodeUpdate: None,
63+
};
64+
65+
consul.register_entity(&payload).await.unwrap();
66+
```
67+
### Deregister a service
68+
```rust
69+
let node_id = "root-node";
70+
let service_name = "new-service-1";
71+
72+
let payload = DeregisterEntityPayload {
73+
Node: Some(node_id.to_string()),
74+
Datacenter: None,
75+
CheckID: None,
76+
ServiceID: Some(service_name.to_string()),
77+
Namespace: None,
78+
};
79+
consul.deregister_entity(&payload).await.unwrap();
80+
```
1881

1982
## Development
2083

examples/deregister_service.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
use rs_consul::{types::*, Config, Consul};
2+
3+
#[tokio::main] // Enables async main
4+
async fn main() {
5+
let consul_config = Config {
6+
address: "http://localhost:8500".to_string(),
7+
token: None, // Token is None in developpement mode
8+
..Default::default()
9+
};
10+
let consul = Consul::new(consul_config);
11+
12+
let node_id = "root-node";
13+
let service_name = "new-service-1";
14+
15+
let payload = DeregisterEntityPayload {
16+
Node: Some(node_id.to_string()),
17+
Datacenter: None,
18+
CheckID: None,
19+
ServiceID: Some(service_name.to_string()),
20+
Namespace: None,
21+
};
22+
consul.deregister_entity(&payload).await.unwrap();
23+
}

examples/register_service.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
use rs_consul::{types::*, Config, Consul};
2+
3+
#[tokio::main] // Enables async main
4+
async fn main() {
5+
let consul_config = Config {
6+
address: "http://localhost:8500".to_string(),
7+
token: None, // Token is None in developpement mode
8+
..Default::default()
9+
};
10+
let consul = Consul::new(consul_config);
11+
12+
let node_id = "root-node";
13+
let service_name = "new-service-1";
14+
let payload = RegisterEntityPayload {
15+
ID: None,
16+
Node: node_id.to_string(),
17+
Address: "127.0.0.1".to_string(),
18+
Datacenter: None,
19+
TaggedAddresses: Default::default(),
20+
NodeMeta: Default::default(),
21+
Service: Some(RegisterEntityService {
22+
ID: None,
23+
Service: service_name.to_string(),
24+
Tags: vec![],
25+
TaggedAddresses: Default::default(),
26+
Meta: Default::default(),
27+
Port: Some(42424),
28+
Namespace: None,
29+
}),
30+
Check: None,
31+
SkipNodeUpdate: None,
32+
};
33+
consul.register_entity(&payload).await.unwrap();
34+
}

src/errors.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
use thiserror::Error;
2+
3+
pub(crate) type Result<T> = std::result::Result<T, ConsulError>;
4+
5+
/// The error type returned from all calls into this crate.
6+
#[derive(Debug, Error)]
7+
pub enum ConsulError {
8+
/// The request was invalid and could not be serialized to valid json.
9+
#[error("Invalid request: {0}")]
10+
InvalidRequest(#[source] serde_json::Error),
11+
12+
/// The request was invalid and could not be converted into a proper http request.
13+
#[error("Request error: {0}")]
14+
RequestError(#[source] http::Error),
15+
16+
/// The consul server response could not be converted into a proper http response.
17+
#[error("Response error: {0}")]
18+
ResponseError(#[source] hyper_util::client::legacy::Error),
19+
20+
/// The consul server response was invalid.
21+
#[error("Invalid response: {0}")]
22+
InvalidResponse(#[source] hyper::Error),
23+
24+
/// The consul server response could not be deserialized from json.
25+
#[error("Response deserialization failed: {0}")]
26+
ResponseDeserializationFailed(#[source] serde_json::Error),
27+
28+
/// The consul server response could not be deserialized from bytes.
29+
#[error("Response string deserialization failed: {0}")]
30+
ResponseStringDeserializationFailed(#[source] std::str::Utf8Error),
31+
32+
/// The consul server response was something other than 200.
33+
#[error("Unexpected response code: {0}, body: {1:?}")]
34+
UnexpectedResponseCode(hyper::http::StatusCode, Option<String>),
35+
36+
/// The consul server refused a lock acquisition.
37+
#[error("Lock acquisition failure: {0}")]
38+
LockAcquisitionFailure(u64),
39+
40+
/// Consul returned invalid UTF8.
41+
#[error("Invalid UTF8: {0}")]
42+
InvalidUtf8(#[from] std::str::Utf8Error),
43+
44+
/// Consul returned invalid base64.
45+
#[error("Invalid base64: {0}")]
46+
InvalidBase64(#[from] base64::DecodeError),
47+
48+
/// IO error from sync api.
49+
#[error("Sync IO error: {0}")]
50+
SyncIoError(#[from] std::io::Error),
51+
52+
/// Response parse error from sync api.
53+
#[error("Sync invalid response error: {0}")]
54+
SyncInvalidResponseError(#[from] std::str::ParseBoolError),
55+
56+
/// Unexpected response code from sync api.
57+
#[error("Sync unexpected response code: {0}, body: {1}")]
58+
SyncUnexpectedResponseCode(u16, String),
59+
60+
/// Consul request exceeded specified timeout.
61+
#[error("Consul request exceeded timeout of {0:?}")]
62+
TimeoutExceeded(std::time::Duration),
63+
64+
/// Unable to resolve the service's instances in Consul.
65+
#[error("Unable to resolve service '{0}' to a concrete list of addresses and ports for its instances via consul.")]
66+
ServiceInstanceResolutionFailed(String),
67+
68+
/// An error from ureq occurred.
69+
#[error("UReq error: {0}")]
70+
UReqError(#[from] ureq::Error),
71+
}

0 commit comments

Comments
 (0)