# batata-consul-client
A Rust client library for [HashiCorp Consul](https://www.consul.io/), supporting service discovery, health checking, key-value store, sessions, ACL, and more.
## Features
- **KV Store**: Get, put, delete keys with CAS support and distributed locking
- **Agent**: Register/deregister services, manage health checks, TTL updates
- **Catalog**: Query nodes and services across the cluster
- **Health**: Health check queries with status filtering
- **Session**: Distributed locking and leader election
- **ACL**: Token, policy, and role management
## Installation
Add to your `Cargo.toml`:
```toml
[dependencies]
batata-consul-client = "0.0.1"
```
## Quick Start
```rust
use batata_consul_client::{Client, Config};
#[tokio::main]
async fn main() -> batata_consul_client::Result<()> {
// Create client with default configuration (localhost:8500)
let client = Client::new(Config::default())?;
// Use KV store
let kv = client.kv();
kv.put_string("my/key", "my-value", None).await?;
let (pair, _meta) = kv.get("my/key", None).await?;
if let Some(p) = pair {
println!("Value: {:?}", p.value_string());
}
Ok(())
}
```
## Configuration
### Default Configuration
```rust
let client = Client::new(Config::default())?;
```
### From Environment Variables
```rust
let client = Client::from_env()?;
```
Supported environment variables:
| `CONSUL_HTTP_ADDR` | Consul server address (e.g., `http://127.0.0.1:8500`) |
| `CONSUL_HTTP_TOKEN` | ACL token |
| `CONSUL_HTTP_AUTH` | HTTP basic auth (`username:password`) |
| `CONSUL_HTTP_SSL` | Enable HTTPS (`true` or `1`) |
| `CONSUL_HTTP_SSL_VERIFY` | Verify TLS certificates (`false` or `0` to skip) |
| `CONSUL_CACERT` | CA certificate path |
| `CONSUL_CLIENT_CERT` | Client certificate path |
| `CONSUL_CLIENT_KEY` | Client key path |
| `CONSUL_NAMESPACE` | Namespace (Enterprise only) |
| `CONSUL_PARTITION` | Partition (Enterprise only) |
### Builder Pattern
```rust
use std::time::Duration;
let client = Client::builder()
.address("consul.example.com:8500")
.scheme("https")
.token("my-acl-token")
.datacenter("dc1")
.timeout(Duration::from_secs(60))
.build()?;
```
## API Examples
### Service Registration
```rust
use batata_consul_client::api::agent::{AgentServiceRegistration, AgentServiceCheck};
let registration = AgentServiceRegistration::new("my-service")
.with_id("my-service-1")
.with_address("127.0.0.1")
.with_port(8080)
.with_tags(vec!["api", "v1"])
.with_check(AgentServiceCheck::http("http://127.0.0.1:8080/health", "10s"));
client.agent().service_register(®istration).await?;
```
### Service Discovery
```rust
// Get healthy instances of a service
let (services, _meta) = client.health().service_healthy("my-service", None).await?;
for service in services {
println!("{}:{}", service.service.address, service.service.port);
}
```
### KV Store with CAS
```rust
let kv = client.kv();
// Get current value
let (pair, _meta) = kv.get("config/key", None).await?;
if let Some(mut p) = pair {
// Update with CAS (Check-And-Set)
p.set_value_string("new-value");
let (success, _) = kv.cas(&p, None).await?;
println!("CAS update success: {}", success);
}
```
### Blocking Queries
```rust
use std::time::Duration;
use batata_consul_client::QueryOptions;
let opts = QueryOptions::new()
.with_wait(last_index, Duration::from_secs(30));
let (services, meta) = client.health().service("my-service", None, Some(opts)).await?;
// meta.last_index can be used for the next blocking query
```
### Session and Locking
```rust
use batata_consul_client::api::session::{SessionRequest, SessionBehavior};
// Create a session
let session_req = SessionRequest::new()
.with_name("my-lock")
.with_ttl("30s")
.with_behavior(SessionBehavior::Release);
let (session_id, _) = client.session().create(&session_req, None).await?;
// Acquire a lock
let (acquired, _) = client.kv().acquire("locks/my-resource", &session_id, None).await?;
if acquired {
// Do work while holding the lock
// Release the lock
client.kv().release("locks/my-resource", &session_id, None).await?;
}
// Destroy the session
client.session().destroy(&session_id, None).await?;
```
## Running Examples
Make sure you have a Consul server running locally:
```bash
# Start Consul in dev mode
consul agent -dev
# Run examples
cargo run --example kv_example
cargo run --example service_discovery
cargo run --example health_check
```
## License
Apache-2.0