Skip to main content

pot_rs/
bridge.rs

1use crate::error::PotError;
2use crate::Result;
3use ipnet::IpNet;
4use std::convert::TryFrom;
5use std::net::IpAddr;
6use std::str::FromStr;
7
8use crate::PotSystemConfig;
9use std::path::PathBuf;
10
11pub fn get_bridges_list(conf: &PotSystemConfig) -> Result<Vec<BridgeConf>> {
12    let path_list = get_bridges_path_list(conf);
13    let mut result = Vec::new();
14    for f in path_list {
15        if let Ok(conf_str) = std::fs::read_to_string(f.as_path()) {
16            if let Ok(bridge_conf) = conf_str.parse() {
17                result.push(bridge_conf);
18            }
19        }
20    }
21    Ok(result)
22}
23
24fn get_bridges_path_list(conf: &PotSystemConfig) -> Vec<PathBuf> {
25    let mut result = Vec::new();
26    let bridges_path = std::path::Path::new(&conf.fs_root).join("bridges");
27    walkdir::WalkDir::new(bridges_path)
28        .max_depth(1)
29        .min_depth(1)
30        .into_iter()
31        .filter_map(std::result::Result::ok)
32        .filter(|x| x.file_type().is_file())
33        .for_each(|x| result.push(x.into_path()));
34    result
35}
36#[derive(Debug)]
37pub struct BridgeConf {
38    pub name: String,
39    pub network: IpNet,
40    pub gateway: IpAddr,
41}
42
43impl FromStr for BridgeConf {
44    type Err = crate::error::PotError;
45    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
46        let partial = PartialBridgeConf::from_str(s).unwrap();
47        BridgeConf::try_from(partial)
48    }
49}
50
51impl TryFrom<PartialBridgeConf> for BridgeConf {
52    type Error = PotError;
53
54    fn try_from(value: PartialBridgeConf) -> std::result::Result<Self, Self::Error> {
55        if !value.is_valid() {
56            Err(PotError::BridgeConfError)
57        } else {
58            let network = value.network.unwrap();
59            let gateway = value.gateway.unwrap();
60            if !network.contains(&gateway) {
61                Err(PotError::BridgeConfError)
62            } else {
63                Ok(BridgeConf {
64                    name: value.name.unwrap(),
65                    network: value.network.unwrap(),
66                    gateway: value.gateway.unwrap(),
67                })
68            }
69        }
70    }
71}
72
73#[derive(Default, Debug)]
74struct PartialBridgeConf {
75    name: Option<String>,
76    network: Option<IpNet>,
77    gateway: Option<IpAddr>,
78}
79
80impl FromStr for PartialBridgeConf {
81    type Err = std::convert::Infallible;
82    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
83        use crate::util::get_value;
84        let lines: Vec<String> = s
85            .to_string()
86            .lines()
87            .map(|x| x.trim().to_string())
88            .filter(|x| !x.starts_with('#'))
89            .collect();
90        let mut result = PartialBridgeConf::default();
91        for linestr in &lines {
92            if linestr.starts_with("name=") {
93                result.name = get_value(linestr);
94            }
95            if linestr.starts_with("net=") {
96                result.network = get_value(linestr);
97            }
98            if linestr.starts_with("gateway=") {
99                result.gateway = get_value(linestr);
100            }
101        }
102        Ok(result)
103    }
104}
105
106impl PartialBridgeConf {
107    fn is_valid(&self) -> bool {
108        self.name.is_some() && self.network.is_some() && self.gateway.is_some()
109    }
110}
111
112#[cfg(test)]
113mod tests {
114    use super::*;
115
116    #[test]
117    fn bridge_conf_fromstr_001() {
118        let uut = BridgeConf::from_str("");
119        assert_eq!(uut.is_ok(), false);
120    }
121
122    #[test]
123    fn bridge_conf_fromstr_002() {
124        let uut = BridgeConf::from_str("net=10.192.0.24/29");
125        assert_eq!(uut.is_ok(), false);
126    }
127
128    #[test]
129    fn bridge_conf_fromstr_003() {
130        let uut = BridgeConf::from_str("gateway=10.192.0.24");
131        assert_eq!(uut.is_ok(), false);
132    }
133
134    #[test]
135    fn bridge_conf_fromstr_004() {
136        let uut = BridgeConf::from_str("name=test-bridge");
137        assert_eq!(uut.is_ok(), false);
138    }
139
140    #[test]
141    fn bridge_conf_fromstr_005() {
142        let uut = BridgeConf::from_str("net=10.192.0.24/29\ngateway=10.192.1.25\nname=test-bridge");
143        assert_eq!(uut.is_ok(), false);
144    }
145
146    #[test]
147    fn bridge_conf_fromstr_020() {
148        let uut = BridgeConf::from_str("net=10.192.0.24/29\ngateway=10.192.0.25\nname=test-bridge");
149        assert_eq!(uut.is_ok(), true);
150    }
151}