1use crate::client::RestClient;
9use crate::error::Result;
10use serde::{Deserialize, Serialize};
11use serde_json::Value;
12use std::collections::BTreeMap;
13use typed_builder::TypedBuilder;
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct NodeActionResponse {
18 pub action_uid: String,
20 pub description: Option<String>,
22}
23
24#[derive(Debug, Clone, Serialize, Deserialize)]
26#[non_exhaustive]
27pub struct Node {
28 pub uid: u32,
30
31 #[serde(rename = "addr")]
33 pub addr: Option<String>,
34
35 pub status: String,
37
38 pub accept_servers: Option<bool>,
40
41 pub architecture: Option<String>,
43
44 #[serde(rename = "cores")]
46 pub cores: Option<u32>,
47
48 pub external_addr: Option<Vec<String>>,
50
51 pub total_memory: Option<u64>,
53
54 pub os_version: Option<String>,
56 pub os_name: Option<String>,
58 pub os_family: Option<String>,
60 pub os_semantic_version: Option<String>,
62
63 pub ephemeral_storage_size: Option<f64>,
65 pub persistent_storage_size: Option<f64>,
67
68 pub ephemeral_storage_path: Option<String>,
70 pub persistent_storage_path: Option<String>,
72 pub bigredis_storage_path: Option<String>,
74
75 pub rack_id: Option<String>,
77 pub second_rack_id: Option<String>,
79
80 pub shard_count: Option<u32>,
82 pub shard_list: Option<Vec<u32>>,
84 pub ram_shard_count: Option<u32>,
86 pub flash_shard_count: Option<u32>,
88
89 pub bigstore_enabled: Option<bool>,
91 pub fips_enabled: Option<bool>,
93 pub use_internal_ipv6: Option<bool>,
95
96 pub max_listeners: Option<u32>,
98 pub max_redis_servers: Option<u32>,
100 pub max_redis_forks: Option<i32>,
102 pub max_slave_full_syncs: Option<i32>,
104
105 pub uptime: Option<u64>,
107 pub software_version: Option<String>,
109
110 pub supported_database_versions: Option<Vec<Value>>,
112
113 pub bigstore_driver: Option<String>,
115
116 pub bigstore_size: Option<u64>,
118
119 pub public_addr: Option<String>,
121
122 pub recovery_path: Option<String>,
124
125 pub node_guardrails_ingress_throttling_worker_limit_ops_per_sec: Option<i64>,
129
130 #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
132 pub additional_fields: BTreeMap<String, Value>,
133}
134
135#[derive(Debug, Clone, Serialize, Deserialize)]
137pub struct NodeStats {
138 pub uid: u32,
140 pub cpu_user: Option<f64>,
142 pub cpu_system: Option<f64>,
144 pub cpu_idle: Option<f64>,
146 pub free_memory: Option<u64>,
148 pub network_bytes_in: Option<u64>,
150 pub network_bytes_out: Option<u64>,
152 pub persistent_storage_free: Option<u64>,
154 pub ephemeral_storage_free: Option<u64>,
156}
157
158#[derive(Debug, Serialize, TypedBuilder)]
160pub struct NodeActionRequest {
161 #[builder(setter(into))]
163 pub action: String,
164 #[serde(skip_serializing_if = "Option::is_none")]
166 #[builder(default, setter(strip_option))]
167 pub node_uid: Option<u32>,
168}
169
170pub struct NodeHandler {
172 client: RestClient,
173}
174
175pub type NodesHandler = NodeHandler;
177
178impl NodeHandler {
179 pub fn new(client: RestClient) -> Self {
181 NodeHandler { client }
182 }
183
184 pub async fn list(&self) -> Result<Vec<Node>> {
186 self.client.get("/v1/nodes").await
187 }
188
189 pub async fn get(&self, uid: u32) -> Result<Node> {
191 self.client.get(&format!("/v1/nodes/{}", uid)).await
192 }
193
194 pub async fn update(&self, uid: u32, updates: Value) -> Result<Node> {
196 self.client
197 .put(&format!("/v1/nodes/{}", uid), &updates)
198 .await
199 }
200
201 pub async fn remove(&self, uid: u32) -> Result<()> {
203 self.client
204 .post_action(&format!("/v1/nodes/{}/actions/remove", uid), &Value::Null)
205 .await
206 }
207
208 pub async fn check(&self, uid: u32) -> Result<Value> {
210 self.client.get(&format!("/v1/nodes/check/{}", uid)).await
211 }
212
213 pub async fn stats(&self, uid: u32) -> Result<NodeStats> {
215 self.client.get(&format!("/v1/nodes/stats/{}", uid)).await
216 }
217
218 pub async fn actions(&self, uid: u32) -> Result<Value> {
220 self.client.get(&format!("/v1/nodes/{}/actions", uid)).await
221 }
222
223 pub async fn execute_action(&self, uid: u32, action: &str) -> Result<NodeActionResponse> {
234 let response: Value = self
235 .client
236 .post(
237 &format!("/v1/nodes/{}/actions/{}", uid, action),
238 &serde_json::json!({}),
239 )
240 .await?;
241 serde_json::from_value(response).map_err(Into::into)
242 }
243
244 pub async fn list_actions(&self) -> Result<Value> {
248 self.client.get("/v1/nodes/actions").await
249 }
250
251 pub async fn action_detail(&self, uid: u32, action: &str) -> Result<Value> {
253 self.client
254 .get(&format!("/v1/nodes/{}/actions/{}", uid, action))
255 .await
256 }
257
258 pub async fn action_execute(&self, uid: u32, action: &str, body: Value) -> Result<Value> {
260 self.client
261 .post(&format!("/v1/nodes/{}/actions/{}", uid, action), &body)
262 .await
263 }
264
265 pub async fn action_delete(&self, uid: u32, action: &str) -> Result<()> {
267 self.client
268 .delete(&format!("/v1/nodes/{}/actions/{}", uid, action))
269 .await
270 }
271
272 pub async fn snapshots(&self, uid: u32) -> Result<Value> {
274 self.client
275 .get(&format!("/v1/nodes/{}/snapshots", uid))
276 .await
277 }
278
279 pub async fn snapshot_create(&self, uid: u32, name: &str) -> Result<Value> {
281 self.client
282 .post(
283 &format!("/v1/nodes/{}/snapshots/{}", uid, name),
284 &serde_json::json!({}),
285 )
286 .await
287 }
288
289 pub async fn snapshot_delete(&self, uid: u32, name: &str) -> Result<()> {
291 self.client
292 .delete(&format!("/v1/nodes/{}/snapshots/{}", uid, name))
293 .await
294 }
295
296 pub async fn status_all(&self) -> Result<Value> {
298 self.client.get("/v1/nodes/status").await
299 }
300
301 pub async fn wd_status_all(&self) -> Result<Value> {
303 self.client.get("/v1/nodes/wd_status").await
304 }
305
306 pub async fn status(&self, uid: u32) -> Result<Value> {
308 self.client.get(&format!("/v1/nodes/{}/status", uid)).await
309 }
310
311 pub async fn wd_status(&self, uid: u32) -> Result<Value> {
313 self.client
314 .get(&format!("/v1/nodes/{}/wd_status", uid))
315 .await
316 }
317
318 pub async fn alerts_all(&self) -> Result<Value> {
320 self.client.get("/v1/nodes/alerts").await
321 }
322
323 pub async fn alerts_for(&self, uid: u32) -> Result<Value> {
325 self.client.get(&format!("/v1/nodes/alerts/{}", uid)).await
326 }
327
328 pub async fn alert_detail(&self, uid: u32, alert: &str) -> Result<Value> {
330 self.client
331 .get(&format!("/v1/nodes/alerts/{}/{}", uid, alert))
332 .await
333 }
334}