Compare commits
2 Commits
main
...
zinit_clie
Author | SHA1 | Date | |
---|---|---|---|
|
f386890a8a | ||
|
61bd58498a |
@ -27,6 +27,10 @@ log = "0.4" # Logging facade
|
|||||||
rhai = { version = "1.12.0", features = ["sync"] } # Embedded scripting language
|
rhai = { version = "1.12.0", features = ["sync"] } # Embedded scripting language
|
||||||
rand = "0.8.5" # Random number generation
|
rand = "0.8.5" # Random number generation
|
||||||
clap = "2.33" # Command-line argument parsing
|
clap = "2.33" # Command-line argument parsing
|
||||||
|
zinit-client = { git = "https://github.com/threefoldtech/zinit", branch = "json_rpc", package = "zinit-client" }
|
||||||
|
anyhow = "1.0.98"
|
||||||
|
jsonrpsee = "0.25.1"
|
||||||
|
tokio = "1.45.0"
|
||||||
|
|
||||||
# Optional features for specific OS functionality
|
# Optional features for specific OS functionality
|
||||||
[target.'cfg(unix)'.dependencies]
|
[target.'cfg(unix)'.dependencies]
|
||||||
|
87
examples/zinit/zinit_basic.rhai
Normal file
87
examples/zinit/zinit_basic.rhai
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
// Basic example of using the Zinit client in Rhai
|
||||||
|
|
||||||
|
// Socket path for Zinit
|
||||||
|
let socket_path = "/var/run/zinit.sock";
|
||||||
|
|
||||||
|
// List all services
|
||||||
|
print("Listing all services:");
|
||||||
|
let services = zinit_list(socket_path);
|
||||||
|
|
||||||
|
if services.is_empty() {
|
||||||
|
print("No services found.");
|
||||||
|
} else {
|
||||||
|
// Iterate over the keys of the map
|
||||||
|
for name in services.keys() {
|
||||||
|
let state = services[name];
|
||||||
|
print(`${name}: ${state}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get status of a specific service
|
||||||
|
let service_name = "test";
|
||||||
|
print(`Getting status for ${service_name}:`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
let status = zinit_status(socket_path, service_name);
|
||||||
|
print(`Service: ${status.name}`);
|
||||||
|
print(`PID: ${status.pid}`);
|
||||||
|
print(`State: ${status.state}`);
|
||||||
|
print(`Target: ${status.target}`);
|
||||||
|
print("Dependencies:");
|
||||||
|
|
||||||
|
for (dep, state) in status.after.keys() {
|
||||||
|
print(` ${dep}: ${state}`);
|
||||||
|
}
|
||||||
|
} catch(err) {
|
||||||
|
print(`Error getting status: ${err}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new service
|
||||||
|
print("\nCreating a new service:");
|
||||||
|
let new_service = "rhai-test-service";
|
||||||
|
let exec_command = "echo 'Hello from Rhai'";
|
||||||
|
let oneshot = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
let result = zinit_create_service(socket_path, new_service, exec_command, oneshot);
|
||||||
|
print(`Service created: ${result}`);
|
||||||
|
|
||||||
|
// Monitor the service
|
||||||
|
print("\nMonitoring the service:");
|
||||||
|
let monitor_result = zinit_monitor(socket_path, new_service);
|
||||||
|
print(`Service monitored: ${monitor_result}`);
|
||||||
|
|
||||||
|
// Start the service
|
||||||
|
print("\nStarting the service:");
|
||||||
|
let start_result = zinit_start(socket_path, new_service);
|
||||||
|
print(`Service started: ${start_result}`);
|
||||||
|
|
||||||
|
// Get logs for a specific service
|
||||||
|
print("\nGetting logs:");
|
||||||
|
let logs = zinit_logs(socket_path, new_service);
|
||||||
|
|
||||||
|
for log in logs {
|
||||||
|
print(log);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Or to get all logs (uncomment if needed)
|
||||||
|
// print("\nGetting all logs:");
|
||||||
|
// let all_logs = zinit_logs_all(socket_path);
|
||||||
|
//
|
||||||
|
// for log in all_logs {
|
||||||
|
// print(log);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
print("\nCleaning up:");
|
||||||
|
let stop_result = zinit_stop(socket_path, new_service);
|
||||||
|
print(`Service stopped: ${stop_result}`);
|
||||||
|
|
||||||
|
let forget_result = zinit_forget(socket_path, new_service);
|
||||||
|
print(`Service forgotten: ${forget_result}`);
|
||||||
|
|
||||||
|
let delete_result = zinit_delete_service(socket_path, new_service);
|
||||||
|
print(`Service deleted: ${delete_result}`);
|
||||||
|
} catch(err) {
|
||||||
|
print(`Error: ${err}`);
|
||||||
|
}
|
@ -44,6 +44,7 @@ pub mod text;
|
|||||||
pub mod virt;
|
pub mod virt;
|
||||||
pub mod rhai;
|
pub mod rhai;
|
||||||
pub mod cmd;
|
pub mod cmd;
|
||||||
|
pub mod zinit_client;
|
||||||
|
|
||||||
// Version information
|
// Version information
|
||||||
/// Returns the version of the SAL library
|
/// Returns the version of the SAL library
|
||||||
|
@ -11,6 +11,7 @@ mod nerdctl;
|
|||||||
mod git;
|
mod git;
|
||||||
mod text;
|
mod text;
|
||||||
mod rfs;
|
mod rfs;
|
||||||
|
mod zinit;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
@ -60,6 +61,9 @@ pub use rfs::register as register_rfs_module;
|
|||||||
pub use git::register_git_module;
|
pub use git::register_git_module;
|
||||||
pub use crate::git::{GitTree, GitRepo};
|
pub use crate::git::{GitTree, GitRepo};
|
||||||
|
|
||||||
|
// Re-export zinit module
|
||||||
|
pub use zinit::register_zinit_module;
|
||||||
|
|
||||||
// Re-export text module
|
// Re-export text module
|
||||||
pub use text::register_text_module;
|
pub use text::register_text_module;
|
||||||
// Re-export text functions directly from text module
|
// Re-export text functions directly from text module
|
||||||
@ -110,6 +114,9 @@ pub fn register(engine: &mut Engine) -> Result<(), Box<rhai::EvalAltResult>> {
|
|||||||
// Register Git module functions
|
// Register Git module functions
|
||||||
git::register_git_module(engine)?;
|
git::register_git_module(engine)?;
|
||||||
|
|
||||||
|
// Register Zinit module functions
|
||||||
|
zinit::register_zinit_module(engine)?;
|
||||||
|
|
||||||
// Register Text module functions
|
// Register Text module functions
|
||||||
text::register_text_module(engine)?;
|
text::register_text_module(engine)?;
|
||||||
|
|
||||||
|
345
src/rhai/zinit.rs
Normal file
345
src/rhai/zinit.rs
Normal file
@ -0,0 +1,345 @@
|
|||||||
|
//! Rhai wrappers for Zinit client module functions
|
||||||
|
//!
|
||||||
|
//! This module provides Rhai wrappers for the functions in the Zinit client module.
|
||||||
|
|
||||||
|
use rhai::{Engine, EvalAltResult, Array, Dynamic, Map};
|
||||||
|
use crate::zinit_client as client;
|
||||||
|
use tokio::runtime::Runtime;
|
||||||
|
use serde_json::{json, Value};
|
||||||
|
use crate::rhai::error::ToRhaiError;
|
||||||
|
|
||||||
|
/// Register Zinit module functions with the Rhai engine
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `engine` - The Rhai engine to register the functions with
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// * `Result<(), Box<EvalAltResult>>` - Ok if registration was successful, Err otherwise
|
||||||
|
pub fn register_zinit_module(engine: &mut Engine) -> Result<(), Box<EvalAltResult>> {
|
||||||
|
// Register Zinit client functions
|
||||||
|
engine.register_fn("zinit_list", zinit_list);
|
||||||
|
engine.register_fn("zinit_status", zinit_status);
|
||||||
|
engine.register_fn("zinit_start", zinit_start);
|
||||||
|
engine.register_fn("zinit_stop", zinit_stop);
|
||||||
|
engine.register_fn("zinit_restart", zinit_restart);
|
||||||
|
engine.register_fn("zinit_monitor", zinit_monitor);
|
||||||
|
engine.register_fn("zinit_forget", zinit_forget);
|
||||||
|
engine.register_fn("zinit_kill", zinit_kill);
|
||||||
|
engine.register_fn("zinit_create_service", zinit_create_service);
|
||||||
|
engine.register_fn("zinit_delete_service", zinit_delete_service);
|
||||||
|
engine.register_fn("zinit_get_service", zinit_get_service);
|
||||||
|
engine.register_fn("zinit_logs", zinit_logs);
|
||||||
|
engine.register_fn("zinit_logs_all", zinit_logs_all);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> ToRhaiError<T> for Result<T, zinit_client::ClientError> {
|
||||||
|
fn to_rhai_error(self) -> Result<T, Box<EvalAltResult>> {
|
||||||
|
self.map_err(|e| {
|
||||||
|
Box::new(EvalAltResult::ErrorRuntime(
|
||||||
|
format!("Zinit error: {}", e).into(),
|
||||||
|
rhai::Position::NONE
|
||||||
|
))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to get a runtime
|
||||||
|
fn get_runtime() -> Result<Runtime, Box<EvalAltResult>> {
|
||||||
|
tokio::runtime::Runtime::new().map_err(|e| {
|
||||||
|
Box::new(EvalAltResult::ErrorRuntime(
|
||||||
|
format!("Failed to create Tokio runtime: {}", e).into(),
|
||||||
|
rhai::Position::NONE
|
||||||
|
))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Zinit Client Function Wrappers
|
||||||
|
//
|
||||||
|
|
||||||
|
/// Wrapper for zinit_client::list
|
||||||
|
///
|
||||||
|
/// Lists all services managed by Zinit.
|
||||||
|
pub fn zinit_list(socket_path: &str) -> Result<Map, Box<EvalAltResult>> {
|
||||||
|
let rt = get_runtime()?;
|
||||||
|
|
||||||
|
let result = rt.block_on(async {
|
||||||
|
client::list(socket_path).await
|
||||||
|
});
|
||||||
|
|
||||||
|
let services = result.to_rhai_error()?;
|
||||||
|
|
||||||
|
// Convert HashMap<String, String> to Rhai Map
|
||||||
|
let mut map = Map::new();
|
||||||
|
for (name, state) in services {
|
||||||
|
map.insert(name.into(), Dynamic::from(state));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(map)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wrapper for zinit_client::status
|
||||||
|
///
|
||||||
|
/// Gets the status of a specific service.
|
||||||
|
pub fn zinit_status(socket_path: &str, name: &str) -> Result<Map, Box<EvalAltResult>> {
|
||||||
|
let rt = get_runtime()?;
|
||||||
|
|
||||||
|
let result = rt.block_on(async {
|
||||||
|
client::status(socket_path, name).await
|
||||||
|
});
|
||||||
|
|
||||||
|
let status = result.to_rhai_error()?;
|
||||||
|
|
||||||
|
// Convert Status to Rhai Map
|
||||||
|
let mut map = Map::new();
|
||||||
|
map.insert("name".into(), Dynamic::from(status.name));
|
||||||
|
map.insert("pid".into(), Dynamic::from(status.pid));
|
||||||
|
map.insert("state".into(), Dynamic::from(status.state));
|
||||||
|
map.insert("target".into(), Dynamic::from(status.target));
|
||||||
|
|
||||||
|
// Convert dependencies
|
||||||
|
let mut deps_map = Map::new();
|
||||||
|
for (dep, state) in status.after {
|
||||||
|
deps_map.insert(dep.into(), Dynamic::from(state));
|
||||||
|
}
|
||||||
|
map.insert("after".into(), Dynamic::from_map(deps_map));
|
||||||
|
|
||||||
|
Ok(map)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wrapper for zinit_client::start
|
||||||
|
///
|
||||||
|
/// Starts a service.
|
||||||
|
pub fn zinit_start(socket_path: &str, name: &str) -> Result<bool, Box<EvalAltResult>> {
|
||||||
|
let rt = get_runtime()?;
|
||||||
|
|
||||||
|
let result = rt.block_on(async {
|
||||||
|
client::start(socket_path, name).await
|
||||||
|
});
|
||||||
|
|
||||||
|
result.to_rhai_error()?;
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wrapper for zinit_client::stop
|
||||||
|
///
|
||||||
|
/// Stops a service.
|
||||||
|
pub fn zinit_stop(socket_path: &str, name: &str) -> Result<bool, Box<EvalAltResult>> {
|
||||||
|
let rt = get_runtime()?;
|
||||||
|
|
||||||
|
let result = rt.block_on(async {
|
||||||
|
client::stop(socket_path, name).await
|
||||||
|
});
|
||||||
|
|
||||||
|
result.to_rhai_error()?;
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wrapper for zinit_client::restart
|
||||||
|
///
|
||||||
|
/// Restarts a service.
|
||||||
|
pub fn zinit_restart(socket_path: &str, name: &str) -> Result<bool, Box<EvalAltResult>> {
|
||||||
|
let rt = get_runtime()?;
|
||||||
|
|
||||||
|
let result = rt.block_on(async {
|
||||||
|
client::restart(socket_path, name).await
|
||||||
|
});
|
||||||
|
|
||||||
|
result.to_rhai_error()?;
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wrapper for zinit_client::monitor
|
||||||
|
///
|
||||||
|
/// Starts monitoring a service.
|
||||||
|
pub fn zinit_monitor(socket_path: &str, name: &str) -> Result<bool, Box<EvalAltResult>> {
|
||||||
|
let rt = get_runtime()?;
|
||||||
|
|
||||||
|
let result = rt.block_on(async {
|
||||||
|
let client = client::get_zinit_client(socket_path).await?;
|
||||||
|
client.monitor(name).await
|
||||||
|
});
|
||||||
|
|
||||||
|
result.to_rhai_error()?;
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wrapper for zinit_client::forget
|
||||||
|
///
|
||||||
|
/// Stops monitoring a service.
|
||||||
|
pub fn zinit_forget(socket_path: &str, name: &str) -> Result<bool, Box<EvalAltResult>> {
|
||||||
|
let rt = get_runtime()?;
|
||||||
|
|
||||||
|
let result = rt.block_on(async {
|
||||||
|
let client = client::get_zinit_client(socket_path).await?;
|
||||||
|
client.forget(name).await
|
||||||
|
});
|
||||||
|
|
||||||
|
result.to_rhai_error()?;
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wrapper for zinit_client::kill
|
||||||
|
///
|
||||||
|
/// Sends a signal to a service.
|
||||||
|
pub fn zinit_kill(socket_path: &str, name: &str, signal: &str) -> Result<bool, Box<EvalAltResult>> {
|
||||||
|
let rt = get_runtime()?;
|
||||||
|
|
||||||
|
let result = rt.block_on(async {
|
||||||
|
let client = client::get_zinit_client(socket_path).await?;
|
||||||
|
client.kill(name, signal).await
|
||||||
|
});
|
||||||
|
|
||||||
|
result.to_rhai_error()?;
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wrapper for zinit_client::create_service
|
||||||
|
///
|
||||||
|
/// Creates a new service.
|
||||||
|
pub fn zinit_create_service(socket_path: &str, name: &str, exec: &str, oneshot: bool) -> Result<String, Box<EvalAltResult>> {
|
||||||
|
let rt = get_runtime()?;
|
||||||
|
|
||||||
|
// Create service configuration
|
||||||
|
let content = serde_json::from_value(json!({
|
||||||
|
"exec": exec,
|
||||||
|
"oneshot": oneshot
|
||||||
|
})).map_err(|e| {
|
||||||
|
Box::new(EvalAltResult::ErrorRuntime(
|
||||||
|
format!("Failed to create service configuration: {}", e).into(),
|
||||||
|
rhai::Position::NONE
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let result = rt.block_on(async {
|
||||||
|
let client = client::get_zinit_client(socket_path).await?;
|
||||||
|
client.create_service(name, content).await
|
||||||
|
});
|
||||||
|
|
||||||
|
result.to_rhai_error()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wrapper for zinit_client::delete_service
|
||||||
|
///
|
||||||
|
/// Deletes a service.
|
||||||
|
pub fn zinit_delete_service(socket_path: &str, name: &str) -> Result<String, Box<EvalAltResult>> {
|
||||||
|
let rt = get_runtime()?;
|
||||||
|
|
||||||
|
let result = rt.block_on(async {
|
||||||
|
let client = client::get_zinit_client(socket_path).await?;
|
||||||
|
client.delete_service(name).await
|
||||||
|
});
|
||||||
|
|
||||||
|
result.to_rhai_error()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wrapper for zinit_client::get_service
|
||||||
|
///
|
||||||
|
/// Gets a service configuration.
|
||||||
|
pub fn zinit_get_service(socket_path: &str, name: &str) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
|
let rt = get_runtime()?;
|
||||||
|
|
||||||
|
let result = rt.block_on(async {
|
||||||
|
let client = client::get_zinit_client(socket_path).await?;
|
||||||
|
client.get_service(name).await
|
||||||
|
});
|
||||||
|
|
||||||
|
let value = result.to_rhai_error()?;
|
||||||
|
|
||||||
|
// Convert Value to Dynamic
|
||||||
|
match value {
|
||||||
|
Value::Object(map) => {
|
||||||
|
let mut rhai_map = Map::new();
|
||||||
|
for (k, v) in map {
|
||||||
|
rhai_map.insert(k.into(), value_to_dynamic(v));
|
||||||
|
}
|
||||||
|
Ok(Dynamic::from_map(rhai_map))
|
||||||
|
},
|
||||||
|
_ => Err(Box::new(EvalAltResult::ErrorRuntime(
|
||||||
|
"Expected object from get_service".into(),
|
||||||
|
rhai::Position::NONE
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wrapper for zinit_client::logs with a filter
|
||||||
|
///
|
||||||
|
/// Gets logs for a specific service.
|
||||||
|
pub fn zinit_logs(socket_path: &str, filter: &str) -> Result<Array, Box<EvalAltResult>> {
|
||||||
|
let rt = get_runtime()?;
|
||||||
|
|
||||||
|
let filter_string = Some(filter.to_string());
|
||||||
|
|
||||||
|
let result = rt.block_on(async {
|
||||||
|
let client = client::get_zinit_client(socket_path).await?;
|
||||||
|
client.logs(filter_string).await
|
||||||
|
});
|
||||||
|
|
||||||
|
let logs = result.to_rhai_error()?;
|
||||||
|
|
||||||
|
// Convert Vec<String> to Rhai Array
|
||||||
|
let mut array = Array::new();
|
||||||
|
for log in logs {
|
||||||
|
array.push(Dynamic::from(log));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(array)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wrapper for zinit_client::logs without a filter
|
||||||
|
///
|
||||||
|
/// Gets all logs.
|
||||||
|
pub fn zinit_logs_all(socket_path: &str) -> Result<Array, Box<EvalAltResult>> {
|
||||||
|
let rt = get_runtime()?;
|
||||||
|
|
||||||
|
let result = rt.block_on(async {
|
||||||
|
let client = client::get_zinit_client(socket_path).await?;
|
||||||
|
client.logs(None).await
|
||||||
|
});
|
||||||
|
|
||||||
|
let logs = result.to_rhai_error()?;
|
||||||
|
|
||||||
|
// Convert Vec<String> to Rhai Array
|
||||||
|
let mut array = Array::new();
|
||||||
|
for log in logs {
|
||||||
|
array.push(Dynamic::from(log));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(array)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to convert serde_json::Value to rhai::Dynamic
|
||||||
|
fn value_to_dynamic(value: Value) -> Dynamic {
|
||||||
|
match value {
|
||||||
|
Value::Null => Dynamic::UNIT,
|
||||||
|
Value::Bool(b) => Dynamic::from(b),
|
||||||
|
Value::Number(n) => {
|
||||||
|
if let Some(i) = n.as_i64() {
|
||||||
|
Dynamic::from(i)
|
||||||
|
} else if let Some(f) = n.as_f64() {
|
||||||
|
Dynamic::from(f)
|
||||||
|
} else {
|
||||||
|
Dynamic::from(n.to_string())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Value::String(s) => Dynamic::from(s),
|
||||||
|
Value::Array(arr) => {
|
||||||
|
let mut rhai_arr = Array::new();
|
||||||
|
for item in arr {
|
||||||
|
rhai_arr.push(value_to_dynamic(item));
|
||||||
|
}
|
||||||
|
Dynamic::from(rhai_arr)
|
||||||
|
},
|
||||||
|
Value::Object(map) => {
|
||||||
|
let mut rhai_map = Map::new();
|
||||||
|
for (k, v) in map {
|
||||||
|
rhai_map.insert(k.into(), value_to_dynamic(v));
|
||||||
|
}
|
||||||
|
Dynamic::from_map(rhai_map)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
203
src/zinit_client/mod.rs
Normal file
203
src/zinit_client/mod.rs
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
use std::sync::{Arc, Mutex, Once};
|
||||||
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
use zinit_client::{Client as ZinitClient, ClientError, Status};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use serde_json::{Map, Value};
|
||||||
|
|
||||||
|
// Global Zinit client instance using lazy_static
|
||||||
|
lazy_static! {
|
||||||
|
static ref ZINIT_CLIENT: Mutex<Option<Arc<ZinitClientWrapper>>> = Mutex::new(None);
|
||||||
|
static ref INIT: Once = Once::new();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrapper for Zinit client to handle connection
|
||||||
|
pub struct ZinitClientWrapper {
|
||||||
|
client: ZinitClient,
|
||||||
|
initialized: AtomicBool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ZinitClientWrapper {
|
||||||
|
// Create a new Zinit client wrapper
|
||||||
|
fn new(client: ZinitClient) -> Self {
|
||||||
|
ZinitClientWrapper {
|
||||||
|
client,
|
||||||
|
initialized: AtomicBool::new(false),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the client
|
||||||
|
async fn initialize(&self) -> Result<(), ClientError> {
|
||||||
|
if self.initialized.load(Ordering::Relaxed) {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to list services to check if the connection works
|
||||||
|
let _ = self.client.list().await.map_err(|e| {
|
||||||
|
eprintln!("Failed to initialize Zinit client: {}", e);
|
||||||
|
e
|
||||||
|
})?;
|
||||||
|
|
||||||
|
self.initialized.store(true, Ordering::Relaxed);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// List all services
|
||||||
|
pub async fn list(&self) -> Result<HashMap<String, String>, ClientError> {
|
||||||
|
self.client.list().await
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get status of a service
|
||||||
|
pub async fn status(&self, name: &str) -> Result<Status, ClientError> {
|
||||||
|
self.client.status(name).await
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start a service
|
||||||
|
pub async fn start(&self, name: &str) -> Result<(), ClientError> {
|
||||||
|
self.client.start(name).await
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop a service
|
||||||
|
pub async fn stop(&self, name: &str) -> Result<(), ClientError> {
|
||||||
|
self.client.stop(name).await
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restart a service
|
||||||
|
pub async fn restart(&self, name: &str) -> Result<(), ClientError> {
|
||||||
|
self.client.restart(name).await
|
||||||
|
}
|
||||||
|
|
||||||
|
// Monitor a service
|
||||||
|
pub async fn monitor(&self, name: &str) -> Result<(), ClientError> {
|
||||||
|
self.client.monitor(name).await
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forget a service
|
||||||
|
pub async fn forget(&self, name: &str) -> Result<(), ClientError> {
|
||||||
|
self.client.forget(name).await
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send a signal to a service
|
||||||
|
pub async fn kill(&self, name: &str, signal: &str) -> Result<(), ClientError> {
|
||||||
|
self.client.kill(name, signal).await
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new service
|
||||||
|
pub async fn create_service(&self, name: &str, content: Map<String, Value>) -> Result<String, ClientError> {
|
||||||
|
self.client.create_service(name, content).await
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete a service
|
||||||
|
pub async fn delete_service(&self, name: &str) -> Result<String, ClientError> {
|
||||||
|
self.client.delete_service(name).await
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a service configuration
|
||||||
|
pub async fn get_service(&self, name: &str) -> Result<Value, ClientError> {
|
||||||
|
self.client.get_service(name).await
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shutdown the system
|
||||||
|
pub async fn shutdown(&self) -> Result<(), ClientError> {
|
||||||
|
self.client.shutdown().await
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reboot the system
|
||||||
|
pub async fn reboot(&self) -> Result<(), ClientError> {
|
||||||
|
self.client.reboot().await
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start HTTP server
|
||||||
|
pub async fn start_http_server(&self, address: &str) -> Result<String, ClientError> {
|
||||||
|
self.client.start_http_server(address).await
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop HTTP server
|
||||||
|
pub async fn stop_http_server(&self) -> Result<(), ClientError> {
|
||||||
|
self.client.stop_http_server().await
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get logs
|
||||||
|
pub async fn logs(&self, filter: Option<String>) -> Result<Vec<String>, ClientError> {
|
||||||
|
self.client.logs(filter).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the Zinit client instance
|
||||||
|
pub async fn get_zinit_client(socket_path: &str) -> Result<Arc<ZinitClientWrapper>, ClientError> {
|
||||||
|
// Check if we already have a client
|
||||||
|
{
|
||||||
|
let guard = ZINIT_CLIENT.lock().unwrap();
|
||||||
|
if let Some(ref client) = &*guard {
|
||||||
|
return Ok(Arc::clone(client));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new client
|
||||||
|
let client = create_zinit_client(socket_path).await?;
|
||||||
|
|
||||||
|
// Store the client globally
|
||||||
|
{
|
||||||
|
let mut guard = ZINIT_CLIENT.lock().unwrap();
|
||||||
|
*guard = Some(Arc::clone(&client));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(client)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new Zinit client
|
||||||
|
async fn create_zinit_client(socket_path: &str) -> Result<Arc<ZinitClientWrapper>, ClientError> {
|
||||||
|
// Connect via Unix socket
|
||||||
|
let client = ZinitClient::unix_socket(socket_path).await?;
|
||||||
|
let wrapper = Arc::new(ZinitClientWrapper::new(client));
|
||||||
|
|
||||||
|
// Initialize the client
|
||||||
|
wrapper.initialize().await?;
|
||||||
|
|
||||||
|
Ok(wrapper)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the Zinit client
|
||||||
|
pub async fn reset(socket_path: &str) -> Result<(), ClientError> {
|
||||||
|
// Clear the existing client
|
||||||
|
{
|
||||||
|
let mut client_guard = ZINIT_CLIENT.lock().unwrap();
|
||||||
|
*client_guard = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new client, only return error if it fails
|
||||||
|
get_zinit_client(socket_path).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convenience functions for common operations
|
||||||
|
|
||||||
|
// List all services
|
||||||
|
pub async fn list(socket_path: &str) -> Result<HashMap<String, String>, ClientError> {
|
||||||
|
let client = get_zinit_client(socket_path).await?;
|
||||||
|
client.list().await
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get status of a service
|
||||||
|
pub async fn status(socket_path: &str, name: &str) -> Result<Status, ClientError> {
|
||||||
|
let client = get_zinit_client(socket_path).await?;
|
||||||
|
client.status(name).await
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start a service
|
||||||
|
pub async fn start(socket_path: &str, name: &str) -> Result<(), ClientError> {
|
||||||
|
let client = get_zinit_client(socket_path).await?;
|
||||||
|
client.start(name).await
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop a service
|
||||||
|
pub async fn stop(socket_path: &str, name: &str) -> Result<(), ClientError> {
|
||||||
|
let client = get_zinit_client(socket_path).await?;
|
||||||
|
client.stop(name).await
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restart a service
|
||||||
|
pub async fn restart(socket_path: &str, name: &str) -> Result<(), ClientError> {
|
||||||
|
let client = get_zinit_client(socket_path).await?;
|
||||||
|
client.restart(name).await
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user