feat(opnsense-config): Public API now a bit simpler, added support for latest opnsense version in xml types
This commit is contained in:
114
harmony-rs/opnsense-config/src/config/config.rs
Normal file
114
harmony-rs/opnsense-config/src/config/config.rs
Normal file
@@ -0,0 +1,114 @@
|
||||
use crate::{error::Error, modules::dhcp::DhcpConfig};
|
||||
use log::trace;
|
||||
use opnsense_config_xml::OPNsense;
|
||||
|
||||
use super::ConfigRepository;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Config {
|
||||
opnsense: OPNsense,
|
||||
repository: Box<dyn ConfigRepository + Send + Sync>,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub async fn new(repository: Box<dyn ConfigRepository + Send + Sync>) -> Result<Self, Error> {
|
||||
let xml = repository.load().await?;
|
||||
trace!("xml {}", xml);
|
||||
|
||||
let opnsense = OPNsense::from(xml);
|
||||
|
||||
Ok(Self {
|
||||
opnsense,
|
||||
repository,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn dhcp(&mut self) -> DhcpConfig {
|
||||
DhcpConfig::new(&mut self.opnsense)
|
||||
}
|
||||
|
||||
pub async fn save(&self) -> Result<(), Error> {
|
||||
self.repository.save(&self.opnsense.to_xml()).await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::config::LocalFileConfigRepository;
|
||||
use crate::modules::dhcp::DhcpConfig;
|
||||
use std::fs;
|
||||
use std::net::Ipv4Addr;
|
||||
|
||||
use super::*;
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_load_config_from_local_file() {
|
||||
for path in vec![
|
||||
"src/tests/data/config-vm-test.xml",
|
||||
"src/tests/data/config-full-1.xml",
|
||||
"src/tests/data/config-structure.xml",
|
||||
] {
|
||||
let mut test_file_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
test_file_path.push(path);
|
||||
|
||||
let config_file_path = test_file_path.to_str().unwrap().to_string();
|
||||
println!("File path {config_file_path}");
|
||||
let repository = Box::new(LocalFileConfigRepository::new(config_file_path));
|
||||
let config_file_str = repository.load().await.unwrap();
|
||||
let config = Config::new(repository)
|
||||
.await
|
||||
.expect("Failed to load config");
|
||||
|
||||
println!("Config {:?}", config);
|
||||
|
||||
let serialized = config.opnsense.to_xml();
|
||||
|
||||
fs::write("/tmp/serialized.xml", &serialized).unwrap();
|
||||
|
||||
// Since the order of all fields is not always the same in opnsense config files
|
||||
// I think it is good enough to have exactly the same amount of the same lines
|
||||
let config_file_str_sorted = vec![config_file_str.lines().collect::<Vec<_>>()].sort();
|
||||
let serialized_sorted = vec![config_file_str.lines().collect::<Vec<_>>()].sort();
|
||||
assert_eq!(config_file_str_sorted, serialized_sorted);
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_add_dhcpd_static_entry() {
|
||||
let mut test_file_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
test_file_path.push("src/tests/data/config-structure.xml");
|
||||
|
||||
let config_file_path = test_file_path.to_str().unwrap().to_string();
|
||||
println!("File path {config_file_path}");
|
||||
let repository = Box::new(LocalFileConfigRepository::new(config_file_path));
|
||||
let mut config = Config::new(repository)
|
||||
.await
|
||||
.expect("Failed to load config");
|
||||
|
||||
println!("Config {:?}", config);
|
||||
|
||||
let mut dhcp_config = DhcpConfig::new(&mut config.opnsense);
|
||||
dhcp_config
|
||||
.add_static_mapping(
|
||||
"00:00:00:00:00:00",
|
||||
Ipv4Addr::new(192, 168, 20, 100),
|
||||
"hostname",
|
||||
)
|
||||
.expect("Should add static mapping");
|
||||
|
||||
let serialized = config.opnsense.to_xml();
|
||||
|
||||
fs::write("/tmp/serialized.xml", &serialized).unwrap();
|
||||
|
||||
let mut test_file_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
test_file_path.push("src/tests/data/config-structure-with-dhcp-staticmap-entry.xml");
|
||||
|
||||
let config_file_path = test_file_path.to_str().unwrap().to_string();
|
||||
println!("File path {config_file_path}");
|
||||
let repository = Box::new(LocalFileConfigRepository::new(config_file_path));
|
||||
let expected_config_file_str = repository.load().await.unwrap();
|
||||
assert_eq!(expected_config_file_str, serialized);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user