Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/component_onhost_e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ permissions:
env:
HOST_E2E_INFRA_AGENT_VERSION: "1.74.3"
HOST_E2E_NRDOT_VERSION: "1.14.0"
HOST_E2E_PRELOAD_VERSION: "0.1.0"

jobs:
build-packages:
Expand All @@ -53,6 +54,7 @@ jobs:
- infra-agent
- nrdot-agent
- proxy
- preload-agent
steps:
- name: Record job start time
run: echo "JOB_START_TIME=$(date +%s)" >> "$GITHUB_ENV"
Expand All @@ -79,7 +81,8 @@ jobs:
--agent-control-version "0.900.${{ github.run_id }}" \
--recipes-repo-branch "main" \
--infra-agent-version "${{ env.HOST_E2E_INFRA_AGENT_VERSION }}" \
--nrdot-version "${{ env.HOST_E2E_NRDOT_VERSION }}"
--nrdot-version "${{ env.HOST_E2E_NRDOT_VERSION }}" \
--preload-version "${{ env.HOST_E2E_PRELOAD_VERSION }}"

- name: Report test result to New Relic
if: always()
Expand Down

This file was deleted.

2 changes: 2 additions & 0 deletions test/e2e-runner/src/linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ pub fn local_config_path(agent_id: &str) -> String {

const DEFAULT_LOG_PATH: &str = "/var/log/newrelic-agent-control/agent-control/";

pub const AGENT_CONTROL_DATA_DIR: &str = "/var/lib/newrelic-agent-control";

const SERVICE_NAME: &str = "newrelic-agent-control";

/// Run Linux e2e corresponding scenario which will panic on failure
Expand Down
122 changes: 90 additions & 32 deletions test/e2e-runner/src/linux/scenarios/preload_agent.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,33 @@
use crate::common::config::{DEBUG_LOGGING_CONFIG, update_config, write_agent_local_config};
use crate::common::file::write;
use crate::common::on_drop::CleanUp;
use crate::common::test::{TestResult, retry_panic};
use crate::common::{InstallationArgs, RecipeData};
use crate::{
linux::{
self,
install::{install_agent_control_from_recipe, tear_down_test},
bash::exec_bash_command
},
use crate::linux::{
self,
bash::exec_bash_command,
install::{install_agent_control_from_recipe, tear_down_test},
};
use glob::glob;
use std::time::Duration;
use tracing::{debug, info};

/// Directory where Agent Control loads dynamic (custom) agent type definitions.
const DYNAMIC_AGENT_TYPES_DIR: &str = "/etc/newrelic-agent-control/dynamic-agent-types";

/// Expected package installation directory for the preload agent.
fn preload_package_dir() -> String {
format!(
"{}/packages/nr-preload/stored_packages/preload-agent",
linux::AGENT_CONTROL_DATA_DIR
)
}

pub fn test_installation_with_preload_agent(args: InstallationArgs) {
let preload_version = args
.preload_version
.clone()
.expect("--preload-agent-version is required for this scenario");

let staging = matches!(args.nr_region.to_lowercase().as_str(), "staging");
.expect("--preload-version is required for this scenario");

let recipe_data = RecipeData {
args,
Expand All @@ -35,6 +46,40 @@ pub fn test_installation_with_preload_agent(args: InstallationArgs) {

let preload_agent_id = "nr-preload";

info!("Writing custom preload agent type definition");
let custom_agent_type_path = format!("{DYNAMIC_AGENT_TYPES_DIR}/preload.yaml");
let custom_agent_type = r#"namespace: newrelic

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude found this issue:

🔴 Bug: ${{ ... }} won't be substituted by Agent Control

test/e2e-runner/src/linux/scenarios/preload_agent.rs:50-77 — the YAML is a plain r#"..."# raw string, not a format! template, so the doubled braces are not escapes — they end up literally in the file:

repository: ${{nr-var:oci.repository}}
version: ${{nr-var:version}}

Compare with agent-control/tests/on_host/scenarios/oci_auth.rs:43-54, where ${{...}} is inside format!(...) and correctly resolves to ${...}. AC's template engine expects the single-brace form
(${nr-var:version}), so the inlined agent type will fail to resolve version and the OCI download won't get a valid tag.

Fix: use single braces (${nr-var:...}) since this is a raw string, or wrap the literal in format! if you want to keep the doubled form for visual consistency with the other tests.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed e91cd32

name: com.newrelic.preload
version: 0.1.0
variables:
linux:
oci:
repository:
description: "Package repository name"
type: string
required: false
default: newrelic/preload-agent-artifacts
variants:
ac_config_field: "oci_repository_urls"
values: ["newrelic/preload-agent-artifacts"]
version:
description: "Agent version"
type: string
required: true
deployment:
linux:
packages:
preload-agent:
download:
oci:
repository: ${nr-var:oci.repository}
version: ${nr-var:version}
public_key_url: https://publickeys.newrelic.com/g/agent-control-oci/global/nrpreloadagent/jwks.json
"#;
exec_bash_command(&format!("mkdir -p {DYNAMIC_AGENT_TYPES_DIR}"))
.unwrap_or_else(|err| panic!("Failed to create dynamic agent types directory: {err}"));
write(&custom_agent_type_path, custom_agent_type);

info!("Setup Agent Control config");
update_config(
linux::DEFAULT_AC_CONFIG_PATH,
Expand All @@ -51,35 +96,48 @@ agents:

write_agent_local_config(
&linux::local_config_path(preload_agent_id),
// Correct Config?
format! {r#"
fleet_id: alphanumeric_id # needed anymore?
apm_language: java
agent_version: 8.13.0
application_names:
- my-app
- functions
- lib
- bin
new_relic_license_key: '{{{{NEW_RELIC_LICENSE_KEY}}}}'
staging: {staging}
version: {preload_version}"#},
version: {preload_version}"#},
);

linux::service::restart_service(linux::SERVICE_NAME);

// ToDo update with actual path
let ld_preload_path = "path_to_ld_preload";
let install_command = format!(r#"echo "{ld_preload_path}" >> /ec/ld.so.preload"#);
let output = exec_bash_command(&install_command)
.unwrap_or_else(|err| panic!("Editing /ec/ld.so.preload failed: {err}"));
debug!("echo output:\n{output}");
info!("Waiting for preload OCI package to be downloaded and extracted");
let package_dir = preload_package_dir();
let retries = 60;
retry_panic(
retries,
Duration::from_secs(10),
"preload package download assertion",
|| assert_preload_package_downloaded(&package_dir),
);

linux::service::restart_service(linux::SERVICE_NAME);
info!("Searching for shared library inside extracted package");
let so_path = glob(&format!("{package_dir}/**/*.so"))
.expect("Failed to read glob pattern")
.find_map(|entry| entry.ok())
.map(|path| path.to_string_lossy().into_owned())
.unwrap_or_default();
if so_path.is_empty() {
panic!("No .so file found in extracted preload package at {package_dir}");
}
info!("Found shared library: {so_path}");

let ls_command = format!("ls {ld_preload_path}");
let output = exec_bash_command(&ls_command)
.unwrap_or_else(|err| panic!("Installation failed: {err}"));
debug!("ls output:\n{output}");
info!("Installing shared library into /etc/ld.so.preload");
let install_command = format!(r#"echo "{so_path}" >> /etc/ld.so.preload"#);
let output = exec_bash_command(&install_command)
.unwrap_or_else(|err| panic!("Editing /etc/ld.so.preload failed: {err}"));
debug!("Install output:\n{output}");

info!("Test completed successfully");
}

fn assert_preload_package_downloaded(package_dir: &str) -> TestResult<()> {
let output = exec_bash_command(&format!("ls -d {package_dir}"))?;
if output.contains("No such file") || output.contains("cannot access") {
return Err(format!("Preload package directory not found yet at {package_dir}").into());
}
let listing = exec_bash_command(&format!("ls -la {package_dir}"))?;
debug!("Package listing:\n{listing}");
Ok(())
}
3 changes: 2 additions & 1 deletion test/e2e-runner/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ enum LinuxScenarios {
EBPFAgent(InstallationArgs),
/// Local installation of Agent Control with NRDot. It checks that nr-dot eventually reports data.
NrdotAgent(InstallationArgs),
/// Local installation of Agent Control with Preload Agent. It checks that the preload-agent eventually reports data.
/// Local installation of Agent Control with a custom preload agent type. Verifies that the
/// OCI artifact is downloaded and present in the environment.
PreloadAgent(InstallationArgs),
/// Checks that remote configuration for a sub-agent has been applied.
RemoteConfig(InstallationArgs),
Expand Down
Loading