1pub mod api;
2pub mod apiextensions_apiserver;
3pub mod apimachinery;
4pub mod kube_aggregator;
5pub mod metrics;
6
7use serde::{Deserialize, Serialize};
8use protobuf::MessageField;
9
10#[derive(Serialize, Deserialize)]
11#[serde(remote = "MessageField")]
12pub struct MessageFieldDef<T>(pub Option<Box<T>>); pub mod custom_date {
16 use serde::{Deserialize, Deserializer, Serialize, Serializer};
17 use super::apimachinery::pkg::apis::meta::v1::Duration;
18
19 use super::apimachinery::pkg::apis::meta::v1::Time as TimePb;
20 use chrono::DateTime;
21
22 impl Serialize for Duration {
23 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
24 where
25 S: Serializer {
26 serializer.serialize_i64(self.duration())
27 }
28 }
29
30 impl <'de> Deserialize <'de> for Duration {
31 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
32 where
33 D: Deserializer<'de> {
34 let value = String::deserialize(deserializer).unwrap();
35
36 let (d, _) = value.split_once("s").unwrap();
37
38 match d.parse::<i64>() {
39 Ok(val) => {
40 let mut dur = Duration::new();
41
42 dur.set_duration(val);
43
44 Ok(dur)
45 },
46 Err(e) => {
47 if e.to_string().contains("invalid digit") {
48 let mut dur = Duration::new();
49
50 let val = d.parse::<f64>().unwrap();
51
52 dur.set_duration(val as i64);
53
54 return Ok(dur);
55 }
56 Err(serde::de::Error::custom(e.to_string()))
57 }
58 }
59 }
60 }
61
62 impl Serialize for TimePb {
63 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
64 where S: Serializer {
65 let value = DateTime::from_timestamp(self.seconds(), self.nanos() as u32).unwrap();
66
67 serializer.serialize_str(&value.to_rfc3339())
68 }
69 }
70
71 impl <'de> Deserialize <'de> for TimePb {
72 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
73 where
74 D: Deserializer<'de> {
75 let time_as_str = String::deserialize(deserializer).unwrap_or_default();
76 match DateTime::parse_from_rfc3339(&time_as_str) {
77 Ok(val) => {
78 let secs = val.timestamp();
79 let nanos = val.timestamp_subsec_nanos();
80
81 let mut new_time = TimePb::new();
82
83 new_time.set_seconds(secs);
84 new_time.set_nanos(nanos as i32);
85
86 Ok(new_time)
87 },
88 Err(err) => {
89 eprintln!("parse error: {}", err);
90
91 let def_time = TimePb::default();
92
93 Ok(def_time)
94 },
95 }
96 }
97 }
98}
99
100pub mod intorstr {
101 use std::fmt;
102 use protobuf::MessageField;
103 use serde::{de::Visitor, Deserializer};
104 use super::apimachinery::pkg::util::intstr::IntOrString;
105
106 pub fn deserialize<'de, D>(deserializer: D) -> Result<::protobuf::MessageField<IntOrString>, D::Error>
107 where
108 D: Deserializer<'de>,
109 {
110 struct IntOrStringVisitor;
111
112 impl <'de> Visitor<'de> for IntOrStringVisitor {
113
114 type Value = MessageField<IntOrString>;
115
116 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> std::fmt::Result {
117 formatter.write_str("int or string")
118 }
119
120 fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
121 where
122 E: serde::de::Error,
123 {
124 let mut int_or_str = IntOrString::new();
125 int_or_str.set_type(v);
126
127 let mes = MessageField::some(int_or_str);
128
129 Ok(mes)
130
131 }
132
133 fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
134 where
135 E: serde::de::Error,
136 {
137 let mut int_or_str = IntOrString::new();
138 int_or_str.set_intVal(v);
139
140 let mes = MessageField::some(int_or_str);
141
142 Ok(mes)
143 }
144
145 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
147 where
148 E: serde::de::Error,
149 {
150 let mut int_or_str = IntOrString::new();
151 int_or_str.set_type(v as i64);
152
153 let mes = MessageField::some(int_or_str);
154
155 Ok(mes)
156 }
157
158 fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
159 where
160 E: serde::de::Error,
161 {
162 let mut int_or_str = IntOrString::new();
163 int_or_str.set_intVal(v as i32);
164
165 let mes = MessageField::some(int_or_str);
166
167 Ok(mes)
168 }
169
170 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
171 where
172 E: serde::de::Error,
173 {
174 let mut int_or_str = IntOrString::new();
175 int_or_str.set_strVal(v.to_owned());
176
177 let mes = MessageField::some(int_or_str);
178
179 Ok(mes)
180 }
181 }
182
183 deserializer.deserialize_any(IntOrStringVisitor)
184 }
185}
186
187pub mod quantity_parse {
188 use std::collections::BTreeMap;
189
190 use serde::{Deserialize, Deserializer, Serialize, Serializer};
191
192 use crate::apimachinery::pkg::api::resource::Quantity;
193
194 pub fn deserialize<'de, D>(deserializer: D) -> Result<::std::collections::BTreeMap<::std::string::String, crate::apimachinery::pkg::api::resource::Quantity>, D::Error>
195 where
196 D: Deserializer<'de>,
197 {
198 let map_iter: BTreeMap<String, String> = BTreeMap::deserialize(deserializer).unwrap_or_default();
199 let mut new_map: BTreeMap<String, crate::apimachinery::pkg::api::resource::Quantity> = BTreeMap::new();
200
201 if map_iter.len() > 0 {
202 for (k, v) in map_iter.iter() {
203 let mut quantity = Quantity::new();
204 quantity.set_string(v.to_string());
205 new_map.insert(k.to_string(), quantity);
206 }
207
208 Ok(new_map)
209 } else {
210 Ok(new_map)
211 }
212 }
213
214 impl Serialize for Quantity {
215 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
216 where
217 S: Serializer {
218 serializer.serialize_newtype_struct("Quantity", &self.string.as_ref().unwrap().to_string())
219 }
220 }
221
222 impl <'de> Deserialize<'de> for Quantity {
223 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
224 where
225 D: Deserializer<'de> {
226 let subtype = vec!["u", "m", "n", "Mi", "Ki", "Gi"];
227
228 let inc_value = String::deserialize(deserializer).unwrap();
229
230 let mut quantity = Quantity::new();
231
232 if containe_subtype(&inc_value, subtype) {
233 quantity.set_string(convert_incoming_quantity(&inc_value));
234 Ok(quantity)
235 } else {
236 quantity.set_string(inc_value);
237 Ok(quantity)
238 }
239 }
240 }
241
242 fn containe_subtype(value: &str, subtypes: Vec<&str>) -> bool {
243 subtypes.iter().any(|&substring| value.contains(substring))
244 }
245
246 fn convert_incoming_quantity(value: &str) -> String {
247 if value.contains("Ki") {
248 let (v, _) = value.split_once("Ki").unwrap();
249 return format!("{:.1}MB", kib_to_mb(v.parse::<f64>().unwrap()))
250 }
251 if value.contains("Mi") {
252 let (v, _) = value.split_once("Mi").unwrap();
253 return format!("{:.1}MB", mib_to_mb(v.parse::<f64>().unwrap()))
254 }
255 if value.contains("Gi") {
256 let (v, _) = value.split_once("Gi").unwrap();
257 return format!("{:.1}GB", gib_to_gb(v.parse::<f64>().unwrap()))
258 }
259 if value.contains("n") {
260 let (v, _) = value.split_once("n").unwrap();
261 return format!("{:.5}", from_nano_cpu(v.parse::<f64>().unwrap()))
262 }
263 if value.contains("m") {
264 let (v, _) = value.split_once("m").unwrap();
265 return format!("{:.5}", from_micro_cpu(v.parse::<f64>().unwrap()))
266 }
267 if value.contains("u") {
268 let (v, _) = value.split_once("u").unwrap();
269 return format!("{:.5}", from_milli_cpu(v.parse::<f64>().unwrap()))
270 }
271
272 value.parse::<f64>().unwrap().to_string()
273 }
274
275 fn from_nano_cpu(v: f64) -> f64 {
276 v / 1_000_000_000.0
277 }
278
279 fn from_micro_cpu(v: f64) -> f64 {
280 v / 1_000_000.0
281 }
282
283 fn from_milli_cpu(v: f64) -> f64 {
284 v / 1_000.0
285 }
286
287 fn kib_to_mb(val: f64) -> f64 {
288 (val * 1024.0) / 1_000_000.0
289 }
290
291 fn mib_to_mb(val: f64) -> f64 {
292 val * 1.048576
294 }
295
296 fn gib_to_gb(val: f64) -> f64 {
297 val * 1.073741824
299 }
300}
301
302pub mod converter {
304 use std::io;
305
306 use serde::{de::DeserializeOwned, Serialize};
307
308 pub fn from_openapi<P, T>(val: T) -> Result<P, io::Error>
320 where
321 T: Serialize,
322 P: DeserializeOwned
323 {
324 let to_val_pb = serde_json::to_value(val)?;
325
326 let pb_value: P = serde_json::from_value(to_val_pb)?;
327
328 Ok(pb_value)
329 }
330
331 }
343
344
345#[cfg(test)]
346mod tests {
347 use std::fs;
348
349 use api::{apps::v1::DeploymentList, core::v1::{Event, Node, Pod, PodList}};
350 use k8s_openapi::api::core::v1::{Event as OtherEvent, Node as OtherNode, Pod as OtherPod};
351
352 use crate::metrics::pkg::apis::metrics::v1beta1::{NodeMetrics, PodMetrics};
353
354 use super::*;
355
356 #[test]
357 fn succesfully_des() {
358 let pod_tt = OtherPod::default();
359
360 let pod_x: Pod = converter::from_openapi(pod_tt).unwrap();
361
362 assert_eq!(pod_x.has_metadata(), true);
363
364 let node_tt = OtherNode::default();
365
366 let node_x: Node = converter::from_openapi(node_tt).unwrap();
367
368 assert_eq!(node_x.has_metadata(), true);
369
370 }
372
373 #[test]
374 fn success_metrics_node() {
375 let node = fs::read_to_string("testdata/node_metrics.json").unwrap();
376
377 let _nd: NodeMetrics = serde_json::from_str(&node).unwrap();
378 }
379
380 #[test]
381 fn succes_metrics_pod() {
382 let pod = fs::read_to_string("testdata/etcd_metrics.json").unwrap();
383
384 let _x: PodMetrics = serde_json::from_str(&pod).unwrap();
385 }
386
387 #[test]
388 #[should_panic]
389 fn bad_des() {
390 let asadsd = String::from("ASDASDASD");
391
392 let _px: PodList = converter::from_openapi(asadsd).unwrap();
393 }
394
395 #[test]
396 fn succesfully_des_with_serde_from_str() {
397 let pd_list = fs::read_to_string("testdata/podlist.json").unwrap();
398
399 let mut pb_pd_list: PodList = serde_json::from_str(&pd_list).unwrap();
400
401 let items = pb_pd_list.take_items();
402
403 assert_eq!(pb_pd_list.has_metadata(), true);
404 assert_eq!(items.is_empty(), false);
405
406 let pd = fs::read_to_string("testdata/pod.json").unwrap();
407
408 let pb_pd: Pod = serde_json::from_str(&pd).unwrap();
409
410 assert_eq!(pb_pd.has_metadata(), true);
411 assert_eq!(pb_pd.has_spec(), true);
412 assert_eq!(pb_pd.has_status(), true);
413
414 let dp_list = fs::read_to_string("testdata/deploy.json").unwrap();
416
417 let x: DeploymentList = serde_json::from_str(&dp_list).unwrap();
418
419 println!{"{:#?}", x};
420
421 assert_eq!(x.has_metadata(), true);
422 }
423
424 #[test]
425 fn event_des() {
426 let open_event = OtherEvent::default();
427
428 let pb_event: Event = converter::from_openapi(open_event).unwrap();
429
430 assert_eq!(pb_event.has_metadata(), true);
431 }
432}