Integrating consul catalog for autoconfig of listeners
This commit is contained in:
85
src/main.rs
85
src/main.rs
@ -1,69 +1,20 @@
|
||||
mod config;
|
||||
mod listener;
|
||||
mod shutdown;
|
||||
mod tcp;
|
||||
mod udp;
|
||||
|
||||
#[cfg(feature = "consul")]
|
||||
mod consul;
|
||||
|
||||
use log::{debug, error, info, warn};
|
||||
use serde::Deserialize;
|
||||
use simple_error::bail;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::error::Error;
|
||||
use std::fs::File;
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
use tokio::signal::unix::{signal, SignalKind};
|
||||
use tokio::sync::{broadcast, RwLock};
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Box<dyn Error>>;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct Target {
|
||||
udp: Option<bool>,
|
||||
source: String,
|
||||
targets: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct Config {
|
||||
mappings: Vec<Target>,
|
||||
}
|
||||
|
||||
fn load_yaml(path: &Path) -> Result<Config> {
|
||||
let file = File::open(path)?;
|
||||
let config: Config = serde_yaml::from_reader(file).expect("Failed to parse!"); //TODO: Print path
|
||||
|
||||
return Ok(config);
|
||||
}
|
||||
|
||||
fn load_json(path: &Path) -> Result<Config> {
|
||||
let file = File::open(path)?;
|
||||
let config: Config = serde_json::from_reader(file).expect("Failed to parse!"); //TODO: Print path
|
||||
|
||||
return Ok(config);
|
||||
}
|
||||
|
||||
fn load_config() -> Result<Config> {
|
||||
for path in [
|
||||
"config.yaml",
|
||||
"config.json",
|
||||
"/etc/rustocat.yaml",
|
||||
"/etc/rustocat.json",
|
||||
]
|
||||
.iter()
|
||||
{
|
||||
// if(p)
|
||||
let config = if path.ends_with(".yaml") {
|
||||
load_yaml(Path::new(path))
|
||||
} else {
|
||||
load_json(Path::new(path))
|
||||
};
|
||||
if config.is_ok() {
|
||||
return config;
|
||||
}
|
||||
}
|
||||
bail!("No config file found");
|
||||
}
|
||||
|
||||
// #[derive(Debug)]
|
||||
struct ActiveListener {
|
||||
notify_shutdown: broadcast::Sender<()>,
|
||||
@ -84,18 +35,34 @@ async fn main() -> Result<()> {
|
||||
})
|
||||
// Add blanket level filter -
|
||||
.level(log::LevelFilter::Info)
|
||||
.level_for("rustocat", log::LevelFilter::Trace)
|
||||
.level_for("rustocat", log::LevelFilter::Debug)
|
||||
.chain(std::io::stdout())
|
||||
.apply()?;
|
||||
|
||||
let mut listeners: HashMap<String, ActiveListener> = HashMap::new();
|
||||
let mut sighup_stream = signal(SignalKind::hangup())?;
|
||||
let text_config_provider = config::FileConfigProvider::new();
|
||||
|
||||
let mut target_provider: Box<dyn config::ConfigProvider> = {
|
||||
#[cfg(feature = "consul")]
|
||||
{
|
||||
let cfg = text_config_provider.load_config()?;
|
||||
if cfg.consul.is_some() && cfg.consul.unwrap() {
|
||||
let consul_config_provider = consul::ConsulConfigProvider::new();
|
||||
Box::new(consul_config_provider)
|
||||
} else {
|
||||
Box::new(text_config_provider)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "consul"))]
|
||||
Box::new(text_config_provider)
|
||||
};
|
||||
|
||||
loop {
|
||||
let config = load_config().expect("config not found");
|
||||
let mappings = target_provider.get_targets().await?;
|
||||
let mut required_listeners: HashSet<String> = HashSet::new();
|
||||
|
||||
for target in config.mappings {
|
||||
for target in mappings {
|
||||
let mut source_str = "".to_owned();
|
||||
if target.udp == None || target.udp == Some(false) {
|
||||
source_str.push_str("udp:");
|
||||
@ -151,7 +118,7 @@ async fn main() -> Result<()> {
|
||||
}
|
||||
} else {
|
||||
if let Err(err) = udp::start_udp_listener(l).await {
|
||||
error!("udp listener error: {}", err);
|
||||
error!("udp listener error {}: {}", target.source, err);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -183,7 +150,7 @@ async fn main() -> Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
sighup_stream.recv().await;
|
||||
target_provider.wait_for_change().await?;
|
||||
info!("Recevied SIGHUP, reloading config!");
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user