cli: Add routing entries per rid and or nid

To allow third party tools read the routing table entries filtered by
rid or nid and if needed in json format.

Signed-off-by: Sebastian Martinez <me@sebastinez.dev>
This commit is contained in:
Sebastian Martinez 2023-05-18 12:36:33 +02:00
parent 2d55ffba81
commit 76ba25268d
No known key found for this signature in database
2 changed files with 56 additions and 11 deletions

View File

@ -3,6 +3,7 @@ use std::ffi::OsString;
use anyhow::anyhow; use anyhow::anyhow;
use radicle::node::{Address, Node, NodeId, ROUTING_DB_FILE, TRACKING_DB_FILE}; use radicle::node::{Address, Node, NodeId, ROUTING_DB_FILE, TRACKING_DB_FILE};
use radicle::prelude::Id;
use crate::terminal as term; use crate::terminal as term;
use crate::terminal::args::{Args, Error, Help}; use crate::terminal::args::{Args, Error, Help};
@ -28,7 +29,7 @@ Usage
rad node start [--daemon|-d] [<option>...] [-- <node-option>...] rad node start [--daemon|-d] [<option>...] [-- <node-option>...]
rad node stop [<option>...] rad node stop [<option>...]
rad node connect <nid> <addr> [<option>...] rad node connect <nid> <addr> [<option>...]
rad node routing [<option>...] rad node routing [--rid <rid>] [--nid <nid>] [--json] [<option>...]
rad node tracking [--repos|--nodes] [<option>...] rad node tracking [--repos|--nodes] [<option>...]
For `<node-option>` see `radicle-node --help`. For `<node-option>` see `radicle-node --help`.
@ -38,6 +39,9 @@ Options
--help Print help --help Print help
--repos Show the tracked repositories table --repos Show the tracked repositories table
--nodes Show the tracked nodes table --nodes Show the tracked nodes table
--rid Show the routing table entries for the given RID
--nid Show the routing table entries for the given NID
--json Output the routing table as json
"#, "#,
}; };
@ -51,7 +55,11 @@ pub enum Operation {
addr: Address, addr: Address,
}, },
Events, Events,
Routing, Routing {
json: bool,
rid: Option<Id>,
nid: Option<NodeId>,
},
Start { Start {
daemon: bool, daemon: bool,
options: Vec<OsString>, options: Vec<OsString>,
@ -92,6 +100,8 @@ impl Args for Options {
let mut op: Option<OperationName> = None; let mut op: Option<OperationName> = None;
let mut tracking_mode = TrackingMode::default(); let mut tracking_mode = TrackingMode::default();
let mut nid: Option<NodeId> = None; let mut nid: Option<NodeId> = None;
let mut rid: Option<Id> = None;
let mut json: bool = false;
let mut addr: Option<Address> = None; let mut addr: Option<Address> = None;
while let Some(arg) = parser.next()? { while let Some(arg) = parser.next()? {
@ -123,6 +133,15 @@ impl Args for Options {
}, },
} }
} }
Long("rid") if matches!(op, Some(OperationName::Routing)) => {
let val = parser.value()?;
rid = term::args::rid(&val).ok();
}
Long("nid") if matches!(op, Some(OperationName::Routing)) => {
let val = parser.value()?;
nid = term::args::nid(&val).ok();
}
Long("json") if matches!(op, Some(OperationName::Routing)) => json = true,
Long("repos") if matches!(op, Some(OperationName::Tracking)) => { Long("repos") if matches!(op, Some(OperationName::Tracking)) => {
tracking_mode = TrackingMode::Repos tracking_mode = TrackingMode::Repos
} }
@ -145,7 +164,7 @@ impl Args for Options {
addr: addr.ok_or_else(|| anyhow!("an address must be provided"))?, addr: addr.ok_or_else(|| anyhow!("an address must be provided"))?,
}, },
OperationName::Events => Operation::Events, OperationName::Events => Operation::Events,
OperationName::Routing => Operation::Routing, OperationName::Routing => Operation::Routing { rid, nid, json },
OperationName::Start => Operation::Start { daemon, options }, OperationName::Start => Operation::Start { daemon, options },
OperationName::Status => Operation::Status, OperationName::Status => Operation::Status,
OperationName::Stop => Operation::Stop, OperationName::Stop => Operation::Stop,
@ -169,10 +188,10 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
let node = Node::new(profile.socket()); let node = Node::new(profile.socket());
events::run(node)?; events::run(node)?;
} }
Operation::Routing => { Operation::Routing { rid, nid, json } => {
let store = let store =
radicle::node::routing::Table::reader(profile.home.node().join(ROUTING_DB_FILE))?; radicle::node::routing::Table::reader(profile.home.node().join(ROUTING_DB_FILE))?;
routing::run(&store)?; routing::run(&store, rid, nid, json)?;
} }
Operation::Start { daemon, options } => control::start(daemon, options)?, Operation::Start { daemon, options } => control::start(daemon, options)?,
Operation::Status => { Operation::Status => {

View File

@ -1,9 +1,31 @@
use radicle::node; use radicle::node;
use radicle::prelude::{Id, NodeId};
use crate::terminal as term; use crate::terminal as term;
use crate::terminal::Element; use crate::terminal::Element;
pub fn run<S: node::routing::Store>(routing: &S) -> anyhow::Result<()> { pub fn run<S: node::routing::Store>(
routing: &S,
rid: Option<Id>,
nid: Option<NodeId>,
json: bool,
) -> anyhow::Result<()> {
// Filters entries by RID or NID exclusively, or show all of them if none given.
let entries = routing.entries()?.filter(|(rid_, nid_)| {
(nid.is_none() || Some(nid_) == nid.as_ref())
&& (rid.is_none() || Some(rid_) == rid.as_ref())
});
if json {
print_json(entries);
} else {
print_table(entries);
}
Ok(())
}
fn print_table(entries: impl IntoIterator<Item = (Id, NodeId)>) {
let mut t = term::Table::new(term::table::TableOptions::bordered()); let mut t = term::Table::new(term::table::TableOptions::bordered());
t.push([ t.push([
term::format::default(String::from("RID")), term::format::default(String::from("RID")),
@ -11,13 +33,17 @@ pub fn run<S: node::routing::Store>(routing: &S) -> anyhow::Result<()> {
]); ]);
t.divider(); t.divider();
for (id, node) in routing.entries()? { for (rid, nid) in entries {
t.push([ t.push([
term::format::highlight(id.to_string()), term::format::highlight(rid.to_string()),
term::format::default(term::format::node(&node)), term::format::default(term::format::node(&nid)),
]); ]);
} }
t.print(); t.print();
}
Ok(())
fn print_json(entries: impl IntoIterator<Item = (Id, NodeId)>) {
for (rid, nid) in entries {
println!("{}", serde_json::json!({ "rid": rid, "nid": nid }));
}
} }