pub mod error; pub mod models; use self::models::{ Boot, Rescue, Server, SshKey, ServerAddonProduct, ServerAddonProductWrapper, AuctionServerProduct, AuctionServerProductWrapper, AuctionTransaction, AuctionTransactionWrapper, BootWrapper, Cancellation, CancellationWrapper, OrderServerBuilder, OrderServerProduct, OrderServerProductWrapper, RescueWrapped, ServerWrapper, SshKeyWrapper, Transaction, TransactionWrapper, ServerAddonTransaction, ServerAddonTransactionWrapper, OrderServerAddonBuilder, }; use crate::api::error::ApiError; use crate::config::Config; use error::AppError; use reqwest::blocking::Client as HttpClient; use serde_json::json; #[derive(Clone)] pub struct Client { http_client: HttpClient, config: Config, } impl Client { pub fn new(config: Config) -> Self { Self { http_client: HttpClient::new(), config, } } fn handle_response(&self, response: reqwest::blocking::Response) -> Result where T: serde::de::DeserializeOwned, { let status = response.status(); let body = response.text()?; if status.is_success() { serde_json::from_str::(&body).map_err(Into::into) } else { Err(AppError::ApiError(ApiError { status: status.as_u16(), message: body, })) } } pub fn get_server(&self, server_number: i32) -> Result { let response = self .http_client .get(format!("{}/server/{}", self.config.api_url, server_number)) .basic_auth(&self.config.username, Some(&self.config.password)) .send()?; let wrapped: ServerWrapper = self.handle_response(response)?; Ok(wrapped.server) } pub fn get_servers(&self) -> Result, AppError> { let response = self .http_client .get(format!("{}/server", self.config.api_url)) .basic_auth(&self.config.username, Some(&self.config.password)) .send()?; let wrapped: Vec = 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 { 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 { 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 { 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, AppError> { let response = self .http_client .get(format!("{}/key", self.config.api_url)) .basic_auth(&self.config.username, Some(&self.config.password)) .send()?; let wrapped: Vec = 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 { let response = self .http_client .get(format!("{}/key/{}", self.config.api_url, fingerprint)) .basic_auth(&self.config.username, Some(&self.config.password)) .send()?; let wrapped: SshKeyWrapper = self.handle_response(response)?; Ok(wrapped.key) } pub fn add_ssh_key(&self, name: &str, data: &str) -> Result { let params = [("name", name), ("data", data)]; let response = self .http_client .post(format!("{}/key", self.config.api_url)) .basic_auth(&self.config.username, Some(&self.config.password)) .form(¶ms) .send()?; let wrapped: SshKeyWrapper = self.handle_response(response)?; Ok(wrapped.key) } pub fn update_ssh_key_name(&self, fingerprint: &str, name: &str) -> Result { let params = [("name", name)]; let response = self .http_client .post(format!("{}/key/{}", self.config.api_url, fingerprint)) .basic_auth(&self.config.username, Some(&self.config.password)) .form(¶ms) .send()?; let wrapped: SshKeyWrapper = self.handle_response(response)?; Ok(wrapped.key) } pub fn delete_ssh_key(&self, fingerprint: &str) -> Result<(), AppError> { self.http_client .delete(format!("{}/key/{}", self.config.api_url, fingerprint)) .basic_auth(&self.config.username, Some(&self.config.password)) .send()?; Ok(()) } pub fn get_boot_configuration(&self, server_number: i32) -> Result { let response = self .http_client .get(format!("{}/boot/{}", self.config.api_url, server_number)) .basic_auth(&self.config.username, Some(&self.config.password)) .send()?; let wrapped: BootWrapper = self.handle_response(response)?; Ok(wrapped.boot) } pub fn get_rescue_boot_configuration(&self, server_number: i32) -> Result { let response = self .http_client .get(format!( "{}/boot/{}/rescue", self.config.api_url, server_number )) .basic_auth(&self.config.username, Some(&self.config.password)) .send()?; let wrapped: RescueWrapped = self.handle_response(response)?; Ok(wrapped.rescue) } pub fn enable_rescue_mode( &self, server_number: i32, os: &str, authorized_keys: Option<&[String]>, ) -> Result { let mut params = vec![("os", os)]; if let Some(keys) = authorized_keys { for key in keys { params.push(("authorized_key[]", key)); } } let response = self .http_client .post(format!( "{}/boot/{}/rescue", self.config.api_url, server_number )) .basic_auth(&self.config.username, Some(&self.config.password)) .form(¶ms) .send()?; let wrapped: RescueWrapped = self.handle_response(response)?; Ok(wrapped.rescue) } pub fn disable_rescue_mode(&self, server_number: i32) -> Result { let response = self .http_client .delete(format!( "{}/boot/{}/rescue", self.config.api_url, server_number )) .basic_auth(&self.config.username, Some(&self.config.password)) .send()?; let wrapped: RescueWrapped = self.handle_response(response)?; Ok(wrapped.rescue) } pub fn get_server_products( &self, ) -> Result, AppError> { let response = self .http_client .get(format!("{}/order/server/product", &self.config.api_url)) .basic_auth(&self.config.username, Some(&self.config.password)) .send()?; let wrapped: Vec = self.handle_response(response)?; let products = wrapped.into_iter().map(|sop| sop.product).collect(); Ok(products) } pub fn get_server_product_by_id( &self, product_id: &str, ) -> Result { let response = self .http_client .get(format!( "{}/order/server/product/{}", &self.config.api_url, product_id )) .basic_auth(&self.config.username, Some(&self.config.password)) .send()?; let wrapped: OrderServerProductWrapper = self.handle_response(response)?; Ok(wrapped.product) } pub fn order_server(&self, order: OrderServerBuilder) -> Result { let mut params = json!({ "product_id": order.product_id, "dist": order.dist, "location": order.location, "authorized_key": order.authorized_keys.unwrap_or_default(), }); if let Some(addons) = order.addons { params["addon"] = json!(addons); } if let Some(test) = order.test { if test { params["test"] = json!(test); } } let response = self .http_client .post(format!("{}/order/server/transaction", &self.config.api_url)) .basic_auth(&self.config.username, Some(&self.config.password)) .json(¶ms) .send()?; let wrapped: TransactionWrapper = self.handle_response(response)?; Ok(wrapped.transaction) } pub fn get_transaction_by_id(&self, transaction_id: &str) -> Result { let response = self .http_client .get(format!( "{}/order/server/transaction/{}", &self.config.api_url, transaction_id )) .basic_auth(&self.config.username, Some(&self.config.password)) .send()?; let wrapped: TransactionWrapper = self.handle_response(response)?; Ok(wrapped.transaction) } pub fn get_transactions(&self) -> Result, AppError> { let response = self .http_client .get(format!("{}/order/server/transaction", &self.config.api_url)) .basic_auth(&self.config.username, Some(&self.config.password)) .send()?; let wrapped: Vec = self.handle_response(response)?; let transactions = wrapped.into_iter().map(|t| t.transaction).collect(); Ok(transactions) } pub fn get_auction_server_products(&self) -> Result, AppError> { let response = self .http_client .get(format!( "{}/order/server_market/product", &self.config.api_url )) .basic_auth(&self.config.username, Some(&self.config.password)) .send()?; let wrapped: Vec = self.handle_response(response)?; let products = wrapped.into_iter().map(|asp| asp.product).collect(); Ok(products) } pub fn get_auction_server_product_by_id(&self, product_id: &str) -> Result { let response = self .http_client .get(format!("{}/order/server_market/product/{}", &self.config.api_url, product_id)) .basic_auth(&self.config.username, Some(&self.config.password)) .send()?; let wrapped: AuctionServerProductWrapper = self.handle_response(response)?; Ok(wrapped.product) } pub fn get_auction_transactions(&self) -> Result, AppError> { let response = self .http_client .get(format!("{}/order/server_market/transaction", &self.config.api_url)) .basic_auth(&self.config.username, Some(&self.config.password)) .send()?; let wrapped: Vec = self.handle_response(response)?; let transactions = wrapped.into_iter().map(|t| t.transaction).collect(); Ok(transactions) } pub fn get_auction_transaction_by_id(&self, transaction_id: &str) -> Result { let response = self .http_client .get(format!("{}/order/server_market/transaction/{}", &self.config.api_url, transaction_id)) .basic_auth(&self.config.username, Some(&self.config.password)) .send()?; let wrapped: AuctionTransactionWrapper = self.handle_response(response)?; Ok(wrapped.transaction) } pub fn get_server_addon_products( &self, server_number: i64, ) -> Result, AppError> { let response = self .http_client .get(format!( "{}/order/server_addon/{}/product", &self.config.api_url, server_number )) .basic_auth(&self.config.username, Some(&self.config.password)) .send()?; let wrapped: Vec = self.handle_response(response)?; let products = wrapped.into_iter().map(|sap| sap.product).collect(); Ok(products) } pub fn order_auction_server( &self, product_id: i64, authorized_keys: Vec, dist: Option, arch: Option, lang: Option, comment: Option, addons: Option>, test: Option, ) -> Result { let mut params: Vec<(&str, String)> = Vec::new(); params.push(("product_id", product_id.to_string())); for key in &authorized_keys { params.push(("authorized_key[]", key.clone())); } if let Some(dist) = dist { params.push(("dist", dist)); } if let Some(arch) = arch { params.push(("@deprecated arch", arch)); } if let Some(lang) = lang { params.push(("lang", lang)); } if let Some(comment) = comment { params.push(("comment", comment)); } if let Some(addons) = addons { for addon in addons { params.push(("addon[]", addon)); } } if let Some(test) = test { params.push(("test", test.to_string())); } let response = self .http_client .post(format!("{}/order/server_market/transaction", &self.config.api_url)) .basic_auth(&self.config.username, Some(&self.config.password)) .form(¶ms) .send()?; let wrapped: AuctionTransactionWrapper = self.handle_response(response)?; Ok(wrapped.transaction) } pub fn get_server_addon_transactions(&self) -> Result, AppError> { let response = self .http_client .get(format!("{}/order/server_addon/transaction", &self.config.api_url)) .basic_auth(&self.config.username, Some(&self.config.password)) .send()?; let wrapped: Vec = self.handle_response(response)?; let transactions = wrapped.into_iter().map(|satw| satw.transaction).collect(); Ok(transactions) } pub fn get_server_addon_transaction_by_id( &self, transaction_id: &str, ) -> Result { let response = self .http_client .get(format!( "{}/order/server_addon/transaction/{}", &self.config.api_url, transaction_id )) .basic_auth(&self.config.username, Some(&self.config.password)) .send()?; let wrapped: ServerAddonTransactionWrapper = self.handle_response(response)?; Ok(wrapped.transaction) } pub fn order_server_addon( &self, order: OrderServerAddonBuilder, ) -> Result { let mut params = json!({ "server_number": order.server_number, "product_id": order.product_id, }); if let Some(reason) = order.reason { params["reason"] = json!(reason); } if let Some(gateway) = order.gateway { params["gateway"] = json!(gateway); } if let Some(test) = order.test { if test { params["test"] = json!(test); } } let response = self .http_client .post(format!("{}/order/server_addon/transaction", &self.config.api_url)) .basic_auth(&self.config.username, Some(&self.config.password)) .form(¶ms) .send()?; let wrapped: ServerAddonTransactionWrapper = self.handle_response(response)?; Ok(wrapped.transaction) } }