[8.19](backport #7815) test: E2E regression test for fleet-server parsed policy race condition (#7794) - #7839
mergify[bot] wants to merge 3 commits into
Conversation
|
Cherry-pick of 552fb78 has failed: To fix up this pull request, you can check it out locally. See documentation: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/checking-out-pull-requests-locally |
This comment has been minimized.
This comment has been minimized.
TL;DRBuildkite Remediation
Investigation detailsRoot CauseThis is a code/backport mismatch, not infrastructure flakiness. The newly added test in this PR references Evidence
Verification
Follow-up
What is this? | From workflow: Observability Agentic Workflow — Status Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not. |
…on (#7794) (#7815) * test: E2E regression test for fleet-server parsed policy race condition fix Adds TestRemoteESOutputWithSecrets to AgentContainerSuite in testing/e2e/remote_es_output_test.go. The test verifies that fleet-server correctly serves a policy with a remote_elasticsearch output whose service_token is stored as a Fleet secret (non-empty secret_references) without crashing, and that an enrolled agent successfully applies the policy. This is the trigger condition for the race fixed in #7794. Also adds four scaffold helpers to testing/e2e/scaffold/scaffold.go: CreateServiceToken, CreateFleetOutput, CreateAgentPolicy, and GetAgentPolicyRevision. Closes elastic/elastic-agent#16582 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: address Copilot review feedback on TestRemoteESOutputWithSecrets - Add CreateEnrollmentAPIKey scaffold helper and use it in the test instead of GetEnrollmentTokenForPolicyID; CreateAgentPolicy does not guarantee an auto-generated key is immediately available, so creating one explicitly is more reliable - Enroll two agents concurrently under the same policy so fleet-server dispatches the policy to multiple subscribers simultaneously — the scenario that exercises the shared-ParsedPolicy race fixed in #7794 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: remove GOCOVERDIR from enrolled agent containers fleet-server never starts in FLEET_ENROLL mode, so the env var and /cover mount have no effect on the agent containers. Only the fleet-server container (FLEET_SERVER_ENABLE=1) needs GOCOVERDIR. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: verify secret_references is populated before enrolling agents Add WaitForPolicySecretReferences scaffold helper that polls .fleet-policies until the latest revision for a given policy ID has a non-empty secret_references array. Call it in TestRemoteESOutputWithSecrets after CreateAgentPolicy so the test fails fast — with a clear message — if the "secrets" wrapper on the Fleet output did not produce a secret reference. Without this check, Kibana silently dropping the wrapper would let the test pass against an ordinary (non-secret-referencing) policy that never touches the #7794 code path. Serial agent container startup is intentional: the bug manifests even sequentially because agent 1 receives the already-mutated cached ParsedPolicy that agent 0's processPolicy corrupted. >= in the revision check is intentional: the policy revision is monotonic and can advance between the two reads, so == would be flaky. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: verify agent data lands in remote ES over the output connection Add Outputs field to ESAgentDoc and WaitForAgentDocsInIndex scaffold helper. In TestRemoteESOutputWithSecrets, set monitoring_output_id to the remote ES output and monitoring_enabled to ["logs", "metrics"] so the agent writes its self-monitoring metrics there. Assert those documents appear in metrics-elastic_agent.* in the remote ES, proving the full path: secret reference resolved → API key created in remote ES → agent authenticated → data indexed. CreateAgentPolicy now accepts variadic extra body fields so callers can set optional Fleet API fields without changing the base signature. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: start agent containers concurrently to reliably trigger the race Replace the sequential for-loop with a sync.WaitGroup that launches all five agent containers in parallel goroutines. This maximises the window during which multiple agents are receiving and applying the same policy simultaneously in fleet-server, reliably triggering the shared- ParsedPolicy mutation when the fix is absent. Verified: 10/10 test runs fail (agent panic: index out of range [-1]) against code with #7794 and #7740 reverted; 0/1 fail with the fix in place. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: extend timeouts to survive 5-minute long-poll retry cycle Agents that miss the initial policy dispatch (due to the Subscribe→kickDeploy cancellation race) must wait for their 5-minute long-poll to expire before retrying. The previous 3-minute Eventually and 5-minute outer context were too short for this retry cycle. Bump the outer context to 12 minutes and the Eventually to 9 minutes to give agents time to exhaust their long-poll and succeed on the second attempt. Also drop the monitoring_output_id / WaitForAgentDocsInIndex assertions: they require inter-container network access that is not set up in this test environment, so they always failed. The core regression (no panic, all agents reach online) is covered by the remaining assertions. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: include name in CreateEnrollmentAPIKey request body The Fleet enrollment_api_keys API accepts a name field alongside policy_id. Including it makes the request unambiguous and avoids any Kibana validation that may require it in stricter versions. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: register agent container cleanup before checking startup errors If Require().NoError aborted on agent N's startup error, the cleanup callbacks for agents N+1 through numAgents-1 were never registered, leaving those containers running and interfering with subsequent E2E runs. Fix: iterate agentContainers first to register a Cleanup for every non-nil container, then iterate agentErrs to fail on any error. This guarantees all created containers are terminated regardless of which agent failed to start. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: use sync.WaitGroup.Go instead of manual Add/goroutine/Done Go 1.25 added (*sync.WaitGroup).Go, which combines Add(1), go func(), and defer Done() into a single call. The project is on Go 1.26, so we can use it here to simplify the concurrent agent container launch loop. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: verify agent monitoring data lands in remote ES output Route both the data and monitoring outputs to the remote_elasticsearch output. After all agents come online, wait for metrics-elastic_agent.* documents attributed to an enrolled agent to appear in Elasticsearch. This end-to-end check confirms the full path: secret_references resolved → fleet-server creates API key in remote ES → agent receives key and authenticates → self-monitoring data indexed. Extend WaitForAgentDocsInIndex timeout from 2 to 4 minutes so two full 60-second metric periods are covered before giving up. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> (cherry picked from commit 552fb78) # Conflicts: # testing/e2e/scaffold/scaffold.go
Mergify left unresolved conflict markers when backporting #7815 to 8.19. GetPolicy did not exist on 8.19, so the cherry-pick conflicted. Resolved by keeping the incoming version (GetPolicy + new helpers) and removing the <<<<<<< / ======= / >>>>>>> markers. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
c06d1d5 to
181d2e6
Compare
…e fix The E2E test added in #7815 calls suite.GetAgent() which was added to main after the 8.19 branch was cut. Add the missing ESAgentDoc type and GetAgent method to the 8.19 scaffold so the backport compiles. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Warning
Merge after #7840 ([8.19] backport of #7794). This PR is a regression test for that fix — without the fix in place the test will fail or produce misleading results.
Summary
Regression test for #7794 (the
ParsedPolicyshared-state race whensecret_referencesis non-empty), moved from elastic/elastic-agent#16582 into fleet-server's own E2E suite where it belongs.TestRemoteESOutputWithSecretstoAgentContainerSuiteintesting/e2e/remote_es_output_test.goAGENT_E2E_IMAGE)remote_elasticsearchFleet output whoseservice_tokenis stored as a Fleet secret (using the"secrets"wrapper), which populatessecret_referencesin the generated policy — the trigger condition for the raceonlinestate (fleet-server did not crash)testing/e2e/scaffold/scaffold.go:CreateServiceToken,CreateFleetOutput,CreateAgentPolicy,GetAgentPolicyRevisionTest plan
mage test:e2erunsTestRemoteESOutputWithSecretsand it passesParsedPolicy.Clone()at dispatch site) causes the test to fail (fleet-server panics with index-out-of-range, agent never reaches online)🤖 Generated with Claude Code
This is an automatic backport of pull request #7815 done by Mergify.