1use crate::{
2 client::{TencentCloudAsync, TencentCloudBlocking},
3 core::{Endpoint, TencentCloudResult},
4 services::Filter,
5};
6use serde::{Deserialize, Serialize};
7use serde_json::{json, Value};
8use std::borrow::Cow;
9use std::collections::HashMap;
10
11#[derive(Debug, Deserialize)]
12pub struct DescribeInstancesResponse {
13 #[serde(rename = "Response")]
14 pub response: DescribeInstancesResult,
15}
16
17#[derive(Debug, Deserialize)]
18pub struct DescribeInstancesResult {
19 #[serde(rename = "TotalCount")]
20 pub total_count: Option<u64>,
21 #[serde(rename = "InstanceSet")]
22 #[serde(default)]
23 pub instance_set: Vec<InstanceSummary>,
24 #[serde(rename = "RequestId")]
25 pub request_id: String,
26}
27
28#[derive(Debug, Deserialize)]
29pub struct InstanceSummary {
30 #[serde(rename = "InstanceId")]
31 pub instance_id: Option<String>,
32 #[serde(rename = "InstanceName")]
33 pub instance_name: Option<String>,
34 #[serde(rename = "InstanceState")]
35 pub instance_state: Option<String>,
36 #[serde(rename = "InstanceType")]
37 pub instance_type: Option<String>,
38 #[serde(rename = "Cpu")]
39 pub cpu: Option<u64>,
40 #[serde(rename = "Memory")]
41 pub memory: Option<u64>,
42 #[serde(rename = "PrivateIpAddresses")]
43 pub private_ip_addresses: Option<Vec<String>>,
44 #[serde(rename = "PublicIpAddresses")]
45 pub public_ip_addresses: Option<Vec<String>>,
46 #[serde(default)]
47 pub placement: Option<InstancePlacement>,
48 #[serde(default)]
49 pub system_disk: Option<DiskSummary>,
50 #[serde(default)]
51 pub data_disks: Option<Vec<DiskSummary>>,
52 #[serde(flatten, default)]
53 pub extra: HashMap<String, Value>,
54}
55
56#[derive(Debug, Deserialize)]
57pub struct InstancePlacement {
58 #[serde(rename = "Zone")]
59 pub zone: Option<String>,
60 #[serde(rename = "ProjectId")]
61 pub project_id: Option<i64>,
62 #[serde(flatten, default)]
63 pub extra: HashMap<String, Value>,
64}
65
66#[derive(Debug, Deserialize)]
67pub struct DiskSummary {
68 #[serde(rename = "DiskType")]
69 pub disk_type: Option<String>,
70 #[serde(rename = "DiskSize")]
71 pub disk_size: Option<u64>,
72 #[serde(flatten, default)]
73 pub extra: HashMap<String, Value>,
74}
75
76#[derive(Serialize)]
77#[serde(rename_all = "PascalCase")]
78struct DescribeInstancesPayload<'a> {
79 #[serde(skip_serializing_if = "Option::is_none")]
80 filters: Option<&'a [Filter<'a>]>,
81 #[serde(skip_serializing_if = "Option::is_none")]
82 limit: Option<u32>,
83 #[serde(skip_serializing_if = "Option::is_none")]
84 offset: Option<u32>,
85}
86
87pub struct DescribeInstances<'a> {
89 pub region: Option<&'a str>,
90 pub filters: Option<Vec<Filter<'a>>>,
91 pub limit: Option<u32>,
92 pub offset: Option<u32>,
93}
94
95impl<'a> Default for DescribeInstances<'a> {
96 fn default() -> Self {
97 Self::new()
98 }
99}
100
101impl<'a> DescribeInstances<'a> {
102 pub fn new() -> Self {
104 Self {
105 region: None,
106 filters: None,
107 limit: None,
108 offset: None,
109 }
110 }
111
112 pub fn with_region(mut self, region: &'a str) -> Self {
114 self.region = Some(region);
115 self
116 }
117
118 pub fn push_filter(mut self, filter: Filter<'a>) -> Self {
120 self.filters.get_or_insert_with(Vec::new).push(filter);
121 self
122 }
123
124 pub fn with_limit(mut self, limit: u32) -> Self {
126 self.limit = Some(limit);
127 self
128 }
129
130 pub fn with_offset(mut self, offset: u32) -> Self {
132 self.offset = Some(offset);
133 self
134 }
135}
136
137impl<'a> Endpoint for DescribeInstances<'a> {
138 type Output = DescribeInstancesResponse;
139
140 fn service(&self) -> Cow<'static, str> {
141 Cow::Borrowed("cvm")
142 }
143
144 fn action(&self) -> Cow<'static, str> {
145 Cow::Borrowed("DescribeInstances")
146 }
147
148 fn version(&self) -> Cow<'static, str> {
149 Cow::Borrowed("2017-03-12")
150 }
151
152 fn region(&self) -> Option<Cow<'_, str>> {
153 self.region.map(Cow::Borrowed)
154 }
155
156 fn payload(&self) -> Value {
157 let filters = self.filters.as_deref();
158 serde_json::to_value(DescribeInstancesPayload {
159 filters,
160 limit: self.limit,
161 offset: self.offset,
162 })
163 .expect("serialize DescribeInstances payload")
164 }
165}
166
167#[derive(Debug, Deserialize)]
168pub struct GenericActionResponse {
169 #[serde(rename = "Response")]
170 pub response: GenericActionResult,
171}
172
173#[derive(Debug, Deserialize)]
174pub struct GenericActionResult {
175 #[serde(rename = "RequestId")]
176 pub request_id: String,
177}
178
179pub struct ResetInstancesPassword<'a> {
181 pub region: &'a str,
182 pub instance_ids: &'a [&'a str],
183 pub password: &'a str,
184 pub username: Option<&'a str>,
185 pub force_stop: Option<bool>,
186}
187
188impl<'a> Endpoint for ResetInstancesPassword<'a> {
189 type Output = GenericActionResponse;
190
191 fn service(&self) -> Cow<'static, str> {
192 Cow::Borrowed("cvm")
193 }
194
195 fn action(&self) -> Cow<'static, str> {
196 Cow::Borrowed("ResetInstancesPassword")
197 }
198
199 fn version(&self) -> Cow<'static, str> {
200 Cow::Borrowed("2017-03-12")
201 }
202
203 fn region(&self) -> Option<Cow<'_, str>> {
204 Some(Cow::Borrowed(self.region))
205 }
206
207 fn payload(&self) -> Value {
208 let mut payload = json!({
209 "InstanceIds": self.instance_ids,
210 "Password": self.password
211 });
212
213 if let Some(username) = self.username {
214 payload["UserName"] = json!(username);
215 }
216 if let Some(force_stop) = self.force_stop {
217 payload["ForceStop"] = json!(force_stop);
218 }
219 payload
220 }
221}
222
223#[derive(Debug, Deserialize)]
224pub struct DescribeInstanceVncUrlResponse {
225 #[serde(rename = "Response")]
226 pub response: DescribeInstanceVncUrlResult,
227}
228
229#[derive(Debug, Deserialize)]
230pub struct DescribeInstanceVncUrlResult {
231 #[serde(rename = "InstanceVncUrl")]
232 pub instance_vnc_url: Option<String>,
233 #[serde(rename = "RequestId")]
234 pub request_id: String,
235}
236
237pub struct DescribeInstanceVncUrl<'a> {
239 pub region: &'a str,
240 pub instance_id: &'a str,
241}
242
243impl<'a> Endpoint for DescribeInstanceVncUrl<'a> {
244 type Output = DescribeInstanceVncUrlResponse;
245
246 fn service(&self) -> Cow<'static, str> {
247 Cow::Borrowed("cvm")
248 }
249
250 fn action(&self) -> Cow<'static, str> {
251 Cow::Borrowed("DescribeInstanceVncUrl")
252 }
253
254 fn version(&self) -> Cow<'static, str> {
255 Cow::Borrowed("2017-03-12")
256 }
257
258 fn region(&self) -> Option<Cow<'_, str>> {
259 Some(Cow::Borrowed(self.region))
260 }
261
262 fn payload(&self) -> Value {
263 json!({ "InstanceId": self.instance_id })
264 }
265}
266
267#[derive(Debug, Deserialize)]
268pub struct RunInstancesResponse {
269 #[serde(rename = "Response")]
270 pub response: RunInstancesResult,
271}
272
273#[derive(Debug, Deserialize)]
274pub struct RunInstancesResult {
275 #[serde(rename = "InstanceIdSet")]
276 pub instance_id_set: Option<Vec<String>>,
277 #[serde(rename = "RequestId")]
278 pub request_id: String,
279}
280
281#[derive(Serialize)]
282#[serde(rename_all = "PascalCase")]
283struct RunInstancesPayload<'a> {
284 image_id: &'a str,
285 instance_type: &'a str,
286 #[serde(skip_serializing_if = "Option::is_none")]
287 instance_name: Option<&'a str>,
288 #[serde(skip_serializing_if = "Option::is_none")]
289 instance_count: Option<u32>,
290 #[serde(skip_serializing_if = "Option::is_none")]
291 client_token: Option<&'a str>,
292 #[serde(skip_serializing_if = "Option::is_none")]
293 subnet_id: Option<&'a str>,
294 #[serde(skip_serializing_if = "Option::is_none")]
295 vpc_id: Option<&'a str>,
296 #[serde(skip_serializing_if = "Option::is_none")]
297 security_group_ids: Option<&'a [&'a str]>,
298}
299
300pub struct RunInstances<'a> {
302 pub region: &'a str,
303 pub image_id: &'a str,
304 pub instance_type: &'a str,
305 pub instance_name: Option<&'a str>,
306 pub instance_count: Option<u32>,
307 pub client_token: Option<&'a str>,
308 pub subnet_id: Option<&'a str>,
309 pub vpc_id: Option<&'a str>,
310 pub security_group_ids: Option<Vec<&'a str>>,
311}
312
313impl<'a> RunInstances<'a> {
314 pub fn new(region: &'a str, image_id: &'a str, instance_type: &'a str) -> Self {
315 Self {
316 region,
317 image_id,
318 instance_type,
319 instance_name: None,
320 instance_count: None,
321 client_token: None,
322 subnet_id: None,
323 vpc_id: None,
324 security_group_ids: None,
325 }
326 }
327
328 pub fn with_instance_name(mut self, name: &'a str) -> Self {
329 self.instance_name = Some(name);
330 self
331 }
332
333 pub fn with_instance_count(mut self, count: u32) -> Self {
334 self.instance_count = Some(count);
335 self
336 }
337
338 pub fn with_client_token(mut self, token: &'a str) -> Self {
339 self.client_token = Some(token);
340 self
341 }
342
343 pub fn with_subnet(mut self, subnet_id: &'a str) -> Self {
344 self.subnet_id = Some(subnet_id);
345 self
346 }
347
348 pub fn with_vpc(mut self, vpc_id: &'a str) -> Self {
349 self.vpc_id = Some(vpc_id);
350 self
351 }
352
353 pub fn with_security_groups<I>(mut self, groups: I) -> Self
354 where
355 I: IntoIterator<Item = &'a str>,
356 {
357 self.security_group_ids = Some(groups.into_iter().collect());
358 self
359 }
360}
361
362impl<'a> Endpoint for RunInstances<'a> {
363 type Output = RunInstancesResponse;
364
365 fn service(&self) -> Cow<'static, str> {
366 Cow::Borrowed("cvm")
367 }
368
369 fn action(&self) -> Cow<'static, str> {
370 Cow::Borrowed("RunInstances")
371 }
372
373 fn version(&self) -> Cow<'static, str> {
374 Cow::Borrowed("2017-03-12")
375 }
376
377 fn region(&self) -> Option<Cow<'_, str>> {
378 Some(Cow::Borrowed(self.region))
379 }
380
381 fn payload(&self) -> Value {
382 let security_group_ids = self.security_group_ids.as_ref().map(|ids| ids.to_vec());
383
384 let payload = RunInstancesPayload {
385 image_id: self.image_id,
386 instance_type: self.instance_type,
387 instance_name: self.instance_name,
388 instance_count: self.instance_count,
389 client_token: self.client_token,
390 subnet_id: self.subnet_id,
391 vpc_id: self.vpc_id,
392 security_group_ids: security_group_ids.as_deref(),
393 };
394
395 serde_json::to_value(payload).expect("serialize RunInstances payload")
396 }
397}
398
399pub struct StartInstances<'a> {
401 pub region: &'a str,
402 pub instance_ids: &'a [&'a str],
403}
404
405impl<'a> Endpoint for StartInstances<'a> {
406 type Output = GenericActionResponse;
407
408 fn service(&self) -> Cow<'static, str> {
409 Cow::Borrowed("cvm")
410 }
411
412 fn action(&self) -> Cow<'static, str> {
413 Cow::Borrowed("StartInstances")
414 }
415
416 fn version(&self) -> Cow<'static, str> {
417 Cow::Borrowed("2017-03-12")
418 }
419
420 fn region(&self) -> Option<Cow<'_, str>> {
421 Some(Cow::Borrowed(self.region))
422 }
423
424 fn payload(&self) -> Value {
425 json!({ "InstanceIds": self.instance_ids })
426 }
427}
428
429pub struct RebootInstances<'a> {
431 pub region: &'a str,
432 pub instance_ids: &'a [&'a str],
433 pub force_reboot: Option<bool>,
434}
435
436impl<'a> Endpoint for RebootInstances<'a> {
437 type Output = GenericActionResponse;
438
439 fn service(&self) -> Cow<'static, str> {
440 Cow::Borrowed("cvm")
441 }
442
443 fn action(&self) -> Cow<'static, str> {
444 Cow::Borrowed("RebootInstances")
445 }
446
447 fn version(&self) -> Cow<'static, str> {
448 Cow::Borrowed("2017-03-12")
449 }
450
451 fn region(&self) -> Option<Cow<'_, str>> {
452 Some(Cow::Borrowed(self.region))
453 }
454
455 fn payload(&self) -> Value {
456 let mut payload = json!({ "InstanceIds": self.instance_ids });
457 if let Some(force_reboot) = self.force_reboot {
458 payload["ForceReboot"] = json!(force_reboot);
459 }
460 payload
461 }
462}
463
464pub struct StopInstances<'a> {
466 pub region: &'a str,
467 pub instance_ids: &'a [&'a str],
468 pub stop_type: Option<&'a str>,
469}
470
471impl<'a> Endpoint for StopInstances<'a> {
472 type Output = GenericActionResponse;
473
474 fn service(&self) -> Cow<'static, str> {
475 Cow::Borrowed("cvm")
476 }
477
478 fn action(&self) -> Cow<'static, str> {
479 Cow::Borrowed("StopInstances")
480 }
481
482 fn version(&self) -> Cow<'static, str> {
483 Cow::Borrowed("2017-03-12")
484 }
485
486 fn region(&self) -> Option<Cow<'_, str>> {
487 Some(Cow::Borrowed(self.region))
488 }
489
490 fn payload(&self) -> Value {
491 let mut payload = json!({ "InstanceIds": self.instance_ids });
492 if let Some(stop_type) = self.stop_type {
493 payload["StopType"] = json!(stop_type);
494 }
495 payload
496 }
497}
498
499pub struct ModifyInstancesProject<'a> {
501 pub region: &'a str,
502 pub instance_ids: &'a [&'a str],
503 pub project_id: u64,
504}
505
506impl<'a> Endpoint for ModifyInstancesProject<'a> {
507 type Output = GenericActionResponse;
508
509 fn service(&self) -> Cow<'static, str> {
510 Cow::Borrowed("cvm")
511 }
512
513 fn action(&self) -> Cow<'static, str> {
514 Cow::Borrowed("ModifyInstancesProject")
515 }
516
517 fn version(&self) -> Cow<'static, str> {
518 Cow::Borrowed("2017-03-12")
519 }
520
521 fn region(&self) -> Option<Cow<'_, str>> {
522 Some(Cow::Borrowed(self.region))
523 }
524
525 fn payload(&self) -> Value {
526 json!({
527 "InstanceIds": self.instance_ids,
528 "ProjectId": self.project_id
529 })
530 }
531}
532
533#[derive(Debug, Deserialize)]
534pub struct TerminateInstancesResponse {
535 #[serde(rename = "Response")]
536 pub response: GenericActionResult,
537}
538
539pub struct TerminateInstances<'a> {
541 pub region: &'a str,
542 pub instance_ids: &'a [&'a str],
543}
544
545impl<'a> Endpoint for TerminateInstances<'a> {
546 type Output = TerminateInstancesResponse;
547
548 fn service(&self) -> Cow<'static, str> {
549 Cow::Borrowed("cvm")
550 }
551
552 fn action(&self) -> Cow<'static, str> {
553 Cow::Borrowed("TerminateInstances")
554 }
555
556 fn version(&self) -> Cow<'static, str> {
557 Cow::Borrowed("2017-03-12")
558 }
559
560 fn region(&self) -> Option<Cow<'_, str>> {
561 Some(Cow::Borrowed(self.region))
562 }
563
564 fn payload(&self) -> Value {
565 json!({ "InstanceIds": self.instance_ids })
566 }
567}
568
569#[derive(Debug, Deserialize)]
570pub struct DescribeImagesResponse {
571 #[serde(rename = "Response")]
572 pub response: DescribeImagesResult,
573}
574
575#[derive(Debug, Deserialize)]
576pub struct DescribeImagesResult {
577 #[serde(rename = "TotalCount")]
578 pub total_count: Option<u64>,
579 #[serde(rename = "ImageSet")]
580 pub image_set: Vec<ImageSummary>,
581 #[serde(rename = "RequestId")]
582 pub request_id: String,
583}
584
585#[derive(Debug, Deserialize)]
586pub struct ImageSummary {
587 #[serde(rename = "ImageId")]
588 pub image_id: Option<String>,
589 #[serde(rename = "ImageName")]
590 pub image_name: Option<String>,
591 #[serde(rename = "ImageType")]
592 pub image_type: Option<String>,
593 #[serde(rename = "CreatedTime")]
594 pub created_time: Option<String>,
595 #[serde(flatten)]
596 pub extra: HashMap<String, Value>,
597}
598
599#[derive(Serialize)]
600#[serde(rename_all = "PascalCase")]
601struct DescribeImagesPayload<'a> {
602 #[serde(skip_serializing_if = "Option::is_none")]
603 image_ids: Option<&'a [&'a str]>,
604 #[serde(skip_serializing_if = "Option::is_none")]
605 filters: Option<&'a [Filter<'a>]>,
606 #[serde(skip_serializing_if = "Option::is_none")]
607 limit: Option<u32>,
608 #[serde(skip_serializing_if = "Option::is_none")]
609 offset: Option<u32>,
610}
611
612pub struct DescribeImages<'a> {
613 pub region: Option<&'a str>,
614 pub image_ids: Option<Vec<&'a str>>,
615 pub filters: Option<Vec<Filter<'a>>>,
616 pub limit: Option<u32>,
617 pub offset: Option<u32>,
618}
619
620impl<'a> Default for DescribeImages<'a> {
621 fn default() -> Self {
622 Self::new()
623 }
624}
625
626impl<'a> DescribeImages<'a> {
627 pub fn new() -> Self {
628 Self {
629 region: None,
630 image_ids: None,
631 filters: None,
632 limit: None,
633 offset: None,
634 }
635 }
636
637 pub fn with_region(mut self, region: &'a str) -> Self {
638 self.region = Some(region);
639 self
640 }
641
642 pub fn push_image_id(mut self, id: &'a str) -> Self {
643 self.image_ids.get_or_insert_with(Vec::new).push(id);
644 self
645 }
646
647 pub fn push_filter(mut self, filter: Filter<'a>) -> Self {
648 self.filters.get_or_insert_with(Vec::new).push(filter);
649 self
650 }
651
652 pub fn with_limit(mut self, limit: u32) -> Self {
653 self.limit = Some(limit);
654 self
655 }
656
657 pub fn with_offset(mut self, offset: u32) -> Self {
658 self.offset = Some(offset);
659 self
660 }
661}
662
663impl<'a> Endpoint for DescribeImages<'a> {
664 type Output = DescribeImagesResponse;
665
666 fn service(&self) -> Cow<'static, str> {
667 Cow::Borrowed("cvm")
668 }
669
670 fn action(&self) -> Cow<'static, str> {
671 Cow::Borrowed("DescribeImages")
672 }
673
674 fn version(&self) -> Cow<'static, str> {
675 Cow::Borrowed("2017-03-12")
676 }
677
678 fn region(&self) -> Option<Cow<'_, str>> {
679 self.region.map(Cow::Borrowed)
680 }
681
682 fn payload(&self) -> Value {
683 let payload = DescribeImagesPayload {
684 image_ids: self.image_ids.as_deref(),
685 filters: self.filters.as_deref(),
686 limit: self.limit,
687 offset: self.offset,
688 };
689
690 serde_json::to_value(payload).expect("serialize DescribeImages payload")
691 }
692}
693
694pub async fn describe_instances_async(
696 client: &TencentCloudAsync,
697 request: &DescribeInstances<'_>,
698) -> TencentCloudResult<DescribeInstancesResponse> {
699 client.request(request).await
700}
701
702pub fn describe_instances_blocking(
704 client: &TencentCloudBlocking,
705 request: &DescribeInstances<'_>,
706) -> TencentCloudResult<DescribeInstancesResponse> {
707 client.request(request)
708}
709
710pub async fn reset_instances_password_async(
712 client: &TencentCloudAsync,
713 request: &ResetInstancesPassword<'_>,
714) -> TencentCloudResult<GenericActionResponse> {
715 client.request(request).await
716}
717
718pub fn reset_instances_password_blocking(
720 client: &TencentCloudBlocking,
721 request: &ResetInstancesPassword<'_>,
722) -> TencentCloudResult<GenericActionResponse> {
723 client.request(request)
724}
725
726pub async fn describe_instance_vnc_url_async(
728 client: &TencentCloudAsync,
729 request: &DescribeInstanceVncUrl<'_>,
730) -> TencentCloudResult<DescribeInstanceVncUrlResponse> {
731 client.request(request).await
732}
733
734pub fn describe_instance_vnc_url_blocking(
736 client: &TencentCloudBlocking,
737 request: &DescribeInstanceVncUrl<'_>,
738) -> TencentCloudResult<DescribeInstanceVncUrlResponse> {
739 client.request(request)
740}
741
742pub async fn start_instances_async(
744 client: &TencentCloudAsync,
745 request: &StartInstances<'_>,
746) -> TencentCloudResult<GenericActionResponse> {
747 client.request(request).await
748}
749
750pub fn start_instances_blocking(
752 client: &TencentCloudBlocking,
753 request: &StartInstances<'_>,
754) -> TencentCloudResult<GenericActionResponse> {
755 client.request(request)
756}
757
758pub async fn reboot_instances_async(
760 client: &TencentCloudAsync,
761 request: &RebootInstances<'_>,
762) -> TencentCloudResult<GenericActionResponse> {
763 client.request(request).await
764}
765
766pub fn reboot_instances_blocking(
768 client: &TencentCloudBlocking,
769 request: &RebootInstances<'_>,
770) -> TencentCloudResult<GenericActionResponse> {
771 client.request(request)
772}
773
774pub async fn stop_instances_async(
776 client: &TencentCloudAsync,
777 request: &StopInstances<'_>,
778) -> TencentCloudResult<GenericActionResponse> {
779 client.request(request).await
780}
781
782pub fn stop_instances_blocking(
784 client: &TencentCloudBlocking,
785 request: &StopInstances<'_>,
786) -> TencentCloudResult<GenericActionResponse> {
787 client.request(request)
788}
789
790pub async fn modify_instances_project_async(
792 client: &TencentCloudAsync,
793 request: &ModifyInstancesProject<'_>,
794) -> TencentCloudResult<GenericActionResponse> {
795 client.request(request).await
796}
797
798pub fn modify_instances_project_blocking(
800 client: &TencentCloudBlocking,
801 request: &ModifyInstancesProject<'_>,
802) -> TencentCloudResult<GenericActionResponse> {
803 client.request(request)
804}
805
806pub async fn run_instances_async(
808 client: &TencentCloudAsync,
809 request: &RunInstances<'_>,
810) -> TencentCloudResult<RunInstancesResponse> {
811 client.request(request).await
812}
813
814pub fn run_instances_blocking(
816 client: &TencentCloudBlocking,
817 request: &RunInstances<'_>,
818) -> TencentCloudResult<RunInstancesResponse> {
819 client.request(request)
820}
821
822pub async fn terminate_instances_async(
824 client: &TencentCloudAsync,
825 request: &TerminateInstances<'_>,
826) -> TencentCloudResult<TerminateInstancesResponse> {
827 client.request(request).await
828}
829
830pub fn terminate_instances_blocking(
832 client: &TencentCloudBlocking,
833 request: &TerminateInstances<'_>,
834) -> TencentCloudResult<TerminateInstancesResponse> {
835 client.request(request)
836}
837
838pub async fn describe_images_async(
840 client: &TencentCloudAsync,
841 request: &DescribeImages<'_>,
842) -> TencentCloudResult<DescribeImagesResponse> {
843 client.request(request).await
844}
845
846pub fn describe_images_blocking(
848 client: &TencentCloudBlocking,
849 request: &DescribeImages<'_>,
850) -> TencentCloudResult<DescribeImagesResponse> {
851 client.request(request)
852}
853
854#[cfg(test)]
855mod tests {
856 use super::*;
857 use crate::services::Filter;
858
859 #[test]
860 fn describe_instances_payload_supports_filters() {
861 let filters = vec![
862 Filter::new("instance-id", ["ins-123"]),
863 Filter::new("zone", ["ap-shanghai-1"]),
864 ];
865 let request = DescribeInstances {
866 region: Some("ap-shanghai"),
867 filters: Some(filters.clone()),
868 limit: Some(20),
869 offset: Some(0),
870 };
871
872 let payload = request.payload();
873 assert_eq!(payload["Filters"][0]["Name"], json!("instance-id"));
874 assert_eq!(payload["Filters"][1]["Values"], json!(["ap-shanghai-1"]));
875 assert_eq!(payload["Limit"], json!(20));
876 assert_eq!(payload["Offset"], json!(0));
877 }
878
879 #[test]
880 fn deserialize_generic_action_response() {
881 let payload = r#"{
882 "Response": {
883 "RequestId": "req-abc"
884 }
885 }"#;
886 let parsed: GenericActionResponse = serde_json::from_str(payload).unwrap();
887 assert_eq!(parsed.response.request_id, "req-abc");
888 }
889
890 #[test]
891 fn deserialize_vnc_url_response() {
892 let payload = r#"{
893 "Response": {
894 "InstanceVncUrl": "https://example.com",
895 "RequestId": "req-xyz"
896 }
897 }"#;
898 let parsed: DescribeInstanceVncUrlResponse = serde_json::from_str(payload).unwrap();
899 assert_eq!(
900 parsed.response.instance_vnc_url.as_deref(),
901 Some("https://example.com")
902 );
903 }
904
905 #[test]
906 fn describe_instances_builder_accumulates_filters() {
907 let request = DescribeInstances::new()
908 .with_region("ap-guangzhou")
909 .push_filter(Filter::new("zone", ["ap-guangzhou-1"]))
910 .with_limit(10)
911 .with_offset(5);
912
913 assert_eq!(request.region, Some("ap-guangzhou"));
914 let filters = request.filters.as_ref().expect("filters set");
915 assert_eq!(filters.len(), 1);
916 assert_eq!(filters[0].name, "zone");
917 assert_eq!(filters[0].values[0], "ap-guangzhou-1");
918 assert_eq!(request.limit, Some(10));
919 assert_eq!(request.offset, Some(5));
920 }
921
922 #[test]
923 fn run_instances_payload_includes_optional_fields() {
924 let request = RunInstances::new("ap-beijing", "img-123", "S4.SMALL1")
925 .with_instance_name("demo")
926 .with_instance_count(2)
927 .with_client_token("token")
928 .with_subnet("subnet-123")
929 .with_security_groups(["sg-1", "sg-2"]);
930
931 let payload = request.payload();
932 assert_eq!(payload["ImageId"], json!("img-123"));
933 assert_eq!(payload["InstanceType"], json!("S4.SMALL1"));
934 assert_eq!(payload["InstanceName"], json!("demo"));
935 assert_eq!(payload["InstanceCount"], json!(2));
936 assert_eq!(payload["ClientToken"], json!("token"));
937 assert_eq!(payload["SubnetId"], json!("subnet-123"));
938 assert_eq!(payload["SecurityGroupIds"], json!(["sg-1", "sg-2"]));
939 }
940
941 #[test]
942 fn describe_images_payload_supports_filters() {
943 let request = DescribeImages::new()
944 .with_region("ap-beijing")
945 .push_image_id("img-123")
946 .push_filter(Filter::new("image-type", ["PUBLIC_IMAGE"]))
947 .with_limit(10);
948
949 let payload = request.payload();
950 assert_eq!(payload["ImageIds"], json!(["img-123"]));
951 assert_eq!(
952 payload["Filters"],
953 json!([{ "Name": "image-type", "Values": ["PUBLIC_IMAGE"] }])
954 );
955 assert_eq!(payload["Limit"], json!(10));
956 }
957
958 #[test]
959 fn deserialize_run_instances_response() {
960 let payload = r#"{
961 "Response": {
962 "InstanceIdSet": ["ins-1", "ins-2"],
963 "RequestId": "req-789"
964 }
965 }"#;
966 let parsed: RunInstancesResponse = serde_json::from_str(payload).unwrap();
967 assert_eq!(
968 parsed.response.instance_id_set.unwrap(),
969 vec!["ins-1".to_string(), "ins-2".to_string()]
970 );
971 }
972
973 #[test]
974 fn deserialize_describe_images_response() {
975 let payload = r#"{
976 "Response": {
977 "TotalCount": 1,
978 "ImageSet": [{
979 "ImageId": "img-1",
980 "ImageName": "test"
981 }],
982 "RequestId": "req-111"
983 }
984 }"#;
985 let parsed: DescribeImagesResponse = serde_json::from_str(payload).unwrap();
986 assert_eq!(parsed.response.total_count, Some(1));
987 assert_eq!(
988 parsed.response.image_set[0].image_id.as_deref(),
989 Some("img-1")
990 );
991 }
992}