added functionality to list SSH key IDs
This commit is contained in:
		| @@ -1,4 +1,4 @@ | ||||
| use crate::hetzner_api::{HetznerClient, WrappedServer}; | ||||
| use crate::hetzner_api::{HetznerClient, WrappedServer, WrappedSshKey}; | ||||
| use std::sync::mpsc::{Receiver, Sender}; | ||||
| use tokio::runtime::Builder; | ||||
|  | ||||
| @@ -11,9 +11,11 @@ pub enum Request { | ||||
|     ResetServer(HetznerClient, i64), | ||||
|     EnableRescueMode(HetznerClient, i64, Vec<i64>), | ||||
|     DisableRescueMode(HetznerClient, i64), | ||||
|     ListSshKeys(HetznerClient), | ||||
| } | ||||
|  | ||||
| pub enum Response { | ||||
|     ListSshKeys(Result<Vec<WrappedSshKey>, String>), | ||||
|     ListServers(Result<Vec<WrappedServer>, String>), | ||||
|     GetServerStatus(Result<String, String>), | ||||
|     GetServer(Result<WrappedServer, String>), | ||||
| @@ -63,6 +65,10 @@ pub fn run_worker( | ||||
|                     let result = rt.block_on(client.disable_rescue_mode_for_server(server_id)).map_err(|e| e.to_string()); | ||||
|                     Response::DisableRescueMode(result) | ||||
|                 } | ||||
|                 Request::ListSshKeys(client) => { | ||||
|                     let result = rt.block_on(client.list_ssh_keys()).map_err(|e| e.to_string()); | ||||
|                     Response::ListSshKeys(result) | ||||
|                 } | ||||
|             }; | ||||
|             reply_tx.send(response).expect("Failed to send response"); | ||||
|         } | ||||
|   | ||||
| @@ -1,5 +1,12 @@ | ||||
| use hcloud::apis::{configuration::Configuration, servers_api::{self, ListServersParams, ResetServerParams, EnableRescueModeForServerParams, DisableRescueModeForServerParams}}; | ||||
| use hcloud::models::{Server, EnableRescueModeForServerRequest}; | ||||
| use hcloud::apis::{ | ||||
|     configuration::Configuration, | ||||
|     servers_api::{ | ||||
|         self, DisableRescueModeForServerParams, EnableRescueModeForServerParams, ListServersParams, | ||||
|         ResetServerParams, | ||||
|     }, | ||||
|     ssh_keys_api::{self, ListSshKeysParams}, | ||||
| }; | ||||
| use hcloud::models::{EnableRescueModeForServerRequest, Server, SshKey}; | ||||
|  | ||||
| #[derive(Debug, Clone)] | ||||
| pub struct HetznerClient { | ||||
| @@ -9,6 +16,9 @@ pub struct HetznerClient { | ||||
| #[derive(Clone)] | ||||
| pub struct WrappedServer(pub Server); | ||||
|  | ||||
| #[derive(Clone)] | ||||
| pub struct WrappedSshKey(pub SshKey); | ||||
|  | ||||
| impl HetznerClient { | ||||
|     pub fn new(api_token: &str) -> Self { | ||||
|         let mut configuration = Configuration::new(); | ||||
| @@ -19,7 +29,6 @@ impl HetznerClient { | ||||
|             .unwrap(); | ||||
|         configuration.client = client; | ||||
|  | ||||
|  | ||||
|         Self { configuration } | ||||
|     } | ||||
|  | ||||
| @@ -36,11 +45,12 @@ impl HetznerClient { | ||||
|             }; | ||||
|  | ||||
|             let response = servers_api::list_servers(&self.configuration, params).await?; | ||||
|             let mut servers: Vec<WrappedServer> = response.servers.into_iter().map(WrappedServer).collect(); | ||||
|             let mut servers: Vec<WrappedServer> = | ||||
|                 response.servers.into_iter().map(WrappedServer).collect(); | ||||
|             let is_empty = servers.is_empty(); | ||||
|  | ||||
|             all_servers.append(&mut servers); | ||||
|              | ||||
|  | ||||
|             if is_empty || response.meta.pagination.next_page.is_none() { | ||||
|                 break; | ||||
|             } | ||||
| @@ -51,12 +61,12 @@ impl HetznerClient { | ||||
|         Ok(all_servers) | ||||
|     } | ||||
|  | ||||
|     pub async fn get_server_status(&self, server_id: i64) -> Result<String, Box<dyn std::error::Error>> { | ||||
|         let params = servers_api::GetServerParams { | ||||
|             id: server_id, | ||||
|         }; | ||||
|         let server_response = servers_api::get_server(&self.configuration, params) | ||||
|             .await?; | ||||
|     pub async fn get_server_status( | ||||
|         &self, | ||||
|         server_id: i64, | ||||
|     ) -> Result<String, Box<dyn std::error::Error>> { | ||||
|         let params = servers_api::GetServerParams { id: server_id }; | ||||
|         let server_response = servers_api::get_server(&self.configuration, params).await?; | ||||
|  | ||||
|         if let Some(server) = server_response.server { | ||||
|             Ok(format!("{:?}", server.status)) | ||||
| @@ -65,12 +75,12 @@ impl HetznerClient { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub async fn get_server(&self, server_id: i64) -> Result<WrappedServer, Box<dyn std::error::Error>> { | ||||
|         let params = servers_api::GetServerParams { | ||||
|             id: server_id, | ||||
|         }; | ||||
|         let server_response = servers_api::get_server(&self.configuration, params) | ||||
|             .await?; | ||||
|     pub async fn get_server( | ||||
|         &self, | ||||
|         server_id: i64, | ||||
|     ) -> Result<WrappedServer, Box<dyn std::error::Error>> { | ||||
|         let params = servers_api::GetServerParams { id: server_id }; | ||||
|         let server_response = servers_api::get_server(&self.configuration, params).await?; | ||||
|  | ||||
|         if let Some(server) = server_response.server { | ||||
|             Ok(WrappedServer(*server)) | ||||
| @@ -80,37 +90,73 @@ impl HetznerClient { | ||||
|     } | ||||
|  | ||||
|     pub async fn reboot_server(&self, server_id: i64) -> Result<(), Box<dyn std::error::Error>> { | ||||
|         let params = servers_api::SoftRebootServerParams { | ||||
|             id: server_id, | ||||
|         }; | ||||
|         let params = servers_api::SoftRebootServerParams { id: server_id }; | ||||
|         servers_api::soft_reboot_server(&self.configuration, params).await?; | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     pub async fn reset_server(&self, server_id: i64) -> Result<(), Box<dyn std::error::Error>> { | ||||
|         let params = ResetServerParams { | ||||
|             id: server_id, | ||||
|         }; | ||||
|         let params = ResetServerParams { id: server_id }; | ||||
|         servers_api::reset_server(&self.configuration, params).await?; | ||||
|         Ok(()) | ||||
|     } | ||||
|     pub async fn enable_rescue_mode_for_server(&self, server_id: i64, ssh_keys: Vec<i64>) -> Result<String, Box<dyn std::error::Error>> { | ||||
|     pub async fn enable_rescue_mode_for_server( | ||||
|         &self, | ||||
|         server_id: i64, | ||||
|         ssh_keys: Vec<i64>, | ||||
|     ) -> Result<String, Box<dyn std::error::Error>> { | ||||
|         let params = EnableRescueModeForServerParams { | ||||
|             id: server_id, | ||||
|             enable_rescue_mode_for_server_request: Some(EnableRescueModeForServerRequest { | ||||
|                 ssh_keys: if ssh_keys.is_empty() { None } else { Some(ssh_keys) }, | ||||
|                 ssh_keys: if ssh_keys.is_empty() { | ||||
|                     None | ||||
|                 } else { | ||||
|                     Some(ssh_keys) | ||||
|                 }, | ||||
|                 r#type: Some(hcloud::models::enable_rescue_mode_for_server_request::Type::Linux64), | ||||
|             }), | ||||
|         }; | ||||
|         let response = servers_api::enable_rescue_mode_for_server(&self.configuration, params).await?; | ||||
|         Ok(response.root_password.expect("Unable to fetch root_password from enabling rescue mode for server response")) | ||||
|         let response = | ||||
|             servers_api::enable_rescue_mode_for_server(&self.configuration, params).await?; | ||||
|         Ok(response | ||||
|             .root_password | ||||
|             .expect("Unable to fetch root_password from enabling rescue mode for server response")) | ||||
|     } | ||||
|  | ||||
|     pub async fn disable_rescue_mode_for_server(&self, server_id: i64) -> Result<(), Box<dyn std::error::Error>> { | ||||
|         let params = DisableRescueModeForServerParams { | ||||
|             id: server_id, | ||||
|         }; | ||||
|     pub async fn disable_rescue_mode_for_server( | ||||
|         &self, | ||||
|         server_id: i64, | ||||
|     ) -> Result<(), Box<dyn std::error::Error>> { | ||||
|         let params = DisableRescueModeForServerParams { id: server_id }; | ||||
|         servers_api::disable_rescue_mode_for_server(&self.configuration, params).await?; | ||||
|         Ok(()) | ||||
|     } | ||||
|     pub async fn list_ssh_keys(&self) -> Result<Vec<WrappedSshKey>, Box<dyn std::error::Error>> { | ||||
|         let mut all_keys = Vec::new(); | ||||
|         let mut page = 1; | ||||
|         let per_page = 50; | ||||
|  | ||||
|         loop { | ||||
|             let params = ListSshKeysParams { | ||||
|                 page: Some(page), | ||||
|                 per_page: Some(per_page), | ||||
|                 ..Default::default() | ||||
|             }; | ||||
|  | ||||
|             let response = ssh_keys_api::list_ssh_keys(&self.configuration, params).await?; | ||||
|             let mut keys: Vec<WrappedSshKey> = | ||||
|                 response.ssh_keys.into_iter().map(WrappedSshKey).collect(); | ||||
|             let is_empty = keys.is_empty(); | ||||
|  | ||||
|             all_keys.append(&mut keys); | ||||
|  | ||||
|             if is_empty || response.meta.pagination.next_page.is_none() { | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             page += 1; | ||||
|         } | ||||
|  | ||||
|         Ok(all_keys) | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| use crate::async_handler::Response; | ||||
| use crate::async_handler::Request; | ||||
| use crate::hetzner_api::{HetznerClient, WrappedServer}; | ||||
| use crate::hetzner_api::{HetznerClient, WrappedServer, WrappedSshKey}; | ||||
| use rhai::{Engine, EvalAltResult}; | ||||
| use std::env; | ||||
| use std::sync::{mpsc::{Receiver, Sender}, Arc, Mutex}; | ||||
| @@ -52,6 +52,15 @@ pub fn register_hetzner_api( | ||||
|                 }) | ||||
|             } | ||||
|         }) | ||||
|         .register_fn("list_ssh_keys", { | ||||
|             let bridge = api_bridge.clone(); | ||||
|             move |client: &mut HetznerClient| { | ||||
|                 bridge.call(Request::ListSshKeys(client.clone()), |response| match response { | ||||
|                     Response::ListSshKeys(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| { | ||||
| @@ -197,4 +206,32 @@ pub fn register_hetzner_api( | ||||
|     engine.register_fn("get_env", |key: &str| -> String { | ||||
|         env::var(key).unwrap_or("".to_string()) | ||||
|     }); | ||||
|  | ||||
|     engine | ||||
|         .register_type_with_name::<WrappedSshKey>("SshKey") | ||||
|         .register_get("id", |key: &mut WrappedSshKey| key.0.id) | ||||
|         .register_get("name", |key: &mut WrappedSshKey| key.0.name.clone()) | ||||
|         .register_get("fingerprint", |key: &mut WrappedSshKey| key.0.fingerprint.clone()); | ||||
|  | ||||
|     engine | ||||
|         .register_iterator::<Vec<WrappedSshKey>>() | ||||
|         .register_fn("len", |list: &mut Vec<WrappedSshKey>| list.len() as i64) | ||||
|         .register_indexer_get(|list: &mut Vec<WrappedSshKey>, index: i64| list[index as usize].clone()) | ||||
|         .register_fn("show_table", |keys: &mut Vec<WrappedSshKey>| -> Result<String, Box<EvalAltResult>> { | ||||
|             let mut table = Table::new(); | ||||
|             table.set_titles(Row::new(vec![Cell::new("SSH Keys").style_spec("c")])); | ||||
|             table.add_row(Row::new(vec![ | ||||
|                 Cell::new("ID"), | ||||
|                 Cell::new("Name"), | ||||
|                 Cell::new("Fingerprint"), | ||||
|             ])); | ||||
|             for key in keys { | ||||
|                 table.add_row(Row::new(vec![ | ||||
|                     Cell::new(&key.0.id.to_string()), | ||||
|                     Cell::new(&key.0.name), | ||||
|                     Cell::new(&key.0.fingerprint), | ||||
|                 ])); | ||||
|             } | ||||
|             Ok(table.to_string()) | ||||
|         }); | ||||
| } | ||||
							
								
								
									
										22
									
								
								test.rhai
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								test.rhai
									
									
									
									
									
								
							| @@ -5,6 +5,10 @@ let client = new_hetzner_client(HETZNER_API_TOKEN); | ||||
| print("Listing all servers..."); | ||||
| let servers = client.list_servers(); | ||||
| print(servers.show_table()); | ||||
| // List all SSH keys and print in table | ||||
| print("Listing all SSH keys..."); | ||||
| let ssh_keys = client.list_ssh_keys(); | ||||
| print(ssh_keys.show_table()); | ||||
|  | ||||
| // Get server through ID and print details in table | ||||
| print("Listing details from server with ID 104301883..."); | ||||
| @@ -12,19 +16,19 @@ 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, 1337); | ||||
| print(`Root password is: ${root_password}`); | ||||
| // print(`Enabling rescue mode on server with ID: ${test_server.id}`); | ||||
| // let root_password = client.enable_rescue_mode(test_server.id, 1337); | ||||
| // print(`Root password is: ${root_password}`); | ||||
|  | ||||
| // Enable rescue mode with multiple keys from array | ||||
| let ssh_keys = [123, 456, 789]; | ||||
| let ssh_keys = [100324992, 100325001]; | ||||
| let root_password = client.enable_rescue_mode(test_server.id, ssh_keys); | ||||
|  | ||||
| // read SSH key from env var | ||||
| let ssh_key_from_env = get_env("SSH_KEY_ID"); | ||||
| if ssh_key_from_env != "" { | ||||
|     client.enable_rescue_mode(test_server.id, ssh_key_from_env.parse_int()); | ||||
| } | ||||
| // // read SSH key from env var and use it for rescue mode | ||||
| // let ssh_key_from_env = get_env("SSH_KEY_ID"); | ||||
| // if ssh_key_from_env != "" { | ||||
| //     client.enable_rescue_mode(test_server.id, ssh_key_from_env.parse_int()); | ||||
| // } | ||||
|  | ||||
| // Disable rescue mode flag on server | ||||
| print(`Disabling rescue mode on server with ID: ${test_server.id}`); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user