Skip to content

Commit 155161e

Browse files
Extract config/profile management to library crate (#410)
* docs: rewrite README for presentation readiness - Add hero section with clear value proposition - Create 'Why redisctl?' section explaining benefits over raw APIs - Add feature showcase with before/after examples - Include 4 real-world usage scenarios - Move installation section lower after establishing value - Streamline quick start to 3 simple steps - Maintain all technical accuracy while improving readability * docs: remove emojis from README * feat: extract config/profile management to redisctl-config library Closes #409 - Created new redisctl-config library crate for reusable config system - Moved config.rs and credential_store.rs to new crate - Refactored to use thiserror for library errors - Added clap::ValueEnum derive to DeploymentType - Updated all imports in redisctl to use new library - Removed old config and credential_store modules from redisctl - All tests passing, clippy clean Benefits: - Config system can now be reused by other tools (e.g., redis-up) - Cleaner separation of concerns - Independent versioning for config library - Well-documented public API Breaking changes: None (internal refactoring only)
1 parent 9d9e801 commit 155161e

File tree

21 files changed

+476
-168
lines changed

21 files changed

+476
-168
lines changed

Cargo.lock

Lines changed: 66 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
[workspace]
22
resolver = "2"
33
members = [
4+
"crates/redisctl-config",
45
"crates/redis-cloud",
56
"crates/redis-enterprise",
67
"crates/redisctl",
78
]
89
default-members = [
10+
"crates/redisctl-config",
911
"crates/redis-cloud",
1012
"crates/redis-enterprise",
1113
"crates/redisctl",
@@ -91,6 +93,7 @@ serial_test = "3.1"
9193
pretty_assertions = "1.4"
9294

9395
# Internal crates
96+
redisctl-config = { path = "crates/redisctl-config" }
9497
redis-cloud = { path = "crates/redis-cloud" }
9598
redis-enterprise = { path = "crates/redis-enterprise" }
9699

crates/redisctl-config/Cargo.toml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
[package]
2+
name = "redisctl-config"
3+
version = "0.1.0"
4+
edition = "2024"
5+
authors = ["Josh Rotenberg <[email protected]>"]
6+
license = "MIT OR Apache-2.0"
7+
repository = "https://github.com/joshrotenberg/redisctl"
8+
homepage = "https://github.com/joshrotenberg/redisctl"
9+
description = "Configuration and profile management for Redis CLI tools"
10+
keywords = ["redis", "config", "profile", "credentials"]
11+
categories = ["config", "authentication"]
12+
readme = "README.md"
13+
14+
[dependencies]
15+
# Serialization
16+
serde = { version = "1.0", features = ["derive"] }
17+
toml = "0.8"
18+
19+
# Error handling (use thiserror for libraries)
20+
thiserror = "2.0"
21+
22+
# Platform paths
23+
directories = "6.0"
24+
25+
# Environment variable expansion
26+
shellexpand = "3.1"
27+
28+
# CLI support (for ValueEnum derive)
29+
clap = { version = "4.5", features = ["derive"] }
30+
31+
# Optional: Secure credential storage
32+
keyring = { version = "3.6", optional = true, features = ["apple-native", "windows-native", "linux-native"] }
33+
34+
[dev-dependencies]
35+
serial_test = "3.1"
36+
tempfile = "3.8"
37+
38+
[features]
39+
default = []
40+
# Note: secure-storage may not work on musl targets due to keyring native dependencies
41+
secure-storage = ["dep:keyring"]

crates/redisctl-config/README.md

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# redisctl-config
2+
3+
Configuration and profile management for Redis CLI tools.
4+
5+
## Overview
6+
7+
This library provides a reusable configuration and profile system for managing
8+
credentials and settings for Redis Cloud and Redis Enterprise deployments.
9+
10+
## Features
11+
12+
- Multiple named profiles for different Redis deployments
13+
- Secure credential storage using OS keyring (optional)
14+
- Environment variable expansion in config files
15+
- Platform-specific config file locations
16+
- Support for both Redis Cloud and Redis Enterprise
17+
18+
## Installation
19+
20+
Add this to your `Cargo.toml`:
21+
22+
```toml
23+
[dependencies]
24+
redisctl-config = "0.1"
25+
26+
# Optional: Enable secure credential storage
27+
redisctl-config = { version = "0.1", features = ["secure-storage"] }
28+
```
29+
30+
## Usage
31+
32+
### Basic Configuration
33+
34+
```rust
35+
use redisctl_config::{Config, Profile, DeploymentType, ProfileCredentials};
36+
37+
// Load configuration from standard location
38+
let config = Config::load()?;
39+
40+
// Create a new Cloud profile
41+
let profile = Profile {
42+
deployment_type: DeploymentType::Cloud,
43+
credentials: ProfileCredentials::Cloud {
44+
api_key: "your-api-key".to_string(),
45+
api_secret: "your-secret".to_string(),
46+
api_url: "https://api.redislabs.com/v1".to_string(),
47+
},
48+
files_api_key: None,
49+
};
50+
51+
// Add profile to config
52+
let mut config = Config::default();
53+
config.set_profile("production".to_string(), profile);
54+
config.save()?;
55+
```
56+
57+
### Profile Resolution
58+
59+
```rust
60+
// Resolve which profile to use for Cloud operations
61+
let profile_name = config.resolve_cloud_profile(None)?;
62+
let profile = config.profiles.get(&profile_name).unwrap();
63+
64+
// Get credentials with keyring support
65+
if let Some((api_key, api_secret, api_url)) = profile.resolve_cloud_credentials()? {
66+
println!("API URL: {}", api_url);
67+
}
68+
```
69+
70+
### Credential Storage
71+
72+
```rust
73+
use redisctl_config::CredentialStore;
74+
75+
let store = CredentialStore::new();
76+
77+
// Store credential in keyring (requires secure-storage feature)
78+
#[cfg(feature = "secure-storage")]
79+
let reference = store.store_credential("my-key", "secret-value")?;
80+
81+
// Retrieve credential (with environment variable fallback)
82+
let value = store.get_credential("${MY_VAR}", Some("MY_VAR"))?;
83+
```
84+
85+
## Environment Variables
86+
87+
Credentials can reference environment variables in the config file:
88+
89+
```toml
90+
[profiles.production]
91+
deployment_type = "cloud"
92+
api_key = "${REDIS_CLOUD_API_KEY}"
93+
api_secret = "${REDIS_CLOUD_SECRET_KEY}"
94+
api_url = "${REDIS_CLOUD_API_URL:-https://api.redislabs.com/v1}"
95+
```
96+
97+
## Config File Location
98+
99+
The config file is automatically placed in platform-specific locations:
100+
101+
- **Linux/macOS**: `~/.config/redisctl/config.toml`
102+
- **macOS** (fallback): `~/Library/Application Support/com.redis.redisctl/config.toml`
103+
- **Windows**: `%APPDATA%\redis\redisctl\config.toml`
104+
105+
## License
106+
107+
Licensed under either of Apache License, Version 2.0 or MIT license at your option.

0 commit comments

Comments
 (0)