batata-consul-client 0.0.2

Rust client for HashiCorp Consul or batata
Documentation
# 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:

| Variable | Description |
|----------|-------------|
| `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(&registration).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