Skip to main content

runpod_sdk/model/
common.rs

1use std::collections::HashMap;
2
3use serde::{Deserialize, Serialize};
4#[cfg(feature = "strum")]
5use strum::{Display, EnumString};
6
7/// Compute type for Pod resources.
8///
9/// Determines whether a Pod will have GPU or CPU compute resources attached.
10/// When set to `GPU`, the Pod will have GPU resources and GPU-related properties
11/// will be considered. When set to `CPU`, only CPU-related properties will be used.
12#[derive(Debug, Clone, Default, Copy, PartialEq, Eq, Serialize, Deserialize)]
13#[cfg_attr(feature = "strum", derive(Display, EnumString))]
14#[serde(rename_all = "UPPERCASE")]
15#[cfg_attr(feature = "strum", strum(serialize_all = "UPPERCASE"))]
16pub enum ComputeType {
17    /// GPU-based compute resources.
18    #[default]
19    Gpu,
20    /// CPU-based compute resources.
21    Cpu,
22}
23
24/// RunPod cloud deployment type.
25///
26/// Determines which RunPod cloud environment the Pod will be deployed to.
27/// Secure Cloud offers guaranteed availability and enterprise features,
28/// while Community Cloud offers lower costs with potentially less reliability.
29#[derive(Debug, Clone, Default, Copy, PartialEq, Eq, Serialize, Deserialize)]
30#[cfg_attr(feature = "strum", derive(Display, EnumString))]
31#[serde(rename_all = "UPPERCASE")]
32#[cfg_attr(feature = "strum", strum(serialize_all = "UPPERCASE"))]
33pub enum CloudType {
34    /// Secure Cloud deployment with guaranteed resources and enterprise features.
35    #[default]
36    Secure,
37    /// Community Cloud deployment with lower costs and shared resources.
38    Community,
39}
40
41/// Current operational status of a Pod.
42///
43/// Represents the lifecycle state of a Pod, indicating whether it's actively
44/// running, has exited gracefully, or has been forcibly terminated.
45#[derive(Debug, Clone, Default, Copy, PartialEq, Eq, Serialize, Deserialize)]
46#[cfg_attr(feature = "strum", derive(Display, EnumString))]
47#[serde(rename_all = "UPPERCASE")]
48#[cfg_attr(feature = "strum", strum(serialize_all = "UPPERCASE"))]
49pub enum PodStatus {
50    /// Pod is currently running and operational.
51    #[default]
52    Running,
53    /// Pod has finished execution and exited normally.
54    Exited,
55    /// Pod has been forcibly terminated or stopped.
56    Terminated,
57}
58
59/// Available CUDA versions for GPU Pods.
60///
61/// Specifies which CUDA runtime version should be available on the GPU Pod.
62/// This is only relevant for GPU Pods and determines software compatibility.
63#[derive(Debug, Clone, Default, Copy, PartialEq, Eq, Serialize, Deserialize)]
64pub enum CudaVersion {
65    /// CUDA version 13.0.
66    #[serde(rename = "13.0")]
67    V13_0,
68    /// CUDA version 12.9.
69    #[serde(rename = "12.9")]
70    V12_9,
71    /// CUDA version 12.8.
72    #[serde(rename = "12.8")]
73    V12_8,
74    /// CUDA version 12.7.
75    #[serde(rename = "12.7")]
76    V12_7,
77    /// CUDA version 12.6.
78    #[serde(rename = "12.6")]
79    V12_6,
80    /// CUDA version 12.5.
81    #[serde(rename = "12.5")]
82    V12_5,
83    /// CUDA version 12.4.
84    #[serde(rename = "12.4")]
85    V12_4,
86    /// CUDA version 12.3.
87    #[serde(rename = "12.3")]
88    V12_3,
89    /// CUDA version 12.2.
90    #[serde(rename = "12.2")]
91    V12_2,
92    /// CUDA version 12.1.
93    #[serde(rename = "12.1")]
94    V12_1,
95    /// CUDA version 12.0.
96    #[serde(rename = "12.0")]
97    #[default]
98    V12_0,
99    /// CUDA version 11.8.
100    #[serde(rename = "11.8")]
101    V11_8,
102}
103
104/// Available GPU hardware types for GPU Pods.
105///
106/// Represents the specific GPU models that can be attached to a Pod.
107/// Each GPU type has different performance characteristics, memory capacity,
108/// and pricing. The availability of each type varies by data center and time.
109#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
110pub enum GpuTypeId {
111    /// NVIDIA GeForce RTX 4090.
112    #[serde(rename = "NVIDIA GeForce RTX 4090")]
113    NvidiaGeForceRtx4090,
114    /// NVIDIA A40.
115    #[serde(rename = "NVIDIA A40")]
116    NvidiaA40,
117    /// NVIDIA RTX A5000.
118    #[serde(rename = "NVIDIA RTX A5000")]
119    NvidiaRtxA5000,
120    /// NVIDIA GeForce RTX 3090.
121    #[serde(rename = "NVIDIA GeForce RTX 3090")]
122    NvidiaGeForceRtx3090,
123    /// NVIDIA RTX A4500.
124    #[serde(rename = "NVIDIA RTX A4500")]
125    NvidiaRtxA4500,
126    /// NVIDIA RTX A6000.
127    #[serde(rename = "NVIDIA RTX A6000")]
128    NvidiaRtxA6000,
129    /// NVIDIA L40S.
130    #[serde(rename = "NVIDIA L40S")]
131    NvidiaL40S,
132    /// NVIDIA L4.
133    #[serde(rename = "NVIDIA L4")]
134    NvidiaL4,
135    /// NVIDIA H100 80GB HBM3.
136    #[serde(rename = "NVIDIA H100 80GB HBM3")]
137    NvidiaH100_80GbHbm3,
138    /// NVIDIA RTX 4000 Ada Generation.
139    #[serde(rename = "NVIDIA RTX 4000 Ada Generation")]
140    NvidiaRtx4000Ada,
141    /// NVIDIA A100 80GB PCIe.
142    #[serde(rename = "NVIDIA A100 80GB PCIe")]
143    NvidiaA100_80GbPcie,
144    /// NVIDIA A100-SXM4-80GB.
145    #[serde(rename = "NVIDIA A100-SXM4-80GB")]
146    NvidiaA100Sxm4_80Gb,
147    /// NVIDIA A100-SXM4-40GB.
148    #[serde(rename = "NVIDIA A100-SXM4-40GB")]
149    NvidiaA100Sxm4_40Gb,
150    /// NVIDIA RTX A4000.
151    #[serde(rename = "NVIDIA RTX A4000")]
152    NvidiaRtxA4000,
153    /// NVIDIA RTX 6000 Ada Generation.
154    #[serde(rename = "NVIDIA RTX 6000 Ada Generation")]
155    NvidiaRtx6000Ada,
156    /// NVIDIA RTX 2000 Ada Generation.
157    #[serde(rename = "NVIDIA RTX 2000 Ada Generation")]
158    NvidiaRtx2000Ada,
159    /// NVIDIA H200.
160    #[serde(rename = "NVIDIA H200")]
161    NvidiaH200,
162    /// NVIDIA L40.
163    #[serde(rename = "NVIDIA L40")]
164    NvidiaL40,
165    /// NVIDIA H100 NVL.
166    #[serde(rename = "NVIDIA H100 NVL")]
167    NvidiaH100Nvl,
168    /// NVIDIA H100 PCIe.
169    #[serde(rename = "NVIDIA H100 PCIe")]
170    NvidiaH100Pcie,
171    /// NVIDIA GeForce RTX 3080 Ti.
172    #[serde(rename = "NVIDIA GeForce RTX 3080 Ti")]
173    NvidiaGeForceRtx3080Ti,
174    /// NVIDIA GeForce RTX 3080.
175    #[serde(rename = "NVIDIA GeForce RTX 3080")]
176    NvidiaGeForceRtx3080,
177    /// NVIDIA GeForce RTX 3070.
178    #[serde(rename = "NVIDIA GeForce RTX 3070")]
179    NvidiaGeForceRtx3070,
180    /// Tesla V100-PCIE-16GB.
181    #[serde(rename = "Tesla V100-PCIE-16GB")]
182    TeslaV100Pcie16Gb,
183    /// Tesla V100-PCIE-32GB.
184    #[serde(rename = "Tesla V100-PCIE-32GB")]
185    TeslaV100Pcie32Gb,
186    /// Tesla T4.
187    #[serde(rename = "Tesla T4")]
188    TeslaT4,
189    /// AMD Instinct MI300X OAM.
190    #[serde(rename = "AMD Instinct MI300X OAM")]
191    AmdInstinctMi300XOam,
192    /// NVIDIA RTX A2000.
193    #[serde(rename = "NVIDIA RTX A2000")]
194    NvidiaRtxA2000,
195    /// NVIDIA RTX A30.
196    #[serde(rename = "NVIDIA RTX A30")]
197    NvidiaRtxA30,
198    /// Tesla V100-FHHL-16GB.
199    #[serde(rename = "Tesla V100-FHHL-16GB")]
200    TeslaV100Fhhl16Gb,
201    /// NVIDIA GeForce RTX 4080 SUPER.
202    #[serde(rename = "NVIDIA GeForce RTX 4080 SUPER")]
203    NvidiaGeForceRtx4080Super,
204    /// Tesla V100-SXM2-16GB.
205    #[serde(rename = "Tesla V100-SXM2-16GB")]
206    TeslaV100Sxm2_16Gb,
207    /// NVIDIA GeForce RTX 4070 Ti.
208    #[serde(rename = "NVIDIA GeForce RTX 4070 Ti")]
209    NvidiaGeForceRtx4070Ti,
210    /// Tesla V100-SXM2-32GB.
211    #[serde(rename = "Tesla V100-SXM2-32GB")]
212    TeslaV100Sxm2_32Gb,
213    /// NVIDIA RTX 4000 SFF Ada Generation.
214    #[serde(rename = "NVIDIA RTX 4000 SFF Ada Generation")]
215    NvidiaRtx4000SffAda,
216    /// NVIDIA RTX 5000 Ada Generation.
217    #[serde(rename = "NVIDIA RTX 5000 Ada Generation")]
218    NvidiaRtx5000Ada,
219    /// NVIDIA GeForce RTX 5090.
220    #[serde(rename = "NVIDIA GeForce RTX 5090")]
221    NvidiaGeForceRtx5090,
222    /// NVIDIA A30.
223    #[serde(rename = "NVIDIA A30")]
224    NvidiaA30,
225    /// NVIDIA GeForce RTX 4080.
226    #[serde(rename = "NVIDIA GeForce RTX 4080")]
227    NvidiaGeForceRtx4080,
228    /// NVIDIA GeForce RTX 5080.
229    #[serde(rename = "NVIDIA GeForce RTX 5080")]
230    NvidiaGeForceRtx5080,
231    /// NVIDIA GeForce RTX 3090 Ti.
232    #[serde(rename = "NVIDIA GeForce RTX 3090 Ti")]
233    NvidiaGeForceRtx3090Ti,
234    /// NVIDIA B200.
235    #[serde(rename = "NVIDIA B200")]
236    NvidiaB200,
237    /// Unknown or unsupported GPU hardware type.
238    #[default]
239    #[serde(other)]
240    Unknown,
241}
242
243impl std::fmt::Display for GpuTypeId {
244    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
245        let s = match self {
246            Self::Unknown => "Unknown",
247            Self::NvidiaGeForceRtx4090 => "NVIDIA GeForce RTX 4090",
248            Self::NvidiaA40 => "NVIDIA A40",
249            Self::NvidiaRtxA5000 => "NVIDIA RTX A5000",
250            Self::NvidiaGeForceRtx3090 => "NVIDIA GeForce RTX 3090",
251            Self::NvidiaRtxA4500 => "NVIDIA RTX A4500",
252            Self::NvidiaRtxA6000 => "NVIDIA RTX A6000",
253            Self::NvidiaL40S => "NVIDIA L40S",
254            Self::NvidiaL4 => "NVIDIA L4",
255            Self::NvidiaH100_80GbHbm3 => "NVIDIA H100 80GB HBM3",
256            Self::NvidiaRtx4000Ada => "NVIDIA RTX 4000 Ada Generation",
257            Self::NvidiaA100_80GbPcie => "NVIDIA A100 80GB PCIe",
258            Self::NvidiaA100Sxm4_80Gb => "NVIDIA A100-SXM4-80GB",
259            Self::NvidiaA100Sxm4_40Gb => "NVIDIA A100-SXM4-40GB",
260            Self::NvidiaRtxA4000 => "NVIDIA RTX A4000",
261            Self::NvidiaRtx6000Ada => "NVIDIA RTX 6000 Ada Generation",
262            Self::NvidiaRtx2000Ada => "NVIDIA RTX 2000 Ada Generation",
263            Self::NvidiaH200 => "NVIDIA H200",
264            Self::NvidiaL40 => "NVIDIA L40",
265            Self::NvidiaH100Nvl => "NVIDIA H100 NVL",
266            Self::NvidiaH100Pcie => "NVIDIA H100 PCIe",
267            Self::NvidiaGeForceRtx3080Ti => "NVIDIA GeForce RTX 3080 Ti",
268            Self::NvidiaGeForceRtx3080 => "NVIDIA GeForce RTX 3080",
269            Self::NvidiaGeForceRtx3070 => "NVIDIA GeForce RTX 3070",
270            Self::TeslaV100Pcie16Gb => "Tesla V100-PCIE-16GB",
271            Self::TeslaV100Pcie32Gb => "Tesla V100-PCIE-32GB",
272            Self::TeslaT4 => "Tesla T4",
273            Self::AmdInstinctMi300XOam => "AMD Instinct MI300X OAM",
274            Self::NvidiaRtxA2000 => "NVIDIA RTX A2000",
275            Self::NvidiaRtxA30 => "NVIDIA RTX A30",
276            Self::TeslaV100Fhhl16Gb => "Tesla V100-FHHL-16GB",
277            Self::NvidiaGeForceRtx4080Super => "NVIDIA GeForce RTX 4080 SUPER",
278            Self::TeslaV100Sxm2_16Gb => "Tesla V100-SXM2-16GB",
279            Self::NvidiaGeForceRtx4070Ti => "NVIDIA GeForce RTX 4070 Ti",
280            Self::TeslaV100Sxm2_32Gb => "Tesla V100-SXM2-32GB",
281            Self::NvidiaRtx4000SffAda => "NVIDIA RTX 4000 SFF Ada Generation",
282            Self::NvidiaRtx5000Ada => "NVIDIA RTX 5000 Ada Generation",
283            Self::NvidiaGeForceRtx5090 => "NVIDIA GeForce RTX 5090",
284            Self::NvidiaA30 => "NVIDIA A30",
285            Self::NvidiaGeForceRtx4080 => "NVIDIA GeForce RTX 4080",
286            Self::NvidiaGeForceRtx5080 => "NVIDIA GeForce RTX 5080",
287            Self::NvidiaGeForceRtx3090Ti => "NVIDIA GeForce RTX 3090 Ti",
288            Self::NvidiaB200 => "NVIDIA B200",
289        };
290        write!(f, "{}", s)
291    }
292}
293
294/// Available CPU flavor configurations for CPU Pods.
295///
296/// Represents different CPU configurations available for CPU-only Pods.
297/// Each flavor provides different combinations of cores, memory, and performance
298/// characteristics optimized for various workload types.
299#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
300#[serde(rename_all = "lowercase")]
301pub enum CpuFlavorId {
302    /// 3rd generation CPU configuration - compute optimized.
303    Cpu3c,
304    /// 3rd generation CPU configuration - general purpose.
305    Cpu3g,
306    /// 3rd generation CPU configuration - memory optimized.
307    Cpu3m,
308    /// 5th generation CPU configuration - compute optimized.
309    Cpu5c,
310    /// 5th generation CPU configuration - general purpose.
311    Cpu5g,
312    /// 5th generation CPU configuration - memory optimized.
313    Cpu5m,
314    /// Unknown or unsupported CPU flavor.
315    #[default]
316    #[serde(other)]
317    Unknown,
318}
319
320impl std::fmt::Display for CpuFlavorId {
321    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
322        let s = match self {
323            Self::Unknown => "unknown",
324            Self::Cpu3c => "cpu3c",
325            Self::Cpu3g => "cpu3g",
326            Self::Cpu3m => "cpu3m",
327            Self::Cpu5c => "cpu5c",
328            Self::Cpu5g => "cpu5g",
329            Self::Cpu5m => "cpu5m",
330        };
331        write!(f, "{}", s)
332    }
333}
334
335/// RunPod data center locations.
336///
337/// Represents the geographic locations where RunPod has data centers.
338/// The choice of data center affects latency, regulatory compliance,
339/// and resource availability. Costs may also vary by location.
340#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
341pub enum DataCenterId {
342    /// Romania (EU-RO-1).
343    #[serde(rename = "EU-RO-1")]
344    EuRo1,
345    /// Montreal, Canada (CA-MTL-1).
346    #[serde(rename = "CA-MTL-1")]
347    CaMtl1,
348    /// Sweden (EU-SE-1).
349    #[serde(rename = "EU-SE-1")]
350    EuSe1,
351    /// Illinois, USA (US-IL-1).
352    #[serde(rename = "US-IL-1")]
353    UsIl1,
354    /// Iceland (EUR-IS-1).
355    #[serde(rename = "EUR-IS-1")]
356    EurIs1,
357    /// Czech Republic (EU-CZ-1).
358    #[serde(rename = "EU-CZ-1")]
359    EuCz1,
360    /// Texas, USA (US-TX-3).
361    #[serde(rename = "US-TX-3")]
362    UsTx3,
363    /// Iceland (EUR-IS-2).
364    #[serde(rename = "EUR-IS-2")]
365    EurIs2,
366    /// Kansas, USA (US-KS-2).
367    #[serde(rename = "US-KS-2")]
368    UsKs2,
369    /// Georgia, USA (US-GA-2).
370    #[serde(rename = "US-GA-2")]
371    UsGa2,
372    /// Washington, USA (US-WA-1).
373    #[serde(rename = "US-WA-1")]
374    UsWa1,
375    /// Texas, USA (US-TX-1).
376    #[serde(rename = "US-TX-1")]
377    UsTx1,
378    /// Montreal, Canada (CA-MTL-3).
379    #[serde(rename = "CA-MTL-3")]
380    CaMtl3,
381    /// Netherlands (EU-NL-1).
382    #[serde(rename = "EU-NL-1")]
383    EuNl1,
384    /// Texas, USA (US-TX-4).
385    #[serde(rename = "US-TX-4")]
386    UsTx4,
387    /// California, USA (US-CA-2).
388    #[serde(rename = "US-CA-2")]
389    UsCa2,
390    /// North Carolina, USA (US-NC-1).
391    #[serde(rename = "US-NC-1")]
392    UsNc1,
393    /// Australia (OC-AU-1).
394    #[serde(rename = "OC-AU-1")]
395    OcAu1,
396    /// Delaware, USA (US-DE-1).
397    #[serde(rename = "US-DE-1")]
398    UsDe1,
399    /// Iceland (EUR-IS-3).
400    #[serde(rename = "EUR-IS-3")]
401    EurIs3,
402    /// Montreal, Canada (CA-MTL-2).
403    #[serde(rename = "CA-MTL-2")]
404    CaMtl2,
405    /// Japan (AP-JP-1).
406    #[serde(rename = "AP-JP-1")]
407    ApJp1,
408    /// Norway (EUR-NO-1).
409    #[serde(rename = "EUR-NO-1")]
410    EurNo1,
411    /// France (EU-FR-1).
412    #[serde(rename = "EU-FR-1")]
413    EuFr1,
414    /// Kansas, USA (US-KS-3).
415    #[serde(rename = "US-KS-3")]
416    UsKs3,
417    /// Georgia, USA (US-GA-1).
418    #[serde(rename = "US-GA-1")]
419    UsGa1,
420    /// India (AP-IN-1).
421    #[serde(rename = "AP-IN-1")]
422    ApIn1,
423    /// Maryland, USA (US-MD-1).
424    #[serde(rename = "US-MD-1")]
425    UsMd1,
426    /// Unknown or unsupported data center region.
427    #[default]
428    #[serde(other)]
429    Unknown,
430}
431
432impl std::fmt::Display for DataCenterId {
433    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
434        let s = match self {
435            Self::Unknown => "Unknown",
436            Self::EuRo1 => "EU-RO-1",
437            Self::CaMtl1 => "CA-MTL-1",
438            Self::EuSe1 => "EU-SE-1",
439            Self::UsIl1 => "US-IL-1",
440            Self::EurIs1 => "EUR-IS-1",
441            Self::EuCz1 => "EU-CZ-1",
442            Self::UsTx3 => "US-TX-3",
443            Self::EurIs2 => "EUR-IS-2",
444            Self::UsKs2 => "US-KS-2",
445            Self::UsGa2 => "US-GA-2",
446            Self::UsWa1 => "US-WA-1",
447            Self::UsTx1 => "US-TX-1",
448            Self::CaMtl3 => "CA-MTL-3",
449            Self::EuNl1 => "EU-NL-1",
450            Self::UsTx4 => "US-TX-4",
451            Self::UsCa2 => "US-CA-2",
452            Self::UsNc1 => "US-NC-1",
453            Self::OcAu1 => "OC-AU-1",
454            Self::UsDe1 => "US-DE-1",
455            Self::EurIs3 => "EUR-IS-3",
456            Self::CaMtl2 => "CA-MTL-2",
457            Self::ApJp1 => "AP-JP-1",
458            Self::EurNo1 => "EUR-NO-1",
459            Self::EuFr1 => "EU-FR-1",
460            Self::UsKs3 => "US-KS-3",
461            Self::UsGa1 => "US-GA-1",
462            Self::ApIn1 => "AP-IN-1",
463            Self::UsMd1 => "US-MD-1",
464        };
465        write!(f, "{}", s)
466    }
467}
468
469/// Detailed information about GPU resources attached to a Pod.
470///
471/// Contains comprehensive details about the GPU configuration including
472/// hardware specifications, pricing across different billing periods,
473/// and availability in different cloud types.
474#[derive(Debug, Clone, Serialize, Deserialize)]
475#[serde(rename_all = "camelCase")]
476pub struct GpuInfo {
477    /// Unique identifier for this GPU type.
478    pub id: String,
479    /// Number of GPUs of this type attached to the Pod.
480    pub count: i32,
481    /// Human-readable display name for the GPU type.
482    pub display_name: String,
483    /// Hourly price per GPU in RunPod credits for Secure Cloud.
484    pub secure_price: f64,
485    /// Hourly price per GPU in RunPod credits for Community Cloud.
486    pub community_price: f64,
487    /// Monthly rate per GPU in RunPod credits (30-day billing).
488    pub one_month_price: f64,
489    /// Quarterly rate per GPU in RunPod credits (90-day billing).
490    pub three_month_price: f64,
491    /// Semi-annual rate per GPU in RunPod credits (180-day billing).
492    pub six_month_price: f64,
493    /// Weekly rate per GPU in RunPod credits (7-day billing).
494    pub one_week_price: f64,
495    /// Spot pricing per GPU hour in RunPod credits for Community Cloud.
496    pub community_spot_price: f64,
497    /// Spot pricing per GPU hour in RunPod credits for Secure Cloud.
498    pub secure_spot_price: f64,
499}
500
501/// Detailed information about CPU resources for a Pod.
502///
503/// Contains specifications about the CPU configuration including
504/// core count, threading capabilities, and organizational grouping.
505#[derive(Debug, Clone, Serialize, Deserialize)]
506#[serde(rename_all = "camelCase")]
507pub struct CpuType {
508    /// Unique identifier for this CPU type.
509    pub id: String,
510    /// Human-readable display name for the CPU type.
511    pub display_name: String,
512    /// Number of physical CPU cores available.
513    pub cores: f64,
514    /// Number of threads supported per physical core.
515    pub threads_per_core: f64,
516    /// Group identifier for organizing similar CPU types.
517    pub group_id: String,
518}
519
520/// Detailed information about the physical machine hosting a Pod.
521///
522/// Contains comprehensive details about the hardware infrastructure,
523/// networking capabilities, pricing, and operational status of the
524/// machine where the Pod is running.
525#[derive(Debug, Clone, Serialize, Deserialize)]
526#[serde(rename_all = "camelCase")]
527pub struct Machine {
528    /// Minimum number of GPUs required for Pods on this machine.
529    pub min_pod_gpu_count: Option<i32>,
530    /// Identifier for the GPU type available on this machine.
531    pub gpu_type_id: Option<String>,
532    /// Detailed information about the GPU type on this machine.
533    pub gpu_type: Option<GpuInfo>,
534    /// Total number of CPU cores available on this machine.
535    pub cpu_count: Option<i32>,
536    /// Identifier for the CPU type on this machine.
537    pub cpu_type_id: Option<String>,
538    /// Detailed information about the CPU type on this machine.
539    pub cpu_type: Option<CpuType>,
540    /// Geographic location description of this machine.
541    #[serde(default)]
542    pub location: String,
543    /// Data center identifier where this machine is located.
544    #[serde(default)]
545    pub data_center_id: String,
546    /// Disk I/O throughput capacity in megabytes per second.
547    pub disk_throughput_m_bps: Option<i32>,
548    /// Maximum network download speed in megabits per second.
549    pub max_download_speed_mbps: Option<i32>,
550    /// Maximum network upload speed in megabits per second.
551    pub max_upload_speed_mbps: Option<i32>,
552    /// Whether this machine supports public IP assignment.
553    #[serde(default)]
554    pub support_public_ip: bool,
555    /// Whether this machine is in the Secure Cloud environment.
556    #[serde(default)]
557    pub secure_cloud: bool,
558    /// Scheduled maintenance start time, if any.
559    pub maintenance_start: Option<String>,
560    /// Scheduled maintenance end time, if any.
561    pub maintenance_end: Option<String>,
562    /// Additional information about scheduled maintenance.
563    pub maintenance_note: Option<String>,
564    /// General notes or information about this machine.
565    pub note: Option<String>,
566    /// Current hourly cost in RunPod credits for this machine.
567    #[serde(default)]
568    pub cost_per_hr: f64,
569    /// Current price per GPU hour in RunPod credits, if applicable.
570    pub current_price_per_gpu: Option<f64>,
571    /// Number of GPUs currently available on this machine.
572    pub gpu_available: Option<i32>,
573    /// Human-readable name of the GPU type on this machine.
574    pub gpu_display_name: Option<String>,
575}
576
577/// A savings plan applied to reduce Pod costs.
578///
579/// Savings plans offer discounted pricing in exchange for longer-term
580/// commitments to specific GPU types. They automatically apply to
581/// eligible Pods to reduce the effective hourly cost.
582#[derive(Debug, Clone, Serialize, Deserialize)]
583#[serde(rename_all = "camelCase")]
584pub struct SavingsPlan {
585    /// Discounted hourly cost per GPU in RunPod credits.
586    pub cost_per_hr: f64,
587    /// UTC timestamp when this savings plan expires.
588    pub end_time: String,
589    /// GPU type identifier that this savings plan applies to.
590    pub gpu_type_id: String,
591    /// Unique identifier for this savings plan.
592    pub id: String,
593    /// Pod identifier that this savings plan is currently applied to.
594    pub pod_id: String,
595    /// UTC timestamp when this savings plan became active.
596    pub start_time: String,
597}
598
599/// A persistent network-attached storage volume.
600///
601/// Network volumes provide persistent storage that can be shared across
602/// multiple Pods and persists beyond individual Pod lifecycles. They are
603/// located in specific data centers and can be mounted to Pods in the same region.
604#[derive(Debug, Clone, Serialize, Deserialize)]
605#[serde(rename_all = "camelCase")]
606pub struct NetworkVolume {
607    /// Unique identifier for this network volume.
608    pub id: String,
609    /// User-defined name for this network volume.
610    pub name: String,
611    /// Storage capacity of this volume in gigabytes.
612    pub size: i32,
613    /// Data center where this network volume is located.
614    pub data_center_id: String,
615}
616
617/// Environment variables for Pod containers.
618///
619/// A key-value mapping of environment variables that will be set
620/// in the Pod's container runtime environment.
621pub type EnvVars = HashMap<String, String>;
622
623/// Port mappings from internal to external ports.
624///
625/// Maps internal container ports (as strings) to external public ports
626/// (as integers) for network access to the Pod.
627pub type PortMappings = HashMap<String, i32>;
628
629#[cfg(test)]
630mod tests {
631    use super::*;
632
633    #[test]
634    fn test_machine_deserialization_from_empty_json() {
635        let m: Machine = serde_json::from_str("{}").expect("empty machine should work");
636        assert_eq!(m.location, "");
637        assert_eq!(m.data_center_id, "");
638        assert!(!m.support_public_ip);
639        assert!(!m.secure_cloud);
640        assert_eq!(m.cost_per_hr, 0.0);
641    }
642}