cleanup + added test script to demonstrate functioality + removed uncessary ping module

This commit is contained in:
Maxime Van Hees 2025-07-15 16:10:35 +02:00
parent 5e8e9754b2
commit b4200a2673
7 changed files with 148 additions and 119 deletions

View File

@ -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
```
cargo run -- <script_name>.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);

View File

@ -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}`);
}

View File

@ -1,5 +1,4 @@
use crate::hetzner_api::{HetznerClient, WrappedServer};
use std::net::IpAddr;
use std::sync::mpsc::{Receiver, Sender};
use tokio::runtime::Builder;

View File

@ -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};

View File

View File

@ -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::<WrappedServer>("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::<Vec<WrappedServer>>()

25
test.rhai Normal file
View File

@ -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);