1use crate::client::RestClient;
9use crate::error::Result;
10use serde::{Deserialize, Serialize};
11use serde_json::Value;
12use typed_builder::TypedBuilder;
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct NodeActionResponse {
17 pub action_uid: String,
19 pub description: Option<String>,
21 #[serde(flatten)]
23 pub extra: Value,
24}
25
26#[derive(Debug, Clone, Serialize, Deserialize)]
28pub struct Node {
29 pub uid: u32,
30
31 #[serde(rename = "addr")]
33 pub addr: Option<String>,
34
35 pub status: String,
36
37 pub accept_servers: Option<bool>,
39
40 pub architecture: Option<String>,
42
43 #[serde(rename = "cores")]
45 pub cores: Option<u32>,
46
47 pub external_addr: Option<Vec<String>>,
49
50 pub total_memory: Option<u64>,
52
53 pub os_version: Option<String>,
55 pub os_name: Option<String>,
56 pub os_family: Option<String>,
57 pub os_semantic_version: Option<String>,
58
59 pub ephemeral_storage_size: Option<f64>,
61 pub persistent_storage_size: Option<f64>,
62
63 pub ephemeral_storage_path: Option<String>,
65 pub persistent_storage_path: Option<String>,
66 pub bigredis_storage_path: Option<String>,
67
68 pub rack_id: Option<String>,
70 pub second_rack_id: Option<String>,
71
72 pub shard_count: Option<u32>,
74 pub shard_list: Option<Vec<u32>>,
75 pub ram_shard_count: Option<u32>,
76 pub flash_shard_count: Option<u32>,
77
78 pub bigstore_enabled: Option<bool>,
80 pub fips_enabled: Option<bool>,
81 pub use_internal_ipv6: Option<bool>,
82
83 pub max_listeners: Option<u32>,
85 pub max_redis_servers: Option<u32>,
86 pub max_redis_forks: Option<i32>,
87 pub max_slave_full_syncs: Option<i32>,
88
89 pub uptime: Option<u64>,
91 pub software_version: Option<String>,
92
93 pub supported_database_versions: Option<Vec<Value>>,
95
96 #[serde(flatten)]
98 pub extra: Value,
99}
100
101#[derive(Debug, Clone, Serialize, Deserialize)]
103pub struct NodeStats {
104 pub uid: u32,
105 pub cpu_user: Option<f64>,
106 pub cpu_system: Option<f64>,
107 pub cpu_idle: Option<f64>,
108 pub free_memory: Option<u64>,
109 pub network_bytes_in: Option<u64>,
110 pub network_bytes_out: Option<u64>,
111 pub persistent_storage_free: Option<u64>,
112 pub ephemeral_storage_free: Option<u64>,
113
114 #[serde(flatten)]
115 pub extra: Value,
116}
117
118#[derive(Debug, Serialize, TypedBuilder)]
120pub struct NodeActionRequest {
121 #[builder(setter(into))]
122 pub action: String,
123 #[serde(skip_serializing_if = "Option::is_none")]
124 #[builder(default, setter(strip_option))]
125 pub node_uid: Option<u32>,
126}
127
128pub struct NodeHandler {
130 client: RestClient,
131}
132
133pub type NodesHandler = NodeHandler;
135
136impl NodeHandler {
137 pub fn new(client: RestClient) -> Self {
138 NodeHandler { client }
139 }
140
141 pub async fn list(&self) -> Result<Vec<Node>> {
143 self.client.get("/v1/nodes").await
144 }
145
146 pub async fn get(&self, uid: u32) -> Result<Node> {
148 self.client.get(&format!("/v1/nodes/{}", uid)).await
149 }
150
151 pub async fn update(&self, uid: u32, updates: Value) -> Result<Node> {
153 self.client
154 .put(&format!("/v1/nodes/{}", uid), &updates)
155 .await
156 }
157
158 pub async fn remove(&self, uid: u32) -> Result<()> {
160 self.client.delete(&format!("/v1/nodes/{}", uid)).await
161 }
162
163 pub async fn stats(&self, uid: u32) -> Result<NodeStats> {
165 self.client.get(&format!("/v1/nodes/{}/stats", uid)).await
166 }
167
168 pub async fn actions(&self, uid: u32) -> Result<Value> {
170 self.client.get(&format!("/v1/nodes/{}/actions", uid)).await
171 }
172
173 pub async fn execute_action(&self, uid: u32, action: &str) -> Result<NodeActionResponse> {
175 let request = NodeActionRequest {
176 action: action.to_string(),
177 node_uid: Some(uid),
178 };
179 self.client
180 .post(&format!("/v1/nodes/{}/actions", uid), &request)
181 .await
182 }
183
184 pub async fn list_actions(&self) -> Result<Value> {
188 self.client.get("/v1/nodes/actions").await
189 }
190
191 pub async fn action_detail(&self, uid: u32, action: &str) -> Result<Value> {
193 self.client
194 .get(&format!("/v1/nodes/{}/actions/{}", uid, action))
195 .await
196 }
197
198 pub async fn action_execute(&self, uid: u32, action: &str, body: Value) -> Result<Value> {
200 self.client
201 .post(&format!("/v1/nodes/{}/actions/{}", uid, action), &body)
202 .await
203 }
204
205 pub async fn action_delete(&self, uid: u32, action: &str) -> Result<()> {
207 self.client
208 .delete(&format!("/v1/nodes/{}/actions/{}", uid, action))
209 .await
210 }
211
212 pub async fn snapshots(&self, uid: u32) -> Result<Value> {
214 self.client
215 .get(&format!("/v1/nodes/{}/snapshots", uid))
216 .await
217 }
218
219 pub async fn snapshot_create(&self, uid: u32, name: &str) -> Result<Value> {
221 self.client
222 .post(
223 &format!("/v1/nodes/{}/snapshots/{}", uid, name),
224 &serde_json::json!({}),
225 )
226 .await
227 }
228
229 pub async fn snapshot_delete(&self, uid: u32, name: &str) -> Result<()> {
231 self.client
232 .delete(&format!("/v1/nodes/{}/snapshots/{}", uid, name))
233 .await
234 }
235
236 pub async fn status_all(&self) -> Result<Value> {
238 self.client.get("/v1/nodes/status").await
239 }
240
241 pub async fn wd_status_all(&self) -> Result<Value> {
243 self.client.get("/v1/nodes/wd_status").await
244 }
245
246 pub async fn status(&self, uid: u32) -> Result<Value> {
248 self.client.get(&format!("/v1/nodes/{}/status", uid)).await
249 }
250
251 pub async fn wd_status(&self, uid: u32) -> Result<Value> {
253 self.client
254 .get(&format!("/v1/nodes/{}/wd_status", uid))
255 .await
256 }
257
258 pub async fn alerts_all(&self) -> Result<Value> {
260 self.client.get("/v1/nodes/alerts").await
261 }
262
263 pub async fn alerts_for(&self, uid: u32) -> Result<Value> {
265 self.client.get(&format!("/v1/nodes/alerts/{}", uid)).await
266 }
267
268 pub async fn alert_detail(&self, uid: u32, alert: &str) -> Result<Value> {
270 self.client
271 .get(&format!("/v1/nodes/alerts/{}/{}", uid, alert))
272 .await
273 }
274}