1use crate::client::RestClient;
51use crate::error::Result;
52use serde::{Deserialize, Serialize};
53use serde_json::Value;
54use typed_builder::TypedBuilder;
55
56#[derive(Debug, Clone, Serialize, Deserialize)]
58pub struct ClusterActionResponse {
59 pub action_uid: String,
61 pub description: Option<String>,
63 #[serde(flatten)]
65 pub extra: Value,
66}
67
68#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct ClusterNode {
71 pub id: u32,
72 pub address: String,
73 pub status: String,
74 pub role: Option<String>,
75 pub total_memory: Option<u64>,
76 pub used_memory: Option<u64>,
77 pub cpu_cores: Option<u32>,
78
79 #[serde(flatten)]
80 pub extra: Value,
81}
82
83#[derive(Debug, Clone, Serialize, Deserialize)]
85pub struct ClusterInfo {
86 pub uid: Option<u32>,
88
89 pub name: String,
91
92 pub created: Option<String>,
94
95 pub last_changed_time: Option<String>,
97
98 pub version: Option<String>,
100
101 pub license_expired: Option<bool>,
103
104 pub nodes: Option<Vec<u32>>,
106
107 pub databases: Option<Vec<u32>>,
109
110 pub status: Option<String>,
112
113 pub email_alerts: Option<bool>,
115
116 pub rack_aware: Option<bool>,
118
119 pub bigstore_driver: Option<String>,
121
122 pub cnm_http_port: Option<u16>,
124
125 pub cnm_https_port: Option<u16>,
127
128 pub total_memory: Option<u64>,
131
132 pub used_memory: Option<u64>,
134
135 pub total_shards: Option<u32>,
137
138 pub alert_settings: Option<Value>,
141
142 pub block_cluster_changes: Option<bool>,
144
145 pub ccs_internode_encryption: Option<bool>,
147
148 pub cluster_api_internal_port: Option<u32>,
150
151 pub cluster_ssh_public_key: Option<String>,
153
154 pub cm_port: Option<u32>,
156
157 pub cm_server_version: Option<u32>,
159
160 pub cm_session_timeout_minutes: Option<u32>,
162
163 pub cnm_http_max_threads_per_worker: Option<u32>,
165
166 pub cnm_http_workers: Option<u32>,
168
169 pub control_cipher_suites: Option<String>,
171
172 pub control_cipher_suites_tls_1_3: Option<String>,
174
175 pub crdb_coordinator_ignore_requests: Option<bool>,
177
178 pub crdb_coordinator_port: Option<u32>,
180
181 pub crdt_supported_featureset_version: Option<u32>,
183
184 pub crdt_supported_protocol_versions: Option<Vec<String>>,
186
187 pub created_time: Option<String>,
189
190 pub data_cipher_list: Option<String>,
192
193 pub data_cipher_suites_tls_1_3: Option<Vec<Value>>,
195
196 pub debuginfo_path: Option<String>,
198
199 pub encrypt_pkeys: Option<bool>,
201
202 pub entra_id_cache_ttl: Option<u32>,
204
205 pub envoy_admin_port: Option<u32>,
207
208 pub envoy_external_authorization: Option<bool>,
210
211 pub envoy_max_downstream_connections: Option<u32>,
213
214 pub envoy_mgmt_server_port: Option<u32>,
216
217 pub gossip_envoy_admin_port: Option<u32>,
219
220 pub handle_metrics_redirects: Option<bool>,
222
223 pub handle_redirects: Option<bool>,
225
226 pub http_support: Option<bool>,
228
229 pub logrotate_settings: Option<Value>,
231
232 pub mask_bdb_credentials: Option<bool>,
234
235 pub metrics_system: Option<u32>,
237
238 #[serde(rename = "min_control_TLS_version")]
240 pub min_control_tls_version: Option<String>,
241
242 #[serde(rename = "min_data_TLS_version")]
244 pub min_data_tls_version: Option<String>,
245
246 #[serde(rename = "min_sentinel_TLS_version")]
248 pub min_sentinel_tls_version: Option<String>,
249
250 pub module_upload_max_size_mb: Option<u32>,
252
253 pub mtls_authorized_subjects: Option<Vec<String>>,
255
256 pub mtls_certificate_authentication: Option<bool>,
258
259 pub mtls_client_cert_subject_validation_type: Option<String>,
261
262 pub multi_commands_opt: Option<String>,
264
265 pub options_method_forbidden: Option<bool>,
267
268 pub password_complexity: Option<bool>,
270
271 pub password_expiration_duration: Option<u32>,
273
274 pub password_hashing_algorithm: Option<String>,
276
277 pub password_min_length: Option<u32>,
279
280 pub proxy_certificate: Option<String>,
282
283 pub reserved_ports: Option<Vec<u32>>,
285
286 pub robust_crdt_syncer: Option<bool>,
288
289 pub s3_certificate_verification: Option<bool>,
291
292 pub sentinel_cipher_suites: Option<Vec<String>>,
294
295 pub sentinel_cipher_suites_tls_1_3: Option<String>,
297
298 pub sentinel_tls_mode: Option<String>,
300
301 pub slave_ha: Option<bool>,
303
304 pub slave_ha_bdb_cooldown_period: Option<u32>,
306
307 pub slave_ha_cooldown_period: Option<u32>,
309
310 pub slave_ha_grace_period: Option<u32>,
312
313 pub slowlog_in_sanitized_support: Option<bool>,
315
316 pub smtp_tls_mode: Option<String>,
318
319 pub smtp_use_tls: Option<bool>,
321
322 pub syncer_certificate: Option<String>,
324
325 pub system_reserved_ports: Option<Vec<u32>>,
327
328 pub upgrade_in_progress: Option<bool>,
330
331 pub upgrade_mode: Option<bool>,
333
334 pub use_external_ipv6: Option<bool>,
336
337 pub use_ipv6: Option<bool>,
339
340 pub wait_command: Option<bool>,
342
343 #[serde(flatten)]
344 pub extra: Value,
345}
346
347#[derive(Debug, Clone, Serialize, Deserialize)]
349pub struct ClusterSettings {
350 pub auto_recovery: Option<bool>,
352
353 pub automatic_node_offload: Option<bool>,
355
356 pub bigstore_migrate_node_threshold: Option<u32>,
358 pub bigstore_migrate_node_threshold_p: Option<u32>,
359 pub bigstore_provision_node_threshold: Option<u32>,
360 pub bigstore_provision_node_threshold_p: Option<u32>,
361
362 pub default_bigstore_version: Option<u32>,
364
365 pub data_internode_encryption: Option<bool>,
367
368 pub db_conns_auditing: Option<bool>,
370
371 pub default_concurrent_restore_actions: Option<u32>,
373
374 pub default_fork_evict_ram: Option<bool>,
376
377 pub default_non_sharded_proxy_policy: Option<String>,
379 pub default_sharded_proxy_policy: Option<String>,
380
381 pub default_oss_cluster: Option<bool>,
383 pub default_oss_sharding: Option<bool>,
384
385 pub default_provisioned_redis_version: Option<String>,
387
388 pub default_recovery_wait_time: Option<u32>,
390
391 pub default_shards_placement: Option<String>,
393
394 pub default_tracking_table_max_keys_policy: Option<String>,
396
397 pub email_alerts: Option<bool>,
399 pub endpoint_rebind_enabled: Option<bool>,
400 pub failure_detection_sensitivity: Option<String>,
401 pub gossip_envoy_admin_port: Option<u32>,
402 pub gossip_envoy_port: Option<u32>,
403 pub gossip_envoy_proxy_mode: Option<bool>,
404 pub hot_spare: Option<bool>,
405 pub max_saved_events_per_type: Option<u32>,
406 pub max_simultaneous_backups: Option<u32>,
407 pub parallel_shards_upgrade: Option<u32>,
408 pub persistent_node_removal: Option<bool>,
409 pub rack_aware: Option<bool>,
410 pub redis_migrate_node_threshold: Option<String>,
411 pub redis_migrate_node_threshold_p: Option<u32>,
412 pub redis_provision_node_threshold: Option<String>,
413 pub redis_provision_node_threshold_p: Option<u32>,
414 pub redis_upgrade_policy: Option<String>,
415 pub resp3_default: Option<bool>,
416 pub show_internals: Option<bool>,
417 pub slave_threads_when_master: Option<bool>,
418 pub use_empty_shard_backups: Option<bool>,
419
420 #[serde(flatten)]
421 pub extra: Value,
422}
423
424#[derive(Debug, Serialize, TypedBuilder)]
426pub struct BootstrapRequest {
427 #[builder(setter(into))]
428 pub action: String,
429 pub cluster: ClusterBootstrapInfo,
430 pub credentials: BootstrapCredentials,
431}
432
433#[derive(Debug, Serialize, TypedBuilder)]
435pub struct ClusterBootstrapInfo {
436 #[builder(setter(into))]
437 pub name: String,
438}
439
440#[derive(Debug, Serialize, TypedBuilder)]
442pub struct BootstrapCredentials {
443 #[builder(setter(into))]
444 pub username: String,
445 #[builder(setter(into))]
446 pub password: String,
447}
448
449pub struct ClusterHandler {
451 client: RestClient,
452}
453
454impl ClusterHandler {
455 pub fn new(client: RestClient) -> Self {
456 ClusterHandler { client }
457 }
458
459 pub async fn info(&self) -> Result<ClusterInfo> {
461 self.client.get("/v1/cluster").await
462 }
463
464 pub async fn bootstrap(&self, request: BootstrapRequest) -> Result<Value> {
466 self.client
469 .post_bootstrap("/v1/bootstrap/create_cluster", &request)
470 .await
471 }
472
473 pub async fn update(&self, updates: Value) -> Result<Value> {
475 self.client.put("/v1/cluster", &updates).await
476 }
477
478 pub async fn stats(&self) -> Result<Value> {
480 self.client.get("/v1/cluster/stats").await
481 }
482
483 pub async fn nodes(&self) -> Result<Vec<NodeInfo>> {
485 self.client.get("/v1/nodes").await
486 }
487
488 pub async fn license(&self) -> Result<LicenseInfo> {
490 self.client.get("/v1/license").await
491 }
492
493 pub async fn join_node(
495 &self,
496 node_address: &str,
497 username: &str,
498 password: &str,
499 ) -> Result<Value> {
500 let body = serde_json::json!({
501 "action": "join_cluster",
502 "cluster": {
503 "nodes": [node_address]
504 },
505 "credentials": {
506 "username": username,
507 "password": password
508 }
509 });
510 self.client.post("/v1/bootstrap/join", &body).await
511 }
512
513 pub async fn remove_node(&self, node_uid: u32) -> Result<Value> {
515 self.client
516 .delete(&format!("/v1/nodes/{}", node_uid))
517 .await?;
518 Ok(serde_json::json!({"message": format!("Node {} removed", node_uid)}))
519 }
520
521 pub async fn reset(&self) -> Result<ClusterActionResponse> {
523 self.client
524 .post("/v1/cluster/actions/reset", &serde_json::json!({}))
525 .await
526 }
527
528 pub async fn recover(&self) -> Result<ClusterActionResponse> {
532 self.client
533 .post("/v1/cluster/actions/recover", &serde_json::json!({}))
534 .await
535 }
536
537 pub async fn settings(&self) -> Result<Value> {
541 self.client.get("/v1/cluster/settings").await
542 }
543
544 pub async fn topology(&self) -> Result<Value> {
546 self.client.get("/v1/cluster/topology").await
547 }
548
549 pub async fn actions(&self) -> Result<Value> {
551 self.client.get("/v1/cluster/actions").await
552 }
553
554 pub async fn action_detail(&self, action: &str) -> Result<Value> {
556 self.client
557 .get(&format!("/v1/cluster/actions/{}", action))
558 .await
559 }
560
561 pub async fn action_execute(&self, action: &str, body: Value) -> Result<Value> {
563 self.client
564 .post(&format!("/v1/cluster/actions/{}", action), &body)
565 .await
566 }
567
568 pub async fn action_delete(&self, action: &str) -> Result<()> {
570 self.client
571 .delete(&format!("/v1/cluster/actions/{}", action))
572 .await
573 }
574
575 pub async fn auditing_db_conns(&self) -> Result<Value> {
577 self.client.get("/v1/cluster/auditing/db_conns").await
578 }
579
580 pub async fn auditing_db_conns_update(&self, cfg: Value) -> Result<Value> {
582 self.client.put("/v1/cluster/auditing/db_conns", &cfg).await
583 }
584
585 pub async fn auditing_db_conns_delete(&self) -> Result<()> {
587 self.client.delete("/v1/cluster/auditing/db_conns").await
588 }
589
590 pub async fn certificates(&self) -> Result<Value> {
592 self.client.get("/v1/cluster/certificates").await
593 }
594
595 pub async fn certificate_delete(&self, uid: u32) -> Result<()> {
597 self.client
598 .delete(&format!("/v1/cluster/certificates/{}", uid))
599 .await
600 }
601
602 pub async fn certificates_rotate(&self) -> Result<Value> {
604 self.client
605 .post("/v1/cluster/certificates/rotate", &serde_json::json!({}))
606 .await
607 }
608
609 pub async fn update_cert(&self, body: Value) -> Result<Value> {
611 self.client.put("/v1/cluster/update_cert", &body).await
612 }
613
614 pub async fn ldap_delete(&self) -> Result<()> {
616 self.client.delete("/v1/cluster/ldap").await
617 }
618
619 pub async fn module_capabilities(&self) -> Result<Value> {
621 self.client.get("/v1/cluster/module-capabilities").await
622 }
623
624 pub async fn policy(&self) -> Result<Value> {
626 self.client.get("/v1/cluster/policy").await
627 }
628
629 pub async fn policy_update(&self, policy: Value) -> Result<Value> {
631 self.client.put("/v1/cluster/policy", &policy).await
632 }
633
634 pub async fn policy_restore_default(&self) -> Result<Value> {
636 self.client
637 .put("/v1/cluster/policy/restore_default", &serde_json::json!({}))
638 .await
639 }
640
641 pub async fn services_configuration(&self) -> Result<Value> {
643 self.client.get("/v1/cluster/services_configuration").await
644 }
645
646 pub async fn services_configuration_update(&self, cfg: Value) -> Result<Value> {
648 self.client
649 .put("/v1/cluster/services_configuration", &cfg)
650 .await
651 }
652
653 pub async fn witness_disk(&self) -> Result<Value> {
655 self.client.get("/v1/cluster/witness_disk").await
656 }
657
658 pub async fn alert_detail(&self, alert: &str) -> Result<Value> {
660 self.client
661 .get(&format!("/v1/cluster/alerts/{}", alert))
662 .await
663 }
664}
665
666#[derive(Debug, Clone, Serialize, Deserialize)]
668pub struct NodeInfo {
669 pub uid: u32,
670 pub address: String,
671 pub status: String,
672 pub role: Option<String>,
673 pub shards: Option<Vec<u32>>,
674 pub total_memory: Option<u64>,
675 pub used_memory: Option<u64>,
676
677 #[serde(flatten)]
678 pub extra: Value,
679}
680
681#[derive(Debug, Clone, Serialize, Deserialize)]
683pub struct LicenseInfo {
684 pub license_type: Option<String>,
685 pub expired: Option<bool>,
686 pub expiration_date: Option<String>,
687 pub shards_limit: Option<u32>,
688 pub features: Option<Vec<String>>,
689
690 #[serde(flatten)]
691 pub extra: Value,
692}