implemented additional server functions
This commit is contained in:
		@@ -1,9 +1,21 @@
 | 
				
			|||||||
// Get all servers and print them in a table
 | 
					// Get all servers and print them in a table
 | 
				
			||||||
let servers = hetzner.get_servers();
 | 
					// let servers = hetzner.get_servers();
 | 
				
			||||||
print(servers);
 | 
					// servers.pretty_print();
 | 
				
			||||||
servers.pretty_print();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Get a specific server and print its details
 | 
					// // Get a specific server and print its details
 | 
				
			||||||
// Replace 1825193 with the server number you want to fetch
 | 
					// // Replace 2550253 with the server number you want to fetch
 | 
				
			||||||
let server = hetzner.get_server(1825193);
 | 
					// let server = hetzner.get_server(2550253);
 | 
				
			||||||
print(server);
 | 
					// print(server);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Update the name of a specific server and print it
 | 
				
			||||||
 | 
					// print(hetzner.update_server_name(2550253, "kristof-123456"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Query cancellation data for a server
 | 
				
			||||||
 | 
					let c_d = hetzner.get_cancellation_data(2550253);
 | 
				
			||||||
 | 
					print(c_d);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Cancel a server
 | 
				
			||||||
 | 
					// Replace 2550253 with the server number you want to cancel
 | 
				
			||||||
 | 
					// Replace "2014-04-15" with the desired cancellation date
 | 
				
			||||||
 | 
					let cancelled_server = hetzner.cancel_server(2550253, "2014-04-15");
 | 
				
			||||||
 | 
					print(cancelled_server);
 | 
				
			||||||
@@ -1,22 +1,22 @@
 | 
				
			|||||||
// Get all SSH keys and print them in a table
 | 
					// Get all SSH keys and print them in a table
 | 
				
			||||||
let keys = hetzner.get_ssh_keys();
 | 
					let keys = hetzner.get_ssh_keys();
 | 
				
			||||||
print(keys);
 | 
					keys.pretty_print();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Get a specific SSH key
 | 
					// Get a specific SSH key
 | 
				
			||||||
// Replace "13:dc:a2:1e:a9:d2:1d:a9:39:f4:44:c5:f1:00:ec:c7" with the fingerprint of the key you want to fetch
 | 
					// Replace "13:dc:a2:1e:a9:d2:1d:a9:39:f4:44:c5:f1:00:ec:c7" with the fingerprint of the key you want to fetch
 | 
				
			||||||
let key = hetzner.get_ssh_key("13:dc:a2:1e:a9:d2:1d:a9:39:f4:44:c5:f1:00:ec:c7");
 | 
					// let key = hetzner.get_ssh_key("13:dc:a2:1e:a9:d2:1d:a9:39:f4:44:c5:f1:00:ec:c7");
 | 
				
			||||||
print(key);
 | 
					// print(key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Add a new SSH key
 | 
					// Add a new SSH key
 | 
				
			||||||
// Replace "my-new-key" with the desired name and "ssh-rsa ..." with your public key data
 | 
					// Replace "my-new-key" with the desired name and "ssh-rsa ..." with your public key data
 | 
				
			||||||
let new_key = hetzner.add_ssh_key("my-new-key", "ssh-rsa ...");
 | 
					// let new_key = hetzner.add_ssh_key("vanheesm@incubaid.com", "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFyZJCEsvRc0eitsOoq+ywC5Lmqejvk3hXMVbO0AxPrd");
 | 
				
			||||||
print(new_key);
 | 
					// print(new_key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Update an SSH key's name
 | 
					// Update an SSH key's name
 | 
				
			||||||
// Replace "cb:8b:ef:a7:fe:04:87:3f:e5:55:cd:12:e3:e8:9f:99" with the fingerprint of the key you want to update
 | 
					// Replace "cb:8b:ef:a7:fe:04:87:3f:e5:55:cd:12:e3:e8:9f:99" with the fingerprint of the key you want to update
 | 
				
			||||||
let updated_key = hetzner.update_ssh_key_name("cb:8b:ef:a7:fe:04:87:3f:e5:55:cd:12:e3:e8:9f:99", "my-updated-key-name");
 | 
					// let updated_key = hetzner.update_ssh_key_name("e0:73:80:26:80:46:f0:c8:bb:74:f4:d0:2d:10:2d:6f", "my-updated-key-name");
 | 
				
			||||||
