client: add opts for non-interactive network installs
parent
6d28e7f4ab
commit
b92ad65b17
|
@ -3,9 +3,9 @@ use dialoguer::{Confirm, Input};
|
|||
use hostsfile::HostsBuilder;
|
||||
use indoc::printdoc;
|
||||
use shared::{
|
||||
interface_config::InterfaceConfig, prompts, AddCidrContents, AddPeerContents, Association,
|
||||
AssociationContents, Cidr, CidrTree, EndpointContents, Interface, IoErrorContext, Peer,
|
||||
RedeemContents, State, CLIENT_CONFIG_PATH, REDEEM_TRANSITION_WAIT,
|
||||
interface_config::InterfaceConfig, prompts, AddCidrOpts, AddPeerOpts, Association,
|
||||
AssociationContents, Cidr, CidrTree, EndpointContents, InstallOpts, Interface, IoErrorContext,
|
||||
Peer, RedeemContents, State, CLIENT_CONFIG_PATH, REDEEM_TRANSITION_WAIT,
|
||||
};
|
||||
use std::{
|
||||
fmt,
|
||||
|
@ -56,6 +56,9 @@ enum Command {
|
|||
|
||||
#[structopt(flatten)]
|
||||
hosts: HostsOpt,
|
||||
|
||||
#[structopt(flatten)]
|
||||
opts: InstallOpts,
|
||||
},
|
||||
|
||||
/// Enumerate all innernet connections.
|
||||
|
@ -107,7 +110,7 @@ enum Command {
|
|||
interface: Interface,
|
||||
|
||||
#[structopt(flatten)]
|
||||
args: AddPeerContents,
|
||||
opts: AddPeerOpts,
|
||||
},
|
||||
|
||||
/// Add a new CIDR.
|
||||
|
@ -115,7 +118,7 @@ enum Command {
|
|||
interface: Interface,
|
||||
|
||||
#[structopt(flatten)]
|
||||
args: AddCidrContents,
|
||||
opts: AddCidrOpts,
|
||||
},
|
||||
|
||||
/// Disable an enabled peer.
|
||||
|
@ -191,14 +194,20 @@ fn update_hosts_file(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn install(invite: &Path, hosts_file: Option<PathBuf>) -> Result<(), Error> {
|
||||
fn install(invite: &Path, hosts_file: Option<PathBuf>, opts: InstallOpts) -> Result<(), Error> {
|
||||
shared::ensure_dirs_exist(&[*CLIENT_CONFIG_PATH])?;
|
||||
let config = InterfaceConfig::from_file(invite)?;
|
||||
|
||||
let iface = Input::with_theme(&*prompts::THEME)
|
||||
.with_prompt("Interface name")
|
||||
.default(config.interface.network_name.clone())
|
||||
.interact()?;
|
||||
let iface = if opts.default_name {
|
||||
config.interface.network_name.clone()
|
||||
} else if let Some(ref iface) = opts.name {
|
||||
iface.clone()
|
||||
} else {
|
||||
Input::with_theme(&*prompts::THEME)
|
||||
.with_prompt("Interface name")
|
||||
.default(config.interface.network_name.clone())
|
||||
.interact()?
|
||||
};
|
||||
|
||||
let target_conf = CLIENT_CONFIG_PATH.join(&iface).with_extension("conf");
|
||||
if target_conf.exists() {
|
||||
|
@ -217,13 +226,14 @@ fn install(invite: &Path, hosts_file: Option<PathBuf>) -> Result<(), Error> {
|
|||
|
||||
fetch(&iface, false, hosts_file)?;
|
||||
|
||||
if Confirm::with_theme(&*prompts::THEME)
|
||||
.with_prompt(&format!(
|
||||
"Delete invitation file \"{}\" now? (It's no longer needed)",
|
||||
invite.to_string_lossy().yellow()
|
||||
))
|
||||
.default(true)
|
||||
.interact()?
|
||||
if opts.delete_invite
|
||||
|| Confirm::with_theme(&*prompts::THEME)
|
||||
.with_prompt(&format!(
|
||||
"Delete invitation file \"{}\" now? (It's no longer needed)",
|
||||
invite.to_string_lossy().yellow()
|
||||
))
|
||||
.default(true)
|
||||
.interact()?
|
||||
{
|
||||
std::fs::remove_file(invite).with_path(invite)?;
|
||||
}
|
||||
|
@ -473,13 +483,13 @@ fn uninstall(interface: &InterfaceName) -> Result<(), Error> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn add_cidr(interface: &InterfaceName, args: AddCidrContents) -> Result<(), Error> {
|
||||
fn add_cidr(interface: &InterfaceName, opts: AddCidrOpts) -> Result<(), Error> {
|
||||
let InterfaceConfig { server, .. } = InterfaceConfig::from_interface(interface)?;
|
||||
println!("Fetching CIDRs");
|
||||
let api = Api::new(&server);
|
||||
let cidrs: Vec<Cidr> = api.http("GET", "/admin/cidrs")?;
|
||||
|
||||
let cidr_request = prompts::add_cidr(&cidrs, &args)?;
|
||||
let cidr_request = prompts::add_cidr(&cidrs, &opts)?;
|
||||
|
||||
println!("Creating CIDR...");
|
||||
let cidr: Cidr = api.http_form("POST", "/admin/cidrs", cidr_request)?;
|
||||
|
@ -499,7 +509,7 @@ fn add_cidr(interface: &InterfaceName, args: AddCidrContents) -> Result<(), Erro
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn add_peer(interface: &InterfaceName, args: AddPeerContents) -> Result<(), Error> {
|
||||
fn add_peer(interface: &InterfaceName, opts: AddPeerOpts) -> Result<(), Error> {
|
||||
let InterfaceConfig { server, .. } = InterfaceConfig::from_interface(interface)?;
|
||||
let api = Api::new(&server);
|
||||
|
||||
|
@ -509,7 +519,7 @@ fn add_peer(interface: &InterfaceName, args: AddPeerContents) -> Result<(), Erro
|
|||
let peers: Vec<Peer> = api.http("GET", "/admin/peers")?;
|
||||
let cidr_tree = CidrTree::new(&cidrs[..]);
|
||||
|
||||
if let Some((peer_request, keypair)) = prompts::add_peer(&peers, &cidr_tree, &args)? {
|
||||
if let Some((peer_request, keypair)) = prompts::add_peer(&peers, &cidr_tree, &opts)? {
|
||||
println!("Creating peer...");
|
||||
let peer: Peer = api.http_form("POST", "/admin/peers", peer_request)?;
|
||||
let server_peer = peers.iter().find(|p| p.id == 1).unwrap();
|
||||
|
@ -520,7 +530,7 @@ fn add_peer(interface: &InterfaceName, args: AddPeerContents) -> Result<(), Erro
|
|||
&cidr_tree,
|
||||
keypair,
|
||||
&server.internal_endpoint,
|
||||
&args.save_config,
|
||||
&opts.save_config,
|
||||
)?;
|
||||
} else {
|
||||
println!("exited without creating peer.");
|
||||
|
@ -830,7 +840,11 @@ fn run(opt: Opt) -> Result<(), Error> {
|
|||
});
|
||||
|
||||
match command {
|
||||
Command::Install { config, hosts } => install(&config, hosts.into())?,
|
||||
Command::Install {
|
||||
config,
|
||||
hosts,
|
||||
opts,
|
||||
} => install(&config, hosts.into(), opts)?,
|
||||
Command::Show {
|
||||
short,
|
||||
tree,
|
||||
|
@ -849,8 +863,8 @@ fn run(opt: Opt) -> Result<(), Error> {
|
|||
)?,
|
||||
Command::Down { interface } => wg::down(&interface)?,
|
||||
Command::Uninstall { interface } => uninstall(&interface)?,
|
||||
Command::AddPeer { interface, args } => add_peer(&interface, args)?,
|
||||
Command::AddCidr { interface, args } => add_cidr(&interface, args)?,
|
||||
Command::AddPeer { interface, opts } => add_peer(&interface, opts)?,
|
||||
Command::AddCidr { interface, opts } => add_cidr(&interface, opts)?,
|
||||
Command::DisablePeer { interface } => enable_or_disable_peer(&interface, false)?,
|
||||
Command::EnablePeer { interface } => enable_or_disable_peer(&interface, true)?,
|
||||
Command::AddAssociation { interface } => add_association(&interface)?,
|
||||
|
|
|
@ -7,7 +7,7 @@ use ipnetwork::IpNetwork;
|
|||
use parking_lot::Mutex;
|
||||
use rusqlite::Connection;
|
||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||
use shared::{AddCidrContents, AddPeerContents, IoErrorContext, INNERNET_PUBKEY_HEADER};
|
||||
use shared::{AddCidrOpts, AddPeerOpts, IoErrorContext, INNERNET_PUBKEY_HEADER};
|
||||
use std::{
|
||||
convert::Infallible,
|
||||
env,
|
||||
|
@ -64,7 +64,7 @@ enum Command {
|
|||
interface: Interface,
|
||||
|
||||
#[structopt(flatten)]
|
||||
args: AddPeerContents,
|
||||
args: AddPeerOpts,
|
||||
},
|
||||
|
||||
/// Add a new CIDR to an existing network.
|
||||
|
@ -72,7 +72,7 @@ enum Command {
|
|||
interface: Interface,
|
||||
|
||||
#[structopt(flatten)]
|
||||
args: AddCidrContents,
|
||||
args: AddCidrOpts,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -237,7 +237,7 @@ fn open_database_connection(
|
|||
fn add_peer(
|
||||
interface: &InterfaceName,
|
||||
conf: &ServerConfig,
|
||||
args: AddPeerContents,
|
||||
args: AddPeerOpts,
|
||||
) -> Result<(), Error> {
|
||||
let config = ConfigFile::from_file(conf.config_path(interface))?;
|
||||
let conn = open_database_connection(interface, conf)?;
|
||||
|
@ -280,7 +280,7 @@ fn add_peer(
|
|||
fn add_cidr(
|
||||
interface: &InterfaceName,
|
||||
conf: &ServerConfig,
|
||||
args: AddCidrContents,
|
||||
args: AddCidrOpts,
|
||||
) -> Result<(), Error> {
|
||||
let conn = open_database_connection(interface, conf)?;
|
||||
let cidrs = DatabaseCidr::list(&conn)?;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
interface_config::{InterfaceConfig, InterfaceInfo, ServerInfo},
|
||||
AddCidrContents, AddPeerContents, Association, Cidr, CidrContents, CidrTree, Error, Peer,
|
||||
PeerContents, PERSISTENT_KEEPALIVE_INTERVAL_SECS,
|
||||
AddCidrOpts, AddPeerOpts, Association, Cidr, CidrContents, CidrTree, Error, Peer, PeerContents,
|
||||
PERSISTENT_KEEPALIVE_INTERVAL_SECS,
|
||||
};
|
||||
use colored::*;
|
||||
use dialoguer::{theme::ColorfulTheme, Confirm, Input, Select};
|
||||
|
@ -32,7 +32,7 @@ pub fn hostname_validator(name: &String) -> Result<(), &'static str> {
|
|||
}
|
||||
|
||||
/// Bring up a prompt to create a new CIDR. Returns the peer request.
|
||||
pub fn add_cidr(cidrs: &[Cidr], request: &AddCidrContents) -> Result<Option<CidrContents>, Error> {
|
||||
pub fn add_cidr(cidrs: &[Cidr], request: &AddCidrOpts) -> Result<Option<CidrContents>, Error> {
|
||||
let parent_cidr = if let Some(ref parent_name) = request.parent {
|
||||
cidrs
|
||||
.iter()
|
||||
|
@ -161,7 +161,7 @@ pub fn delete_association<'a>(
|
|||
pub fn add_peer(
|
||||
peers: &[Peer],
|
||||
cidr_tree: &CidrTree,
|
||||
args: &AddPeerContents,
|
||||
args: &AddPeerOpts,
|
||||
) -> Result<Option<(PeerContents, KeyPair)>, Error> {
|
||||
let leaves = cidr_tree.leaves();
|
||||
|
||||
|
|
|
@ -167,7 +167,22 @@ pub struct RedeemContents {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, StructOpt)]
|
||||
pub struct AddPeerContents {
|
||||
pub struct InstallOpts {
|
||||
/// Set a specific interface name
|
||||
#[structopt(long, conflicts_with = "default-name")]
|
||||
pub name: Option<String>,
|
||||
|
||||
/// Use the network name inside the invitation as the interface name
|
||||
#[structopt(long = "default-name")]
|
||||
pub default_name: bool,
|
||||
|
||||
/// Delete the invitation after a successful install
|
||||
#[structopt(short, long)]
|
||||
pub delete_invite: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, StructOpt)]
|
||||
pub struct AddPeerOpts {
|
||||
/// Name of new peer
|
||||
#[structopt(long)]
|
||||
pub name: Option<String>,
|
||||
|
@ -197,7 +212,7 @@ pub struct AddPeerContents {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, StructOpt)]
|
||||
pub struct AddCidrContents {
|
||||
pub struct AddCidrOpts {
|
||||
#[structopt(long)]
|
||||
pub name: Option<String>,
|
||||
|
||||
|
|
Loading…
Reference in New Issue