redis_enterprise/
bootstrap.rs

1//! Bootstrap operations for Redis Enterprise cluster initialization
2
3use crate::client::RestClient;
4use crate::error::Result;
5use serde::{Deserialize, Serialize};
6use serde_json::Value;
7
8/// Bootstrap configuration for cluster initialization
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct BootstrapConfig {
11    pub action: String,
12    #[serde(skip_serializing_if = "Option::is_none")]
13    pub cluster: Option<ClusterBootstrap>,
14    #[serde(skip_serializing_if = "Option::is_none")]
15    pub node: Option<NodeBootstrap>,
16    #[serde(skip_serializing_if = "Option::is_none")]
17    pub credentials: Option<CredentialsBootstrap>,
18
19    #[serde(flatten)]
20    pub extra: Value,
21}
22
23/// Cluster bootstrap configuration
24#[derive(Debug, Clone, Serialize, Deserialize)]
25pub struct ClusterBootstrap {
26    pub name: String,
27    #[serde(skip_serializing_if = "Option::is_none")]
28    pub dns_suffixes: Option<Vec<String>>,
29    #[serde(skip_serializing_if = "Option::is_none")]
30    pub rack_aware: Option<bool>,
31}
32
33/// Node bootstrap configuration
34#[derive(Debug, Clone, Serialize, Deserialize)]
35pub struct NodeBootstrap {
36    #[serde(skip_serializing_if = "Option::is_none")]
37    pub paths: Option<NodePaths>,
38}
39
40/// Node paths configuration
41#[derive(Debug, Clone, Serialize, Deserialize)]
42pub struct NodePaths {
43    #[serde(skip_serializing_if = "Option::is_none")]
44    pub persistent_path: Option<String>,
45    #[serde(skip_serializing_if = "Option::is_none")]
46    pub ephemeral_path: Option<String>,
47}
48
49/// Credentials bootstrap configuration
50#[derive(Debug, Clone, Serialize, Deserialize)]
51pub struct CredentialsBootstrap {
52    pub username: String,
53    pub password: String,
54}
55
56/// Bootstrap status response
57#[derive(Debug, Clone, Serialize, Deserialize)]
58pub struct BootstrapStatus {
59    pub status: String,
60    #[serde(skip_serializing_if = "Option::is_none")]
61    pub progress: Option<f32>,
62    #[serde(skip_serializing_if = "Option::is_none")]
63    pub message: Option<String>,
64
65    #[serde(flatten)]
66    pub extra: Value,
67}
68
69/// Bootstrap handler for cluster initialization
70pub struct BootstrapHandler {
71    client: RestClient,
72}
73
74impl BootstrapHandler {
75    pub fn new(client: RestClient) -> Self {
76        BootstrapHandler { client }
77    }
78
79    /// Initialize cluster bootstrap
80    pub async fn create(&self, config: BootstrapConfig) -> Result<BootstrapStatus> {
81        self.client.post("/v1/bootstrap", &config).await
82    }
83
84    /// Get bootstrap status
85    pub async fn status(&self) -> Result<BootstrapStatus> {
86        self.client.get("/v1/bootstrap").await
87    }
88
89    /// Join node to existing cluster
90    pub async fn join(&self, config: BootstrapConfig) -> Result<BootstrapStatus> {
91        self.client.post("/v1/bootstrap/join", &config).await
92    }
93
94    /// Reset bootstrap (dangerous operation)
95    pub async fn reset(&self) -> Result<()> {
96        self.client.delete("/v1/bootstrap").await
97    }
98}