test(ffe): cover agentless CDN configuration-source contract#7277
test(ffe): cover agentless CDN configuration-source contract#7277leoromanovsky wants to merge 21 commits into
Conversation
|
|
🎉 All green!🧪 All tests passed 🔄 Datadog auto-retried 1 job - 1 passed on retry 🔗 Commit SHA: 81bbcdd | Docs | Datadog PR Page | Give us feedback! |
- Add parametric FFE source-mode test class - Cover RC, CDN, default CDN, and negative fixture cases
- Add mock CDN control and metadata-only status endpoints - Add valid, malformed, and unchanged UFC fixtures
- Add source-mode class rows to all target SDK manifests - Gate rows pending agentless CDN source-mode implementations
- Register mock CDN fixture via pytest_plugins - Keep mock handler typing compatible with instance server state
- Add endpoint-form CDN base URL coverage - Add 509 and 304 transition cases for source-mode L3 - Assert CDN source metadata across mock-backed cases
- add deterministic retry/etag response sequences for CDN source-mode tests - expose metadata-only status code evidence and endpoint URL handling
73df0cf to
2874813
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 81bbcdd41a
ℹ️ 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".
|
|
||
| status = _wait_for_status( | ||
| mock_ffe_cdn, | ||
| lambda current: current["status_codes"][-2:] == expected_status_codes, |
There was a problem hiding this comment.
Match CDN status transitions anywhere in history
When the SDK keeps polling after the expected transition, this predicate can miss a successful 500 -> 200 sequence and time out: for example, if another poll lands before _wait_for_status samples /status, the history becomes [500, 200, 200] and status_codes[-2:] is no longer [500, 200]. The same last-two-codes pattern is used for the other recovery/warm sequence tests, so these tests can be flaky once SDK polling is fast enough; checking for the expected adjacent pair anywhere in status_codes would make the assertion stable.
Useful? React with 👍 / 👎.
| self.in_flight += 1 | ||
| self.max_in_flight = max(self.max_in_flight, self.in_flight) | ||
| self.last_path = parsed.path | ||
| self.last_if_none_match = headers.get("If-None-Match") |
There was a problem hiding this comment.
Normalize If-None-Match before storing it
If an SDK sends the ETag validator with different casing, e.g. if-none-match, this case-sensitive lookup records None even though HTTP header names are case-insensitive. test_good_to_unchanged_etag_sequence then times out on last_if_none_match == '"ufc-v1"' despite the SDK making a valid 304 request, so the mock can falsely fail conforming implementations.
Useful? React with 👍 / 👎.
| assert apply_state["apply_state"] == RemoteConfigApplyState.ACKNOWLEDGED.value | ||
| assert apply_state["product"] == RC_PRODUCT | ||
|
|
||
| assert test_library.ffe_start(UFC_VALID_DATA), "failed to start FFE provider in remote_config mode" |
There was a problem hiding this comment.
Do not inject UFC into the remote-config source test
Passing UFC_VALID_DATA directly to /ffe/start lets SDK test servers that consume the configuration request body, such as PHP's parametric endpoint, load the flag payload locally instead of proving that DD_FLAGGING_CONFIGURATION_SOURCE=remote_config read it from Agent RC. In that context the test can pass with zero CDN requests even if the remote-config source is broken, so this source-selection check should start the provider without the direct configuration payload and rely on the RC set above.
Useful? React with 👍 / 👎.
Motivation
Server SDK agentless flag delivery needs one shared system-test contract before the SDK implementations land. These tests are intentionally red behind
missing_feature; they define the cross-SDK behavior we expect for configuration-source selection, CDN polling, cold failures, warm preservation, and no-Agent reachability.Tracking:
FFL-2731, under epicFFL-2662.Internal RFC:
Supporting OpenFeature Agentless mode in Server SDKsChanges
Configuration-source tests
remote_config, explicitcdn, defaultcdn, customer endpoint override, invalid source, cold failure/recovery, warm preservation, timeout, and poller no-overlap.DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED=trueto enable the current provider; the renamed contract under test isDD_FLAGGING_CONFIGURATION_SOURCE*.Mock FFE CDN
/mock/ufc/configwith test-owned response timelines.tests/parametric/test_ffe/flags-v1.json; malformed UFC stays inline.500for 5xx retryable failures. No509.Docker reachability
host.docker.internal:host-gatewayfor the test agent and for parametric SDK containers when their env points athost.docker.internal.Decisions
Mock scope
Keep the fixture FFE/UFC-specific for this PR. A generic HTTP fixture can come later if another suite needs it.
Configuration model
Customer-hosted HTTP endpoints are covered as
cdnwith a different base URL, not a fourth SDK mode.Provider enablement
This suite does not rename provider enablement. It uses the current system-tests/SDK provider flag and focuses the new contract on configuration-source env vars.
SDK Gates
FFL-2693FFL-2731FFL-2695FFL-2731FFL-2697FFL-2731FFL-2699FFL-2731FFL-2701FFL-2731FFL-2703FFL-2731FFL-2705FFL-2731irrelevantFFL-2731irrelevantFFL-2731Coverage
Source Selection
test_remote_config_positive_ignores_cdn_envflags-v1.json; CDN base URL can be present but mock CDN must receive zero requests.test_remote_config_without_rc_does_not_fallback_to_cdnremote_configwithout RC stays default/not-ready and does not fall back to CDN.test_explicit_cdn_positiveDD_FLAGGING_CONFIGURATION_SOURCE=cdnfetches the mock and evaluates the same flag value as RC.test_default_cdn_positivetest_customer_http_endpoint_default_cdn_positivetest_invalid_configuration_source_fails_closedCold Failure And Recovery
test_missing_auth_coldtest_malformed_coldtest_request_timeout_coldDD_FLAGGING_CONFIGURATION_SOURCE_REQUEST_TIMEOUT_SECONDSis treated as cold failure.test_bad_to_good_cold_recoverytest_bad_to_unchanged_cold_preserves_not_readyWarm State Preservation
test_missing_auth_warmtest_good_to_bad_warm_preservationtest_good_to_unchanged_etag_sequenceIf-None-Matchand keeps evaluator state unchanged.test_malformed_warmPoller And Fixture
test_delayed_no_overlaptest_mock_ffe_cdn_status_is_metadata_onlytest_mock_ffe_cdn_reachable_from_test_agent_networkValidation