From 85a6f9d054fe63cad8ee48293ee60b540b9d3e57 Mon Sep 17 00:00:00 2001 From: andrussal Date: Tue, 24 Feb 2026 03:46:54 +0100 Subject: [PATCH] refactor cfgsync rendering to generic runtime config --- Cargo.lock | 2 - logos/infra/assets/stack/cfgsync.yaml | 51 --------- logos/infra/assets/stack/scripts/run_logos.sh | 2 +- logos/runtime/ext/Cargo.toml | 2 - logos/runtime/ext/src/cfgsync/mod.rs | 66 ++++++------ logos/runtime/ext/src/cfgsync/template.rs | 26 ----- logos/runtime/ext/src/compose_env.rs | 2 +- logos/runtime/ext/src/k8s_env.rs | 22 +--- .../tools/cfgsync-runtime/src/render.rs | 100 +++++++++++++++++- 9 files changed, 136 insertions(+), 137 deletions(-) delete mode 100644 logos/infra/assets/stack/cfgsync.yaml delete mode 100644 logos/runtime/ext/src/cfgsync/template.rs diff --git a/Cargo.lock b/Cargo.lock index 23419e2..844e836 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2894,8 +2894,6 @@ dependencies = [ "cfgsync-runtime", "kube", "logos-blockchain-http-api-common", - "logos-blockchain-tracing", - "logos-blockchain-tracing-service", "reqwest", "serde", "serde_yaml", diff --git a/logos/infra/assets/stack/cfgsync.yaml b/logos/infra/assets/stack/cfgsync.yaml deleted file mode 100644 index 23852a4..0000000 --- a/logos/infra/assets/stack/cfgsync.yaml +++ /dev/null @@ -1,51 +0,0 @@ -port: 4400 -n_hosts: 4 -timeout: 10 -global_params_path: "/etc/logos/global_params" -# Optional: serve prebuilt configs from a bundle file. -# bundle_path: cfgsync.bundle.yaml - -# ConsensusConfig related parameters -security_param: 10 -active_slot_coeff: 0.9 -wallet: - accounts: [] - -# DaConfig related parameters -subnetwork_size: 2 -dispersal_factor: 2 -num_samples: 1 -num_subnets: 2 -old_blobs_check_interval: "5.0" -blobs_validity_duration: "60.0" -min_dispersal_peers: 1 -min_replication_peers: 1 -monitor_failure_time_window: "5.0" -balancer_interval: "5.0" -# Dispersal mempool publish strategy -mempool_publish_strategy: !SampleSubnetworks - sample_threshold: 2 - timeout: "2.0" - cooldown: "0.0001" - -replication_settings: - seen_message_cache_size: 204800 - seen_message_ttl: "900.0" -retry_shares_limit: 5 -retry_commitments_limit: 5 - -# Tracing -tracing_settings: - # Default to stdout so `docker logs` / `kubectl logs` shows node output. - # Switch to `!File` if you want per-node log files inside the container/pod. - logger: Stdout - # Disable OTLP traces to remove DNS errors; metrics stay enabled below. - tracing: None - filter: !EnvFilter - filters: - nomos: debug - cryptarchia: debug - logos_blockchain_chain_leader_service: debug - metrics: None - console: None - level: DEBUG diff --git a/logos/infra/assets/stack/scripts/run_logos.sh b/logos/infra/assets/stack/scripts/run_logos.sh index 229bcf2..06edebb 100755 --- a/logos/infra/assets/stack/scripts/run_logos.sh +++ b/logos/infra/assets/stack/scripts/run_logos.sh @@ -64,7 +64,7 @@ export CFG_FILE_PATH="/config.yaml" \ CFG_HOST_KIND="${CFG_HOST_KIND:-$role}" \ CFG_HOST_IDENTIFIER="${CFG_HOST_IDENTIFIER:-$host_identifier_default}" \ LOGOS_BLOCKCHAIN_TIME_BACKEND="${LOGOS_BLOCKCHAIN_TIME_BACKEND:-monotonic}" \ - LOG_LEVEL="${LOG_LEVEL:-INFO}"``" + LOG_LEVEL="${LOG_LEVEL:-INFO}" # Ensure recovery directory exists to avoid early crashes in services that # persist state. diff --git a/logos/runtime/ext/Cargo.toml b/logos/runtime/ext/Cargo.toml index 585e5d9..16b4f1d 100644 --- a/logos/runtime/ext/Cargo.toml +++ b/logos/runtime/ext/Cargo.toml @@ -17,8 +17,6 @@ testing-framework-runner-local = { workspace = true } # Logos / Nomos deps lb_http_api_common = { workspace = true } -lb_tracing = { workspace = true } -lb_tracing_service = { workspace = true } # External anyhow = "1" diff --git a/logos/runtime/ext/src/cfgsync/mod.rs b/logos/runtime/ext/src/cfgsync/mod.rs index d1b809b..47c2842 100644 --- a/logos/runtime/ext/src/cfgsync/mod.rs +++ b/logos/runtime/ext/src/cfgsync/mod.rs @@ -1,16 +1,14 @@ -mod template; - -use std::path::Path; - use anyhow::Result; pub(crate) use cfgsync_runtime::render::CfgsyncOutputPaths; use cfgsync_runtime::{ bundle::build_cfgsync_bundle_with_hostnames, - render::{RenderedCfgsync, apply_timeout_floor, ensure_bundle_path, write_rendered_cfgsync}, + render::{ + CfgsyncConfigOverrides, RenderedCfgsync, ensure_bundle_path, + render_cfgsync_yaml_from_template, write_rendered_cfgsync, + }, }; -use lb_tracing::metrics::otlp::OtlpMetricsConfig; -use lb_tracing_service::MetricsLayerSettings; use reqwest::Url; +use serde_yaml::{Mapping, Value}; use testing_framework_core::cfgsync::CfgsyncEnv; pub(crate) struct CfgsyncRenderOptions { @@ -21,16 +19,14 @@ pub(crate) struct CfgsyncRenderOptions { } pub(crate) fn render_cfgsync_from_template( - template_path: &Path, topology: &E::Deployment, hostnames: &[String], options: CfgsyncRenderOptions, ) -> Result { - let mut cfg = template::load_cfgsync_template(template_path)?; - apply_render_options::(&mut cfg, topology, options); - + let cfg = build_cfgsync_server_config(); + let overrides = build_overrides::(topology, options); + let config_yaml = render_cfgsync_yaml_from_template(cfg, &overrides)?; let bundle = build_cfgsync_bundle_with_hostnames::(topology, hostnames)?; - let config_yaml = serde_yaml::to_string(&cfg)?; let bundle_yaml = serde_yaml::to_string(&bundle)?; Ok(RenderedCfgsync { @@ -39,8 +35,22 @@ pub(crate) fn render_cfgsync_from_template( }) } +fn build_cfgsync_server_config() -> Value { + let mut root = Mapping::new(); + root.insert( + Value::String("port".to_string()), + Value::Number(4400_u64.into()), + ); + + root.insert( + Value::String("bundle_path".to_string()), + Value::String("cfgsync.bundle.yaml".to_string()), + ); + + Value::Mapping(root) +} + pub(crate) fn render_and_write_cfgsync_from_template( - template_path: &Path, topology: &E::Deployment, hostnames: &[String], mut options: CfgsyncRenderOptions, @@ -48,16 +58,16 @@ pub(crate) fn render_and_write_cfgsync_from_template( ) -> Result { ensure_bundle_path(&mut options.bundle_path, output.bundle_path); - let rendered = render_cfgsync_from_template::(template_path, topology, hostnames, options)?; + let rendered = render_cfgsync_from_template::(topology, hostnames, options)?; write_rendered_cfgsync(&rendered, output)?; + Ok(rendered) } -fn apply_render_options( - cfg: &mut template::CfgSyncConfig, +fn build_overrides( topology: &E::Deployment, options: CfgsyncRenderOptions, -) { +) -> CfgsyncConfigOverrides { let CfgsyncRenderOptions { port, bundle_path, @@ -65,21 +75,11 @@ fn apply_render_options( metrics_otlp_ingest_url, } = options; - if let Some(port) = port { - cfg.port = port; - } - - cfg.n_hosts = E::nodes(topology).len(); - cfg.bundle_path = bundle_path; - apply_metrics_endpoint(cfg, metrics_otlp_ingest_url); - apply_timeout_floor(&mut cfg.timeout, min_timeout_secs); -} - -fn apply_metrics_endpoint(cfg: &mut template::CfgSyncConfig, endpoint: Option) { - if let Some(endpoint) = endpoint { - cfg.tracing_settings.metrics = MetricsLayerSettings::Otlp(OtlpMetricsConfig { - endpoint, - host_identifier: "node".into(), - }); + CfgsyncConfigOverrides { + port, + n_hosts: Some(E::nodes(topology).len()), + timeout_floor_secs: min_timeout_secs, + bundle_path, + metrics_otlp_ingest_url: metrics_otlp_ingest_url.map(|url| url.to_string()), } } diff --git a/logos/runtime/ext/src/cfgsync/template.rs b/logos/runtime/ext/src/cfgsync/template.rs deleted file mode 100644 index 4812101..0000000 --- a/logos/runtime/ext/src/cfgsync/template.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::{fs::File, path::Path}; - -use anyhow::{Context as _, Result}; -use lb_tracing_service::TracingSettings; -use serde::{Deserialize, Serialize}; -use tracing::debug; - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct CfgSyncConfig { - pub port: u16, - #[serde(default)] - pub n_hosts: usize, - pub timeout: u64, - #[serde(default)] - #[serde(skip_serializing_if = "Option::is_none")] - pub bundle_path: Option, - #[serde(default)] - pub tracing_settings: TracingSettings, -} - -pub fn load_cfgsync_template(path: &Path) -> Result { - debug!(path = %path.display(), "loading cfgsync template"); - let file = File::open(path) - .with_context(|| format!("opening cfgsync template at {}", path.display()))?; - serde_yaml::from_reader(file).context("parsing cfgsync template") -} diff --git a/logos/runtime/ext/src/compose_env.rs b/logos/runtime/ext/src/compose_env.rs index f2a2290..4fa3018 100644 --- a/logos/runtime/ext/src/compose_env.rs +++ b/logos/runtime/ext/src/compose_env.rs @@ -120,8 +120,8 @@ impl ComposeDeployEnv for LbcExtEnv { let bundle_path = cfgsync_bundle_path(path); let hostnames = topology_hostnames(topology); let options = cfgsync_render_options(port, metrics_otlp_ingest_url); + render_and_write_cfgsync_from_template::( - path, topology, &hostnames, options, diff --git a/logos/runtime/ext/src/k8s_env.rs b/logos/runtime/ext/src/k8s_env.rs index 667b83c..15b2dc9 100644 --- a/logos/runtime/ext/src/k8s_env.rs +++ b/logos/runtime/ext/src/k8s_env.rs @@ -183,7 +183,7 @@ pub fn prepare_assets( let tempdir = create_assets_tempdir()?; let (cfgsync_file, cfgsync_yaml, bundle_yaml) = - render_and_write_cfgsync(&root, topology, metrics_otlp_ingest_url, &tempdir)?; + render_and_write_cfgsync(topology, metrics_otlp_ingest_url, &tempdir)?; let scripts = validate_scripts(&root)?; let chart_path = helm_chart_path()?; let values_file = render_and_write_values(topology, &tempdir, &cfgsync_yaml, &bundle_yaml)?; @@ -346,7 +346,6 @@ fn create_assets_tempdir() -> Result { } fn render_and_write_cfgsync( - root: &Path, topology: &DeploymentPlan, metrics_otlp_ingest_url: Option<&Url>, tempdir: &TempDir, @@ -354,12 +353,12 @@ fn render_and_write_cfgsync( let cfgsync_file = tempdir.path().join("cfgsync.yaml"); let bundle_file = tempdir.path().join("cfgsync.bundle.yaml"); let (cfgsync_yaml, bundle_yaml) = render_cfgsync_config( - root, topology, metrics_otlp_ingest_url, &cfgsync_file, &bundle_file, )?; + Ok((cfgsync_file, cfgsync_yaml, bundle_yaml)) } @@ -378,17 +377,13 @@ fn testnet_image() -> String { } fn render_cfgsync_config( - root: &Path, topology: &DeploymentPlan, metrics_otlp_ingest_url: Option<&Url>, cfgsync_file: &Path, bundle_file: &Path, ) -> Result<(String, String), AssetsError> { - let cfgsync_template_path = cfgsync_template_path(root); - debug!(path = %cfgsync_template_path.display(), "loading cfgsync template"); let hostnames = k8s_node_hostnames(topology); let rendered = render_and_write_cfgsync_from_template::( - &cfgsync_template_path, topology, &hostnames, CfgsyncRenderOptions { @@ -407,10 +402,6 @@ fn render_cfgsync_config( Ok((rendered.config_yaml, rendered.bundle_yaml)) } -fn cfgsync_template_path(root: &Path) -> PathBuf { - stack_assets_root(root).join("cfgsync.yaml") -} - fn k8s_node_hostnames(topology: &DeploymentPlan) -> Vec { topology .nodes() @@ -517,15 +508,6 @@ pub fn workspace_root() -> AnyhowResult { )) } -fn stack_assets_root(root: &Path) -> PathBuf { - if let Some(override_dir) = assets_override_dir(root) - && override_dir.exists() - { - return override_dir; - } - root.join(DEFAULT_ASSETS_STACK_DIR) -} - fn stack_scripts_root(root: &Path) -> PathBuf { if let Some(scripts) = override_scripts_dir(root) && scripts.exists() diff --git a/testing-framework/tools/cfgsync-runtime/src/render.rs b/testing-framework/tools/cfgsync-runtime/src/render.rs index 105e6ca..0f59b5c 100644 --- a/testing-framework/tools/cfgsync-runtime/src/render.rs +++ b/testing-framework/tools/cfgsync-runtime/src/render.rs @@ -1,6 +1,7 @@ use std::{fs, path::Path}; -use anyhow::Result; +use anyhow::{Context as _, Result}; +use serde_yaml::{Mapping, Value}; #[derive(Debug, Clone)] pub struct RenderedCfgsync { @@ -42,3 +43,100 @@ pub fn write_rendered_cfgsync( fs::write(output.bundle_path, &rendered.bundle_yaml)?; Ok(()) } + +#[derive(Debug, Clone, Default)] +pub struct CfgsyncConfigOverrides { + pub port: Option, + pub n_hosts: Option, + pub timeout_floor_secs: Option, + pub bundle_path: Option, + pub metrics_otlp_ingest_url: Option, +} + +pub fn load_cfgsync_template_yaml(path: &Path) -> Result { + let file = fs::File::open(path) + .with_context(|| format!("opening cfgsync template at {}", path.display()))?; + serde_yaml::from_reader(file).context("parsing cfgsync template") +} + +pub fn render_cfgsync_yaml_from_template( + mut template: Value, + overrides: &CfgsyncConfigOverrides, +) -> Result { + apply_cfgsync_overrides(&mut template, overrides)?; + serde_yaml::to_string(&template).context("serializing rendered cfgsync config") +} + +pub fn apply_cfgsync_overrides( + template: &mut Value, + overrides: &CfgsyncConfigOverrides, +) -> Result<()> { + let root = mapping_mut(template)?; + + if let Some(port) = overrides.port { + root.insert( + Value::String("port".to_string()), + serde_yaml::to_value(port)?, + ); + } + + if let Some(n_hosts) = overrides.n_hosts { + root.insert( + Value::String("n_hosts".to_string()), + serde_yaml::to_value(n_hosts)?, + ); + } + + if let Some(bundle_path) = &overrides.bundle_path { + root.insert( + Value::String("bundle_path".to_string()), + Value::String(bundle_path.clone()), + ); + } + + if let Some(timeout_floor_secs) = overrides.timeout_floor_secs { + let timeout_key = Value::String("timeout".to_string()); + let timeout_value = root + .get(&timeout_key) + .and_then(Value::as_u64) + .unwrap_or(timeout_floor_secs) + .max(timeout_floor_secs); + root.insert(timeout_key, serde_yaml::to_value(timeout_value)?); + } + + if let Some(endpoint) = &overrides.metrics_otlp_ingest_url { + let tracing_settings = nested_mapping_mut(root, "tracing_settings"); + tracing_settings.insert( + Value::String("metrics".to_string()), + parse_otlp_metrics_layer(endpoint)?, + ); + } + + Ok(()) +} + +fn mapping_mut(value: &mut Value) -> Result<&mut Mapping> { + value + .as_mapping_mut() + .context("cfgsync template root must be a YAML map") +} + +fn nested_mapping_mut<'a>(mapping: &'a mut Mapping, key: &str) -> &'a mut Mapping { + let key = Value::String(key.to_string()); + let entry = mapping + .entry(key) + .or_insert_with(|| Value::Mapping(Mapping::new())); + + if !entry.is_mapping() { + *entry = Value::Mapping(Mapping::new()); + } + + entry + .as_mapping_mut() + .expect("mapping entry should always be a mapping") +} + +fn parse_otlp_metrics_layer(endpoint: &str) -> Result { + let yaml = format!("!Otlp\nendpoint: \"{endpoint}\"\nhost_identifier: \"node\"\n"); + serde_yaml::from_str(&yaml).context("building metrics OTLP layer") +}