Skip to content

Commit a3bf764

Browse files
feat: unify yamlconfig and hash and do not store hash if failed (#1299)
* feat: unify yamlconfig and hash in a new Remote Config values and don't store a failed hash. * feat: Modify LocalConfig enum to use custom type * feat: Modify update_hash method to upda_hash_state because a hash should never be updated, only the state * feat: Improve Update Hash state error message * feat: Correct wrong comment in config_repository * feat: Simplify loading a file if it's present for Config Repository File * feat: Remove hash apply and fail and call update_state from remote_config instead * feat: Rename yaml_config_repository tests file to match the code * feat: Rename opamp->RemoteConfig to opamp->OpampRemoteConfig to avoid collision and confusion with value's RemoteConfig * feat: Add new case and test when we receive an empty remote config that forces to use local but local fails. In that case the remote config should still be reported as applied. * feat: Return a reference in get_yaml_config * feat: Modify fmt for imports in agent_control * feat: parse remote before creating supervisor to be able to distinguish between a failed supervisor from remote or local * feat: Add effective config reporting for reset to local and stop old supervisor if resetting to local fails * feat: Add comments explaining error procedence
1 parent c842031 commit a3bf764

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1597
-1542
lines changed

agent-control/src/agent_control/agent_control.rs

Lines changed: 140 additions & 188 deletions
Large diffs are not rendered by default.

agent-control/src/agent_control/config.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use super::uptime_report::UptimeReportConfig;
44
use crate::http::config::ProxyConfig;
55
use crate::instrumentation::config::logs::config::LoggingConfig;
66
use crate::opamp::auth::config::AuthConfig;
7-
use crate::opamp::remote_config::RemoteConfigError;
7+
use crate::opamp::remote_config::OpampRemoteConfigError;
88
use crate::opamp::remote_config::validators::signature::validator::SignatureValidatorConfig;
99
use crate::values::yaml_config::YAMLConfig;
1010
use crate::{
@@ -61,14 +61,16 @@ pub enum AgentControlConfigError {
6161
Load(String),
6262
#[error("storing agent control config: `{0}`")]
6363
Store(String),
64+
#[error("updating agent control config: `{0}`")]
65+
Update(String),
6466
#[error("building source to parse environment variables: `{0}`")]
6567
ConfigError(#[from] config::ConfigError),
6668
#[error("sub agent configuration `{0}` not found")]
6769
SubAgentNotFound(String),
6870
#[error("configuration is not valid YAML: `{0}`")]
6971
InvalidYamlConfiguration(#[from] serde_yaml::Error),
7072
#[error("remote config error: `{0}`")]
71-
RemoteConfigError(#[from] RemoteConfigError),
73+
RemoteConfigError(#[from] OpampRemoteConfigError),
7274
#[error("remote config error: `{0}`")]
7375
IOError(#[from] std::io::Error),
7476
}

agent-control/src/agent_control/config_storer/loader_storer.rs

Lines changed: 38 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,35 @@
11
use crate::agent_control::config::{
22
AgentControlConfig, AgentControlConfigError, AgentControlDynamicConfig,
33
};
4-
use crate::values::yaml_config::YAMLConfig;
4+
use crate::opamp::remote_config::hash::{ConfigState, Hash};
5+
use crate::values::config::RemoteConfig;
56

67
/// AgentControlConfigLoader loads a whole AgentControlConfig
78
#[cfg_attr(test, mockall::automock)]
89
pub trait AgentControlConfigLoader {
910
fn load(&self) -> Result<AgentControlConfig, AgentControlConfigError>;
1011
}
1112

12-
/// AgentControlDynamicConfigStorer stores the dynamic part of the AgentControlConfig
13-
pub trait AgentControlDynamicConfigStorer {
14-
fn store(&self, config: &YAMLConfig) -> Result<(), AgentControlConfigError>;
13+
/// AgentControlRemoteConfigStorer stores a remote_config containing
14+
/// the dynamic part of the AgentControlConfig and the remote config hash and status
15+
pub trait AgentControlRemoteConfigStorer {
16+
fn store(&self, config: &RemoteConfig) -> Result<(), AgentControlConfigError>;
17+
}
18+
19+
/// AgentControlRemoteConfigHashUpdater stores the hash and status for a remote_config
20+
pub trait AgentControlRemoteConfigHashStateUpdater {
21+
fn update_hash_state(&self, state: &ConfigState) -> Result<(), AgentControlConfigError>;
22+
}
23+
24+
/// AgentControlRemoteConfigHashGetter retrieves the hash and status
25+
/// from the stored remote_config if exists
26+
pub trait AgentControlRemoteConfigHashGetter {
27+
fn get_hash(&self) -> Result<Option<Hash>, AgentControlConfigError>;
28+
}
29+
30+
/// AgentControlRemoteConfigDeleter deletes the dynamic part of the AgentControlConfig
31+
pub trait AgentControlRemoteConfigDeleter {
32+
fn delete(&self) -> Result<(), AgentControlConfigError>;
1533
}
1634

1735
/// AgentControlDynamicConfigLoader loads the dynamic part of the AgentControlConfig
@@ -20,34 +38,36 @@ pub trait AgentControlDynamicConfigLoader {
2038
fn load(&self) -> Result<AgentControlDynamicConfig, AgentControlConfigError>;
2139
}
2240

23-
/// AgentControlDynamicConfigDeleter deletes the dynamic part of the AgentControlConfig
24-
pub trait AgentControlDynamicConfigDeleter {
25-
fn delete(&self) -> Result<(), AgentControlConfigError>;
26-
}
27-
2841
#[cfg(test)]
2942
pub(crate) mod tests {
30-
use super::AgentControlConfigError;
3143
use super::{
32-
AgentControlDynamicConfigDeleter, AgentControlDynamicConfigLoader,
33-
AgentControlDynamicConfigStorer,
44+
AgentControlConfigError, AgentControlDynamicConfigLoader, AgentControlRemoteConfigDeleter,
45+
AgentControlRemoteConfigHashGetter, AgentControlRemoteConfigHashStateUpdater,
46+
AgentControlRemoteConfigStorer,
3447
};
3548
use crate::agent_control::config::AgentControlDynamicConfig;
36-
use crate::values::yaml_config::YAMLConfig;
49+
use crate::opamp::remote_config::hash::{ConfigState, Hash};
50+
use crate::values::config::RemoteConfig;
3751
use mockall::{mock, predicate};
3852

3953
mock! {
4054
pub AgentControlDynamicConfigStore {}
4155

42-
impl AgentControlDynamicConfigStorer for AgentControlDynamicConfigStore {
43-
fn store(&self, config: &YAMLConfig) -> Result<(), AgentControlConfigError>;
56+
impl AgentControlRemoteConfigStorer for AgentControlDynamicConfigStore {
57+
fn store(&self, config: &RemoteConfig) -> Result<(), AgentControlConfigError>;
4458
}
4559
impl AgentControlDynamicConfigLoader for AgentControlDynamicConfigStore {
4660
fn load(&self) -> Result<AgentControlDynamicConfig, AgentControlConfigError>;
4761
}
48-
impl AgentControlDynamicConfigDeleter for AgentControlDynamicConfigStore {
62+
impl AgentControlRemoteConfigDeleter for AgentControlDynamicConfigStore {
4963
fn delete(&self) -> Result<(), AgentControlConfigError>;
5064
}
65+
impl AgentControlRemoteConfigHashStateUpdater for AgentControlDynamicConfigStore {
66+
fn update_hash_state(&self, state: &ConfigState) -> Result<(), AgentControlConfigError>;
67+
}
68+
impl AgentControlRemoteConfigHashGetter for AgentControlDynamicConfigStore {
69+
fn get_hash(&self) -> Result<Option<Hash>, AgentControlConfigError>;
70+
}
5171
}
5272

5373
impl MockAgentControlDynamicConfigStore {
@@ -58,11 +78,10 @@ pub(crate) mod tests {
5878
.returning(move || Ok(sub_agents_config.clone()));
5979
}
6080

61-
pub fn should_store(&mut self, sub_agents_config: &AgentControlDynamicConfig) {
62-
let sub_agents_config: YAMLConfig = sub_agents_config.try_into().unwrap();
81+
pub fn should_store(&mut self, remote_config: RemoteConfig) {
6382
self.expect_store()
6483
.once()
65-
.with(predicate::eq(sub_agents_config))
84+
.with(predicate::eq(remote_config))
6685
.returning(move |_| Ok(()));
6786
}
6887
}

agent-control/src/agent_control/config_storer/store.rs

Lines changed: 57 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,23 @@ use crate::agent_control::config::{
33
AgentControlConfig, AgentControlConfigError, AgentControlDynamicConfig,
44
};
55
use crate::agent_control::config_storer::loader_storer::{
6-
AgentControlConfigLoader, AgentControlDynamicConfigDeleter, AgentControlDynamicConfigLoader,
7-
AgentControlDynamicConfigStorer,
6+
AgentControlConfigLoader, AgentControlDynamicConfigLoader, AgentControlRemoteConfigDeleter,
7+
AgentControlRemoteConfigHashGetter, AgentControlRemoteConfigHashStateUpdater,
8+
AgentControlRemoteConfigStorer,
89
};
910
use crate::agent_control::defaults::{AGENT_CONTROL_CONFIG_ENV_VAR_PREFIX, default_capabilities};
10-
use crate::values::yaml_config::{YAMLConfig, YAMLConfigError};
11-
use crate::values::yaml_config_repository::{YAMLConfigRepository, YAMLConfigRepositoryError};
11+
use crate::opamp::remote_config::hash::{ConfigState, Hash};
12+
use crate::values::config::RemoteConfig;
13+
use crate::values::config_repository::{ConfigRepository, ConfigRepositoryError};
14+
use crate::values::yaml_config::YAMLConfigError;
1215
use config::builder::DefaultState;
1316
use config::{Config, ConfigBuilder, Environment, File, FileFormat};
1417
use opamp_client::operation::capabilities::Capabilities;
1518
use std::sync::Arc;
1619

1720
pub struct AgentControlConfigStore<Y>
1821
where
19-
Y: YAMLConfigRepository,
22+
Y: ConfigRepository,
2023
{
2124
config_builder: ConfigBuilder<DefaultState>,
2225
values_repository: Arc<Y>,
@@ -26,7 +29,7 @@ where
2629

2730
impl<Y> AgentControlConfigLoader for AgentControlConfigStore<Y>
2831
where
29-
Y: YAMLConfigRepository,
32+
Y: ConfigRepository,
3033
{
3134
fn load(&self) -> Result<AgentControlConfig, AgentControlConfigError> {
3235
self._load_config()
@@ -35,16 +38,16 @@ where
3538

3639
impl<Y> AgentControlDynamicConfigLoader for AgentControlConfigStore<Y>
3740
where
38-
Y: YAMLConfigRepository,
41+
Y: ConfigRepository,
3942
{
4043
fn load(&self) -> Result<AgentControlDynamicConfig, AgentControlConfigError> {
4144
Ok(self._load_config()?.dynamic)
4245
}
4346
}
4447

45-
impl<Y> AgentControlDynamicConfigDeleter for AgentControlConfigStore<Y>
48+
impl<Y> AgentControlRemoteConfigDeleter for AgentControlConfigStore<Y>
4649
where
47-
Y: YAMLConfigRepository,
50+
Y: ConfigRepository,
4851
{
4952
fn delete(&self) -> Result<(), AgentControlConfigError> {
5053
self.values_repository
@@ -53,20 +56,40 @@ where
5356
}
5457
}
5558

56-
impl<Y> AgentControlDynamicConfigStorer for AgentControlConfigStore<Y>
59+
impl<Y> AgentControlRemoteConfigStorer for AgentControlConfigStore<Y>
5760
where
58-
Y: YAMLConfigRepository,
61+
Y: ConfigRepository,
5962
{
60-
fn store(&self, yaml_config: &YAMLConfig) -> Result<(), AgentControlConfigError> {
63+
fn store(&self, config: &RemoteConfig) -> Result<(), AgentControlConfigError> {
6164
self.values_repository
62-
.store_remote(&self.agent_control_id, yaml_config)?;
65+
.store_remote(&self.agent_control_id, config)?;
6366
Ok(())
6467
}
6568
}
6669

70+
impl<Y> AgentControlRemoteConfigHashStateUpdater for AgentControlConfigStore<Y>
71+
where
72+
Y: ConfigRepository,
73+
{
74+
fn update_hash_state(&self, state: &ConfigState) -> Result<(), AgentControlConfigError> {
75+
self.values_repository
76+
.update_hash_state(&self.agent_control_id, state)?;
77+
Ok(())
78+
}
79+
}
80+
81+
impl<Y> AgentControlRemoteConfigHashGetter for AgentControlConfigStore<Y>
82+
where
83+
Y: ConfigRepository,
84+
{
85+
fn get_hash(&self) -> Result<Option<Hash>, AgentControlConfigError> {
86+
Ok(self.values_repository.get_hash(&self.agent_control_id)?)
87+
}
88+
}
89+
6790
impl<V> AgentControlConfigStore<V>
6891
where
69-
V: YAMLConfigRepository,
92+
V: ConfigRepository,
7093
{
7194
pub fn new(values_repository: Arc<V>) -> Self {
7295
let config_builder = Config::builder();
@@ -89,6 +112,8 @@ where
89112
.ok_or(AgentControlConfigError::Load(
90113
"missing local agent control config".to_string(),
91114
))?
115+
.get_yaml_config()
116+
.clone()
92117
.try_into()
93118
.map_err(|e: YAMLConfigError| AgentControlConfigError::Load(e.to_string()))?;
94119

@@ -114,20 +139,22 @@ where
114139
.values_repository
115140
.load_remote(&self.agent_control_id, &self.agent_control_capabilities)?
116141
{
117-
let dynamic_config: AgentControlDynamicConfig = remote_config.try_into()?;
142+
let dynamic_config: AgentControlDynamicConfig =
143+
remote_config.get_yaml_config().clone().try_into()?;
118144
config.dynamic = dynamic_config;
119145
}
120146

121147
Ok(config)
122148
}
123149
}
124150

125-
impl From<YAMLConfigRepositoryError> for AgentControlConfigError {
126-
fn from(e: YAMLConfigRepositoryError) -> Self {
151+
impl From<ConfigRepositoryError> for AgentControlConfigError {
152+
fn from(e: ConfigRepositoryError) -> Self {
127153
match e {
128-
YAMLConfigRepositoryError::LoadError(e) => AgentControlConfigError::Load(e),
129-
YAMLConfigRepositoryError::StoreError(e) => AgentControlConfigError::Store(e),
130-
YAMLConfigRepositoryError::DeleteError(e) => AgentControlConfigError::Delete(e),
154+
ConfigRepositoryError::LoadError(e) => AgentControlConfigError::Load(e),
155+
ConfigRepositoryError::StoreError(e) => AgentControlConfigError::Store(e),
156+
ConfigRepositoryError::DeleteError(e) => AgentControlConfigError::Delete(e),
157+
ConfigRepositoryError::UpdateHashStateError(e) => AgentControlConfigError::Update(e),
131158
}
132159
}
133160
}
@@ -138,7 +165,7 @@ pub(crate) mod tests {
138165
use crate::agent_control::config::{AgentControlConfig, OpAMPClientConfig, SubAgentConfig};
139166
use crate::agent_control::defaults::AGENT_CONTROL_CONFIG_FILENAME;
140167
use crate::agent_type::agent_type_id::AgentTypeID;
141-
use crate::values::file::YAMLConfigRepositoryFile;
168+
use crate::values::file::ConfigRepositoryFile;
142169
use serial_test::serial;
143170
use std::path::PathBuf;
144171
use std::{collections::HashMap, env};
@@ -162,13 +189,16 @@ fleet_control:
162189
let remote_file = remote_dir.join(AGENT_CONTROL_CONFIG_FILENAME);
163190

164191
let remote_config = r#"
165-
agents:
166-
rolldice:
167-
agent_type: "namespace/com.newrelic.infrastructure:0.0.2"
192+
config:
193+
agents:
194+
rolldice:
195+
agent_type: "namespace/com.newrelic.infrastructure:0.0.2"
196+
hash: a-hash
197+
state: applying
168198
"#;
169199
std::fs::write(remote_file.as_path(), remote_config).unwrap();
170200

171-
let vr = YAMLConfigRepositoryFile::new(local_dir, remote_dir).with_remote();
201+
let vr = ConfigRepositoryFile::new(local_dir, remote_dir).with_remote();
172202
let store = AgentControlConfigStore::new(Arc::new(vr));
173203
let actual = AgentControlConfigLoader::load(&store).unwrap();
174204

@@ -215,7 +245,7 @@ fleet_control:
215245
let env_var_name = "NR_AC_AGENTS__ROLLDICE1__AGENT_TYPE";
216246
unsafe { env::set_var(env_var_name, "namespace/com.newrelic.infrastructure:0.0.2") };
217247

218-
let vr = YAMLConfigRepositoryFile::new(local_dir, PathBuf::new()).with_remote();
248+
let vr = ConfigRepositoryFile::new(local_dir, PathBuf::new()).with_remote();
219249
let store = AgentControlConfigStore::new(Arc::new(vr));
220250
let actual = AgentControlConfigLoader::load(&store).unwrap();
221251

@@ -264,7 +294,7 @@ agents:
264294
let env_var_name = "NR_AC_AGENTS__ROLLDICE2__AGENT_TYPE";
265295
unsafe { env::set_var(env_var_name, "namespace/com.newrelic.infrastructure:0.0.2") };
266296

267-
let vr = YAMLConfigRepositoryFile::new(local_dir, PathBuf::new()).with_remote();
297+
let vr = ConfigRepositoryFile::new(local_dir, PathBuf::new()).with_remote();
268298
let store = AgentControlConfigStore::new(Arc::new(vr));
269299
let actual: AgentControlConfig = AgentControlConfigLoader::load(&store).unwrap();
270300

agent-control/src/agent_control/error.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,14 @@ use crate::agent_type::error::AgentTypeError;
66
use crate::agent_type::render::persister::config_persister::PersistError;
77
use crate::event::channel::EventPublisherError;
88
use crate::opamp::client_builder::OpAMPClientBuilderError;
9-
use crate::opamp::hash_repository::repository::HashRepositoryError;
109
use crate::opamp::instance_id;
1110

1211
use crate::opamp::instance_id::on_host::getter::IdentifiersProviderError;
13-
use crate::opamp::remote_config::RemoteConfigError;
12+
use crate::opamp::remote_config::OpampRemoteConfigError;
1413
use crate::sub_agent::effective_agents_assembler::EffectiveAgentsAssemblerError;
1514
use crate::sub_agent::error::{SubAgentBuilderError, SubAgentCollectionError, SubAgentError};
15+
use crate::values::config_repository::ConfigRepositoryError;
1616
use crate::values::yaml_config::YAMLConfigError;
17-
use crate::values::yaml_config_repository::YAMLConfigRepositoryError;
1817
use fs::file_reader::FileReaderError;
1918
use opamp_client::{ClientError, NotStartedClientError, StartedClientError};
2019
use std::fmt::Debug;
@@ -71,17 +70,14 @@ pub enum AgentError {
7170
#[error("system time error: `{0}`")]
7271
SystemTime(#[from] SystemTimeError),
7372

74-
#[error("remote config hash error: `{0}`")]
75-
RemoteConfigHash(#[from] HashRepositoryError),
76-
7773
#[error("effective agents assembler error: `{0}`")]
7874
EffectiveAgentsAssembler(#[from] EffectiveAgentsAssemblerError),
7975

8076
#[error("remote config error: `{0}`")]
81-
RemoteConfig(#[from] RemoteConfigError),
77+
RemoteConfig(#[from] OpampRemoteConfigError),
8278

8379
#[error("sub agent remote config error: `{0}`")]
84-
SubAgentRemoteConfig(#[from] YAMLConfigRepositoryError),
80+
SubAgentRemoteConfig(#[from] ConfigRepositoryError),
8581

8682
#[error("External module error: `{0}`")]
8783
ExternalError(String),

0 commit comments

Comments
 (0)