Skip to main content

web_arena_indigo/
instance.rs

1//! Instance (VM) APIs.
2
3use crate::http::HttpClient;
4use crate::serde_util::opt_string_lenient;
5use crate::{WebArenaIndigoApi, WebArenaIndigoApiError};
6use serde::{Deserialize, Serialize};
7use serde_json::json;
8
9pub struct InstanceApi<'a> {
10    indigo: &'a WebArenaIndigoApi,
11}
12
13impl<'a> InstanceApi<'a> {
14    pub(crate) fn new(api: &'a WebArenaIndigoApi) -> Self {
15        InstanceApi { indigo: api }
16    }
17
18    /// `GET /webarenaIndigo/v1/vm/instancetypes`
19    pub async fn instance_type_list(
20        &self,
21    ) -> Result<InstanceTypeListResponse, WebArenaIndigoApiError> {
22        HttpClient::get(
23            self.indigo.throttle(),
24            self.indigo.access_token(),
25            &self.indigo.endpoint("/webarenaIndigo/v1/vm/instancetypes"),
26        )
27        .await
28    }
29
30    /// `GET /webarenaIndigo/v1/vm/getregion`
31    pub async fn region_list(
32        &self,
33        instance_type_id: u32,
34    ) -> Result<RegionListResponse, WebArenaIndigoApiError> {
35        HttpClient::get(
36            self.indigo.throttle(),
37            self.indigo.access_token(),
38            &self.indigo.endpoint(&format!(
39                "/webarenaIndigo/v1/vm/getregion?instanceTypeId={}",
40                instance_type_id
41            )),
42        )
43        .await
44    }
45
46    /// `GET /webarenaIndigo/v1/vm/oslist`
47    pub async fn os_list(
48        &self,
49        instance_type_id: u32,
50    ) -> Result<OsListResponse, WebArenaIndigoApiError> {
51        HttpClient::get(
52            self.indigo.throttle(),
53            self.indigo.access_token(),
54            &self.indigo.endpoint(&format!(
55                "/webarenaIndigo/v1/vm/oslist?instanceTypeId={}",
56                instance_type_id
57            )),
58        )
59        .await
60    }
61
62    /// `GET /webarenaIndigo/v1/vm/getinstancespec`
63    pub async fn instance_specification(
64        &self,
65        instance_type_id: u32,
66    ) -> Result<InstanceSpecificationResponse, WebArenaIndigoApiError> {
67        HttpClient::get(
68            self.indigo.throttle(),
69            self.indigo.access_token(),
70            &self.indigo.endpoint(&format!(
71                "/webarenaIndigo/v1/vm/getinstancespec?instanceTypeId={}",
72                instance_type_id
73            )),
74        )
75        .await
76    }
77
78    /// `POST /webarenaIndigo/v1/vm/createinstance`
79    pub async fn create_instance(
80        &self,
81        request: CreateInstanceRequest,
82    ) -> Result<CreateInstanceResponse, WebArenaIndigoApiError> {
83        HttpClient::post(
84            self.indigo.throttle(),
85            self.indigo.access_token(),
86            &self.indigo.endpoint("/webarenaIndigo/v1/vm/createinstance"),
87            &request,
88        )
89        .await
90    }
91
92    /// `GET /webarenaIndigo/v1/vm/getinstancelist`
93    pub async fn instance_list(&self) -> Result<Vec<Instance>, WebArenaIndigoApiError> {
94        HttpClient::get(
95            self.indigo.throttle(),
96            self.indigo.access_token(),
97            &self
98                .indigo
99                .endpoint("/webarenaIndigo/v1/vm/getinstancelist"),
100        )
101        .await
102    }
103
104    /// `POST /webarenaIndigo/v1/vm/instance/statusupdate`
105    ///
106    /// [`InstanceStatus::Destroy`] deletes the instance.
107    pub async fn update_instance_status(
108        &self,
109        instance_id: u32,
110        status: InstanceStatus,
111    ) -> Result<UpdateInstanceStatusResponse, WebArenaIndigoApiError> {
112        HttpClient::post(
113            self.indigo.throttle(),
114            self.indigo.access_token(),
115            &self
116                .indigo
117                .endpoint("/webarenaIndigo/v1/vm/instance/statusupdate"),
118            &json!({
119                "instanceId": instance_id,
120                "status": status,
121            }),
122        )
123        .await
124    }
125}
126
127#[derive(Debug, Clone, Serialize, Deserialize)]
128pub struct InstanceTypeListResponse {
129    pub success: bool,
130    pub total: u32,
131    #[serde(rename = "instanceTypes")]
132    pub instance_types: Vec<InstanceType>,
133}
134
135#[derive(Debug, Clone, Serialize, Deserialize)]
136pub struct InstanceType {
137    pub id: u32,
138    pub name: String,
139    pub display_name: String,
140    pub created_at: String,
141    pub updated_at: String,
142}
143
144#[derive(Debug, Clone, Serialize, Deserialize)]
145pub struct RegionListResponse {
146    pub success: bool,
147    pub total: u32,
148    #[serde(rename = "regionlist")]
149    pub region_list: Vec<Region>,
150}
151
152#[derive(Debug, Clone, Serialize, Deserialize)]
153pub struct Region {
154    pub id: u32,
155    pub name: String,
156    pub use_possible_date: String,
157}
158
159#[derive(Debug, Clone, Serialize, Deserialize)]
160pub struct OsListResponse {
161    pub success: bool,
162    pub total: u32,
163    #[serde(rename = "osCategory")]
164    pub os_category: Vec<OsCategory>,
165}
166
167#[derive(Debug, Clone, Serialize, Deserialize)]
168pub struct OsCategory {
169    pub id: u32,
170    pub name: String,
171    pub logo: String,
172    #[serde(rename = "osLists")]
173    pub os_lists: Vec<OsList>,
174}
175
176#[derive(Debug, Clone, Serialize, Deserialize)]
177pub struct OsList {
178    pub id: u32,
179    /// The live API sends `categoryid` although the documentation says
180    /// `categoryId`; both are accepted.
181    #[serde(rename = "categoryid", alias = "categoryId")]
182    pub category_id: u32,
183    /// Not documented, but returned by the live API (e.g. `"Ubuntu"`).
184    pub code: Option<String>,
185    pub name: String,
186    #[serde(rename = "viewname")]
187    pub view_name: String,
188    #[serde(rename = "instancetype_id")]
189    pub instance_type_id: u32,
190}
191
192#[derive(Debug, Clone, Serialize, Deserialize)]
193pub struct InstanceSpecificationResponse {
194    pub success: bool,
195    pub total: u32,
196    #[serde(rename = "speclist")]
197    pub spec_list: Vec<InstanceSpec>,
198}
199
200#[derive(Debug, Clone, Serialize, Deserialize)]
201pub struct InstanceSpec {
202    pub id: u32,
203    pub name: String,
204    pub description: String,
205    pub use_possible_date: String,
206    #[serde(rename = "instancetype_id")]
207    pub instance_type_id: u32,
208    pub created_at: String,
209    pub updated_at: String,
210    pub instance_type: InstanceType,
211}
212
213/// Request body for [`InstanceApi::create_instance`]. One variant per
214/// documented boot method.
215#[derive(Debug, Clone, Serialize)]
216#[serde(untagged)]
217pub enum CreateInstanceRequest {
218    /// Boot a Linux instance with an SSH key.
219    Standard {
220        #[serde(rename = "sshKeyId")]
221        ssh_key_id: u32,
222        #[serde(rename = "regionId")]
223        region_id: u32,
224        #[serde(rename = "osId")]
225        os_id: u32,
226        #[serde(rename = "instancePlan")]
227        instance_plan: u32,
228        #[serde(rename = "instanceName")]
229        instance_name: String,
230    },
231    /// Boot a Windows instance with an administrator password.
232    Windows {
233        #[serde(rename = "winPassword")]
234        win_password: String,
235        #[serde(rename = "regionId")]
236        region_id: u32,
237        #[serde(rename = "osId")]
238        os_id: u32,
239        #[serde(rename = "instancePlan")]
240        instance_plan: u32,
241        #[serde(rename = "instanceName")]
242        instance_name: String,
243    },
244    /// Boot from an image imported from a URL.
245    Import {
246        #[serde(rename = "importUrl")]
247        import_url: String,
248        #[serde(rename = "regionId")]
249        region_id: u32,
250        #[serde(rename = "osId")]
251        os_id: u32,
252        #[serde(rename = "instancePlan")]
253        instance_plan: u32,
254        #[serde(rename = "instanceName")]
255        instance_name: String,
256    },
257    /// Boot from an existing snapshot.
258    FromSnapshot {
259        #[serde(rename = "sshKeyId")]
260        ssh_key_id: u32,
261        #[serde(rename = "snapshotId")]
262        snapshot_id: u32,
263        #[serde(rename = "instancePlan")]
264        instance_plan: u32,
265        #[serde(rename = "instanceName")]
266        instance_name: String,
267    },
268}
269
270#[derive(Debug, Clone, Serialize, Deserialize)]
271pub struct CreateInstanceResponse {
272    pub success: bool,
273    pub message: String,
274    pub vms: Instance,
275}
276
277#[derive(Debug, Clone, Serialize, Deserialize)]
278pub struct Instance {
279    pub id: u32,
280    pub instance_name: String,
281    pub set_no: u32,
282    /// The API returns this as either a number or a string.
283    #[serde(default, deserialize_with = "opt_string_lenient")]
284    pub vps_kind: Option<String>,
285    pub sequence_id: u32,
286    pub user_id: u32,
287    pub service_id: String,
288    pub status: String,
289    #[serde(rename = "sshkey_id")]
290    pub ssh_key_id: u32,
291    pub start_date: Option<InstanceDate>,
292    pub host_id: u32,
293    pub plan: String,
294    pub disk_point: u32,
295    #[serde(rename = "memsize")]
296    pub mem_size: u32,
297    pub cpus: u32,
298    pub os_id: u32,
299    #[serde(rename = "otherstatus")]
300    pub other_status: u32,
301    pub uuid: Option<String>,
302    #[serde(rename = "uidgid")]
303    pub uid_gid: u32,
304    pub vnc_port: u32,
305    pub vnc_passwd: String,
306    #[serde(rename = "arpaname")]
307    pub arpa_name: Option<String>,
308    #[serde(rename = "arpadate")]
309    pub arpa_date: u32,
310    pub ipaddress: Option<String>,
311    pub secondary_ip: Option<String>,
312    pub macaddress: Option<String>,
313    pub ipaddress_type: Option<String>,
314    pub status_change_date: Option<InstanceDate>,
315    pub updated_at: Option<InstanceDate>,
316    pub vm_revert: u32,
317}
318
319#[derive(Debug, Clone, Serialize, Deserialize)]
320pub struct InstanceDate {
321    pub date: String,
322    pub timezone_type: u32,
323    pub timezone: String,
324}
325
326#[derive(Debug, Clone, Copy, Serialize)]
327pub enum InstanceStatus {
328    #[serde(rename = "start")]
329    Start,
330    #[serde(rename = "stop")]
331    Stop,
332    #[serde(rename = "forcestop")]
333    ForceStop,
334    #[serde(rename = "reset")]
335    Reset,
336    /// Deletes the instance.
337    #[serde(rename = "destroy")]
338    Destroy,
339}
340
341#[derive(Debug, Clone, Serialize, Deserialize)]
342pub struct UpdateInstanceStatusResponse {
343    pub success: bool,
344    pub message: String,
345    #[serde(rename = "sucessCode")]
346    pub success_code: String,
347    #[serde(rename = "instanceStatus")]
348    pub instance_status: String,
349}