2026-02-19 11:53:46 +01:00
|
|
|
use std::{
|
|
|
|
|
collections::HashMap,
|
|
|
|
|
path::{Path, PathBuf},
|
|
|
|
|
sync::Arc,
|
|
|
|
|
};
|
2026-02-02 07:19:22 +01:00
|
|
|
|
|
|
|
|
use async_trait::async_trait;
|
|
|
|
|
pub use lb_framework::*;
|
2026-02-19 11:53:46 +01:00
|
|
|
use reqwest::Url;
|
|
|
|
|
pub use scenario::{
|
|
|
|
|
CoreBuilderExt, ObservabilityBuilderExt, ScenarioBuilder, ScenarioBuilderExt,
|
|
|
|
|
ScenarioBuilderWith,
|
|
|
|
|
};
|
|
|
|
|
use testing_framework_core::scenario::{
|
2026-02-22 03:52:27 +01:00
|
|
|
Application, DynError, ExternalNodeSource, FeedRuntime, NodeClients, RunContext,
|
|
|
|
|
StartNodeOptions,
|
2026-02-19 11:53:46 +01:00
|
|
|
};
|
|
|
|
|
use testing_framework_runner_local::{
|
|
|
|
|
BuiltNodeConfig, LocalDeployerEnv, NodeConfigEntry,
|
|
|
|
|
process::{LaunchSpec, NodeEndpoints, ProcessSpawnError},
|
|
|
|
|
};
|
2026-02-02 07:19:22 +01:00
|
|
|
use tokio::sync::broadcast;
|
2026-02-19 11:53:46 +01:00
|
|
|
use workloads::{LbcBlockFeedEnv, LbcScenarioEnv};
|
2026-02-02 07:19:22 +01:00
|
|
|
|
|
|
|
|
pub mod cfgsync;
|
|
|
|
|
mod compose_env;
|
|
|
|
|
pub mod constants;
|
|
|
|
|
mod k8s_env;
|
|
|
|
|
pub mod scenario;
|
|
|
|
|
|
2026-02-19 11:53:46 +01:00
|
|
|
pub type LbcComposeDeployer = testing_framework_runner_compose::ComposeDeployer<LbcExtEnv>;
|
|
|
|
|
pub type LbcK8sDeployer = testing_framework_runner_k8s::K8sDeployer<LbcExtEnv>;
|
|
|
|
|
|
2026-02-02 07:19:22 +01:00
|
|
|
pub struct LbcExtEnv;
|
|
|
|
|
|
|
|
|
|
#[async_trait]
|
|
|
|
|
impl Application for LbcExtEnv {
|
2026-02-19 11:53:46 +01:00
|
|
|
type Deployment = <LbcEnv as Application>::Deployment;
|
|
|
|
|
|
|
|
|
|
type NodeClient = <LbcEnv as Application>::NodeClient;
|
|
|
|
|
|
|
|
|
|
type NodeConfig = <LbcEnv as Application>::NodeConfig;
|
|
|
|
|
|
|
|
|
|
type FeedRuntime = <LbcEnv as Application>::FeedRuntime;
|
|
|
|
|
|
|
|
|
|
fn external_node_client(source: &ExternalNodeSource) -> Result<Self::NodeClient, DynError> {
|
2026-03-08 13:38:10 +01:00
|
|
|
let base_url = Url::parse(source.endpoint())?;
|
2026-02-19 11:53:46 +01:00
|
|
|
Ok(NodeHttpClient::from_urls(base_url, None))
|
|
|
|
|
}
|
2026-02-02 07:19:22 +01:00
|
|
|
|
|
|
|
|
async fn prepare_feed(
|
2026-02-22 03:52:27 +01:00
|
|
|
node_clients: NodeClients<Self>,
|
2026-02-02 07:19:22 +01:00
|
|
|
) -> Result<(<Self::FeedRuntime as FeedRuntime>::Feed, Self::FeedRuntime), DynError> {
|
2026-02-22 03:52:27 +01:00
|
|
|
let clients = node_clients.snapshot();
|
|
|
|
|
let upstream_clients = NodeClients::<lb_framework::LbcEnv>::new(clients);
|
|
|
|
|
|
|
|
|
|
<LbcEnv as Application>::prepare_feed(upstream_clients).await
|
2026-02-02 07:19:22 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-19 11:53:46 +01:00
|
|
|
impl LbcScenarioEnv for LbcExtEnv {}
|
2026-02-02 07:19:22 +01:00
|
|
|
|
2026-02-19 11:53:46 +01:00
|
|
|
impl LbcBlockFeedEnv for LbcExtEnv {
|
|
|
|
|
fn block_feed_subscription(ctx: &RunContext<Self>) -> broadcast::Receiver<Arc<BlockRecord>> {
|
|
|
|
|
ctx.feed().subscribe()
|
|
|
|
|
}
|
2026-02-22 03:52:27 +01:00
|
|
|
|
|
|
|
|
fn block_feed(ctx: &RunContext<Self>) -> BlockFeed {
|
|
|
|
|
ctx.feed()
|
|
|
|
|
}
|
2026-02-19 11:53:46 +01:00
|
|
|
}
|
2026-02-02 07:19:22 +01:00
|
|
|
|
2026-02-19 11:53:46 +01:00
|
|
|
#[async_trait]
|
|
|
|
|
impl LocalDeployerEnv for LbcExtEnv {
|
|
|
|
|
fn build_node_config(
|
|
|
|
|
topology: &Self::Deployment,
|
|
|
|
|
index: usize,
|
|
|
|
|
peer_ports_by_name: &HashMap<String, u16>,
|
|
|
|
|
options: &StartNodeOptions<Self>,
|
|
|
|
|
peer_ports: &[u16],
|
|
|
|
|
) -> Result<BuiltNodeConfig<<Self as Application>::NodeConfig>, DynError> {
|
|
|
|
|
let mapped_options = map_start_options(options)?;
|
|
|
|
|
<LbcEnv as LocalDeployerEnv>::build_node_config(
|
|
|
|
|
topology,
|
|
|
|
|
index,
|
|
|
|
|
peer_ports_by_name,
|
|
|
|
|
&mapped_options,
|
|
|
|
|
peer_ports,
|
|
|
|
|
)
|
|
|
|
|
}
|
2026-02-02 07:19:22 +01:00
|
|
|
|
2026-02-19 11:53:46 +01:00
|
|
|
fn build_initial_node_configs(
|
|
|
|
|
topology: &Self::Deployment,
|
|
|
|
|
) -> Result<Vec<NodeConfigEntry<<Self as Application>::NodeConfig>>, ProcessSpawnError> {
|
|
|
|
|
<LbcEnv as LocalDeployerEnv>::build_initial_node_configs(topology)
|
2026-02-02 07:19:22 +01:00
|
|
|
}
|
2026-02-19 11:53:46 +01:00
|
|
|
|
|
|
|
|
fn initial_persist_dir(
|
|
|
|
|
topology: &Self::Deployment,
|
|
|
|
|
node_name: &str,
|
|
|
|
|
index: usize,
|
|
|
|
|
) -> Option<PathBuf> {
|
|
|
|
|
<LbcEnv as LocalDeployerEnv>::initial_persist_dir(topology, node_name, index)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn build_launch_spec(
|
|
|
|
|
config: &<Self as Application>::NodeConfig,
|
|
|
|
|
dir: &Path,
|
|
|
|
|
label: &str,
|
|
|
|
|
) -> Result<LaunchSpec, DynError> {
|
|
|
|
|
<LbcEnv as LocalDeployerEnv>::build_launch_spec(config, dir, label)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn node_endpoints(config: &<Self as Application>::NodeConfig) -> NodeEndpoints {
|
|
|
|
|
<LbcEnv as LocalDeployerEnv>::node_endpoints(config)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn node_client(endpoints: &NodeEndpoints) -> Self::NodeClient {
|
|
|
|
|
<LbcEnv as LocalDeployerEnv>::node_client(endpoints)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn readiness_endpoint_path() -> &'static str {
|
|
|
|
|
<LbcEnv as LocalDeployerEnv>::readiness_endpoint_path()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn map_start_options(
|
|
|
|
|
options: &StartNodeOptions<LbcExtEnv>,
|
|
|
|
|
) -> Result<StartNodeOptions<LbcEnv>, DynError> {
|
|
|
|
|
if options.config_patch.is_some() {
|
|
|
|
|
return Err("LbcExtEnv local deployer bridge does not support config_patch yet".into());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let mut mapped = StartNodeOptions::<LbcEnv>::default();
|
|
|
|
|
mapped.peers = options.peers.clone();
|
|
|
|
|
mapped.config_override = options.config_override.clone();
|
|
|
|
|
mapped.persist_dir = options.persist_dir.clone();
|
|
|
|
|
|
|
|
|
|
Ok(mapped)
|
2026-02-02 07:19:22 +01:00
|
|
|
}
|