use std::{env, process, time::Duration}; use anyhow::{Context as _, Result}; use runner_examples::{ScenarioBuilderExt as _, demo, read_env_any}; use testing_framework_core::scenario::{ Deployer as _, ObservabilityCapability, Runner, ScenarioBuilder, }; use testing_framework_runner_k8s::{K8sDeployer, K8sRunnerError}; use testing_framework_workflows::ObservabilityBuilderExt as _; use tracing::{info, warn}; const MIXED_TXS_PER_BLOCK: u64 = 2; const TOTAL_WALLETS: usize = 200; const TRANSACTION_WALLETS: usize = 50; const DA_BLOB_RATE: u64 = 1; #[tokio::main] async fn main() { tracing_subscriber::fmt::init(); let validators = read_env_any(&["NOMOS_DEMO_VALIDATORS"], demo::DEFAULT_VALIDATORS); let executors = read_env_any(&["NOMOS_DEMO_EXECUTORS"], demo::DEFAULT_EXECUTORS); let run_secs = read_env_any(&["NOMOS_DEMO_RUN_SECS"], demo::DEFAULT_RUN_SECS); info!(validators, executors, run_secs, "starting k8s runner demo"); if let Err(err) = run_k8s_case(validators, executors, Duration::from_secs(run_secs)).await { warn!("k8s runner demo failed: {err:#}"); process::exit(1); } } async fn run_k8s_case(validators: usize, executors: usize, run_duration: Duration) -> Result<()> { info!( validators, executors, duration_secs = run_duration.as_secs(), "building scenario plan" ); let mut scenario = ScenarioBuilder::topology_with(|t| { t.network_star().validators(validators).executors(executors) }) .with_capabilities(ObservabilityCapability::default()) .wallets(TOTAL_WALLETS) .transactions_with(|txs| txs.rate(MIXED_TXS_PER_BLOCK).users(TRANSACTION_WALLETS)) .da_with(|da| da.blob_rate(DA_BLOB_RATE).headroom_percent(0)) .with_run_duration(run_duration) .expect_consensus_liveness(); if let Ok(url) = env::var("NOMOS_METRICS_QUERY_URL") { if !url.trim().is_empty() { scenario = scenario.with_metrics_query_url_str(url.trim()); } } if let Ok(url) = env::var("NOMOS_METRICS_OTLP_INGEST_URL") { if !url.trim().is_empty() { scenario = scenario.with_metrics_otlp_ingest_url_str(url.trim()); } } let mut plan = scenario.build(); let deployer = K8sDeployer::new(); info!("deploying k8s stack"); let runner: Runner = match deployer.deploy(&plan).await { Ok(runner) => runner, Err(K8sRunnerError::ClientInit { source }) => { warn!("Kubernetes cluster unavailable ({source}); skipping"); return Ok(()); } Err(err) => return Err(anyhow::Error::new(err)).context("deploying k8s stack failed"), }; if !runner.context().telemetry().is_configured() { warn!("metrics querying is disabled; set NOMOS_METRICS_QUERY_URL to enable PromQL queries"); } info!("running scenario"); runner .run(&mut plan) .await .context("running k8s scenario failed")?; Ok(()) }