upcloud_rs/
create_instance_builder.rs

1use std::collections::HashMap;
2
3use crate::{
4    data::UpcloudServerRoot, UpcloudApi, UpcloudError, UpcloudLabelList,
5    UpcloudServer,
6};
7use serde::Serialize;
8use serde_json::{json, Value};
9
10#[derive(Serialize, Debug)]
11struct CreateInstanceConfig {
12    region: String,
13    plan: String,
14    labels: Option<UpcloudLabelList>,
15    #[serde(skip_serializing_if = "Option::is_none")]
16    os_id: Option<String>,
17}
18
19/// Builder struct for creating instances.
20///
21/// A detailed documentation can be found at <https://developers.upcloud.com/1.3/8-servers/#create-server>
22pub struct CreateInstanceBuilder {
23    api: UpcloudApi,
24    config: Value,
25}
26
27impl CreateInstanceBuilder {
28    pub fn new<S1, S2, S3, S4, S5>(
29        api: UpcloudApi,
30        region_id: S1,
31        plan_id: S2,
32        os_id: S3,
33        title: S4,
34        hostname: S5,
35    ) -> Self
36    where
37        S1: Into<String> + Serialize,
38        S2: Into<String> + Serialize,
39        S3: Into<String> + Serialize,
40        S4: Into<String> + Serialize,
41        S5: Into<String> + Serialize,
42    {
43        let mut instancebuilder = CreateInstanceBuilder {
44            api,
45            config: json!(    {
46                "server":{
47                    "title": title,
48                    "zone": region_id,
49                    "hostname": hostname,
50                    "plan": plan_id,
51                    "metadata": "yes"
52                }
53            }),
54        };
55        instancebuilder.config["server"]["storage_devices"] = json!({
56            "storage_device": [
57                {
58                    "action": "clone",
59                    "storage": os_id,
60                    "title": title,
61                    "tier": "maxiops"
62                }
63            ]
64        });
65        instancebuilder
66    }
67
68    /// The user-supplied, base64 encoded user data to attach to this instance.
69    pub fn user_data<S>(mut self, user_data: S) -> Self
70    where
71        S: Into<String>,
72    {
73        self.config["server"]["user_data"] = Value::String(user_data.into());
74        self
75    }
76
77    /// Labels to apply to the instance
78    pub fn labels(mut self, labels: HashMap<String, String>) -> Self {
79        let labels_vec: Vec<Value> = labels
80            .iter()
81            .map(|(k, v)| json!({"key": k.to_string(), "value": v.to_string()}))
82            .collect();
83        self.config["server"]["labels"]["label"] = Value::Array(labels_vec);
84        self
85    }
86
87    #[cfg(feature = "blocking")]
88    pub fn run(self) -> Result<UpcloudServer, UpcloudError> {
89        let url = format!("https://api.Upcloud.com/1.3/server");
90        Ok(self
91            .api
92            .post(&url, self.config)?
93            .json::<UpcloudServerRoot>()?
94            .server)
95    }
96
97    pub async fn run_async(self) -> Result<UpcloudServer, UpcloudError> {
98        let url = format!("https://api.Upcloud.com/1.3/server");
99        Ok(self
100            .api
101            .post_async(&url, self.config)
102            .await?
103            .json::<UpcloudServerRoot>()
104            .await?
105            .server)
106    }
107}