Skip to content

Commit

Permalink
fix(config): fix the parse of edge_path ENV var (#482)
Browse files Browse the repository at this point in the history
Signed-off-by: Simon Paitrault <simon.paitrault@gmail.com>
Co-authored-by: Monir Hadji <hadji.szs@gmail.com>
  • Loading branch information
Freyskeyd and hadjiszs authored Mar 20, 2024
1 parent 8f10090 commit b2a1af0
Show file tree
Hide file tree
Showing 12 changed files with 231 additions and 20 deletions.
35 changes: 35 additions & 0 deletions crates/topos-config/src/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ use std::{
use tokio::{spawn, task::JoinHandle};
use tracing::{error, info};

use self::command::BINARY_NAME;

// TODO: Provides the default arguments here
// Serde `flatten` and `default` doesn't work together yet
// https://github.com/serde-rs/serde/issues/1626
Expand Down Expand Up @@ -44,6 +46,39 @@ impl Config for EdgeConfig {
}
}

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "kebab-case")]
pub struct EdgeBinConfig {
pub edge_path: PathBuf,
}

impl EdgeBinConfig {
pub fn binary_path(&self) -> PathBuf {
self.edge_path.join(BINARY_NAME)
}
}

impl Config for EdgeBinConfig {
type Output = EdgeBinConfig;

fn load_from_file(figment: Figment, home: &Path) -> Figment {
let home = home.join("config.toml");

let edge = Figment::new()
.merge(Toml::file(home).nested())
.select("edge");

figment.merge(edge)
}

fn load_context(figment: Figment) -> Result<Self::Output, figment::Error> {
figment.extract()
}

fn profile() -> String {
"edge".to_string()
}
}
pub mod command;

