Skip to content

Commit 1cde8c0

Browse files
Merge pull request #374 from joshrotenberg/feat/api-ergonomics-373
feat(redis-cloud): expose all known API fields as first-class struct members
2 parents d00107e + 7de821d commit 1cde8c0

File tree

8 files changed

+1216
-33
lines changed

8 files changed

+1216
-33
lines changed

CLAUDE.md

Lines changed: 885 additions & 0 deletions
Large diffs are not rendered by default.

crates/redis-cloud/src/acl.rs

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -115,33 +115,47 @@ pub struct AclUserUpdateRequest {
115115
}
116116

117117
/// Redis list of ACL users in current account
118+
///
119+
/// Response from GET /acl/users
118120
#[derive(Debug, Clone, Serialize, Deserialize)]
119121
#[serde(rename_all = "camelCase")]
120122
pub struct AccountACLUsers {
123+
/// Account ID
121124
#[serde(skip_serializing_if = "Option::is_none")]
122125
pub account_id: Option<i32>,
123126

124-
/// HATEOAS links
127+
/// List of ACL users (typically in extra as 'users' array)
128+
#[serde(skip_serializing_if = "Option::is_none")]
129+
pub users: Option<Vec<ACLUser>>,
130+
131+
/// HATEOAS links for API navigation
125132
#[serde(skip_serializing_if = "Option::is_none")]
126133
pub links: Option<Vec<HashMap<String, Value>>>,
127134

128-
/// Additional fields from the API
135+
/// Only for truly unknown/future API fields
129136
#[serde(flatten)]
130137
pub extra: Value,
131138
}
132139

133140
/// Redis list of ACL redis rules in current account
141+
///
142+
/// Response from GET /acl/redisRules
134143
#[derive(Debug, Clone, Serialize, Deserialize)]
135144
#[serde(rename_all = "camelCase")]
136145
pub struct AccountACLRedisRules {
146+
/// Account ID
137147
#[serde(skip_serializing_if = "Option::is_none")]
138148
pub account_id: Option<i32>,
139149

140-
/// HATEOAS links
150+
/// List of Redis ACL rules (typically in extra as 'redisRules' array)
151+
#[serde(skip_serializing_if = "Option::is_none")]
152+
pub redis_rules: Option<Vec<Value>>,
153+
154+
/// HATEOAS links for API navigation
141155
#[serde(skip_serializing_if = "Option::is_none")]
142156
pub links: Option<Vec<HashMap<String, Value>>>,
143157

144-
/// Additional fields from the API
158+
/// Only for truly unknown/future API fields
145159
#[serde(flatten)]
146160
pub extra: Value,
147161
}
@@ -165,17 +179,24 @@ pub struct AclRedisRuleCreateRequest {
165179
}
166180

167181
/// Redis list of ACL roles in current account
182+
///
183+
/// Response from GET /acl/roles
168184
#[derive(Debug, Clone, Serialize, Deserialize)]
169185
#[serde(rename_all = "camelCase")]
170186
pub struct AccountACLRoles {
187+
/// Account ID
171188
#[serde(skip_serializing_if = "Option::is_none")]
172189
pub account_id: Option<i32>,
173190

174-
/// HATEOAS links
191+
/// List of ACL roles (typically in extra as 'roles' array)
192+
#[serde(skip_serializing_if = "Option::is_none")]
193+
pub roles: Option<Vec<Value>>,
194+
195+
/// HATEOAS links for API navigation
175196
#[serde(skip_serializing_if = "Option::is_none")]
176197
pub links: Option<Vec<HashMap<String, Value>>>,
177198

178-
/// Additional fields from the API
199+
/// Only for truly unknown/future API fields
179200
#[serde(flatten)]
180201
pub extra: Value,
181202
}

