Skip to content

Commit 8649764

Browse files
committed
chore(config): add config translation
Add the translation layer that turns the two configuration sources into one SalukiConfiguration. SalukiConfigBuilder implements the Datadog witness, so the generated drive feeds it one key at a time, converting each raw value into its refined model type; finish assembles the multi-key endpoint field. SalukiOnly parses the Saluki-schema-only source and seeds the fields the Datadog schema does not cover. The two writers fill disjoint fields. The translate entry point runs both and returns the assembled model. A unit test exercises a scalar conversion, an enum parse, a seconds-to-Duration conversion, endpoint assembly, and a seeded field.
1 parent 15506da commit 8649764

7 files changed

Lines changed: 1670 additions & 7 deletions

File tree

Cargo.lock

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/agent-data-plane-config-system/Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,13 @@ edition = { workspace = true }
55
license = { workspace = true }
66
repository = { workspace = true }
77

8+
[dependencies]
9+
agent-data-plane-config = { workspace = true }
10+
bytesize = { workspace = true }
11+
datadog-agent-config = { workspace = true }
12+
serde = { workspace = true, features = ["derive"] }
13+
serde_json = { workspace = true }
14+
snafu = { workspace = true }
15+
816
[lints]
917
workspace = true
Lines changed: 88 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,90 @@
1-
//! Configuration system facade: loading, authority resolution, translation, validation, config
2-
//! views, and runtime updates.
1+
//! The Configuration system: translation and subscription of external configuration sources into an
2+
//! ADP-typed model.
33
//!
4-
//! This is the only ADP production crate permitted to use the raw-map APIs of `saluki-config`; all
5-
//! raw configuration access is confined here. It wires the Datadog source-normalization metadata
6-
//! (`KEY_ALIASES` and the remapper) from `datadog-agent-config` into the loader, drives the witness
7-
//! translation, and produces a `SalukiConfiguration`.
4+
//! This crate turns configuration sources into `SalukiConfiguration`:
85
//!
9-
//! It does not construct components and does not depend on `saluki-components`.
6+
//! - the typed Datadog source (`DatadogConfiguration`), whose supported keys the generated `drive`
7+
//! feeds to `DatadogTranslator` (a `DatadogConfigWitness`) one key at a time, and
8+
//! - the Saluki-schema-only source ([`SalukiOnly`]), whose values [`SalukiOnly::seed`] copies into
9+
//! the fields the Datadog schema does not cover.
10+
//!
11+
//! [`translate`] runs both writers and returns the assembled model. This is the only ADP production
12+
//! crate that bridges the source configuration to the model; it constructs no components and does
13+
//! not depend on `saluki-components`.
14+
15+
mod saluki_only;
16+
mod translators;
17+
18+
use agent_data_plane_config::SalukiConfiguration;
19+
use datadog_agent_config::{DatadogConfiguration, TranslateError};
20+
pub use saluki_only::SalukiOnly;
21+
pub use translators::ConfigTranslator;
22+
use translators::DatadogTranslator;
23+
24+
/// Translates the Datadog and Saluki-only sources into one [`SalukiConfiguration`].
25+
///
26+
/// The Datadog `drive` feeds every supported key in `datadog` to a `DatadogTranslator`, which
27+
/// assembles the multi-key endpoint field. Finally [`SalukiOnly::seed`] copies the Saluki-only
28+
/// values into their (disjoint) destinations.
29+
///
30+
/// # Errors
31+
///
32+
/// Returns the first [`TranslateError`] recorded while consuming a Datadog value (for example, an
33+
/// enum or byte-size string that cannot be parsed). Seeding does not fail.
34+
pub fn translate(
35+
datadog: &DatadogConfiguration, saluki_only: &SalukiOnly,
36+
) -> Result<SalukiConfiguration, TranslateError> {
37+
let mut config = DatadogTranslator::new(datadog).translate()?;
38+
saluki_only.seed(&mut config);
39+
Ok(config)
40+
}
41+
42+
#[cfg(test)]
43+
mod tests {
44+
use std::time::Duration;
45+
46+
use agent_data_plane_config::domains::dogstatsd::OriginTagCardinality;
47+
use datadog_agent_config::DatadogConfiguration;
48+
use serde_json::json;
49+
50+
use super::{translate, SalukiOnly};
51+
52+
#[test]
53+
fn translate_small_map_through_witness_and_seed() {
54+
// A small raw Datadog source map exercising a scalar conversion, an enum parse, a
55+
// seconds->Duration conversion, and the endpoint-assembly inputs.
56+
let datadog: DatadogConfiguration = serde_json::from_value(json!({
57+
"api_key": "abc",
58+
"dd_url": "https://custom.example.com",
59+
"dogstatsd_port": 9125,
60+
"dogstatsd_tag_cardinality": "high",
61+
"expected_tags_duration": 15.0,
62+
}))
63+
.expect("datadog source deserializes");
64+
65+
// A small Saluki-only source setting one seeded field.
66+
let saluki_only: SalukiOnly = serde_json::from_value(json!({
67+
"dogstatsd": { "tcp_port": 8126 },
68+
}))
69+
.expect("saluki-only source deserializes");
70+
71+
let config = translate(&datadog, &saluki_only).expect("translation succeeds");
72+
73+
// Driven scalar conversion: i64 -> u16.
74+
assert_eq!(config.domains.dogstatsd.listeners.port, 9125);
75+
// Driven enum parse.
76+
assert_eq!(
77+
config.domains.dogstatsd.origin.tag_cardinality,
78+
OriginTagCardinality::High
79+
);
80+
// Driven seconds(f64) -> Duration.
81+
assert_eq!(config.shared.tags.expected_tags_duration, Duration::from_secs_f64(15.0));
82+
// Assembled multi-key field: the primary endpoint carries the api key and the resolved URL
83+
// (`dd_url` takes precedence over `site`).
84+
let primary = &config.shared.endpoints.endpoints[0];
85+
assert_eq!(primary.api_keys, vec!["abc".to_string()]);
86+
assert_eq!(primary.url, "https://custom.example.com");
87+
// Seeded Saluki-only field.
88+
assert_eq!(config.domains.dogstatsd.listeners.tcp_port, 8126);
89+
}
90+
}

0 commit comments

Comments
 (0)