wip: Full opnsense deserializer almost done, works on a slightly cheated config file, next step is to try the real config file

This commit is contained in:
Jean-Gabriel Gill-Couture 2024-10-18 00:48:57 -04:00
parent b332723431
commit e0acbf304b
9 changed files with 3475 additions and 24 deletions

3
harmony-rs/Cargo.lock generated
View File

@ -1240,6 +1240,7 @@ name = "opnsense-config"
version = "0.1.0"
dependencies = [
"async-trait",
"env_logger",
"log",
"russh",
"russh-keys",
@ -2596,7 +2597,6 @@ dependencies = [
[[package]]
name = "yaserde"
version = "0.11.1"
source = "git+https://git.nationtech.io/NationTech/yaserde#353558737f3ef73e93164c596ff920d4344f30a3"
dependencies = [
"log",
"xml-rs",
@ -2605,7 +2605,6 @@ dependencies = [
[[package]]
name = "yaserde_derive"
version = "0.11.1"
source = "git+https://git.nationtech.io/NationTech/yaserde#353558737f3ef73e93164c596ff920d4344f30a3"
dependencies = [
"heck",
"log",

View File

@ -6,10 +6,13 @@ edition = "2021"
[dependencies]
serde = { version = "1.0.123", features = [ "derive" ] }
log = { workspace = true }
env_logger = { workspace = true }
russh = { workspace = true }
russh-keys = { workspace = true }
yaserde = { git = "https://git.nationtech.io/NationTech/yaserde" }
yaserde_derive = { git = "https://git.nationtech.io/NationTech/yaserde" }
#yaserde = { git = "https://git.nationtech.io/NationTech/yaserde" }
#yaserde_derive = { git = "https://git.nationtech.io/NationTech/yaserde" }
yaserde = { path = "../../../../github/yaserde/yaserde" }
yaserde_derive = { path = "../../../../github/yaserde/yaserde_derive" }
xml-rs = "0.8"
thiserror = "1.0"
async-trait = { workspace = true }

View File

@ -176,7 +176,7 @@ mod tests {
#[tokio::test]
async fn test_load_config_from_local_file() {
let mut test_file_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
test_file_path.push("src/tests/data/config-full-1.xml");
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}");

View File

@ -0,0 +1,110 @@
use xml::reader::XmlEvent;
use yaserde::{YaDeserialize, YaSerialize};
use crate::modules::opnsense::{Interface, Interfaces};
impl YaSerialize for Interfaces {
fn serialize<W: std::io::Write>(
&self,
writer: &mut yaserde::ser::Serializer<W>,
) -> Result<(), String> {
todo!()
}
fn serialize_attributes(
&self,
attributes: Vec<xml::attribute::OwnedAttribute>,
namespace: xml::namespace::Namespace,
) -> Result<
(
Vec<xml::attribute::OwnedAttribute>,
xml::namespace::Namespace,
),
String,
> {
todo!()
}
}
impl YaDeserialize for Interfaces {
fn deserialize<R: std::io::Read>(
reader: &mut yaserde::de::Deserializer<R>,
) -> Result<Self, String> {
let mut interfaces = Interfaces::default();
let mut current_interface_name = String::new();
let mut current_interface = Interface::default();
let mut event = reader.next_event()?;
loop {
match event {
xml::reader::XmlEvent::EndElement { name } => {
println!(
"Handling EndElement {}, current_interface_name: {}",
name.local_name, current_interface_name
);
println!("Peeking after EndElement {:?}", reader.peek()?);
if name.local_name == "interfaces" {
break;
}
todo!("Should not hit here");
}
xml::reader::XmlEvent::StartElement { ref name, .. } => {
println!("Got start Element {:?}", name);
current_interface_name = name.local_name.clone();
println!("About to deserialize interface from name {:?}", name);
// TODO store names
'inner_iface: loop {
let peek = reader.peek()?;
println!("Peeking before forcing next event {:?}", peek);
if let XmlEvent::EndElement { name } = peek {
// TODO save the interface name and struct in the hashmap
println!("Forcing next_event");
reader.next_event()?;
let peek = reader.peek()?;
println!("Peeking after next event deserializing {:?}", peek);
if let XmlEvent::EndElement { name } = peek {
println!("Got two EndElement in a row, breaking out of loop");
break 'inner_iface;
}
}
println!("Peeking before deserializing {:?}", reader.peek()?);
let interface = <Interface as yaserde::YaDeserialize>::deserialize(reader)?;
println!("Interface deserialized {:?}", interface);
println!("Peeking after deserializing {:?}", reader.peek()?);
}
println!(
"Done with inner interface, loop completed {:?}",
reader.peek()?
);
}
xml::reader::XmlEvent::EndDocument => break,
_ => {
return Err(
"This Interfaces Deserializer does not support all XmlEvent types".into(),
)
}
}
let peek = reader.peek()?;
let mut read_next = true;
if let XmlEvent::EndElement { name } = peek {
if name.local_name == "interfaces" {
println!("Got endElement interfaces, not reading next event");
break;
}
}
if read_next {
event = reader.next_event()?;
}
println!("Outer loop got event {:?}", event);
println!("Outer loop got peek {:?}", reader.peek()?);
}
println!("Done with interfaces {:?}", interfaces);
println!("reader peeking shows {:?}", reader.peek());
Ok(interfaces)
}
}

View File

@ -0,0 +1,3 @@
mod interfaces;

View File

@ -14,6 +14,10 @@ impl<'a> DhcpConfig<'a> {
mac,
ipaddr,
hostname,
descr: Some("Automatically generated".into()),
winsserver: None,
dnsserver: None,
ntpserver: None,
};
self.opnsense.dhcpd.lan.staticmaps.push(static_map);
}

View File

@ -1,2 +1,3 @@
pub mod opnsense;
pub mod dhcp;
mod deserializer;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff