client: add verbose logging

pull/74/head
Jake McGinty 2021-05-20 03:11:51 +09:00
parent 7d3529f600
commit e95d79db66
5 changed files with 72 additions and 24 deletions

2
Cargo.lock generated
View File

@ -160,6 +160,7 @@ dependencies = [
"ipnetwork", "ipnetwork",
"lazy_static", "lazy_static",
"libc", "libc",
"log",
"regex", "regex",
"serde", "serde",
"serde_json", "serde_json",
@ -934,6 +935,7 @@ dependencies = [
"indoc", "indoc",
"ipnetwork", "ipnetwork",
"lazy_static", "lazy_static",
"log",
"publicip", "publicip",
"regex", "regex",
"serde", "serde",

View File

@ -21,6 +21,7 @@ indoc = "1"
ipnetwork = { git = "https://github.com/mcginty/ipnetwork" } # pending https://github.com/achanda/ipnetwork/pull/129 ipnetwork = { git = "https://github.com/mcginty/ipnetwork" } # pending https://github.com/achanda/ipnetwork/pull/129
lazy_static = "1" lazy_static = "1"
libc = "0.2" libc = "0.2"
log = "0.4"
regex = { version = "1", default-features = false, features = ["std"] } regex = { version = "1", default-features = false, features = ["std"] }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"

View File

@ -42,6 +42,9 @@ struct Opts {
#[structopt(subcommand)] #[structopt(subcommand)]
command: Option<Command>, command: Option<Command>,
#[structopt(short, parse(from_occurrences))]
verbosity: u64,
#[structopt(flatten)] #[structopt(flatten)]
network: NetworkOpt, network: NetworkOpt,
} }
@ -406,7 +409,7 @@ fn fetch(
.into()); .into());
} }
println!("{} bringing up the interface.", "[*]".dimmed()); log::info!("bringing up the interface.");
let resolved_endpoint = config.server.external_endpoint.resolve()?; let resolved_endpoint = config.server.external_endpoint.resolve()?;
wg::up( wg::up(
interface, interface,
@ -422,7 +425,7 @@ fn fetch(
)? )?
} }
println!("{} fetching state from server.", "[*]".dimmed()); log::info!("fetching state from server.");
let mut store = DataStore::open_or_create(&interface)?; let mut store = DataStore::open_or_create(&interface)?;
let State { peers, cidrs } = Api::new(&config.server).http("GET", "/user/state")?; let State { peers, cidrs } = Api::new(&config.server).http("GET", "/user/state")?;
@ -492,13 +495,13 @@ fn fetch(
update_hosts_file(interface, path, &peers)?; update_hosts_file(interface, path, &peers)?;
} }
println!( println!();
"\n{} updated interface {}\n", log::info!(
"[*]".dimmed(), "updated interface {}\n",
interface.as_str_lossy().yellow() interface.as_str_lossy().yellow()
); );
} else { } else {
println!("{}", " peers are already up to date.".green()); log::info!("{}", "peers are already up to date.".green());
} }
store.set_cidrs(cidrs); store.set_cidrs(cidrs);
store.update_peers(peers)?; store.update_peers(peers)?;
@ -539,13 +542,13 @@ fn uninstall(interface: &InterfaceName, network: NetworkOpt) -> Result<(), Error
fn add_cidr(interface: &InterfaceName, opts: AddCidrOpts) -> Result<(), Error> { fn add_cidr(interface: &InterfaceName, opts: AddCidrOpts) -> Result<(), Error> {
let InterfaceConfig { server, .. } = InterfaceConfig::from_interface(interface)?; let InterfaceConfig { server, .. } = InterfaceConfig::from_interface(interface)?;
println!("Fetching CIDRs"); log::info!("Fetching CIDRs");
let api = Api::new(&server); let api = Api::new(&server);
let cidrs: Vec<Cidr> = api.http("GET", "/admin/cidrs")?; let cidrs: Vec<Cidr> = api.http("GET", "/admin/cidrs")?;
let cidr_request = prompts::add_cidr(&cidrs, &opts)?; let cidr_request = prompts::add_cidr(&cidrs, &opts)?;
println!("Creating CIDR..."); log::info!("Creating CIDR...");
let cidr: Cidr = api.http_form("POST", "/admin/cidrs", cidr_request)?; let cidr: Cidr = api.http_form("POST", "/admin/cidrs", cidr_request)?;
printdoc!( printdoc!(
@ -567,9 +570,9 @@ fn add_peer(interface: &InterfaceName, opts: AddPeerOpts) -> Result<(), Error> {
let InterfaceConfig { server, .. } = InterfaceConfig::from_interface(interface)?; let InterfaceConfig { server, .. } = InterfaceConfig::from_interface(interface)?;
let api = Api::new(&server); let api = Api::new(&server);
println!("Fetching CIDRs"); log::info!("Fetching CIDRs");
let cidrs: Vec<Cidr> = api.http("GET", "/admin/cidrs")?; let cidrs: Vec<Cidr> = api.http("GET", "/admin/cidrs")?;
println!("Fetching peers"); log::info!("Fetching peers");
let peers: Vec<Peer> = api.http("GET", "/admin/peers")?; let peers: Vec<Peer> = api.http("GET", "/admin/peers")?;
let cidr_tree = CidrTree::new(&cidrs[..]); let cidr_tree = CidrTree::new(&cidrs[..]);
@ -597,7 +600,7 @@ fn enable_or_disable_peer(interface: &InterfaceName, enable: bool) -> Result<(),
let InterfaceConfig { server, .. } = InterfaceConfig::from_interface(interface)?; let InterfaceConfig { server, .. } = InterfaceConfig::from_interface(interface)?;
let api = Api::new(&server); let api = Api::new(&server);
println!("Fetching peers."); log::info!("Fetching peers.");
let peers: Vec<Peer> = api.http("GET", "/admin/peers")?; let peers: Vec<Peer> = api.http("GET", "/admin/peers")?;
if let Some(peer) = prompts::enable_or_disable_peer(&peers[..], enable)? { if let Some(peer) = prompts::enable_or_disable_peer(&peers[..], enable)? {
@ -605,7 +608,7 @@ fn enable_or_disable_peer(interface: &InterfaceName, enable: bool) -> Result<(),
contents.is_disabled = !enable; contents.is_disabled = !enable;
api.http_form("PUT", &format!("/admin/peers/{}", id), contents)?; api.http_form("PUT", &format!("/admin/peers/{}", id), contents)?;
} else { } else {
println!("exited without disabling peer."); log::info!("exiting without disabling peer.");
} }
Ok(()) Ok(())
@ -615,7 +618,7 @@ fn add_association(interface: &InterfaceName, opts: AddAssociationOpts) -> Resul
let InterfaceConfig { server, .. } = InterfaceConfig::from_interface(interface)?; let InterfaceConfig { server, .. } = InterfaceConfig::from_interface(interface)?;
let api = Api::new(&server); let api = Api::new(&server);
println!("Fetching CIDRs"); log::info!("Fetching CIDRs");
let cidrs: Vec<Cidr> = api.http("GET", "/admin/cidrs")?; let cidrs: Vec<Cidr> = api.http("GET", "/admin/cidrs")?;
let association = if let (Some(ref cidr1), Some(ref cidr2)) = (opts.cidr1, opts.cidr2) { let association = if let (Some(ref cidr1), Some(ref cidr2)) = (opts.cidr1, opts.cidr2) {
@ -631,7 +634,7 @@ fn add_association(interface: &InterfaceName, opts: AddAssociationOpts) -> Resul
} else if let Some((cidr1, cidr2)) = prompts::add_association(&cidrs[..])? { } else if let Some((cidr1, cidr2)) = prompts::add_association(&cidrs[..])? {
(cidr1, cidr2) (cidr1, cidr2)
} else { } else {
println!("exited without adding association."); log::info!("exiting without adding association.");
return Ok(()); return Ok(());
}; };
@ -651,15 +654,15 @@ fn delete_association(interface: &InterfaceName) -> Result<(), Error> {
let InterfaceConfig { server, .. } = InterfaceConfig::from_interface(interface)?; let InterfaceConfig { server, .. } = InterfaceConfig::from_interface(interface)?;
let api = Api::new(&server); let api = Api::new(&server);
println!("Fetching CIDRs"); log::info!("Fetching CIDRs");
let cidrs: Vec<Cidr> = api.http("GET", "/admin/cidrs")?; let cidrs: Vec<Cidr> = api.http("GET", "/admin/cidrs")?;
println!("Fetching associations"); log::info!("Fetching associations");
let associations: Vec<Association> = api.http("GET", "/admin/associations")?; let associations: Vec<Association> = api.http("GET", "/admin/associations")?;
if let Some(association) = prompts::delete_association(&associations[..], &cidrs[..])? { if let Some(association) = prompts::delete_association(&associations[..], &cidrs[..])? {
api.http("DELETE", &format!("/admin/associations/{}", association.id))?; api.http("DELETE", &format!("/admin/associations/{}", association.id))?;
} else { } else {
println!("exited without adding association."); log::info!("exiting without adding association.");
} }
Ok(()) Ok(())
@ -669,9 +672,9 @@ fn list_associations(interface: &InterfaceName) -> Result<(), Error> {
let InterfaceConfig { server, .. } = InterfaceConfig::from_interface(interface)?; let InterfaceConfig { server, .. } = InterfaceConfig::from_interface(interface)?;
let api = Api::new(&server); let api = Api::new(&server);
println!("Fetching CIDRs"); log::info!("Fetching CIDRs");
let cidrs: Vec<Cidr> = api.http("GET", "/admin/cidrs")?; let cidrs: Vec<Cidr> = api.http("GET", "/admin/cidrs")?;
println!("Fetching associations"); log::info!("Fetching associations");
let associations: Vec<Association> = api.http("GET", "/admin/associations")?; let associations: Vec<Association> = api.http("GET", "/admin/associations")?;
for association in associations { for association in associations {
@ -705,13 +708,13 @@ fn set_listen_port(
if let Some(listen_port) = prompts::set_listen_port(&config.interface, unset)? { if let Some(listen_port) = prompts::set_listen_port(&config.interface, unset)? {
wg::set_listen_port(interface, listen_port, network.backend)?; wg::set_listen_port(interface, listen_port, network.backend)?;
println!("{} the interface is updated", "[*]".dimmed(),); log::info!("the interface is updated");
config.interface.listen_port = listen_port; config.interface.listen_port = listen_port;
config.write_to_interface(interface)?; config.write_to_interface(interface)?;
println!("{} the config file is updated", "[*]".dimmed(),); log::info!("the config file is updated");
} else { } else {
println!("exited without updating listen port."); log::info!("exiting without updating the listen port.");
} }
Ok(()) Ok(())
@ -739,7 +742,7 @@ fn override_endpoint(
EndpointContents::from(endpoint), EndpointContents::from(endpoint),
)?; )?;
} else { } else {
println!("exited without overriding endpoint."); log::info!("exiting without overriding endpoint.");
} }
Ok(()) Ok(())
@ -771,7 +774,7 @@ fn show(
.collect::<Vec<_>>(); .collect::<Vec<_>>();
if devices.is_empty() { if devices.is_empty() {
println!("No innernet networks currently running."); log::info!("No innernet networks currently running.");
return Ok(()); return Ok(());
} }
@ -917,6 +920,7 @@ fn print_peer(peer: &PeerState, short: bool, level: usize) {
fn main() { fn main() {
let opt = Opts::from_args(); let opt = Opts::from_args();
util::init_logger(opt.verbosity);
if let Err(e) = run(opt) { if let Err(e) = run(opt) {
eprintln!("\n{} {}\n", "[ERROR]".red(), e); eprintln!("\n{} {}\n", "[ERROR]".red(), e);

View File

@ -1,10 +1,50 @@
use crate::{ClientError, Error}; use crate::{ClientError, Error};
use colored::*; use colored::*;
use log::{Level, LevelFilter};
use serde::{de::DeserializeOwned, Serialize}; use serde::{de::DeserializeOwned, Serialize};
use shared::{interface_config::ServerInfo, INNERNET_PUBKEY_HEADER}; use shared::{interface_config::ServerInfo, INNERNET_PUBKEY_HEADER};
use std::time::Duration; use std::time::Duration;
use ureq::{Agent, AgentBuilder}; use ureq::{Agent, AgentBuilder};
static LOGGER: Logger = Logger;
struct Logger;
impl log::Log for Logger {
fn enabled(&self, metadata: &log::Metadata) -> bool {
metadata.level() <= log::max_level() && (log::max_level() == LevelFilter::Trace
|| metadata.target().starts_with("shared::")
|| metadata.target() == "innernet")
}
fn log(&self, record: &log::Record) {
if self.enabled(record.metadata()) {
let level_str = match record.level() {
Level::Error => "[E]".red(),
Level::Warn => "[!]".yellow(),
Level::Info => "[*]".dimmed(),
Level::Debug => "[D]".blue(),
Level::Trace => "[T]".purple(),
};
if record.level() <= LevelFilter::Debug && record.target() != "innernet" {
println!("{} {} {}", level_str, format!("[{}]", record.target()).dimmed(), record.args());
} else {
println!("{} {}", level_str, record.args());
}
}
}
fn flush(&self) {}
}
pub fn init_logger(verbosity: u64) {
let level = match verbosity {
0 => log::LevelFilter::Info,
1 => log::LevelFilter::Debug,
_ => log::LevelFilter::Trace,
};
log::set_max_level(level);
log::set_logger(&LOGGER).unwrap();
}
pub fn human_duration(duration: Duration) -> String { pub fn human_duration(duration: Duration) -> String {
match duration.as_secs() { match duration.as_secs() {
n if n < 1 => "just now".cyan().to_string(), n if n < 1 => "just now".cyan().to_string(),

View File

@ -12,6 +12,7 @@ dialoguer = "0.8"
indoc = "1" indoc = "1"
ipnetwork = { git = "https://github.com/mcginty/ipnetwork" } # pending https://github.com/achanda/ipnetwork/pull/129 ipnetwork = { git = "https://github.com/mcginty/ipnetwork" } # pending https://github.com/achanda/ipnetwork/pull/129
lazy_static = "1" lazy_static = "1"
log = "0.4"
publicip = { path = "../publicip" } publicip = { path = "../publicip" }
regex = "1" regex = "1"
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }