1use aws_sdk_route53::types::RrType;
2use serde::{Deserialize, Serialize};
3use std::fmt;
4
5#[derive(Debug, Clone, PartialEq, Eq, Copy, Serialize, Deserialize)]
7pub enum RecordType {
8 A,
9 NS,
10 SOA,
11 TXT,
12}
13
14impl From<&str> for RecordType {
15 fn from(s: &str) -> Self {
16 match s {
17 "A" => Self::A,
18 "NS" => Self::NS,
19 "SOA" => Self::SOA,
20 "TXT" => Self::TXT,
21 _ => panic!("Invalid record type: {s}"),
22 }
23 }
24}
25
26impl From<RrType> for RecordType {
27 fn from(rr_type: RrType) -> Self {
28 match rr_type {
29 RrType::A => Self::A,
30 RrType::Ns => Self::NS,
31 RrType::Soa => Self::SOA,
32 RrType::Txt => Self::TXT,
33 _ => panic!("Invalid record type: {rr_type}"),
34 }
35 }
36}
37
38impl From<RecordType> for RrType {
39 fn from(value: RecordType) -> Self {
40 match value {
41 RecordType::A => Self::A,
42 RecordType::NS => Self::Ns,
43 RecordType::SOA => Self::Soa,
44 RecordType::TXT => Self::Txt,
45 }
46 }
47}
48
49impl RecordType {
50 pub fn as_str(&self) -> &str {
51 match self {
52 RecordType::A => "A",
53 RecordType::NS => "NS",
54 RecordType::SOA => "SOA",
55 RecordType::TXT => "TXT",
56 }
57 }
58}
59
60impl fmt::Display for RecordType {
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62 f.write_str(self.as_str())
63 }
64}
65
66#[derive(Debug, PartialEq, Eq)]
68pub struct InstanceInfo {
69 pub cpus: u32,
71 pub memory: u64,
73}
74
75#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
76pub enum InstanceType {
77 T3Nano,
78 T3Micro,
79 T3Small,
80 T3Medium,
81 T3Large,
82 T3Xlarge,
83 T32xlarge,
84}
85
86impl InstanceType {
87 pub fn as_str(&self) -> &str {
88 match self {
89 InstanceType::T3Nano => "t3.nano",
90 InstanceType::T3Micro => "t3.micro",
91 InstanceType::T3Small => "t3.small",
92 InstanceType::T3Medium => "t3.medium",
93 InstanceType::T3Large => "t3.large",
94 InstanceType::T3Xlarge => "t3.xlarge",
95 InstanceType::T32xlarge => "t3.2xlarge",
96 }
97 }
98
99 pub fn from_resources(cpus: u32, memory: u64) -> Option<Self> {
102 let instances = [
103 Self::T3Nano,
104 Self::T3Micro,
105 Self::T3Small,
106 Self::T3Medium,
107 Self::T3Large,
108 Self::T3Xlarge,
109 Self::T32xlarge,
110 ];
111
112 for instance in instances {
113 let info = instance.get_info();
114 if cpus <= info.cpus && memory <= info.memory {
115 return Some(instance);
116 }
117 }
118
119 None
120 }
121
122 pub fn get_info(&self) -> InstanceInfo {
123 match self {
124 Self::T3Nano => InstanceInfo {
125 cpus: 2000,
126 memory: 512,
127 },
128 Self::T3Micro => InstanceInfo {
129 cpus: 2000,
130 memory: 1024,
131 },
132 Self::T3Small => InstanceInfo {
133 cpus: 2000,
134 memory: 2048,
135 },
136 Self::T3Medium => InstanceInfo {
137 cpus: 2000,
138 memory: 4096,
139 },
140 Self::T3Large => InstanceInfo {
141 cpus: 2000,
142 memory: 8192,
143 },
144 Self::T3Xlarge => InstanceInfo {
145 cpus: 4000,
146 memory: 16384,
147 },
148 Self::T32xlarge => InstanceInfo {
149 cpus: 8000,
150 memory: 32768,
151 },
152 }
153 }
154}
155
156impl From<&str> for InstanceType {
157 fn from(value: &str) -> Self {
163 match value {
164 "t3.nano" => Self::T3Nano,
165 "t3.micro" => Self::T3Micro,
166 "t3.small" => Self::T3Small,
167 "t3.medium" => Self::T3Medium,
168 "t3.large" => Self::T3Large,
169 "t3.xlarge" => Self::T3Xlarge,
170 "t3.2xlarge" => Self::T32xlarge,
171 _ => panic!("Invalid instance type: {value}"),
172 }
173 }
174}
175
176#[cfg(test)]
177mod tests {
178 use aws_sdk_route53::types::RrType;
179
180 use super::*;
181
182 #[test]
183 fn test_display() {
184 assert_eq!(RecordType::A.to_string(), "A");
185 assert_eq!(RecordType::NS.to_string(), "NS");
186 assert_eq!(RecordType::SOA.to_string(), "SOA");
187 assert_eq!(RecordType::TXT.to_string(), "TXT");
188 }
189
190 #[test]
191 fn test_rr_type_from_record_type() {
192 assert_eq!(RrType::from(RecordType::A), RrType::A);
193 assert_eq!(RrType::from(RecordType::NS), RrType::Ns);
194 assert_eq!(RrType::from(RecordType::SOA), RrType::Soa);
195 assert_eq!(RrType::from(RecordType::TXT), RrType::Txt);
196 }
197
198 #[test]
199 fn test_record_type_from_str() {
200 assert_eq!(RecordType::from("A"), RecordType::A);
201 assert_eq!(RecordType::from("NS"), RecordType::NS);
202 assert_eq!(RecordType::from("SOA"), RecordType::SOA);
203 assert_eq!(RecordType::from("TXT"), RecordType::TXT);
204 }
205
206 #[test]
207 #[should_panic(expected = "Invalid record type: invalid")]
208 fn test_record_type_from_str_invalid() {
209 let _ = RecordType::from("invalid");
210 }
211
212 #[test]
213 fn test_record_type_from_rr_type() {
214 assert_eq!(
215 RecordType::from(aws_sdk_route53::types::RrType::A),
216 RecordType::A
217 );
218 assert_eq!(
219 RecordType::from(aws_sdk_route53::types::RrType::Ns),
220 RecordType::NS
221 );
222 assert_eq!(
223 RecordType::from(aws_sdk_route53::types::RrType::Soa),
224 RecordType::SOA
225 );
226 assert_eq!(
227 RecordType::from(aws_sdk_route53::types::RrType::Txt),
228 RecordType::TXT
229 );
230 }
231 #[test]
232 #[should_panic(expected = "Invalid record type: AAAA")]
233 fn test_record_type_from_rr_type_invalid() {
234 let _ = RecordType::from(aws_sdk_route53::types::RrType::Aaaa);
235 }
236
237 #[test]
238 fn test_record_type_as_str() {
239 assert_eq!(RecordType::A.as_str(), "A");
240 assert_eq!(RecordType::NS.as_str(), "NS");
241 assert_eq!(RecordType::SOA.as_str(), "SOA");
242 assert_eq!(RecordType::TXT.as_str(), "TXT");
243 }
244
245 #[test]
246 fn test_instance_type_as_str() {
247 assert_eq!(InstanceType::T3Nano.as_str(), "t3.nano");
248 assert_eq!(InstanceType::T32xlarge.as_str(), "t3.2xlarge");
249 }
250
251 #[test]
252 fn test_instance_type_get_info() {
253 assert_eq!(
254 InstanceType::T3Nano.get_info(),
255 InstanceInfo {
256 cpus: 2000,
257 memory: 512
258 }
259 );
260 assert_eq!(
261 InstanceType::T32xlarge.get_info(),
262 InstanceInfo {
263 cpus: 8000,
264 memory: 32768
265 }
266 );
267 }
268
269 #[test]
270 fn test_instance_type_from_str() {
271 assert_eq!(InstanceType::from("t3.nano"), InstanceType::T3Nano);
272 assert_eq!(InstanceType::from("t3.2xlarge"), InstanceType::T32xlarge);
273 }
274
275 #[test]
276 #[should_panic(expected = "Invalid instance type: invalid")]
277 fn test_instance_type_from_str_invalid() {
278 let _ = InstanceType::from("invalid");
279 }
280
281 #[test]
282 fn test_from_resources_fits_t3_nano_small_request() {
283 assert_eq!(
284 InstanceType::from_resources(500, 512),
285 Some(InstanceType::T3Nano)
286 );
287 }
288
289 #[test]
290 fn test_from_resources_fits_t3_nano_exact_request() {
291 assert_eq!(
292 InstanceType::from_resources(2000, 512),
293 Some(InstanceType::T3Nano)
294 );
295 }
296
297 #[test]
298 fn test_from_resources_fits_t3_micro_mem_overflow() {
299 assert_eq!(
300 InstanceType::from_resources(2000, 513),
301 Some(InstanceType::T3Micro)
302 );
303 }
304
305 #[test]
306 fn test_from_resources_fits_t3_medium_cpu_overflow() {
307 assert_eq!(
308 InstanceType::from_resources(2001, 8192),
309 Some(InstanceType::T3Xlarge)
310 );
311 }
312
313 #[test]
314 fn test_from_resources_fits_t3_xlarge_exact() {
315 assert_eq!(
316 InstanceType::from_resources(4000, 16384),
317 Some(InstanceType::T3Xlarge)
318 );
319 }
320
321 #[test]
322 fn test_from_resources_fits_t3_2xlarge_mem_overflow() {
323 assert_eq!(
324 InstanceType::from_resources(4000, 16385),
325 Some(InstanceType::T32xlarge)
326 );
327 }
328
329 #[test]
330 fn test_from_resources_fits_t3_2xlarge_exact_request() {
331 assert_eq!(
332 InstanceType::from_resources(8000, 32768),
333 Some(InstanceType::T32xlarge)
334 );
335 }
336
337 #[test]
338 fn test_from_resources_no_fit_cpu_overflow() {
339 assert_eq!(InstanceType::from_resources(8001, 32768), None);
340 }
341
342 #[test]
343 fn test_from_resources_no_fit_mem_overflow() {
344 assert_eq!(InstanceType::from_resources(8000, 32769), None);
345 }
346
347 #[test]
348 fn test_from_resources_no_fit_large_request() {
349 assert_eq!(InstanceType::from_resources(u32::MAX, u64::MAX), None);
350 }
351}