diff --git a/cfgsync/adapter/src/lib.rs b/cfgsync/adapter/src/lib.rs index 6df51e9..caad421 100644 --- a/cfgsync/adapter/src/lib.rs +++ b/cfgsync/adapter/src/lib.rs @@ -2,7 +2,7 @@ use std::{collections::HashMap, error::Error, sync::Mutex}; use cfgsync_artifacts::ArtifactFile; use cfgsync_core::{ - CfgSyncErrorResponse, CfgSyncPayload, ConfigResolveResponse, NodeConfigSource, + CfgSyncErrorResponse, ConfigResolveResponse, NodeArtifactsPayload, NodeConfigSource, NodeRegistration, RegisterNodeResponse, }; use serde::{Deserialize, Serialize}; @@ -281,9 +281,9 @@ where }; match catalog.resolve(®istration.identifier) { - Some(config) => { - ConfigResolveResponse::Config(CfgSyncPayload::from_files(config.files.clone())) - } + Some(config) => ConfigResolveResponse::Config(NodeArtifactsPayload::from_files( + config.files.clone(), + )), None => ConfigResolveResponse::Error(CfgSyncErrorResponse::missing_config( ®istration.identifier, )), @@ -317,7 +317,7 @@ where let registrations = self.registration_set(); match self.materializer.materialize(®istration, ®istrations) { - Ok(Some(artifacts)) => ConfigResolveResponse::Config(CfgSyncPayload::from_files( + Ok(Some(artifacts)) => ConfigResolveResponse::Config(NodeArtifactsPayload::from_files( artifacts.files().to_vec(), )), Ok(None) => ConfigResolveResponse::Error(CfgSyncErrorResponse::not_ready( diff --git a/cfgsync/core/src/bundle.rs b/cfgsync/core/src/bundle.rs index 003dd8a..d8f6cab 100644 --- a/cfgsync/core/src/bundle.rs +++ b/cfgsync/core/src/bundle.rs @@ -1,26 +1,32 @@ use serde::{Deserialize, Serialize}; -use crate::CfgSyncFile; +use crate::NodeArtifactFile; /// Top-level cfgsync bundle containing per-node file payloads. #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct CfgSyncBundle { - pub nodes: Vec, +pub struct NodeArtifactsBundle { + pub nodes: Vec, } -impl CfgSyncBundle { +impl NodeArtifactsBundle { #[must_use] - pub fn new(nodes: Vec) -> Self { + pub fn new(nodes: Vec) -> Self { Self { nodes } } } /// Artifact set for a single node resolved by identifier. #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct CfgSyncBundleNode { +pub struct NodeArtifactsBundleEntry { /// Stable node identifier used by cfgsync lookup. pub identifier: String, /// Files that should be materialized for the node. #[serde(default)] - pub files: Vec, + pub files: Vec, } + +#[doc(hidden)] +pub type CfgSyncBundle = NodeArtifactsBundle; + +#[doc(hidden)] +pub type CfgSyncBundleNode = NodeArtifactsBundleEntry; diff --git a/cfgsync/core/src/client.rs b/cfgsync/core/src/client.rs index bfc07ec..545d9a2 100644 --- a/cfgsync/core/src/client.rs +++ b/cfgsync/core/src/client.rs @@ -1,7 +1,7 @@ use serde::Serialize; use thiserror::Error; -use crate::repo::{CfgSyncErrorResponse, CfgSyncPayload, NodeRegistration}; +use crate::repo::{CfgSyncErrorResponse, NodeArtifactsPayload, NodeRegistration}; /// cfgsync client-side request/response failures. #[derive(Debug, Error)] @@ -58,7 +58,7 @@ impl CfgSyncClient { pub async fn fetch_node_config( &self, payload: &NodeRegistration, - ) -> Result { + ) -> Result { self.post_json("/node", payload).await } @@ -66,7 +66,7 @@ impl CfgSyncClient { pub async fn fetch_init_with_node_config( &self, payload: &NodeRegistration, - ) -> Result { + ) -> Result { self.post_json("/init-with-node", payload).await } @@ -93,7 +93,7 @@ impl CfgSyncClient { &self, path: &str, payload: &P, - ) -> Result { + ) -> Result { let url = self.endpoint_url(path); let response = self.http.post(url).json(payload).send().await?; diff --git a/cfgsync/core/src/lib.rs b/cfgsync/core/src/lib.rs index e49e20f..75ed135 100644 --- a/cfgsync/core/src/lib.rs +++ b/cfgsync/core/src/lib.rs @@ -4,7 +4,9 @@ pub mod render; pub mod repo; pub mod server; +#[doc(hidden)] pub use bundle::{CfgSyncBundle, CfgSyncBundleNode}; +pub use bundle::{NodeArtifactsBundle, NodeArtifactsBundleEntry}; pub use client::{CfgSyncClient, ClientError, ConfigFetchStatus}; pub use render::{ CfgsyncConfigOverrides, CfgsyncOutputPaths, RenderedCfgsync, apply_cfgsync_overrides, @@ -13,13 +15,14 @@ pub use render::{ }; pub use repo::{ BundleConfigSource, BundleConfigSourceError, CFGSYNC_SCHEMA_VERSION, CfgSyncErrorCode, - CfgSyncErrorResponse, CfgSyncFile, CfgSyncPayload, ConfigResolveResponse, NodeConfigSource, - NodeRegistration, RegisterNodeResponse, RegistrationPayload, StaticConfigSource, + CfgSyncErrorResponse, ConfigResolveResponse, NodeArtifactFile, NodeArtifactsPayload, + NodeConfigSource, NodeRegistration, RegisterNodeResponse, RegistrationPayload, + StaticConfigSource, }; #[doc(hidden)] pub use repo::{ - ConfigProvider, ConfigRepo, FileConfigProvider, FileConfigProviderError, RegistrationResponse, - RepoResponse, + CfgSyncFile, CfgSyncPayload, ConfigProvider, ConfigRepo, FileConfigProvider, + FileConfigProviderError, RegistrationResponse, RepoResponse, }; #[doc(hidden)] pub use server::CfgSyncState; diff --git a/cfgsync/core/src/repo.rs b/cfgsync/core/src/repo.rs index 692a8fb..b1581f7 100644 --- a/cfgsync/core/src/repo.rs +++ b/cfgsync/core/src/repo.rs @@ -5,22 +5,22 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer, de::DeserializeOwn use serde_json::Value; use thiserror::Error; -use crate::{CfgSyncBundle, CfgSyncBundleNode}; +use crate::{NodeArtifactsBundle, NodeArtifactsBundleEntry}; /// Schema version served by cfgsync payload responses. pub const CFGSYNC_SCHEMA_VERSION: u16 = 1; /// Canonical cfgsync file type used in payloads and bundles. -pub type CfgSyncFile = ArtifactFile; +pub type NodeArtifactFile = ArtifactFile; /// Payload returned by cfgsync server for one node. #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct CfgSyncPayload { +pub struct NodeArtifactsPayload { /// Payload schema version for compatibility checks. pub schema_version: u16, /// Files that must be written on the target node. #[serde(default)] - pub files: Vec, + pub files: Vec, } /// Adapter-owned registration payload stored alongside a generic node identity. @@ -137,9 +137,9 @@ impl NodeRegistration { } } -impl CfgSyncPayload { +impl NodeArtifactsPayload { #[must_use] - pub fn from_files(files: Vec) -> Self { + pub fn from_files(files: Vec) -> Self { Self { schema_version: CFGSYNC_SCHEMA_VERSION, files, @@ -147,7 +147,7 @@ impl CfgSyncPayload { } #[must_use] - pub fn files(&self) -> &[CfgSyncFile] { + pub fn files(&self) -> &[NodeArtifactFile] { &self.files } @@ -201,7 +201,7 @@ impl CfgSyncErrorResponse { /// Resolution outcome for a requested node identifier. pub enum ConfigResolveResponse { - Config(CfgSyncPayload), + Config(NodeArtifactsPayload), Error(CfgSyncErrorResponse), } @@ -220,12 +220,12 @@ pub trait NodeConfigSource: Send + Sync { /// In-memory map-backed source used by cfgsync server state. pub struct StaticConfigSource { - configs: HashMap, + configs: HashMap, } impl StaticConfigSource { #[must_use] - pub fn from_bundle(configs: HashMap) -> Arc { + pub fn from_bundle(configs: HashMap) -> Arc { Arc::new(Self { configs }) } } @@ -273,19 +273,19 @@ pub enum BundleLoadError { } #[must_use] -pub fn bundle_to_payload_map(bundle: CfgSyncBundle) -> HashMap { +pub fn bundle_to_payload_map(bundle: NodeArtifactsBundle) -> HashMap { bundle .nodes .into_iter() .map(|node| { - let CfgSyncBundleNode { identifier, files } = node; + let NodeArtifactsBundleEntry { identifier, files } = node; - (identifier, CfgSyncPayload::from_files(files)) + (identifier, NodeArtifactsPayload::from_files(files)) }) .collect() } -pub fn load_bundle(path: &Path) -> Result { +pub fn load_bundle(path: &Path) -> Result { let path_string = path.display().to_string(); let raw = fs::read_to_string(path).map_err(|source| BundleLoadError::ReadBundle { path: path_string.clone(), @@ -337,8 +337,8 @@ mod tests { assert_eq!(typed.service, "blend"); } - fn sample_payload() -> CfgSyncPayload { - CfgSyncPayload::from_files(vec![CfgSyncFile::new("/config.yaml", "key: value")]) + fn sample_payload() -> NodeArtifactsPayload { + NodeArtifactsPayload::from_files(vec![NodeArtifactFile::new("/config.yaml", "key: value")]) } #[test] @@ -455,7 +455,7 @@ impl BundleConfigSource { source, })?; - let bundle: CfgSyncBundle = + let bundle: NodeArtifactsBundle = serde_yaml::from_str(&raw).map_err(|source| BundleConfigSourceError::Parse { path: path.display().to_string(), source, @@ -483,8 +483,11 @@ impl NodeConfigSource for BundleConfigSource { } } -fn payload_from_bundle_node(node: CfgSyncBundleNode) -> (String, CfgSyncPayload) { - (node.identifier, CfgSyncPayload::from_files(node.files)) +fn payload_from_bundle_node(node: NodeArtifactsBundleEntry) -> (String, NodeArtifactsPayload) { + ( + node.identifier, + NodeArtifactsPayload::from_files(node.files), + ) } #[doc(hidden)] @@ -506,3 +509,9 @@ pub type FileConfigProvider = BundleConfigSource; #[doc(hidden)] pub type FileConfigProviderError = BundleConfigSourceError; + +#[doc(hidden)] +pub type CfgSyncFile = NodeArtifactFile; + +#[doc(hidden)] +pub type CfgSyncPayload = NodeArtifactsPayload; diff --git a/cfgsync/core/src/server.rs b/cfgsync/core/src/server.rs index 6ac57ab..2ab2da7 100644 --- a/cfgsync/core/src/server.rs +++ b/cfgsync/core/src/server.rs @@ -119,12 +119,12 @@ mod tests { use super::{CfgsyncServerState, NodeRegistration, node_config, register_node}; use crate::repo::{ - CFGSYNC_SCHEMA_VERSION, CfgSyncErrorCode, CfgSyncErrorResponse, CfgSyncFile, - CfgSyncPayload, ConfigResolveResponse, NodeConfigSource, RegisterNodeResponse, + CFGSYNC_SCHEMA_VERSION, CfgSyncErrorCode, CfgSyncErrorResponse, ConfigResolveResponse, + NodeArtifactFile, NodeArtifactsPayload, NodeConfigSource, RegisterNodeResponse, }; struct StaticProvider { - data: HashMap, + data: HashMap, } impl NodeConfigSource for StaticProvider { @@ -154,7 +154,7 @@ mod tests { } struct RegistrationAwareProvider { - data: HashMap, + data: HashMap, registrations: std::sync::Mutex>, } @@ -201,10 +201,10 @@ mod tests { } } - fn sample_payload() -> CfgSyncPayload { - CfgSyncPayload { + fn sample_payload() -> NodeArtifactsPayload { + NodeArtifactsPayload { schema_version: CFGSYNC_SCHEMA_VERSION, - files: vec![CfgSyncFile::new("/app-config.yaml", "app: test")], + files: vec![NodeArtifactFile::new("/app-config.yaml", "app: test")], } } diff --git a/cfgsync/runtime/src/client.rs b/cfgsync/runtime/src/client.rs index 1fb9efe..d0bea51 100644 --- a/cfgsync/runtime/src/client.rs +++ b/cfgsync/runtime/src/client.rs @@ -6,8 +6,8 @@ use std::{ use anyhow::{Context as _, Result, bail}; use cfgsync_core::{ - CFGSYNC_SCHEMA_VERSION, CfgSyncClient, CfgSyncFile, CfgSyncPayload, NodeRegistration, - RegistrationPayload, + CFGSYNC_SCHEMA_VERSION, CfgSyncClient, NodeArtifactFile, NodeArtifactsPayload, + NodeRegistration, RegistrationPayload, }; use thiserror::Error; use tokio::time::{Duration, sleep}; @@ -22,7 +22,10 @@ enum ClientEnvError { InvalidIp { value: String }, } -async fn fetch_with_retry(payload: &NodeRegistration, server_addr: &str) -> Result { +async fn fetch_with_retry( + payload: &NodeRegistration, + server_addr: &str, +) -> Result { let client = CfgSyncClient::new(server_addr); for attempt in 1..=FETCH_ATTEMPTS { @@ -43,7 +46,10 @@ async fn fetch_with_retry(payload: &NodeRegistration, server_addr: &str) -> Resu unreachable!("cfgsync fetch loop always returns before exhausting attempts"); } -async fn fetch_once(client: &CfgSyncClient, payload: &NodeRegistration) -> Result { +async fn fetch_once( + client: &CfgSyncClient, + payload: &NodeRegistration, +) -> Result { let response = client.fetch_node_config(payload).await?; Ok(response) @@ -92,7 +98,7 @@ async fn register_node(payload: &NodeRegistration, server_addr: &str) -> Result< unreachable!("cfgsync register loop always returns before exhausting attempts"); } -fn ensure_schema_version(config: &CfgSyncPayload) -> Result<()> { +fn ensure_schema_version(config: &NodeArtifactsPayload) -> Result<()> { if config.schema_version != CFGSYNC_SCHEMA_VERSION { bail!( "unsupported cfgsync payload schema version {}, expected {}", @@ -104,7 +110,7 @@ fn ensure_schema_version(config: &CfgSyncPayload) -> Result<()> { Ok(()) } -fn collect_payload_files(config: &CfgSyncPayload) -> Result<&[CfgSyncFile]> { +fn collect_payload_files(config: &NodeArtifactsPayload) -> Result<&[NodeArtifactFile]> { if config.is_empty() { bail!("cfgsync payload contains no files"); } @@ -112,7 +118,7 @@ fn collect_payload_files(config: &CfgSyncPayload) -> Result<&[CfgSyncFile]> { Ok(config.files()) } -fn write_cfgsync_file(file: &CfgSyncFile) -> Result<()> { +fn write_cfgsync_file(file: &NodeArtifactFile) -> Result<()> { let path = PathBuf::from(&file.path); ensure_parent_dir(&path)?; @@ -181,8 +187,8 @@ mod tests { use std::collections::HashMap; use cfgsync_core::{ - CfgSyncBundle, CfgSyncBundleNode, CfgSyncPayload, CfgsyncServerState, StaticConfigSource, - run_cfgsync, + CfgsyncServerState, NodeArtifactsBundle, NodeArtifactsBundleEntry, NodeArtifactsPayload, + StaticConfigSource, run_cfgsync, }; use tempfile::tempdir; @@ -194,11 +200,11 @@ mod tests { let app_config_path = dir.path().join("config.yaml"); let deployment_path = dir.path().join("deployment.yaml"); - let bundle = CfgSyncBundle::new(vec![CfgSyncBundleNode { + let bundle = NodeArtifactsBundle::new(vec![NodeArtifactsBundleEntry { identifier: "node-1".to_owned(), files: vec![ - CfgSyncFile::new(app_config_path.to_string_lossy(), "app_key: app_value"), - CfgSyncFile::new(deployment_path.to_string_lossy(), "mode: local"), + NodeArtifactFile::new(app_config_path.to_string_lossy(), "app_key: app_value"), + NodeArtifactFile::new(deployment_path.to_string_lossy(), "mode: local"), ], }]); @@ -227,14 +233,14 @@ mod tests { assert_eq!(deployment, "mode: local"); } - fn bundle_to_payload_map(bundle: CfgSyncBundle) -> HashMap { + fn bundle_to_payload_map(bundle: NodeArtifactsBundle) -> HashMap { bundle .nodes .into_iter() .map(|node| { - let CfgSyncBundleNode { identifier, files } = node; + let NodeArtifactsBundleEntry { identifier, files } = node; - (identifier, CfgSyncPayload::from_files(files)) + (identifier, NodeArtifactsPayload::from_files(files)) }) .collect() } diff --git a/cfgsync/runtime/src/server.rs b/cfgsync/runtime/src/server.rs index 1090ac0..00f114c 100644 --- a/cfgsync/runtime/src/server.rs +++ b/cfgsync/runtime/src/server.rs @@ -3,7 +3,7 @@ use std::{fs, path::Path, sync::Arc}; use anyhow::Context as _; use cfgsync_adapter::{NodeArtifacts, NodeArtifactsCatalog, RegistrationConfigProvider}; use cfgsync_core::{ - BundleConfigSource, CfgSyncBundle, CfgsyncServerState, NodeConfigSource, run_cfgsync, + BundleConfigSource, CfgsyncServerState, NodeArtifactsBundle, NodeConfigSource, run_cfgsync, }; use serde::Deserialize; use thiserror::Error; @@ -120,7 +120,7 @@ fn load_materializing_provider(bundle_path: &Path) -> anyhow::Result anyhow::Result { +fn load_bundle_yaml(bundle_path: &Path) -> anyhow::Result { let raw = fs::read_to_string(bundle_path) .with_context(|| format!("reading cfgsync bundle from {}", bundle_path.display()))?; @@ -128,7 +128,7 @@ fn load_bundle_yaml(bundle_path: &Path) -> anyhow::Result { .with_context(|| format!("parsing cfgsync bundle from {}", bundle_path.display())) } -fn build_node_catalog(bundle: CfgSyncBundle) -> NodeArtifactsCatalog { +fn build_node_catalog(bundle: NodeArtifactsBundle) -> NodeArtifactsCatalog { let nodes = bundle .nodes .into_iter() diff --git a/logos/runtime/ext/src/cfgsync/mod.rs b/logos/runtime/ext/src/cfgsync/mod.rs index 6bc28cc..4d06cd6 100644 --- a/logos/runtime/ext/src/cfgsync/mod.rs +++ b/logos/runtime/ext/src/cfgsync/mod.rs @@ -2,7 +2,7 @@ use anyhow::Result; use cfgsync_adapter::{CfgsyncEnv, build_cfgsync_node_catalog}; pub(crate) use cfgsync_core::render::CfgsyncOutputPaths; use cfgsync_core::{ - CfgSyncBundle, CfgSyncBundleNode, + NodeArtifactsBundle, NodeArtifactsBundleEntry, render::{ CfgsyncConfigOverrides, RenderedCfgsync, ensure_bundle_path, render_cfgsync_yaml_from_template, write_rendered_cfgsync, @@ -48,20 +48,20 @@ pub(crate) fn render_cfgsync_from_template( fn build_cfgsync_bundle( topology: &E::Deployment, hostnames: &[String], -) -> Result { +) -> Result { let nodes = build_cfgsync_node_catalog::(topology, hostnames)?.into_configs(); let nodes = nodes .into_iter() - .map(|node| CfgSyncBundleNode { + .map(|node| NodeArtifactsBundleEntry { identifier: node.identifier, files: node.files, }) .collect(); - Ok(CfgSyncBundle::new(nodes)) + Ok(NodeArtifactsBundle::new(nodes)) } -fn append_deployment_files(bundle: &mut CfgSyncBundle) -> Result<()> { +fn append_deployment_files(bundle: &mut NodeArtifactsBundle) -> Result<()> { for node in &mut bundle.nodes { if has_file_path(node, "/deployment.yaml") { continue; @@ -80,18 +80,18 @@ fn append_deployment_files(bundle: &mut CfgSyncBundle) -> Result<()> { Ok(()) } -fn has_file_path(node: &CfgSyncBundleNode, path: &str) -> bool { +fn has_file_path(node: &NodeArtifactsBundleEntry, path: &str) -> bool { node.files.iter().any(|file| file.path == path) } -fn config_file_content(node: &CfgSyncBundleNode) -> Option { +fn config_file_content(node: &NodeArtifactsBundleEntry) -> Option { node.files .iter() .find_map(|file| (file.path == "/config.yaml").then_some(file.content.clone())) } -fn build_bundle_file(path: &str, content: String) -> cfgsync_core::CfgSyncFile { - cfgsync_core::CfgSyncFile { +fn build_bundle_file(path: &str, content: String) -> cfgsync_core::NodeArtifactFile { + cfgsync_core::NodeArtifactFile { path: path.to_owned(), content, }