diff --git a/crates/configuration/src/relaychain.rs b/crates/configuration/src/relaychain.rs index 9d33d5fac40c7cb658b9891b255cf21cf344583f..66edf9d362fb75da78682df9a52877c5a542c094 100644 --- a/crates/configuration/src/relaychain.rs +++ b/crates/configuration/src/relaychain.rs @@ -33,7 +33,7 @@ pub struct RelaychainConfig { max_nominations: Option<u8>, #[serde(skip_serializing_if = "std::vec::Vec::is_empty", default)] nodes: Vec<NodeConfig>, - genesis_overrides: Option<serde_json::Value>, + runtime_genesis_patch: Option<serde_json::Value>, command: Option<Command>, } @@ -89,8 +89,8 @@ impl RelaychainConfig { } /// The genesis overrides as a JSON value. - pub fn genesis_overrides(&self) -> Option<&serde_json::Value> { - self.genesis_overrides.as_ref() + pub fn runtime_genesis_patch(&self) -> Option<&serde_json::Value> { + self.runtime_genesis_patch.as_ref() } /// The nodes of the relay chain. @@ -133,7 +133,7 @@ impl Default for RelaychainConfigBuilder<Initial> { command: None, random_nominators_count: None, max_nominations: None, - genesis_overrides: None, + runtime_genesis_patch: None, nodes: vec![], }, validation_context: Default::default(), @@ -338,7 +338,7 @@ impl RelaychainConfigBuilder<WithChain> { pub fn with_genesis_overrides(self, genesis_overrides: impl Into<serde_json::Value>) -> Self { Self::transition( RelaychainConfig { - genesis_overrides: Some(genesis_overrides.into()), + runtime_genesis_patch: Some(genesis_overrides.into()), ..self.config }, self.validation_context, diff --git a/crates/configuration/src/shared/node.rs b/crates/configuration/src/shared/node.rs index e8b0ff3507851016160569209aaa28327dde6f6f..32851db8c17ebb796dd61059e48961f869edd582 100644 --- a/crates/configuration/src/shared/node.rs +++ b/crates/configuration/src/shared/node.rs @@ -65,6 +65,7 @@ pub struct NodeConfig { name: String, pub(crate) image: Option<Image>, pub(crate) command: Option<Command>, + pub(crate) subcommand: Option<Command>, #[serde(default)] args: Vec<Arg>, #[serde(alias = "validator", default = "default_as_true")] @@ -112,6 +113,12 @@ impl Serialize for NodeConfig { state.serialize_field("command", &self.command)?; } + if self.subcommand.is_none() { + state.skip_field("subcommand")?; + } else { + state.serialize_field("subcommand", &self.subcommand)?; + } + if self.args.is_empty() || self.args == self.chain_context.default_args { state.skip_field("args")?; } else { @@ -174,6 +181,11 @@ impl NodeConfig { self.command.as_ref() } + /// Subcommand to run the node. + pub fn subcommand(&self) -> Option<&Command> { + self.subcommand.as_ref() + } + /// Arguments to use for node. pub fn args(&self) -> Vec<&Arg> { self.args.iter().collect() @@ -265,6 +277,7 @@ impl Default for NodeConfigBuilder<Initial> { name: "".into(), image: None, command: None, + subcommand: None, args: vec![], is_validator: true, is_invulnerable: true, @@ -371,6 +384,29 @@ impl NodeConfigBuilder<Buildable> { } } + /// Set the subcommand that will be executed to launch the node. + pub fn with_subcommand<T>(self, subcommand: T) -> Self + where + T: TryInto<Command>, + T::Error: Error + Send + Sync + 'static, + { + match subcommand.try_into() { + Ok(subcommand) => Self::transition( + NodeConfig { + subcommand: Some(subcommand), + ..self.config + }, + self.validation_context, + self.errors, + ), + Err(error) => Self::transition( + self.config, + self.validation_context, + merge_errors(self.errors, FieldError::Command(error.into()).into()), + ), + } + } + /// Set the image that will be used for the node (only podman/k8s). Override the default. pub fn with_image<T>(self, image: T) -> Self where diff --git a/crates/examples/examples/0001-simple.toml b/crates/examples/examples/0001-simple.toml index 3a0bc70840f658e87a2f2b7dd2d4de71ba0cf6c3..04e6590dbc8bc7abafb645402b4ea9e72bd4b51b 100644 --- a/crates/examples/examples/0001-simple.toml +++ b/crates/examples/examples/0001-simple.toml @@ -1,6 +1,11 @@ [settings] timeout = 1000 +[relaychain.runtime_genesis_patch.configuration.config] +max_validators_per_core = 1 +needed_approvals = 2 +group_rotation_frequency = 10 + [relaychain] default_image = "{{ZOMBIENET_INTEGRATION_TEST_IMAGE}}" chain = "rococo-local" @@ -18,7 +23,7 @@ command = "polkadot" id = 100 addToGenesis = false - [parachains.collator] + [[parachains.collators]] name = "collator01" image = "{{COL_IMAGE}}" command = "adder-collator" @@ -27,4 +32,4 @@ addToGenesis = false [types.Header] number = "u64" parent_hash = "Hash" -post_state = "Hash" \ No newline at end of file +post_state = "Hash" diff --git a/crates/examples/examples/simple_network_example.rs b/crates/examples/examples/simple_network_example.rs index 0e6cf9306b70340966eb082d1946e06d8c99dde8..d600209abc33e399ed59b0c50a5a37cf8dd2603c 100644 --- a/crates/examples/examples/simple_network_example.rs +++ b/crates/examples/examples/simple_network_example.rs @@ -12,7 +12,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { println!("🚀🚀🚀🚀 network deployed"); let client = network - .get_node("alice")? + .get_node("collator01")? .client::<subxt::PolkadotConfig>() .await?; let mut blocks = client.blocks().subscribe_finalized().await?.take(3); diff --git a/crates/orchestrator/src/generators/chain_spec.rs b/crates/orchestrator/src/generators/chain_spec.rs index 0d3f9df1c8536244819d34bae0af684f104700f5..c26047b07f43f253e0d0a5f83980fc037d7a55e9 100644 --- a/crates/orchestrator/src/generators/chain_spec.rs +++ b/crates/orchestrator/src/generators/chain_spec.rs @@ -306,7 +306,7 @@ impl ChainSpec { if let Some(overrides) = ¶.genesis_overrides { if let Some(genesis) = chain_spec_json.pointer_mut(&format!("{}/genesis", pointer)) { - override_genesis(genesis, overrides); + merge(genesis, overrides); } } @@ -389,10 +389,9 @@ impl ChainSpec { .map_err(GeneratorError::ChainSpecGeneration)?; // make genesis overrides first. - if let Some(overrides) = &relaychain.genesis_overrides { - if let Some(genesis) = chain_spec_json.pointer_mut(&format!("{}/genesis", pointer)) - { - override_genesis(genesis, overrides); + if let Some(overrides) = &relaychain.runtime_genesis_patch { + if let Some(patch_section) = chain_spec_json.pointer_mut(&pointer) { + merge(patch_section, overrides); } } @@ -604,10 +603,10 @@ fn get_runtime_config_pointer(chain_spec_json: &serde_json::Value) -> Result<Str Err("Can not find the runtime pointer".into()) } -// Override `genesis` key if present -fn override_genesis(genesis: &mut serde_json::Value, overrides: &serde_json::Value) { +// Merge `patch_section` with `overrides`. +fn merge(patch_section: &mut serde_json::Value, overrides: &serde_json::Value) { if let (Some(genesis_obj), Some(overrides_obj)) = - (genesis.as_object_mut(), overrides.as_object()) + (patch_section.as_object_mut(), overrides.as_object()) { for overrides_key in overrides_obj.keys() { // we only want to override keys present in the genesis object @@ -617,7 +616,7 @@ fn override_genesis(genesis: &mut serde_json::Value, overrides: &serde_json::Val (serde_json::Value::Object(_), Some(overrides_value)) if overrides_value.is_object() => { - override_genesis(genesis_value, overrides_value); + merge(genesis_value, overrides_value); }, // override if genesis value not an object (_, Some(overrides_value)) => { diff --git a/crates/orchestrator/src/generators/command.rs b/crates/orchestrator/src/generators/command.rs index 8848ee1d1c2f54be3880ffddf9285e994547c7ea..ad757002a36bbeaaf3bf2d4c35e791967ad339e8 100644 --- a/crates/orchestrator/src/generators/command.rs +++ b/crates/orchestrator/src/generators/command.rs @@ -329,6 +329,10 @@ pub fn generate_for_node( final_args.append(&mut tmp_args); + if let Some(ref subcommand) = node.subcommand { + final_args.insert(1, subcommand.as_str().to_string()); + } + if options.use_wrapper { ("/cfg/zombie-wrapper.sh".to_string(), final_args) } else { diff --git a/crates/orchestrator/src/network_spec/node.rs b/crates/orchestrator/src/network_spec/node.rs index 731abd69c4dcf4dce1a2b6052c9cee2c745d17fa..0e3cba823b750089384fa094807cc85afaf9fc28 100644 --- a/crates/orchestrator/src/network_spec/node.rs +++ b/crates/orchestrator/src/network_spec/node.rs @@ -26,6 +26,7 @@ macro_rules! impl_from_for_add_node_opts { Self { image: value.image, command: value.command, + subcommand: value.subcommand, args: value.args, env: value.env, is_validator: value.is_validator, @@ -62,6 +63,9 @@ pub struct NodeSpec { /// Command to run the node. Override the default. pub(crate) command: Command, + /// Optional subcommand for the node. + pub(crate) subcommand: Option<Command>, + /// Arguments to use for node. Appended to default. pub(crate) args: Vec<Arg>, @@ -125,6 +129,8 @@ impl NodeSpec { )); }; + let subcommand = node_config.subcommand().cloned(); + // If `args` is set at `node` level use them // otherwise use the default_args (can be empty). let args: Vec<Arg> = if node_config.args().is_empty() { @@ -150,6 +156,7 @@ impl NodeSpec { peer_id, image, command, + subcommand, args, is_validator: node_config.is_validator(), is_invulnerable: node_config.is_invulnerable(), @@ -197,6 +204,8 @@ impl NodeSpec { )); }; + let subcommand = options.subcommand.clone(); + // If `args` is set at `node` level use them // otherwise use the default_args (can be empty). let args: Vec<Arg> = if options.args.is_empty() { @@ -226,6 +235,7 @@ impl NodeSpec { peer_id, image, command, + subcommand, args, is_validator: options.is_validator, is_invulnerable: false, diff --git a/crates/orchestrator/src/network_spec/relaychain.rs b/crates/orchestrator/src/network_spec/relaychain.rs index a7adee2ab4badb87b6e71f7d75478801f9c50295..4b2b92ec347c296ebe6ad8854598912b4ca00026 100644 --- a/crates/orchestrator/src/network_spec/relaychain.rs +++ b/crates/orchestrator/src/network_spec/relaychain.rs @@ -44,7 +44,7 @@ pub struct RelaychainSpec { pub(crate) max_nominations: u8, /// Genesis overrides as JSON value. - pub(crate) genesis_overrides: Option<serde_json::Value>, + pub(crate) runtime_genesis_patch: Option<serde_json::Value>, /// Nodes to run. pub(crate) nodes: Vec<NodeSpec>, @@ -110,7 +110,7 @@ impl RelaychainSpec { chain_spec, random_nominators_count: config.random_nominators_count().unwrap_or(0), max_nominations: config.max_nominations().unwrap_or(24), - genesis_overrides: config.genesis_overrides().cloned(), + runtime_genesis_patch: config.runtime_genesis_patch().cloned(), nodes, }) } diff --git a/crates/orchestrator/src/shared/macros.rs b/crates/orchestrator/src/shared/macros.rs index f79b3a1aa6ecb225605ee147725c69fd6836ad30..caeff77699759b4769c30fa79cac33f3d58bc2c6 100644 --- a/crates/orchestrator/src/shared/macros.rs +++ b/crates/orchestrator/src/shared/macros.rs @@ -6,6 +6,8 @@ macro_rules! create_add_options { pub image: Option<Image>, /// Command to run the node pub command: Option<Command>, + /// Subcommand for the node + pub subcommand: Option<Command>, /// Arguments to pass to the node pub args: Vec<Arg>, /// Env vars to set diff --git a/crates/sdk/src/lib.rs b/crates/sdk/src/lib.rs index 828a00ed761c6eea61b6ac467a9b8a8940dd78cd..c2d02638dd54fde781df9f1dd2830c9fb753f3f5 100644 --- a/crates/sdk/src/lib.rs +++ b/crates/sdk/src/lib.rs @@ -1,11 +1,13 @@ use async_trait::async_trait; pub use configuration::{NetworkConfig, NetworkConfigBuilder, RegistrationStrategy}; pub use orchestrator::{ - errors::OrchestratorError, network::Network, AddCollatorOptions, AddNodeOptions, Orchestrator, - PjsResult, + errors::OrchestratorError, + network::{node::NetworkNode, Network}, + AddCollatorOptions, AddNodeOptions, Orchestrator, PjsResult, }; use provider::NativeProvider; -use support::{fs::local::LocalFileSystem, process::os::OsProcessManager}; +pub use support::fs::local::LocalFileSystem; +use support::process::os::OsProcessManager; #[async_trait] pub trait NetworkConfigExt {