Load default configuration overrides from files
This commit is contained in:
parent
a6784fdce0
commit
24baa3a6a6
|
@ -396,6 +396,7 @@ name = "haunter"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"scraper",
|
||||
"tempfile",
|
||||
"thirtyfour_sync",
|
||||
]
|
||||
|
||||
|
|
|
@ -8,3 +8,4 @@ edition = "2021"
|
|||
[dependencies]
|
||||
thirtyfour_sync = "0.27"
|
||||
scraper = "0.13"
|
||||
tempfile = "3"
|
|
@ -0,0 +1,125 @@
|
|||
use std::io::Read;
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
|
||||
pub struct Conf {
|
||||
pub job_dir: String,
|
||||
pub output_dir: String,
|
||||
pub check_interval: Duration,
|
||||
}
|
||||
|
||||
impl Conf {
|
||||
pub fn update_from_file(&mut self, f: &str) {
|
||||
let path = std::path::Path::new(f);
|
||||
let mut file = match std::fs::File::open(&path) {
|
||||
Err(why) => {
|
||||
println!("Could not open file '{}': {}", path.display(), why); return;
|
||||
},
|
||||
Ok(file) => file,
|
||||
};
|
||||
let mut content = String::new();
|
||||
match file.read_to_string(&mut content) {
|
||||
Err(why) => println!("Could not read from file '{}': {}", path.display(), why),
|
||||
Ok(_) => (),
|
||||
}
|
||||
|
||||
let lines = content.lines();
|
||||
for line in lines {
|
||||
if line.starts_with('#') {
|
||||
continue;
|
||||
}
|
||||
let result = line.split_once('=');
|
||||
if result.is_none() {
|
||||
println!("Skipping configuration line '{}', no key-value delimiter (=) found", line);
|
||||
continue;
|
||||
}
|
||||
|
||||
let key = result.unwrap().0.trim();
|
||||
let value = result.unwrap().1.trim();
|
||||
if key.eq("") || value.eq("") {
|
||||
println!("Skipping configuration line '{}', no key or value side is empty", line);
|
||||
continue;
|
||||
}
|
||||
|
||||
match key {
|
||||
"job_dir" => {
|
||||
println!("{} changed from '{}' to '{}' by line in '{}'", key, self.job_dir, value, path.display());
|
||||
self.job_dir = String::from_str(value).unwrap();
|
||||
},
|
||||
"output_dir" => {
|
||||
println!("{} changed from '{}' to '{}' by line in '{}'", key, self.output_dir, value, path.display());
|
||||
self.output_dir = String::from_str(value).unwrap();
|
||||
},
|
||||
"check_interval" => {
|
||||
let converted_value = match value.parse::<u64>() {
|
||||
Err(why) => { println!("Failed to convert '{}' to u64: {}", value, why); continue;},
|
||||
Ok(v) => v,
|
||||
};
|
||||
println!("{} changed from '{}' to '{}' by line in '{}'", key, self.check_interval.as_secs(), value, path.display());
|
||||
self.check_interval = Duration::new(converted_value, 0);
|
||||
},
|
||||
_ => {
|
||||
println!("Unknown key '{}' in file '{}'", key, path.display());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use std::io::Write;
|
||||
use std::str::FromStr;
|
||||
use tempfile::NamedTempFile;
|
||||
use std::time::Duration;
|
||||
|
||||
use super::*;
|
||||
|
||||
fn get_default_conf() -> Conf {
|
||||
return Conf {
|
||||
job_dir: String::from_str("jobs.d").unwrap(),
|
||||
output_dir: String::from_str("results.d").unwrap(),
|
||||
check_interval: Duration::new(15*60, 0),
|
||||
};
|
||||
}
|
||||
|
||||
fn write_conf_to_temp_file(content: &str) -> NamedTempFile {
|
||||
let mut f = NamedTempFile::new().unwrap();
|
||||
f.write_all(content.as_bytes());
|
||||
return f;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_not_existing() {
|
||||
let mut conf = get_default_conf();
|
||||
conf.update_from_file("/not/a/real/file");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_all_values() {
|
||||
let mut conf = get_default_conf();
|
||||
let tf = write_conf_to_temp_file(r#"
|
||||
job_dir = /value
|
||||
output_dir=/var/lib/output
|
||||
check_interval=3600
|
||||
"#);
|
||||
let f = tf.path().to_str().unwrap();
|
||||
conf.update_from_file(f);
|
||||
assert!(String::from_str("/value").unwrap().eq(&conf.job_dir));
|
||||
assert!(String::from_str("/var/lib/output").unwrap().eq(&conf.output_dir));
|
||||
assert_eq!(3600, conf.check_interval.as_secs());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_non_numeric_check_interval_fails() {
|
||||
let mut conf = get_default_conf();
|
||||
let tf = write_conf_to_temp_file(r#"
|
||||
check_interval=d3600
|
||||
"#);
|
||||
let f = tf.path().to_str().unwrap();
|
||||
conf.update_from_file(f);
|
||||
assert_eq!(15*60, conf.check_interval.as_secs());
|
||||
|
||||
}
|
||||
}
|
27
src/main.rs
27
src/main.rs
|
@ -1,9 +1,13 @@
|
|||
use std::option;
|
||||
use std::env;
|
||||
use std::str::FromStr;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
use std::time::Instant;
|
||||
use thirtyfour_sync::WebDriverCommands;
|
||||
|
||||
mod conf;
|
||||
use conf::Conf;
|
||||
|
||||
struct Job<'a> {
|
||||
url: &'a str,
|
||||
selector: &'a str,
|
||||
|
@ -20,7 +24,26 @@ struct ThreadJob<'a> {
|
|||
>,
|
||||
last_result: Option<String>,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut conf = Conf {
|
||||
job_dir: String::from_str("jobs.d").unwrap(),
|
||||
output_dir: String::from_str("results.d").unwrap(),
|
||||
check_interval: Duration::new(15*60, 0),
|
||||
};
|
||||
|
||||
conf.update_from_file("/etc/haunter/haunter.conf");
|
||||
|
||||
let mut args = env::args();
|
||||
while let Some(arg) = args.next() {
|
||||
if arg.eq("-f") {
|
||||
match args.next() {
|
||||
Some(file) => conf.update_from_file(file.as_str()),
|
||||
_ => {println!("Missing argument after '-f'"); std::process::exit(1);},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
let driver = "http://localhost:4444";
|
||||
let mut jobs = Vec::new();
|
||||
let some_job = Job {
|
||||
|
@ -106,3 +129,5 @@ fn get_source(driver: &str, url: &str) -> Result<String, &'static str> {
|
|||
driver.quit().expect("failed to close session");
|
||||
return Ok(source);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue