|
| 1 | +use crate::common::opamp::{ConfigResponse, FakeServer}; |
| 2 | +use crate::common::retry::retry; |
| 3 | +use crate::on_host::tools::instance_id::get_instance_id; |
| 4 | +use crate::on_host::tools::super_agent::start_super_agent_with_custom_config; |
| 5 | +use newrelic_super_agent::super_agent::config::{AgentID, SuperAgentDynamicConfig}; |
| 6 | +use newrelic_super_agent::super_agent::defaults::{set_local_dir, set_remote_dir}; |
| 7 | +use std::error::Error; |
| 8 | +use std::fs::File; |
| 9 | +use std::io::Write; |
| 10 | +use std::thread; |
| 11 | +use std::time::Duration; |
| 12 | +use tempfile::tempdir; |
| 13 | +use url::Url; |
| 14 | + |
| 15 | +#[cfg(unix)] |
| 16 | +#[test] |
| 17 | +fn onhost_opamp_superagent_configuration_change() { |
| 18 | + // Given a super-agent without agents and opamp configured. |
| 19 | + let mut server = FakeServer::start_new(); |
| 20 | + let server_endpoint = Url::try_from(server.endpoint().as_str()).unwrap(); |
| 21 | + |
| 22 | + let local_dir = tempdir().expect("failed to create local temp dir"); |
| 23 | + let remote_dir = tempdir().expect("failed to create remote temp dir"); |
| 24 | + |
| 25 | + set_local_dir(local_dir.path()); |
| 26 | + set_remote_dir(remote_dir.path()); |
| 27 | + |
| 28 | + let config_file_path = local_dir.path().join("config.yaml"); |
| 29 | + let mut local_file = |
| 30 | + File::create(config_file_path.clone()).expect("failed to create local config file"); |
| 31 | + let local_config = r#" |
| 32 | +host_id: integration-test |
| 33 | +fleet_id: integration |
| 34 | +opamp: |
| 35 | + endpoint: http://127.0.0.1/v1/opamp |
| 36 | +agents: {} |
| 37 | +"#; |
| 38 | + write!(local_file, "{}", local_config).unwrap(); |
| 39 | + |
| 40 | + // We won't join and wait for the thread to finish because we want the super_agent to exit |
| 41 | + // if our assertions were not ok. |
| 42 | + let _super_agent_join = thread::spawn(move || { |
| 43 | + start_super_agent_with_custom_config(config_file_path.as_path(), server_endpoint) |
| 44 | + }); |
| 45 | + |
| 46 | + let super_agent_instance_id = get_instance_id(&AgentID::new_super_agent_id()); |
| 47 | + |
| 48 | + // When a new config with two agents is received from OpAMP |
| 49 | + server.set_config_response( |
| 50 | + super_agent_instance_id, |
| 51 | + ConfigResponse::from( |
| 52 | + r#" |
| 53 | +agents: |
| 54 | + nr-infra-agent: |
| 55 | + agent_type: "newrelic/com.newrelic.infrastructure_agent:0.1.2" |
| 56 | + otel-collector: |
| 57 | + agent_type: "newrelic/io.opentelemetry.collector:0.0.1" |
| 58 | +"#, |
| 59 | + ), |
| 60 | + ); |
| 61 | + |
| 62 | + // Then the config should be updated in the remote filesystem. |
| 63 | + let expected_config = r#"agents: |
| 64 | + nr-infra-agent: |
| 65 | + agent_type: newrelic/com.newrelic.infrastructure_agent:0.1.2 |
| 66 | + otel-collector: |
| 67 | + agent_type: newrelic/io.opentelemetry.collector:0.0.1 |
| 68 | +"#; |
| 69 | + let expected_config_parsed = |
| 70 | + serde_yaml::from_str::<SuperAgentDynamicConfig>(expected_config).unwrap(); |
| 71 | + |
| 72 | + retry(20, Duration::from_secs(5), || { |
| 73 | + || -> Result<(), Box<dyn Error>> { |
| 74 | + let remote_file = remote_dir.path().join("config.yaml"); |
| 75 | + let content = |
| 76 | + std::fs::read_to_string(remote_file.as_path()).unwrap_or("agents:".to_string()); |
| 77 | + let content_parsed = |
| 78 | + serde_yaml::from_str::<SuperAgentDynamicConfig>(content.as_str()).unwrap(); |
| 79 | + if content_parsed != expected_config_parsed { |
| 80 | + return Err(format!( |
| 81 | + "Super agent config not as expected, Expected: {:?}, Found: {:?}", |
| 82 | + expected_config, content, |
| 83 | + ) |
| 84 | + .into()); |
| 85 | + } |
| 86 | + Ok(()) |
| 87 | + }() |
| 88 | + }); |
| 89 | + |
| 90 | + // TODO: Then OpAMP receives applied (& applying?) AgentToServer (check state on the server). |
| 91 | + // TODO: Then the two agent processes are running (we should create custom agent_types for custom binary). |
| 92 | +} |
0 commit comments