Skip to content

test(ffe): add agentless end-to-end harness#7298

Open
leoromanovsky wants to merge 9 commits into
mainfrom
exec/system-tests-agentless-harness
Open

test(ffe): add agentless end-to-end harness#7298
leoromanovsky wants to merge 9 commits into
mainfrom
exec/system-tests-agentless-harness

Conversation

@leoromanovsky

@leoromanovsky leoromanovsky commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Motivation

Server SDK Feature Flags are moving to authenticated CDN delivery as the default configuration path, with Agent Remote Configuration remaining an explicit alternative. The existing FFE end-to-end scenario can exercise only the Agent/RC lifecycle: it starts an Agent and weblog, then supplies UFC after the application is running.

That cannot prove the agentless startup contract. An agentless SDK may request UFC while the application is starting, so the test backend must already exist before the weblog starts. The scenario must also run without an Agent; otherwise a passing test cannot rule out an accidental Agent dependency.

This PR adds that missing, dormant test foundation. It starts a deterministic CDN-style UFC backend before a no-Agent weblog, injects the endpoint and credentials, and verifies authenticated configuration fetch plus evaluation. No SDK manifest is enabled here, so ordinary SDK CI behavior does not change until a later activation PR.

flowchart LR
    subgraph BEFORE["Existing end-to-end coverage"]
        B1["Start Agent and weblog"] --> B2["SDK starts"]
        B3["RC fixture"] --> B4["Agent Remote Configuration"]
        B4 --> B2
        B2 --> B5["Evaluate flag"]
    end

    subgraph THIS["Agentless harness added here"]
        A1["1. Start mock CDN backend"] --> A2["2. Start weblog and SDK<br/>without an Agent"]
        A2 --> A3["3. Fetch UFC with API key"]
        A3 --> A4["4. Evaluate flag"]
    end

    GAP["Missing on main:<br/>pre-start UFC service<br/>and no-Agent lifecycle"] -.-> A1

    classDef current fill:#fcbf49,stroke:#8a5a00,stroke-width:3px,color:#111;
    class A1,A2,A3,A4 current;
Loading

Stack Position

This is the inactive foundation of the stack. Later PRs add the telemetry topology and then activate individual Java capabilities only when their implementation is green.

flowchart TD
    ST1["#7298 · this PR<br/>no-Agent CDN configuration harness<br/>all manifests disabled"]
    ST2["#7299 · next stacked PR<br/>side-effect transport contracts<br/>sidecar preferred, direct fallback"]
    STM["#7300 and small follow-ups<br/>enable Java capabilities one at a time"]

    J1["dd-trace-java #11892<br/>agentless configuration source"]
    J2["dd-trace-java side-effects work<br/>exposures · evaluation EVP · OTLP"]

    ST1 --> ST2 --> STM
    J1 --> STM
    J2 --> STM

    classDef current fill:#fcbf49,stroke:#8a5a00,stroke-width:3px,color:#111;
    class ST1 current;
Loading

Architecture Boundary

Configuration source and telemetry transport are independent. The Agent belongs only to the explicit Remote Configuration branch. Default agentless configuration has no Agent dependency. Post-evaluation side effects are a stacked follow-up: prefer the Datadog serverless sidecar when available and fall back to direct authenticated intake otherwise.

flowchart LR
    subgraph CONFIG["Configuration delivery"]
        RC["RC fixture"] --> RCA["Agent<br/>RC only"]
        RCA --> RCS["SDK remote_config source"]

        CDN["Datadog CDN<br/>or controlled mock"] -->|"authenticated HTTP"| AGS["SDK agentless source<br/>default"]

        RCS --> EVAL["Same UFC / OpenFeature evaluator"]
        AGS --> EVAL
    end

    subgraph FOLLOWUP["Telemetry transport · stacked follow-up"]
        EVAL --> FX["Exposure EVP · evaluation EVP · OTLP metrics"]
        FX --> PICK{"Serverless sidecar available?"}
        PICK -->|"yes"| SIDECAR["Datadog serverless sidecar"]
        PICK -->|"no"| DIRECT["Direct authenticated intake"]
        SIDECAR --> INTAKE["Datadog backend"]
        DIRECT --> INTAKE
    end

    classDef current fill:#fcbf49,stroke:#8a5a00,stroke-width:3px,color:#111;
    class CDN,AGS,EVAL current;
Loading

Changes

  • Add a deterministic CDN-style UFC backend with API-key validation, ETag/If-None-Match, and metadata-only status inspection.
  • Add a dormant FEATURE_FLAGGING_AND_EXPERIMENTATION_AGENTLESS scenario that starts the backend before the weblog.
  • Allow the shared end-to-end lifecycle to omit the Datadog Agent and its proxy/interface handling.
  • Run the agentless scenario without an Agent or Agent proxy and explicitly disable Remote Configuration.
  • Add the default-agentless configuration/evaluation contract test.
  • Gate the test in every SDK manifest and keep the dormant scenario out of broad all, end_to_end, and tracer_release selections.
  • Add regression coverage for backend lifecycle, scenario topology, and CI scenario selection.

