added ability to also order regular servers (previously only auctioned ones)
This commit is contained in:
		@@ -1,11 +1,23 @@
 | 
			
		||||
/// --- Get all available products (servers) that we can order and print them in a table
 | 
			
		||||
// let available_server_products = hetzner.get_server_ordering_product_overview();
 | 
			
		||||
// let available_server_products = hetzner.get_server_products();
 | 
			
		||||
// available_server_products.pretty_print();
 | 
			
		||||
 | 
			
		||||
/// --- List the details from a specific sever product based on the ID
 | 
			
		||||
// let example_server_product = hetzner.get_server_ordering_product_by_id("AX41-NVMe");
 | 
			
		||||
// let example_server_product = hetzner.get_server_product_by_id("AX41-NVMe");
 | 
			
		||||
// print(example_server_product);
 | 
			
		||||
 | 
			
		||||
/// --- Order a server
 | 
			
		||||
// 1. Grab the SSH key to pass to the deployment
 | 
			
		||||
let ssh_key = hetzner.get_ssh_key("e0:73:80:26:80:46:f0:c8:bb:74:f4:d0:2d:10:2d:6f");
 | 
			
		||||
// 2. Use the builder to bundle the details on what to order
 | 
			
		||||
let order_builder = new_server_builder("AX41-NVMe")
 | 
			
		||||
    .with_authorized_keys([ssh_key.fingerprint])
 | 
			
		||||
    .with_test(true);
 | 
			
		||||
 | 
			
		||||
let ordered_server_transaction = hetzner.order_server(order_builder);
 | 
			
		||||
print(ordered_server_transaction);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// --- List all the transactions from the past 30 days
 | 
			
		||||
// let transactions_last_30 = hetzner.get_transactions();
 | 
			
		||||
// print(transactions_last_30);
 | 
			
		||||
@@ -32,7 +44,7 @@
 | 
			
		||||
 | 
			
		||||
/// --- Order an auction server
 | 
			
		||||
// 1. Grab the SSH key to pass to the deployment
 | 
			
		||||
let ssh_key = hetzner.get_ssh_key("e0:73:80:26:80:46:f0:c8:bb:74:f4:d0:2d:10:2d:6f");
 | 
			
		||||
// let ssh_key = hetzner.get_ssh_key("e0:73:80:26:80:46:f0:c8:bb:74:f4:d0:2d:10:2d:6f");
 | 
			
		||||
// 2. Use the builder to bundle the details on what to order
 | 
			
		||||
// let order_builder = new_auction_server_builder(2741558)
 | 
			
		||||
//     .with_authorized_keys([ssh_key.fingerprint])
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,10 @@ pub mod models;
 | 
			
		||||
use self::models::{Boot, Rescue, Server, SshKey};
 | 
			
		||||
use crate::api::error::ApiError;
 | 
			
		||||
use crate::api::models::{
 | 
			
		||||
    AuctionServerProduct, AuctionServerProductWrapper, AuctionTransaction, AuctionTransactionWrapper, BootWrapper, Cancellation, CancellationWrapper, OrderServerProduct, OrderServerProductWrapper, RescueWrapped, ServerWrapper, SshKeyWrapper, Transaction, TransactionWrapper
 | 
			
		||||
    AuctionServerProduct, AuctionServerProductWrapper, AuctionTransaction,
 | 
			
		||||
    AuctionTransactionWrapper, BootWrapper, Cancellation, CancellationWrapper,
 | 
			
		||||
    OrderServerBuilder, OrderServerProduct, OrderServerProductWrapper, RescueWrapped,
 | 
			
		||||
    ServerWrapper, SshKeyWrapper, Transaction, TransactionWrapper,
 | 
			
		||||
};
 | 
			
		||||
use crate::config::Config;
 | 
			
		||||
use error::AppError;
 | 
			
		||||
