Better command line argument parsing
Use structs and enums instead of builder style options.
This commit is contained in:
parent
5d20366e5d
commit
34e3e3f32a
1 changed files with 31 additions and 23 deletions
54
src/main.rs
54
src/main.rs
|
@ -1,7 +1,7 @@
|
||||||
#![feature(proc_macro_hygiene, decl_macro)]
|
#![feature(proc_macro_hygiene, decl_macro)]
|
||||||
|
|
||||||
use anyhow::{anyhow, bail, Result};
|
use anyhow::{anyhow, bail, Result};
|
||||||
use clap::{app_from_crate, App, Arg};
|
use clap::{crate_authors, crate_version, AppSettings, Clap};
|
||||||
use hmac::{Hmac, Mac, NewMac};
|
use hmac::{Hmac, Mac, NewMac};
|
||||||
use ipnet::IpNet;
|
use ipnet::IpNet;
|
||||||
use log::{debug, error, info, trace, warn};
|
use log::{debug, error, info, trace, warn};
|
||||||
|
@ -54,6 +54,27 @@ enum WebhookeyError {
|
||||||
Regex(regex::Error),
|
Regex(regex::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clap, Debug)]
|
||||||
|
enum Command {
|
||||||
|
/// Verifies if the configuration can be parsed without errors
|
||||||
|
Configtest,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clap, Debug)]
|
||||||
|
#[clap(
|
||||||
|
version = crate_version!(),
|
||||||
|
author = crate_authors!(", "),
|
||||||
|
global_setting = AppSettings::VersionlessSubcommands,
|
||||||
|
global_setting = AppSettings::InferSubcommands,
|
||||||
|
)]
|
||||||
|
struct Opts {
|
||||||
|
/// Provide a path to the configuration file
|
||||||
|
#[clap(short, long, value_name = "FILE")]
|
||||||
|
config: Option<String>,
|
||||||
|
#[clap(subcommand)]
|
||||||
|
command: Option<Command>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
#[serde(deny_unknown_fields, untagged)]
|
#[serde(deny_unknown_fields, untagged)]
|
||||||
enum AddrType {
|
enum AddrType {
|
||||||
|
@ -86,6 +107,12 @@ impl IpFilter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
struct Config {
|
||||||
|
hooks: HashMap<String, Hook>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
#[serde(deny_unknown_fields)]
|
#[serde(deny_unknown_fields)]
|
||||||
struct JsonFilter {
|
struct JsonFilter {
|
||||||
|
@ -319,12 +346,6 @@ impl FromDataSimple for Hooks {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
|
||||||
#[serde(deny_unknown_fields)]
|
|
||||||
struct Config {
|
|
||||||
hooks: HashMap<String, Hook>,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn accept_ip(hook_name: &str, client_ip: &IpAddr, ip: &IpFilter) -> bool {
|
fn accept_ip(hook_name: &str, client_ip: &IpAddr, ip: &IpFilter) -> bool {
|
||||||
if ip.validate(client_ip) {
|
if ip.validate(client_ip) {
|
||||||
info!("Allow hook `{}` from {}", &hook_name, &client_ip);
|
info!("Allow hook `{}` from {}", &hook_name, &client_ip);
|
||||||
|
@ -475,29 +496,16 @@ fn get_config() -> Result<File> {
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
|
|
||||||
let cli = app_from_crate!()
|
let cli: Opts = Opts::parse();
|
||||||
.arg(
|
|
||||||
Arg::new("config")
|
|
||||||
.short('c')
|
|
||||||
.long("config")
|
|
||||||
.takes_value(true)
|
|
||||||
.value_name("FILE")
|
|
||||||
.about("Provide a path to the configuration file"),
|
|
||||||
)
|
|
||||||
.subcommand(
|
|
||||||
App::new("configtest")
|
|
||||||
.about("Verifies if the configuration can be parsed without errors"),
|
|
||||||
)
|
|
||||||
.get_matches();
|
|
||||||
|
|
||||||
let config: Config = match cli.value_of("config") {
|
let config: Config = match cli.config {
|
||||||
Some(config) => serde_yaml::from_reader(BufReader::new(File::open(config)?))?,
|
Some(config) => serde_yaml::from_reader(BufReader::new(File::open(config)?))?,
|
||||||
_ => serde_yaml::from_reader(BufReader::new(get_config()?))?,
|
_ => serde_yaml::from_reader(BufReader::new(get_config()?))?,
|
||||||
};
|
};
|
||||||
|
|
||||||
trace!("Parsed configuration:\n{}", serde_yaml::to_string(&config)?);
|
trace!("Parsed configuration:\n{}", serde_yaml::to_string(&config)?);
|
||||||
|
|
||||||
if cli.subcommand_matches("configtest").is_some() {
|
if cli.command.is_some() {
|
||||||
debug!("Configtest succeded.");
|
debug!("Configtest succeded.");
|
||||||
println!("Config is OK");
|
println!("Config is OK");
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
|
Loading…
Reference in a new issue