diff --git a/example.rhai b/example.rhai index 0c93ee9..ee5ef10 100644 --- a/example.rhai +++ b/example.rhai @@ -13,13 +13,6 @@ try { print(`Getting details for server: ${first_server.name}`); let detailed_server = client.get_server(first_server.id); print(detailed_server.show_details()); - print(`Pinging server ${detailed_server.name}...`); - let is_online = detailed_server.ping(); - if is_online { - print("Server is online."); - } else { - print("Server is offline."); - } // --- REBOOT --- // To reboot the server, uncomment the following lines: diff --git a/src/hetzner_api.rs b/src/hetzner_api.rs index 2225f5f..d43655b 100644 --- a/src/hetzner_api.rs +++ b/src/hetzner_api.rs @@ -41,8 +41,6 @@ impl HetznerClient { all_servers.append(&mut servers); - println!("next page? {:#?}", response.meta); - if is_empty || response.meta.pagination.next_page.is_none() { break; } diff --git a/src/rhai_api.rs b/src/rhai_api.rs index 54d9172..6121c4d 100644 --- a/src/rhai_api.rs +++ b/src/rhai_api.rs @@ -2,14 +2,38 @@ use crate::async_handler::Response; use crate::async_handler::Request; use crate::hetzner_api::{HetznerClient, WrappedServer}; use rhai::{Engine, EvalAltResult}; -use std::sync::{Arc, Mutex, mpsc::{Sender, Receiver}}; +use std::sync::{mpsc::{Receiver, Sender}, Arc, Mutex}; use prettytable::{Table, Row, Cell}; +#[derive(Clone)] +struct ApiBridge { + command_tx: Sender, + reply_rx: Arc>>, +} + +impl ApiBridge { + fn new(command_tx: Sender, reply_rx: Arc>>) -> Self { + Self { command_tx, reply_rx } + } + + fn call( + &self, + request: Request, + response_handler: impl FnOnce(Response) -> Result>, + ) -> Result> { + self.command_tx.send(request).map_err(|e| e.to_string())?; + let response = self.reply_rx.lock().unwrap().recv().map_err(|e| e.to_string())?; + response_handler(response) + } +} + pub fn register_hetzner_api( engine: &mut Engine, command_tx: Sender, reply_rx: Arc>>, ) { + let api_bridge = ApiBridge::new(command_tx, reply_rx); + engine .register_type_with_name::("HetznerClient") .register_fn("new_hetzner_client", |api_token: &str| -> Result> { @@ -19,261 +43,127 @@ pub fn register_hetzner_api( Ok(HetznerClient::new(api_token)) }); - let list_servers_tx = command_tx.clone(); - let list_servers_rx = reply_rx.clone(); - let get_server_status_tx = command_tx.clone(); - let get_server_status_rx = reply_rx.clone(); - let get_server_tx = command_tx.clone(); - let get_server_rx = reply_rx.clone(); - let reboot_server_tx = command_tx.clone(); - let reboot_server_rx = reply_rx.clone(); - let reset_server_tx = command_tx.clone(); - let reset_server_rx = reply_rx.clone(); - let enable_rescue_mode_tx = command_tx.clone(); - let enable_rescue_mode_rx = reply_rx.clone(); - let disable_rescue_mode_tx = command_tx.clone(); - let disable_rescue_mode_rx = reply_rx.clone(); + let bridge = api_bridge.clone(); + engine.register_fn("list_servers", move |client: &mut HetznerClient| { + bridge.call(Request::ListServers(client.clone()), |response| { + match response { + Response::ListServers(result) => result.map_err(|e| e.into()), + _ => Err("Unexpected response".into()), + } + }) + }); + + let bridge = api_bridge.clone(); + engine.register_fn("get_server_status", move |client: &mut HetznerClient, server_id: i64| { + bridge.call(Request::GetServerStatus(client.clone(), server_id), |response| { + match response { + Response::GetServerStatus(result) => result.map_err(|e| e.into()), + _ => Err("Unexpected response".into()), + } + }) + }); + + let bridge = api_bridge.clone(); + engine.register_fn("get_server", move |client: &mut HetznerClient, server_id: i64| { + bridge.call(Request::GetServer(client.clone(), server_id), |response| { + match response { + Response::GetServer(result) => result.map_err(|e| e.into()), + _ => Err("Unexpected response".into()), + } + }) + }); engine - .register_fn( - "list_servers", - move |client: &mut HetznerClient| -> Result, Box> { - list_servers_tx.send(Request::ListServers(client.clone())) - .map_err(|e| e.to_string())?; - - let response = list_servers_rx.lock().unwrap().recv() - .map_err(|e| e.to_string())?; - - match response { - Response::ListServers(result) => result.map_err(|e| e.into()), - _ => Err("Unexpected response".into()), - } - }, - ) - .register_fn( - "get_server_status", - move |client: &mut HetznerClient, - server_id: i64| - -> Result> { - get_server_status_tx.send(Request::GetServerStatus(client.clone(), server_id)) - .map_err(|e| e.to_string())?; - - let response = get_server_status_rx.lock().unwrap().recv() - .map_err(|e| e.to_string())?; - - match response { - Response::GetServerStatus(result) => result.map_err(|e| e.into()), - _ => Err("Unexpected response".into()), - } - }, - ) - .register_fn( - "get_server", - move |client: &mut HetznerClient, - server_id: i64| - -> Result> { - get_server_tx.send(Request::GetServer(client.clone(), server_id)) - .map_err(|e| e.to_string())?; - - let response = get_server_rx.lock().unwrap().recv() - .map_err(|e| e.to_string())?; - - match response { - Response::GetServer(result) => result.map_err(|e| e.into()), - _ => Err("Unexpected response".into()), - } - }, - ) .register_type_with_name::("Server") .register_get("id", |server: &mut WrappedServer| server.0.id) - .register_get("name", |server: &mut WrappedServer| { - server.0.name.clone() + .register_get("name", |server: &mut WrappedServer| server.0.name.clone()) + .register_get("status", |server: &mut WrappedServer| format!("{:?}", server.0.status)) + .register_get("created", |server: &mut WrappedServer| server.0.created.clone()) + .register_get("public_ipv4", |server: &mut WrappedServer| server.0.public_net.ipv4.clone().unwrap().ip) + .register_get("server_type", |server: &mut WrappedServer| server.0.server_type.clone().name) + .register_get("included_traffic", |server: &mut WrappedServer| server.0.included_traffic.unwrap_or(0)) + .register_get("ingoing_traffic", |server: &mut WrappedServer| server.0.ingoing_traffic.unwrap_or(0)) + .register_get("outgoing_traffic", |server: &mut WrappedServer| server.0.outgoing_traffic.unwrap_or(0)) + .register_get("primary_disk_size", |server: &mut WrappedServer| server.0.primary_disk_size) + .register_get("rescue_enabled", |server: &mut WrappedServer| server.0.rescue_enabled); + + let bridge = api_bridge.clone(); + engine.register_fn("reboot", move |server: &mut WrappedServer, client: HetznerClient| { + bridge.call(Request::RebootServer(client, server.0.id), |response| { + match response { + Response::RebootServer(result) => result.map_err(|e| e.into()), + _ => Err("Unexpected response".into()), + } }) - .register_get("status", |server: &mut WrappedServer| { - format!("{:?}", server.0.status) - }) - .register_get("created", |server: &mut WrappedServer| { - server.0.created.clone() - }) - .register_get("public_ipv4", |server: &mut WrappedServer| { - server.0.public_net.ipv4.clone().unwrap().ip - }) - .register_get("server_type", |server: &mut WrappedServer| { - server.0.server_type.clone().name - }) - .register_get("included_traffic", |server: &mut WrappedServer| { - server.0.included_traffic.unwrap_or(0) - }) - .register_get("ingoing_traffic", |server: &mut WrappedServer| { - server.0.ingoing_traffic.unwrap_or(0) - }) - .register_get("outgoing_traffic", |server: &mut WrappedServer| { - server.0.outgoing_traffic.unwrap_or(0) - }) - .register_get("primary_disk_size", |server: &mut WrappedServer| { - server.0.primary_disk_size - }) - .register_get("rescue_enabled", |server: &mut WrappedServer| { - server.0.rescue_enabled - }) - .register_fn( - "reboot", - move |server: &mut WrappedServer, - client: HetznerClient| - -> Result<(), Box> { - reboot_server_tx - .send(Request::RebootServer(client, server.0.id)) - .map_err(|e| e.to_string())?; + }); - let response = reboot_server_rx - .lock() - .unwrap() - .recv() - .map_err(|e| e.to_string())?; + let bridge = api_bridge.clone(); + engine.register_fn("reset", move |server: &mut WrappedServer, client: HetznerClient| { + bridge.call(Request::ResetServer(client, server.0.id), |response| { + match response { + Response::ResetServer(result) => result.map_err(|e| e.into()), + _ => Err("Unexpected response".into()), + } + }) + }); - match response { - Response::RebootServer(result) => result.map_err(|e| e.into()), - _ => Err("Unexpected response".into()), - } - }, - ) - .register_fn( - "reset", - move |server: &mut WrappedServer, - client: HetznerClient| - -> Result<(), Box> { - reset_server_tx - .send(Request::ResetServer(client, server.0.id)) - .map_err(|e| e.to_string())?; + let bridge = api_bridge.clone(); + engine.register_fn("enable_rescue_mode", move |server: &mut WrappedServer, client: HetznerClient| { + bridge.call(Request::EnableRescueMode(client, server.0.id), |response| { + match response { + Response::EnableRescueMode(result) => result.map_err(|e| e.into()), + _ => Err("Unexpected response".into()), + } + }) + }); - let response = reset_server_rx - .lock() - .unwrap() - .recv() - .map_err(|e| e.to_string())?; + let bridge = api_bridge.clone(); + engine.register_fn("disable_rescue_mode", move |server: &mut WrappedServer, client: HetznerClient| { + bridge.call(Request::DisableRescueMode(client, server.0.id), |response| { + match response { + Response::DisableRescueMode(result) => result.map_err(|e| e.into()), + _ => Err("Unexpected response".into()), + } + }) + }); - match response { - Response::ResetServer(result) => result.map_err(|e| e.into()), - _ => Err("Unexpected response".into()), - } - }, - ) - .register_iterator::>() + engine + .register_iterator::>() .register_fn("len", |list: &mut Vec| list.len() as i64) .register_indexer_get(|list: &mut Vec, index: i64| list[index as usize].clone()) - .register_fn( - "show_table", - |servers: &mut Vec| -> Result> { - let mut table = Table::new(); - table.set_titles(Row::new(vec![Cell::new("Server List").style_spec("c")])); + .register_fn("show_table", |servers: &mut Vec| -> Result> { + let mut table = Table::new(); + table.set_titles(Row::new(vec![Cell::new("Server List").style_spec("c")])); + table.add_row(Row::new(vec![ + Cell::new("ID"), + Cell::new("Name"), + Cell::new("Status"), + Cell::new("Public IPv4"), + ])); + for server in servers { table.add_row(Row::new(vec![ - Cell::new("ID"), - Cell::new("Name"), - Cell::new("Status"), - Cell::new("Public IPv4"), - ])); - for server in servers { - table.add_row(Row::new(vec![ - Cell::new(&server.0.id.to_string()), - Cell::new(&server.0.name), - Cell::new(&format!("{:?}", server.0.status)), - Cell::new(&server.0.public_net.ipv4.clone().unwrap().ip.to_string()), - ])); - } - Ok(table.to_string()) - }, - ) - .register_fn( - "show_details", - |server: &mut WrappedServer| -> Result> { - let mut table = Table::new(); - table.set_titles(Row::new(vec![ - Cell::new(&server.0.name).style_spec("c") - ])); - table.add_row(Row::new(vec![ - Cell::new("ID"), Cell::new(&server.0.id.to_string()), - ])); - table.add_row(Row::new(vec![ - Cell::new("Status"), + Cell::new(&server.0.name), Cell::new(&format!("{:?}", server.0.status)), - ])); - table.add_row(Row::new(vec![ - Cell::new("Created"), - Cell::new(&server.0.created), - ])); - table.add_row(Row::new(vec![ - Cell::new("IPv4"), Cell::new(&server.0.public_net.ipv4.clone().unwrap().ip.to_string()), ])); - table.add_row(Row::new(vec![ - Cell::new("Type"), - Cell::new(&server.0.server_type.name), - ])); - table.add_row(Row::new(vec![ - Cell::new("Included Traffic"), - Cell::new(&format!("{} GB", server.0.included_traffic.unwrap_or(0) / 1024 / 1024 / 1024)), - ])); - table.add_row(Row::new(vec![ - Cell::new("Ingoing Traffic"), - Cell::new(&format!("{} MB", server.0.ingoing_traffic.unwrap_or(0) / 1024 / 1024)), - ])); - table.add_row(Row::new(vec![ - Cell::new("Outgoing Traffic"), - Cell::new(&format!("{} MB", server.0.outgoing_traffic.unwrap_or(0) / 1024 / 1024)), - ])); - table.add_row(Row::new(vec![ - Cell::new("Primary Disk Size"), - Cell::new(&server.0.primary_disk_size.to_string()), - ])); - table.add_row(Row::new(vec![ - Cell::new("Rescue Enabled"), - Cell::new(&server.0.rescue_enabled.to_string()), - ])); + } + Ok(table.to_string()) + }) + .register_fn("show_details", |server: &mut WrappedServer| -> Result> { + let mut table = Table::new(); + table.set_titles(Row::new(vec![Cell::new(&server.0.name).style_spec("c")])); + table.add_row(Row::new(vec![Cell::new("ID"), Cell::new(&server.0.id.to_string())])); + table.add_row(Row::new(vec![Cell::new("Status"), Cell::new(&format!("{:?}", server.0.status))])); + table.add_row(Row::new(vec![Cell::new("Created"), Cell::new(&server.0.created)])); + table.add_row(Row::new(vec![Cell::new("IPv4"), Cell::new(&server.0.public_net.ipv4.clone().unwrap().ip.to_string())])); + table.add_row(Row::new(vec![Cell::new("Type"), Cell::new(&server.0.server_type.name)])); + table.add_row(Row::new(vec![Cell::new("Included Traffic"), Cell::new(&format!("{} GB", server.0.included_traffic.unwrap_or(0) / 1024 / 1024 / 1024))])); + table.add_row(Row::new(vec![Cell::new("Ingoing Traffic"), Cell::new(&format!("{} MB", server.0.ingoing_traffic.unwrap_or(0) / 1024 / 1024))])); + table.add_row(Row::new(vec![Cell::new("Outgoing Traffic"), Cell::new(&format!("{} MB", server.0.outgoing_traffic.unwrap_or(0) / 1024 / 1024))])); + table.add_row(Row::new(vec![Cell::new("Primary Disk Size"), Cell::new(&server.0.primary_disk_size.to_string())])); + table.add_row(Row::new(vec![Cell::new("Rescue Enabled"), Cell::new(&server.0.rescue_enabled.to_string())])); - Ok(table.to_string()) - }, - ); - engine.register_fn( - "enable_rescue_mode", - move |server: &mut WrappedServer, - client: HetznerClient| - -> Result> { - enable_rescue_mode_tx - .send(Request::EnableRescueMode(client, server.0.id)) - .map_err(|e| e.to_string())?; - - let response = enable_rescue_mode_rx - .lock() - .unwrap() - .recv() - .map_err(|e| e.to_string())?; - - match response { - Response::EnableRescueMode(result) => result.map_err(|e| e.into()), - _ => Err("Unexpected response".into()), - } - }, - ) - .register_fn( - "disable_rescue_mode", - move |server: &mut WrappedServer, - client: HetznerClient| - -> Result<(), Box> { - disable_rescue_mode_tx - .send(Request::DisableRescueMode(client, server.0.id)) - .map_err(|e| e.to_string())?; - - let response = disable_rescue_mode_rx - .lock() - .unwrap() - .recv() - .map_err(|e| e.to_string())?; - - match response { - Response::DisableRescueMode(result) => result.map_err(|e| e.into()), - _ => Err("Unexpected response".into()), - } - }, - ); + Ok(table.to_string()) + }); } \ No newline at end of file