use anyhow::{Context, Error};
use exonum_supervisor::mode::Mode as SupervisorMode;
use serde_derive::{Deserialize, Serialize};
use structopt::StructOpt;
use std::{fs, net::SocketAddr, path::PathBuf, str::FromStr};
use crate::command::{
finalize::Finalize,
generate_config::{GenerateConfig, PRIVATE_CONFIG_FILE_NAME, PUBLIC_CONFIG_FILE_NAME},
generate_template::GenerateTemplate,
run::Run,
ExonumCommand, StandardResult,
};
#[derive(StructOpt, Debug, Serialize, Deserialize)]
#[non_exhaustive]
pub struct RunDev {
#[structopt(long, short = "-p")]
pub blockchain_path: PathBuf,
#[structopt(long, default_value = "127.0.0.1:8080")]
pub public_api_address: SocketAddr,
#[structopt(long, default_value = "127.0.0.1:8081")]
pub private_api_address: SocketAddr,
#[structopt(long)]
pub clean: bool,
}
impl RunDev {
fn cleanup(&self) -> Result<(), Error> {
let database_dir = self.blockchain_path.join("db");
if database_dir.exists() {
fs::remove_dir_all(&self.blockchain_path)
.context("Expected DATABASE_PATH directory being removable")?;
}
Ok(())
}
}
impl ExonumCommand for RunDev {
fn execute(self) -> Result<StandardResult, Error> {
if self.clean {
self.cleanup()?;
}
let config_dir = self.blockchain_path.join("config");
let node_config_path = config_dir.join("node.toml");
let common_config_path = config_dir.join("template.toml");
let public_config_path = config_dir.join(PUBLIC_CONFIG_FILE_NAME);
let private_config_path = config_dir.join(PRIVATE_CONFIG_FILE_NAME);
let db_path = self.blockchain_path.join("db");
if !node_config_path.exists() {
let generate_template = GenerateTemplate {
common_config: common_config_path.clone(),
validators_count: 1,
supervisor_mode: SupervisorMode::Simple,
};
generate_template.execute()?;
let generate_config = GenerateConfig {
common_config: common_config_path,
output_dir: config_dir,
peer_address: "127.0.0.1:6200".parse().unwrap(),
listen_address: None,
no_password: true,
master_key_pass: None,
master_key_path: None,
};
generate_config.execute()?;
let finalize = Finalize {
private_config_path,
output_config_path: node_config_path.clone(),
public_configs: vec![public_config_path],
public_api_address: Some(self.public_api_address),
private_api_address: Some(self.private_api_address),
public_allow_origin: Some("*".to_owned()),
private_allow_origin: Some("*".to_owned()),
};
finalize.execute()?;
}
let run = Run {
node_config: node_config_path,
db_path,
public_api_address: None,
private_api_address: None,
master_key_pass: Some(FromStr::from_str("pass:").unwrap()),
};
run.execute()
}
}