diff --git a/harmony-rs/examples/opnsense/src/main.rs b/harmony-rs/examples/opnsense/src/main.rs index 723a55d..eda7b2f 100644 --- a/harmony-rs/examples/opnsense/src/main.rs +++ b/harmony-rs/examples/opnsense/src/main.rs @@ -13,6 +13,7 @@ use harmony::{ dummy::{ErrorScore, PanicScore, SuccessScore}, http::HttpScore, okd::{dhcp::OKDDhcpScore, dns::OKDDnsScore}, + opnsense::OPNSenseShellCommandScore, tftp::TftpScore, }, topology::{LogicalHost, UnmanagedRouter, Url}, @@ -91,6 +92,10 @@ async fn main() { Box::new(load_balancer_score), Box::new(tftp_score), Box::new(http_score), + Box::new(OPNSenseShellCommandScore { + opnsense: opnsense.get_opnsense_config(), + command: "touch /tmp/helloharmonytouching".to_string(), + }), Box::new(SuccessScore {}), Box::new(ErrorScore {}), Box::new(PanicScore {}), diff --git a/harmony-rs/harmony/src/domain/interpret/mod.rs b/harmony-rs/harmony/src/domain/interpret/mod.rs index 01ba62f..731d663 100644 --- a/harmony-rs/harmony/src/domain/interpret/mod.rs +++ b/harmony-rs/harmony/src/domain/interpret/mod.rs @@ -18,6 +18,7 @@ pub enum InterpretName { Http, Dummy, Panic, + OPNSense, } impl std::fmt::Display for InterpretName { @@ -30,6 +31,7 @@ impl std::fmt::Display for InterpretName { InterpretName::Http => f.write_str("Http"), InterpretName::Dummy => f.write_str("Dummy"), InterpretName::Panic => f.write_str("Panic"), + InterpretName::OPNSense => f.write_str("OPNSense"), } } } diff --git a/harmony-rs/harmony/src/infra/opnsense/mod.rs b/harmony-rs/harmony/src/infra/opnsense/mod.rs index 5d3f365..0aa5532 100644 --- a/harmony-rs/harmony/src/infra/opnsense/mod.rs +++ b/harmony-rs/harmony/src/infra/opnsense/mod.rs @@ -16,7 +16,7 @@ use crate::{ topology::{IpAddress, LogicalHost}, }; -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct OPNSenseFirewall { opnsense_config: Arc>, host: LogicalHost, @@ -36,6 +36,10 @@ impl OPNSenseFirewall { } } + pub fn get_opnsense_config(&self) -> Arc> { + self.opnsense_config.clone() + } + async fn commit_config(&self) -> Result<(), ExecutorError> { self.opnsense_config .read() diff --git a/harmony-rs/harmony/src/modules/mod.rs b/harmony-rs/harmony/src/modules/mod.rs index dd5e177..c181375 100644 --- a/harmony-rs/harmony/src/modules/mod.rs +++ b/harmony-rs/harmony/src/modules/mod.rs @@ -5,4 +5,5 @@ pub mod http; pub mod k8s; pub mod load_balancer; pub mod okd; +pub mod opnsense; pub mod tftp; diff --git a/harmony-rs/harmony/src/modules/opnsense.rs b/harmony-rs/harmony/src/modules/opnsense.rs new file mode 100644 index 0000000..9ed1c2e --- /dev/null +++ b/harmony-rs/harmony/src/modules/opnsense.rs @@ -0,0 +1,85 @@ +use std::sync::Arc; + +use async_trait::async_trait; +use tokio::sync::RwLock; + +use crate::{ + data::{Id, Version}, + interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome}, + inventory::Inventory, + score::Score, + topology::HAClusterTopology, +}; + +#[derive(Debug, Clone)] +pub struct OPNSenseShellCommandScore { + pub opnsense: Arc>, + pub command: String, +} + +impl Score for OPNSenseShellCommandScore { + fn create_interpret(&self) -> Box { + Box::new(OPNsenseInterpret { + status: InterpretStatus::QUEUED, + score: self.clone(), + }) + } + + fn name(&self) -> String { + "OPNSenseShellCommandScore".to_string() + } + + fn clone_box(&self) -> Box { + Box::new(self.clone()) + } +} + +#[derive(Debug)] +pub struct OPNsenseInterpret { + status: InterpretStatus, + score: OPNSenseShellCommandScore, +} + +#[async_trait] +impl Interpret for OPNsenseInterpret { + async fn execute( + &self, + _inventory: &Inventory, + _topology: &HAClusterTopology, + ) -> Result { + let output = self + .score + .opnsense + .read() + .await + .run_command(&self.score.command) + .await?; + + Ok(Outcome::success(format!( + "Command execution successful : {}\n\n{output}", + self.score.command + ))) + } + + fn get_name(&self) -> InterpretName { + InterpretName::OPNSense + } + + fn get_version(&self) -> Version { + Version::from("1.0.0").unwrap() + } + + fn get_status(&self) -> InterpretStatus { + self.status.clone() + } + + fn get_children(&self) -> Vec { + todo!() + } +} + +impl From for InterpretError { + fn from(value: opnsense_config::Error) -> Self { + Self::new(format!("opnsense_config::Error {value:?}")) + } +} diff --git a/harmony-rs/opnsense-config/src/config/config.rs b/harmony-rs/opnsense-config/src/config/config.rs index 614ebca..7250783 100644 --- a/harmony-rs/opnsense-config/src/config/config.rs +++ b/harmony-rs/opnsense-config/src/config/config.rs @@ -181,6 +181,10 @@ impl Config { Ok(OPNsense::from(xml)) } + + pub async fn run_command(&self, command: &str) -> Result { + self.shell.exec(command).await + } } #[cfg(test)]