@@ -276,25 +279,24 @@ impl Client {
 | 
			
		||||
        let wrapped: OrderServerProductWrapper = self.handle_response(response)?;
 | 
			
		||||
        Ok(wrapped.product)
 | 
			
		||||
    }
 | 
			
		||||
    pub fn order_server(
 | 
			
		||||
        &self,
 | 
			
		||||
        product_id: &str,
 | 
			
		||||
        dist: &str,
 | 
			
		||||
        location: &str,
 | 
			
		||||
        authorized_keys: Vec<String>,
 | 
			
		||||
        addons: Option<Vec<String>>,
 | 
			
		||||
    ) -> Result<Transaction, AppError> {
 | 
			
		||||
    pub fn order_server(&self, order: OrderServerBuilder) -> Result<Transaction, AppError> {
 | 
			
		||||
        let mut params = json!({
 | 
			
		||||
            "product_id": product_id,
 | 
			
		||||
            "dist": dist,
 | 
			
		||||
            "location": location,
 | 
			
		||||
            "authorized_key": authorized_keys,
 | 
			
		||||
            "product_id": order.product_id,
 | 
			
		||||
            "dist": order.dist,
 | 
			
		||||
            "location": order.location,
 | 
			
		||||
            "authorized_key": order.authorized_keys.unwrap_or_default(),
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        if let Some(addons) = addons {
 | 
			
		||||
        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))
 | 
			
		||||
 
 | 
			
		||||
@@ -51,6 +51,19 @@ 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("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())
 | 
			
		||||
            .with_get("vnc", |s: &mut Server| s.vnc.clone())
 | 
			
		||||
            .with_get("windows", |s: &mut Server| s.windows.clone())
 | 
			
		||||
            .with_get("plesk", |s: &mut Server| s.plesk.clone())
 | 
			
		||||
            .with_get("cpanel", |s: &mut Server| s.cpanel.clone())
 | 
			
		||||
            .with_get("wol", |s: &mut Server| s.wol.clone())
 | 
			
		||||
            .with_get("hot_swap", |s: &mut Server| s.hot_swap.clone())
 | 
			
		||||
            .with_get("linked_storagebox", |s: &mut Server| {
 | 
			
		||||
                s.linked_storagebox.clone()
 | 
			
		||||
            })
 | 
			
		||||
            // when doing `print(server) in Rhai script, this will execute`
 | 
			
		||||
            .on_print(|s: &mut Server| s.to_string())
 | 
			
		||||
            // also add the pretty_print function for convience
 | 
			
		||||
@@ -90,11 +103,6 @@ impl fmt::Display for Server {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Deserialize)]
 | 
			
		||||
struct SubnetWrapper {
 | 
			
		||||
    _subnet: Subnet,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Deserialize, Clone, CustomType)]
 | 
			
		||||
#[rhai_type(extra = Self::build_rhai_type)]
 | 
			
		||||
pub struct Subnet {
 | 
			
		||||
@@ -575,49 +583,6 @@ impl fmt::Display for Cancellation {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn string_or_seq_string<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
 | 
			
		||||
where
 | 
			
		||||
    D: Deserializer<'de>,
 | 
			
		||||
{
 | 
			
		||||
    let value = Value::deserialize(deserializer)?;
 | 
			
		||||
    match value {
 | 
			
		||||
        Value::String(s) => Ok(vec![s]),
 | 
			
		||||
        Value::Array(a) => a
 | 
			
		||||
            .into_iter()
 | 
			
		||||
            .map(|v| {
 | 
			
		||||
                v.as_str()
 | 
			
		||||
                    .map(ToString::to_string)
 | 
			
		||||
                    .ok_or(serde::de::Error::custom("expected string"))
 | 
			
		||||
            })
 | 
			
		||||
            .collect(),
 | 
			
		||||
        _ => Err(serde::de::Error::custom(
 | 
			
		||||
            "expected string or array of strings",
 | 
			
		||||
        )),
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn option_string_or_seq_string<'de, D>(deserializer: D) -> Result<Option<Vec<String>>, D::Error>
 | 
			
		||||
where
 | 
			
		||||
    D: Deserializer<'de>,
 | 
			
		||||
{
 | 
			
		||||
    let value = Value::deserialize(deserializer)?;
 | 
			
		||||
    match value {
 | 
			
		||||
        Value::Null => Ok(None),
 | 
			
		||||
        Value::String(s) => Ok(Some(vec![s])),
 | 
			
		||||
        Value::Array(a) => Ok(Some(
 | 
			
		||||
            a.into_iter()
 | 
			
		||||
                .map(|v| {
 | 
			
		||||
                    v.as_str()
 | 
			
		||||
                        .map(ToString::to_string)
 | 
			
		||||
                        .ok_or(serde::de::Error::custom("expected string"))
 | 
			
		||||
                })
 | 
			
		||||
                .collect::<Result<Vec<String>, _>>()?,
 | 
			
		||||
        )),
 | 
			
		||||
        _ => Err(serde::de::Error::custom(
 | 
			
		||||
            "expected string or array of strings",
 | 
			
		||||
        )),
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Deserialize)]
 | 
			
		||||
pub struct ApiError {
 | 
			
		||||
@@ -1255,27 +1220,69 @@ impl fmt::Display for AuctionTransaction {
 | 
			
		||||
        table.add_row(row!["ID", self.id.clone()]);
 | 
			
		||||
        table.add_row(row!["Date", self.date.clone()]);
 | 
			
		||||
        table.add_row(row!["Status", self.status.clone()]);
 | 
			
		||||
        table.add_row(row!["Server Number", self.server_number.map_or("N/A".to_string(), |id| id.to_string())]);
 | 
			
		||||
        table.add_row(row!["Server IP", self.server_ip.as_deref().unwrap_or("N/A").to_string()]);
 | 
			
		||||
        table.add_row(row!["Comment", self.comment.as_deref().unwrap_or("N/A").to_string()]);
 | 
			
		||||
        table.add_row(row![
 | 
			
		||||
            "Server Number",
 | 
			
		||||
            self.server_number
 | 
			
		||||
                .map_or("N/A".to_string(), |id| id.to_string())
 | 
			
		||||
        ]);
 | 
			
		||||
        table.add_row(row![
 | 
			
		||||
            "Server IP",
 | 
			
		||||
            self.server_ip.as_deref().unwrap_or("N/A").to_string()
 | 
			
		||||
        ]);
 | 
			
		||||
        table.add_row(row![
 | 
			
		||||
            "Comment",
 | 
			
		||||
            self.comment.as_deref().unwrap_or("N/A").to_string()
 | 
			
		||||
        ]);
 | 
			
		||||
        table.add_row(row!["Product ID", self.product.id.to_string()]);
 | 
			
		||||
        table.add_row(row!["Product Name", self.product.name.clone()]);
 | 
			
		||||
        table.add_row(row!["Product Description", self.product.description.join(", ")]);
 | 
			
		||||
        table.add_row(row![
 | 
			
		||||
            "Product Description",
 | 
			
		||||
            self.product.description.join(", ")
 | 
			
		||||
        ]);
 | 
			
		||||
        table.add_row(row!["Product Traffic", self.product.traffic.clone()]);
 | 
			
		||||
        table.add_row(row!["Product Distributions", self.product.dist.clone()]);
 | 
			
		||||
        table.add_row(row!["Product Architectures", self.product.arch.as_deref().unwrap_or("N/A")]);
 | 
			
		||||
        table.add_row(row![
 | 
			
		||||
            "Product Architectures",
 | 
			
		||||
            self.product.arch.as_deref().unwrap_or("N/A")
 | 
			
		||||
        ]);
 | 
			
		||||
        table.add_row(row!["Product Languages", self.product.lang.clone()]);
 | 
			
		||||
        table.add_row(row!["Product CPU", self.product.cpu.clone()]);
 | 
			
		||||
        table.add_row(row!["Product CPU Benchmark", self.product.cpu_benchmark.to_string()]);
 | 
			
		||||
        table.add_row(row!["Product Memory Size (GB)", self.product.memory_size.to_string()]);
 | 
			
		||||
        table.add_row(row!["Product HDD Size (GB)", self.product.hdd_size.to_string()]);
 | 
			
		||||
        table.add_row(row![
 | 
			
		||||
            "Product CPU Benchmark",
 | 
			
		||||
            self.product.cpu_benchmark.to_string()
 | 
			
		||||
        ]);
 | 
			
		||||
        table.add_row(row![
 | 
			
		||||
            "Product Memory Size (GB)",
 | 
			
		||||
            self.product.memory_size.to_string()
 | 
			
		||||
        ]);
 | 
			
		||||
        table.add_row(row![
 | 
			
		||||
            "Product HDD Size (GB)",
 | 
			
		||||
            self.product.hdd_size.to_string()
 | 
			
		||||
        ]);
 | 
			
		||||
        table.add_row(row!["Product HDD Text", self.product.hdd_text.clone()]);
 | 
			
		||||
        table.add_row(row!["Product HDD Count", self.product.hdd_count.to_string()]);
 | 
			
		||||
        table.add_row(row![
 | 
			
		||||
            "Product HDD Count",
 | 
			
		||||
            self.product.hdd_count.to_string()
 | 
			
		||||
        ]);
 | 
			
		||||
        table.add_row(row!["Product Datacenter", self.product.datacenter.clone()]);
 | 
			
		||||
        table.add_row(row!["Product Network Speed", self.product.network_speed.clone()]);
 | 
			
		||||
        table.add_row(row!["Product Fixed Price", self.product.fixed_price.unwrap_or_default().to_string()]);
 | 
			
		||||
        table.add_row(row!["Product Next Reduce (seconds)", self.product.next_reduce.map_or("N/A".to_string(), |r| r.to_string())]);
 | 
			
		||||
        table.add_row(row!["Product Next Reduce Date", self.product.next_reduce_date.as_deref().unwrap_or("N/A")]);
 | 
			
		||||
        table.add_row(row![
 | 
			
		||||
            "Product Network Speed",
 | 
			
		||||
            self.product.network_speed.clone()
 | 
			
		||||
        ]);
 | 
			
		||||
        table.add_row(row![
 | 
			
		||||
            "Product Fixed Price",
 | 
			
		||||
            self.product.fixed_price.unwrap_or_default().to_string()
 | 
			
		||||
        ]);
 | 
			
		||||
        table.add_row(row![
 | 
			
		||||
            "Product Next Reduce (seconds)",
 | 
			
		||||
            self.product
 | 
			
		||||
                .next_reduce
 | 
			
		||||
                .map_or("N/A".to_string(), |r| r.to_string())
 | 
			
		||||
        ]);
 | 
			
		||||
        table.add_row(row![
 | 
			
		||||
            "Product Next Reduce Date",
 | 
			
		||||
            self.product.next_reduce_date.as_deref().unwrap_or("N/A")
 | 
			
		||||
        ]);
 | 
			
		||||
        table.add_row(row!["Addons", self.addons.join(", ")]);
 | 
			
		||||
 | 
			
		||||
        let mut authorized_keys_table = Table::new();
 | 
			
		||||
@@ -1348,6 +1355,102 @@ impl AuctionTransactionProduct {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Deserialize, Clone, CustomType)]
 | 
			
		||||
#[rhai_type(extra = Self::build_rhai_type)]
 | 
			
		||||
pub struct OrderServerBuilder {
 | 
			
		||||
    pub product_id: String,
 | 
			
		||||
    pub authorized_keys: Option<Vec<String>>,
 | 
			
		||||
    pub dist: Option<String>,
 | 
			
		||||
    pub location: Option<String>,
 | 
			
		||||
    pub lang: Option<String>,
 | 
			
		||||
    pub comment: Option<String>,
 | 
			
		||||
    pub addons: Option<Vec<String>>,
 | 
			
		||||
    pub test: Option<bool>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl OrderServerBuilder {
 | 
			
		||||
    pub fn new(product_id: &str) -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            product_id: product_id.to_string(),
 | 
			
		||||
            authorized_keys: None,
 | 
			
		||||
            dist: None,
 | 
			
		||||
            location: None,
 | 
			
		||||
            lang: None,
 | 
			
		||||
            comment: None,
 | 
			
		||||
            addons: None,
 | 
			
		||||
            test: Some(true),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn with_authorized_keys(mut self, keys: Array) -> Self {
 | 
			
		||||
        let authorized_keys: Vec<String> = if keys.is_empty() {
 | 
			
		||||
            vec![]
 | 
			
		||||
        } else if keys[0].is::<SshKey>() {
 | 
			
		||||
            keys.into_iter()
 | 
			
		||||
                .map(|k| k.cast::<SshKey>().fingerprint)
 | 
			
		||||
                .collect()
 | 
			
		||||
        } else {
 | 
			
		||||
            keys.into_iter().map(|k| k.into_string().unwrap()).collect()
 | 
			
		||||
        };
 | 
			
		||||
        self.authorized_keys = Some(authorized_keys);
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn with_dist(mut self, dist: &str) -> Self {
 | 
			
		||||
        self.dist = Some(dist.to_string());
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn with_location(mut self, location: &str) -> Self {
 | 
			
		||||
        self.location = Some(location.to_string());
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn with_lang(mut self, lang: &str) -> Self {
 | 
			
		||||
        self.lang = Some(lang.to_string());
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn with_comment(mut self, comment: &str) -> Self {
 | 
			
		||||
        self.comment = Some(comment.to_string());
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn with_addons(mut self, addons: Array) -> Self {
 | 
			
		||||
        let addon_list: Vec<String> = addons
 | 
			
		||||
            .into_iter()
 | 
			
		||||
            .map(|a| a.into_string().unwrap())
 | 
			
		||||
            .collect();
 | 
			
		||||
        self.addons = Some(addon_list);
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn with_test(mut self, test: bool) -> Self {
 | 
			
		||||
        self.test = Some(test);
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn build_rhai_type(builder: &mut TypeBuilder<Self>) {
 | 
			
		||||
        builder
 | 
			
		||||
            .with_name("OrderServerBuilder")
 | 
			
		||||
            .with_fn("new_server_builder", Self::new)
 | 
			
		||||
            .with_fn("with_authorized_keys", Self::with_authorized_keys)
 | 
			
		||||
            .with_fn("with_dist", Self::with_dist)
 | 
			
		||||
            .with_fn("with_location", Self::with_location)
 | 
			
		||||
            .with_fn("with_lang", Self::with_lang)
 | 
			
		||||
            .with_fn("with_comment", Self::with_comment)
 | 
			
		||||
            .with_fn("with_addons", Self::with_addons)
 | 
			
		||||
            .with_fn("with_test", Self::with_test)
 | 
			
		||||
            .with_get("product_id", |b: &mut OrderServerBuilder| b.product_id.clone())
 | 
			
		||||
            .with_get("dist", |b: &mut OrderServerBuilder| b.dist.clone())
 | 
			
		||||
            .with_get("location", |b: &mut OrderServerBuilder| b.location.clone())
 | 
			
		||||
            .with_get("authorized_keys", |b: &mut OrderServerBuilder| {
 | 
			
		||||
                b.authorized_keys.clone()
 | 
			
		||||
            })
 | 
			
		||||
            .with_get("addons", |b: &mut OrderServerBuilder| b.addons.clone())
 | 
			
		||||
            .with_get("test", |b: &mut OrderServerBuilder| b.test.clone());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Deserialize, Clone, CustomType)]
 | 
			
		||||
#[rhai_type(extra = Self::build_rhai_type)]
 | 
			
		||||
@@ -1428,9 +1531,60 @@ impl OrderAuctionServerBuilder {
 | 
			
		||||
            .with_fn("with_comment", Self::with_comment)
 | 
			
		||||
            .with_fn("with_addon", Self::with_addon)
 | 
			
		||||
            .with_fn("with_test", Self::with_test)
 | 
			
		||||
            // TODO implement other getters
 | 
			
		||||
            .with_get("authorized_keys", |b: &mut OrderAuctionServerBuilder| {
 | 
			
		||||
                b.authorized_keys.clone()
 | 
			
		||||
            })
 | 
			
		||||
            .with_get("dist", |b: &mut OrderAuctionServerBuilder| b.dist.clone())
 | 
			
		||||
            .with_get("lang", |b: &mut OrderAuctionServerBuilder| b.lang.clone())
 | 
			
		||||
            .with_get("comment", |b: &mut OrderAuctionServerBuilder| {
 | 
			
		||||
                b.comment.clone().unwrap_or("".to_string())
 | 
			
		||||
            });
 | 
			
		||||
            })
 | 
			
		||||
            .with_get("addon", |b: &mut OrderAuctionServerBuilder| b.addon.clone())
 | 
			
		||||
            .with_get("test", |b: &mut OrderAuctionServerBuilder| b.test.clone());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
fn string_or_seq_string<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
 | 
			
		||||
where
 | 
			
		||||
    D: Deserializer<'de>,
 | 
			
		||||
{
 | 
			
		||||
    let value = Value::deserialize(deserializer)?;
 | 
			
		||||
    match value {
 | 
			
		||||
        Value::String(s) => Ok(vec![s]),
 | 
			
		||||
        Value::Array(a) => a
 | 
			
		||||
            .into_iter()
 | 
			
		||||
            .map(|v| {
 | 
			
		||||
                v.as_str()
 | 
			
		||||
                    .map(ToString::to_string)
 | 
			
		||||
                    .ok_or(serde::de::Error::custom("expected string"))
 | 
			
		||||
            })
 | 
			
		||||
            .collect(),
 | 
			
		||||
        _ => Err(serde::de::Error::custom(
 | 
			
		||||
            "expected string or array of strings",
 | 
			
		||||
        )),
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn option_string_or_seq_string<'de, D>(deserializer: D) -> Result<Option<Vec<String>>, D::Error>
 | 
			
		||||
where
 | 
			
		||||
    D: Deserializer<'de>,
 | 
			
		||||
{
 | 
			
		||||
    let value = Value::deserialize(deserializer)?;
 | 
			
		||||
    match value {
 | 
			
		||||
        Value::Null => Ok(None),
 | 
			
		||||
        Value::String(s) => Ok(Some(vec![s])),
 | 
			
		||||
        Value::Array(a) => Ok(Some(
 | 
			
		||||
            a.into_iter()
 | 
			
		||||
                .map(|v| {
 | 
			
		||||
                    v.as_str()
 | 
			
		||||
                        .map(ToString::to_string)
 | 
			
		||||
                        .ok_or(serde::de::Error::custom("expected string"))
 | 
			
		||||
                })
 | 
			
		||||
                .collect::<Result<Vec<String>, _>>()?,
 | 
			
		||||
        )),
 | 
			
		||||
        _ => Err(serde::de::Error::custom(
 | 
			
		||||
            "expected string or array of strings",
 | 
			
		||||
        )),
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
use crate::api::Client;
 | 
			
		||||
use crate::api::models::{
 | 
			
		||||
    AuctionServerProduct, AuctionTransaction, AuctionTransactionProduct, AuthorizedKey, Boot, Cancellation, Cpanel, HostKey, Linux, OrderAuctionServerBuilder, OrderServerProduct, Plesk, Rescue, Server, SshKey, Transaction, TransactionProduct, Vnc, Windows
 | 
			
		||||
    AuctionServerProduct, AuctionTransaction, AuctionTransactionProduct, AuthorizedKey, Boot, Cancellation, Cpanel, HostKey, Linux, OrderAuctionServerBuilder, OrderServerBuilder, OrderServerProduct, Plesk, Rescue, Server, SshKey, Transaction, TransactionProduct, Vnc, Windows
 | 
			
		||||
};
 | 
			
		||||
use rhai::{Engine, Scope};
 | 
			
		||||
 | 
			
		||||
@@ -33,6 +33,7 @@ pub fn setup_engine(client: Client) -> (Engine, Scope<'static>) {
 | 
			
		||||
    engine.build_type::<AuctionTransaction>();
 | 
			
		||||
    engine.build_type::<AuctionTransactionProduct>();
 | 
			
		||||
    engine.build_type::<OrderAuctionServerBuilder>();
 | 
			
		||||
    engine.build_type::<OrderServerBuilder>();
 | 
			
		||||
 | 
			
		||||
    server::register(&mut engine);
 | 
			
		||||
    ssh_keys::register(&mut engine);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,9 @@
 | 
			
		||||
use crate::api::{
 | 
			
		||||
    Client,
 | 
			
		||||
    models::{AuctionServerProduct, AuctionTransaction, OrderServerProduct, SshKey, Transaction},
 | 
			
		||||
    models::{
 | 
			
		||||
        AuctionServerProduct, AuctionTransaction, OrderAuctionServerBuilder, OrderServerBuilder,
 | 
			
		||||
        OrderServerProduct, Transaction,
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
use rhai::{Array, Dynamic, plugin::*};
 | 
			
		||||
 | 
			
		||||
@@ -11,8 +14,6 @@ pub fn register(engine: &mut Engine) {
 | 
			
		||||
 | 
			
		||||
#[export_module]
 | 
			
		||||
pub mod server_order_api {
 | 
			
		||||
    use crate::api::models::OrderAuctionServerBuilder;
 | 
			
		||||
 | 
			
		||||
    #[rhai_fn(name = "get_server_products", return_raw)]
 | 
			
		||||
    pub fn get_server_ordering_product_overview(
 | 
			
		||||
        client: &mut Client,
 | 
			
		||||
@@ -37,39 +38,10 @@ pub mod server_order_api {
 | 
			
		||||
    #[rhai_fn(name = "order_server", return_raw)]
 | 
			
		||||
    pub fn order_server(
 | 
			
		||||
        client: &mut Client,
 | 
			
		||||
        product_id: &str,
 | 
			
		||||
        dist: &str,
 | 
			
		||||
        location: &str,
 | 
			
		||||
        authorized_keys: Array,
 | 
			
		||||
        addons: Array,
 | 
			
		||||
        order: OrderServerBuilder,
 | 
			
		||||
    ) -> Result<Transaction, Box<EvalAltResult>> {
 | 
			
		||||
        let authorized_keys: Vec<String> = if authorized_keys.is_empty() {
 | 
			
		||||
            vec![]
 | 
			
		||||
        } else if authorized_keys[0].is::<SshKey>() {
 | 
			
		||||
            authorized_keys
 | 
			
		||||
                .into_iter()
 | 
			
		||||
                .map(|k| k.cast::<SshKey>().fingerprint)
 | 
			
		||||
                .collect()
 | 
			
		||||
        } else {
 | 
			
		||||
            authorized_keys
 | 
			
		||||
                .into_iter()
 | 
			
		||||
                .map(|k| k.into_string().unwrap())
 | 
			
		||||
                .collect()
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        let addons = if addons.is_empty() {
 | 
			
		||||
            None
 | 
			
		||||
        } else {
 | 
			
		||||
            Some(
 | 
			
		||||
                addons
 | 
			
		||||
                    .into_iter()
 | 
			
		||||
                    .map(|a| a.into_string().unwrap())
 | 
			
		||||
                    .collect(),
 | 
			
		||||
            )
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        let transaction = client
 | 
			
		||||
            .order_server(product_id, dist, location, authorized_keys, addons)
 | 
			
		||||
            .order_server(order)
 | 
			
		||||
            .map_err(|e| Into::<Box<EvalAltResult>>::into(e.to_string()))?;
 | 
			
		||||
        Ok(transaction)
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user