pub mod adapters;
pub mod andna_key;
pub mod cli;
pub mod codec;
pub mod dispatch;
pub mod ip_route;
pub mod kernel_handle;
pub mod lifecycle;
#[cfg(test)]
mod negotiation_tests;
pub mod peers;
pub mod registry;
pub mod services;
pub mod status;
pub mod stubs;
pub mod supervisor;
pub mod transport;
pub fn main() {
use clap::Parser;
let cli = cli::Cli::parse();
let runtime = tokio::runtime::Runtime::new().expect("failed to start tokio runtime");
let result = runtime.block_on(async move {
match cli.command {
cli::Command::Run {
config,
nics,
log_level,
status_socket,
} => {
let socket = status_socket.unwrap_or_else(status::default_socket_path);
supervisor::run(config, nics, &log_level, socket).await
}
cli::Command::Status { socket } => supervisor::status(socket).await,
cli::Command::AndnaRegister { hostname, socket } => {
supervisor::andna_register(socket, hostname).await
}
cli::Command::AndnaResolve { hostname, socket } => {
supervisor::andna_resolve(socket, hostname).await
}
}
});
if let Err(err) = result {
eprintln!("ntkd: error: {}", render_error_chain(&err));
std::process::exit(1);
}
}
pub(crate) fn render_error_chain(err: &anyhow::Error) -> String {
let mut rendered = err.to_string();
for cause in err.chain().skip(1) {
let text = cause.to_string();
if !rendered.contains(&text) {
rendered.push_str(": ");
rendered.push_str(&text);
}
}
rendered
}
#[cfg(test)]
mod tests {
use anyhow::Context as _;
use super::render_error_chain;
#[test]
fn error_chain_shows_the_io_cause_under_a_context_message() {
let err = std::fs::metadata("/nonexistent/ntkd.sock")
.context("connecting to the ntkd status socket /nonexistent/ntkd.sock")
.unwrap_err();
let rendered = render_error_chain(&err);
assert!(
rendered.starts_with("connecting to the ntkd status socket /nonexistent/ntkd.sock: "),
"{rendered}"
);
assert!(rendered.contains("No such file or directory"), "{rendered}");
}
#[test]
fn error_chain_does_not_repeat_a_cause_the_message_already_embeds() {
let missing =
crate::kernel::config::NtkdConfig::load(std::path::Path::new("/nonexistent/ntkd.toml"))
.unwrap_err();
let err = anyhow::Error::from(missing);
let rendered = render_error_chain(&err);
assert_eq!(
rendered.matches("No such file or directory").count(),
1,
"{rendered}"
);
assert!(rendered.contains("/nonexistent/ntkd.toml"), "{rendered}");
}
}