mirror of
https://github.com/logos-blockchain/logos-blockchain-testing.git
synced 2026-03-31 08:13:48 +00:00
Use materializing cfgsync provider at runtime
This commit is contained in:
parent
911d09e2c1
commit
b775f7fd81
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -922,6 +922,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"cfgsync-artifacts",
|
||||
"cfgsync-core",
|
||||
"serde",
|
||||
"thiserror 2.0.18",
|
||||
]
|
||||
|
||||
@ -954,6 +955,7 @@ name = "cfgsync-runtime"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cfgsync-adapter",
|
||||
"cfgsync-core",
|
||||
"clap",
|
||||
"serde",
|
||||
|
||||
@ -15,4 +15,5 @@ workspace = true
|
||||
[dependencies]
|
||||
cfgsync-artifacts = { workspace = true }
|
||||
cfgsync-core = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
|
||||
@ -5,18 +5,19 @@ use cfgsync_core::{
|
||||
CfgSyncErrorResponse, CfgSyncPayload, ConfigProvider, NodeRegistration, RegistrationResponse,
|
||||
RepoResponse,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
|
||||
/// Type-erased cfgsync adapter error used to preserve source context.
|
||||
pub type DynCfgsyncError = Box<dyn Error + Send + Sync + 'static>;
|
||||
|
||||
/// Per-node rendered config output used to build cfgsync bundles.
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct CfgsyncNodeConfig {
|
||||
/// Stable node identifier resolved by the adapter.
|
||||
pub identifier: String,
|
||||
/// Serialized config payload for the node.
|
||||
pub config_yaml: String,
|
||||
/// Files served to the node after cfgsync registration.
|
||||
pub files: Vec<ArtifactFile>,
|
||||
}
|
||||
|
||||
/// Node artifacts produced by a cfgsync materializer.
|
||||
@ -260,7 +261,7 @@ fn build_node_entry<E: CfgsyncEnv>(
|
||||
|
||||
Ok(CfgsyncNodeConfig {
|
||||
identifier: E::node_identifier(index, node),
|
||||
config_yaml,
|
||||
files: vec![ArtifactFile::new("/config.yaml", &config_yaml)],
|
||||
})
|
||||
}
|
||||
|
||||
@ -278,11 +279,12 @@ fn build_rewritten_node_config<E: CfgsyncEnv>(
|
||||
}
|
||||
|
||||
fn build_node_artifacts_from_config(config: &CfgsyncNodeConfig) -> CfgsyncNodeArtifacts {
|
||||
CfgsyncNodeArtifacts::new(vec![ArtifactFile::new("/config.yaml", &config.config_yaml)])
|
||||
CfgsyncNodeArtifacts::new(config.files.clone())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use cfgsync_artifacts::ArtifactFile;
|
||||
use cfgsync_core::{CfgSyncErrorCode, ConfigProvider, NodeRegistration, RepoResponse};
|
||||
|
||||
use super::{CfgsyncNodeCatalog, CfgsyncNodeConfig, MaterializingConfigProvider};
|
||||
@ -291,19 +293,19 @@ mod tests {
|
||||
fn catalog_resolves_identifier() {
|
||||
let catalog = CfgsyncNodeCatalog::new(vec![CfgsyncNodeConfig {
|
||||
identifier: "node-1".to_owned(),
|
||||
config_yaml: "key: value".to_owned(),
|
||||
files: vec![ArtifactFile::new("/config.yaml", "key: value")],
|
||||
}]);
|
||||
|
||||
let node = catalog.resolve("node-1").expect("resolve node config");
|
||||
|
||||
assert_eq!(node.config_yaml, "key: value");
|
||||
assert_eq!(node.files[0].content, "key: value");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn materializing_provider_resolves_registered_node() {
|
||||
let catalog = CfgsyncNodeCatalog::new(vec![CfgsyncNodeConfig {
|
||||
identifier: "node-1".to_owned(),
|
||||
config_yaml: "key: value".to_owned(),
|
||||
files: vec![ArtifactFile::new("/config.yaml", "key: value")],
|
||||
}]);
|
||||
let provider = MaterializingConfigProvider::new(catalog);
|
||||
let registration = NodeRegistration {
|
||||
@ -323,7 +325,7 @@ mod tests {
|
||||
fn materializing_provider_reports_not_ready_before_registration() {
|
||||
let catalog = CfgsyncNodeCatalog::new(vec![CfgsyncNodeConfig {
|
||||
identifier: "node-1".to_owned(),
|
||||
config_yaml: "key: value".to_owned(),
|
||||
files: vec![ArtifactFile::new("/config.yaml", "key: value")],
|
||||
}]);
|
||||
let provider = MaterializingConfigProvider::new(catalog);
|
||||
let registration = NodeRegistration {
|
||||
|
||||
@ -13,14 +13,15 @@ version = { workspace = true }
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1"
|
||||
cfgsync-core = { workspace = true }
|
||||
clap = { version = "4", features = ["derive"] }
|
||||
serde = { workspace = true }
|
||||
serde_yaml = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
tokio = { default-features = false, features = ["macros", "net", "rt-multi-thread"], version = "1" }
|
||||
tracing = { workspace = true }
|
||||
anyhow = "1"
|
||||
cfgsync-adapter = { workspace = true }
|
||||
cfgsync-core = { workspace = true }
|
||||
clap = { version = "4", features = ["derive"] }
|
||||
serde = { workspace = true }
|
||||
serde_yaml = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
tokio = { default-features = false, features = ["macros", "net", "rt-multi-thread"], version = "1" }
|
||||
tracing = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = { workspace = true }
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
use std::{fs, path::Path, sync::Arc};
|
||||
|
||||
use anyhow::Context as _;
|
||||
use cfgsync_core::{CfgSyncState, ConfigProvider, FileConfigProvider, run_cfgsync};
|
||||
use cfgsync_adapter::{CfgsyncNodeCatalog, MaterializingConfigProvider};
|
||||
use cfgsync_core::{CfgSyncBundle, CfgSyncState, ConfigProvider, FileConfigProvider, run_cfgsync};
|
||||
use serde::Deserialize;
|
||||
|
||||
/// Runtime cfgsync server config loaded from YAML.
|
||||
@ -9,6 +10,8 @@ use serde::Deserialize;
|
||||
pub struct CfgSyncServerConfig {
|
||||
pub port: u16,
|
||||
pub bundle_path: String,
|
||||
#[serde(default)]
|
||||
pub registration_flow: bool,
|
||||
}
|
||||
|
||||
impl CfgSyncServerConfig {
|
||||
@ -22,13 +25,42 @@ impl CfgSyncServerConfig {
|
||||
}
|
||||
}
|
||||
|
||||
fn load_bundle(bundle_path: &Path) -> anyhow::Result<Arc<dyn ConfigProvider>> {
|
||||
fn load_bundle_provider(bundle_path: &Path) -> anyhow::Result<Arc<dyn ConfigProvider>> {
|
||||
let provider = FileConfigProvider::from_yaml_file(bundle_path)
|
||||
.with_context(|| format!("loading cfgsync provider from {}", bundle_path.display()))?;
|
||||
|
||||
Ok(Arc::new(provider))
|
||||
}
|
||||
|
||||
fn load_materializing_provider(bundle_path: &Path) -> anyhow::Result<Arc<dyn ConfigProvider>> {
|
||||
let bundle = load_bundle_yaml(bundle_path)?;
|
||||
let catalog = build_node_catalog(bundle);
|
||||
let provider = MaterializingConfigProvider::new(catalog);
|
||||
|
||||
Ok(Arc::new(provider))
|
||||
}
|
||||
|
||||
fn load_bundle_yaml(bundle_path: &Path) -> anyhow::Result<CfgSyncBundle> {
|
||||
let raw = fs::read_to_string(bundle_path)
|
||||
.with_context(|| format!("reading cfgsync bundle from {}", bundle_path.display()))?;
|
||||
|
||||
serde_yaml::from_str(&raw)
|
||||
.with_context(|| format!("parsing cfgsync bundle from {}", bundle_path.display()))
|
||||
}
|
||||
|
||||
fn build_node_catalog(bundle: CfgSyncBundle) -> CfgsyncNodeCatalog {
|
||||
let nodes = bundle
|
||||
.nodes
|
||||
.into_iter()
|
||||
.map(|node| cfgsync_adapter::CfgsyncNodeConfig {
|
||||
identifier: node.identifier,
|
||||
files: node.files,
|
||||
})
|
||||
.collect();
|
||||
|
||||
CfgsyncNodeCatalog::new(nodes)
|
||||
}
|
||||
|
||||
fn resolve_bundle_path(config_path: &Path, bundle_path: &str) -> std::path::PathBuf {
|
||||
let path = Path::new(bundle_path);
|
||||
if path.is_absolute() {
|
||||
@ -46,14 +78,21 @@ pub async fn run_cfgsync_server(config_path: &Path) -> anyhow::Result<()> {
|
||||
let config = CfgSyncServerConfig::load_from_file(config_path)?;
|
||||
let bundle_path = resolve_bundle_path(config_path, &config.bundle_path);
|
||||
|
||||
let state = build_server_state(&bundle_path)?;
|
||||
let state = build_server_state(&config, &bundle_path)?;
|
||||
run_cfgsync(config.port, state).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn build_server_state(bundle_path: &Path) -> anyhow::Result<CfgSyncState> {
|
||||
let repo = load_bundle(bundle_path)?;
|
||||
fn build_server_state(
|
||||
config: &CfgSyncServerConfig,
|
||||
bundle_path: &Path,
|
||||
) -> anyhow::Result<CfgSyncState> {
|
||||
let repo = if config.registration_flow {
|
||||
load_materializing_provider(bundle_path)?
|
||||
} else {
|
||||
load_bundle_provider(bundle_path)?
|
||||
};
|
||||
|
||||
Ok(CfgSyncState::new(repo))
|
||||
}
|
||||
|
||||
@ -54,7 +54,7 @@ fn build_cfgsync_bundle<E: CfgsyncEnv>(
|
||||
.into_iter()
|
||||
.map(|node| CfgSyncBundleNode {
|
||||
identifier: node.identifier,
|
||||
files: vec![build_bundle_file("/config.yaml", node.config_yaml)],
|
||||
files: node.files,
|
||||
})
|
||||
.collect();
|
||||
|
||||
@ -121,6 +121,11 @@ fn build_cfgsync_server_config() -> Value {
|
||||
Value::String("cfgsync.bundle.yaml".to_string()),
|
||||
);
|
||||
|
||||
root.insert(
|
||||
Value::String("registration_flow".to_string()),
|
||||
Value::Bool(true),
|
||||
);
|
||||
|
||||
Value::Mapping(root)
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user