use clap::{ArgMatches, Command}; use clap_utils::get_color_style; use common::write_to_json_file; use environment::Environment; use serde::Serialize; use std::path::PathBuf; use types::EthSpec; pub mod common; pub mod create_validators; pub mod delete_validators; pub mod exit_validators; pub mod import_validators; pub mod list_validators; pub mod move_validators; pub const CMD: &str = "validator_manager"; /// This flag is on the top-level `lighthouse` binary. const DUMP_CONFIGS_FLAG: &str = "dump-config"; /// Used only in testing, this allows a command to dump its configuration to a file and then exit /// successfully. This allows for testing how the CLI arguments translate to some configuration. pub enum DumpConfig { Disabled, Enabled(PathBuf), } impl DumpConfig { /// Returns `Ok(true)` if the configuration was successfully written to a file and the /// application should exit successfully without doing anything else. pub fn should_exit_early(&self, config: &T) -> Result { match self { DumpConfig::Disabled => Ok(false), DumpConfig::Enabled(dump_path) => { dbg!(dump_path); write_to_json_file(dump_path, config)?; Ok(true) } } } } pub fn cli_app() -> Command { Command::new(CMD) .visible_aliases(["vm", "validator-manager"]) .display_order(0) .styles(get_color_style()) .about("Utilities for managing a Lighthouse validator client via the HTTP API.") .subcommand(create_validators::cli_app()) .subcommand(import_validators::cli_app()) .subcommand(move_validators::cli_app()) .subcommand(list_validators::cli_app()) .subcommand(delete_validators::cli_app()) .subcommand(exit_validators::cli_app()) } /// Run the account manager, returning an error if the operation did not succeed. pub fn run(matches: &ArgMatches, env: Environment) -> Result<(), String> { let context = env.core_context(); let spec = context.eth2_config.spec; let dump_config = clap_utils::parse_optional(matches, DUMP_CONFIGS_FLAG)? .map(DumpConfig::Enabled) .unwrap_or_else(|| DumpConfig::Disabled); context .executor // This `block_on_dangerous` call reasonable since it is at the very highest level of the // application, the rest of which is all async. All other functions below this should be // async and should never call `block_on_dangerous` themselves. .block_on_dangerous( async { match matches.subcommand() { Some((create_validators::CMD, matches)) => { create_validators::cli_run::(matches, &spec, dump_config).await } Some((import_validators::CMD, matches)) => { import_validators::cli_run(matches, dump_config).await } Some((move_validators::CMD, matches)) => { move_validators::cli_run(matches, dump_config).await } Some((list_validators::CMD, matches)) => { list_validators::cli_run::(matches, dump_config).await } Some((delete_validators::CMD, matches)) => { delete_validators::cli_run(matches, dump_config).await } Some((exit_validators::CMD, matches)) => { exit_validators::cli_run::(matches, dump_config).await } Some(("", _)) => Err("No command supplied. See --help.".to_string()), Some((unknown, _)) => Err(format!( "{} is not a valid {} command. See --help.", unknown, CMD )), _ => Err("No command supplied. See --help.".to_string()), } }, "validator_manager", ) .ok_or("Shutting down")? }