pub fn generate_edge_config(
Expand Down
5 changes: 4 additions & 1 deletion crates/topos-config/src/edge/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,10 @@ impl CommandConfig {
}

pub async fn spawn(self) -> Result<ExitStatus, std::io::Error> {
info!("Spawning Polygon Edge with args: {:?}", self.binary_path);
info!(
"Spawning Polygon Edge binary located at: {:?}, args: {:?}",
self.binary_path, self.args
);
let mut command = Command::new(self.binary_path);
command.kill_on_drop(true);
command.args(self.args);
Expand Down
2 changes: 1 addition & 1 deletion crates/topos-config/src/genesis/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,6 @@ impl TryFrom<&NodeConfig> for Genesis {
type Error = Error;

fn try_from(config: &NodeConfig) -> Result<Self, Self::Error> {
Genesis::new(&config.edge_path)
Genesis::new(&config.genesis_path)
}
}
4 changes: 2 additions & 2 deletions crates/topos-config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pub trait Config: Serialize {
/// It will load the configuration from the file and an optional existing struct (if any)
/// and then extract the configuration from the context in order to build the Config.
/// The Config is then returned or an error if the configuration is not valid.
fn load<S: Serialize>(home: &Path, config: Option<S>) -> Result<Self::Output, figment::Error> {
fn load<S: Serialize>(home: &Path, config: Option<&S>) -> Result<Self::Output, figment::Error> {
let mut figment = Figment::new();

figment = Self::load_from_file(figment, home);
Expand All @@ -61,7 +61,7 @@ pub trait Config: Serialize {

pub(crate) fn load_config<T: Config, S: Serialize>(
node_path: &Path,
config: Option<S>,
config: Option<&S>,
) -> T::Output {
match T::load(node_path, config) {
Ok(config) => config,
Expand Down
28 changes: 21 additions & 7 deletions crates/topos-config/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ use topos_wallet::SecretManager;
use tracing::{debug, error};

use crate::{
base::BaseConfig, edge::EdgeConfig, load_config, sequencer::SequencerConfig, tce::TceConfig,
base::BaseConfig,
edge::{EdgeBinConfig, EdgeConfig},
load_config,
sequencer::SequencerConfig,
tce::TceConfig,
Config,
};

Expand All @@ -36,7 +40,10 @@ pub struct NodeConfig {
pub node_path: PathBuf,

#[serde(skip)]
pub edge_path: PathBuf,
pub genesis_path: PathBuf,

#[serde(skip)]
pub edge_bin: Option<EdgeBinConfig>,
}

impl NodeConfig {
Expand All @@ -47,7 +54,7 @@ impl NodeConfig {
pub fn try_from<S: Serialize>(
home_path: &Path,
node_name: &str,
config: Option<S>,
config: Option<&S>,
) -> Result<Self, std::io::Error> {
let node_path = home_path.join("node").join(node_name);
let config_path = node_path.join("config.toml");
Expand All @@ -68,26 +75,30 @@ impl NodeConfig {
///
/// It doesn't check the existence of the config file.
/// It's useful for creating a config file for a new node, relying on the default values.
pub fn create<S: Serialize>(home_path: &Path, node_name: &str, config: Option<S>) -> Self {
pub fn create<S: Serialize>(home_path: &Path, node_name: &str, config: Option<&S>) -> Self {
let node_path = home_path.join("node").join(node_name);

Self::build_config(node_path, home_path, config)
}

/// Common function to build a node config struct from the given home path and node name.
fn build_config<S: Serialize>(node_path: PathBuf, home_path: &Path, config: Option<S>) -> Self {
fn build_config<S: Serialize>(
node_path: PathBuf,
home_path: &Path,
config: Option<&S>,
) -> Self {
let node_folder = node_path.as_path();
let base = load_config::<BaseConfig, _>(node_folder, config);

// Load genesis pointed by the local config
let edge_path = home_path
let genesis_path = home_path
.join("subnet")
.join(base.subnet.clone())
.join("genesis.json");

let mut config = NodeConfig {
node_path: node_path.to_path_buf(),
edge_path,
genesis_path,
home_path: home_path.to_path_buf(),
base: base.clone(),
sequencer: base
Expand All @@ -96,6 +107,9 @@ impl NodeConfig {
tce: base
.need_tce()
.then(|| load_config::<TceConfig, ()>(node_folder, None)),
edge_bin: base
.need_edge()
.then(|| load_config::<EdgeBinConfig, _>(node_folder, config)),
edge: base
.need_edge()
.then(|| load_config::<EdgeConfig, ()>(node_folder, None)),
Expand Down
10 changes: 5 additions & 5 deletions crates/topos-node/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use tokio::{
};
use tokio_util::sync::CancellationToken;
use topos_config::{
edge::command::BINARY_NAME,
genesis::Genesis,
node::{NodeConfig, NodeRole},
};
Expand Down Expand Up @@ -76,7 +75,7 @@ pub async fn start(
info!(
"Could not load genesis.json file on path {} \n Please make sure to have a valid \
genesis.json file for your subnet in the {}/subnet/{} folder.",
config.edge_path.display(),
config.genesis_path.display(),
config.home_path.display(),
&config.base.subnet
);
Expand Down Expand Up @@ -159,21 +158,22 @@ fn spawn_processes(
info!("Using external edge node, skip running of local edge instance...")
} else {
let edge_config = config.edge.take().ok_or(Error::MissingEdgeConfig)?;
let edge_bin_config = config.edge_bin.take().ok_or(Error::MissingEdgeConfig)?;

let data_dir = config.node_path.clone();

info!(
"Spawning edge process with genesis file: {}, data directory: {}, additional edge \
arguments: {:?}",
config.edge_path.display(),
config.genesis_path.display(),
data_dir.display(),
edge_config.args
);

processes.push(process::spawn_edge_process(
config.home_path.join(BINARY_NAME),
edge_bin_config.binary_path(),
data_dir,
config.edge_path.clone(),
config.genesis_path.clone(),
edge_config.args,
));
}
Expand Down
7 changes: 6 additions & 1 deletion crates/topos/src/components/node/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,12 @@ pub(crate) struct NodeCommand {
pub(crate) home: PathBuf,

/// Installation directory path for Polygon Edge binary
#[arg(long, env = "TOPOS_POLYGON_EDGE_BIN_PATH", default_value = ".")]
#[arg(
global = true,
long,
env = "TOPOS_POLYGON_EDGE_BIN_PATH",
default_value = "."
)]
pub(crate) edge_path: PathBuf,

#[clap(subcommand)]
Expand Down
6 changes: 6 additions & 0 deletions crates/topos/src/components/node/commands/init.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::path::PathBuf;

use clap::Args;
use serde::Serialize;
use topos_config::node::NodeRole;
Expand Down Expand Up @@ -27,4 +29,8 @@ pub struct Init {
/// rely on polygon-edge during runtime. Example: A sequencer which runs for an external EVM chain
#[arg(long, env = "TOPOS_NO_EDGE_PROCESS", action)]
pub no_edge_process: bool,

/// Installation directory path for Polygon Edge binary
#[clap(from_global)]
pub(crate) edge_path: PathBuf,
}
6 changes: 6 additions & 0 deletions crates/topos/src/components/node/commands/up.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::path::PathBuf;

use clap::Args;
use serde::Serialize;

Expand Down Expand Up @@ -26,4 +28,8 @@ pub struct Up {
/// If not provided open telemetry will not be used
#[arg(long, env = "TOPOS_OTLP_SERVICE_NAME")]
pub otlp_service_name: Option<String>,

/// Installation directory path for Polygon Edge binary
#[clap(from_global)]
pub(crate) edge_path: PathBuf,
}
4 changes: 2 additions & 2 deletions crates/topos/src/components/node/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ pub(crate) async fn handle_command(
}
}

let node_config = NodeConfig::create(&home, &name, Some(cmd));
let node_config = NodeConfig::create(&home, &name, Some(&cmd));

// Creating the TOML output
let config_toml = match node_config.to_toml() {
Expand Down Expand Up @@ -135,7 +135,7 @@ pub(crate) async fn handle_command(
.as_ref()
.expect("No name or default was given for node");

let config = NodeConfig::try_from(&home, name, Some(command))?;
let config = NodeConfig::try_from(&home, name, Some(&command))?;

topos_node::start(
verbose,
Expand Down
76 changes: 76 additions & 0 deletions crates/topos/tests/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,80 @@ mod serial_integration {

Ok(())
}

#[test_log::test(tokio::test)]
async fn command_node_up_custom_polygon() -> Result<(), Box<dyn std::error::Error>> {
let tmp_home_dir = tempdir()?;

// Create config file
let node_up_home_env = tmp_home_dir.path().to_str().unwrap();
let custom_path = tmp_home_dir.path().join("custom_path");
let node_edge_path_env = utils::setup_polygon_edge(custom_path.to_str().unwrap()).await;
let node_up_name_env = "TEST_NODE_UP";
let node_up_role_env = "full-node";
let node_up_subnet_env = "topos-up-env-subnet";

let mut cmd = Command::cargo_bin("topos")?;
cmd.arg("node")
.env("TOPOS_POLYGON_EDGE_BIN_PATH", &node_edge_path_env)
.env("TOPOS_HOME", node_up_home_env)
.env("TOPOS_NODE_NAME", node_up_name_env)
.env("TOPOS_NODE_ROLE", node_up_role_env)
.env("TOPOS_NODE_SUBNET", node_up_subnet_env)
.arg("init");

let output = cmd.assert().success();
let result: &str = std::str::from_utf8(&output.get_output().stdout)?;
assert!(result.contains("Created node config file"));

// Run node init with cli flags
let home = PathBuf::from(node_up_home_env);
// Verification: check that the config file was created
let config_path = home.join("node").join(node_up_name_env).join("config.toml");
assert!(config_path.exists());

// Generate polygon edge genesis file
let polygon_edge_bin = format!("{}/polygon-edge", node_edge_path_env);
generate_polygon_edge_genesis_file(
&polygon_edge_bin,
node_up_home_env,
node_up_name_env,
node_up_subnet_env,
)
.await?;
let polygon_edge_genesis_path = home
.join("subnet")
.join(node_up_subnet_env)
.join("genesis.json");
assert!(polygon_edge_genesis_path.exists());

let mut cmd = Command::cargo_bin("topos")?;
cmd.arg("node")
.env("TOPOS_POLYGON_EDGE_BIN_PATH", &node_edge_path_env)
.env("TOPOS_HOME", node_up_home_env)
.env("TOPOS_NODE_NAME", node_up_name_env)
.arg("up");

let mut cmd = tokio::process::Command::from(cmd).spawn().unwrap();
let pid = cmd.id().unwrap();
let _ = tokio::time::sleep(std::time::Duration::from_secs(10)).await;

let s = System::new_all();
if let Some(process) = s.process(Pid::from_u32(pid)) {
if process.kill_with(Signal::Term).is_none() {
eprintln!("This signal isn't supported on this platform");
}
}

if let Ok(code) = cmd.wait().await {
assert!(code.success());
} else {
panic!("Failed to shutdown gracefully");
}

// Cleanup
std::fs::remove_dir_all(node_up_home_env)?;

Ok(())
}
}
Loading

0 comments on commit b2a1af0

Please sign in to comment.