Decisions

  • Keep this PR deliberately inactive until an SDK-specific manifest PR opts in.
  • Treat no-Agent execution as part of the agentless contract, not merely as a future dogfooding concern.
  • Keep side-effect assertions out of this configuration-foundation PR.
  • Put the serverless-sidecar/direct-fallback telemetry topology in the next stacked contract PR.
  • Keep the Agent/RC scenario unchanged as the explicit alternative configuration path.

Validation

  • ./format.sh --check — passes.
  • Focused lifecycle and scenario tests — 6 passed.
  • Forced Java run against java@1.65.0-SNAPSHOT+f9e70e67c4 — 1 passed in 2.11s.
  • The Java run starts no Agent or Agent proxy and waits on no Agent interface; it verifies an authenticated mock-CDN request and the expected flag evaluation.

Next Steps

@github-actions

github-actions Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

CODEOWNERS have been resolved as:

tests/ffe/test_agentless_configuration.py                               @DataDog/feature-flagging-and-experimentation-sdk @DataDog/system-tests-core
manifests/cpp_httpd.yml                                                 @DataDog/dd-trace-cpp
manifests/cpp_nginx.yml                                                 @DataDog/dd-trace-cpp
manifests/dotnet.yml                                                    @DataDog/apm-dotnet @DataDog/asm-dotnet
manifests/golang.yml                                                    @DataDog/dd-trace-go-guild
manifests/java.yml                                                      @DataDog/asm-java @DataDog/apm-java
manifests/nodejs.yml                                                    @DataDog/dd-trace-js
manifests/php.yml                                                       @DataDog/apm-php @DataDog/asm-php
manifests/python.yml                                                    @DataDog/apm-python @DataDog/asm-python
manifests/ruby.yml                                                      @DataDog/ruby-guild @DataDog/asm-ruby
manifests/rust.yml                                                      @DataDog/apm-rust
tests/test_the_test/scenarios.json                                      @DataDog/system-tests-core
tests/test_the_test/test_compute_libraries_and_scenarios.py             @DataDog/system-tests-core
tests/test_the_test/test_group_rules.py                                 @DataDog/system-tests-core
tests/test_the_test/test_mock_ffe_agentless_backend.py                  @DataDog/system-tests-core
utils/_context/_scenarios/__init__.py                                   @DataDog/system-tests-core
utils/_context/_scenarios/endtoend.py                                   @DataDog/system-tests-core
utils/_context/containers.py                                            @DataDog/system-tests-core
utils/_context/weblog_infrastructure.py                                 @DataDog/system-tests-core
utils/build/docker/otel_collector/weblog_metadata.yml                   @DataDog/system-tests-core
utils/docker_fixtures/_core.py                                          @DataDog/system-tests-core

@datadog-official

datadog-official Bot commented Jul 11, 2026

Copy link
Copy Markdown

Pipelines  Tests

Fix all issues with BitsAI

⚠️ Warnings

🚦 11 Pipeline jobs failed

Testing the test | System Tests (php, prod) / End-to-end #2 / laravel11x 2   View in Datadog   GitHub Actions

🧪 1 Test failed

All test failures are known flaky.

❄️ Known flaky: tests.appsec.api_security.test_apisec_sampling.Test_API_Security_Sampling_Different_Endpoints.test_sampling_delay[laravel11x] from system_tests_suite   View in Datadog
assert False
 &#43;  where False = all(&lt;generator object Test_API_Security_Sampling_Different_Endpoints.test_sampling_delay.&lt;locals&gt;.&lt;genexpr&gt; at 0x7f70b4181b60&gt;)

self = &lt;tests.appsec.api_security.test_apisec_sampling.Test_API_Security_Sampling_Different_Endpoints object at 0x7f70c4d528d0&gt;

    def test_sampling_delay(self):
        assert self.request1.status_code == 200
        schema1 = get_schema(self.request1, &#34;req.headers&#34;)
        assert schema1 is not None
    
...

Not introduced in this PR.

DataDog/system-tests | Debian_12_amd64.INS: [test-app-python]   View in Datadog   GitLab

DataDog/system-tests | Ubuntu_20_amd64.CON: [test-app-java-alpine]   View in Datadog   GitLab

View all 11 failed jobs.

ℹ️ Info

No other issues found (see more)

❄️ No new flaky tests detected

🔄 Datadog auto-retried 1 job - 1 passed on retry View in Datadog

Useful? React with 👍 / 👎

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: c9f955e | Docs | Datadog PR Page | Give us feedback!

Base automatically changed from agent/pin-ffe-e2e-remote-config to main July 11, 2026 22:14
@leoromanovsky leoromanovsky marked this pull request as ready for review July 14, 2026 01:04
@leoromanovsky leoromanovsky requested review from a team as code owners July 14, 2026 01:04
@leoromanovsky leoromanovsky requested review from ZStriker19, claponcet, jandro996, manuel-alvarez-alvarez and ncybul and removed request for a team July 14, 2026 01:04
@leoromanovsky leoromanovsky requested review from dubloom, pavlokhrebto, sameerank and typotter and removed request for a team and pavlokhrebto July 14, 2026 01:04

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9af665a8a9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread tests/ffe/test_agentless_configuration.py
Comment thread tests/ffe/test_agentless_configuration.py
Comment thread utils/_context/_scenarios/__init__.py
@leoromanovsky leoromanovsky marked this pull request as draft July 14, 2026 02:13
@leoromanovsky leoromanovsky marked this pull request as ready for review July 14, 2026 17:04

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: eb57dc60db

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

"attributes": {},
},
)
self.backend_status = scenarios.feature_flagging_and_experimentation_agentless.mock_backend_status()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Move backend status polling out of setup

