diff --git a/README.md b/README.md index 97ac93e..fb05088 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Hetzner Cloud API - Rhai Wrapper -This project provides a Rhai wrapper for interacting with the Hetzner Cloud API. +This project provides a Rhai wrapper for interacting with the Hetzner Cloud API, allowing you to manage your servers through simple scripts. ## Setup @@ -12,10 +12,62 @@ export HETZNER_API_TOKEN="YOUR_API_TOKEN_HERE" Replace `"YOUR_API_TOKEN_HERE"` with your actual Hetzner API token. -## Running the Example +## Usage -You can run the example Rhai script (`example.rhai`) using `cargo run`: +You can execute any `.rhai` script by passing it as an argument to `cargo run`. ```bash -cargo run -``` \ No newline at end of file +cargo run -- .rhai +``` + +For example, to run the provided `test.rhai` script: + +```bash +cargo run -- test.rhai +``` + +## API Examples + +Here are some examples of what you can do with the API, taken from the `test.rhai` script. + +### 1. Create a Client + +All API interactions start by creating a client instance. + +```rust +// Create client to communicate with Hetzner API +let client = new_hetzner_client(HETZNER_API_TOKEN); +``` + +### 2. List Servers & Display Details + +You can fetch all your servers and display their details in a formatted table. + +```rust +// List all servers and print in table +print("Listing all servers..."); +let servers = client.list_servers(); +print(servers.show_table()); + +// Get a specific server by ID and show its details +let test_server = client.get_server(104301883); +print(test_server.show_details()); +``` + +### 3. Manage Server State + +Perform actions like enabling rescue mode, disabling it, or rebooting the server. + +```rust +// Enable rescue mode and get the root password +print(`Enabling rescue mode on server with ID: ${test_server.id}`); +let root_password = client.enable_rescue_mode(test_server.id); +print(`Root password is: ${root_password}`); + +// Disable rescue mode +print(`Disabling rescue mode on server with ID: ${test_server.id}`); +client.disable_rescue_mode(test_server.id); + +// Reboot server +print(`Rebooting server with ID: ${test_server.id}`); +client.reboot(test_server.id); diff --git a/example.rhai b/example.rhai deleted file mode 100644 index ee5ef10..0000000 --- a/example.rhai +++ /dev/null @@ -1,49 +0,0 @@ -let client = new_hetzner_client(HETZNER_API_TOKEN); - -try { - print("Listing servers..."); - let servers = client.list_servers(); - - if servers.len() == 0 { - print("No servers found."); - } else { - print(servers.show_table()); - - let first_server = servers[0]; - print(`Getting details for server: ${first_server.name}`); - let detailed_server = client.get_server(first_server.id); - print(detailed_server.show_details()); - - // --- REBOOT --- - // To reboot the server, uncomment the following lines: - // print("\nAttempting to reboot the server..."); - // try { - // first_server.reboot(client); - // print("Reboot command sent successfully."); - // } catch(e) { - // print(`Error during reboot: ${e}`); - // } - - // --- ENABLE RESCUE MODE --- - // To enable rescue mode, uncomment the following lines: - // print("\nEnabling rescue mode..."); - // try { - // let root_password = first_server.enable_rescue_mode(client); - // print(`Rescue mode enabled. Root password: ${root_password}`); - // } catch(e) { - // print(`Error enabling rescue mode: ${e}`); - // } - - // --- DISABLE RESCUE MODE --- - // To disable rescue mode, uncomment the following lines: - // print("\nDisabling rescue mode..."); - // try { - // first_server.disable_rescue_mode(client); - // print("Rescue mode disabled."); - // } catch(e) { - // print(`Error disabling rescue mode: ${e}`); - // } - } -} catch (e) { - print(`An error occurred: ${e}`); -} \ No newline at end of file diff --git a/src/async_handler.rs b/src/async_handler.rs index 0036aff..93ccbd7 100644 --- a/src/async_handler.rs +++ b/src/async_handler.rs @@ -1,5 +1,4 @@ use crate::hetzner_api::{HetznerClient, WrappedServer}; -use std::net::IpAddr; use std::sync::mpsc::{Receiver, Sender}; use tokio::runtime::Builder; diff --git a/src/main.rs b/src/main.rs index 31adf51..e500e62 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,6 @@ mod error; mod hetzner_api; mod rhai_api; mod async_handler; -mod ping; use crate::rhai_api::register_hetzner_api; use rhai::{Engine, Scope}; diff --git a/src/ping.rs b/src/ping.rs deleted file mode 100644 index e69de29..0000000 diff --git a/src/rhai_api.rs b/src/rhai_api.rs index 6121c4d..e7fce39 100644 --- a/src/rhai_api.rs +++ b/src/rhai_api.rs @@ -41,38 +41,35 @@ pub fn register_hetzner_api( return Err("HETZNER_API_TOKEN cannot be empty.".into()); } Ok(HetznerClient::new(api_token)) + }) + .register_fn("list_servers", { + let bridge = api_bridge.clone(); + 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()), + }) + } + }) + .register_fn("get_server_status", { + let bridge = api_bridge.clone(); + 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()), + }) + } + }) + .register_fn("get_server", { + let bridge = api_bridge.clone(); + 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()), + }) + } }); - 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_type_with_name::("Server") .register_get("id", |server: &mut WrappedServer| server.0.id) @@ -86,46 +83,52 @@ pub fn register_hetzner_api( .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()), - } - }) - }); - 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()), + engine + .register_fn("reboot", { + let bridge = api_bridge.clone(); + move |client: &mut HetznerClient, server_id: i64| { + bridge.call(Request::RebootServer(client.clone(), server_id), |response| { + match response { + Response::RebootServer(result) => result.map_err(|e| e.into()), + _ => Err("Unexpected response".into()), + } + }) } }) - }); - - 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()), + .register_fn("reset", { + let bridge = api_bridge.clone(); + move |client: &mut HetznerClient, server_id: i64| { + bridge.call(Request::ResetServer(client.clone(), server_id), |response| { + match response { + Response::ResetServer(result) => result.map_err(|e| e.into()), + _ => Err("Unexpected response".into()), + } + }) } }) - }); - - 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()), + .register_fn("enable_rescue_mode", { + let bridge = api_bridge.clone(); + move |client: &mut HetznerClient, server_id: i64| { + bridge.call(Request::EnableRescueMode(client.clone(), server_id), |response| { + match response { + Response::EnableRescueMode(result) => result.map_err(|e| e.into()), + _ => Err("Unexpected response".into()), + } + }) } }) - }); + .register_fn("disable_rescue_mode", { + let bridge = api_bridge.clone(); + move |client: &mut HetznerClient, server_id: i64| { + bridge.call(Request::DisableRescueMode(client.clone(), server_id), |response| { + match response { + Response::DisableRescueMode(result) => result.map_err(|e| e.into()), + _ => Err("Unexpected response".into()), + } + }) + } + }); engine .register_iterator::>() diff --git a/test.rhai b/test.rhai new file mode 100644 index 0000000..98e85a8 --- /dev/null +++ b/test.rhai @@ -0,0 +1,25 @@ +// Create client to communicate with Hetzner API +let client = new_hetzner_client(HETZNER_API_TOKEN); + +// List all servers and print in table +print("Listing all servers..."); +let servers = client.list_servers(); +print(servers.show_table()); + +// Get server through ID and print details in table +print("Listing details from server with ID 104301883..."); +let test_server = client.get_server(104301883); +print(test_server.show_details()); + +// Enable rescue mode flag on server +print(`Enabling rescue mode on server with ID: ${test_server.id}`); +let root_password = client.enable_rescue_mode(test_server.id); +print(`Root password is: ${root_password}`); + +// Disable rescue mode flag on server +print(`Disabling rescue mode on server with ID: ${test_server.id}`); +client.disable_rescue_mode(test_server.id); + +// Reboot server +print(`Rebooting server with ID: ${test_server.id}`); +client.reboot(test_server.id); \ No newline at end of file