hoprd_cfg/
hoprd-cfg.rs

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