Fresh evidence after the prior thread: the current code again calls mock_backend_status() from setup_default_agentless_source. That helper performs a /status request and MockFFEAgentlessBackendServer.status() raises on non-2xx responses, so a transient mock-control failure aborts the scenario as a setup error before test_default_agentless_source can report it as an ordinary test failure; keep setup to triggering /ffe and fetch/assert the backend status in the test method.

Useful? React with 👍 / 👎.

default_libs_with_dev,
3600,
"false",
"DEFAULT,FEATURE_FLAGGING_AND_EXPERIMENTATION_AGENTLESS",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Add a workflow path for the selected scenario

When this test file changes, this new expectation makes the CI selector emit FEATURE_FLAGGING_AND_EXPERIMENTATION_AGENTLESS, and compute-workflow-parameters schedules it as end-to-end work; however I checked .github/workflows/run-end-to-end.yml:320-322 and the workflow only has the existing FEATURE_FLAGGING_AND_EXPERIMENTATION run step, with no AGENTLESS step found. Those jobs can build weblogs and then skip every scenario run step, so PRs changing or enabling this test get green end-to-end jobs without running the selected scenario; either keep the dormant scenario out of the selector or add the matching run step.

Useful? React with 👍 / 👎.

@cbeauchesne cbeauchesne left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Great job, congrats. I've few request changes and question. There are also two missing bits :

  • add rules in utils/scripts/libraries_and_scenarios_rules.yml for this new scenario
  • add the scenario in the CI

)
from utils._context.weblog_infrastructure import EndToEndWeblogInfra
from utils.docker_fixtures._core import extra_hosts_for_environment
from utils.docker_fixtures._mock_ffe_agentless_backend import (

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

There is a mechanism in our CI that control which scenario is executed based on changes. As now, utils.docker_fixtures triggers a change only on INTEGRATION_FRAMEWORKS and PARAMETRIC scenarios.

As _mock_ffe_agentless_backend will be a utilitity of both scenario, we must move this module in an dedicated module.

I also feel that it should be generic, as I expect FFE won't be the only feature to use it.

WDYT about utils.mocked_backend ? For the CI orchestrator, it happens here : utils/scripts/libraries_and_scenarios_rules.yml

super().start_interfaces_watchdog(
[interfaces.library, interfaces.agent]
[interfaces.library]
+ agent_interfaces

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The type of agent_interfaces is list | None, if I'm not wrong, you can't add None to a list here. The fox is just above, by setting [] if include_agent==False

)

self.weblog_infra.stop()
self.weblog_infra.stop(flush=self._flush_weblog_on_stop)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why do you need to disable the flush here ?



@scenarios.test_the_test
@features.not_reported

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

You don't need to add @features.not_reported here, same goes for other test_the_test files

client_drop_p0s: bool | None = None,
iast_enabled: bool = True,
include_agent: bool = True,
include_default_scenario_groups: bool = True,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

IIUC, it's a temporary situation? If yes, could you rather force the groups in FeatureFlaggingAgentlessEndToEndScenario.__init__, rather adding an argument to the constructor? (it's already too big).

Comment on lines +739 to +745
include_agent=False,
include_default_scenario_groups=False,
flush_weblog_on_stop=False,
library_interface_timeout=0,
scenario_groups=[scenario_groups.ffe],
use_proxy_for_agent=False,
use_proxy_for_weblog=False,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

If ever some of those value will be constant for the majority of FeatureFlaggingAgentlessEndToEndScenario, it's better to set the directly inside FeatureFlaggingAgentlessEndToEndScenario constructor, or inside FeatureFlaggingAgentlessEndToEndScenario construtor prototype as optional argument with defaults.

It keeps this file shorter and easier to maintain.


def configure(self, config: pytest.Config) -> None:
try:
if not self.replay:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I'm not sure it's usefull, we never use xdist with end-to-end scenario.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants