Skip to content

Commit 0e9708a

Browse files
nr-ahemsathclaudepranav-new-relic
authored
test: Add Windows Server 2022 and 2025 test definitions for the .NET agent (#1384)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: pranav-new-relic <pnandula@newrelic.com>
1 parent 8760c37 commit 0e9708a

19 files changed

Lines changed: 700 additions & 40 deletions
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
# Design: Modernize .NET APM Agent Linux Test Definitions
2+
3+
**Date:** 2026-06-25
4+
**Branch:** `chore/update-dotnet-agent-test-definitions-linux`
5+
**Status:** Approved (design); pending implementation plan
6+
7+
## Problem
8+
9+
The three existing test definitions that validate the New Relic .NET APM agent on
10+
Linux all target end-of-life or near-EOL software at multiple layers:
11+
12+
| File | Region | Distro | Runtime installed | App artifact | Agent validation |
13+
|---|---|---|---|---|---|
14+
| `test/definitions/apm/dotNet/linux/linux2-aspnetcore5.json` | US | Amazon Linux 2 (EOL ~2026-06) | .NET SDK 7.0 + ASP.NET Core 7.0 via **CentOS 7 RPM** (7.0 EOL) | `net5webapplication` (.NET 5, EOL 2022-05) | **none — no `instrumentations` block** |
15+
| `test/definitions-eu/apm/dotNet/linux/ubuntu20-apache-aspnetcore.json` | EU | Ubuntu 20.04 Focal (standard support ended 2025-04) | ASP.NET Core 8.0 | `net5webapplication` | infra + `apm/dotNet/linux-systemd` |
16+
| `test/definitions-jp/apm/dotNet/linux/ubuntu20-apache-aspnetcore.json` | JP | Ubuntu 20.04 Focal | ASP.NET Core 8.0 | `net5webapplication` | infra + `apm/dotNet/linux-systemd` |
17+
18+
The US definition additionally has **no `instrumentations` block**, so it deploys the
19+
app but never runs the install recipe or validates that the agent installed — it is
20+
not actually testing the agent.
21+
22+
## Goals
23+
24+
- Test the .NET agent on **modern, supported Linux distros**: Ubuntu 24.04 (Noble) and
25+
Amazon Linux 2023.
26+
- Deploy a **.NET 10** ASP.NET Core application (current LTS) instead of .NET 5.
27+
- Every new definition includes a full `instrumentations` block that runs the install
28+
recipe and validates the agent (fixing the US gap).
29+
- Cover **US, EU, and JP** regions.
30+
- Add the new definitions first; **retire the old ones only after the new ones are
31+
green** (no coverage gap).
32+
33+
## Non-Goals
34+
35+
- Adding an nginx reverse-proxy variant (Apache only, matching today).
36+
- arm64 coverage (the `apm/dotNet/linux-systemd` recipe targets `kernelArch: x86_64`).
37+
- Refactoring deploy scripts beyond what serves this change.
38+
39+
## Key Decisions
40+
41+
1. **Strategy:** Add new definitions + retire old ones after the new set passes.
42+
2. **Distros:** Ubuntu 24.04 (Noble) and Amazon Linux 2023.
43+
3. **App runtime target:** .NET 10.
44+
4. **Regions:** US, EU, JP.
45+
5. **Region/distro matrix:** US gets both distros; EU and JP each get Ubuntu 24.04.
46+
**4 new definitions.**
47+
6. **Web server:** Apache only.
48+
7. **App artifact:** external prerequisite — build/upload the .NET 10 zips to the
49+
`open-install-library-artifacts` S3 bucket outside this repo; **parameterize** the
50+
deploy scripts to consume them.
51+
8. **Agent validation:** all four new definitions include the full `instrumentations`
52+
block.
53+
9. **Deploy-script structuring:** **Approach A — parameterize the shared
54+
`apache/deploy-application/dotNet/{debian,rhel}` scripts** with behavior-preserving
55+
defaults, rather than cloning into version-specific dirs (Approach B).
56+
57+
## Verified Constraints (from exploration)
58+
59+
- `recipes/newrelic/apm/dotNet/linux-systemd.yml` has a wide-open install target
60+
(`os: linux`, `kernelArch: x86_64`, no platform/version restriction) → **no recipe
61+
changes needed**; it already accepts Ubuntu 24.04 and AL2023 on x86_64.
62+
- `recipes/newrelic/infrastructure/awslinux.yml` already supports AL2023
63+
(`platformVersion: "(2023\.*)"`).
64+
- `recipes/newrelic/infrastructure/ubuntu.yml` is version-agnostic → Ubuntu 24.04 fine.
65+
- AMI name patterns for the target distros are already in use elsewhere in the repo and
66+
can be reused:
67+
- Ubuntu Noble: `ubuntu/images/hvm-ssd-gp3/ubuntu-noble-24.04-amd64-server-????????`
68+
- Amazon Linux 2023: `al2023-ami-2023.*-x86_64`
69+
- The deployed apps are **prebuilt S3 zips** (`selfcontained-net5webapplication.zip`,
70+
`frameworkdependent-net5webapplication.zip`); there is **no app source in this repo**.
71+
72+
## Detailed Design
73+
74+
### 1. New test definitions (4 files)
75+
76+
All `t3.micro`, x86_64, two services behind Apache (self-contained `dotnet1` +
77+
framework-dependent `dotnet2`), each with a full `instrumentations` block validating
78+
`.NET Agent\s+(installed)`.
79+
80+
| File | Region | Distro | AMI pattern | `user_name` | Infra recipe URL |
81+
|---|---|---|---|---|---|
82+
| `test/definitions/apm/dotNet/linux/ubuntu24-apache-aspnetcore.json` | US | Ubuntu 24.04 | `ubuntu/images/hvm-ssd-gp3/ubuntu-noble-24.04-amd64-server-????????` | `ubuntu` | `.../infrastructure/ubuntu.yml` |
83+
| `test/definitions/apm/dotNet/linux/al2023-apache-aspnetcore.json` | US | Amazon Linux 2023 | `al2023-ami-2023.*-x86_64` | `ec2-user` | `.../infrastructure/awslinux.yml` |
84+
| `test/definitions-eu/apm/dotNet/linux/ubuntu24-apache-aspnetcore.json` | EU | Ubuntu 24.04 | (noble, as above) | `ubuntu` | `.../infrastructure/ubuntu.yml` |
85+
| `test/definitions-jp/apm/dotNet/linux/ubuntu24-apache-aspnetcore.json` | JP | Ubuntu 24.04 | (noble, as above) | `ubuntu` | `.../infrastructure/ubuntu.yml` |
86+
87+
Each Ubuntu def's `services` reference:
88+
- `dotNet/install/ubuntu24` (new runtime-install role)
89+
- `apache/install/debian`
90+
- `apache/deploy-application/dotNet/debian` (parameterized for .NET 10), self-contained + framework-dependent
91+
92+
The AL2023 def references:
93+
- `dotNet/install/al2023` (new runtime-install role)
94+
- `apache/install/rhel`
95+
- `apache/deploy-application/dotNet/rhel` (parameterized for .NET 10)
96+
97+
`instrumentations` `recipe_content_url` chains the appropriate infra recipe +
98+
`.../apm/dotNet/linux-systemd.yml`, with `validate_output: ".NET Agent\\s+\\(installed\\)"`.
99+
100+
### 2. New .NET 10 runtime-install roles
101+
102+
Under `test/deploy/linux/dotNet/install/`:
103+
104+
- **`ubuntu24/`** — mirrors the existing `ubuntu20` role (reads `/etc/os-release`,
105+
builds the `packages.microsoft.com` `.deb` URL), but installs
106+
**`aspnetcore-runtime-10.0`** instead of 8.0.
107+
- **`al2023/`** — installs ASP.NET Core Runtime 10.0 on AL2023 using `dnf`.
108+
**⚠️ Highest-risk item.** The current `rhel` role uses a CentOS 7 RPM, which is wrong
109+
for AL2023. The exact package source must be confirmed during implementation
110+
(candidates, in preference order): AL2023 native `dotnet`/`aspnetcore-runtime-10.0`
111+
dnf packages; the `packages.microsoft.com` RHEL 9 feed; or `dotnet-install.sh`.
112+
Treated as an explicit verification spike before the AL2023 definition is finalized.
113+
114+
Only the ASP.NET Core **runtime** is required (the apps are ASP.NET Core web apps); no
115+
SDK. The self-contained app does not need the runtime, but the framework-dependent app
116+
does, so the runtime install remains necessary.
117+
118+
### 3. Parameterize `apache/deploy-application/dotNet/{debian,rhel}`
119+
120+
In `onbeforestart/tasks/main.yml` for both `debian` and `rhel`:
121+
122+
- Introduce `dotnet_app_name` (default `net5webapplication`) used to build
123+
`startup_command` (`/var/www/{{service_id}}/{{dotnet_app_name}}` and
124+
`.../{{dotnet_app_name}}.dll`).
125+
- Keep `web_app_url` overridable (already is); the new defs pass the .NET 10
126+
self-contained / framework-dependent URLs. Defaults remain the net5 URLs so the
127+
old defs keep working until retired.
128+
- Update the human-readable `apache_service_description` strings to be version-neutral
129+
or driven by a param.
130+
131+
The new definitions pass `dotnet_app_name` + the .NET 10 artifact URLs via service
132+
`params`. The published entrypoint name inside the new zips must match
133+
`dotnet_app_name`.
134+
135+
Verify the `rhel` `.service` template's `User=` value is correct for AL2023 (the
136+
`debian` template hardcodes `User=ubuntu`; the AL2023 service must run as a user that
137+
exists and owns `/var/www/...`).
138+
139+
### 4. Apache install (reuse)
140+
141+
- Ubuntu 24.04 → existing `apache/install/debian` (apt, `apache2`). Expected to work on
142+
Noble.
143+
- AL2023 → existing `apache/install/rhel` (`yum install httpd`; `yum` aliases to `dnf`
144+
on AL2023). Verify it succeeds on AL2023.
145+
146+
### 5. External prerequisite — .NET 10 app artifacts (out of repo)
147+
148+
Build a .NET 10 ASP.NET Core sample web app in two flavors and upload to the
149+
`open-install-library-artifacts` S3 bucket (us-west-2):
150+
151+
- `selfcontained-net10webapplication.zip` (self-contained, bundles runtime)
152+
- `frameworkdependent-net10webapplication.zip` (framework-dependent)
153+
154+
Published entrypoint name (e.g. `net10webapplication` for the dll/executable) must match
155+
the `dotnet_app_name` the new definitions pass. This work happens outside this repo and
156+
requires S3 upload access; the repo wiring proceeds against the agreed names, but the
157+
new tests cannot pass until the artifacts exist.
158+
159+
### 6. Retirement (after the 4 new defs are green)
160+
161+
Delete, only after confirming no other definitions reference them:
162+
163+
- `test/definitions/apm/dotNet/linux/linux2-aspnetcore5.json`
164+
- `test/definitions-eu/apm/dotNet/linux/ubuntu20-apache-aspnetcore.json`
165+
- `test/definitions-jp/apm/dotNet/linux/ubuntu20-apache-aspnetcore.json`
166+
- `test/deploy/linux/dotNet/install/ubuntu20/` and `test/deploy/linux/dotNet/install/rhel/`
167+
(orphaned runtime-install roles) — **only if** no remaining definition references them.
168+
- Any net5-only template cruft left behind once the parameterization defaults are no
169+
longer needed.
170+
171+
## Error Handling / Edge Cases
172+
173+
- **AL2023 .NET 10 install** is the primary failure risk → verification spike (§2).
174+
- **AL2023 service user** mismatch in the `.service` template → verify (§3).
175+
- **AMI availability per region** — the noble/al2023 AMI glob patterns must resolve in
176+
EU and JP regions, not just US. Verify during implementation.
177+
- **Artifact naming coupling** — deploy-script `dotnet_app_name` must exactly match the
178+
published entrypoint inside the S3 zips.
179+
180+
## Testing / Validation
181+
182+
- Each new definition is exercised by the repo's existing validator harness (deploy →
183+
run install recipe → assert `.NET Agent (installed)` → app reachable via Apache).
184+
- The two-app pattern (self-contained + framework-dependent) preserves coverage of both
185+
deployment models.
186+
- Retirement step gated on the new definitions passing in their respective regions.
187+
188+
## Open Items Tracked Into the Plan
189+
190+
1. Confirm the AL2023 .NET 10 ASP.NET Core runtime install path (spike).
191+
2. Confirm `apache/install/rhel` works unmodified on AL2023.
192+
3. Confirm the `rhel` `.service` template user for AL2023.
193+
4. Confirm noble + al2023 AMI patterns resolve in EU and JP.
194+
5. Agree exact S3 artifact names + published entrypoint name; build/upload (external).
195+
6. Confirm no other definitions consume the install/deploy roles slated for retirement.

test/definitions-eu/apm/dotNet/windows/iis-blank.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
},
88

99
"resources": [{
10-
"id": "iiswindows2019",
10+
"id": "iiswin2019-eu",
1111
"provider": "aws",
1212
"type": "ec2",
1313
"size": "t3.small",
@@ -18,7 +18,7 @@
1818

1919
"services": [{
2020
"id": "iis",
21-
"destinations": ["iiswindows2019"],
21+
"destinations": ["iiswin2019-eu"],
2222
"source_repository": "https://github.com/newrelic/open-install-library.git",
2323
"deploy_script_path": "test/deploy/windows/iis/install/roles",
2424
"port": 9999
@@ -28,7 +28,7 @@
2828
"resources": [
2929
{
3030
"id": "nr_infra",
31-
"resource_ids": ["iiswindows2019"],
31+
"resource_ids": ["iiswin2019-eu"],
3232
"provider": "newrelic",
3333
"source_repository": "https://github.com/newrelic/open-install-library.git",
3434
"deploy_script_path": "test/deploy/windows/newrelic-cli/install-recipe/roles",

test/definitions-eu/apm/dotNet/windows/windows2016-iis.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
},
88

99
"resources": [{
10-
"id": "iiswindows2016",
10+
"id": "iiswin2016-eu",
1111
"provider": "aws",
1212
"type": "ec2",
1313
"size": "t3.small",
@@ -18,25 +18,25 @@
1818

1919
"services": [{
2020
"id": "iis",
21-
"destinations": ["iiswindows2016"],
21+
"destinations": ["iiswin2016-eu"],
2222
"source_repository": "https://github.com/newrelic/open-install-library.git",
2323
"deploy_script_path": "test/deploy/windows/iis/install/roles",
2424
"port": 9999
2525
},{
2626
"id": "webapp1",
27-
"destinations": ["iiswindows2016"],
27+
"destinations": ["iiswin2016-eu"],
2828
"source_repository": "https://github.com/newrelic/open-install-library.git",
2929
"deploy_script_path": "test/deploy/windows/iis/deploy-webapplication/roles",
3030
"port": 8081
3131
},{
3232
"id": "webapp2",
33-
"destinations": ["iiswindows2016"],
33+
"destinations": ["iiswin2016-eu"],
3434
"source_repository": "https://github.com/newrelic/open-install-library.git",
3535
"deploy_script_path": "test/deploy/windows/iis/deploy-webapplication/roles",
3636
"port": 8082
3737
},{
3838
"id": "webapp3",
39-
"destinations": ["iiswindows2016"],
39+
"destinations": ["iiswin2016-eu"],
4040
"source_repository": "https://github.com/newrelic/open-install-library.git",
4141
"deploy_script_path": "test/deploy/windows/iis/deploy-webapplication/roles",
4242
"port": 8083,
@@ -49,7 +49,7 @@
4949
"resources": [
5050
{
5151
"id": "nr_infra",
52-
"resource_ids": ["iiswindows2016"],
52+
"resource_ids": ["iiswin2016-eu"],
5353
"provider": "newrelic",
5454
"source_repository": "https://github.com/newrelic/open-install-library.git",
5555
"deploy_script_path": "test/deploy/windows/newrelic-cli/install-recipe/roles",

test/definitions-eu/apm/dotNet/windows/windows2019-core-only-iis.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
},
88

99
"resources": [{
10-
"id": "iiswindows2019",
10+
"id": "iiswin2019-eu",
1111
"provider": "aws",
1212
"type": "ec2",
1313
"size": "t3.small",
@@ -18,14 +18,14 @@
1818

1919
"services": [{
2020
"id": "iis",
21-
"destinations": ["iiswindows2019"],
21+
"destinations": ["iiswin2019-eu"],
2222
"source_repository": "https://github.com/newrelic/open-install-library.git",
2323
"deploy_script_path": "test/deploy/windows/iis/install/roles",
2424
"port": 9999
2525
},
2626
{
2727
"id": "coreapp",
28-
"destinations": ["iiswindows2019"],
28+
"destinations": ["iiswin2019-eu"],
2929
"source_repository": "https://github.com/newrelic/open-install-library.git",
3030
"deploy_script_path": "test/deploy/windows/iis/deploy-webapplication/roles",
3131
"port": 8083,
@@ -38,7 +38,7 @@
3838
"resources": [
3939
{
4040
"id": "nr_infra",
41-
"resource_ids": ["iiswindows2019"],
41+
"resource_ids": ["iiswin2019-eu"],
4242
"provider": "newrelic",
4343
"source_repository": "https://github.com/newrelic/open-install-library.git",
4444
"deploy_script_path": "test/deploy/windows/newrelic-cli/install/roles",

test/definitions-eu/apm/dotNet/windows/windows2019-iis.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
},
88

99
"resources": [{
10-
"id": "iiswindows2019",
10+
"id": "iiswin2019-eu",
1111
"provider": "aws",
1212
"type": "ec2",
1313
"size": "t3.small",
@@ -18,25 +18,25 @@
1818

1919
"services": [{
2020
"id": "iis",
21-
"destinations": ["iiswindows2019"],
21+
"destinations": ["iiswin2019-eu"],
2222
"source_repository": "https://github.com/newrelic/open-install-library.git",
2323
"deploy_script_path": "test/deploy/windows/iis/install/roles",
2424
"port": 9999
2525
},{
2626
"id": "webapp1",
27-
"destinations": ["iiswindows2019"],
27+
"destinations": ["iiswin2019-eu"],
2828
"source_repository": "https://github.com/newrelic/open-install-library.git",
2929
"deploy_script_path": "test/deploy/windows/iis/deploy-webapplication/roles",
3030
"port": 8081
3131
},{
3232
"id": "webapp2",
33-
"destinations": ["iiswindows2019"],
33+
"destinations": ["iiswin2019-eu"],
3434
"source_repository": "https://github.com/newrelic/open-install-library.git",
3535
"deploy_script_path": "test/deploy/windows/iis/deploy-webapplication/roles",
3636
"port": 8082
3737
},{
3838
"id": "webapp3",
39-
"destinations": ["iiswindows2019"],
39+
"destinations": ["iiswin2019-eu"],
4040
"source_repository": "https://github.com/newrelic/open-install-library.git",
4141
"deploy_script_path": "test/deploy/windows/iis/deploy-webapplication/roles",
4242
"port": 8083,
@@ -49,7 +49,7 @@
4949
"resources": [
5050
{
5151
"id": "nr_infra",
52-
"resource_ids": ["iiswindows2019"],
52+
"resource_ids": ["iiswin2019-eu"],
5353
"provider": "newrelic",
5454
"source_repository": "https://github.com/newrelic/open-install-library.git",
5555
"deploy_script_path": "test/deploy/windows/newrelic-cli/install-recipe/roles",

0 commit comments

Comments
 (0)