redis_enterprise/lib.rs
1//! Redis Enterprise REST API client
2//!
3//! A comprehensive Rust client library for the Redis Enterprise REST API, providing
4//! full cluster management, database operations, security configuration, and monitoring
5//! capabilities. This crate offers both typed and untyped API access with comprehensive
6//! coverage of all Enterprise REST endpoints.
7//!
8//! # Features
9//!
10//! - **Complete API Coverage**: Full coverage of v1 endpoints plus select v2
11//! endpoints where they exist (e.g., actions, modules)
12//! - **Type-Safe Operations**: Strongly typed request/response models
13//! - **Flexible Authentication**: Basic auth with optional SSL verification
14//! - **Async/Await Support**: Built on Tokio for high-performance async operations
15//! - **Error Handling**: Comprehensive error types with context
16//! - **Builder Patterns**: Ergonomic API for complex request construction
17//! - **Versioned APIs**: Clear accessors for v1 and v2 where both exist
18//!
19//! # Quick Start
20//!
21//! Add to your `Cargo.toml`:
22//! ```toml
23//! [dependencies]
24//! redis-enterprise = "0.2.0"
25//! tokio = { version = "1", features = ["full"] }
26//! ```
27//!
28//! # Environment Variables
29//!
30//! The client supports configuration via environment variables:
31//! - `REDIS_ENTERPRISE_URL`: Base URL for the cluster (e.g., `https://cluster:9443`)
32//! - `REDIS_ENTERPRISE_USER`: Username for authentication
33//! - `REDIS_ENTERPRISE_PASSWORD`: Password for authentication
34//! - `REDIS_ENTERPRISE_INSECURE`: Set to `true` to skip SSL verification (dev only)
35//!
36//! # Module Organization
37//!
38//! The library is organized into domain-specific modules:
39//!
40//! - **Core Resources**: [`bdb`], [`cluster`], [`nodes`], [`users`], [`roles`]
41//! - **Monitoring**: [`stats`], [`alerts`], [`logs`], [`diagnostics`]
42//! - **Advanced**: [`crdb`], [`shards`], [`proxies`], [`redis_acls`]
43//! - **Configuration**: [`services`], [`cm_settings`], [`suffixes`]
44//!
45//! # Return Types
46//!
47//! Most methods return strongly-typed structs. Methods returning `serde_json::Value`:
48//! - **Stats/Metrics**: Dynamic keys based on metric names
49//! - **Legacy endpoints**: `start()`, `stop()` - use typed action methods instead
50//! - **Variable schemas**: Endpoints with version-dependent responses
51//! - **Passthrough access**: For direct API access via the CLI
52//!
53//! # Examples
54//!
55//! ## Creating a Client
56//!
57//! ```no_run
58//! use redis_enterprise::EnterpriseClient;
59//!
60//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
61//! // From environment variables
62//! let client = EnterpriseClient::from_env()?;
63//!
64//! // Or using the builder
65//! let client = EnterpriseClient::builder()
66//! .base_url("https://cluster.example.com:9443")
67//! .username("admin@example.com")
68//! .password("password")
69//! .insecure(false)
70//! .build()?;
71//! # Ok(())
72//! # }
73//! ```
74//!
75//! ## Working with Databases
76//!
77//! ```no_run
78//! use redis_enterprise::{EnterpriseClient, BdbHandler, CreateDatabaseRequest};
79//!
80//! # async fn example(client: EnterpriseClient) -> Result<(), Box<dyn std::error::Error>> {
81//! // List all databases
82//! let handler = BdbHandler::new(client.clone());
83//! let databases = handler.list().await?;
84//! for db in databases {
85//! println!("Database: {} ({})", db.name, db.uid);
86//! }
87//!
88//! // Create a new database
89//! let request = CreateDatabaseRequest::builder()
90//! .name("my-database")
91//! .memory_size(1024 * 1024 * 1024) // 1GB
92//! .port(12000)
93//! .replication(false)
94//! .persistence("aof")
95//! .build();
96//!
97//! let new_db = handler.create(request).await?;
98//! println!("Created database: {}", new_db.uid);
99//!
100//! // Get database stats
101//! let stats = handler.stats(new_db.uid).await?;
102//! println!("Ops/sec: {:?}", stats);
103//! # Ok(())
104//! # }
105//! ```
106//!
107//! ## Managing Nodes
108//!
109//! ```no_run
110//! use redis_enterprise::{EnterpriseClient, NodeHandler};
111//!
112//! # async fn example(client: EnterpriseClient) -> Result<(), Box<dyn std::error::Error>> {
113//! let handler = NodeHandler::new(client);
114//!
115//! // List all nodes in the cluster
116//! let nodes = handler.list().await?;
117//! for node in nodes {
118//! println!("Node {}: {:?} ({})", node.uid, node.addr, node.status);
119//! }
120//!
121//! // Get detailed node information
122//! let node_info = handler.get(1).await?;
123//! println!("Node memory: {:?} bytes", node_info.total_memory);
124//!
125//! // Check node stats
126//! let stats = handler.stats(1).await?;
127//! println!("CPU usage: {:?}", stats);
128//! # Ok(())
129//! # }
130//! ```
131//!
132//! ## Cluster Operations
133//!
134//! ```no_run
135//! use redis_enterprise::{EnterpriseClient, ClusterHandler};
136//!
137//! # async fn example(client: EnterpriseClient) -> Result<(), Box<dyn std::error::Error>> {
138//! let handler = ClusterHandler::new(client);
139//!
140//! // Get cluster information
141//! let cluster_info = handler.info().await?;
142//! println!("Cluster name: {}", cluster_info.name);
143//! println!("Nodes: {:?}", cluster_info.nodes);
144//!
145//! // Get cluster statistics
146//! let stats = handler.stats().await?;
147//! println!("Total memory: {:?}", stats);
148//!
149//! // Check license status
150//! let license = handler.license().await?;
151//! println!("License expires: {:?}", license);
152//! # Ok(())
153//! # }
154//! ```
155//!
156//! ## Versioned Endpoints (v1/v2)
157//!
158//! Some Enterprise endpoints have both v1 and v2 flavors. Use versioned sub-handlers
159//! to make intent explicit and keep models clean.
160//!
161//! ```no_run
162//! use redis_enterprise::{EnterpriseClient, ActionHandler, ModuleHandler};
163//!
164//! # async fn example(client: EnterpriseClient) -> Result<(), Box<dyn std::error::Error>> {
165//! // Actions: v1 and v2
166//! let actions = ActionHandler::new(client.clone());
167//! let v1_actions = actions.v1().list().await?; // GET /v1/actions
168//! let v2_actions = actions.v2().list().await?; // GET /v2/actions
169//!
170//! // Modules
171//! let modules = ModuleHandler::new(client.clone());
172//! let all = modules.list().await?; // GET /v1/modules
173//! // Upload uses v2 endpoint with fallback to v1
174//! let uploaded = modules.upload(b"module_data".to_vec(), "module.zip").await?;
175//! # Ok(())
176//! # }
177//! ```
178//!
179//! # Typed-Only Client
180//!
181//! The Enterprise client exposes typed request/response APIs by default. Raw JSON
182//! passthroughs are avoided except for intentionally opaque operations (for example,
183//! database command passthrough or module uploads). This keeps CLI and library usage
184//! consistent and safer while maintaining flexibility where the wire format is open.
185//!
186//! ## User Management
187//!
188//! ```no_run
189//! use redis_enterprise::{EnterpriseClient, UserHandler, CreateUserRequest};
190//!
191//! # async fn example(client: EnterpriseClient) -> Result<(), Box<dyn std::error::Error>> {
192//! let handler = UserHandler::new(client);
193//!
194//! // List all users
195//! let users = handler.list().await?;
196//! for user in users {
197//! println!("User: {} ({})", user.email, user.role);
198//! }
199//!
200//! // Create a new user
201//! let request = CreateUserRequest::builder()
202//! .email("newuser@example.com")
203//! .password("secure_password")
204//! .role("db_member")
205//! .name("New User")
206//! .email_alerts(true)
207//! .build();
208//!
209//! let new_user = handler.create(request).await?;
210//! println!("Created user: {}", new_user.uid);
211//! # Ok(())
212//! # }
213//! ```
214//!
215//! ## Monitoring and Alerts
216//!
217//! ```no_run
218//! use redis_enterprise::{EnterpriseClient, AlertHandler, StatsHandler};
219//!
220//! # async fn example(client: EnterpriseClient) -> Result<(), Box<dyn std::error::Error>> {
221//! // Check active alerts
222//! let alert_handler = AlertHandler::new(client.clone());
223//! let alerts = alert_handler.list().await?;
224//! for alert in alerts {
225//! println!("Alert: {} - {}", alert.name, alert.severity);
226//! }
227//!
228//! // Get cluster statistics
229//! let stats_handler = StatsHandler::new(client);
230//! let cluster_stats = stats_handler.cluster(None).await?;
231//! println!("Cluster stats: {:?}", cluster_stats);
232//! # Ok(())
233//! # }
234//! ```
235//!
236//! ## Active-Active Databases (CRDB)
237//!
238//! ```no_run
239//! use redis_enterprise::{EnterpriseClient, CrdbHandler, CreateCrdbRequest};
240//!
241//! # async fn example(client: EnterpriseClient) -> Result<(), Box<dyn std::error::Error>> {
242//! let handler = CrdbHandler::new(client);
243//!
244//! // List Active-Active databases
245//! let crdbs = handler.list().await?;
246//! for crdb in crdbs {
247//! println!("CRDB: {} ({})", crdb.name, crdb.guid);
248//! }
249//!
250//! // Create an Active-Active database
251//! let request = CreateCrdbRequest {
252//! name: "global-cache".to_string(),
253//! memory_size: 1024 * 1024 * 1024, // 1GB per instance
254//! instances: vec![
255//! // Define instances for each participating cluster
256//! ],
257//! encryption: Some(false),
258//! data_persistence: Some("aof".to_string()),
259//! eviction_policy: Some("allkeys-lru".to_string()),
260//! };
261//!
262//! let new_crdb = handler.create(request).await?;
263//! println!("Created CRDB: {}", new_crdb.guid);
264//! # Ok(())
265//! # }
266//! ```
267//!
268//! # Error Handling
269//!
270//! The library provides detailed error information for all API operations with
271//! convenient error variants and helper methods:
272//!
273//! ```no_run
274//! use redis_enterprise::{EnterpriseClient, bdb::DatabaseHandler, RestError};
275//!
276//! # async fn example(client: EnterpriseClient) -> Result<(), Box<dyn std::error::Error>> {
277//! let handler = DatabaseHandler::new(client);
278//!
279//! match handler.get(999).await {
280//! Ok(db) => println!("Found database: {}", db.name),
281//! Err(RestError::NotFound) => println!("Database not found"),
282//! Err(RestError::Unauthorized) => println!("Invalid credentials"),
283//! Err(RestError::ServerError(msg)) => println!("Server error: {}", msg),
284//! Err(e) if e.is_not_found() => println!("Not found: {}", e),
285//! Err(e) => println!("Unexpected error: {}", e),
286//! }
287//! # Ok(())
288//! # }
289//! ```
290//!
291//! ## Handler Overview
292//!
293//! The library exposes focused handlers per API domain to keep code organized and discoverable:
294//!
295//! | Handler | Purpose | Key Operations |
296//! |---------|---------|----------------|
297//! | `ClusterHandler` | Cluster lifecycle | info, update, license, services |
298//! | `BdbHandler` | Databases (BDB) | list, get, create, update, delete, stats |
299//! | `NodeHandler` | Node management | list, get, stats |
300//! | `UserHandler` | Users | list, get, create, update, delete |
301//! | `RoleHandler` | Roles | list, get, assign |
302//! | `ModuleHandler` | Modules | list (v1), upload (v2) |
303//! | `AlertHandler` | Alerts | list, acknowledge |
304//! | `StatsHandler` | Monitoring | cluster/node/database stats |
305//! | `LogsHandler` | Logs | cluster and database logs |
306//! | `ActionHandler` | Actions | v1/v2 workflows |
307//!
308//! # Production Best Practices
309//!
310//! - **Connection Pooling**: The client reuses HTTP connections automatically
311//! - **Timeout Configuration**: Set appropriate timeouts for your environment
312//! - **SSL Verification**: Always enable in production (disable only for development)
313//! - **Error Handling**: Implement retry logic for transient failures
314//! - **Monitoring**: Log all API operations and track response times
315//!
316//! # API Coverage
317//!
318//! This crate provides complete coverage of the Redis Enterprise REST API:
319//!
320//! - **Cluster Management**: Bootstrap, configuration, licenses
321//! - **Database Operations**: CRUD, backup/restore, configuration
322//! - **Security**: Users, roles, ACLs, LDAP integration
323//! - **Monitoring**: Stats, alerts, logs, diagnostics
324//! - **High Availability**: Active-Active (CRDB), replication
325//! - **Modules**: Redis module management
326//! - **Maintenance**: Upgrades, migrations, debug info
327
328pub mod actions;
329pub mod alerts;
330pub mod bdb;
331pub mod bdb_groups;
332pub mod bootstrap;
333pub mod client;
334pub mod cluster;
335pub mod cm_settings;
336pub mod crdb;
337pub mod crdb_tasks;
338pub mod debuginfo;
339pub mod diagnostics;
340pub mod endpoints;
341pub mod error;
342pub mod job_scheduler;
343pub mod jsonschema;
344pub mod ldap_mappings;
345pub mod license;
346pub mod local;
347pub mod logs;
348pub mod migrations;
349pub mod modules;
350pub mod nodes;
351pub mod ocsp;
352pub mod proxies;
353pub mod redis_acls;
354pub mod roles;
355pub mod services;
356pub mod shards;
357pub mod stats;
358pub mod suffixes;
359pub mod types;
360pub mod usage_report;
361pub mod users;
362
363#[cfg(test)]
364mod lib_tests;
365
366// Core client and error types
367pub use client::{EnterpriseClient, EnterpriseClientBuilder};
368pub use error::{RestError, Result};
369
370// Database management
371pub use bdb::{
372 BdbHandler, CreateDatabaseRequest, CreateDatabaseRequestBuilder, Database, ModuleConfig,
373};
374
375// Database groups
376pub use bdb_groups::{BdbGroup, BdbGroupsHandler};
377
378// Cluster management
379pub use cluster::{
380 BootstrapRequest, ClusterHandler, ClusterInfo, ClusterNode, LicenseInfo, NodeInfo,
381};
382
383// Node management
384pub use nodes::{Node, NodeActionRequest, NodeHandler, NodeStats};
385
386// User management
387pub use users::{CreateUserRequest, Role, RoleHandler, UpdateUserRequest, User, UserHandler};
388
389// Module management
390pub use modules::{Module, ModuleHandler};
391
392// Action tracking
393pub use actions::{Action, ActionHandler};
394
395// Logs
396pub use logs::{LogEntry, LogsHandler, LogsQuery};
397
398// Active-Active databases
399pub use crdb::{Crdb, CrdbHandler, CrdbInstance, CreateCrdbInstance, CreateCrdbRequest};
400
401// Statistics
402pub use stats::{StatsHandler, StatsInterval, StatsQuery, StatsResponse};
403
404// Alerts
405pub use alerts::{Alert, AlertHandler, AlertSettings};
406
407// Redis ACLs
408pub use redis_acls::{CreateRedisAclRequest, RedisAcl, RedisAclHandler};
409
410// Shards
411pub use shards::{Shard, ShardHandler, ShardStats};
412
413// Proxies
414pub use proxies::{Proxy, ProxyHandler, ProxyStats};
415
416// LDAP mappings
417pub use ldap_mappings::{
418 CreateLdapMappingRequest, LdapConfig, LdapMapping, LdapMappingHandler, LdapServer,
419};
420
421// OCSP
422pub use ocsp::{OcspConfig, OcspHandler, OcspStatus, OcspTestResult};
423
424// Local endpoints
425pub use local::LocalHandler;
426
427// Bootstrap
428pub use bootstrap::{
429 BootstrapConfig, BootstrapHandler, BootstrapStatus, ClusterBootstrap, CredentialsBootstrap,
430 NodeBootstrap, NodePaths,
431};
432
433// Cluster Manager settings
434pub use cm_settings::{CmSettings, CmSettingsHandler};
435
436// CRDB tasks
437pub use crdb_tasks::{CrdbTask, CrdbTasksHandler, CreateCrdbTaskRequest};
438
439// Debug info
440pub use debuginfo::{DebugInfoHandler, DebugInfoRequest, DebugInfoStatus, TimeRange};
441
442// Diagnostics
443pub use diagnostics::{
444 DiagnosticReport, DiagnosticRequest, DiagnosticResult, DiagnosticSummary, DiagnosticsHandler,
445};
446
447// Endpoints
448pub use endpoints::{Endpoint, EndpointStats, EndpointsHandler};
449
450// Job scheduler
451pub use job_scheduler::{
452 CreateScheduledJobRequest, JobExecution, JobSchedulerHandler, ScheduledJob,
453};
454
455// JSON Schema
456pub use jsonschema::JsonSchemaHandler;
457
458// License
459pub use license::{License, LicenseHandler, LicenseUpdateRequest, LicenseUsage};
460
461// Migrations
462pub use migrations::{CreateMigrationRequest, Migration, MigrationEndpoint, MigrationsHandler};
463
464// Roles
465pub use roles::{BdbRole, CreateRoleRequest, RoleInfo, RolesHandler};
466
467// Services
468pub use services::{
469 NodeServiceStatus, Service, ServiceConfigRequest, ServiceStatus, ServicesHandler,
470};
471
472// Suffixes
473pub use suffixes::{CreateSuffixRequest, Suffix, SuffixesHandler};
474
475// Usage report
476pub use usage_report::{
477 DatabaseUsage, NodeUsage, UsageReport, UsageReportConfig, UsageReportHandler, UsageSummary,
478};