updated models to work with API + added a README

This commit is contained in:
Maxime Van Hees 2025-07-24 17:31:36 +02:00
parent 038229bb92
commit abfb79b0cd
4 changed files with 48 additions and 11 deletions

29
README.md Normal file
View File

@ -0,0 +1,29 @@
# Hetzner Robot API Rhai Client
This project provides a Rhai scripting client for interacting with the Hetzner Robot API. It allows users to manage their Hetzner servers, SSH keys, boot configurations, and order new servers and addons directly from Rhai scripts.
## Goal
The primary goal of this project is to offer a flexible and scriptable interface to the Hetzner Robot API, enabling automation of server management tasks. By leveraging Rhai, users can write simple yet powerful scripts to interact with their Hetzner infrastructure.
## Examples
The `examples/` directory contains several Rhai scripts demonstrating the capabilities of this client:
- [`examples/server_management.rhai`](examples/server_management.rhai): Showcases basic server management operations, such as fetching server details and updating server names.
- [`examples/ssh_key_management.rhai`](examples/ssh_key_management.rhai): Demonstrates how to list, add, update, and delete SSH keys.
- [`examples/boot_management.rhai`](examples/boot_management.rhai): Provides examples for managing server boot configurations, including rescue mode.
- [`examples/server_ordering.rhai`](examples/server_ordering.rhai): Contains comprehensive examples for ordering new servers and managing server addons, including:
- Getting available server products.
- Ordering new servers.
- Listing server order transactions.
- Fetching specific transaction details.
- Listing and ordering auction servers.
- Getting available server addon products.
- Listing server addon transactions.
- Ordering server addons.
- Querying specific server addon transactions.
## Important Note on IPv6 Addresses
When ordering a server without an IPv4 addon, the server might be assigned an IPv6 network like `2a01:4f8:221:1fe3::/64`. It's important to note that you cannot directly SSH to this network address. Hetzner does not use SLAAC for server assignments. The actual address to SSH to will typically be the network address with `2` appended (e.g., `2a01:4f8:221:1fe3::2`).

View File

@ -504,7 +504,7 @@ impl Client {
.http_client
.post(format!("{}/order/server_addon/transaction", &self.config.api_url))
.basic_auth(&self.config.username, Some(&self.config.password))
.json(&params)
.form(&params)
.send()?;
let wrapped: ServerAddonTransactionWrapper = self.handle_response(response)?;

View File

@ -12,8 +12,8 @@ pub struct ServerWrapper {
#[derive(Debug, Deserialize, Clone, CustomType)]
#[rhai_type(extra = Self::build_rhai_type)]
pub struct Server {
pub server_ip: String,
pub server_ipv6_net: String,
pub server_ip: Option<String>,
pub server_ipv6_net: Option<String>,
pub server_number: i32,
pub server_name: String,
pub product: String,
@ -22,7 +22,7 @@ pub struct Server {
pub status: String,
pub cancelled: bool,
pub paid_until: String,
pub ip: Vec<String>,
pub ip: Option<Vec<String>>,
pub subnet: Option<Vec<Subnet>>,
pub reset: Option<bool>,
pub rescue: Option<bool>,
@ -39,9 +39,11 @@ impl Server {
fn build_rhai_type(builder: &mut TypeBuilder<Self>) {
builder
.with_name("Server")
.with_get("server_ip", |s: &mut Server| s.server_ip.clone())
.with_get("server_ip", |s: &mut Server| {
s.server_ip.clone().unwrap_or_default()
})
.with_get("server_ipv6_net", |s: &mut Server| {
s.server_ipv6_net.clone()
s.server_ipv6_net.clone().unwrap_or_default()
})
.with_get("server_number", |s: &mut Server| s.server_number)
.with_get("server_name", |s: &mut Server| s.server_name.clone())
@ -51,7 +53,7 @@ impl Server {
.with_get("status", |s: &mut Server| s.status.clone())
.with_get("cancelled", |s: &mut Server| s.cancelled)
.with_get("paid_until", |s: &mut Server| s.paid_until.clone())
.with_get("ip", |s: &mut Server| s.ip.clone())
.with_get("ip", |s: &mut Server| s.ip.clone().unwrap_or_default())
.with_get("subnet", |s: &mut Server| s.subnet.clone())
.with_get("reset", |s: &mut Server| s.reset.clone())
.with_get("rescue", |s: &mut Server| s.rescue.clone())
@ -78,16 +80,22 @@ impl fmt::Display for Server {
table.add_row(row!["Property", "Value"]);
table.add_row(row!["Server Number", self.server_number.to_string()]);
table.add_row(row!["Server Name", self.server_name.clone()]);
table.add_row(row!["Server IP", self.server_ip.clone()]);
table.add_row(row!["IPv6 Network", self.server_ipv6_net.clone()]);
table.add_row(row![
"Server IP",
self.server_ip.as_deref().unwrap_or("N/A")
]);
table.add_row(row![
"IPv6 Network",
self.server_ipv6_net.as_deref().unwrap_or("N/A")
]);
table.add_row(row!["Product", self.product.clone()]);
table.add_row(row!["Datacenter", self.dc.clone()]);
table.add_row(row!["Traffic", self.traffic.clone()]);
table.add_row(row!["Status", self.status.clone()]);
table.add_row(row!["Cancelled", self.cancelled.to_string()]);
table.add_row(row!["Paid Until", self.paid_until.clone()]);
table.add_row(row!["IP Addresses", self.ip.as_deref().unwrap_or_default().join(", ")]);
table.add_row(row!["Reset", self.reset.unwrap_or(false).to_string()]);
table.add_row(row!["Rescue", self.rescue.unwrap_or(false).to_string()]);
table.add_row(row!["VNC", self.vnc.unwrap_or(false).to_string()]);
table.add_row(row!["Windows", self.windows.is_some().to_string()]);
table.add_row(row!["Plesk", self.plesk.is_some().to_string()]);

View File

@ -19,7 +19,7 @@ pub fn pretty_print_servers(servers: Array) {
table.add_row(row![
server.server_number.to_string(),
server.server_name,
server.server_ip,
server.server_ip.unwrap_or("N/A".to_string()),
server.product,
server.dc,
server.status