diff --git a/crates/redis-cloud/README.md b/crates/redis-cloud/README.md index b2ef10c7..6c8597a8 100644 --- a/crates/redis-cloud/README.md +++ b/crates/redis-cloud/README.md @@ -23,33 +23,52 @@ A comprehensive Rust client library for the Redis Cloud REST API. redis-cloud = "0.1.0" ``` -## Usage +## Quick Start ```rust -use redis_cloud::{CloudClient, CloudClientConfig}; +use redis_cloud::CloudClient; #[tokio::main] async fn main() -> Result<(), Box> { - let config = CloudClientConfig { - api_key: "your-api-key".to_string(), - secret_key: "your-secret-key".to_string(), - base_url: None, // Uses default https://api.redislabs.com/v1 - }; - - let client = CloudClient::new(config)?; + // Create client using builder pattern + let client = CloudClient::builder() + .api_key("your-api-key") + .api_secret("your-api-secret") + .build()?; + + // Get account information + let account = client.account().get().await?; + println!("Account: {:?}", account); // List all subscriptions - let subscriptions = client.list_subscriptions(None).await?; + let subscriptions = client.subscription().list().await?; println!("Subscriptions: {:?}", subscriptions); - // Get account information - let account = client.get_account().await?; - println!("Account: {:?}", account); + // List databases in a subscription + let databases = client.database().list("subscription-id").await?; + println!("Databases: {:?}", databases); Ok(()) } ``` +## Examples + +The `examples/` directory contains runnable examples demonstrating common use cases: + +- [`basic.rs`](examples/basic.rs) - Getting started with the API client +- [`database_management.rs`](examples/database_management.rs) - Managing databases + +Run examples with: +```bash +# Set your API credentials +export REDIS_CLOUD_API_KEY="your-api-key" +export REDIS_CLOUD_API_SECRET="your-api-secret" + +# Run an example +cargo run --example basic +``` + ## API Coverage This library provides comprehensive coverage of the Redis Cloud REST API, including: diff --git a/crates/redis-cloud/examples/basic.rs b/crates/redis-cloud/examples/basic.rs new file mode 100644 index 00000000..92bc04db --- /dev/null +++ b/crates/redis-cloud/examples/basic.rs @@ -0,0 +1,51 @@ +//! Basic example of using the Redis Cloud API client +//! +//! This example shows how to: +//! - Connect to the Redis Cloud API +//! - Get account information +//! - List subscriptions +//! +//! Run with: cargo run --example basic + +use redis_cloud::CloudClient; +use std::env; + +#[tokio::main] +async fn main() -> Result<(), Box> { + // Get API credentials from environment variables + let api_key = + env::var("REDIS_CLOUD_API_KEY").expect("REDIS_CLOUD_API_KEY environment variable not set"); + let api_secret = env::var("REDIS_CLOUD_API_SECRET") + .expect("REDIS_CLOUD_API_SECRET environment variable not set"); + + // Create the client using the builder pattern + let client = CloudClient::builder() + .api_key(&api_key) + .api_secret(&api_secret) + .build()?; + + // Get account information using raw API + println!("Fetching account information..."); + let account = client.get_raw("/account").await?; + println!("Account ID: {}", account["account"]["id"]); + println!("Account Name: {}", account["account"]["name"]); + println!(); + + // List all subscriptions using raw API + println!("Fetching subscriptions..."); + let subscriptions = client.get_raw("/subscriptions").await?; + + if let Some(subs) = subscriptions.as_array() { + println!("Found {} subscription(s):", subs.len()); + for sub in subs { + println!( + " - ID: {}, Name: {}, Status: {}", + sub["id"], sub["name"], sub["status"] + ); + } + } else { + println!("No subscriptions found"); + } + + Ok(()) +} diff --git a/crates/redis-cloud/examples/database_management.rs b/crates/redis-cloud/examples/database_management.rs new file mode 100644 index 00000000..580d90bf --- /dev/null +++ b/crates/redis-cloud/examples/database_management.rs @@ -0,0 +1,96 @@ +//! Example of database management operations +//! +//! This example shows how to: +//! - List databases in a subscription +//! - Get database details +//! - Create a new database +//! +//! Run with: cargo run --example database_management + +use redis_cloud::{CloudClient, CloudDatabaseHandler}; +use std::env; + +// Uncomment when using the database creation example +// use redis_cloud::CreateDatabaseRequest; + +#[tokio::main] +async fn main() -> Result<(), Box> { + // Get API credentials from environment variables + let api_key = env::var("REDIS_CLOUD_API_KEY")?; + let api_secret = env::var("REDIS_CLOUD_API_SECRET")?; + + // Optional: specify subscription ID via env var or use a default + let subscription_id: u32 = env::var("REDIS_CLOUD_SUBSCRIPTION_ID") + .unwrap_or_else(|_| "123456".to_string()) + .parse()?; + + // Create the client and database handler + let client = CloudClient::builder() + .api_key(&api_key) + .api_secret(&api_secret) + .build()?; + + let db_handler = CloudDatabaseHandler::new(client.clone()); + + // List all databases in the subscription + println!("Listing databases in subscription {}...", subscription_id); + let databases = db_handler.list(subscription_id).await?; + + if let Some(dbs) = databases.as_array() { + println!("Found {} database(s):", dbs.len()); + for db in dbs { + println!( + " - ID: {}, Name: {}, Status: {}, Memory: {} MB", + db["databaseId"], + db["name"], + db["status"], + db["memoryLimitInGb"].as_f64().unwrap_or(0.0) * 1024.0 + ); + } + + // Get details of the first database + if let Some(first_db) = dbs.first() { + let db_id = first_db["databaseId"].as_u64().unwrap() as u32; + println!("\nGetting details for database {}...", db_id); + + let db_details = db_handler.get_raw(subscription_id, db_id).await?; + + println!("Database details:"); + println!(" Protocol: {}", db_details["protocol"]); + println!(" Endpoint: {}", db_details["publicEndpoint"]); + println!( + " Security: {}", + db_details["security"]["sslClientAuthentication"] + ); + } + } else { + println!("No databases found"); + } + + // Example: Create a new database (commented out to prevent accidental creation) + // Uncomment and modify as needed + /* + println!("\nCreating a new database..."); + let new_database = CreateDatabaseRequest { + name: "example-db".to_string(), + memory_limit_in_gb: 0.1, // 100 MB + data_persistence: "none".to_string(), + replication: false, + data_eviction: Some("volatile-lru".to_string()), + password: None, + support_oss_cluster_api: Some(false), + use_external_endpoint_for_oss_cluster_api: None, + }; + + let created_db = db_handler + .create(subscription_id, new_database) + .await?; + + println!("Created database: ID={}, Name={}", + created_db["databaseId"], + created_db["name"] + ); + */ + + Ok(()) +} diff --git a/crates/redis-enterprise/README.md b/crates/redis-enterprise/README.md index cfb1c96e..7637dd18 100644 --- a/crates/redis-enterprise/README.md +++ b/crates/redis-enterprise/README.md @@ -24,38 +24,56 @@ A comprehensive Rust client library for the Redis Enterprise REST API. redis-enterprise = "0.1.0" ``` -## Usage +## Quick Start ```rust -use redis_enterprise::{EnterpriseClient, EnterpriseClientConfig}; +use redis_enterprise::EnterpriseClient; #[tokio::main] async fn main() -> Result<(), Box> { - let config = EnterpriseClientConfig { - base_url: "https://cluster.example.com:9443".to_string(), - username: "admin@example.com".to_string(), - password: "your-password".to_string(), - insecure: false, // Set to true for self-signed certificates - }; - - let client = EnterpriseClient::new(config)?; + // Create client using builder pattern + let client = EnterpriseClient::builder() + .url("https://cluster.example.com:9443") + .username("admin@example.com") + .password("your-password") + .insecure(false) // Set to true for self-signed certificates + .build()?; // Get cluster information - let cluster = client.get_cluster_info().await?; + let cluster = client.cluster().info().await?; println!("Cluster: {:?}", cluster); - // List databases - let databases = client.list_databases().await?; + // List databases (BDBs) + let databases = client.database().list().await?; println!("Databases: {:?}", databases); // Get node statistics - let stats = client.get_node_stats("1").await?; - println!("Node stats: {:?}", stats); + let nodes = client.node().list().await?; + println!("Nodes: {:?}", nodes); Ok(()) } ``` +## Examples + +The `examples/` directory contains runnable examples demonstrating common use cases: + +- [`basic.rs`](examples/basic.rs) - Getting started with cluster connection +- [`database_management.rs`](examples/database_management.rs) - Managing databases and viewing statistics + +Run examples with: +```bash +# Set your cluster credentials +export REDIS_ENTERPRISE_URL="https://localhost:9443" +export REDIS_ENTERPRISE_USER="admin@redis.local" +export REDIS_ENTERPRISE_PASSWORD="your-password" +export REDIS_ENTERPRISE_INSECURE="true" # For self-signed certificates + +# Run an example +cargo run --example basic +``` + ## API Coverage This library provides 100% coverage of the Redis Enterprise REST API, including: diff --git a/crates/redis-enterprise/examples/basic.rs b/crates/redis-enterprise/examples/basic.rs new file mode 100644 index 00000000..b8b09d51 --- /dev/null +++ b/crates/redis-enterprise/examples/basic.rs @@ -0,0 +1,76 @@ +//! Basic example of using the Redis Enterprise API client +//! +//! This example shows how to: +//! - Connect to a Redis Enterprise cluster +//! - Get cluster information +//! - List databases and nodes +//! +//! Run with: cargo run --example basic + +use redis_enterprise::{BdbHandler, EnterpriseClient}; +use std::env; + +#[tokio::main] +async fn main() -> Result<(), Box> { + // Get cluster credentials from environment variables + let url = + env::var("REDIS_ENTERPRISE_URL").unwrap_or_else(|_| "https://localhost:9443".to_string()); + let username = + env::var("REDIS_ENTERPRISE_USER").unwrap_or_else(|_| "admin@redis.local".to_string()); + let password = env::var("REDIS_ENTERPRISE_PASSWORD") + .expect("REDIS_ENTERPRISE_PASSWORD environment variable not set"); + + // Check if we should skip SSL verification (for development/self-signed certs) + let insecure = env::var("REDIS_ENTERPRISE_INSECURE") + .unwrap_or_else(|_| "false".to_string()) + .parse::() + .unwrap_or(false); + + // Create the client using the builder pattern + let client = EnterpriseClient::builder() + .base_url(&url) + .username(&username) + .password(&password) + .insecure(insecure) + .build()?; + + // Get cluster information using raw API + println!("Fetching cluster information..."); + let cluster: serde_json::Value = client.get("/v1/cluster").await?; + println!("Cluster Name: {}", cluster["name"]); + println!("Cluster Version: {}", cluster["software_version"]); + println!(); + + // List all nodes using raw API + println!("Fetching nodes..."); + let nodes: serde_json::Value = client.get("/v1/nodes").await?; + + if let Some(nodes_array) = nodes.as_array() { + println!("Found {} node(s):", nodes_array.len()); + for node in nodes_array { + println!( + " - Node {}: {} ({})", + node["uid"], node["addr"], node["status"] + ); + } + } + println!(); + + // List all databases (BDBs) using handler + println!("Fetching databases..."); + let db_handler = BdbHandler::new(client.clone()); + let databases = db_handler.list().await?; + + println!("Found {} database(s):", databases.len()); + for db in &databases { + println!( + " - BDB {}: {} (Memory: {} MB, Status: {})", + db.uid, + db.name, + db.memory_size.unwrap_or(0) / (1024 * 1024), + db.status.as_deref().unwrap_or("unknown") + ); + } + + Ok(()) +} diff --git a/crates/redis-enterprise/examples/database_management.rs b/crates/redis-enterprise/examples/database_management.rs new file mode 100644 index 00000000..8a8627d1 --- /dev/null +++ b/crates/redis-enterprise/examples/database_management.rs @@ -0,0 +1,109 @@ +//! Example of database management operations in Redis Enterprise +//! +//! This example shows how to: +//! - Create a new database +//! - Configure database settings +//! - Get database statistics +//! +//! Run with: cargo run --example database_management + +use redis_enterprise::{BdbHandler, EnterpriseClient}; +use std::env; + +// Uncomment when using the database creation example +// use serde_json::json; + +#[tokio::main] +async fn main() -> Result<(), Box> { + // Get cluster credentials from environment variables + let url = + env::var("REDIS_ENTERPRISE_URL").unwrap_or_else(|_| "https://localhost:9443".to_string()); + let username = + env::var("REDIS_ENTERPRISE_USER").unwrap_or_else(|_| "admin@redis.local".to_string()); + let password = env::var("REDIS_ENTERPRISE_PASSWORD")?; + let insecure = env::var("REDIS_ENTERPRISE_INSECURE") + .unwrap_or_else(|_| "false".to_string()) + .parse::() + .unwrap_or(false); + + // Create the client + let client = EnterpriseClient::builder() + .base_url(&url) + .username(&username) + .password(&password) + .insecure(insecure) + .build()?; + + // List existing databases using handler + println!("Listing existing databases..."); + let db_handler = BdbHandler::new(client.clone()); + let databases = db_handler.list().await?; + + for db in &databases { + println!("Database {}: {}", db.uid, db.name); + + // Get statistics for this database using raw API + println!(" Getting statistics..."); + let stats: serde_json::Value = client.get(&format!("/v1/bdbs/{}/stats", db.uid)).await?; + + if let Some(intervals) = stats["intervals"].as_array() + && let Some(latest) = intervals.last() + { + println!(" Latest stats:"); + println!( + " Used memory: {} MB", + latest["used_memory"].as_f64().unwrap_or(0.0) / 1024.0 / 1024.0 + ); + println!( + " Total requests: {}", + latest["total_req"].as_u64().unwrap_or(0) + ); + println!(" Connections: {}", latest["conns"].as_u64().unwrap_or(0)); + } + } + println!(); + + // Example: Create a new database (commented out to prevent accidental creation) + // Uncomment and modify as needed + /* + println!("Creating a new database..."); + let new_database = json!({ + "name": "example-db", + "memory_size": 104857600, // 100 MB in bytes + "type": "redis", + "port": 12000, + "replication": false, + "persistence": "disabled", + "eviction_policy": "volatile-lru", + "sharding": false, + "shard_count": 1, + "module_list": [], + "authentication_redis_pass": "SecurePassword123!" + }); + + let created_db = client + .database() + .create(new_database) + .await?; + + println!("Created database: ID={}, Name={}, Port={}", + created_db["uid"], + created_db["name"], + created_db["port"] + ); + + // Wait for database to become active + let db_id = created_db["uid"].as_u64().unwrap(); + loop { + let status = client.database().get(db_id).await?; + if status["status"].as_str() == Some("active") { + println!("Database is now active!"); + break; + } + println!("Waiting for database to become active..."); + tokio::time::sleep(tokio::time::Duration::from_secs(2)).await; + } + */ + + Ok(()) +} diff --git a/docs/book.toml b/docs/book.toml index bc7b13d0..8f6a2e24 100644 --- a/docs/book.toml +++ b/docs/book.toml @@ -14,7 +14,3 @@ edit-url-template = "https://github.com/joshrotenberg/redisctl/edit/main/docs/{p [output.html.fold] enable = true level = 1 - -# mdbook-lint can be run manually via CLI -# Disabled as preprocessor due to configuration issues -# Run with: mdbook-lint lint src