datadog_agent_config/
env_provider.rs1use figment::providers::Serialized;
14use figment::value::{Dict, Map};
15use figment::{Error, Metadata, Profile, Provider};
16use serde_json::Value;
17
18use crate::env_reader::{apply_datadog_env, apply_datadog_env_vars};
19
20pub struct DatadogEnvProvider {
25 values: Value,
26}
27
28impl DatadogEnvProvider {
29 pub fn new() -> Result<Self, String> {
39 Self::build(|values| apply_datadog_env(values, true))
40 }
41
42 pub fn from_env_vars(vars: Vec<(String, String)>) -> Result<Self, String> {
50 Self::build(|values| apply_datadog_env_vars(values, vars, true))
51 }
52
53 fn build(read: impl FnOnce(&mut Value) -> Result<(), String>) -> Result<Self, String> {
54 let mut values = Value::Object(serde_json::Map::new());
57 read(&mut values)?;
58 Ok(Self { values })
59 }
60}
61
62impl Provider for DatadogEnvProvider {
63 fn metadata(&self) -> Metadata {
64 Metadata::named("Datadog schema environment variables")
65 }
66
67 fn data(&self) -> Result<Map<Profile, Dict>, Error> {
68 Serialized::defaults(&self.values).data()
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75
76 #[test]
77 fn nested_key_lands_at_its_canonical_path() {
78 let provider = DatadogEnvProvider::from_env_vars(vec![(
79 "DD_PROXY_HTTP".to_string(),
80 "http://proxy.example.com".to_string(),
81 )])
82 .expect("environment reads");
83
84 assert_eq!(
85 provider.values.pointer("/proxy/http"),
86 Some(&Value::String("http://proxy.example.com".to_string()))
87 );
88 }
89
90 #[test]
91 fn canonical_proxy_variable_is_honored() {
92 let provider = DatadogEnvProvider::from_env_vars(vec![(
94 "HTTP_PROXY".to_string(),
95 "http://canonical.example.com".to_string(),
96 )])
97 .expect("environment reads");
98
99 assert_eq!(
100 provider.values.pointer("/proxy/http"),
101 Some(&Value::String("http://canonical.example.com".to_string()))
102 );
103 }
104
105 #[test]
106 fn a_value_is_decoded_into_the_shape_its_key_declares() {
107 let provider = DatadogEnvProvider::from_env_vars(vec![("DD_DOGSTATSD_PORT".to_string(), "9125".to_string())])
108 .expect("environment reads");
109
110 assert_eq!(provider.values.pointer("/dogstatsd_port"), Some(&Value::from(9125)));
111 }
112
113 #[test]
114 fn unset_keys_contribute_nothing() {
115 let provider = DatadogEnvProvider::from_env_vars(Vec::new()).expect("environment reads");
116 assert_eq!(provider.values, serde_json::json!({}));
117 }
118
119 #[test]
120 fn a_malformed_value_is_rejected() {
121 let result =
122 DatadogEnvProvider::from_env_vars(vec![("DD_DOGSTATSD_PORT".to_string(), "not-a-number".to_string())]);
123 assert!(result.is_err());
124 }
125}