Merge pull request 'feat: implementation for opnsense os-node_exporter' (#173) from feat/install_opnsense_node_exporter into master
Reviewed-on: #173
This commit is contained in:
52
Cargo.lock
generated
52
Cargo.lock
generated
@@ -690,6 +690,24 @@ dependencies = [
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "brocade-snmp-server"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"brocade",
|
||||
"env_logger",
|
||||
"harmony",
|
||||
"harmony_cli",
|
||||
"harmony_macros",
|
||||
"harmony_secret",
|
||||
"harmony_types",
|
||||
"log",
|
||||
"serde",
|
||||
"tokio",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "brocade-switch"
|
||||
version = "0.1.0"
|
||||
@@ -1885,6 +1903,25 @@ dependencies = [
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "example-opnsense-node-exporter"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"cidr",
|
||||
"env_logger",
|
||||
"harmony",
|
||||
"harmony_cli",
|
||||
"harmony_macros",
|
||||
"harmony_secret",
|
||||
"harmony_secret_derive",
|
||||
"harmony_types",
|
||||
"log",
|
||||
"serde",
|
||||
"tokio",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "example-pxe"
|
||||
version = "0.1.0"
|
||||
@@ -6095,21 +6132,6 @@ version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683"
|
||||
|
||||
[[package]]
|
||||
name = "test-score"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"env_logger",
|
||||
"harmony",
|
||||
"harmony_cli",
|
||||
"harmony_macros",
|
||||
"harmony_types",
|
||||
"log",
|
||||
"tokio",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.69"
|
||||
|
||||
@@ -106,6 +106,7 @@ async fn main() {
|
||||
name: "wk2".to_string(),
|
||||
},
|
||||
],
|
||||
node_exporter: opnsense.clone(),
|
||||
switch_client: switch_client.clone(),
|
||||
network_manager: OnceLock::new(),
|
||||
};
|
||||
|
||||
@@ -83,6 +83,7 @@ pub async fn get_topology() -> HAClusterTopology {
|
||||
name: "bootstrap".to_string(),
|
||||
},
|
||||
workers: vec![],
|
||||
node_exporter: opnsense.clone(),
|
||||
switch_client: switch_client.clone(),
|
||||
network_manager: OnceLock::new(),
|
||||
}
|
||||
|
||||
@@ -78,6 +78,7 @@ pub async fn get_topology() -> HAClusterTopology {
|
||||
name: "cp0".to_string(),
|
||||
},
|
||||
workers: vec![],
|
||||
node_exporter: opnsense.clone(),
|
||||
switch_client: switch_client.clone(),
|
||||
network_manager: OnceLock::new(),
|
||||
}
|
||||
|
||||
@@ -78,6 +78,7 @@ async fn main() {
|
||||
name: "cp0".to_string(),
|
||||
},
|
||||
workers: vec![],
|
||||
node_exporter: opnsense.clone(),
|
||||
switch_client: switch_client.clone(),
|
||||
network_manager: OnceLock::new(),
|
||||
};
|
||||
|
||||
21
examples/opnsense_node_exporter/Cargo.toml
Normal file
21
examples/opnsense_node_exporter/Cargo.toml
Normal file
@@ -0,0 +1,21 @@
|
||||
[package]
|
||||
name = "example-opnsense-node-exporter"
|
||||
edition = "2024"
|
||||
version.workspace = true
|
||||
readme.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
harmony = { path = "../../harmony" }
|
||||
harmony_cli = { path = "../../harmony_cli" }
|
||||
harmony_types = { path = "../../harmony_types" }
|
||||
harmony_secret = { path = "../../harmony_secret" }
|
||||
harmony_secret_derive = { path = "../../harmony_secret_derive" }
|
||||
cidr = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
harmony_macros = { path = "../../harmony_macros" }
|
||||
log = { workspace = true }
|
||||
env_logger = { workspace = true }
|
||||
url = { workspace = true }
|
||||
serde.workspace = true
|
||||
async-trait.workspace = true
|
||||
80
examples/opnsense_node_exporter/src/main.rs
Normal file
80
examples/opnsense_node_exporter/src/main.rs
Normal file
@@ -0,0 +1,80 @@
|
||||
use std::{
|
||||
net::{IpAddr, Ipv4Addr},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use cidr::Ipv4Cidr;
|
||||
use harmony::{
|
||||
executors::ExecutorError,
|
||||
hardware::{HostCategory, Location, PhysicalHost, SwitchGroup},
|
||||
infra::opnsense::OPNSenseManagementInterface,
|
||||
inventory::Inventory,
|
||||
modules::opnsense::node_exporter::NodeExporterScore,
|
||||
topology::{
|
||||
HAClusterTopology, LogicalHost, PreparationError, PreparationOutcome, Topology,
|
||||
UnmanagedRouter, node_exporter::NodeExporter,
|
||||
},
|
||||
};
|
||||
use harmony_macros::{ip, ipv4, mac_address};
|
||||
|
||||
#[derive(Debug)]
|
||||
struct OpnSenseTopology {
|
||||
node_exporter: Arc<dyn NodeExporter>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Topology for OpnSenseTopology {
|
||||
async fn ensure_ready(&self) -> Result<PreparationOutcome, PreparationError> {
|
||||
Ok(PreparationOutcome::Success {
|
||||
details: "Success".to_string(),
|
||||
})
|
||||
}
|
||||
fn name(&self) -> &str {
|
||||
"OpnsenseTopology"
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl NodeExporter for OpnSenseTopology {
|
||||
async fn ensure_initialized(&self) -> Result<(), ExecutorError> {
|
||||
self.node_exporter.ensure_initialized().await
|
||||
}
|
||||
|
||||
async fn commit_config(&self) -> Result<(), ExecutorError> {
|
||||
self.node_exporter.commit_config().await
|
||||
}
|
||||
|
||||
async fn reload_restart(&self) -> Result<(), ExecutorError> {
|
||||
self.node_exporter.reload_restart().await
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let firewall = harmony::topology::LogicalHost {
|
||||
ip: ip!("192.168.1.1"),
|
||||
name: String::from("fw0"),
|
||||
};
|
||||
|
||||
let opnsense = Arc::new(
|
||||
harmony::infra::opnsense::OPNSenseFirewall::new(firewall, None, "root", "opnsense").await,
|
||||
);
|
||||
|
||||
let topology = OpnSenseTopology {
|
||||
node_exporter: opnsense.clone(),
|
||||
};
|
||||
|
||||
let inventory = Inventory::empty();
|
||||
|
||||
let node_exporter_score = NodeExporterScore {};
|
||||
|
||||
harmony_cli::run(
|
||||
inventory,
|
||||
topology,
|
||||
vec![Box::new(node_exporter_score)],
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
@@ -9,7 +9,7 @@ use harmony_types::{
|
||||
use log::debug;
|
||||
use log::info;
|
||||
|
||||
use crate::{data::FileContent, executors::ExecutorError};
|
||||
use crate::{data::FileContent, executors::ExecutorError, topology::node_exporter::NodeExporter};
|
||||
use crate::{infra::network_manager::OpenShiftNmStateNetworkManager, topology::PortConfig};
|
||||
use crate::{modules::inventory::HarmonyDiscoveryStrategy, topology::PxeOptions};
|
||||
|
||||
@@ -19,7 +19,6 @@ use super::{
|
||||
NetworkManager, PreparationError, PreparationOutcome, Router, Switch, SwitchClient,
|
||||
SwitchError, TftpServer, Topology, k8s::K8sClient,
|
||||
};
|
||||
|
||||
use std::sync::{Arc, OnceLock};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -32,6 +31,7 @@ pub struct HAClusterTopology {
|
||||
pub tftp_server: Arc<dyn TftpServer>,
|
||||
pub http_server: Arc<dyn HttpServer>,
|
||||
pub dns_server: Arc<dyn DnsServer>,
|
||||
pub node_exporter: Arc<dyn NodeExporter>,
|
||||
pub switch_client: Arc<dyn SwitchClient>,
|
||||
pub bootstrap_host: LogicalHost,
|
||||
pub control_plane: Vec<LogicalHost>,
|
||||
@@ -116,6 +116,7 @@ impl HAClusterTopology {
|
||||
tftp_server: dummy_infra.clone(),
|
||||
http_server: dummy_infra.clone(),
|
||||
dns_server: dummy_infra.clone(),
|
||||
node_exporter: dummy_infra.clone(),
|
||||
switch_client: dummy_infra.clone(),
|
||||
bootstrap_host: dummy_host,
|
||||
control_plane: vec![],
|
||||
@@ -320,6 +321,23 @@ impl NetworkManager for HAClusterTopology {
|
||||
async fn configure_bond(&self, config: &HostNetworkConfig) -> Result<(), NetworkError> {
|
||||
self.network_manager().await.configure_bond(config).await
|
||||
}
|
||||
|
||||
//TODO add snmp here
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl NodeExporter for HAClusterTopology {
|
||||
async fn ensure_initialized(&self) -> Result<(), ExecutorError> {
|
||||
self.node_exporter.ensure_initialized().await
|
||||
}
|
||||
|
||||
async fn commit_config(&self) -> Result<(), ExecutorError> {
|
||||
self.node_exporter.commit_config().await
|
||||
}
|
||||
|
||||
async fn reload_restart(&self) -> Result<(), ExecutorError> {
|
||||
self.node_exporter.reload_restart().await
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -509,6 +527,21 @@ impl DnsServer for DummyInfra {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl NodeExporter for DummyInfra {
|
||||
async fn ensure_initialized(&self) -> Result<(), ExecutorError> {
|
||||
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
||||
}
|
||||
|
||||
async fn commit_config(&self) -> Result<(), ExecutorError> {
|
||||
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
||||
}
|
||||
|
||||
async fn reload_restart(&self) -> Result<(), ExecutorError> {
|
||||
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl SwitchClient for DummyInfra {
|
||||
async fn setup(&self) -> Result<(), SwitchError> {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
mod failover;
|
||||
mod ha_cluster;
|
||||
pub mod ingress;
|
||||
pub mod node_exporter;
|
||||
pub use failover::*;
|
||||
use harmony_types::net::IpAddress;
|
||||
mod host_binding;
|
||||
|
||||
17
harmony/src/domain/topology/node_exporter.rs
Normal file
17
harmony/src/domain/topology/node_exporter.rs
Normal file
@@ -0,0 +1,17 @@
|
||||
use async_trait::async_trait;
|
||||
|
||||
use crate::executors::ExecutorError;
|
||||
|
||||
#[async_trait]
|
||||
pub trait NodeExporter: Send + Sync + std::fmt::Debug {
|
||||
async fn ensure_initialized(&self) -> Result<(), ExecutorError>;
|
||||
async fn commit_config(&self) -> Result<(), ExecutorError>;
|
||||
async fn reload_restart(&self) -> Result<(), ExecutorError>;
|
||||
}
|
||||
|
||||
// //TODO complete this impl
|
||||
// impl std::fmt::Debug for dyn NodeExporter {
|
||||
// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
// f.write_fmt(format_args!("NodeExporter ",))
|
||||
// }
|
||||
// }
|
||||
@@ -4,6 +4,7 @@ mod firewall;
|
||||
mod http;
|
||||
mod load_balancer;
|
||||
mod management;
|
||||
pub mod node_exporter;
|
||||
mod tftp;
|
||||
use std::sync::Arc;
|
||||
|
||||
|
||||
47
harmony/src/infra/opnsense/node_exporter.rs
Normal file
47
harmony/src/infra/opnsense/node_exporter.rs
Normal file
@@ -0,0 +1,47 @@
|
||||
use async_trait::async_trait;
|
||||
use log::debug;
|
||||
|
||||
use crate::{
|
||||
executors::ExecutorError, infra::opnsense::OPNSenseFirewall,
|
||||
topology::node_exporter::NodeExporter,
|
||||
};
|
||||
|
||||
#[async_trait]
|
||||
impl NodeExporter for OPNSenseFirewall {
|
||||
async fn ensure_initialized(&self) -> Result<(), ExecutorError> {
|
||||
let mut config = self.opnsense_config.write().await;
|
||||
let node_exporter = config.node_exporter();
|
||||
if let Some(config) = node_exporter.get_full_config() {
|
||||
debug!(
|
||||
"Node exporter available in opnsense config, assuming it is already installed. {config:?}"
|
||||
);
|
||||
} else {
|
||||
config
|
||||
.install_package("os-node_exporter")
|
||||
.await
|
||||
.map_err(|e| {
|
||||
ExecutorError::UnexpectedError(format!("Executor failed when trying to install os-node_exporter package with error {e:?}"
|
||||
))
|
||||
})?;
|
||||
}
|
||||
|
||||
config
|
||||
.node_exporter()
|
||||
.enable(true)
|
||||
.map_err(|e| ExecutorError::UnexpectedError(e.to_string()))?;
|
||||
Ok(())
|
||||
}
|
||||
async fn commit_config(&self) -> Result<(), ExecutorError> {
|
||||
OPNSenseFirewall::commit_config(self).await
|
||||
}
|
||||
|
||||
async fn reload_restart(&self) -> Result<(), ExecutorError> {
|
||||
self.opnsense_config
|
||||
.write()
|
||||
.await
|
||||
.node_exporter()
|
||||
.reload_restart()
|
||||
.await
|
||||
.map_err(|e| ExecutorError::UnexpectedError(e.to_string()))
|
||||
}
|
||||
}
|
||||
@@ -69,13 +69,12 @@ impl<T: Topology> Interpret<T> for BrocadeEnableSnmpInterpret {
|
||||
|
||||
let brocade = brocade::init(
|
||||
&switch_addresses,
|
||||
22,
|
||||
&config.username,
|
||||
&config.password,
|
||||
Some(BrocadeOptions {
|
||||
BrocadeOptions {
|
||||
dry_run: self.score.dry_run,
|
||||
..Default::default()
|
||||
}),
|
||||
},
|
||||
)
|
||||
.await
|
||||
.expect("Brocade client failed to connect");
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
pub mod node_exporter;
|
||||
mod shell;
|
||||
mod upgrade;
|
||||
pub use shell::*;
|
||||
|
||||
70
harmony/src/modules/opnsense/node_exporter.rs
Normal file
70
harmony/src/modules/opnsense/node_exporter.rs
Normal file
@@ -0,0 +1,70 @@
|
||||
use async_trait::async_trait;
|
||||
use harmony_types::id::Id;
|
||||
use log::info;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::{
|
||||
data::Version,
|
||||
interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome},
|
||||
inventory::Inventory,
|
||||
score::Score,
|
||||
topology::{Topology, node_exporter::NodeExporter},
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct NodeExporterScore {}
|
||||
|
||||
impl<T: Topology + NodeExporter> Score<T> for NodeExporterScore {
|
||||
fn name(&self) -> String {
|
||||
"NodeExporterScore".to_string()
|
||||
}
|
||||
|
||||
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
||||
Box::new(NodeExporterInterpret {})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct NodeExporterInterpret {}
|
||||
|
||||
#[async_trait]
|
||||
impl<T: Topology + NodeExporter> Interpret<T> for NodeExporterInterpret {
|
||||
async fn execute(
|
||||
&self,
|
||||
_inventory: &Inventory,
|
||||
node_exporter: &T,
|
||||
) -> Result<Outcome, InterpretError> {
|
||||
info!(
|
||||
"Making sure node exporter is initiailized: {:?}",
|
||||
node_exporter.ensure_initialized().await?
|
||||
);
|
||||
|
||||
info!("Applying Node Exporter configuration");
|
||||
|
||||
node_exporter.commit_config().await?;
|
||||
|
||||
info!("Reloading and restarting Node Exporter");
|
||||
|
||||
node_exporter.reload_restart().await?;
|
||||
|
||||
Ok(Outcome::success(format!(
|
||||
"NodeExporter successfully configured"
|
||||
)))
|
||||
}
|
||||
|
||||
fn get_name(&self) -> InterpretName {
|
||||
InterpretName::Custom("NodeExporter")
|
||||
}
|
||||
|
||||
fn get_version(&self) -> Version {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn get_status(&self) -> InterpretStatus {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn get_children(&self) -> Vec<Id> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ pub struct OPNsense {
|
||||
pub interfaces: NamedList<Interface>,
|
||||
pub dhcpd: NamedList<DhcpInterface>,
|
||||
pub snmpd: Snmpd,
|
||||
pub syslog: Syslog,
|
||||
pub syslog: Option<Syslog>,
|
||||
pub nat: Nat,
|
||||
pub filter: Filters,
|
||||
pub load_balancer: Option<LoadBalancer>,
|
||||
@@ -191,7 +191,7 @@ pub struct System {
|
||||
pub webgui: WebGui,
|
||||
pub usevirtualterminal: u8,
|
||||
pub disablenatreflection: Option<String>,
|
||||
pub disableconsolemenu: u8,
|
||||
pub disableconsolemenu: Option<u8>,
|
||||
pub disablevlanhwfilter: u8,
|
||||
pub disablechecksumoffloading: u8,
|
||||
pub disablesegmentationoffloading: u8,
|
||||
@@ -235,16 +235,16 @@ pub struct System {
|
||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||
pub struct Ssh {
|
||||
pub group: String,
|
||||
pub noauto: u8,
|
||||
pub interfaces: MaybeString,
|
||||
pub kex: MaybeString,
|
||||
pub ciphers: MaybeString,
|
||||
pub macs: MaybeString,
|
||||
pub keys: MaybeString,
|
||||
pub enabled: String,
|
||||
pub passwordauth: u8,
|
||||
pub keysig: MaybeString,
|
||||
pub permitrootlogin: u8,
|
||||
pub noauto: Option<u8>,
|
||||
pub interfaces: Option<MaybeString>,
|
||||
pub kex: Option<MaybeString>,
|
||||
pub ciphers: Option<MaybeString>,
|
||||
pub macs: Option<MaybeString>,
|
||||
pub keys: Option<MaybeString>,
|
||||
pub enabled: Option<String>,
|
||||
pub passwordauth: Option<u8>,
|
||||
pub keysig: Option<MaybeString>,
|
||||
pub permitrootlogin: Option<u8>,
|
||||
pub rekeylimit: Option<MaybeString>,
|
||||
}
|
||||
|
||||
@@ -308,11 +308,11 @@ pub struct WebGui {
|
||||
pub protocol: String,
|
||||
#[yaserde(rename = "ssl-certref")]
|
||||
pub ssl_certref: String,
|
||||
pub port: MaybeString,
|
||||
pub port: Option<MaybeString>,
|
||||
#[yaserde(rename = "ssl-ciphers")]
|
||||
pub ssl_ciphers: MaybeString,
|
||||
pub interfaces: MaybeString,
|
||||
pub compression: MaybeString,
|
||||
pub ssl_ciphers: Option<MaybeString>,
|
||||
pub interfaces: Option<MaybeString>,
|
||||
pub compression: Option<MaybeString>,
|
||||
pub nohttpreferercheck: Option<u8>,
|
||||
}
|
||||
|
||||
@@ -436,7 +436,7 @@ pub struct OPNsenseXmlSection {
|
||||
#[yaserde(rename = "Interfaces")]
|
||||
pub interfaces: Option<ConfigInterfaces>,
|
||||
#[yaserde(rename = "NodeExporter")]
|
||||
pub node_exporter: Option<RawXml>,
|
||||
pub node_exporter: Option<NodeExporter>,
|
||||
#[yaserde(rename = "Kea")]
|
||||
pub kea: Option<RawXml>,
|
||||
pub monit: Option<Monit>,
|
||||
@@ -1613,3 +1613,21 @@ pub struct Ifgroups {
|
||||
#[yaserde(attribute = true)]
|
||||
pub version: String,
|
||||
}
|
||||
|
||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||
pub struct NodeExporter {
|
||||
pub enabled: u8,
|
||||
pub listenaddress: Option<MaybeString>,
|
||||
pub listenport: u16,
|
||||
pub cpu: u8,
|
||||
pub exec: u8,
|
||||
pub filesystem: u8,
|
||||
pub loadavg: u8,
|
||||
pub meminfo: u8,
|
||||
pub netdev: u8,
|
||||
pub time: u8,
|
||||
pub devstat: u8,
|
||||
pub interrupts: u8,
|
||||
pub ntp: u8,
|
||||
pub zfs: u8,
|
||||
}
|
||||
|
||||
@@ -5,7 +5,8 @@ use crate::{
|
||||
error::Error,
|
||||
modules::{
|
||||
caddy::CaddyConfig, dhcp_legacy::DhcpConfigLegacyISC, dns::UnboundDnsConfig,
|
||||
dnsmasq::DhcpConfigDnsMasq, load_balancer::LoadBalancerConfig, tftp::TftpConfig,
|
||||
dnsmasq::DhcpConfigDnsMasq, load_balancer::LoadBalancerConfig,
|
||||
node_exporter::NodeExporterConfig, tftp::TftpConfig,
|
||||
},
|
||||
};
|
||||
use log::{debug, info, trace, warn};
|
||||
@@ -13,6 +14,7 @@ use opnsense_config_xml::OPNsense;
|
||||
use russh::client;
|
||||
use serde::Serialize;
|
||||
use sha2::Digest;
|
||||
use tokio::time::{sleep, Duration};
|
||||
|
||||
use super::{ConfigManager, OPNsenseShell};
|
||||
|
||||
@@ -71,6 +73,10 @@ impl Config {
|
||||
LoadBalancerConfig::new(&mut self.opnsense, self.shell.clone())
|
||||
}
|
||||
|
||||
pub fn node_exporter(&mut self) -> NodeExporterConfig<'_> {
|
||||
NodeExporterConfig::new(&mut self.opnsense, self.shell.clone())
|
||||
}
|
||||
|
||||
pub async fn upload_files(&self, source: &str, destination: &str) -> Result<String, Error> {
|
||||
self.shell.upload_folder(source, destination).await
|
||||
}
|
||||
@@ -150,7 +156,8 @@ impl Config {
|
||||
|
||||
async fn reload_config(&mut self) -> Result<(), Error> {
|
||||
info!("Reloading opnsense live config");
|
||||
let (opnsense, sha2) = Self::get_opnsense_instance(self.repository.clone()).await?;
|
||||
let (opnsense, _sha2) = Self::get_opnsense_instance(self.repository.clone()).await?;
|
||||
self.opnsense = opnsense;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -4,4 +4,5 @@ pub mod dhcp_legacy;
|
||||
pub mod dns;
|
||||
pub mod dnsmasq;
|
||||
pub mod load_balancer;
|
||||
pub mod node_exporter;
|
||||
pub mod tftp;
|
||||
|
||||
54
opnsense-config/src/modules/node_exporter.rs
Normal file
54
opnsense-config/src/modules/node_exporter.rs
Normal file
@@ -0,0 +1,54 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use opnsense_config_xml::{NodeExporter, OPNsense};
|
||||
|
||||
use crate::{config::OPNsenseShell, Error};
|
||||
|
||||
pub struct NodeExporterConfig<'a> {
|
||||
opnsense: &'a mut OPNsense,
|
||||
opnsense_shell: Arc<dyn OPNsenseShell>,
|
||||
}
|
||||
|
||||
impl<'a> NodeExporterConfig<'a> {
|
||||
pub fn new(opnsense: &'a mut OPNsense, opnsense_shell: Arc<dyn OPNsenseShell>) -> Self {
|
||||
Self {
|
||||
opnsense,
|
||||
opnsense_shell,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_full_config(&self) -> &Option<NodeExporter> {
|
||||
&self.opnsense.opnsense.node_exporter
|
||||
}
|
||||
|
||||
fn with_node_exporter<F, R>(&mut self, f: F) -> Result<R, &'static str>
|
||||
where
|
||||
F: FnOnce(&mut NodeExporter) -> R,
|
||||
{
|
||||
match &mut self.opnsense.opnsense.node_exporter.as_mut() {
|
||||
Some(node_exporter) => Ok(f(node_exporter)),
|
||||
None => Err("node exporter is not yet installed"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn enable(&mut self, enabled: bool) -> Result<(), &'static str> {
|
||||
self.with_node_exporter(|node_exporter| node_exporter.enabled = enabled as u8)
|
||||
.map(|_| ())
|
||||
}
|
||||
|
||||
pub async fn reload_restart(&self) -> Result<(), Error> {
|
||||
self.opnsense_shell
|
||||
.exec("configctl node_exporter stop")
|
||||
.await?;
|
||||
self.opnsense_shell
|
||||
.exec("configctl template reload OPNsense/NodeExporter")
|
||||
.await?;
|
||||
self.opnsense_shell
|
||||
.exec("configctl node_exporter configtest")
|
||||
.await?;
|
||||
self.opnsense_shell
|
||||
.exec("configctl node_exporter start")
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user