eyre work
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
use crate::settings::*;
|
||||
use crate::*;
|
||||
use clap::{Arg, ArgMatches, Command};
|
||||
use std::ffi::OsStr;
|
||||
use std::path::Path;
|
||||
@@ -145,11 +146,11 @@ fn do_clap_matches(default_config_path: &OsStr) -> Result<clap::ArgMatches, clap
|
||||
Ok(matches.get_matches())
|
||||
}
|
||||
|
||||
pub fn process_command_line() -> Result<(Settings, ArgMatches), String> {
|
||||
pub fn process_command_line() -> EyreResult<(Settings, ArgMatches)> {
|
||||
// Get command line options
|
||||
let default_config_path = Settings::get_default_config_path();
|
||||
let matches = do_clap_matches(default_config_path.as_os_str())
|
||||
.map_err(|e| format!("failed to parse command line: {}", e))?;
|
||||
.wrap_err("failed to parse command line: {}")?;
|
||||
|
||||
// Check for one-off commands
|
||||
#[cfg(debug_assertions)]
|
||||
@@ -169,8 +170,7 @@ pub fn process_command_line() -> Result<(Settings, ArgMatches), String> {
|
||||
None
|
||||
};
|
||||
|
||||
let settings =
|
||||
Settings::new(settings_path).map_err(|e| format!("configuration is invalid: {}", e))?;
|
||||
let settings = Settings::new(settings_path).wrap_err("configuration is invalid")?;
|
||||
|
||||
// write lock the settings
|
||||
let mut settingsrw = settings.write();
|
||||
@@ -185,15 +185,13 @@ pub fn process_command_line() -> Result<(Settings, ArgMatches), String> {
|
||||
}
|
||||
if matches.occurrences_of("subnode-index") != 0 {
|
||||
let subnode_index = match matches.value_of("subnode-index") {
|
||||
Some(x) => x
|
||||
.parse()
|
||||
.map_err(|e| format!("couldn't parse subnode index: {}", e))?,
|
||||
Some(x) => x.parse().wrap_err("couldn't parse subnode index")?,
|
||||
None => {
|
||||
return Err("value not specified for subnode-index".to_owned());
|
||||
bail!("value not specified for subnode-index");
|
||||
}
|
||||
};
|
||||
if subnode_index == 0 {
|
||||
return Err("value of subnode_index should be between 1 and 65535".to_owned());
|
||||
bail!("value of subnode_index should be between 1 and 65535");
|
||||
}
|
||||
settingsrw.testing.subnode_index = subnode_index;
|
||||
}
|
||||
@@ -214,7 +212,7 @@ pub fn process_command_line() -> Result<(Settings, ArgMatches), String> {
|
||||
.expect("should not be null because of default missing value")
|
||||
.to_string(),
|
||||
)
|
||||
.map_err(|e| format!("failed to parse OTLP address: {}", e))?;
|
||||
.wrap_err("failed to parse OTLP address")?;
|
||||
settingsrw.logging.otlp.level = LogLevel::Trace;
|
||||
}
|
||||
if matches.is_present("attach") {
|
||||
@@ -242,13 +240,13 @@ pub fn process_command_line() -> Result<(Settings, ArgMatches), String> {
|
||||
|
||||
// Split or get secret
|
||||
let (k, s) = if let Some((k, s)) = v.split_once(':') {
|
||||
let k = DHTKey::try_decode(k)?;
|
||||
let k = DHTKey::try_decode(k).wrap_err("failed to decode node id from command line")?;
|
||||
let s = DHTKeySecret::try_decode(s)?;
|
||||
(k, s)
|
||||
} else {
|
||||
let k = DHTKey::try_decode(v)?;
|
||||
let buffer = rpassword::prompt_password("Enter secret key (will not echo): ")
|
||||
.map_err(|e| e.to_string())?;
|
||||
.wrap_err("invalid secret key")?;
|
||||
let buffer = buffer.trim().to_string();
|
||||
let s = DHTKeySecret::try_decode(&buffer)?;
|
||||
(k, s)
|
||||
@@ -270,7 +268,7 @@ pub fn process_command_line() -> Result<(Settings, ArgMatches), String> {
|
||||
out
|
||||
}
|
||||
None => {
|
||||
return Err("value not specified for bootstrap".to_owned());
|
||||
bail!("value not specified for bootstrap");
|
||||
}
|
||||
};
|
||||
settingsrw.core.network.bootstrap = bootstrap_list;
|
||||
@@ -284,17 +282,15 @@ pub fn process_command_line() -> Result<(Settings, ArgMatches), String> {
|
||||
for x in x.split(',') {
|
||||
let x = x.trim();
|
||||
println!(" {}", x);
|
||||
out.push(ParsedNodeDialInfo::from_str(x).map_err(|e| {
|
||||
format!(
|
||||
"unable to parse dial info in bootstrap node list: {} for {}",
|
||||
e, x
|
||||
)
|
||||
})?);
|
||||
out.push(
|
||||
ParsedNodeDialInfo::from_str(x)
|
||||
.wrap_err("unable to parse dial info in bootstrap node list")?,
|
||||
);
|
||||
}
|
||||
out
|
||||
}
|
||||
None => {
|
||||
return Err("value not specified for bootstrap node list".to_owned());
|
||||
bail!("value not specified for bootstrap node list");
|
||||
}
|
||||
};
|
||||
settingsrw.core.network.bootstrap_nodes = bootstrap_list;
|
||||
@@ -315,7 +311,7 @@ pub fn process_command_line() -> Result<(Settings, ArgMatches), String> {
|
||||
// Apply subnode index if we're testing
|
||||
settings
|
||||
.apply_subnode_index()
|
||||
.map_err(|_| "failed to apply subnode index".to_owned())?;
|
||||
.wrap_err("failed to apply subnode index")?;
|
||||
|
||||
Ok((settings, matches))
|
||||
}
|
||||
|
@@ -14,6 +14,8 @@ mod veilid_logs;
|
||||
mod windows;
|
||||
|
||||
use cfg_if::*;
|
||||
#[allow(unused_imports)]
|
||||
use color_eyre::eyre::{bail, ensure, eyre, Result as EyreResult, WrapErr};
|
||||
use server::*;
|
||||
use tools::*;
|
||||
use tracing::*;
|
||||
@@ -25,16 +27,17 @@ pub mod veilid_client_capnp {
|
||||
}
|
||||
|
||||
#[instrument(err)]
|
||||
fn main() -> Result<(), String> {
|
||||
fn main() -> EyreResult<()> {
|
||||
#[cfg(windows)]
|
||||
let _ = ansi_term::enable_ansi_support();
|
||||
color_eyre::install()?;
|
||||
|
||||
let (settings, matches) = cmdline::process_command_line()?;
|
||||
|
||||
// --- Dump Config ---
|
||||
if matches.occurrences_of("dump-config") != 0 {
|
||||
return serde_yaml::to_writer(std::io::stdout(), &*settings.read())
|
||||
.map_err(|e| e.to_string());
|
||||
.wrap_err("failed to write yaml");
|
||||
}
|
||||
|
||||
// --- Generate DHT Key ---
|
||||
|
@@ -2,6 +2,7 @@ use crate::client_api;
|
||||
use crate::settings::*;
|
||||
use crate::tools::*;
|
||||
use crate::veilid_logs::*;
|
||||
use crate::*;
|
||||
use flume::{unbounded, Receiver, Sender};
|
||||
use lazy_static::*;
|
||||
use parking_lot::Mutex;
|
||||
@@ -34,16 +35,16 @@ pub async fn run_veilid_server(
|
||||
settings: Settings,
|
||||
server_mode: ServerMode,
|
||||
veilid_logs: VeilidLogs,
|
||||
) -> Result<(), String> {
|
||||
) -> EyreResult<()> {
|
||||
run_veilid_server_internal(settings, server_mode, veilid_logs).await
|
||||
}
|
||||
|
||||
#[instrument(err, skip_all)]
|
||||
//#[instrument(err, skip_all)]
|
||||
pub async fn run_veilid_server_internal(
|
||||
settings: Settings,
|
||||
server_mode: ServerMode,
|
||||
veilid_logs: VeilidLogs,
|
||||
) -> Result<(), String> {
|
||||
) -> EyreResult<()> {
|
||||
trace!(?settings, ?server_mode);
|
||||
|
||||
let settingsr = settings.read();
|
||||
@@ -65,7 +66,7 @@ pub async fn run_veilid_server_internal(
|
||||
// Start Veilid Core and get API
|
||||
let veilid_api = veilid_core::api_startup(update_callback, config_callback)
|
||||
.await
|
||||
.map_err(|e| format!("VeilidCore startup failed: {}", e))?;
|
||||
.wrap_err("VeilidCore startup failed")?;
|
||||
|
||||
// Start client api if one is requested
|
||||
let mut capi = if settingsr.client_api.enabled && matches!(server_mode, ServerMode::Normal) {
|
||||
@@ -98,9 +99,10 @@ pub async fn run_veilid_server_internal(
|
||||
if auto_attach {
|
||||
info!("Auto-attach to the Veilid network");
|
||||
if let Err(e) = veilid_api.attach().await {
|
||||
let outerr = format!("Auto-attaching to the Veilid network failed: {:?}", e);
|
||||
error!("{}", outerr);
|
||||
out = Err(outerr);
|
||||
out = Err(eyre!(
|
||||
"Auto-attaching to the Veilid network failed: {:?}",
|
||||
e
|
||||
));
|
||||
shutdown();
|
||||
}
|
||||
}
|
||||
@@ -116,9 +118,7 @@ pub async fn run_veilid_server_internal(
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
let outerr = format!("Getting state failed: {:?}", e);
|
||||
error!("{}", outerr);
|
||||
out = Err(outerr);
|
||||
out = Err(eyre!("Getting state failed: {:?}", e));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -129,9 +129,7 @@ pub async fn run_veilid_server_internal(
|
||||
print!("{}", v);
|
||||
}
|
||||
Err(e) => {
|
||||
let outerr = format!("Getting TXT record failed: {:?}", e);
|
||||
error!("{}", outerr);
|
||||
out = Err(outerr);
|
||||
out = Err(eyre!("Getting TXT record failed: {:?}", e));
|
||||
}
|
||||
};
|
||||
shutdown();
|
||||
|
@@ -1,5 +1,7 @@
|
||||
#![allow(clippy::bool_assert_comparison)]
|
||||
|
||||
use crate::*;
|
||||
|
||||
use directories::*;
|
||||
use parking_lot::*;
|
||||
|
||||
@@ -11,8 +13,9 @@ use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use url::Url;
|
||||
use veilid_core::xx::*;
|
||||
use veilid_core::*;
|
||||
|
||||
pub fn load_default_config() -> Result<config::Config, config::ConfigError> {
|
||||
pub fn load_default_config() -> EyreResult<config::Config> {
|
||||
let default_config = String::from(
|
||||
r#"---
|
||||
daemon:
|
||||
@@ -172,21 +175,18 @@ core:
|
||||
config::FileFormat::Yaml,
|
||||
))
|
||||
.build()
|
||||
.wrap_err("failed to parse default config")
|
||||
}
|
||||
|
||||
pub fn load_config(
|
||||
cfg: config::Config,
|
||||
config_file: &Path,
|
||||
) -> Result<config::Config, config::ConfigError> {
|
||||
pub fn load_config(cfg: config::Config, config_file: &Path) -> EyreResult<config::Config> {
|
||||
if let Some(config_file_str) = config_file.to_str() {
|
||||
config::Config::builder()
|
||||
.add_source(cfg)
|
||||
.add_source(config::File::new(config_file_str, config::FileFormat::Yaml))
|
||||
.build()
|
||||
.wrap_err("failed to load config")
|
||||
} else {
|
||||
Err(config::ConfigError::Message(
|
||||
"config file path is not valid UTF-8".to_owned(),
|
||||
))
|
||||
bail!("config file path is not valid UTF-8")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,9 +254,11 @@ pub struct ParsedUrl {
|
||||
}
|
||||
|
||||
impl ParsedUrl {
|
||||
pub fn offset_port(&mut self, offset: u16) -> Result<(), ()> {
|
||||
pub fn offset_port(&mut self, offset: u16) -> EyreResult<()> {
|
||||
// Bump port on url
|
||||
self.url.set_port(Some(self.url.port().unwrap() + offset))?;
|
||||
self.url
|
||||
.set_port(Some(self.url.port().unwrap() + offset))
|
||||
.map_err(|_| eyre!("failed to set port on url"))?;
|
||||
self.urlstring = self.url.to_string();
|
||||
Ok(())
|
||||
}
|
||||
@@ -388,16 +390,16 @@ impl serde::Serialize for NamedSocketAddrs {
|
||||
}
|
||||
|
||||
impl NamedSocketAddrs {
|
||||
pub fn offset_port(&mut self, offset: u16) -> Result<(), ()> {
|
||||
pub fn offset_port(&mut self, offset: u16) -> EyreResult<()> {
|
||||
// Bump port on name
|
||||
if let Some(split) = self.name.rfind(':') {
|
||||
let hoststr = &self.name[0..split];
|
||||
let portstr = &self.name[split + 1..];
|
||||
let port: u16 = portstr.parse::<u16>().map_err(drop)? + offset;
|
||||
let port: u16 = portstr.parse::<u16>().wrap_err("failed to parse port")? + offset;
|
||||
|
||||
self.name = format!("{}:{}", hoststr, port);
|
||||
} else {
|
||||
return Err(());
|
||||
bail!("no port specified to offset");
|
||||
}
|
||||
|
||||
// Bump port on addresses
|
||||
@@ -655,7 +657,7 @@ pub struct Settings {
|
||||
}
|
||||
|
||||
impl Settings {
|
||||
pub fn new(config_file: Option<&OsStr>) -> Result<Self, config::ConfigError> {
|
||||
pub fn new(config_file: Option<&OsStr>) -> EyreResult<Self> {
|
||||
// Load the default config
|
||||
let mut cfg = load_default_config()?;
|
||||
|
||||
@@ -681,7 +683,7 @@ impl Settings {
|
||||
self.inner.write()
|
||||
}
|
||||
|
||||
pub fn apply_subnode_index(&self) -> Result<(), ()> {
|
||||
pub fn apply_subnode_index(&self) -> EyreResult<()> {
|
||||
let mut settingsrw = self.write();
|
||||
let idx = settingsrw.testing.subnode_index;
|
||||
if idx == 0 {
|
||||
@@ -869,7 +871,7 @@ impl Settings {
|
||||
pk_path
|
||||
}
|
||||
|
||||
pub fn set(&self, key: &str, value: &str) -> Result<(), String> {
|
||||
pub fn set(&self, key: &str, value: &str) -> EyreResult<()> {
|
||||
let mut inner = self.inner.write();
|
||||
|
||||
macro_rules! set_config_value {
|
||||
@@ -882,9 +884,11 @@ impl Settings {
|
||||
return Ok(());
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(format!(
|
||||
return Err(eyre!(
|
||||
"invalid type for key {}, value: {}: {}",
|
||||
key, value, e
|
||||
key,
|
||||
value,
|
||||
e
|
||||
))
|
||||
}
|
||||
}
|
||||
@@ -1005,7 +1009,7 @@ impl Settings {
|
||||
set_config_value!(inner.core.network.protocol.wss.listen_address, value);
|
||||
set_config_value!(inner.core.network.protocol.wss.path, value);
|
||||
set_config_value!(inner.core.network.protocol.wss.url, value);
|
||||
Err("settings key not found".to_owned())
|
||||
Err(eyre!("settings key not found"))
|
||||
}
|
||||
|
||||
pub fn get_core_config_callback(&self) -> veilid_core::ConfigCallback {
|
||||
@@ -1013,7 +1017,7 @@ impl Settings {
|
||||
|
||||
Arc::new(move |key: String| {
|
||||
let inner = inner.read();
|
||||
let out: Result<Box<dyn core::any::Any + Send>, String> = match key.as_str() {
|
||||
let out: ConfigCallbackReturn = match key.as_str() {
|
||||
"program_name" => Ok(Box::new("veilid-server".to_owned())),
|
||||
"namespace" => Ok(Box::new(if inner.testing.subnode_index == 0 {
|
||||
"".to_owned()
|
||||
@@ -1365,7 +1369,10 @@ impl Settings {
|
||||
.as_ref()
|
||||
.map(|a| a.urlstring.clone()),
|
||||
)),
|
||||
_ => Err(format!("config key '{}' doesn't exist", key)),
|
||||
_ => Err(VeilidAPIError::generic(format!(
|
||||
"config key '{}' doesn't exist",
|
||||
key
|
||||
))),
|
||||
};
|
||||
out
|
||||
})
|
||||
|
@@ -2,6 +2,7 @@ use crate::server::*;
|
||||
use crate::settings::Settings;
|
||||
use crate::tools::*;
|
||||
use crate::veilid_logs::*;
|
||||
use crate::*;
|
||||
use clap::ArgMatches;
|
||||
use futures_util::StreamExt;
|
||||
use signal_hook::consts::signal::*;
|
||||
@@ -26,7 +27,7 @@ async fn handle_signals(mut signals: Signals) {
|
||||
}
|
||||
|
||||
#[instrument(err)]
|
||||
pub fn run_daemon(settings: Settings, _matches: ArgMatches) -> Result<(), String> {
|
||||
pub fn run_daemon(settings: Settings, _matches: ArgMatches) -> EyreResult<()> {
|
||||
let daemon = {
|
||||
let mut daemon = daemonize::Daemonize::new();
|
||||
let s = settings.read();
|
||||
@@ -64,10 +65,7 @@ pub fn run_daemon(settings: Settings, _matches: ArgMatches) -> Result<(), String
|
||||
}
|
||||
|
||||
let stdout_file = if let Some(stdout_file) = &s.daemon.stdout_file {
|
||||
Some(
|
||||
std::fs::File::create(stdout_file)
|
||||
.map_err(|e| format!("Failed to create stdio file: {}", e))?,
|
||||
)
|
||||
Some(std::fs::File::create(stdout_file).wrap_err("Failed to create stdio file")?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@@ -79,12 +77,11 @@ pub fn run_daemon(settings: Settings, _matches: ArgMatches) -> Result<(), String
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.try_clone()
|
||||
.map_err(|e| format!("Failed to clone stdout file: {}", e))?,
|
||||
.wrap_err("Failed to clone stdout file")?,
|
||||
);
|
||||
} else {
|
||||
daemon = daemon.stderr(
|
||||
std::fs::File::create(stderr_file)
|
||||
.map_err(|e| format!("Failed to create stderr file: {}", e))?,
|
||||
std::fs::File::create(stderr_file).wrap_err("Failed to create stderr file")?,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -101,13 +98,11 @@ pub fn run_daemon(settings: Settings, _matches: ArgMatches) -> Result<(), String
|
||||
let veilid_logs = VeilidLogs::setup(settings.clone())?;
|
||||
|
||||
// Daemonize
|
||||
daemon
|
||||
.start()
|
||||
.map_err(|e| format!("Failed to daemonize: {}", e))?;
|
||||
daemon.start().wrap_err("Failed to daemonize")?;
|
||||
|
||||
// Catch signals
|
||||
let signals = Signals::new(&[SIGHUP, SIGTERM, SIGINT, SIGQUIT])
|
||||
.map_err(|e| format!("failed to init signals: {}", e))?;
|
||||
let signals =
|
||||
Signals::new(&[SIGHUP, SIGTERM, SIGINT, SIGQUIT]).wrap_err("failed to init signals")?;
|
||||
let handle = signals.handle();
|
||||
|
||||
let signals_task = spawn(handle_signals(signals));
|
||||
|
@@ -1,4 +1,5 @@
|
||||
use crate::settings::*;
|
||||
use crate::*;
|
||||
use cfg_if::*;
|
||||
use opentelemetry::sdk::*;
|
||||
use opentelemetry::*;
|
||||
@@ -22,7 +23,7 @@ pub struct VeilidLogs {
|
||||
}
|
||||
|
||||
impl VeilidLogs {
|
||||
pub fn setup(settings: Settings) -> Result<VeilidLogs, String> {
|
||||
pub fn setup(settings: Settings) -> EyreResult<VeilidLogs> {
|
||||
let settingsr = settings.read();
|
||||
|
||||
// Set up subscriber and layers
|
||||
@@ -77,7 +78,7 @@ impl VeilidLogs {
|
||||
)]),
|
||||
))
|
||||
.install_batch(batch)
|
||||
.map_err(|e| format!("failed to install OpenTelemetry tracer: {}", e))?;
|
||||
.wrap_err("failed to install OpenTelemetry tracer")?;
|
||||
|
||||
let filter = veilid_core::VeilidLayerFilter::new(
|
||||
convert_loglevel(settingsr.logging.otlp.level),
|
||||
@@ -101,13 +102,11 @@ impl VeilidLogs {
|
||||
.parent()
|
||||
.unwrap_or(Path::new(&MAIN_SEPARATOR.to_string()))
|
||||
.canonicalize()
|
||||
.map_err(|e| {
|
||||
format!(
|
||||
"File log path parent does not exist: {} ({})",
|
||||
settingsr.logging.file.path, e
|
||||
)
|
||||
})?;
|
||||
let log_filename = full_path.file_name().ok_or(format!(
|
||||
.wrap_err(format!(
|
||||
"File log path parent does not exist: {}",
|
||||
settingsr.logging.file.path
|
||||
))?;
|
||||
let log_filename = full_path.file_name().ok_or(eyre!(
|
||||
"File log filename not specified in path: {}",
|
||||
settingsr.logging.file.path
|
||||
))?;
|
||||
@@ -149,7 +148,7 @@ impl VeilidLogs {
|
||||
convert_loglevel(settingsr.logging.system.level),
|
||||
None,
|
||||
);
|
||||
let layer =tracing_journald::layer().map_err(|e| format!("failed to set up journald logging: {}", e))?
|
||||
let layer =tracing_journald::layer().wrap_err("failed to set up journald logging")?
|
||||
.with_filter(filter.clone());
|
||||
filters.insert("system", filter);
|
||||
layers.push(layer.boxed());
|
||||
@@ -160,7 +159,7 @@ impl VeilidLogs {
|
||||
let subscriber = subscriber.with(layers);
|
||||
subscriber
|
||||
.try_init()
|
||||
.map_err(|e| format!("failed to initialize logging: {}", e))?;
|
||||
.wrap_err("failed to initialize logging")?;
|
||||
|
||||
Ok(VeilidLogs {
|
||||
inner: Arc::new(Mutex::new(VeilidLogsInner {
|
||||
|
Reference in New Issue
Block a user