From fd547aa119052c8f17e46e962ae8220c2ae9cf1e Mon Sep 17 00:00:00 2001 From: andrussal Date: Sat, 7 Mar 2026 08:04:15 +0100 Subject: [PATCH] Align compose attach with shared metadata flow --- .../tests/compose_attach_node_control.rs | 48 ++++++++++++++++++- .../deployers/compose/src/deployer/mod.rs | 10 ++++ 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/logos/examples/tests/compose_attach_node_control.rs b/logos/examples/tests/compose_attach_node_control.rs index 386fd77..f265f01 100644 --- a/logos/examples/tests/compose_attach_node_control.rs +++ b/logos/examples/tests/compose_attach_node_control.rs @@ -2,10 +2,53 @@ use std::time::{Duration, Instant}; use anyhow::{Error, Result, anyhow}; use lb_ext::{CoreBuilderExt as _, LbcComposeDeployer, LbcExtEnv, ScenarioBuilder}; -use testing_framework_core::scenario::{AttachSource, Deployer as _, Runner}; +use testing_framework_core::scenario::{Deployer as _, Runner}; use testing_framework_runner_compose::{ComposeDeploymentMetadata, ComposeRunnerError}; use tokio::{process::Command, time::sleep}; +#[tokio::test] +#[ignore = "requires Docker and mutates compose runtime state"] +async fn compose_attach_mode_queries_node_api_opt_in() -> Result<()> { + let managed = ScenarioBuilder::deployment_with(|d| d.with_node_count(1)) + .with_run_duration(Duration::from_secs(5)) + .build()?; + + let deployer = LbcComposeDeployer::default(); + let (_managed_runner, metadata): (Runner, ComposeDeploymentMetadata) = + match deployer.deploy_with_metadata(&managed).await { + Ok(result) => result, + Err(ComposeRunnerError::DockerUnavailable) => return Ok(()), + Err(error) => return Err(Error::new(error)), + }; + + let attach_source = metadata.attach_source().map_err(|err| anyhow!("{err}"))?; + let attached = ScenarioBuilder::deployment_with(|d| d.with_node_count(1)) + .with_run_duration(Duration::from_secs(5)) + .with_attach_source(attach_source) + .build()?; + + let attached_runner: Runner = match deployer.deploy(&attached).await { + Ok(runner) => runner, + Err(ComposeRunnerError::DockerUnavailable) => return Ok(()), + Err(error) => return Err(Error::new(error)), + }; + + if attached_runner.context().node_clients().is_empty() { + return Err(anyhow!("compose attach resolved no node clients")); + } + + for node_client in attached_runner.context().node_clients().snapshot() { + node_client.consensus_info().await.map_err(|err| { + anyhow!( + "attached node api query failed at {}: {err}", + node_client.base_url() + ) + })?; + } + + Ok(()) +} + #[tokio::test] #[ignore = "requires Docker and mutates compose runtime state"] async fn compose_attach_mode_restart_node_opt_in() -> Result<()> { @@ -26,7 +69,8 @@ async fn compose_attach_mode_restart_node_opt_in() -> Result<()> { .project_name() .ok_or_else(|| anyhow!("compose deployment metadata has no project name"))? .to_owned(); - let attach_source = AttachSource::compose(vec![]).with_project(project_name.clone()); + + let attach_source = metadata.attach_source().map_err(|err| anyhow!("{err}"))?; let attached = ScenarioBuilder::deployment_with(|d| d.with_node_count(1)) .enable_node_control() diff --git a/testing-framework/deployers/compose/src/deployer/mod.rs b/testing-framework/deployers/compose/src/deployer/mod.rs index 8bd695d..60a88de 100644 --- a/testing-framework/deployers/compose/src/deployer/mod.rs +++ b/testing-framework/deployers/compose/src/deployer/mod.rs @@ -43,6 +43,16 @@ impl ComposeDeploymentMetadata { self.project_name.as_deref() } + /// Builds an attach source for the same compose project using deployer + /// discovery to resolve services. + pub fn attach_source(&self) -> Result { + let project_name = self + .project_name() + .ok_or(ComposeMetadataError::MissingProjectName)?; + + Ok(AttachSource::compose(Vec::new()).with_project(project_name.to_owned())) + } + /// Builds an attach source for the same compose project. pub fn attach_source_for_services( &self,