From e6d692f4d645dd84552ecfaea833774327a8d5af Mon Sep 17 00:00:00 2001 From: andrussal Date: Thu, 2 Apr 2026 08:18:52 +0200 Subject: [PATCH] feat(local): add restart_node_with_args --- .../core/src/scenario/control.rs | 8 +++++ .../deployers/local/src/env/helpers.rs | 14 ++++++++ .../deployers/local/src/env/mod.rs | 8 +++-- .../deployers/local/src/manual/mod.rs | 15 ++++++++ .../deployers/local/src/node_control/mod.rs | 34 ++++++++++++++++--- .../deployers/local/src/process.rs | 14 ++++++++ 6 files changed, 87 insertions(+), 6 deletions(-) diff --git a/testing-framework/core/src/scenario/control.rs b/testing-framework/core/src/scenario/control.rs index 4f59621..7cc95c9 100644 --- a/testing-framework/core/src/scenario/control.rs +++ b/testing-framework/core/src/scenario/control.rs @@ -9,6 +9,14 @@ pub trait NodeControlHandle: Send + Sync { Err("restart_node not supported by this deployer".into()) } + async fn restart_node_with_args( + &self, + _name: &str, + _args: Vec, + ) -> Result<(), DynError> { + Err("restart_node_with_args not supported by this deployer".into()) + } + async fn start_node(&self, _name: &str) -> Result, DynError> { Err("start_node not supported by this deployer".into()) } diff --git a/testing-framework/deployers/local/src/env/helpers.rs b/testing-framework/deployers/local/src/env/helpers.rs index e2d54fe..7d1d3d5 100644 --- a/testing-framework/deployers/local/src/env/helpers.rs +++ b/testing-framework/deployers/local/src/env/helpers.rs @@ -343,6 +343,20 @@ pub fn yaml_config_launch_spec( rendered_config_launch_spec(config_yaml.into_bytes(), spec) } +pub fn build_launch_spec_with_args( + config: &::NodeConfig, + dir: &std::path::Path, + label: &str, + extra_args: &[String], +) -> Result +where + E: crate::env::LocalDeployerEnv, +{ + let mut launch = E::build_launch_spec(config, dir, label)?; + launch.args.extend(extra_args.iter().cloned()); + Ok(launch) +} + /// Uses an already rendered text config to build a launch spec for `spec`. pub fn text_config_launch_spec( rendered_config: impl Into>, diff --git a/testing-framework/deployers/local/src/env/mod.rs b/testing-framework/deployers/local/src/env/mod.rs index 17ee9ea..7450f16 100644 --- a/testing-framework/deployers/local/src/env/mod.rs +++ b/testing-framework/deployers/local/src/env/mod.rs @@ -21,7 +21,8 @@ mod tests; pub use helpers::{ BuiltNodeConfig, LocalNodePorts, LocalPeerNode, LocalProcessSpec, NodeConfigEntry, - build_indexed_http_peers, build_indexed_node_configs, build_local_cluster_node_config, + build_indexed_http_peers, build_indexed_node_configs, build_launch_spec_with_args, + build_local_cluster_node_config, build_local_peer_nodes, default_yaml_launch_spec, discovered_node_access, preallocate_ports, reserve_local_node_ports, single_http_node_endpoints, text_config_launch_spec, text_node_config, yaml_config_launch_spec, yaml_node_config, @@ -506,11 +507,14 @@ pub async fn spawn_node_from_config( keep_tempdir: bool, persist_dir: Option<&std::path::Path>, snapshot_dir: Option<&std::path::Path>, + extra_args: &[String], ) -> Result, ProcessSpawnError> { + let extra_args = extra_args.to_vec(); + ProcessNode::spawn( &label, config, - E::build_launch_spec, + move |config, dir, label| build_launch_spec_with_args::(config, dir, label, &extra_args), E::node_endpoints, keep_tempdir, persist_dir, diff --git a/testing-framework/deployers/local/src/manual/mod.rs b/testing-framework/deployers/local/src/manual/mod.rs index 028a690..489e150 100644 --- a/testing-framework/deployers/local/src/manual/mod.rs +++ b/testing-framework/deployers/local/src/manual/mod.rs @@ -70,6 +70,14 @@ impl ManualCluster { Ok(self.nodes.restart_node(name).await?) } + pub async fn restart_node_with_args( + &self, + name: &str, + args: Vec, + ) -> Result<(), ManualClusterError> { + Ok(self.nodes.restart_node_with_args(name, args).await?) + } + pub async fn stop_node(&self, name: &str) -> Result<(), ManualClusterError> { Ok(self.nodes.stop_node(name).await?) } @@ -125,6 +133,13 @@ impl NodeControlHandle for ManualCluster { .map_err(|err| err.into()) } + async fn restart_node_with_args(&self, name: &str, args: Vec) -> Result<(), DynError> { + self.nodes + .restart_node_with_args(name, args) + .await + .map_err(|err| err.into()) + } + async fn stop_node(&self, name: &str) -> Result<(), DynError> { self.nodes.stop_node(name).await.map_err(|err| err.into()) } diff --git a/testing-framework/deployers/local/src/node_control/mod.rs b/testing-framework/deployers/local/src/node_control/mod.rs index 149a0dc..d3351dc 100644 --- a/testing-framework/deployers/local/src/node_control/mod.rs +++ b/testing-framework/deployers/local/src/node_control/mod.rs @@ -11,9 +11,9 @@ use thiserror::Error; use crate::{ env::{ - LocalDeployerEnv, Node, build_initial_node_configs, build_node_from_template, - initial_persist_dir, initial_snapshot_dir, node_peer_port, readiness_endpoint_path, - spawn_node_from_config, + LocalDeployerEnv, Node, build_initial_node_configs, build_launch_spec_with_args, + build_node_from_template, initial_persist_dir, initial_snapshot_dir, node_peer_port, + readiness_endpoint_path, spawn_node_from_config, }, process::ProcessSpawnError, }; @@ -96,6 +96,7 @@ impl NodeManager { keep_tempdir, persist_dir.as_deref(), snapshot_dir.as_deref(), + &[], ) .await?, ); @@ -264,6 +265,7 @@ impl NodeManager { built.config, options.persist_dir.as_deref(), options.snapshot_dir.as_deref(), + &[], ) .await?; @@ -274,9 +276,25 @@ impl NodeManager { } pub async fn restart_node(&self, name: &str) -> Result<(), NodeManagerError> { + self.restart_node_with_args(name, Vec::new()).await + } + + pub async fn restart_node_with_args( + &self, + name: &str, + args: Vec, + ) -> Result<(), NodeManagerError> { let (index, mut node) = self.take_node(name)?; - if let Err(source) = node.restart().await { + let launch = build_launch_spec_with_args::( + node.config(), + node.working_dir(), + name, + &args, + ) + .map_err(|source| NodeManagerError::Config { source })?; + + if let Err(source) = node.restart_with_launch(launch).await { self.put_node_back(index, node); return Err(NodeManagerError::Restart { @@ -305,6 +323,7 @@ impl NodeManager { config: ::NodeConfig, persist_dir: Option<&std::path::Path>, snapshot_dir: Option<&std::path::Path>, + extra_args: &[String], ) -> Result { let node = spawn_node_from_config::( node_name.to_string(), @@ -312,6 +331,7 @@ impl NodeManager { self.keep_tempdir, persist_dir, snapshot_dir, + extra_args, ) .await .map_err(|source| NodeManagerError::Spawn { @@ -444,6 +464,12 @@ impl NodeControlHandle for NodeManager { self.restart_node(name).await.map_err(|err| err.into()) } + async fn restart_node_with_args(&self, name: &str, args: Vec) -> Result<(), DynError> { + self.restart_node_with_args(name, args) + .await + .map_err(|err| err.into()) + } + async fn stop_node(&self, name: &str) -> Result<(), DynError> { self.stop_node(name).await.map_err(|err| err.into()) } diff --git a/testing-framework/deployers/local/src/process.rs b/testing-framework/deployers/local/src/process.rs index ced4959..53b8766 100644 --- a/testing-framework/deployers/local/src/process.rs +++ b/testing-framework/deployers/local/src/process.rs @@ -168,6 +168,10 @@ impl &Path { + self.tempdir.path() + } + pub fn pid(&self) -> u32 { self.child.id().unwrap_or_default() } @@ -255,6 +259,16 @@ impl Result<(), ProcessSpawnError> { + self.stop_child().await?; + self.launch = launch; + self.child = self.spawn_child().await?; + Ok(()) + } + pub async fn stop(&mut self) { let _ = self.stop_child().await; }