agent_data_plane_config_system/
env_provider.rs1use datadog_agent_config::apply_datadog_env;
20use figment::providers::Serialized;
21use figment::value::{Dict, Map};
22use figment::{Error, Metadata, Profile, Provider};
23use serde_json::Value;
24
25use crate::saluki_env_overlay;
26
27pub struct EnvironmentProvider {
32 values: Value,
33}
34
35impl EnvironmentProvider {
36 pub fn new() -> Result<Self, String> {
47 let mut values = Value::Object(serde_json::Map::new());
48
49 apply_datadog_env(&mut values, true)?;
52 saluki_env_overlay::apply_env(&mut values, true)?;
53
54 Ok(Self { values })
55 }
56}
57
58impl Provider for EnvironmentProvider {
59 fn metadata(&self) -> Metadata {
60 Metadata::named("Datadog and Saluki-only environment variables")
63 }
64
65 fn data(&self) -> Result<Map<Profile, Dict>, Error> {
66 Serialized::defaults(&self.values).data()
67 }
68}
69
70#[cfg(test)]
71mod tests {
72 use saluki_config::test_env_lock;
73
74 use super::*;
75
76 fn values_of(provider: &EnvironmentProvider) -> &Value {
77 &provider.values
78 }
79
80 #[test]
81 fn nested_datadog_key_lands_at_its_canonical_path() {
82 let _guard = test_env_lock();
83 std::env::set_var("DD_PROXY_HTTP", "http://proxy.example.com");
84
85 let provider = EnvironmentProvider::new().expect("environment reads");
86
87 std::env::remove_var("DD_PROXY_HTTP");
88 assert_eq!(
89 values_of(&provider).pointer("/proxy/http"),
90 Some(&Value::String("http://proxy.example.com".to_string()))
91 );
92 }
93
94 #[test]
95 fn canonical_proxy_variable_is_honored() {
96 let _guard = test_env_lock();
98 std::env::remove_var("DD_PROXY_HTTP");
99 std::env::set_var("HTTP_PROXY", "http://canonical.example.com");
100
101 let provider = EnvironmentProvider::new().expect("environment reads");
102
103 std::env::remove_var("HTTP_PROXY");
104 assert_eq!(
105 values_of(&provider).pointer("/proxy/http"),
106 Some(&Value::String("http://canonical.example.com".to_string()))
107 );
108 }
109
110 #[test]
111 fn saluki_only_key_lands_at_its_canonical_path() {
112 let _guard = test_env_lock();
113 std::env::set_var("DD_DATA_PLANE_STANDALONE_MODE", "true");
114
115 let provider = EnvironmentProvider::new().expect("environment reads");
116
117 std::env::remove_var("DD_DATA_PLANE_STANDALONE_MODE");
118 assert_eq!(
119 values_of(&provider).pointer("/data_plane/standalone_mode"),
120 Some(&Value::Bool(true))
121 );
122 }
123
124 #[test]
127 fn adp_zstd_override_reaches_its_nested_path() {
128 let _guard = test_env_lock();
129 std::env::set_var("DD_DATA_PLANE_SERIALIZER_ZSTD_COMPRESSOR_LEVEL", "7");
130
131 let provider = EnvironmentProvider::new().expect("environment reads");
132
133 std::env::remove_var("DD_DATA_PLANE_SERIALIZER_ZSTD_COMPRESSOR_LEVEL");
134 assert_eq!(
135 values_of(&provider).pointer("/data_plane/serializer_zstd_compressor_level"),
136 Some(&Value::Number(7.into()))
137 );
138 }
139
140 #[test]
141 fn unset_keys_contribute_nothing() {
142 let _guard = test_env_lock();
143 std::env::remove_var("DD_PROXY_HTTP");
144 std::env::remove_var("HTTP_PROXY");
145 std::env::remove_var("http_proxy");
146
147 let provider = EnvironmentProvider::new().expect("environment reads");
148
149 assert!(values_of(&provider).pointer("/proxy/http").is_none());
150 }
151
152 #[test]
153 fn a_malformed_value_is_rejected() {
154 let _guard = test_env_lock();
155 std::env::set_var("DD_DOGSTATSD_PORT", "not-a-number");
156
157 let result = EnvironmentProvider::new();
158
159 std::env::remove_var("DD_DOGSTATSD_PORT");
160 assert!(result.is_err());
161 }
162}