k8s_rs_pb/
lib.rs

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>>); // dont touch
13
14
15pub 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            // GitHub issue https://github.com/serde-rs/serde/issues/1162#issuecomment-367955753
146            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        // 1 MiB = 1.048576 MB
293        val * 1.048576
294    }
295    
296    fn gib_to_gb(val: f64) -> f64 {
297        // 1 GiB = 1.073741824 GB
298        val * 1.073741824
299    }
300}
301
302/// Converter pub
303pub mod converter {
304    use std::io;
305
306    use serde::{de::DeserializeOwned, Serialize};
307
308    /// Function for convertion from k8s_openapi to rust-protobuf
309    /// # Example
310    /// 
311    /// ``` 
312    /// use k8s_rs_pb::api::core::v1::Pod;
313    /// use k8s_openapi::api::core::v1::Pod as OtherPod;
314    /// 
315    /// let pod_openapi = OtherPod::default();
316    /// let pod_pb: Pod = k8s_rs_pb::converter::from_openapi(pod_openapi).unwrap();
317    /// assert_eq!(pod_pb.has_metadata(), true);
318    /// ```
319    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    // pub fn to_openapi<T, P>(val: P) -> Result<T, io::Error> 
332    // where 
333    //     T: DeserializeOwned,
334    //     P: Serialize
335    // {
336    //     let val_pb = serde_json::to_value(val).unwrap();
337
338    //     let openapi_value: T = serde_json::from_value(val_pb).unwrap();
339
340    //     Ok(openapi_value)
341    // }
342}
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        // let dpl = ObjectList<Deployment>;
371    }
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        //close bug with MessageField<IntOrString>
415        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}