eyre work

This commit is contained in:
John Smith
2022-07-06 23:15:51 -04:00
parent 2f05611170
commit cd0cd78e30
21 changed files with 345 additions and 229 deletions

View File

@@ -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))
}

View File

@@ -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 ---

View File

@@ -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();

View File

@@ -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
})

View File

@@ -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));

View File

@@ -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 {