feat(harmony): add OPNSense shell command execution score
Introduces a new `OPNSenseShellCommandScore` to execute shell commands on an OPNSense device within the Harmony framework. This allows for custom command execution as part of the scoring and interpretation process, enhancing the flexibility and functionality of the system.
This commit is contained in:
parent
697c669d05
commit
0b30d82793
@ -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 {}),
|
||||
|
@ -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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ use crate::{
|
||||
topology::{IpAddress, LogicalHost},
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct OPNSenseFirewall {
|
||||
opnsense_config: Arc<RwLock<opnsense_config::Config>>,
|
||||
host: LogicalHost,
|
||||
@ -36,6 +36,10 @@ impl OPNSenseFirewall {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_opnsense_config(&self) -> Arc<RwLock<opnsense_config::Config>> {
|
||||
self.opnsense_config.clone()
|
||||
}
|
||||
|
||||
async fn commit_config(&self) -> Result<(), ExecutorError> {
|
||||
self.opnsense_config
|
||||
.read()
|
||||
|
@ -5,4 +5,5 @@ pub mod http;
|
||||
pub mod k8s;
|
||||
pub mod load_balancer;
|
||||
pub mod okd;
|
||||
pub mod opnsense;
|
||||
pub mod tftp;
|
||||
|
85
harmony-rs/harmony/src/modules/opnsense.rs
Normal file
85
harmony-rs/harmony/src/modules/opnsense.rs
Normal file
@ -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<RwLock<opnsense_config::Config>>,
|
||||
pub command: String,
|
||||
}
|
||||
|
||||
impl Score for OPNSenseShellCommandScore {
|
||||
fn create_interpret(&self) -> Box<dyn Interpret> {
|
||||
Box::new(OPNsenseInterpret {
|
||||
status: InterpretStatus::QUEUED,
|
||||
score: self.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
"OPNSenseShellCommandScore".to_string()
|
||||
}
|
||||
|
||||
fn clone_box(&self) -> Box<dyn Score> {
|
||||
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<Outcome, InterpretError> {
|
||||
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<Id> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<opnsense_config::Error> for InterpretError {
|
||||
fn from(value: opnsense_config::Error) -> Self {
|
||||
Self::new(format!("opnsense_config::Error {value:?}"))
|
||||
}
|
||||
}
|
@ -181,6 +181,10 @@ impl Config {
|
||||
|
||||
Ok(OPNsense::from(xml))
|
||||
}
|
||||
|
||||
pub async fn run_command(&self, command: &str) -> Result<String, Error> {
|
||||
self.shell.exec(command).await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
Loading…
Reference in New Issue
Block a user