Add CLI parameters for disable/enable peer (#248)

* Add CLI parameters for disable/enable peer

Fixes tonarino/innernet#214.

* Formatting

* Remove redundant clones

* Require name for yes param

Yes param only makes sense if name is provided.

* Formatting
pull/299/head
Linus Kendall 2024-01-16 03:13:00 +05:30 committed by GitHub
parent 489f505f67
commit aa1ac515e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 86 additions and 34 deletions

View File

@ -10,9 +10,9 @@ use shared::{
prompts, prompts,
wg::{DeviceExt, PeerInfoExt}, wg::{DeviceExt, PeerInfoExt},
AddCidrOpts, AddDeleteAssociationOpts, AddPeerOpts, Association, AssociationContents, Cidr, AddCidrOpts, AddDeleteAssociationOpts, AddPeerOpts, Association, AssociationContents, Cidr,
CidrTree, DeleteCidrOpts, Endpoint, EndpointContents, InstallOpts, Interface, IoErrorContext, CidrTree, DeleteCidrOpts, EnableDisablePeerOpts, Endpoint, EndpointContents, InstallOpts,
ListenPortOpts, NatOpts, NetworkOpts, OverrideEndpointOpts, Peer, RedeemContents, Interface, IoErrorContext, ListenPortOpts, NatOpts, NetworkOpts, OverrideEndpointOpts, Peer,
RenamePeerOpts, State, WrappedIoError, REDEEM_TRANSITION_WAIT, RedeemContents, RenamePeerOpts, State, WrappedIoError, REDEEM_TRANSITION_WAIT,
}; };
use std::{ use std::{
fmt, io, fmt, io,
@ -211,10 +211,20 @@ enum Command {
}, },
/// Disable an enabled peer /// Disable an enabled peer
DisablePeer { interface: Interface }, DisablePeer {
interface: Interface,
#[clap(flatten)]
sub_opts: EnableDisablePeerOpts,
},
/// Enable a disabled peer /// Enable a disabled peer
EnablePeer { interface: Interface }, EnablePeer {
interface: Interface,
#[clap(flatten)]
sub_opts: EnableDisablePeerOpts,
},
/// Add an association between CIDRs /// Add an association between CIDRs
AddAssociation { AddAssociation {
@ -817,6 +827,7 @@ fn rename_peer(
fn enable_or_disable_peer( fn enable_or_disable_peer(
interface: &InterfaceName, interface: &InterfaceName,
opts: &Opts, opts: &Opts,
sub_opts: EnableDisablePeerOpts,
enable: bool, enable: bool,
) -> Result<(), Error> { ) -> Result<(), Error> {
let InterfaceConfig { server, .. } = let InterfaceConfig { server, .. } =
@ -826,7 +837,7 @@ fn enable_or_disable_peer(
log::info!("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[..], &sub_opts, enable)? {
let Peer { id, mut contents } = peer; let Peer { id, mut contents } = peer;
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)?;
@ -1245,8 +1256,14 @@ fn run(opts: &Opts) -> Result<(), Error> {
sub_opts, sub_opts,
} => delete_cidr(&interface, opts, sub_opts)?, } => delete_cidr(&interface, opts, sub_opts)?,
Command::ListCidrs { interface, tree } => list_cidrs(&interface, opts, tree)?, Command::ListCidrs { interface, tree } => list_cidrs(&interface, opts, tree)?,
Command::DisablePeer { interface } => enable_or_disable_peer(&interface, opts, false)?, Command::DisablePeer {
Command::EnablePeer { interface } => enable_or_disable_peer(&interface, opts, true)?, 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 { Command::AddAssociation {
interface, interface,
sub_opts, sub_opts,

View File

@ -9,8 +9,8 @@ use parking_lot::{Mutex, RwLock};
use rusqlite::Connection; use rusqlite::Connection;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use shared::{ use shared::{
get_local_addrs, AddCidrOpts, AddPeerOpts, DeleteCidrOpts, Endpoint, IoErrorContext, get_local_addrs, AddCidrOpts, AddPeerOpts, DeleteCidrOpts, EnableDisablePeerOpts, Endpoint,
NetworkOpts, PeerContents, RenamePeerOpts, INNERNET_PUBKEY_HEADER, IoErrorContext, NetworkOpts, PeerContents, RenamePeerOpts, INNERNET_PUBKEY_HEADER,
}; };
use std::{ use std::{
collections::{HashMap, VecDeque}, collections::{HashMap, VecDeque},
@ -95,10 +95,20 @@ enum Command {
}, },
/// Disable an enabled peer /// Disable an enabled peer
DisablePeer { interface: Interface }, DisablePeer {
interface: Interface,
#[clap(flatten)]
args: EnableDisablePeerOpts,
},
/// Enable a disabled peer /// Enable a disabled peer
EnablePeer { interface: Interface }, EnablePeer {
interface: Interface,
#[clap(flatten)]
args: EnableDisablePeerOpts,
},
/// Rename an existing peer. /// Rename an existing peer.
RenamePeer { RenamePeer {
@ -271,11 +281,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
} => serve(*interface, &conf, routing).await?, } => serve(*interface, &conf, routing).await?,
Command::AddPeer { interface, args } => add_peer(&interface, &conf, args, opts.network)?, Command::AddPeer { interface, args } => add_peer(&interface, &conf, args, opts.network)?,
Command::RenamePeer { interface, args } => rename_peer(&interface, &conf, args)?, Command::RenamePeer { interface, args } => rename_peer(&interface, &conf, args)?,
Command::DisablePeer { interface } => { Command::DisablePeer { interface, args } => {
enable_or_disable_peer(&interface, &conf, false, opts.network)? enable_or_disable_peer(&interface, &conf, false, opts.network, args)?
}, },
Command::EnablePeer { interface } => { Command::EnablePeer { interface, args } => {
enable_or_disable_peer(&interface, &conf, true, opts.network)? enable_or_disable_peer(&interface, &conf, true, opts.network, args)?
}, },
Command::AddCidr { interface, args } => add_cidr(&interface, &conf, args)?, Command::AddCidr { interface, args } => add_cidr(&interface, &conf, args)?,
Command::DeleteCidr { interface, args } => delete_cidr(&interface, &conf, args)?, Command::DeleteCidr { interface, args } => delete_cidr(&interface, &conf, args)?,
@ -384,6 +394,7 @@ fn enable_or_disable_peer(
conf: &ServerConfig, conf: &ServerConfig,
enable: bool, enable: bool,
network: NetworkOpts, network: NetworkOpts,
opts: EnableDisablePeerOpts,
) -> Result<(), Error> { ) -> Result<(), Error> {
let conn = open_database_connection(interface, conf)?; let conn = open_database_connection(interface, conf)?;
let peers = DatabasePeer::list(&conn)? let peers = DatabasePeer::list(&conn)?
@ -391,7 +402,7 @@ fn enable_or_disable_peer(
.map(|dp| dp.inner) .map(|dp| dp.inner)
.collect::<Vec<_>>(); .collect::<Vec<_>>();
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)?; let mut db_peer = DatabasePeer::get(&conn, peer.id)?;
db_peer.update( db_peer.update(
&conn, &conn,

View File

@ -1,8 +1,8 @@
use crate::{ use crate::{
interface_config::{InterfaceConfig, InterfaceInfo, ServerInfo}, interface_config::{InterfaceConfig, InterfaceInfo, ServerInfo},
AddCidrOpts, AddDeleteAssociationOpts, AddPeerOpts, Association, Cidr, CidrContents, CidrTree, AddCidrOpts, AddDeleteAssociationOpts, AddPeerOpts, Association, Cidr, CidrContents, CidrTree,
DeleteCidrOpts, Endpoint, Error, Hostname, IpNetExt, ListenPortOpts, OverrideEndpointOpts, DeleteCidrOpts, EnableDisablePeerOpts, Endpoint, Error, Hostname, IpNetExt, ListenPortOpts,
Peer, PeerContents, RenamePeerOpts, PERSISTENT_KEEPALIVE_INTERVAL_SECS, OverrideEndpointOpts, Peer, PeerContents, RenamePeerOpts, PERSISTENT_KEEPALIVE_INTERVAL_SECS,
}; };
use anyhow::anyhow; use anyhow::anyhow;
use colored::*; use colored::*;
@ -394,28 +394,41 @@ pub fn rename_peer(
/// Presents a selection and confirmation of eligible peers for either disabling or enabling, /// Presents a selection and confirmation of eligible peers for either disabling or enabling,
/// and returns back the ID of the selected peer. /// and returns back the ID of the selected peer.
pub fn enable_or_disable_peer(peers: &[Peer], enable: bool) -> Result<Option<Peer>, Error> { pub fn enable_or_disable_peer(
peers: &[Peer],
args: &EnableDisablePeerOpts,
enable: bool,
) -> Result<Option<Peer>, Error> {
let enabled_peers: Vec<_> = peers let enabled_peers: Vec<_> = peers
.iter() .iter()
.filter(|peer| enable && peer.is_disabled || !enable && !peer.is_disabled) .filter(|peer| enable && peer.is_disabled || !enable && !peer.is_disabled)
.collect(); .collect();
let peer_selection: Vec<_> = enabled_peers let peer = if let Some(ref name) = args.name {
.iter() enabled_peers
.map(|peer| format!("{} ({})", &peer.name, &peer.ip)) .into_iter()
.collect(); .find(|p| &p.name == name)
let (index, _) = select( .ok_or_else(|| anyhow!("Peer '{}' does not exist", name))?
&format!("Peer to {}able", if enable { "en" } else { "dis" }), } else {
&peer_selection, let peer_selection: Vec<_> = enabled_peers
)?; .iter()
let peer = enabled_peers[index]; .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]
};
Ok( Ok(
if confirm(&format!( if args.yes
"{}able peer {}?", || confirm(&format!(
if enable { "En" } else { "Dis" }, "{}able peer {}?",
peer.name.yellow() if enable { "En" } else { "Dis" },
))? { peer.name.yellow()
))?
{
Some(peer.clone()) Some(peer.clone())
} else { } else {
None None

View File

@ -351,6 +351,17 @@ pub struct RenamePeerOpts {
pub yes: bool, pub yes: bool,
} }
#[derive(Debug, Clone, PartialEq, Eq, Args)]
pub struct EnableDisablePeerOpts {
/// Name of peer to enable/disable
#[clap(long)]
pub name: Option<Hostname>,
/// Bypass confirmation
#[clap(long, requires("name"))]
pub yes: bool,
}
#[derive(Debug, Clone, PartialEq, Eq, Args)] #[derive(Debug, Clone, PartialEq, Eq, Args)]
pub struct AddCidrOpts { pub struct AddCidrOpts {
/// The CIDR name (eg. 'engineers') /// The CIDR name (eg. 'engineers')