Skip to content

Commit 97736fd

Browse files
feat: support split remote config on agents (NR-490636) (#1902)
* feat: support split remote config on agents * review * improve doc * nits
1 parent 3427eb8 commit 97736fd

File tree

9 files changed

+243
-70
lines changed

9 files changed

+243
-70
lines changed

agent-control/src/agent_control.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -598,9 +598,7 @@ mod tests {
598598
use crate::opamp::client_builder::tests::MockStartedOpAMPClient;
599599
use crate::opamp::remote_config::hash::{ConfigState, Hash};
600600
use crate::opamp::remote_config::validators::tests::TestRemoteConfigValidator;
601-
use crate::opamp::remote_config::{
602-
ConfigurationMap, DEFAULT_AGENT_CONFIG_IDENTIFIER, OpampRemoteConfig,
603-
};
601+
use crate::opamp::remote_config::{AGENT_CONFIG_PREFIX, ConfigurationMap, OpampRemoteConfig};
604602
use crate::sub_agent::collection::StartedSubAgents;
605603
use crate::sub_agent::error::SubAgentBuilderError;
606604
use crate::sub_agent::identity::AgentIdentity;
@@ -725,7 +723,7 @@ agents:
725723
hash,
726724
ConfigState::Applying,
727725
ConfigurationMap::new(HashMap::from([(
728-
DEFAULT_AGENT_CONFIG_IDENTIFIER.to_string(),
726+
AGENT_CONFIG_PREFIX.to_string(),
729727
s.to_string(),
730728
)])),
731729
)

agent-control/src/opamp/callbacks.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -264,9 +264,7 @@ pub(crate) mod tests {
264264
use crate::opamp::remote_config::signature::{
265265
ED25519, SIGNATURE_CUSTOM_CAPABILITY, SIGNATURE_CUSTOM_MESSAGE_TYPE,
266266
};
267-
use crate::opamp::remote_config::{
268-
ConfigurationMap, DEFAULT_AGENT_CONFIG_IDENTIFIER, OpampRemoteConfig,
269-
};
267+
use crate::opamp::remote_config::{AGENT_CONFIG_PREFIX, ConfigurationMap, OpampRemoteConfig};
270268
use opamp_client::opamp::proto::{AgentConfigFile, AgentConfigMap, AgentRemoteConfig};
271269
use std::collections::HashMap;
272270
use std::time::Duration;
@@ -340,15 +338,15 @@ pub(crate) mod tests {
340338
let (valid_remote_config_map, expected_remote_config_map) = (
341339
AgentConfigMap {
342340
config_map: HashMap::from([(
343-
DEFAULT_AGENT_CONFIG_IDENTIFIER.to_string(),
341+
AGENT_CONFIG_PREFIX.to_string(),
344342
AgentConfigFile {
345343
body: "enable_proces_metrics: true".as_bytes().to_vec(),
346344
content_type: "".to_string(),
347345
},
348346
)]),
349347
},
350348
ConfigurationMap::new(HashMap::from([(
351-
DEFAULT_AGENT_CONFIG_IDENTIFIER.to_string(),
349+
AGENT_CONFIG_PREFIX.to_string(),
352350
"enable_proces_metrics: true".to_string(),
353351
)])),
354352
);
@@ -493,7 +491,7 @@ pub(crate) mod tests {
493491
capability: SIGNATURE_CUSTOM_CAPABILITY.to_string(),
494492
r#type: SIGNATURE_CUSTOM_MESSAGE_TYPE.to_string(),
495493
data: serde_json::json!({
496-
DEFAULT_AGENT_CONFIG_IDENTIFIER: [{
494+
AGENT_CONFIG_PREFIX: [{
497495
"signature": "fake config",
498496
"signingAlgorithm": "ED25519",
499497
"keyId": "fake keyid"
@@ -508,7 +506,7 @@ pub(crate) mod tests {
508506
expected_remote_config_config_map: expected_remote_config_map.clone(),
509507
expected_remote_config_hash: Hash::from(valid_hash),
510508
expected_remote_config_state: ConfigState::Applying,
511-
expected_signature: Some(Signatures::new_default(DEFAULT_AGENT_CONFIG_IDENTIFIER,
509+
expected_signature: Some(Signatures::new_default(AGENT_CONFIG_PREFIX,
512510
"fake config",
513511
ED25519,
514512
"fake keyid",

agent-control/src/opamp/remote_config.rs

Lines changed: 60 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ pub mod report;
1212
pub mod signature;
1313
pub mod validators;
1414

15-
/// Identifier key for the primary agent configuration within the OpAMP [opamp_client::opamp::proto::AgentConfigMap].
16-
pub const DEFAULT_AGENT_CONFIG_IDENTIFIER: &str = "agentConfig";
15+
/// Prefix that identifies the agent configuration keys within the OpAMP [opamp_client::opamp::proto::AgentConfigMap].
16+
/// Any key that starts with this prefix is considered part of the agent configuration. See parsing implementation
17+
/// for each case.
18+
pub const AGENT_CONFIG_PREFIX: &str = "agentConfig";
1719

1820
/// This structure represents the remote configuration that we would retrieve from a server via OpAMP.
1921
/// Contains identifying metadata and the actual configuration values
@@ -59,16 +61,24 @@ impl OpampRemoteConfig {
5961
}
6062
}
6163

62-
/// Get all configuration values
63-
pub fn configs(&self) -> &ConfigurationMap {
64-
&self.config_map
64+
/// Returns an iterator over the configuration key-value pairs.
65+
pub fn configs_iter(&self) -> impl Iterator<Item = (&String, &String)> {
66+
self.config_map.0.iter()
67+
}
68+
69+
/// Returns an iterator over the configuration key-value pairs that start with [AGENT_CONFIG_PREFIX].
70+
pub fn agent_configs_iter(&self) -> impl Iterator<Item = (&String, &String)> {
71+
self.config_map
72+
.0
73+
.iter()
74+
.filter(|(k, _)| k.starts_with(AGENT_CONFIG_PREFIX))
6575
}
6676

6777
/// Get configuration value at the
6878
pub fn get_default(&self) -> Result<&str, OpampRemoteConfigError> {
6979
self.config_map
7080
.0
71-
.get(DEFAULT_AGENT_CONFIG_IDENTIFIER)
81+
.get(AGENT_CONFIG_PREFIX)
7282
.map(|s| s.as_str())
7383
.ok_or(OpampRemoteConfigError::InvalidConfig(
7484
self.hash.to_string(),
@@ -142,3 +152,47 @@ impl From<ConfigurationMap> for EffectiveConfig {
142152
Self { config_map }
143153
}
144154
}
155+
156+
#[cfg(test)]
157+
mod tests {
158+
use super::*;
159+
use rstest::rstest;
160+
161+
#[rstest]
162+
#[case::single_agent_config(
163+
r#"{"agentConfig": "key: value"}"#,
164+
r#"{"agentConfig": "key: value"}"#
165+
)]
166+
#[case::multiple_agent_configs(
167+
r#"{"agentConfig": "key1: value1", "agentConfig2": "key2: value2"}"#,
168+
r#"{"agentConfig": "key1: value1", "agentConfig2": "key2: value2"}"#
169+
)]
170+
#[case::mixed_configs_filters_non_agent(
171+
r#"{"agentConfig": "key1: value1", "otherConfig": "key2: value2", "agentConfig3": "key3: value3"}"#,
172+
r#"{"agentConfig": "key1: value1", "agentConfig3": "key3: value3"}"#
173+
)]
174+
#[case::no_agent_configs(
175+
r#"{"otherConfig": "key1: value1", "someConfig": "key2: value2"}"#,
176+
r#"{}"#
177+
)]
178+
fn test_agent_configs_iter(#[case] config_json: &str, #[case] expected_json: &str) {
179+
let agent_id = AgentID::try_from("test-agent").unwrap();
180+
let hash = Hash::from("some-hash");
181+
let state = ConfigState::Applying;
182+
let config_map = ConfigurationMap::new(
183+
serde_json::from_str::<HashMap<String, String>>(config_json).unwrap(),
184+
);
185+
let opamp_config = OpampRemoteConfig::new(agent_id, hash, state, config_map);
186+
187+
let result: HashMap<&String, &String> = opamp_config.agent_configs_iter().collect();
188+
let expected: HashMap<String, String> = serde_json::from_str(expected_json).unwrap();
189+
190+
assert_eq!(result.len(), expected.len());
191+
for (expected_key, expected_value) in &expected {
192+
assert_eq!(
193+
result.get(expected_key).map(|v| v.as_str()),
194+
Some(expected_value.as_str())
195+
);
196+
}
197+
}
198+
}

agent-control/src/opamp/remote_config/validators/regexes.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,7 @@ impl RemoteConfigValidator for RegexValidator {
3737
) -> Result<(), RegexValidatorError> {
3838
// This config will fail further on the event processor.
3939
opamp_remote_config
40-
.configs()
41-
.0
42-
.iter()
40+
.agent_configs_iter()
4341
.try_for_each(|(_, raw_config)| {
4442
self.validate_regex_rules(&agent_identity.agent_type_id, raw_config)
4543
})?;
@@ -147,7 +145,7 @@ pub(super) mod tests {
147145
use crate::agent_control::defaults::AGENT_TYPE_NAME_INFRA_AGENT;
148146
use crate::agent_control::defaults::AGENT_TYPE_NAME_NRDOT;
149147
use crate::agent_type::agent_type_id::AgentTypeID;
150-
use crate::opamp::remote_config::DEFAULT_AGENT_CONFIG_IDENTIFIER;
148+
use crate::opamp::remote_config::AGENT_CONFIG_PREFIX;
151149
use crate::opamp::remote_config::hash::{ConfigState, Hash};
152150
use crate::opamp::remote_config::validators::RemoteConfigValidator;
153151
use crate::opamp::remote_config::validators::regexes::{RegexValidator, RegexValidatorError};
@@ -197,7 +195,7 @@ pub(super) mod tests {
197195
Hash::from("this-is-a-hash"),
198196
ConfigState::Applying,
199197
ConfigurationMap::new(HashMap::from([(
200-
DEFAULT_AGENT_CONFIG_IDENTIFIER.to_string(),
198+
AGENT_CONFIG_PREFIX.to_string(),
201199
content.to_string(),
202200
)])),
203201
);
@@ -509,7 +507,7 @@ config:
509507
Hash::from("this-is-a-hash"),
510508
ConfigState::Applying,
511509
ConfigurationMap::new(HashMap::from([(
512-
DEFAULT_AGENT_CONFIG_IDENTIFIER.to_string(),
510+
AGENT_CONFIG_PREFIX.to_string(),
513511
config.to_string(),
514512
)])),
515513
)

agent-control/src/opamp/remote_config/validators/signature/validator.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ impl RemoteConfigValidator for SignatureValidator {
111111
};
112112

113113
// Iterate over all remote configs and verify signatures
114-
for (config_name, config_content) in opamp_remote_config.configs().0.iter() {
114+
for (config_name, config_content) in opamp_remote_config.configs_iter() {
115115
let signature = opamp_remote_config.signature(config_name).map_err(|e| {
116116
SignatureValidatorError::VerifySignature(format!(
117117
"getting signature for config '{}' config signature: {}",

agent-control/src/sub_agent.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -732,9 +732,7 @@ pub mod tests {
732732
use crate::opamp::client_builder::tests::MockStartedOpAMPClient;
733733
use crate::opamp::remote_config::hash::Hash;
734734
use crate::opamp::remote_config::validators::tests::MockRemoteConfigValidator;
735-
use crate::opamp::remote_config::{
736-
ConfigurationMap, DEFAULT_AGENT_CONFIG_IDENTIFIER, OpampRemoteConfig,
737-
};
735+
use crate::opamp::remote_config::{AGENT_CONFIG_PREFIX, ConfigurationMap, OpampRemoteConfig};
738736
use crate::secrets_provider::SecretsProviders;
739737
use crate::values::config::RemoteConfig;
740738
use crate::values::config_repository::tests::InMemoryConfigRepository;
@@ -955,7 +953,7 @@ deployment:
955953
Self::hash(),
956954
ConfigState::Applying,
957955
ConfigurationMap::new(HashMap::from([(
958-
DEFAULT_AGENT_CONFIG_IDENTIFIER.to_string(),
956+
AGENT_CONFIG_PREFIX.to_string(),
959957
Self::valid_config_yaml().try_into().unwrap(),
960958
)])),
961959
)
@@ -967,7 +965,7 @@ deployment:
967965
Self::hash(),
968966
ConfigState::Applying,
969967
ConfigurationMap::new(HashMap::from([(
970-
DEFAULT_AGENT_CONFIG_IDENTIFIER.to_string(),
968+
AGENT_CONFIG_PREFIX.to_string(),
971969
// Reset signal
972970
"".to_string(),
973971
)])),
@@ -982,7 +980,7 @@ deployment:
982980
error_message: "error_message".to_string(),
983981
},
984982
ConfigurationMap::new(HashMap::from([(
985-
DEFAULT_AGENT_CONFIG_IDENTIFIER.to_string(),
983+
AGENT_CONFIG_PREFIX.to_string(),
986984
"broken config:".to_string(),
987985
)])),
988986
)

0 commit comments

Comments
 (0)