blob: 7c3d6b74eaf65862ef9a4cbcddc3df8099c74293 [file] [log] [blame]
Mohammed Naser62c4dd92025-02-16 13:18:14 -05001use serde::Deserialize;
2use std::collections::HashMap;
3use std::{fs::File, path::PathBuf};
4use thiserror::Error;
5use log::{error, info};
6
7#[derive(Deserialize)]
8pub struct NetworkConfig {
9 #[serde(flatten)]
10 pub bridges: HashMap<String, Option<String>>,
11}
12
13#[derive(Debug, Error)]
14pub enum NetworkConfigError {
15 #[error("Failed to open file: {0}")]
16 OpenFile(#[from] std::io::Error),
17
18 #[error("Failed to parse JSON: {0}")]
19 ParseJson(#[from] serde_json::Error),
20}
21
22impl NetworkConfig {
23 pub fn from_path(path: &PathBuf) -> Result<Self, NetworkConfigError> {
24 let file = File::open(path)?;
25 NetworkConfig::from_file(file)
26 }
27
28 pub fn from_file(file: File) -> Result<Self, NetworkConfigError> {
29 let config: NetworkConfig = serde_json::from_reader(file)?;
30 Ok(config)
31 }
32
33 pub fn bridges_with_interfaces_iter(&self) -> impl Iterator<Item = (&String, &String)> {
34 self.bridges.iter().filter_map(|(k, v)| {
35 if let Some(v) = v {
36 Some((k, v))
37 } else {
38 info!(bridge = k.as_str(); "Bridge has no interface, skipping.");
39
40 None
41 }
42 })
43 }
44
45 #[allow(dead_code)]
46 pub fn from_string(json: &str) -> Result<Self, NetworkConfigError> {
47 let config: NetworkConfig = serde_json::from_str(json)?;
48 Ok(config)
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55
56 #[test]
57 fn test_null_interface() {
58 let config = NetworkConfig::from_string("{\"br-ex\": null}").unwrap();
59
60 assert_eq!(config.bridges.len(), 1);
61 assert_eq!(config.bridges.get("br-ex"), Some(&None));
62 }
63
64 #[test]
65 fn test_bridges_with_interfaces_iter_with_null_interface() {
66 let config = NetworkConfig::from_string("{\"br-ex\": null}").unwrap();
67
68 let mut iter = config.bridges_with_interfaces_iter();
69 assert_eq!(iter.next(), None);
70 }
71
72 #[test]
73 fn test_bridges_with_interfaces_iter_with_interface() {
74 let config = NetworkConfig::from_string("{\"br-ex\": \"bond0\"}").unwrap();
75
76 let mut iter = config.bridges_with_interfaces_iter();
77 assert_eq!(
78 iter.next(),
79 Some((&"br-ex".to_string(), &"bond0".to_string()))
80 );
81 }
82}