print(updated_key);
 | 
					// print(updated_key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Delete an SSH key
 | 
					// Delete an SSH key
 | 
				
			||||||
// Replace "cb:8b:ef:a7:fe:04:87:3f:e5:55:cd:12:e3:e8:9f:99" with the fingerprint of the key you want to delete
 | 
					// Replace "cb:8b:ef:a7:fe:04:87:3f:e5:55:cd:12:e3:e8:9f:99" with the fingerprint of the key you want to delete
 | 
				
			||||||
hetzner.delete_ssh_key("cb:8b:ef:a7:fe:04:87:3f:e5:55:cd:12:e3:e8:9f:99");
 | 
					// hetzner.delete_ssh_key("e1:a7:27:ed:12:77:6a:4c:3a:cd:30:18:c4:f3:d0:88");
 | 
				
			||||||
@@ -1,12 +1,54 @@
 | 
				
			|||||||
use crate::api::models::ApiError;
 | 
					use std::fmt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use serde::Deserialize;
 | 
				
			||||||
use thiserror::Error;
 | 
					use thiserror::Error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Error)]
 | 
					#[derive(Debug, Error)]
 | 
				
			||||||
pub enum AppError {
 | 
					pub enum AppError {
 | 
				
			||||||
    #[error("Request failed: {0}")]
 | 
					    #[error("Request failed: {0}")]
 | 
				
