restructure code from lib to mod
This commit is contained in:
270
src/rsnmplib/config.rs
Normal file
270
src/rsnmplib/config.rs
Normal file
@@ -0,0 +1,270 @@
|
||||
use clap::Parser;
|
||||
use figment::{
|
||||
Figment,
|
||||
providers::{Format, Serialized, Yaml},
|
||||
};
|
||||
use log::warn;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::error::Error;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[allow(unused)]
|
||||
use flexi_logger::{
|
||||
FileSpec, LogSpecification, Logger, LoggerHandle, colored_with_thread, with_thread,
|
||||
writers::{SyslogConnection, SyslogLineHeader, SyslogWriter},
|
||||
};
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
pub(crate) struct DataFunctionsInterval {
|
||||
pub(crate) log_debug_watcher: Option<u64>,
|
||||
multipath: Option<u64>,
|
||||
meminfo: Option<u64>,
|
||||
processes: Option<u64>,
|
||||
bonding: Option<u64>,
|
||||
filesum: Option<u64>,
|
||||
}
|
||||
|
||||
impl Default for DataFunctionsInterval {
|
||||
fn default() -> Self {
|
||||
DataFunctionsInterval {
|
||||
log_debug_watcher: Some(5),
|
||||
multipath: Some(60),
|
||||
meminfo: Some(30),
|
||||
processes: Some(30),
|
||||
bonding: Some(30),
|
||||
filesum: Some(60),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DataFunctionsInterval {
|
||||
pub fn meminfo(&self) -> Option<u64> {
|
||||
self.meminfo
|
||||
}
|
||||
pub fn processes(&self) -> Option<u64> {
|
||||
self.processes
|
||||
}
|
||||
pub fn filesum(&self) -> Option<u64> {
|
||||
self.filesum
|
||||
}
|
||||
pub fn bonding(&self) -> Option<u64> {
|
||||
self.bonding
|
||||
}
|
||||
pub fn multipath(&self) -> Option<u64> {
|
||||
self.multipath
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||
pub(crate) struct DataFunctionsFilesum {
|
||||
pub(crate) passwd: Option<String>,
|
||||
pub(crate) shadow: Option<String>,
|
||||
pub(crate) group: Option<String>,
|
||||
pub(crate) authorized_keys: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
pub struct DataFunctionsExtra {
|
||||
multipath: Option<String>,
|
||||
bonding: Option<String>,
|
||||
filesum: DataFunctionsFilesum,
|
||||
}
|
||||
|
||||
impl Default for DataFunctionsExtra {
|
||||
fn default() -> Self {
|
||||
DataFunctionsExtra {
|
||||
multipath: None,
|
||||
bonding: None,
|
||||
filesum: DataFunctionsFilesum {
|
||||
passwd: None,
|
||||
shadow: None,
|
||||
group: None,
|
||||
authorized_keys: None,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DataFunctionsExtra {
|
||||
pub(crate) fn filesum(&self) -> DataFunctionsFilesum {
|
||||
self.filesum.clone()
|
||||
}
|
||||
pub(crate) fn multipath(&self) -> Option<String> {
|
||||
self.multipath.clone()
|
||||
}
|
||||
pub(crate) fn bonding(&self) -> Option<String> {
|
||||
self.bonding.clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug, Clone, clap::ValueEnum)]
|
||||
enum LogConfig {
|
||||
None,
|
||||
StdErr,
|
||||
Syslog,
|
||||
Logfile,
|
||||
LogfileAndSyslog,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
pub struct AppConfig {
|
||||
logoutput: LogConfig,
|
||||
logdir: String,
|
||||
logfile_basename: String,
|
||||
loglevel: String,
|
||||
pub(crate) base_oid: String,
|
||||
pub(crate) debug_log_marker: PathBuf,
|
||||
pub(crate) intervals: DataFunctionsInterval,
|
||||
pub(crate) extra_config: DataFunctionsExtra,
|
||||
}
|
||||
|
||||
impl Default for AppConfig {
|
||||
fn default() -> Self {
|
||||
AppConfig {
|
||||
logoutput: LogConfig::Logfile,
|
||||
logdir: "log".to_string(),
|
||||
logfile_basename: "rsnmpagent".to_string(),
|
||||
loglevel: "info".to_string(),
|
||||
base_oid: ".1.3.6.1.4.1.8072.9999.9999".to_string(),
|
||||
debug_log_marker: "debug.marker".to_string().into(),
|
||||
intervals: DataFunctionsInterval::default(),
|
||||
extra_config: DataFunctionsExtra::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AppConfig {
|
||||
pub fn base_oid(&self) -> &str {
|
||||
&self.base_oid
|
||||
}
|
||||
}
|
||||
|
||||
// Define the struct to hold the command-line arguments.
|
||||
#[derive(Parser, Deserialize, Serialize, Debug)]
|
||||
#[command(author, version, about = "rsnmpd, snmpd passpersist extension", long_about = None)]
|
||||
struct Cli {
|
||||
/// Optional path to a configuration file.
|
||||
#[arg(short, long, value_name = "FILENAME", default_value = "config.yml")]
|
||||
configfile: PathBuf,
|
||||
|
||||
#[arg(short, long, value_name = "LOGOUTPUT", value_enum, default_value_t = LogConfig::Logfile)]
|
||||
logoutput: LogConfig,
|
||||
|
||||
#[arg(short, long)]
|
||||
show_parsed_config: bool,
|
||||
}
|
||||
|
||||
pub fn build_config() -> Result<AppConfig, Box<dyn Error>> {
|
||||
let cli = Cli::parse();
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
if cli.show_parsed_config {
|
||||
eprintln!("Parsed config line options: {:#?}", cli);
|
||||
}
|
||||
|
||||
let config: AppConfig = Figment::new()
|
||||
.merge(Serialized::defaults(AppConfig::default()))
|
||||
.merge(Yaml::file(&cli.configfile))
|
||||
.merge(Serialized::defaults(&cli))
|
||||
.extract()?;
|
||||
|
||||
if cli.show_parsed_config {
|
||||
eprintln!("Loaded configuration: {:#?}", config);
|
||||
}
|
||||
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
pub fn start_logging(config: &AppConfig) -> Result<LoggerHandle, Box<dyn Error>> {
|
||||
let r = match config.logoutput {
|
||||
LogConfig::None => {
|
||||
let handle = Logger::with(LogSpecification::off()).do_not_log().start()?;
|
||||
warn!("Starting None logging config");
|
||||
handle
|
||||
}
|
||||
LogConfig::StdErr => {
|
||||
let handle = Logger::try_with_str(&config.loglevel)?
|
||||
.format(colored_with_thread)
|
||||
.start()?;
|
||||
warn!("Starting StdErr logging config with level: {}", config.loglevel);
|
||||
handle
|
||||
}
|
||||
LogConfig::Syslog => {
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
Err("Syslog in windows not implemented")?
|
||||
}
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
let syslog_writer = SyslogWriter::builder(
|
||||
SyslogConnection::syslog_call(),
|
||||
SyslogLineHeader::Rfc3164,
|
||||
flexi_logger::writers::SyslogFacility::SystemDaemons,
|
||||
)
|
||||
.build()?;
|
||||
let handle = Logger::try_with_str(&config.loglevel)?
|
||||
.log_to_writer(syslog_writer)
|
||||
.format(with_thread)
|
||||
.start()?;
|
||||
warn!("Starting Syslog logging config with level: {}", config.loglevel);
|
||||
handle
|
||||
}
|
||||
}
|
||||
LogConfig::Logfile => {
|
||||
let handle = Logger::try_with_str(&config.loglevel)?
|
||||
.log_to_file(
|
||||
FileSpec::default()
|
||||
.directory(&config.logdir)
|
||||
.basename(&config.logfile_basename)
|
||||
.suppress_timestamp(),
|
||||
)
|
||||
.append()
|
||||
.format(with_thread)
|
||||
.start()?;
|
||||
warn!(
|
||||
"Starting Logfile logging to {} with level: {}",
|
||||
config.logdir, config.loglevel
|
||||
);
|
||||
handle
|
||||
}
|
||||
LogConfig::LogfileAndSyslog => {
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
eprintln!(
|
||||
"Starting LogfileAndSyslog logging to {} with level: {}",
|
||||
config.logdir, config.loglevel
|
||||
);
|
||||
Err("Syslog in windows not implemented")?
|
||||
}
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
let handle = Logger::try_with_str(&config.loglevel)
|
||||
.expect("Log start failed")
|
||||
.log_to_file(
|
||||
FileSpec::default()
|
||||
.directory(&config.logdir)
|
||||
.basename(&config.logfile_basename)
|
||||
.suppress_timestamp(),
|
||||
)
|
||||
.append()
|
||||
.format(with_thread)
|
||||
.add_writer(
|
||||
"syslog",
|
||||
SyslogWriter::builder(
|
||||
SyslogConnection::syslog_call(),
|
||||
SyslogLineHeader::Rfc3164,
|
||||
flexi_logger::writers::SyslogFacility::SystemDaemons,
|
||||
)
|
||||
.build()?,
|
||||
)
|
||||
.start()?;
|
||||
warn!(
|
||||
"Starting LogfileAndSyslog logging to {} with level: {}",
|
||||
config.logdir, config.loglevel
|
||||
);
|
||||
handle
|
||||
}
|
||||
}
|
||||
};
|
||||
Ok(r)
|
||||
}
|
||||
Reference in New Issue
Block a user