hoprd_cfg/hoprd-cfg.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
//! Hoprd configuration utility `hoprd-cfg`
//!
//! This executable offers functionalities associated with configuration management
//! of the HOPRd node configuration.
//!
//! ## Help
//! ```shell
//! ➜ hoprd-cfg --help
//! Usage: hoprd-cfg [OPTIONS]
//!
//! Options:
//! -d, --default Print the default YAML config for the hoprd
//! -v, --validate <VALIDATE> Validate the config at this path
//! -h, --help Print help
//! -V, --version Print version
//! ```
//!
//! ## Dump a default configuration file
//! ```shell
//! ➜ hoprd-cfg -d
//! hopr:
//! host:
//! address: !IPv4 0.0.0.0
//! port: 9091
//!
//! ... <snip>
//!
//! ```
//!
//! ## Validate an existing configuration YAML
//!
//! ```shell
//! ➜ hoprd-cfg -v /tmp/bad-config.yaml
//! Error: ValidationError("The specified network 'anvil-localhost' is not listed as supported ([\"debug-staging\", \"dufour\", \"rotsee\"])")
//!
//! ➜ echo $?
//! 1
//! ```
use std::path::PathBuf;
use clap::Parser;
use hoprd::config::HoprdConfig;
use validator::Validate;
#[derive(Parser, Default)]
#[clap(author, version, about, long_about = None)]
struct CliArgs {
/// Print the default YAML config for the hoprd
#[clap(short = 'd', long, conflicts_with = "validate")]
default: bool,
/// Validate the config at this path
#[clap(short, long, conflicts_with = "default")]
validate: Option<PathBuf>,
}
fn main() -> Result<(), hoprd::errors::HoprdError> {
let args = CliArgs::parse();
if args.default {
println!(
"{}",
serde_yaml::to_string(&hoprd::config::HoprdConfig::default())
.map_err(|e| hoprd::errors::HoprdError::ConfigError(e.to_string()))?
);
} else if let Some(cfg_path) = args.validate {
let cfg_path = cfg_path
.into_os_string()
.into_string()
.map_err(|_| hoprd::errors::HoprdError::ConfigError("file path not convertible".into()))?;
let yaml_configuration = hopr_platform::file::native::read_to_string(&cfg_path)
.map_err(|e| hoprd::errors::HoprdError::ConfigError(e.to_string()))?;
let cfg: HoprdConfig = serde_yaml::from_str(&yaml_configuration)
.map_err(|e| hoprd::errors::HoprdError::SerializationError(e.to_string()))?;
if !cfg
.hopr
.chain
.protocols
.supported_networks(hopr_lib::constants::APP_VERSION_COERCED)
.iter()
.any(|network| network == &cfg.hopr.chain.network)
{
return Err(hoprd::errors::HoprdError::ValidationError(format!(
"The specified network '{}' is not listed as supported ({:?})",
cfg.hopr.chain.network,
cfg.hopr
.chain
.protocols
.supported_networks(hopr_lib::constants::APP_VERSION_COERCED)
)));
};
if let Err(e) = cfg.validate() {
return Err(hoprd::errors::HoprdError::ValidationError(e.to_string()));
};
}
Ok(())
}