			||||||
    RequestError(#[from] reqwest::Error),
 | 
					    RequestError(#[from] reqwest::Error),
 | 
				
			||||||
    #[error("API error: {0:?}")]
 | 
					    #[error("API error: {0}")]
 | 
				
			||||||
    ApiError(ApiError),
 | 
					    ApiError(ApiError),
 | 
				
			||||||
    #[error("Deserialization Error: {0:?}")]
 | 
					    #[error("Deserialization Error: {0:?}")]
 | 
				
			||||||
    SerdeJsonError(#[from] serde_json::Error),
 | 
					    SerdeJsonError(#[from] serde_json::Error),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Deserialize)]
 | 
				
			||||||
 | 
					pub struct ApiError {
 | 
				
			||||||
 | 
					    pub status: u16,
 | 
				
			||||||
 | 
					    pub message: String,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl From<reqwest::blocking::Response> for ApiError {
 | 
				
			||||||
 | 
					    fn from(value: reqwest::blocking::Response) -> Self {
 | 
				
			||||||
 | 
					        ApiError {
 | 
				
			||||||
 | 
					            status: value.status().into(),
 | 
				
			||||||
 | 
					            message: value.text().unwrap_or("The API call returned an error.".to_string()),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl fmt::Display for ApiError {
 | 
				
			||||||
 | 
					    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 | 
				
			||||||
 | 
					        #[derive(Deserialize)]
 | 
				
			||||||
 | 
					        struct HetznerApiError {
 | 
				
			||||||
 | 
					            code: String,
 | 
				
			||||||
 | 
					            message: String,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #[derive(Deserialize)]
 | 
				
			||||||
 | 
					        struct HetznerApiErrorWrapper {
 | 
				
			||||||
 | 
					            error: HetznerApiError,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if let Ok(wrapper) = serde_json::from_str::<HetznerApiErrorWrapper>(&self.message) {
 | 
				
			||||||
 | 
					            write!(
 | 
				
			||||||
 | 
					                f,
 | 
				
			||||||
 | 
					                "Status: {}, Code: {}, Message: {}",
 | 
				
			||||||
 | 
					                self.status, wrapper.error.code, wrapper.error.message
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            write!(f, "Status: {}: {}", self.status, self.message)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										124
									
								
								src/api/mod.rs
									
									
									
									
									
								
							
							
						
						
									
										124
									
								
								src/api/mod.rs
									
									
									
									
									
								
							@@ -1,15 +1,14 @@
 | 
				
			|||||||
pub mod error;
 | 
					pub mod error;
 | 
				
			||||||
pub mod models;
 | 
					pub mod models;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use std::any::type_name;
 | 
					use self::models::{Boot, Rescue, Server, SshKey};
 | 
				
			||||||
 | 
					use crate::api::error::ApiError;
 | 
				
			||||||
use self::models::{
 | 
					use crate::api::models::{
 | 
				
			||||||
    Boot, Rescue, Server, SshKey,
 | 
					    BootWrapper, Cancellation, CancellationWrapper, RescueWrapped, ServerWrapper, SshKeyWrapper,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use crate::config::Config;
 | 
					use crate::config::Config;
 | 
				
			||||||
use error::AppError;
 | 
					use error::AppError;
 | 
				
			||||||
use reqwest::blocking::Client as HttpClient;
 | 
					use reqwest::blocking::Client as HttpClient;
 | 
				
			||||||
use reqwest::StatusCode;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Clone)]
 | 
					#[derive(Clone)]
 | 
				
			||||||
pub struct Client {
 | 
					pub struct Client {
 | 
				
			||||||
@@ -32,13 +31,10 @@ impl Client {
 | 
				
			|||||||
        let status = response.status();
 | 
					        let status = response.status();
 | 
				
			||||||
        let body = response.text()?;
 | 
					        let body = response.text()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        println!("RESPONSE: \n{}", &body);
 | 
					        if status.is_success() {
 | 
				
			||||||
        println!("Type of T to handle_response: {:#?}", type_name::<T>());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if status == StatusCode::OK {
 | 
					 | 
				
			||||||
            serde_json::from_str::<T>(&body).map_err(Into::into)
 | 
					            serde_json::from_str::<T>(&body).map_err(Into::into)
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            Err(AppError::ApiError(models::ApiError {
 | 
					            Err(AppError::ApiError(ApiError {
 | 
				
			||||||
                status: status.as_u16(),
 | 
					                status: status.as_u16(),
 | 
				
			||||||
                message: body,
 | 
					                message: body,
 | 
				
			||||||
            }))
 | 
					            }))
 | 
				
			||||||
@@ -48,14 +44,12 @@ impl Client {
 | 
				
			|||||||
    pub fn get_server(&self, server_number: i32) -> Result<Server, AppError> {
 | 
					    pub fn get_server(&self, server_number: i32) -> Result<Server, AppError> {
 | 
				
			||||||
        let response = self
 | 
					        let response = self
 | 
				
			||||||
            .http_client
 | 
					            .http_client
 | 
				
			||||||
            .get(format!(
 | 
					            .get(format!("{}/server/{}", self.config.api_url, server_number))
 | 
				
			||||||
                "{}/server/{}",
 | 
					 | 
				
			||||||
                self.config.api_url, server_number
 | 
					 | 
				
			||||||
            ))
 | 
					 | 
				
			||||||
            .basic_auth(&self.config.username, Some(&self.config.password))
 | 
					            .basic_auth(&self.config.username, Some(&self.config.password))
 | 
				
			||||||
            .send()?;
 | 
					            .send()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.handle_response(response)
 | 
					        let wrapped: ServerWrapper = self.handle_response(response)?;
 | 
				
			||||||
 | 
					        Ok(wrapped.server)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn get_servers(&self) -> Result<Vec<Server>, AppError> {
 | 
					    pub fn get_servers(&self) -> Result<Vec<Server>, AppError> {
 | 
				
			||||||
@@ -65,8 +59,70 @@ impl Client {
 | 
				
			|||||||
            .basic_auth(&self.config.username, Some(&self.config.password))
 | 
					            .basic_auth(&self.config.username, Some(&self.config.password))
 | 
				
			||||||
            .send()?;
 | 
					            .send()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.handle_response(response)
 | 
					        let wrapped: Vec<ServerWrapper> = self.handle_response(response)?;
 | 
				
			||||||
 | 
					        let servers = wrapped.into_iter().map(|sw| sw.server).collect();
 | 
				
			||||||
 | 
					        Ok(servers)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn update_server_name(&self, server_number: i32, name: &str) -> Result<Server, AppError> {
 | 
				
			||||||
 | 
					        let params = [("server_name", name)];
 | 
				
			||||||
 | 
					        let response = self
 | 
				
			||||||
 | 
					            .http_client
 | 
				
			||||||
 | 
					            .post(format!("{}/server/{}", self.config.api_url, server_number))
 | 
				
			||||||
 | 
					            .basic_auth(&self.config.username, Some(&self.config.password))
 | 
				
			||||||
 | 
					            .form(¶ms)
 | 
				
			||||||
 | 
					            .send()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let wrapped: ServerWrapper = self.handle_response(response)?;
 | 
				
			||||||
 | 
					        Ok(wrapped.server)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn get_cancellation_data(&self, server_number: i32) -> Result<Cancellation, AppError> {
 | 
				
			||||||
 | 
					        let response = self
 | 
				
			||||||
 | 
					            .http_client
 | 
				
			||||||
 | 
					            .get(format!(
 | 
				
			||||||
 | 
					                "{}/server/{}/cancellation",
 | 
				
			||||||
 | 
					                self.config.api_url, server_number
 | 
				
			||||||
 | 
					            ))
 | 
				
			||||||
 | 
					            .basic_auth(&self.config.username, Some(&self.config.password))
 | 
				
			||||||
 | 
					            .send()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let wrapped: CancellationWrapper = self.handle_response(response)?;
 | 
				
			||||||
 | 
					        Ok(wrapped.cancellation)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn cancel_server(
 | 
				
			||||||
 | 
					        &self,
 | 
				
			||||||
 | 
					        server_number: i32,
 | 
				
			||||||
 | 
					        cancellation_date: &str,
 | 
				
			||||||
 | 
					    ) -> Result<Cancellation, AppError> {
 | 
				
			||||||
 | 
					        let params = [("cancellation_date", cancellation_date)];
 | 
				
			||||||
 | 
					        let response = self
 | 
				
			||||||
 | 
					            .http_client
 | 
				
			||||||
 | 
					            .post(format!(
 | 
				
			||||||
 | 
					                "{}/server/{}/cancellation",
 | 
				
			||||||
 | 
					                self.config.api_url, server_number
 | 
				
			||||||
 | 
					            ))
 | 
				
			||||||
 | 
					            .basic_auth(&self.config.username, Some(&self.config.password))
 | 
				
			||||||
 | 
					            .form(¶ms)
 | 
				
			||||||
 | 
					            .send()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let wrapped: CancellationWrapper = self.handle_response(response)?;
 | 
				
			||||||
 | 
					        Ok(wrapped.cancellation)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn withdraw_cancellation(&self, server_number: i32) -> Result<(), AppError> {
 | 
				
			||||||
 | 
					        self.http_client
 | 
				
			||||||
 | 
					            .delete(format!(
 | 
				
			||||||
 | 
					                "{}/server/{}/cancellation",
 | 
				
			||||||
 | 
					                self.config.api_url, server_number
 | 
				
			||||||
 | 
					            ))
 | 
				
			||||||
 | 
					            .basic_auth(&self.config.username, Some(&self.config.password))
 | 
				
			||||||
 | 
					            .send()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn get_ssh_keys(&self) -> Result<Vec<SshKey>, AppError> {
 | 
					    pub fn get_ssh_keys(&self) -> Result<Vec<SshKey>, AppError> {
 | 
				
			||||||
        let response = self
 | 
					        let response = self
 | 
				
			||||||
            .http_client
 | 
					            .http_client
 | 
				
			||||||
@@ -74,7 +130,9 @@ impl Client {
 | 
				
			|||||||
            .basic_auth(&self.config.username, Some(&self.config.password))
 | 
					            .basic_auth(&self.config.username, Some(&self.config.password))
 | 
				
			||||||
            .send()?;
 | 
					            .send()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.handle_response(response)
 | 
					        let wrapped: Vec<SshKeyWrapper> = self.handle_response(response)?;
 | 
				
			||||||
 | 
					        let keys = wrapped.into_iter().map(|sk| sk.key).collect();
 | 
				
			||||||
 | 
					        Ok(keys)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn get_ssh_key(&self, fingerprint: &str) -> Result<SshKey, AppError> {
 | 
					    pub fn get_ssh_key(&self, fingerprint: &str) -> Result<SshKey, AppError> {
 | 
				
			||||||
@@ -84,7 +142,8 @@ impl Client {
 | 
				
			|||||||
            .basic_auth(&self.config.username, Some(&self.config.password))
 | 
					            .basic_auth(&self.config.username, Some(&self.config.password))
 | 
				
			||||||
            .send()?;
 | 
					            .send()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.handle_response(response)
 | 
					        let wrapped: SshKeyWrapper = self.handle_response(response)?;
 | 
				
			||||||
 | 
					        Ok(wrapped.key)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn add_ssh_key(&self, name: &str, data: &str) -> Result<SshKey, AppError> {
 | 
					    pub fn add_ssh_key(&self, name: &str, data: &str) -> Result<SshKey, AppError> {
 | 
				
			||||||
@@ -96,14 +155,11 @@ impl Client {
 | 
				
			|||||||
            .form(¶ms)
 | 
					            .form(¶ms)
 | 
				
			||||||
            .send()?;
 | 
					            .send()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.handle_response(response)
 | 
					        let wrapped: SshKeyWrapper = self.handle_response(response)?;
 | 
				
			||||||
 | 
					        Ok(wrapped.key)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn update_ssh_key_name(
 | 
					    pub fn update_ssh_key_name(&self, fingerprint: &str, name: &str) -> Result<SshKey, AppError> {
 | 
				
			||||||
        &self,
 | 
					 | 
				
			||||||
        fingerprint: &str,
 | 
					 | 
				
			||||||
        name: &str,
 | 
					 | 
				
			||||||
    ) -> Result<SshKey, AppError> {
 | 
					 | 
				
			||||||
        let params = [("name", name)];
 | 
					        let params = [("name", name)];
 | 
				
			||||||
        let response = self
 | 
					        let response = self
 | 
				
			||||||
            .http_client
 | 
					            .http_client
 | 
				
			||||||
@@ -112,7 +168,8 @@ impl Client {
 | 
				
			|||||||
            .form(¶ms)
 | 
					            .form(¶ms)
 | 
				
			||||||
            .send()?;
 | 
					            .send()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.handle_response(response)
 | 
					        let wrapped: SshKeyWrapper = self.handle_response(response)?;
 | 
				
			||||||
 | 
					        Ok(wrapped.key)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn delete_ssh_key(&self, fingerprint: &str) -> Result<(), AppError> {
 | 
					    pub fn delete_ssh_key(&self, fingerprint: &str) -> Result<(), AppError> {
 | 
				
			||||||
@@ -130,13 +187,11 @@ impl Client {
 | 
				
			|||||||
            .basic_auth(&self.config.username, Some(&self.config.password))
 | 
					            .basic_auth(&self.config.username, Some(&self.config.password))
 | 
				
			||||||
            .send()?;
 | 
					            .send()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.handle_response(response)
 | 
					        let wrapped: BootWrapper = self.handle_response(response)?;
 | 
				
			||||||
 | 
					        Ok(wrapped.boot)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn get_rescue_boot_configuration(
 | 
					    pub fn get_rescue_boot_configuration(&self, server_number: i32) -> Result<Rescue, AppError> {
 | 
				
			||||||
        &self,
 | 
					 | 
				
			||||||
        server_number: i32,
 | 
					 | 
				
			||||||
    ) -> Result<Rescue, AppError> {
 | 
					 | 
				
			||||||
        let response = self
 | 
					        let response = self
 | 
				
			||||||
            .http_client
 | 
					            .http_client
 | 
				
			||||||
            .get(format!(
 | 
					            .get(format!(
 | 
				
			||||||
@@ -146,7 +201,8 @@ impl Client {
 | 
				
			|||||||
            .basic_auth(&self.config.username, Some(&self.config.password))
 | 
					            .basic_auth(&self.config.username, Some(&self.config.password))
 | 
				
			||||||
            .send()?;
 | 
					            .send()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.handle_response(response)
 | 
					        let wrapped: RescueWrapped = self.handle_response(response)?;
 | 
				
			||||||
 | 
					        Ok(wrapped.rescue)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn enable_rescue_mode(
 | 
					    pub fn enable_rescue_mode(
 | 
				
			||||||
@@ -171,7 +227,8 @@ impl Client {
 | 
				
			|||||||
            .form(¶ms)
 | 
					            .form(¶ms)
 | 
				
			||||||
            .send()?;
 | 
					            .send()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.handle_response(response)
 | 
					        let wrapped: RescueWrapped = self.handle_response(response)?;
 | 
				
			||||||
 | 
					        Ok(wrapped.rescue)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn disable_rescue_mode(&self, server_number: i32) -> Result<Rescue, AppError> {
 | 
					    pub fn disable_rescue_mode(&self, server_number: i32) -> Result<Rescue, AppError> {
 | 
				
			||||||
@@ -184,6 +241,7 @@ impl Client {
 | 
				
			|||||||
            .basic_auth(&self.config.username, Some(&self.config.password))
 | 
					            .basic_auth(&self.config.username, Some(&self.config.password))
 | 
				
			||||||
            .send()?;
 | 
					            .send()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.handle_response(response)
 | 
					        let wrapped: RescueWrapped = self.handle_response(response)?;
 | 
				
			||||||
 | 
					        Ok(wrapped.rescue)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -88,6 +88,10 @@ impl fmt::Display for Server {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Deserialize)]
 | 
				
			||||||
 | 
					struct SubnetWrapper {
 | 
				
			||||||
 | 
					    _subnet: Subnet,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Deserialize, Clone, CustomType)]
 | 
					#[derive(Debug, Deserialize, Clone, CustomType)]
 | 
				
			||||||
#[rhai_type(extra = Self::build_rhai_type)]
 | 
					#[rhai_type(extra = Self::build_rhai_type)]
 | 
				
			||||||
@@ -113,6 +117,11 @@ impl fmt::Display for Subnet {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Deserialize)]
 | 
				
			||||||
 | 
					pub struct SshKeyWrapper {
 | 
				
			||||||
 | 
					    pub key: SshKey,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Deserialize, Clone, CustomType)]
 | 
					#[derive(Debug, Deserialize, Clone, CustomType)]
 | 
				
			||||||
#[rhai_type(extra = Self::build_rhai_type)]
 | 
					#[rhai_type(extra = Self::build_rhai_type)]
 | 
				
			||||||
pub struct SshKey {
 | 
					pub struct SshKey {
 | 
				
			||||||
@@ -211,6 +220,11 @@ impl fmt::Display for Boot {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Deserialize)]
 | 
				
			||||||
 | 
					pub struct RescueWrapped {
 | 
				
			||||||
 | 
					    pub rescue: Rescue,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Deserialize, Clone, CustomType)]
 | 
					#[derive(Debug, Deserialize, Clone, CustomType)]
 | 
				
			||||||
#[rhai_type(extra = Self::build_rhai_type)]
 | 
					#[rhai_type(extra = Self::build_rhai_type)]
 | 
				
			||||||
pub struct Rescue {
 | 
					pub struct Rescue {
 | 
				
			||||||
@@ -488,6 +502,91 @@ impl fmt::Display for Cpanel {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Deserialize, Clone)]
 | 
				
			||||||
 | 
					pub struct CancellationWrapper {
 | 
				
			||||||
 | 
					    pub cancellation: Cancellation,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Deserialize, Clone, CustomType)]
 | 
				
			||||||
 | 
					#[rhai_type(extra = Self::build_rhai_type)]
 | 
				
			||||||
 | 
					pub struct Cancellation {
 | 
				
			||||||
 | 
					    pub server_ip: String,
 | 
				
			||||||
 | 
					    pub server_ipv6_net: Option<String>,
 | 
				
			||||||
 | 
					    pub server_number: i32,
 | 
				
			||||||
 | 
					    pub server_name: String,
 | 
				
			||||||
 | 
					    pub earliest_cancellation_date: String,
 | 
				
			||||||
 | 
					    pub cancelled: bool,
 | 
				
			||||||
 | 
					    pub reservation_possible: bool,
 | 
				
			||||||
 | 
					    pub reserved: bool,
 | 
				
			||||||
 | 
					    pub cancellation_date: Option<String>,
 | 
				
			||||||
 | 
					    pub cancellation_reason: Vec<String>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Cancellation {
 | 
				
			||||||
 | 
					    fn build_rhai_type(builder: &mut TypeBuilder<Self>) {
 | 
				
			||||||
 | 
					        builder
 | 
				
			||||||
 | 
					            .with_name("Cancellation")
 | 
				
			||||||
 | 
					            .with_get("server_ip", |c: &mut Cancellation| c.server_ip.clone())
 | 
				
			||||||
 | 
					            .with_get("server_ipv6_net", |c: &mut Cancellation| {
 | 
				
			||||||
 | 
					                c.server_ipv6_net.clone()
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .with_get("server_number", |c: &mut Cancellation| c.server_number)
 | 
				
			||||||
 | 
					            .with_get("server_name", |c: &mut Cancellation| c.server_name.clone())
 | 
				
			||||||
 | 
					            .with_get("earliest_cancellation_date", |c: &mut Cancellation| {
 | 
				
			||||||
 | 
					                c.earliest_cancellation_date.clone()
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .with_get("cancelled", |c: &mut Cancellation| c.cancelled)
 | 
				
			||||||
 | 
					            .with_get("reservation_possible", |c: &mut Cancellation| {
 | 
				
			||||||
 | 
					                c.reservation_possible
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .with_get("reserved", |c: &mut Cancellation| c.reserved)
 | 
				
			||||||
 | 
					            .with_get("cancellation_date", |c: &mut Cancellation| {
 | 
				
			||||||
 | 
					                c.cancellation_date.clone()
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .with_get("cancellation_reason", |c: &mut Cancellation| {
 | 
				
			||||||
 | 
					                c.cancellation_reason.clone()
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .on_print(|c: &mut Cancellation| c.to_string())
 | 
				
			||||||
 | 
					            .with_fn("pretty_print", |c: &mut Cancellation| c.to_string());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl fmt::Display for Cancellation {
 | 
				
			||||||
 | 
					    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 | 
				
			||||||
 | 
					        let mut table = Table::new();
 | 
				
			||||||
 | 
					        table.add_row(row!["Property", "Value"]);
 | 
				
			||||||
 | 
					        table.add_row(row!["Server IP", self.server_ip.clone()]);
 | 
				
			||||||
 | 
					        table.add_row(row![
 | 
				
			||||||
 | 
					            "Server IPv6 Net",
 | 
				
			||||||
 | 
					            self.server_ipv6_net
 | 
				
			||||||
 | 
					                .as_deref()
 | 
				
			||||||
 | 
					                .unwrap_or("N/A")
 | 
				
			||||||
 | 
					                .to_string()
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					        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![
 | 
				
			||||||
 | 
					            "Earliest Cancellation Date",
 | 
				
			||||||
 | 
					            self.earliest_cancellation_date.clone()
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					        table.add_row(row!["Cancelled", self.cancelled.to_string()]);
 | 
				
			||||||
 | 
					        table.add_row(row!["Reservation Possible", self.reservation_possible.to_string()]);
 | 
				
			||||||
 | 
					        table.add_row(row!["Reserved", self.reserved.to_string()]);
 | 
				
			||||||
 | 
					        table.add_row(row![
 | 
				
			||||||
 | 
					            "Cancellation Date",
 | 
				
			||||||
 | 
					            self.cancellation_date
 | 
				
			||||||
 | 
					                .as_deref()
 | 
				
			||||||
 | 
					                .unwrap_or("N/A")
 | 
				
			||||||
 | 
					                .to_string()
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					        table.add_row(row![
 | 
				
			||||||
 | 
					            "Cancellation Reason",
 | 
				
			||||||
 | 
					            self.cancellation_reason.join(", ")
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					        write!(f, "{}", table)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn string_or_seq_string<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
 | 
					fn string_or_seq_string<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
 | 
				
			||||||
where
 | 
					where
 | 
				
			||||||
    D: Deserializer<'de>,
 | 
					    D: Deserializer<'de>,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
use crate::api::Client;
 | 
					use crate::api::Client;
 | 
				
			||||||
use crate::api::models::{Rescue, Linux, Vnc, Windows, Plesk, Cpanel, Boot, Server, SshKey};
 | 
					use crate::api::models::{Rescue, Linux, Vnc, Windows, Plesk, Cpanel, Boot, Server, SshKey, Cancellation};
 | 
				
			||||||
use rhai::{Engine, Scope};
 | 
					use rhai::{Engine, Scope};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub mod server;
 | 
					pub mod server;
 | 
				
			||||||
@@ -20,6 +20,7 @@ pub fn setup_engine(client: Client) -> (Engine, Scope<'static>) {
 | 
				
			|||||||
    engine.build_type::<Windows>();
 | 
					    engine.build_type::<Windows>();
 | 
				
			||||||
    engine.build_type::<Plesk>();
 | 
					    engine.build_type::<Plesk>();
 | 
				
			||||||
    engine.build_type::<Cpanel>();
 | 
					    engine.build_type::<Cpanel>();
 | 
				
			||||||
 | 
					    engine.build_type::<Cancellation>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    server::register(&mut engine);
 | 
					    server::register(&mut engine);
 | 
				
			||||||
    ssh_keys::register(&mut engine);
 | 
					    ssh_keys::register(&mut engine);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,7 @@ mod servers_table;
 | 
				
			|||||||
mod ssh_keys_table;
 | 
					mod ssh_keys_table;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn pretty_print_dispatch(array: Array) {
 | 
					pub fn pretty_print_dispatch(array: Array) {
 | 
				
			||||||
 | 
					    println!("pretty print dispatch");
 | 
				
			||||||
    if array.is_empty() {
 | 
					    if array.is_empty() {
 | 
				
			||||||
        println!("<empty table>");
 | 
					        println!("<empty table>");
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,5 @@
 | 
				
			|||||||
use crate::api::{models::Server, Client};
 | 
					use crate::api::{Client, models::Server};
 | 
				
			||||||
use prettytable::{row, Table};
 | 
					use rhai::{Array, Dynamic, plugin::*};
 | 
				
			||||||
use rhai::{plugin::*, Array, Dynamic};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn register(engine: &mut Engine) {
 | 
					pub fn register(engine: &mut Engine) {
 | 
				
			||||||
    let server_module = exported_module!(server_api);
 | 
					    let server_module = exported_module!(server_api);
 | 
				
			||||||
@@ -9,6 +8,8 @@ pub fn register(engine: &mut Engine) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#[export_module]
 | 
					#[export_module]
 | 
				
			||||||
pub mod server_api {
 | 
					pub mod server_api {
 | 
				
			||||||
 | 
					    use crate::api::models::Cancellation;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    use super::*;
 | 
					    use super::*;
 | 
				
			||||||
    use rhai::EvalAltResult;
 | 
					    use rhai::EvalAltResult;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -30,4 +31,46 @@ pub mod server_api {
 | 
				
			|||||||
        Ok(servers.into_iter().map(Dynamic::from).collect())
 | 
					        Ok(servers.into_iter().map(Dynamic::from).collect())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[rhai_fn(name = "update_server_name", return_raw)]
 | 
				
			||||||
 | 
					    pub fn update_server_name(
 | 
				
			||||||
 | 
					        client: &mut Client,
 | 
				
			||||||
 | 
					        server_number: i64,
 | 
				
			||||||
 | 
					        name: &str,
 | 
				
			||||||
 | 
					    ) -> Result<Server, Box<EvalAltResult>> {
 | 
				
			||||||
 | 
					        client
 | 
				
			||||||
 | 
					            .update_server_name(server_number as i32, name)
 | 
				
			||||||
 | 
					            .map_err(|e| e.to_string().into())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[rhai_fn(name = "get_cancellation_data", return_raw)]
 | 
				
			||||||
 | 
					    pub fn get_cancellation_data(
 | 
				
			||||||
 | 
					        client: &mut Client,
 | 
				
			||||||
 | 
					        server_number: i64,
 | 
				
			||||||
 | 
					    ) -> Result<Cancellation, Box<EvalAltResult>> {
 | 
				
			||||||
 | 
					        client
 | 
				
			||||||
 | 
					            .get_cancellation_data(server_number as i32)
 | 
				
			||||||
 | 
					            .map_err(|e| e.to_string().into())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[rhai_fn(name = "cancel_server", return_raw)]
 | 
				
			||||||
 | 
					    pub fn cancel_server(
 | 
				
			||||||
 | 
					        client: &mut Client,
 | 
				
			||||||
 | 
					        server_number: i64,
 | 
				
			||||||
 | 
					        cancellation_date: &str,
 | 
				
			||||||
 | 
					    ) -> Result<Cancellation, Box<EvalAltResult>> {
 | 
				
			||||||
 | 
					        client
 | 
				
			||||||
 | 
					            .cancel_server(server_number as i32, cancellation_date)
 | 
				
			||||||
 | 
					            .map_err(|e| e.to_string().into())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[rhai_fn(name = "withdraw_cancellation", return_raw)]
 | 
				
			||||||
 | 
					    pub fn withdraw_cancellation(
 | 
				
			||||||
 | 
					        client: &mut Client,
 | 
				
			||||||
 | 
					        server_number: i64,
 | 
				
			||||||
 | 
					        cancellation_date: &str,
 | 
				
			||||||
 | 
					    ) -> Result<(), Box<EvalAltResult>> {
 | 
				
			||||||
 | 
					        client
 | 
				
			||||||
 | 
					            .withdraw_cancellation(server_number as i32)
 | 
				
			||||||
 | 
					            .map_err(|e| e.to_string().into())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user