crates/redis-cloud/src/cloud_accounts.rs

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -93,30 +93,51 @@ pub struct CloudAccountUpdateRequest {
9393
/// RedisLabs Cloud Account information
9494
#[derive(Debug, Clone, Serialize, Deserialize)]
9595
#[serde(rename_all = "camelCase")]
96+
/// Cloud Account
97+
///
98+
/// Represents a cloud provider account integration with all known API fields
9699
pub struct CloudAccount {
100+
/// Cloud account ID
97101
#[serde(skip_serializing_if = "Option::is_none")]
98102
pub id: Option<i32>,
99103

104+
/// Cloud account display name
100105
#[serde(skip_serializing_if = "Option::is_none")]
101106
pub name: Option<String>,
102107

108+
/// Account status (e.g., "active", "error")
103109
#[serde(skip_serializing_if = "Option::is_none")]
104110
pub status: Option<String>,
105111

112+
/// Cloud provider (e.g., "AWS", "GCP", "Azure")
113+
#[serde(skip_serializing_if = "Option::is_none")]
114+
pub provider: Option<String>,
115+
116+
/// Cloud provider access key ID
106117
#[serde(skip_serializing_if = "Option::is_none")]
107118
pub access_key_id: Option<String>,
108119

120+
/// Cloud provider secret key (typically masked in responses)
109121
#[serde(skip_serializing_if = "Option::is_none")]
110-
pub sign_in_login_url: Option<String>,
122+
pub access_secret_key: Option<String>,
111123

124+
/// Cloud provider management console username
112125
#[serde(skip_serializing_if = "Option::is_none")]
113-
pub provider: Option<String>,
126+
pub console_username: Option<String>,
114127

115-
/// HATEOAS links
128+
/// Cloud provider management console password (typically masked)
129+
#[serde(skip_serializing_if = "Option::is_none")]
130+
pub console_password: Option<String>,
131+
132+
/// Cloud provider management console login URL
133+
#[serde(skip_serializing_if = "Option::is_none")]
134+
pub sign_in_login_url: Option<String>,
135+
136+
/// HATEOAS links for API navigation
116137
#[serde(skip_serializing_if = "Option::is_none")]
117138
pub links: Option<Vec<HashMap<String, Value>>>,
118139

119-
/// Additional fields from the API
140+
/// Only for truly unknown/future API fields
120141
#[serde(flatten)]
121142
pub extra: Value,
122143
}
@@ -156,17 +177,24 @@ pub struct CloudAccountCreateRequest {
156177
}
157178

158179
/// RedisLabs Cloud Accounts information
180+
///
181+
/// Response from GET /cloud-accounts containing list of cloud provider integrations
159182
#[derive(Debug, Clone, Serialize, Deserialize)]
160183
#[serde(rename_all = "camelCase")]
161184
pub struct CloudAccounts {
185+
/// Account ID
162186
#[serde(skip_serializing_if = "Option::is_none")]
163187
pub account_id: Option<i32>,
164188

165-
/// HATEOAS links
189+
/// List of cloud provider accounts (typically in extra as 'cloudAccounts' array)
190+
#[serde(skip_serializing_if = "Option::is_none")]
191+
pub cloud_accounts: Option<Vec<CloudAccount>>,
192+
193+
/// HATEOAS links for API navigation
166194
#[serde(skip_serializing_if = "Option::is_none")]
167195
pub links: Option<Vec<HashMap<String, Value>>>,
168196

169-
/// Additional fields from the API
197+
/// Only for truly unknown/future API fields
170198
#[serde(flatten)]
171199
pub extra: Value,
172200
}

crates/redis-cloud/src/flexible/databases.rs

Lines changed: 172 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,25 @@ use std::collections::HashMap;
6161
// ============================================================================
6262

6363
/// RedisLabs Account Subscription Databases information
64+
///
65+
/// Response from GET /subscriptions/{subscriptionId}/databases
6466
#[derive(Debug, Clone, Serialize, Deserialize)]
6567
#[serde(rename_all = "camelCase")]
6668
pub struct AccountSubscriptionDatabases {
69+
/// Account ID
6770
#[serde(skip_serializing_if = "Option::is_none")]
6871
pub account_id: Option<i32>,
6972

70-
/// HATEOAS links
73+
/// Subscription information with nested databases array
74+
/// Contains subscriptionId, numberOfDatabases, and databases array
75+
#[serde(skip_serializing_if = "Option::is_none")]
76+
pub subscription: Option<Value>,
77+
78+
/// HATEOAS links for API navigation
7179
#[serde(skip_serializing_if = "Option::is_none")]
7280
pub links: Option<Vec<HashMap<String, Value>>>,
7381

74-
/// Additional fields from the API
82+
/// Only for truly unknown/future API fields
7583
#[serde(flatten)]
7684
pub extra: Value,
7785
}
@@ -522,17 +530,176 @@ pub struct DatabaseBackupRequest {
522530
}
523531

524532
/// Database
533+
///
534+
/// Represents a Redis Cloud database with all known API fields as first-class struct members.
535+
/// The `extra` field is reserved only for truly unknown/future fields that may be added to the API.
525536
#[derive(Debug, Clone, Serialize, Deserialize)]
526537
#[serde(rename_all = "camelCase")]
527538
pub struct Database {
539+
/// Database ID - always present in API responses
540+
pub database_id: i32,
541+
542+
/// Database name
528543
#[serde(skip_serializing_if = "Option::is_none")]
529-
pub database_id: Option<i32>,
544+
pub name: Option<String>,
530545

531-
/// HATEOAS links
546+
/// Database status (e.g., "active", "pending", "error", "draft")
547+
#[serde(skip_serializing_if = "Option::is_none")]
548+
pub status: Option<String>,
549+
550+
/// Cloud provider (e.g., "AWS", "GCP", "Azure")
551+
#[serde(skip_serializing_if = "Option::is_none")]
552+
pub provider: Option<String>,
553+
554+
/// Cloud region (e.g., "us-east-1", "europe-west1")
555+
#[serde(skip_serializing_if = "Option::is_none")]
556+
pub region: Option<String>,
557+
558+
/// Redis version (e.g., "7.2", "7.0")
559+
#[serde(skip_serializing_if = "Option::is_none")]
560+
pub redis_version: Option<String>,
561+
562+
/// Redis Serialization Protocol version
563+
#[serde(skip_serializing_if = "Option::is_none")]
564+
pub resp_version: Option<String>,
565+
566+
/// Total memory limit in GB (including replication and overhead)
567+
#[serde(skip_serializing_if = "Option::is_none")]
568+
pub memory_limit_in_gb: Option<f64>,
569+
570+
/// Dataset size in GB (actual data size, excluding replication)
571+
#[serde(skip_serializing_if = "Option::is_none")]
572+
pub dataset_size_in_gb: Option<f64>,
573+
574+
/// Memory used in MB
575+
#[serde(skip_serializing_if = "Option::is_none")]
576+
pub memory_used_in_mb: Option<f64>,
577+
578+
/// Private endpoint for database connections
579+
#[serde(skip_serializing_if = "Option::is_none")]
580+
pub private_endpoint: Option<String>,
581+
582+
/// Public endpoint for database connections (if enabled)
583+
#[serde(skip_serializing_if = "Option::is_none")]
584+
pub public_endpoint: Option<String>,
585+
586+
/// TCP port on which the database is available
587+
#[serde(skip_serializing_if = "Option::is_none")]
588+
pub port: Option<i32>,
589+
590+
/// Data eviction policy (e.g., "volatile-lru", "allkeys-lru", "noeviction")
591+
#[serde(skip_serializing_if = "Option::is_none")]
592+
pub data_eviction_policy: Option<String>,
593+
594+
/// Data persistence setting (e.g., "aof-every-1-sec", "snapshot-every-1-hour", "none")
595+
#[serde(skip_serializing_if = "Option::is_none")]
596+
pub data_persistence: Option<String>,
597+
598+
/// Whether replication is enabled
599+
#[serde(skip_serializing_if = "Option::is_none")]
600+
pub replication: Option<bool>,
601+
602+
/// Protocol used (e.g., "redis", "memcached")
603+
#[serde(skip_serializing_if = "Option::is_none")]
604+
pub protocol: Option<String>,
605+
606+
/// Support for OSS Cluster API
607+
#[serde(skip_serializing_if = "Option::is_none")]
608+
pub support_oss_cluster_api: Option<bool>,
609+
610+
/// Use external endpoint for OSS Cluster API
611+
#[serde(skip_serializing_if = "Option::is_none")]
612+
pub use_external_endpoint_for_oss_cluster_api: Option<bool>,
613+
614+
/// Whether TLS is enabled for connections
615+
#[serde(skip_serializing_if = "Option::is_none")]
616+
pub enable_tls: Option<bool>,
617+
618+
/// Throughput measurement configuration
619+
#[serde(skip_serializing_if = "Option::is_none")]
620+
pub throughput_measurement: Option<DatabaseThroughputSpec>,
621+
622+
/// Local throughput measurement for Active-Active databases
623+
#[serde(skip_serializing_if = "Option::is_none")]
624+
pub local_throughput_measurement: Option<Vec<LocalThroughput>>,
625+
626+
/// Average item size in bytes (for Auto Tiering)
627+
#[serde(skip_serializing_if = "Option::is_none")]
628+
pub average_item_size_in_bytes: Option<i64>,
629+
630+
/// Path to periodic backup storage location
631+
#[serde(skip_serializing_if = "Option::is_none")]
632+
pub periodic_backup_path: Option<String>,
633+
634+
/// Remote backup configuration
635+
#[serde(skip_serializing_if = "Option::is_none")]
636+
pub remote_backup: Option<Value>,
637+
638+
/// List of source IP addresses or subnet masks allowed to connect
639+
#[serde(skip_serializing_if = "Option::is_none")]
640+
pub source_ip: Option<Vec<String>>,
641+
642+
/// Client TLS/SSL certificate (deprecated, use client_tls_certificates)
643+
#[serde(skip_serializing_if = "Option::is_none")]
644+
pub client_ssl_certificate: Option<String>,
645+
646+
/// List of client TLS/SSL certificates for mTLS authentication
647+
#[serde(skip_serializing_if = "Option::is_none")]
648+
pub client_tls_certificates: Option<Vec<Value>>,
649+
650+
/// Database password (masked in responses for security)
651+
#[serde(skip_serializing_if = "Option::is_none")]
652+
pub password: Option<String>,
653+
654+
/// Memcached SASL username
655+
#[serde(skip_serializing_if = "Option::is_none")]
656+
pub sasl_username: Option<String>,
657+
658+
/// Memcached SASL password (masked in responses)
659+
#[serde(skip_serializing_if = "Option::is_none")]
660+
pub sasl_password: Option<String>,
661+
662+
/// Database alert configurations
663+
#[serde(skip_serializing_if = "Option::is_none")]
664+
pub alerts: Option<Vec<Value>>,
665+
666+
/// Redis modules/capabilities enabled on this database
667+
#[serde(skip_serializing_if = "Option::is_none")]
668+
pub modules: Option<Vec<Value>>,
669+
670+
/// Database hashing policy for clustering
671+
#[serde(skip_serializing_if = "Option::is_none")]
672+
pub sharding_type: Option<String>,
673+
674+
/// Query performance factor (for search and query databases)
675+
#[serde(skip_serializing_if = "Option::is_none")]
676+
pub query_performance_factor: Option<String>,
677+
678+
/// List of databases this database is a replica of
679+
#[serde(skip_serializing_if = "Option::is_none")]
680+
pub replica_of: Option<Vec<String>>,
681+
682+
/// Replica configuration
683+
#[serde(skip_serializing_if = "Option::is_none")]
684+
pub replica: Option<Value>,
685+
686+
/// Whether default Redis user is enabled
687+
#[serde(skip_serializing_if = "Option::is_none")]
688+
pub enable_default_user: Option<bool>,
689+
690+
/// Timestamp when database was activated
691+
#[serde(skip_serializing_if = "Option::is_none")]
692+
pub activated: Option<String>,
693+
694+
/// Timestamp of last modification
695+
#[serde(skip_serializing_if = "Option::is_none")]
696+
pub last_modified: Option<String>,
697+
698+
/// HATEOAS links for API navigation
532699
#[serde(skip_serializing_if = "Option::is_none")]
533700
pub links: Option<Vec<HashMap<String, Value>>>,
534701

535-
/// Additional fields from the API
702+
/// Only for truly unknown/future API fields. All documented fields should be first-class members above.
536703
#[serde(flatten)]
537704
pub extra: Value,
538705
}

0 commit comments

Comments
 (0)