1pub mod rhai;
40
41use lazy_static::lazy_static;
42use serde_json::Value;
43use std::collections::HashMap;
44use std::sync::atomic::{AtomicBool, Ordering};
45use std::sync::{Arc, Mutex};
46use zinit_client::{ServiceState, ServiceStatus as Status, ZinitClient, ZinitError};
47
48lazy_static! {
50 static ref ZINIT_CLIENT: Mutex<Option<Arc<ZinitClientWrapper>>> = Mutex::new(None);
51}
52
53pub struct ZinitClientWrapper {
55 client: ZinitClient,
56 initialized: AtomicBool,
57}
58
59impl ZinitClientWrapper {
60 fn new(client: ZinitClient) -> Self {
62 ZinitClientWrapper {
63 client,
64 initialized: AtomicBool::new(false),
65 }
66 }
67
68 async fn initialize(&self) -> Result<(), ZinitError> {
70 if self.initialized.load(Ordering::Relaxed) {
71 return Ok(());
72 }
73
74 let _ = self.client.list().await.map_err(|e| {
76 log::error!("Failed to initialize Zinit client: {}", e);
77 e
78 })?;
79
80 self.initialized.store(true, Ordering::Relaxed);
81 Ok(())
82 }
83
84 pub async fn list(&self) -> Result<HashMap<String, ServiceState>, ZinitError> {
86 self.client.list().await
87 }
88
89 pub async fn status(&self, name: &str) -> Result<Status, ZinitError> {
91 self.client.status(name).await
92 }
93
94 pub async fn start(&self, name: &str) -> Result<(), ZinitError> {
96 self.client.start(name).await
97 }
98
99 pub async fn stop(&self, name: &str) -> Result<(), ZinitError> {
101 self.client.stop(name).await
102 }
103
104 pub async fn restart(&self, name: &str) -> Result<(), ZinitError> {
106 self.client.restart(name).await
107 }
108
109 pub async fn monitor(&self, name: &str) -> Result<(), ZinitError> {
111 self.client.monitor(name).await
112 }
113
114 pub async fn forget(&self, name: &str) -> Result<(), ZinitError> {
116 self.client.forget(name).await
117 }
118
119 pub async fn kill(&self, name: &str, signal: Option<&str>) -> Result<(), ZinitError> {
121 let signal_str = signal.unwrap_or("TERM");
122 self.client.kill(name, signal_str).await
123 }
124
125 pub async fn create_service(
127 &self,
128 name: &str,
129 service_config: Value,
130 ) -> Result<(), ZinitError> {
131 self.client.create_service(name, service_config).await
132 }
133
134 pub async fn delete_service(&self, name: &str) -> Result<(), ZinitError> {
136 self.client.delete_service(name).await
137 }
138
139 pub async fn get_service(&self, name: &str) -> Result<Value, ZinitError> {
141 self.client.get_service(name).await
142 }
143
144 pub async fn reboot(&self) -> Result<(), ZinitError> {
146 self.client.reboot().await
147 }
148
149 pub async fn logs(&self, filter: Option<String>) -> Result<Vec<String>, ZinitError> {
151 use futures::StreamExt;
152
153 let follow = false; let mut log_stream = self.client.logs(follow, filter).await?;
156 let mut logs = Vec::new();
157
158 let mut count = 0;
160 const MAX_LOGS: usize = 1000;
161
162 while let Some(log_result) = log_stream.next().await {
163 match log_result {
164 Ok(log_entry) => {
165 logs.push(format!("{:?}", log_entry));
167 count += 1;
168 if count >= MAX_LOGS {
169 break;
170 }
171 }
172 Err(e) => {
173 log::warn!("Error reading log entry: {}", e);
174 break;
175 }
176 }
177 }
178
179 Ok(logs)
180 }
181}
182
183pub async fn get_zinit_client(socket_path: &str) -> Result<Arc<ZinitClientWrapper>, ZinitError> {
185 {
187 let guard = ZINIT_CLIENT.lock().unwrap();
188 if let Some(ref client) = &*guard {
189 return Ok(Arc::clone(client));
190 }
191 }
192
193 let client = create_zinit_client(socket_path).await?;
195
196 {
198 let mut guard = ZINIT_CLIENT.lock().unwrap();
199 *guard = Some(Arc::clone(&client));
200 }
201
202 Ok(client)
203}
204
205async fn create_zinit_client(socket_path: &str) -> Result<Arc<ZinitClientWrapper>, ZinitError> {
207 let client = ZinitClient::new(socket_path);
209 let wrapper = Arc::new(ZinitClientWrapper::new(client));
210
211 wrapper.initialize().await?;
213
214 Ok(wrapper)
215}
216
217pub async fn reset(socket_path: &str) -> Result<(), ZinitError> {
219 {
221 let mut client_guard = ZINIT_CLIENT.lock().unwrap();
222 *client_guard = None;
223 }
224
225 get_zinit_client(socket_path).await?;
227 Ok(())
228}
229
230pub async fn list(socket_path: &str) -> Result<HashMap<String, String>, ZinitError> {
234 let client = get_zinit_client(socket_path).await?;
235 let services = client.list().await?;
236
237 let mut result = HashMap::new();
239 for (name, state) in services {
240 result.insert(name, format!("{:?}", state));
241 }
242
243 Ok(result)
244}
245
246pub async fn status(socket_path: &str, name: &str) -> Result<Status, ZinitError> {
248 let client = get_zinit_client(socket_path).await?;
249 client.status(name).await
250}
251
252pub async fn start(socket_path: &str, name: &str) -> Result<(), ZinitError> {
254 let client = get_zinit_client(socket_path).await?;
255 client.start(name).await
256}
257
258pub async fn stop(socket_path: &str, name: &str) -> Result<(), ZinitError> {
260 let client = get_zinit_client(socket_path).await?;
261 client.stop(name).await
262}
263
264pub async fn restart(socket_path: &str, name: &str) -> Result<(), ZinitError> {
266 let client = get_zinit_client(socket_path).await?;
267 client.restart(name).await
268}
269
270pub async fn monitor(socket_path: &str, name: &str) -> Result<(), ZinitError> {
272 let client = get_zinit_client(socket_path).await?;
273 client.monitor(name).await
274}
275
276pub async fn forget(socket_path: &str, name: &str) -> Result<(), ZinitError> {
278 let client = get_zinit_client(socket_path).await?;
279 client.forget(name).await
280}
281
282pub async fn kill(socket_path: &str, name: &str, signal: Option<&str>) -> Result<(), ZinitError> {
284 let client = get_zinit_client(socket_path).await?;
285 client.kill(name, signal).await
286}
287
288pub async fn create_service(
290 socket_path: &str,
291 name: &str,
292 exec: &str,
293 oneshot: bool,
294) -> Result<(), ZinitError> {
295 use serde_json::json;
296
297 let service_config = json!({
298 "exec": exec,
299 "oneshot": oneshot
300 });
301
302 let client = get_zinit_client(socket_path).await?;
303 client.create_service(name, service_config).await
304}
305
306pub async fn create_service_full(
308 socket_path: &str,
309 name: &str,
310 exec: &str,
311 oneshot: bool,
312 after: Option<Vec<String>>,
313 env: Option<HashMap<String, String>>,
314 log: Option<String>,
315 test: Option<String>,
316) -> Result<(), ZinitError> {
317 use serde_json::json;
318
319 let mut service_config = json!({
320 "exec": exec,
321 "oneshot": oneshot
322 });
323
324 if let Some(after_deps) = after {
325 service_config["after"] = json!(after_deps);
326 }
327 if let Some(environment) = env {
328 service_config["env"] = json!(environment);
329 }
330 if let Some(log_path) = log {
331 service_config["log"] = json!(log_path);
332 }
333 if let Some(test_cmd) = test {
334 service_config["test"] = json!(test_cmd);
335 }
336
337 let client = get_zinit_client(socket_path).await?;
338 client.create_service(name, service_config).await
339}
340
341pub async fn delete_service(socket_path: &str, name: &str) -> Result<(), ZinitError> {
343 let client = get_zinit_client(socket_path).await?;
344 client.delete_service(name).await
345}
346
347pub async fn get_service(socket_path: &str, name: &str) -> Result<Value, ZinitError> {
349 let client = get_zinit_client(socket_path).await?;
350 client.get_service(name).await
351}
352
353pub async fn reboot(socket_path: &str) -> Result<(), ZinitError> {
355 let client = get_zinit_client(socket_path).await?;
356 client.reboot().await
357}
358
359pub async fn logs(socket_path: &str, filter: Option<String>) -> Result<Vec<String>, ZinitError> {
361 let client = get_zinit_client(socket_path).await?;
362 client.logs(filter).await
363}