forked from NationTech/harmony
		
	Integrated opnsense-config API in harmony, pretty easy, pretty happy. very much encouraging
This commit is contained in:
		
							parent
							
								
									d30e909b83
								
							
						
					
					
						commit
						9c18c8be6d
					
				
							
								
								
									
										35
									
								
								harmony-rs/Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										35
									
								
								harmony-rs/Cargo.lock
									
									
									
										generated
									
									
									
								
							| @ -895,6 +895,7 @@ dependencies = [ | |||||||
|  "env_logger", |  "env_logger", | ||||||
|  "libredfish", |  "libredfish", | ||||||
|  "log", |  "log", | ||||||
|  |  "opnsense-config", | ||||||
|  "reqwest", |  "reqwest", | ||||||
|  "russh", |  "russh", | ||||||
|  "rust-ipmi", |  "rust-ipmi", | ||||||
| @ -902,7 +903,6 @@ dependencies = [ | |||||||
|  "serde", |  "serde", | ||||||
|  "serde_json", |  "serde_json", | ||||||
|  "tokio", |  "tokio", | ||||||
|  "xml_dom", |  | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| [[package]] | [[package]] | ||||||
| @ -1627,15 +1627,6 @@ dependencies = [ | |||||||
|  "unicode-ident", |  "unicode-ident", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| [[package]] |  | ||||||
| name = "quick-xml" |  | ||||||
| version = "0.36.2" |  | ||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" |  | ||||||
| checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" |  | ||||||
| dependencies = [ |  | ||||||
|  "memchr", |  | ||||||
| ] |  | ||||||
| 
 |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "quote" | name = "quote" | ||||||
| version = "1.0.37" | version = "1.0.37" | ||||||
| @ -2430,21 +2421,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||||||
| checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" | checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "pin-project-lite", |  "pin-project-lite", | ||||||
|  "tracing-attributes", |  | ||||||
|  "tracing-core", |  "tracing-core", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| [[package]] |  | ||||||
| name = "tracing-attributes" |  | ||||||
| version = "0.1.27" |  | ||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" |  | ||||||
| checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" |  | ||||||
| dependencies = [ |  | ||||||
|  "proc-macro2", |  | ||||||
|  "quote", |  | ||||||
|  "syn 2.0.77", |  | ||||||
| ] |  | ||||||
| 
 |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "tracing-core" | name = "tracing-core" | ||||||
| version = "0.1.32" | version = "0.1.32" | ||||||
| @ -2822,18 +2801,6 @@ version = "0.8.22" | |||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "af4e2e2f7cba5a093896c1e150fbfe177d1883e7448200efb81d40b9d339ef26" | checksum = "af4e2e2f7cba5a093896c1e150fbfe177d1883e7448200efb81d40b9d339ef26" | ||||||
| 
 | 
 | ||||||
| [[package]] |  | ||||||
| name = "xml_dom" |  | ||||||
| version = "0.2.8" |  | ||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" |  | ||||||
| checksum = "836bd445caf6b9e969199f2a9667d58b433b286ddb515764303ab75a6d17e51f" |  | ||||||
| dependencies = [ |  | ||||||
|  "log", |  | ||||||
|  "quick-xml", |  | ||||||
|  "regex", |  | ||||||
|  "tracing", |  | ||||||
| ] |  | ||||||
| 
 |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "yansi" | name = "yansi" | ||||||
| version = "1.0.1" | version = "1.0.1" | ||||||
|  | |||||||
| @ -18,6 +18,8 @@ derive-new = "0.7.0" | |||||||
| async-trait = "0.1.82" | async-trait = "0.1.82" | ||||||
| tokio = { version = "1.40.0", features = ["io-std"] } | tokio = { version = "1.40.0", features = ["io-std"] } | ||||||
| cidr = "0.2.3" | cidr = "0.2.3" | ||||||
| xml_dom = "0.2.8" |  | ||||||
| russh = "0.45.0" | russh = "0.45.0" | ||||||
| russh-keys = "0.45.0" | russh-keys = "0.45.0" | ||||||
|  | 
 | ||||||
|  | #[workspace.target.x86_64-unknown-linux-gnu] | ||||||
|  | #rustflags = ["-C", "link-arg=-fuse-ld=mold"] | ||||||
|  | |||||||
| @ -17,4 +17,4 @@ log = { workspace = true } | |||||||
| env_logger = { workspace = true } | env_logger = { workspace = true } | ||||||
| async-trait = { workspace = true } | async-trait = { workspace = true } | ||||||
| cidr = { workspace = true } | cidr = { workspace = true } | ||||||
| xml_dom = { workspace = true } | opnsense-config = { path = "../opnsense-config" } | ||||||
|  | |||||||
| @ -22,6 +22,7 @@ pub struct HAClusterTopology { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub type IpAddress = IpAddr; | pub type IpAddress = IpAddr; | ||||||
|  | 
 | ||||||
| /// Represents a logical member of a cluster that provides one or more services.
 | /// Represents a logical member of a cluster that provides one or more services.
 | ||||||
| ///
 | ///
 | ||||||
| /// A LogicalHost can represent various roles within the infrastructure, such as:
 | /// A LogicalHost can represent various roles within the infrastructure, such as:
 | ||||||
|  | |||||||
| @ -1,3 +1,5 @@ | |||||||
|  | use std::net::Ipv4Addr; | ||||||
|  | 
 | ||||||
| use async_trait::async_trait; | use async_trait::async_trait; | ||||||
| 
 | 
 | ||||||
| use crate::executors::ExecutorError; | use crate::executors::ExecutorError; | ||||||
| @ -8,12 +10,15 @@ use super::{IpAddress, LogicalHost}; | |||||||
| pub struct DHCPStaticEntry { | pub struct DHCPStaticEntry { | ||||||
|     pub name: String, |     pub name: String, | ||||||
|     pub mac: MacAddress, |     pub mac: MacAddress, | ||||||
|     pub ip: IpAddress, |     pub ip: Ipv4Addr, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl std::fmt::Display for DHCPStaticEntry { | impl std::fmt::Display for DHCPStaticEntry { | ||||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||||
|         f.write_fmt(format_args!("DHCPStaticEntry : name {}, mac {}, ip {}", self.name, self.mac, self.ip)) |         f.write_fmt(format_args!( | ||||||
|  |             "DHCPStaticEntry : name {}, mac {}, ip {}", | ||||||
|  |             self.name, self.mac, self.ip | ||||||
|  |         )) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -57,7 +62,11 @@ pub trait DnsServer: Send + Sync { | |||||||
|         record_type: DnsRecordType, |         record_type: DnsRecordType, | ||||||
|         value: &str, |         value: &str, | ||||||
|     ) -> Result<(), ExecutorError>; |     ) -> Result<(), ExecutorError>; | ||||||
|     fn remove_record(&mut self, name: &str, record_type: DnsRecordType) -> Result<(), ExecutorError>; |     fn remove_record( | ||||||
|  |         &mut self, | ||||||
|  |         name: &str, | ||||||
|  |         record_type: DnsRecordType, | ||||||
|  |     ) -> Result<(), ExecutorError>; | ||||||
|     fn list_records(&self) -> Vec<DnsRecord>; |     fn list_records(&self) -> Vec<DnsRecord>; | ||||||
|     fn get_ip(&self) -> IpAddress; |     fn get_ip(&self) -> IpAddress; | ||||||
|     fn get_host(&self) -> LogicalHost; |     fn get_host(&self) -> LogicalHost; | ||||||
| @ -98,11 +107,21 @@ pub struct MacAddress(pub [u8; 6]); | |||||||
| // MacAddress::from!("00:90:7f:df:2c:23"),
 | // MacAddress::from!("00:90:7f:df:2c:23"),
 | ||||||
| 
 | 
 | ||||||
| impl MacAddress { | impl MacAddress { | ||||||
|  |     #[cfg(test)] | ||||||
|     pub fn dummy() -> Self { |     pub fn dummy() -> Self { | ||||||
|         Self([0, 0, 0, 0, 0, 0]) |         Self([0, 0, 0, 0, 0, 0]) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | impl From<&MacAddress> for String { | ||||||
|  |     fn from(value: &MacAddress) -> Self { | ||||||
|  |         format!( | ||||||
|  |             "{}:{}:{}:{}:{}:{}", | ||||||
|  |             value.0[0], value.0[1], value.0[2], value.0[3], value.0[4], value.0[5] | ||||||
|  |         ) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| impl std::fmt::Display for MacAddress { | impl std::fmt::Display for MacAddress { | ||||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||||
|         f.write_fmt(format_args!( |         f.write_fmt(format_args!( | ||||||
|  | |||||||
| @ -1,43 +0,0 @@ | |||||||
| use crate::executors::ExecutorError; |  | ||||||
| 
 |  | ||||||
| pub struct OPNSenseXmlConfigEditor; |  | ||||||
| 
 |  | ||||||
| impl OPNSenseXmlConfigEditor { |  | ||||||
|     pub(crate) async fn add(vec: Vec<&str>, xml_entry: &str) -> Result<(), ExecutorError>{ |  | ||||||
|         todo!() |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[cfg(test)] |  | ||||||
| mod test { |  | ||||||
|     use std::fs; |  | ||||||
|     use std::io::{BufReader, Read}; |  | ||||||
|     use std::process::Command; |  | ||||||
| 
 |  | ||||||
|     use xml_dom::parser::read_xml; |  | ||||||
| 
 |  | ||||||
|     // #[test]
 |  | ||||||
|     // fn should_not_alter_config() {
 |  | ||||||
|     //     let path = "./private_repos/affilium_mcd/private/config.xml";
 |  | ||||||
|     //     //  TODO
 |  | ||||||
|     //     //  Load file to string
 |  | ||||||
|     //     //  Parse with minidom (ex: `let root: Element = file_str.parse().unwrap()`)
 |  | ||||||
|     //     //  save file with suffix name
 |  | ||||||
|     //     //  Verify that file is still identical with md5sum after removing indentation
 |  | ||||||
|     // }
 |  | ||||||
| 
 |  | ||||||
|     #[test] |  | ||||||
|     fn should_not_alter_config() { |  | ||||||
|         let path = "/home/jeangab/work/nationtech/harmony/harmony-rs/affilium_mcd/private/config.xml"; |  | ||||||
|         let output_path = format!("{}.test_output", path); |  | ||||||
| 
 |  | ||||||
|         // Load file to string
 |  | ||||||
|         let file_str = fs::read_to_string(path).expect("Failed to read file"); |  | ||||||
| 
 |  | ||||||
|         // Parse with minidom
 |  | ||||||
|         let root = read_xml(&file_str).unwrap(); |  | ||||||
| 
 |  | ||||||
|         assert_eq!(&root.to_string(), &file_str); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -1,18 +1,21 @@ | |||||||
| mod management; | mod management; | ||||||
| mod config; | use std::sync::{Arc, Mutex, RwLock, RwLockWriteGuard}; | ||||||
|  | 
 | ||||||
| use async_trait::async_trait; | use async_trait::async_trait; | ||||||
|  | use log::debug; | ||||||
| pub use management::*; | pub use management::*; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     executors::ExecutorError, infra::opnsense::config::OPNSenseXmlConfigEditor, topology::{ |     executors::ExecutorError, | ||||||
|  |     topology::{ | ||||||
|         Backend, DHCPStaticEntry, DhcpServer, DnsServer, Firewall, FirewallRule, Frontend, |         Backend, DHCPStaticEntry, DhcpServer, DnsServer, Firewall, FirewallRule, Frontend, | ||||||
|         IpAddress, LoadBalancer, LogicalHost, |         IpAddress, LoadBalancer, LogicalHost, | ||||||
|     } |     }, | ||||||
| }; | }; | ||||||
| use derive_new::new; |  | ||||||
| 
 | 
 | ||||||
| #[derive(new, Clone)] | #[derive(Clone)] | ||||||
| pub struct OPNSenseFirewall { | pub struct OPNSenseFirewall { | ||||||
|  |     opnsense_config: Arc<RwLock<opnsense_config::Config>>, | ||||||
|     host: LogicalHost, |     host: LogicalHost, | ||||||
|     cluster_nic_name: String, |     cluster_nic_name: String, | ||||||
| } | } | ||||||
| @ -22,6 +25,20 @@ impl OPNSenseFirewall { | |||||||
|         self.host.ip |         self.host.ip | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     pub async fn new( | ||||||
|  |         host: LogicalHost, | ||||||
|  |         cluster_nic_name: &str, | ||||||
|  |         username: &str, | ||||||
|  |         password: &str, | ||||||
|  |     ) -> Self { | ||||||
|  |         Self { | ||||||
|  |             opnsense_config: Arc::new(RwLock::new( | ||||||
|  |                 opnsense_config::Config::from_credentials(host.ip, username, password).await, | ||||||
|  |             )), | ||||||
|  |             host, | ||||||
|  |             cluster_nic_name: cluster_nic_name.into(), | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Firewall for OPNSenseFirewall { | impl Firewall for OPNSenseFirewall { | ||||||
| @ -81,27 +98,17 @@ impl LoadBalancer for OPNSenseFirewall { | |||||||
| #[async_trait] | #[async_trait] | ||||||
| impl DhcpServer for OPNSenseFirewall { | impl DhcpServer for OPNSenseFirewall { | ||||||
|     async fn add_static_mapping(&self, entry: &DHCPStaticEntry) -> Result<(), ExecutorError> { |     async fn add_static_mapping(&self, entry: &DHCPStaticEntry) -> Result<(), ExecutorError> { | ||||||
|         let mac = &entry.mac; |         let mac: String = String::from(&entry.mac); | ||||||
|         let name = &entry.name; |  | ||||||
|         let ip = &entry.ip; |  | ||||||
| 
 | 
 | ||||||
|         let xml_entry = format!( |         { | ||||||
|             "<staticmap>
 |             let mut writable_opnsense = self.opnsense_config.write().unwrap(); | ||||||
|           <mac>{mac}</mac> |             writable_opnsense | ||||||
|           <ipaddr>{ip}</ipaddr> |                 .dhcp() | ||||||
|           <hostname>{name}</hostname> |                 .add_static_mapping(&mac, entry.ip, &entry.name).unwrap(); | ||||||
|           <descr>{name}</descr> |         } | ||||||
|           <winsserver/> | 
 | ||||||
|           <dnsserver/> |         debug!("Registered {:?}", entry); | ||||||
|           <ntpserver/> |         Ok(()) | ||||||
|         </staticmap>" |  | ||||||
|         ); |  | ||||||
|         // XML Path : <opnsense><dhcpd><DHCPD_INTERFACE_NAME><staticmap>
 |  | ||||||
|         OPNSenseXmlConfigEditor::add( |  | ||||||
|             vec!["opnsense", "dhcpd", &self.cluster_nic_name, "staticmap"], |  | ||||||
|             &xml_entry, |  | ||||||
|         ).await?; |  | ||||||
|         todo!("Register {:?}", entry) |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     async fn remove_static_mapping( |     async fn remove_static_mapping( | ||||||
| @ -122,6 +129,7 @@ impl DhcpServer for OPNSenseFirewall { | |||||||
|         self.host.clone() |         self.host.clone() | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
| impl DnsServer for OPNSenseFirewall { | impl DnsServer for OPNSenseFirewall { | ||||||
|     fn add_record( |     fn add_record( | ||||||
|         &mut self, |         &mut self, | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| use std::sync::Arc; | use std::{net::Ipv4Addr, sync::Arc}; | ||||||
| 
 | 
 | ||||||
| use async_trait::async_trait; | use async_trait::async_trait; | ||||||
| use derive_new::new; | use derive_new::new; | ||||||
| @ -120,10 +120,17 @@ impl Interpret for DhcpInterpret { | |||||||
|             .score |             .score | ||||||
|             .host_binding |             .host_binding | ||||||
|             .iter() |             .iter() | ||||||
|             .map(|binding| DHCPStaticEntry { |             .map(|binding| { | ||||||
|  |                 let ip = match binding.logical_host.ip { | ||||||
|  |                     std::net::IpAddr::V4(ipv4) => ipv4, | ||||||
|  |                     std::net::IpAddr::V6(_) => unimplemented!("DHCPStaticEntry only supports ipv4 at the moment"), | ||||||
|  |                 }; | ||||||
|  | 
 | ||||||
|  |                 DHCPStaticEntry { | ||||||
|                     name: binding.logical_host.name.clone(), |                     name: binding.logical_host.name.clone(), | ||||||
|                     mac: binding.physical_host.cluster_mac(), |                     mac: binding.physical_host.cluster_mac(), | ||||||
|                 ip: binding.logical_host.ip, |                     ip, | ||||||
|  |                 } | ||||||
|             }) |             }) | ||||||
|             .collect(); |             .collect(); | ||||||
|         info!("DHCPStaticEntry : {:?}", dhcp_entries); |         info!("DHCPStaticEntry : {:?}", dhcp_entries); | ||||||
| @ -136,6 +143,7 @@ impl Interpret for DhcpInterpret { | |||||||
|                 Err(_) => todo!(), |                 Err(_) => todo!(), | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|         todo!("Configure DHCPServer"); |         todo!("Configure DHCPServer"); | ||||||
| 
 | 
 | ||||||
|         Ok(Outcome::new( |         Ok(Outcome::new( | ||||||
|  | |||||||
| @ -20,3 +20,6 @@ tokio = { workspace = true } | |||||||
| 
 | 
 | ||||||
| [dev-dependencies] | [dev-dependencies] | ||||||
| pretty_assertions = "1.4.1" | pretty_assertions = "1.4.1" | ||||||
|  | 
 | ||||||
|  | [target.x86_64-unknown-linux-gnu] | ||||||
|  | rustflags = ["-C", "link-arg=-fuse-ld=mold"] | ||||||
|  | |||||||
| @ -1,8 +1,9 @@ | |||||||
| use std::sync::Arc; | use std::{net::Ipv4Addr, sync::Arc, time::Duration}; | ||||||
| 
 | 
 | ||||||
| use crate::{error::Error, modules::dhcp::DhcpConfig}; | use crate::{config::{SshConfigManager, SshCredentials, SshOPNSenseShell}, error::Error, modules::dhcp::DhcpConfig}; | ||||||
| use log::trace; | use log::trace; | ||||||
| use opnsense_config_xml::OPNsense; | use opnsense_config_xml::OPNsense; | ||||||
|  | use russh::client; | ||||||
| 
 | 
 | ||||||
| use super::{ConfigManager, OPNsenseShell}; | use super::{ConfigManager, OPNsenseShell}; | ||||||
| 
 | 
 | ||||||
| @ -39,6 +40,27 @@ impl Config { | |||||||
|             .apply_new_config(&self.opnsense.to_xml()) |             .apply_new_config(&self.opnsense.to_xml()) | ||||||
|             .await |             .await | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     pub async fn from_credentials(ipaddr: std::net::IpAddr, username: &str, password: &str) -> Self { | ||||||
|  |         let config = Arc::new(client::Config { | ||||||
|  |             inactivity_timeout: Some(Duration::from_secs(5)), | ||||||
|  |             ..<_>::default() | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         let credentials = SshCredentials::Password { | ||||||
|  |             username: String::from(username), | ||||||
|  |             password: String::from(password), | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         let shell = Arc::new(SshOPNSenseShell::new( | ||||||
|  |             (ipaddr, 22), | ||||||
|  |             credentials, | ||||||
|  |             config, | ||||||
|  |         )); | ||||||
|  |         let manager = Arc::new(SshConfigManager::new(shell.clone())); | ||||||
|  | 
 | ||||||
|  |         Config::new(manager, shell).await.unwrap() | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[cfg(test)] | #[cfg(test)] | ||||||
|  | |||||||
| @ -7,7 +7,7 @@ pub use local_file::*; | |||||||
| use crate::Error; | use crate::Error; | ||||||
| 
 | 
 | ||||||
| #[async_trait] | #[async_trait] | ||||||
| pub trait ConfigManager: std::fmt::Debug { | pub trait ConfigManager: std::fmt::Debug + Send + Sync { | ||||||
|     async fn load_as_str(&self) -> Result<String, Error>; |     async fn load_as_str(&self) -> Result<String, Error>; | ||||||
|     async fn apply_new_config(&self, content: &str) -> Result<(), Error>; |     async fn apply_new_config(&self, content: &str) -> Result<(), Error>; | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| use std::{ | use std::{ | ||||||
|     net::Ipv4Addr, |     net::IpAddr, | ||||||
|     sync::Arc, |     sync::Arc, | ||||||
|     time::{SystemTime, UNIX_EPOCH}, |     time::{SystemTime, UNIX_EPOCH}, | ||||||
| }; | }; | ||||||
| @ -20,7 +20,7 @@ use super::OPNsenseShell; | |||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub struct SshOPNSenseShell { | pub struct SshOPNSenseShell { | ||||||
|     host: (Ipv4Addr, u16), |     host: (IpAddr, u16), | ||||||
|     credentials: SshCredentials, |     credentials: SshCredentials, | ||||||
|     ssh_config: Arc<Config>, |     ssh_config: Arc<Config>, | ||||||
| } | } | ||||||
| @ -78,11 +78,7 @@ impl SshOPNSenseShell { | |||||||
|         wait_for_completion(&mut channel).await |         wait_for_completion(&mut channel).await | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn new( |     pub fn new(host: (IpAddr, u16), credentials: SshCredentials, ssh_config: Arc<Config>) -> Self { | ||||||
|         host: (Ipv4Addr, u16), |  | ||||||
|         credentials: SshCredentials, |  | ||||||
|         ssh_config: Arc<Config>, |  | ||||||
|     ) -> Self { |  | ||||||
|         Self { |         Self { | ||||||
|             host, |             host, | ||||||
|             credentials, |             credentials, | ||||||
|  | |||||||
| @ -6,15 +6,10 @@ pub use config::Config; | |||||||
| pub use error::Error; | pub use error::Error; | ||||||
| #[cfg(test)] | #[cfg(test)] | ||||||
| mod test { | mod test { | ||||||
|     use config::SshConfigManager; |  | ||||||
|     use opnsense_config_xml::StaticMap; |     use opnsense_config_xml::StaticMap; | ||||||
|     use russh::client; |     use std::net::Ipv4Addr; | ||||||
|     use std::{net::Ipv4Addr, sync::Arc, time::Duration}; |  | ||||||
| 
 | 
 | ||||||
|     use crate::{ |     use crate::Config; | ||||||
|         config::{self, SshCredentials, SshOPNSenseShell}, |  | ||||||
|         Config, |  | ||||||
|     }; |  | ||||||
|     use pretty_assertions::assert_eq; |     use pretty_assertions::assert_eq; | ||||||
| 
 | 
 | ||||||
|     #[tokio::test] |     #[tokio::test] | ||||||
| @ -38,23 +33,7 @@ mod test { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     async fn initialize_config() -> Config { |     async fn initialize_config() -> Config { | ||||||
|         let config = Arc::new(client::Config { |         Config::from_credentials(Ipv4Addr::new(192, 168, 5, 229), "root", "opnsense").await | ||||||
|             inactivity_timeout: Some(Duration::from_secs(5)), |  | ||||||
|             ..<_>::default() |  | ||||||
|         }); |  | ||||||
| 
 |  | ||||||
|         let credentials = SshCredentials::Password { |  | ||||||
|             username: String::from("root"), |  | ||||||
|             password: String::from("opnsense"), |  | ||||||
|         }; |  | ||||||
| 
 |  | ||||||
|         let shell = Arc::new(SshOPNSenseShell::new( |  | ||||||
|             (Ipv4Addr::new(192, 168, 5, 229), 22), |  | ||||||
|             credentials, |  | ||||||
|             config, |  | ||||||
|         )); |  | ||||||
|         let manager = Arc::new(SshConfigManager::new(shell.clone())); |  | ||||||
|         Config::new(manager, shell).await.unwrap() |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     async fn get_static_mappings() -> Vec<StaticMap> { |     async fn get_static_mappings() -> Vec<StaticMap> { | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user