use clap::Args;
use monocle::database::MonocleDatabase;
use monocle::lens::pfx2as::{Pfx2asLens, Pfx2asSearchArgs};
use monocle::lens::rpki::RpkiLens;
use monocle::utils::OutputFormat;
use monocle::MonocleConfig;
#[derive(Args)]
pub struct Pfx2asArgs {
#[clap(required = true)]
pub query: String,
#[clap(short, long)]
pub update: bool,
#[clap(long)]
pub include_sub: bool,
#[clap(long)]
pub include_super: bool,
#[clap(long)]
pub show_name: bool,
#[clap(long)]
pub show_full_name: bool,
#[clap(long, short, value_name = "N")]
pub limit: Option<usize>,
}
impl From<&Pfx2asArgs> for Pfx2asSearchArgs {
fn from(args: &Pfx2asArgs) -> Self {
let mut search_args = Pfx2asSearchArgs::new(&args.query)
.with_include_sub(args.include_sub)
.with_include_super(args.include_super)
.with_show_name(args.show_name)
.with_show_full_name(args.show_full_name);
if let Some(limit) = args.limit {
search_args = search_args.with_limit(limit);
}
search_args
}
}
pub fn run(config: &MonocleConfig, args: Pfx2asArgs, output_format: OutputFormat, no_update: bool) {
let sqlite_path = config.sqlite_path();
let db = match MonocleDatabase::open(&sqlite_path) {
Ok(db) => db,
Err(e) => {
eprintln!("Failed to open database: {}", e);
std::process::exit(1);
}
};
let lens = Pfx2asLens::new(&db);
if args.update {
if no_update {
eprintln!("[monocle] Warning: --update ignored because --no-update is set");
} else {
eprintln!("[monocle] Updating pfx2as data...");
match lens.refresh(None) {
Ok(count) => {
eprintln!("[monocle] Pfx2as data updated: {} records loaded", count);
}
Err(e) => {
eprintln!("[monocle] Failed to update pfx2as data: {}", e);
std::process::exit(1);
}
}
}
}
if !no_update {
match lens.refresh_reason(config.pfx2as_cache_ttl()) {
Ok(Some(reason)) => {
eprintln!("[monocle] Pfx2as {}, updating now...", reason);
match lens.refresh(None) {
Ok(count) => {
eprintln!("[monocle] Pfx2as data updated: {} records loaded", count);
}
Err(e) => {
eprintln!("[monocle] Failed to update pfx2as data: {}", e);
std::process::exit(1);
}
}
}
Ok(None) => {}
Err(e) => {
eprintln!(
"[monocle] Warning: Could not check pfx2as data status: {}",
e
);
}
}
let rpki_lens = RpkiLens::new(&db);
if let Ok(Some(reason)) = rpki_lens.refresh_reason(config.rpki_cache_ttl()) {
eprintln!("[monocle] RPKI {}, updating for validation...", reason);
match rpki_lens.refresh() {
Ok((roa_count, aspa_count)) => {
eprintln!(
"[monocle] RPKI data updated: {} ROAs, {} ASPAs",
roa_count, aspa_count
);
}
Err(e) => {
eprintln!("[monocle] Warning: Failed to update RPKI data: {}", e);
}
}
}
}
let search_args = Pfx2asSearchArgs::from(&args);
let show_name = args.show_name || args.show_full_name;
let results = match lens.search(&search_args) {
Ok(r) => r,
Err(e) => {
eprintln!("Error searching pfx2as data: {}", e);
std::process::exit(1);
}
};
if results.is_empty() {
if output_format.is_json() {
println!("[]");
} else {
println!("No results found for query: {}", args.query);
}
return;
}
println!(
"{}",
lens.format_search_results(&results, &output_format, show_name)
);
}