From c402798b60b8394525a684a6add5575a62254694 Mon Sep 17 00:00:00 2001 From: linuskendall Date: Wed, 22 Feb 2023 18:34:24 +0000 Subject: [PATCH] Add CLI parameters for disable/enable peer Fixes tonarino/innernet#214. --- client/src/main.rs | 29 +++++++++++++++++++++++------ server/src/main.rs | 27 +++++++++++++++++++-------- shared/src/prompts.rs | 42 ++++++++++++++++++++++++++---------------- shared/src/types.rs | 12 ++++++++++++ 4 files changed, 80 insertions(+), 30 deletions(-) diff --git a/client/src/main.rs b/client/src/main.rs index f9acca4..6845ade 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -12,7 +12,7 @@ use shared::{ AddCidrOpts, AddDeleteAssociationOpts, AddPeerOpts, Association, AssociationContents, Cidr, CidrTree, DeleteCidrOpts, Endpoint, EndpointContents, InstallOpts, Interface, IoErrorContext, ListenPortOpts, NatOpts, NetworkOpts, OverrideEndpointOpts, Peer, RedeemContents, - RenamePeerOpts, State, WrappedIoError, REDEEM_TRANSITION_WAIT, + RenamePeerOpts, EnableDisablePeerOpts, State, WrappedIoError, REDEEM_TRANSITION_WAIT, }; use std::{ fmt, io, @@ -212,10 +212,20 @@ enum Command { }, /// Disable an enabled peer - DisablePeer { interface: Interface }, + DisablePeer { + interface: Interface, + + #[clap(flatten)] + sub_opts: EnableDisablePeerOpts, + }, /// Enable a disabled peer - EnablePeer { interface: Interface }, + EnablePeer { + interface: Interface, + + #[clap(flatten)] + sub_opts: EnableDisablePeerOpts, + }, /// Add an association between CIDRs AddAssociation { @@ -813,6 +823,7 @@ fn rename_peer( fn enable_or_disable_peer( interface: &InterfaceName, opts: &Opts, + sub_opts: EnableDisablePeerOpts, enable: bool, ) -> Result<(), Error> { let InterfaceConfig { server, .. } = @@ -822,7 +833,7 @@ fn enable_or_disable_peer( log::info!("Fetching peers."); let peers: Vec = 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[..], &sub_opts, enable)? { let Peer { id, mut contents } = peer; contents.is_disabled = !enable; api.http_form("PUT", &format!("/admin/peers/{id}"), contents)?; @@ -1251,8 +1262,14 @@ fn run(opts: &Opts) -> Result<(), Error> { sub_opts, } => delete_cidr(&interface, opts, sub_opts)?, Command::ListCidrs { interface, tree } => list_cidrs(&interface, opts, tree)?, - Command::DisablePeer { interface } => enable_or_disable_peer(&interface, opts, false)?, - Command::EnablePeer { interface } => enable_or_disable_peer(&interface, opts, true)?, + Command::DisablePeer { + interface, + sub_opts, + } => enable_or_disable_peer(&interface, opts, sub_opts, false)?, + Command::EnablePeer { + interface, + sub_opts, + } => enable_or_disable_peer(&interface, opts, sub_opts, true)?, Command::AddAssociation { interface, sub_opts, diff --git a/server/src/main.rs b/server/src/main.rs index 3f6eea6..f8bd499 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -10,7 +10,7 @@ use rusqlite::Connection; use serde::{Deserialize, Serialize}; use shared::{ get_local_addrs, AddCidrOpts, AddPeerOpts, DeleteCidrOpts, Endpoint, IoErrorContext, - NetworkOpts, PeerContents, RenamePeerOpts, INNERNET_PUBKEY_HEADER, + NetworkOpts, PeerContents, RenamePeerOpts, EnableDisablePeerOpts, INNERNET_PUBKEY_HEADER, }; use std::{ collections::{HashMap, VecDeque}, @@ -96,10 +96,20 @@ enum Command { }, /// Disable an enabled peer - DisablePeer { interface: Interface }, + DisablePeer { + interface: Interface, + + #[clap(flatten)] + args: EnableDisablePeerOpts, + }, /// Enable a disabled peer - EnablePeer { interface: Interface }, + EnablePeer { + interface: Interface, + + #[clap(flatten)] + args: EnableDisablePeerOpts, + }, /// Rename an existing peer. RenamePeer { @@ -270,11 +280,11 @@ async fn main() -> Result<(), Box> { } => serve(*interface, &conf, routing).await?, Command::AddPeer { interface, args } => add_peer(&interface, &conf, args, opts.network)?, Command::RenamePeer { interface, args } => rename_peer(&interface, &conf, args)?, - Command::DisablePeer { interface } => { - enable_or_disable_peer(&interface, &conf, false, opts.network)? + Command::DisablePeer { interface, args } => { + enable_or_disable_peer(&interface, &conf, false, opts.network, args)? }, - Command::EnablePeer { interface } => { - enable_or_disable_peer(&interface, &conf, true, opts.network)? + Command::EnablePeer { interface, args } => { + enable_or_disable_peer(&interface, &conf, true, opts.network, args)? }, Command::AddCidr { interface, args } => add_cidr(&interface, &conf, args)?, Command::DeleteCidr { interface, args } => delete_cidr(&interface, &conf, args)?, @@ -382,6 +392,7 @@ fn enable_or_disable_peer( conf: &ServerConfig, enable: bool, network: NetworkOpts, + opts: EnableDisablePeerOpts, ) -> Result<(), Error> { let conn = open_database_connection(interface, conf)?; let peers = DatabasePeer::list(&conn)? @@ -389,7 +400,7 @@ fn enable_or_disable_peer( .map(|dp| dp.inner) .collect::>(); - if let Some(peer) = prompts::enable_or_disable_peer(&peers[..], enable)? { + if let Some(peer) = prompts::enable_or_disable_peer(&peers[..], &opts, enable)? { let mut db_peer = DatabasePeer::get(&conn, peer.id)?; db_peer.update( &conn, diff --git a/shared/src/prompts.rs b/shared/src/prompts.rs index 1b685ef..d613c0b 100644 --- a/shared/src/prompts.rs +++ b/shared/src/prompts.rs @@ -2,7 +2,7 @@ use crate::{ interface_config::{InterfaceConfig, InterfaceInfo, ServerInfo}, AddCidrOpts, AddDeleteAssociationOpts, AddPeerOpts, Association, Cidr, CidrContents, CidrTree, DeleteCidrOpts, Endpoint, Error, Hostname, IpNetExt, ListenPortOpts, OverrideEndpointOpts, - Peer, PeerContents, RenamePeerOpts, PERSISTENT_KEEPALIVE_INTERVAL_SECS, + Peer, PeerContents, RenamePeerOpts, EnableDisablePeerOpts, PERSISTENT_KEEPALIVE_INTERVAL_SECS, }; use anyhow::anyhow; use colored::*; @@ -396,28 +396,38 @@ pub fn rename_peer( /// Presents a selection and confirmation of eligible peers for either disabling or enabling, /// and returns back the ID of the selected peer. -pub fn enable_or_disable_peer(peers: &[Peer], enable: bool) -> Result, Error> { +pub fn enable_or_disable_peer(peers: &[Peer], args: &EnableDisablePeerOpts, enable: bool) -> Result, Error> { let enabled_peers: Vec<_> = peers .iter() .filter(|peer| enable && peer.is_disabled || !enable && !peer.is_disabled) .collect(); - let peer_selection: Vec<_> = enabled_peers - .iter() - .map(|peer| format!("{} ({})", &peer.name, &peer.ip)) - .collect(); - let (index, _) = select( - &format!("Peer to {}able", if enable { "en" } else { "dis" }), - &peer_selection, - )?; - let peer = enabled_peers[index]; + let peer = if let Some(ref name) = args.name { + enabled_peers + .into_iter() + .find(|p| &p.name == name) + .ok_or_else(|| anyhow!("Peer '{}' does not exist", name))? + .clone() + } else { + let peer_selection: Vec<_> = enabled_peers + .iter() + .map(|peer| format!("{} ({})", &peer.name, &peer.ip)) + .collect(); + let (index, _) = select( + &format!("Peer to {}able", if enable { "en" } else { "dis" }), + &peer_selection, + )?; + enabled_peers[index].clone() + }; Ok( - if confirm(&format!( - "{}able peer {}?", - if enable { "En" } else { "Dis" }, - peer.name.yellow() - ))? { + if args.yes + || confirm(&format!( + "{}able peer {}?", + if enable { "En" } else { "Dis" }, + peer.name.yellow() + ))? + { Some(peer.clone()) } else { None diff --git a/shared/src/types.rs b/shared/src/types.rs index 446de3f..a326b49 100644 --- a/shared/src/types.rs +++ b/shared/src/types.rs @@ -348,6 +348,18 @@ pub struct RenamePeerOpts { pub yes: bool, } + +#[derive(Debug, Clone, PartialEq, Eq, Args)] +pub struct EnableDisablePeerOpts { + /// Name of peer to enable/disable + #[clap(long)] + pub name: Option, + + /// Bypass confirmation + #[clap(long)] + pub yes: bool, +} + #[derive(Debug, Clone, PartialEq, Eq, Args)] pub struct AddCidrOpts { /// The CIDR name (eg. 'engineers')