diff --git a/tests/apm_tracing_e2e/test_otel.py b/tests/apm_tracing_e2e/test_otel.py index 1d57e18f22b..ec3f91c2858 100644 --- a/tests/apm_tracing_e2e/test_otel.py +++ b/tests/apm_tracing_e2e/test_otel.py @@ -22,7 +22,7 @@ def setup_datadog_otel_span(self): # - duration of one second # - span kind of SpanKind - Internal def test_datadog_otel_span(self): - spans = interfaces.backend_v2.get_spans_list(self.req) + spans = interfaces.mocked_backend.get_spans_list(self.req) assert len(spans) >= 2, "Agent did not submit the spans we want!" # Assert the parent span sent by the agent. @@ -50,7 +50,7 @@ def setup_distributed_otel_trace(self): ) def test_distributed_otel_trace(self): - spans = interfaces.backend_v2.get_spans_list(self.req) + spans = interfaces.mocked_backend.get_spans_list(self.req) assert len(spans) >= 3, "Agent did not submit the spans we want!" # Assert the parent span sent by the agent. diff --git a/tests/apm_tracing_e2e/test_single_span.py b/tests/apm_tracing_e2e/test_single_span.py index 88b16c6c9f6..724d6dd9df2 100644 --- a/tests/apm_tracing_e2e/test_single_span.py +++ b/tests/apm_tracing_e2e/test_single_span.py @@ -28,7 +28,7 @@ def setup_parent_span_is_single_span(self): def test_parent_span_is_single_span(self): # Only the parent span should be submitted to the backend! - spans = interfaces.backend_v2.get_spans_list(self.req) + spans = interfaces.mocked_backend.get_spans_list(self.req) assert len(spans) == 1, "Agent did not submit the spans we want!" # Assert the spans sent by the agent. @@ -47,7 +47,7 @@ def setup_child_span_is_single_span(self): def test_child_span_is_single_span(self): # Only the child should be submitted to the backend! - spans = interfaces.backend_v2.get_spans_list(self.req) + spans = interfaces.mocked_backend.get_spans_list(self.req) assert len(spans) == 1, "Agent did not submit the spans we want!" # Assert the spans sent by the agent. diff --git a/tests/ffe/utils/evp.py b/tests/ffe/utils/evp.py index 53d82ca6a08..7ef6b486c00 100644 --- a/tests/ffe/utils/evp.py +++ b/tests/ffe/utils/evp.py @@ -110,7 +110,7 @@ def excluded_data(self, path_filters: str | None = None) -> list[dict[str, Any]] return [ data for api_key in self.excluded_api_keys - for data in interfaces.backend_v2.get_data(path_filters=path_filters, with_api_key=api_key) + for data in interfaces.mocked_backend.get_data(path_filters=path_filters, with_api_key=api_key) ] @@ -125,7 +125,7 @@ def feature_flagging_evp_egress() -> FeatureFlaggingEVPEgress: assert "serverless-init" in scenario.components # serverless-init relays the events: the SDK must not send them straight to the intake return FeatureFlaggingEVPEgress( - interfaces.backend_v2, + interfaces.mocked_backend, "sidecar", excluded_api_keys=(scenario.weblog_api_key,), expected_api_key=scenario.sidecar_api_key, @@ -133,7 +133,7 @@ def feature_flagging_evp_egress() -> FeatureFlaggingEVPEgress: assert scenario.exposure_egress == "direct" assert "serverless-init" not in scenario.components - return FeatureFlaggingEVPEgress(interfaces.backend_v2, "direct", expected_api_key=scenario.weblog_api_key) + return FeatureFlaggingEVPEgress(interfaces.mocked_backend, "direct", expected_api_key=scenario.weblog_api_key) def register_expected_evp_capture(path: str) -> None: @@ -468,7 +468,7 @@ def assert_agentless_evp_topology(egress: FeatureFlaggingEVPEgress) -> None: assert name not in environment assert "serverless-init" not in scenario.components assert scenario.serverless_init_container is None - assert_no_evp_proxy_requests(interfaces.backend_v2.get_data(with_api_key=scenario.weblog_api_key)) + assert_no_evp_proxy_requests(interfaces.mocked_backend.get_data(with_api_key=scenario.weblog_api_key)) return assert egress.route == "sidecar" diff --git a/tests/test_otlp_runtime_metrics.py b/tests/test_otlp_runtime_metrics.py index 1f5e229ec28..718da081477 100644 --- a/tests/test_otlp_runtime_metrics.py +++ b/tests/test_otlp_runtime_metrics.py @@ -251,7 +251,7 @@ def get_runtime_metrics_by_name() -> dict[str, list[dict[str, str]]]: Tags are parsed from "key:value" strings in the series the agent sent to the mocked backend. """ result: dict[str, list[dict[str, str]]] = {} - for _, metric in interfaces.backend_v2.get_metrics(): + for _, metric in interfaces.mocked_backend.get_metrics(): name: str = metric["metric"] tags: dict[str, str] = dict(tag.split(":", 1) for tag in metric.get("tags", []) if ":" in tag) result.setdefault(name, []).append(tags) @@ -268,7 +268,7 @@ def wait_for_runtime_metrics(library: str) -> None: if not expected: return - interfaces.backend_v2.wait_for( + interfaces.mocked_backend.wait_for( lambda _: expected.keys() <= get_runtime_metrics_by_name().keys(), timeout=RUNTIME_METRICS_WAIT_TIMEOUT, ) diff --git a/tests/test_the_test/test_docker_scenario.py b/tests/test_the_test/test_docker_scenario.py index bbcf643d0cd..e14825a86d8 100644 --- a/tests/test_the_test/test_docker_scenario.py +++ b/tests/test_the_test/test_docker_scenario.py @@ -140,10 +140,8 @@ def test_end_to_end_scenario_only_flushes_agent_backed_non_empty_test_runs( @scenarios.test_the_test -def test_mocked_backend_v2_agent_sends_to_the_mocked_backend_container(monkeypatch: pytest.MonkeyPatch) -> None: - scenario = DdTraceEndToEndScenario( - "FAKE_MOCKED_BACKEND_V2", doc="", mocked_backend_v2=True, use_proxy_for_agent=False - ) +def test_mocked_backend_agent_sends_to_the_mocked_backend_container(monkeypatch: pytest.MonkeyPatch) -> None: + scenario = DdTraceEndToEndScenario("FAKE_MOCKED_BACKEND_V2", doc="", mocked_backend=True, use_proxy_for_agent=False) mocked_backend = scenario.mocked_backend_container assert mocked_backend in scenario._containers # noqa: SLF001 @@ -161,7 +159,7 @@ def test_mocked_backend_v2_agent_sends_to_the_mocked_backend_container(monkeypat @scenarios.test_the_test -def test_no_mocked_backend_container_without_mocked_backend_v2() -> None: +def test_no_mocked_backend_container_without_mocked_backend() -> None: scenario = DdTraceEndToEndScenario("FAKE_NO_MOCKED_BACKEND_V2", doc="", use_proxy_for_agent=False) assert scenario.mocked_backend_container not in scenario._containers # noqa: SLF001 assert "DD_DD_URL" not in scenario.agent_container.environment diff --git a/tests/test_the_test/test_ffe_tests.py b/tests/test_the_test/test_ffe_tests.py index 14057ca1d1f..8c99dbe4ca5 100644 --- a/tests/test_the_test/test_ffe_tests.py +++ b/tests/test_the_test/test_ffe_tests.py @@ -386,9 +386,9 @@ def test_feature_flagging_agentless_evp_topology_supports_both_routes( scenario.weblog_infra.http_container._library = ComponentVersion("java", "0.66.0") # noqa: SLF001 scenario._last_direct_evp_runtime_evidence = _direct_runtime_evidence("java") # noqa: SLF001 monkeypatch.setattr(context, "scenario", scenario) - monkeypatch.setattr(interfaces.backend_v2, "get_data", lambda **_: []) + monkeypatch.setattr(interfaces.mocked_backend, "get_data", lambda **_: []) - assert_agentless_evp_topology(FeatureFlaggingEVPEgress(interfaces.backend_v2, route)) + assert_agentless_evp_topology(FeatureFlaggingEVPEgress(interfaces.mocked_backend, route)) environment = scenario.weblog_infra.library_container.environment for runtime_trust_variable in ("REQUESTS_CA_BUNDLE", "SSL_CERT_FILE"): @@ -407,7 +407,7 @@ def test_feature_flagging_agentless_evp_topology_supports_both_routes( library_container._fix_host_pwd_in_volumes() # noqa: SLF001 - reproduce container start normalization normalized_source = f"{library_container.host_project_dir}{DIRECT_EVP_CA_BUNDLE_SOURCE[1:]}" assert library_container.volumes[normalized_source] == expected_mount - assert_agentless_evp_topology(FeatureFlaggingEVPEgress(interfaces.backend_v2, route)) + assert_agentless_evp_topology(FeatureFlaggingEVPEgress(interfaces.mocked_backend, route)) @scenarios.test_the_test diff --git a/tests/test_the_test/test_mock_backend_v2.py b/tests/test_the_test/test_mock_backend_v2.py index dffe3d543fd..0185c0781cf 100644 --- a/tests/test_the_test/test_mock_backend_v2.py +++ b/tests/test_the_test/test_mock_backend_v2.py @@ -19,7 +19,7 @@ from cryptography.hazmat.primitives.serialization import pkcs12 from utils import scenarios -from utils.interfaces._backend_v2 import _BackendV2InterfaceValidator +from utils.interfaces._mocked_backend import _MockedBackendInterfaceValidator from utils._context.containers import MockedBackendContainer, TestedContainer from utils._context._scenarios.agentless_endtoend import JAVA_TRUSTSTORE_SOURCE from utils.mocked_backend import MockedBackendClient, MockedBackendServer @@ -330,7 +330,7 @@ def test_runs_without_the_rest_of_utils(tmp_path: Path): @scenarios.test_the_test def test_entry_point_serves_until_sigterm(tmp_path: Path): """`python -m utils.mocked_backend` is how the mocked backend will run in its own container.""" - log_folder = tmp_path / "backend_v2" # created by the entry point + log_folder = tmp_path / "mocked_backend" # created by the entry point process = subprocess.Popen( [sys.executable, "-m", "utils.mocked_backend", "--port", "0", "--log-folder", str(log_folder)], cwd=Path(__file__).parents[2], @@ -369,9 +369,11 @@ def test_health_endpoint(server: MockedBackendServer, tmp_path: Path): assert list(tmp_path.glob("*.json")) == [] -def _backend_v2_with_requests(tmp_path: Path, requests_: list[tuple[str, str | None]]) -> _BackendV2InterfaceValidator: - """A backend_v2 interface that received a series request per (filename, api_key)""" - interface = _BackendV2InterfaceValidator() +def _mocked_backend_with_requests( + tmp_path: Path, requests_: list[tuple[str, str | None]] +) -> _MockedBackendInterfaceValidator: + """A mocked backend interface that received a series request per (filename, api_key)""" + interface = _MockedBackendInterfaceValidator() interface.configure(str(tmp_path), replay=False) for filename, api_key in requests_: headers = [["Content-Type", "application/json"]] + ([["DD-API-KEY", api_key]] if api_key else []) @@ -388,8 +390,8 @@ def _backend_v2_with_requests(tmp_path: Path, requests_: list[tuple[str, str | N @scenarios.test_the_test -def test_backend_v2_with_api_key_only_returns_requests_sent_with_this_key(tmp_path: Path): - interface = _backend_v2_with_requests( +def test_mocked_backend_with_api_key_only_returns_requests_sent_with_this_key(tmp_path: Path): + interface = _mocked_backend_with_requests( tmp_path, [("000__agent.json", "agent-key"), ("001__sidecar.json", "sidecar-key"), ("002__nokey.json", None)] ) @@ -403,8 +405,8 @@ def test_backend_v2_with_api_key_only_returns_requests_sent_with_this_key(tmp_pa @scenarios.test_the_test -def test_backend_v2_with_api_key_ignores_the_header_name_case(tmp_path: Path): - interface = _backend_v2_with_requests(tmp_path, [("000__agent.json", "agent-key")]) +def test_mocked_backend_with_api_key_ignores_the_header_name_case(tmp_path: Path): + interface = _mocked_backend_with_requests(tmp_path, [("000__agent.json", "agent-key")]) data = next(interface.get_data()) data["request"]["headers"] = [["dd-api-key", "agent-key"]] diff --git a/tests/test_the_test/test_mock_ffe_agentless_backend.py b/tests/test_the_test/test_mock_ffe_agentless_backend.py index 1e4fc384948..955071551dd 100644 --- a/tests/test_the_test/test_mock_ffe_agentless_backend.py +++ b/tests/test_the_test/test_mock_ffe_agentless_backend.py @@ -302,8 +302,8 @@ def wait_for(matcher: Callable[[dict[str, Any]], bool], *, timeout: int) -> bool return matcher(next(captures)) wait = MagicMock() - monkeypatch.setattr(interfaces.backend_v2, "wait_for", wait_for) - monkeypatch.setattr(interfaces.backend_v2, "wait", wait) + monkeypatch.setattr(interfaces.mocked_backend, "wait_for", wait_for) + monkeypatch.setattr(interfaces.mocked_backend, "wait", wait) scenario._wait_for_expected_evp_captures(is_empty_test_run=False) # noqa: SLF001 @@ -485,9 +485,9 @@ def wait_for(matcher: Callable[[dict[str, Any]], bool], *, timeout: int) -> bool return any(matcher(candidate) for candidate in (priming_capture, capture)) settle = MagicMock(side_effect=lambda _: lifecycle.append("settle")) - monkeypatch.setattr(interfaces.backend_v2, "get_data", get_data) - monkeypatch.setattr(interfaces.backend_v2, "wait_for", wait_for) - monkeypatch.setattr(interfaces.backend_v2, "wait", settle) + monkeypatch.setattr(interfaces.mocked_backend, "get_data", get_data) + monkeypatch.setattr(interfaces.mocked_backend, "wait_for", wait_for) + monkeypatch.setattr(interfaces.mocked_backend, "wait", settle) runtime_container = MagicMock() runtime_container.status = "exited" @@ -552,7 +552,7 @@ def test_agentless_end_to_end_scenario_stops_backend_when_status_fails( monkeypatch.setattr(scenario, "mocked_backend_container", container) with pytest.raises(RuntimeError, match="status failed"): - scenario._stop_mocked_backend_v2() # noqa: SLF001 - focused lifecycle test + scenario._stop_mocked_backend() # noqa: SLF001 - focused lifecycle test container.stop.assert_called_once_with() @@ -580,7 +580,7 @@ def test_agentless_end_to_end_scenario_persists_backend_status_for_replay( container.client.ffe_get_status.return_value = expected_status monkeypatch.setattr(recording_scenario, "mocked_backend_container", container) - recording_scenario._stop_mocked_backend_v2() # noqa: SLF001 - focused lifecycle test + recording_scenario._stop_mocked_backend() # noqa: SLF001 - focused lifecycle test container.stop.assert_called_once_with() assert recording_scenario.mock_backend_status() == expected_status diff --git a/tests/test_v1_payloads.py b/tests/test_v1_payloads.py index e767976a7d9..6d28a0b988b 100644 --- a/tests/test_v1_payloads.py +++ b/tests/test_v1_payloads.py @@ -24,7 +24,7 @@ def setup_field_changes(self): def test_field_changes(self): library_traces = list(interfaces.library.get_traces(self.r)) - agent_traces = list(interfaces.backend_v2.get_traces(self.r)) + agent_traces = list(interfaces.mocked_backend.get_traces(self.r)) assert len(library_traces) == 1 _, trace = library_traces[0] assert isinstance(trace.raw_trace, dict) diff --git a/utils/_context/_scenarios/_core/endtoend.py b/utils/_context/_scenarios/_core/endtoend.py index f0567a46469..7ce4729f14a 100644 --- a/utils/_context/_scenarios/_core/endtoend.py +++ b/utils/_context/_scenarios/_core/endtoend.py @@ -47,7 +47,6 @@ def __init__( scenario_groups: list[ScenarioGroup] | None = None, enable_ipv6: bool = False, use_proxy: bool = True, - mocked_backend: bool = True, rc_api_enabled: bool = False, rc_backend_enabled: bool = False, meta_structs_disabled: bool = False, @@ -91,7 +90,6 @@ def __init__( client_drop_p0s=client_drop_p0s, obfuscation_version=obfuscation_version, enable_ipv6=enable_ipv6, - mocked_backend=mocked_backend, ) self._containers.append(self.proxy_container) @@ -240,7 +238,7 @@ def __init__( include_agent: bool = True, include_opentelemetry: bool = False, require_api_key: bool = False, - mocked_backend_v2: bool = False, + mocked_backend: bool = False, other_weblog_containers: tuple[type[TestedContainer], ...] = (), ) -> None: scenario_groups = [*self._default_scenario_groups, *(scenario_groups or [])] @@ -268,22 +266,22 @@ def __init__( self._use_proxy_for_agent = include_agent and use_proxy_for_agent self._use_proxy_for_weblog = use_proxy_for_weblog self._require_api_key = require_api_key - self._mocked_backend_v2 = mocked_backend_v2 + self._mocked_backend = mocked_backend - if mocked_backend_v2 and self._use_proxy_for_agent: + if mocked_backend and self._use_proxy_for_agent: raise ValueError( - "mocked_backend_v2 is not compatible with use_proxy_for_agent: the agent can't send its " + "mocked_backend is not compatible with use_proxy_for_agent: the agent can't send its " "traffic to both the proxy and the mocked backend. Set use_proxy_for_agent=False." ) self.dd_api_key = ( - FakeDatadogKey.DEFAULT if mocked_backend_v2 else os.environ.get("DD_API_KEY", FakeDatadogKey.DEFAULT) + FakeDatadogKey.DEFAULT if mocked_backend else os.environ.get("DD_API_KEY", FakeDatadogKey.DEFAULT) ) """The API key used by the agent to send data to the backend""" # it serves HTTPS on its domain, and on the intake hostnames derived from it (see MOCKED_BACKEND_DOMAIN) self.mocked_backend_container = MockedBackendContainer(tls=True) - if mocked_backend_v2: + if mocked_backend: self._containers.append(self.mocked_backend_container) if include_agent: agent_env = dict(agent_env) if agent_env else {} @@ -367,8 +365,8 @@ def configure(self, config: pytest.Config): interfaces.library.configure(self.host_log_folder, replay=self.replay) if self._require_api_key: # only used by scenarios querying the real Datadog backend interfaces.backend_legacy.configure(self.host_log_folder, replay=self.replay) - if self._mocked_backend_v2: - interfaces.backend_v2.configure(self.host_log_folder, replay=self.replay) + if self._mocked_backend: + interfaces.mocked_backend.configure(self.host_log_folder, replay=self.replay) interfaces.library_dotnet_managed.configure(self.host_log_folder, replay=self.replay) interfaces.library_stdout.configure(self.host_log_folder, replay=self.replay) if self.include_agent: @@ -412,7 +410,7 @@ def configure(self, config: pytest.Config): self.warmups.append(self._set_weblog_domain) self.warmups.append(self._set_components) - def _stop_mocked_backend_v2(self) -> None: + def _stop_mocked_backend(self) -> None: """Called once the agent and the weblog are stopped. Subclasses can extend it to read the mocked backend state before it stops. """ @@ -429,7 +427,7 @@ def _set_containers_dependancies(self) -> None: for buddy in self.buddies: buddy.depends_on.append(self.agent_container) - if self._mocked_backend_v2: + if self._mocked_backend: if self.include_agent: self.agent_container.depends_on.append(self.mocked_backend_container) # e.g. agentless libraries may reach it as soon as they start @@ -442,7 +440,7 @@ def _start_interfaces_watchdog(self): ) agent_interfaces: list[ProxyBasedInterfaceValidator] = [interfaces.agent] if self.include_agent else [] backend_interfaces: list[ProxyBasedInterfaceValidator] = ( - [interfaces.backend_v2] if self._mocked_backend_v2 else [] + [interfaces.mocked_backend] if self._mocked_backend else [] ) super().start_interfaces_watchdog( [interfaces.library] @@ -512,9 +510,9 @@ def _wait_and_stop_containers(self, *, is_empty_test_run: bool): if self._require_api_key: interfaces.backend_legacy.load_data_from_logs() - if self._mocked_backend_v2: - interfaces.backend_v2.load_data_from_logs() - interfaces.backend_v2.check_deserialization_errors() + if self._mocked_backend: + interfaces.mocked_backend.load_data_from_logs() + interfaces.mocked_backend.check_deserialization_errors() if self.include_opentelemetry: interfaces.open_telemetry.load_data_from_logs() @@ -545,13 +543,13 @@ def _wait_and_stop_containers(self, *, is_empty_test_run: bool): self._wait_interface( interfaces.open_telemetry, 0 if is_empty_test_run else self.backend_interface_timeout ) - if self._mocked_backend_v2: + if self._mocked_backend: # stopped last: it receives what the agent and the weblog send until they stop - self._stop_mocked_backend_v2() + self._stop_mocked_backend() # the watchdog polls files about once per second: the last ones may not be ingested yet. Nothing else # can arrive now, so ingest them all instead of waiting an arbitrary time - interfaces.backend_v2.ingest_all_files() - interfaces.backend_v2.check_deserialization_errors() + interfaces.mocked_backend.ingest_all_files() + interfaces.mocked_backend.check_deserialization_errors() def _stop_weblog(self, *, is_empty_test_run: bool) -> None: """Stop the weblog after setup traffic has been generated.""" @@ -634,7 +632,7 @@ def __init__( include_opentelemetry: bool = False, library_interface_timeout: int | None = None, meta_structs_disabled: bool = False, - mocked_backend_v2: bool = False, + mocked_backend: bool = False, obfuscation_version: int | None | Literal["MISSING"] = None, other_weblog_containers: tuple[type[TestedContainer], ...] = (), rc_api_enabled: bool = False, @@ -663,7 +661,7 @@ def __init__( include_opentelemetry=include_opentelemetry, library_interface_timeout=library_interface_timeout, meta_structs_disabled=meta_structs_disabled, - mocked_backend_v2=mocked_backend_v2, + mocked_backend=mocked_backend, obfuscation_version=obfuscation_version, other_weblog_containers=other_weblog_containers, rc_api_enabled=rc_api_enabled, diff --git a/utils/_context/_scenarios/agentless_endtoend.py b/utils/_context/_scenarios/agentless_endtoend.py index 03e5ae6ba09..7571a8b1904 100644 --- a/utils/_context/_scenarios/agentless_endtoend.py +++ b/utils/_context/_scenarios/agentless_endtoend.py @@ -82,7 +82,7 @@ def __init__( use_proxy_for_agent=False, use_proxy_for_weblog=False, weblog_env=weblog_env, - mocked_backend_v2=True, + mocked_backend=True, ) # The tested library fetches its agentless configuration from the mocked backend container @@ -137,7 +137,7 @@ def _load_mock_backend_status(self) -> None: json.loads(self._mock_backend_status_path.read_text(encoding="utf-8")), ) - def _stop_mocked_backend_v2(self) -> None: + def _stop_mocked_backend(self) -> None: # The mocked backend counters are not recorded as interface data: persist them for replay # TODO : remove this, as it will strongly depends on test order. # Either we need to call the client in setup method, or the interface in test methods. @@ -149,7 +149,7 @@ def _stop_mocked_backend_v2(self) -> None: encoding="utf-8", ) finally: - super()._stop_mocked_backend_v2() + super()._stop_mocked_backend() class FeatureFlaggingAgentlessEndToEndScenario(_AgentlessEndToEndScenario): @@ -240,10 +240,10 @@ def evp_api_key(self) -> str: def _is_evp_capture(self, data: dict[str, Any]) -> bool: """True if the mocked backend received this request with evp_api_key""" - return interfaces.backend_v2.get_api_key(data) == self.evp_api_key + return interfaces.mocked_backend.get_api_key(data) == self.evp_api_key def _evp_captures(self) -> list[dict[str, Any]]: - return list(interfaces.backend_v2.get_data(with_api_key=self.evp_api_key)) + return list(interfaces.mocked_backend.get_data(with_api_key=self.evp_api_key)) def register_expected_evp_capture(self, path: str) -> None: """Register a canonical signal path that must be captured before shutdown.""" @@ -529,7 +529,7 @@ def priming_matcher(data: dict[str, Any]) -> bool: priming_started_at = datetime.now(UTC) priming_response = weblog.post(priming_evaluation.request_path, json=priming_evaluation.body) priming_finished_at = datetime.now(UTC) - priming_observed = interfaces.backend_v2.wait_for(priming_matcher, timeout=DIRECT_EVP_CAPTURE_WAIT_SECONDS) + priming_observed = interfaces.mocked_backend.wait_for(priming_matcher, timeout=DIRECT_EVP_CAPTURE_WAIT_SECONDS) priming_captures = list(filter(priming_matcher, self._evp_captures())) if not priming_observed or len(priming_captures) != 1: raise RuntimeError( @@ -558,8 +558,8 @@ def priming_matcher(data: dict[str, Any]) -> bool: stopped_state = self._stopped_container_state(runtime_container) shutdown_markers, shutdown_marker_errors = self._shutdown_markers(runtime_container) - capture_observed = interfaces.backend_v2.wait_for(matcher, timeout=DIRECT_EVP_CAPTURE_WAIT_SECONDS) - interfaces.backend_v2.wait(DIRECT_EVP_CAPTURE_SETTLE_SECONDS) + capture_observed = interfaces.mocked_backend.wait_for(matcher, timeout=DIRECT_EVP_CAPTURE_WAIT_SECONDS) + interfaces.mocked_backend.wait(DIRECT_EVP_CAPTURE_SETTLE_SECONDS) matching_after = list(filter(matcher, self._evp_captures())) self._last_direct_evp_shutdown_evidence = { "capture_files": [capture.get("log_filename") for capture in matching_after], @@ -618,16 +618,16 @@ def _wait_for_expected_evp_captures(self, *, is_empty_test_run: bool) -> None: def captured(data: dict[str, Any], expected_path: str = path) -> bool: return self._is_evp_capture(data) and data.get("path") == expected_path - logger.terminal.write_sep("-", f"Wait for {path} on {interfaces.backend_v2} before stopping the weblog") + logger.terminal.write_sep("-", f"Wait for {path} on {interfaces.mocked_backend} before stopping the weblog") logger.terminal.flush() - if not interfaces.backend_v2.wait_for(captured, timeout=DIRECT_EVP_CAPTURE_WAIT_SECONDS): + if not interfaces.mocked_backend.wait_for(captured, timeout=DIRECT_EVP_CAPTURE_WAIT_SECONDS): missing_paths.append(path) if missing_paths: raise RuntimeError(f"Timed out waiting for Feature Flags EVP captures: {', '.join(missing_paths)}") # Preserve a bounded window in which an unsafe retry would appear as a duplicate capture. - interfaces.backend_v2.wait(DIRECT_EVP_CAPTURE_SETTLE_SECONDS) + interfaces.mocked_backend.wait(DIRECT_EVP_CAPTURE_SETTLE_SECONDS) def _wait_and_stop_containers(self, *, is_empty_test_run: bool) -> None: try: diff --git a/utils/_context/_scenarios/apm_tracing.py b/utils/_context/_scenarios/apm_tracing.py index 654751ad7fd..589a085650a 100644 --- a/utils/_context/_scenarios/apm_tracing.py +++ b/utils/_context/_scenarios/apm_tracing.py @@ -9,7 +9,7 @@ def __init__(self) -> None: super().__init__( "APM_TRACING_E2E_OTEL", weblog_env={"DD_TRACE_OTEL_ENABLED": "true"}, - mocked_backend_v2=True, + mocked_backend=True, use_proxy_for_agent=False, doc="", ) @@ -25,7 +25,7 @@ def __init__(self) -> None: ), "DD_TRACE_SAMPLE_RATE": "0", }, - mocked_backend_v2=True, + mocked_backend=True, use_proxy_for_agent=False, doc="", ) @@ -60,7 +60,7 @@ def __init__(self) -> None: agent_env={ "DD_APM_ENABLE_V1_TRACE_ENDPOINT": "true", }, - mocked_backend_v2=True, + mocked_backend=True, use_proxy_for_agent=False, doc="End-to-end testing scenario focused on efficient payload handling and v1 trace format validation", ) diff --git a/utils/_context/_scenarios/open_telemetry.py b/utils/_context/_scenarios/open_telemetry.py index 0a7876a1590..f2dcd7f48a2 100644 --- a/utils/_context/_scenarios/open_telemetry.py +++ b/utils/_context/_scenarios/open_telemetry.py @@ -43,7 +43,6 @@ def __init__( include_intake: bool = True, backend_interface_timeout: int = 20, require_api_key: bool = False, - mocked_backend: bool = True, extra_containers: tuple[type[TestedContainer], ...] = (), ) -> None: super().__init__( @@ -53,7 +52,6 @@ def __init__( scenario_groups=[scenario_groups.all, scenario_groups.open_telemetry], weblog_categories=[WeblogCategory.open_telemetry], use_proxy=True, - mocked_backend=mocked_backend, extra_containers=extra_containers, ) if include_agent: diff --git a/utils/_context/_scenarios/otel_collector.py b/utils/_context/_scenarios/otel_collector.py index 5e3f4a97e11..6a6ebf59250 100644 --- a/utils/_context/_scenarios/otel_collector.py +++ b/utils/_context/_scenarios/otel_collector.py @@ -22,7 +22,6 @@ def __init__(self) -> None: doc="TODO", scenario_groups=[scenario_groups.end_to_end, scenario_groups.all, scenario_groups.open_telemetry], use_proxy=True, - mocked_backend=True, ) self.postgres_container = PostgresContainer() @@ -54,14 +53,6 @@ def configure(self, config: pytest.Config) -> None: self.collector_container.depends_on.append(self.postgres_container) - if not self.proxy_container.mocked_backend: - interfaces.backend_legacy.configure(self.host_log_folder, replay=self.replay) - - if "DD_API_KEY" not in os.environ: - pytest.exit(f"{self.name} scenario requires a valid DD_API_KEY") - - self.collector_container.environment["DD_API_KEY"] = os.environ["DD_API_KEY"] - postgres_image = self.postgres_container.image.name image_parts = postgres_image.split(":") docker_image_name = image_parts[0] if len(image_parts) > 0 else "unknown" diff --git a/utils/_context/_scenarios/runtime_metrics.py b/utils/_context/_scenarios/runtime_metrics.py index c6f9cf39559..7de0b090418 100644 --- a/utils/_context/_scenarios/runtime_metrics.py +++ b/utils/_context/_scenarios/runtime_metrics.py @@ -32,7 +32,7 @@ def __init__(self) -> None: runtime_metrics_enabled=True, include_opentelemetry=True, library_interface_timeout=20, - mocked_backend_v2=True, + mocked_backend=True, use_proxy_for_agent=False, doc="Test ddtrace runtime metrics exported via OTLP with OTel semantic convention names", ) diff --git a/utils/_context/containers.py b/utils/_context/containers.py index 0e63626d2dc..da6d433fab4 100644 --- a/utils/_context/containers.py +++ b/utils/_context/containers.py @@ -665,7 +665,6 @@ def __init__( client_drop_p0s: bool | None = None, obfuscation_version: int | None | Literal["MISSING"] = None, enable_ipv6: bool, - mocked_backend: bool = True, ) -> None: """Parameters: span_events: Whether the agent supports the native serialization of span events @@ -673,9 +672,6 @@ def __init__( """ - if rc_api_enabled and not mocked_backend: - raise ValueError("rc_backend_enabled requires mocked_backend") - # Adjust healthcheck for IPv6 scenarios host_target = "::1" if enable_ipv6 else "localhost" socket_family = "socket.AF_INET6" if enable_ipv6 else "socket.AF_INET" @@ -688,7 +684,6 @@ def __init__( "DD_API_KEY": os.environ.get("DD_API_KEY"), "DD_APP_KEY": os.environ.get("DD_APP_KEY"), "SYSTEM_TESTS_IPV6": str(enable_ipv6), - "SYSTEM_TESTS_MOCKED_BACKEND": str(mocked_backend), }, working_dir="/app", volumes={ @@ -751,8 +746,6 @@ def __init__( ), ] - self.mocked_backend = mocked_backend - def configure(self, *, host_log_folder: str, replay: bool): super().configure(host_log_folder=host_log_folder, replay=replay) @@ -785,7 +778,7 @@ def configure(self, *, host_log_folder: str, replay: bool): class MockedBackendContainer(TestedContainer): """The mocked backend (utils/mocked_backend), standing in for the Datadog backend in its own container. - What it receives is recorded in the logs folder, and read by interfaces.backend_v2. + What it receives is recorded in the logs folder, and read by interfaces.mocked_backend. """ # With tls, it serves HTTPS instead of HTTP: for senders that only speak HTTPS to the intake hostnames derived @@ -836,7 +829,7 @@ def configure(self, *, host_log_folder: str, replay: bool): super().configure(host_log_folder=host_log_folder, replay=replay) # Same relative path in the container and on the host, so recorded log filenames are the same - log_folder = f"{host_log_folder}/interfaces/backend_v2" + log_folder = f"{host_log_folder}/interfaces/mocked_backend" self.volumes[f"./{log_folder}"] = {"bind": f"/app/{log_folder}", "mode": "rw"} self.command = [ "python", @@ -851,7 +844,7 @@ def configure(self, *, host_log_folder: str, replay: bool): self.command += ["--tls-cert-file", self.tls_cert_file] if self.internal_mocked_responses: - # not in the recordings folder: interfaces.backend_v2 reads every JSON file there + # not in the recordings folder: interfaces.mocked_backend reads every JSON file there mocks_path = f"{self.log_folder_path}/{MockedBackendResponse.internal_filename}" with Path(mocks_path).open(encoding="utf-8", mode="w") as f: json.dump([mock.to_json() for mock in self.internal_mocked_responses], f, indent=2) diff --git a/utils/interfaces/__init__.py b/utils/interfaces/__init__.py index 1f268027622..0f1425b05ff 100644 --- a/utils/interfaces/__init__.py +++ b/utils/interfaces/__init__.py @@ -3,8 +3,8 @@ # Copyright 2021 Datadog, Inc. from ._agent import AgentInterfaceValidator -from ._backend import _BackendInterfaceValidator -from ._backend_v2 import _BackendV2InterfaceValidator +from ._backend_legacy import _BackendLegacyInterfaceValidator +from ._mocked_backend import _MockedBackendInterfaceValidator from ._library.core import LibraryInterfaceValidator from ._core import ProxyBasedInterfaceValidator from ._logs import ( @@ -24,8 +24,8 @@ library_stdout = _LibraryStdout() agent_stdout = _AgentStdout() library_dotnet_managed = _LibraryDotnetManaged() -backend_legacy = _BackendInterfaceValidator(library_interface=library) -backend_v2 = _BackendV2InterfaceValidator() +backend_legacy = _BackendLegacyInterfaceValidator(library_interface=library) +mocked_backend = _MockedBackendInterfaceValidator() open_telemetry = OpenTelemetryInterfaceValidator() otel_collector = ProxyBasedInterfaceValidator("otel_collector") postgres = _PostgresStdout() @@ -43,12 +43,12 @@ "agent", "agent_stdout", "backend_legacy", - "backend_v2", "golang_buddy", "java_buddy", "library", "library_dotnet_managed", "library_stdout", + "mocked_backend", "nodejs_buddy", "open_telemetry", "postgres", diff --git a/utils/interfaces/_backend.py b/utils/interfaces/_backend_legacy.py similarity index 99% rename from utils/interfaces/_backend.py rename to utils/interfaces/_backend_legacy.py index 70d506b9a75..a2d7ee0e48f 100644 --- a/utils/interfaces/_backend.py +++ b/utils/interfaces/_backend_legacy.py @@ -18,7 +18,7 @@ from utils._weblog import HttpResponse -class _BackendInterfaceValidator(ProxyBasedInterfaceValidator): +class _BackendLegacyInterfaceValidator(ProxyBasedInterfaceValidator): """Validate backend data processors""" def __init__(self, library_interface: LibraryInterfaceValidator): diff --git a/utils/interfaces/_backend_v2.py b/utils/interfaces/_mocked_backend.py similarity index 95% rename from utils/interfaces/_backend_v2.py rename to utils/interfaces/_mocked_backend.py index e585efc771e..ebc69a67210 100644 --- a/utils/interfaces/_backend_v2.py +++ b/utils/interfaces/_mocked_backend.py @@ -18,9 +18,9 @@ from utils.interfaces._misc_validators import HeadersPresenceValidator -class _BackendV2InterfaceValidator(ProxyBasedInterfaceValidator): +class _MockedBackendInterfaceValidator(ProxyBasedInterfaceValidator): def __init__(self): - super().__init__("backend_v2") + super().__init__("mocked_backend") def ingest_all_files(self) -> None: """Ingest every recorded file not seen yet by the watchdog. To call once the mocked backend is stopped. @@ -63,14 +63,14 @@ def get_traces( rid = request.get_rid() if request else None if rid: - logger.debug(f"Will try to find backend_v2 spans related to request {rid}") + logger.debug(f"Will try to find mocked_backend spans related to request {rid}") for data in self.get_data(path_filters="/api/v0.2/traces", with_api_key=with_api_key): - logger.debug(f"Looking at backend_v2 data {data['log_filename']}") + logger.debug(f"Looking at mocked_backend data {data['log_filename']}") if "content" not in data["request"]: raise ValueError( - f"backend_v2 request in {data['log_filename']} could not be deserialized: " + f"mocked_backend request in {data['log_filename']} could not be deserialized: " f"{data['request'].get('traceback', data['request'].get('raw_content'))}" ) @@ -110,7 +110,7 @@ def get_spans( rid = request.get_rid() if request else None if rid: - logger.debug(f"Will try to find backend_v2 spans related to request {rid}") + logger.debug(f"Will try to find mocked_backend spans related to request {rid}") for data, trace in self.get_traces(request=request, with_api_key=with_api_key): for span in trace.spans: diff --git a/utils/mocked_backend/__main__.py b/utils/mocked_backend/__main__.py index 2e4472e58a1..a2effdc0803 100644 --- a/utils/mocked_backend/__main__.py +++ b/utils/mocked_backend/__main__.py @@ -1,6 +1,6 @@ """Run the mocked backend in its own process, e.g. in a container: - python -m utils.mocked_backend --port 4900 --log-folder logs/interfaces/backend_v2 + python -m utils.mocked_backend --port 4900 --log-folder logs/interfaces/mocked_backend It serves until it receives SIGTERM (sent by `docker stop`) or SIGINT. """ diff --git a/utils/mocked_backend/_backend.py b/utils/mocked_backend/_backend.py index d5729a0173f..3b7af6d2b0c 100644 --- a/utils/mocked_backend/_backend.py +++ b/utils/mocked_backend/_backend.py @@ -1,9 +1,9 @@ """MockedBackendServer: the base class for every mocked HTTP backend, and, used as-is, the generic -mocked backend standing in for the real Datadog backend API used by ``interfaces.backend_v2`` +mocked backend standing in for the real Datadog backend API used by ``interfaces.mocked_backend`` (``utils/interfaces/_backend.py``). Used directly, its only job is to record every request it receives into the interface's log folder -(``logs/interfaces/backend_v2``), the same way every other interface persists what it observes. +(``logs/interfaces/mocked_backend``), the same way every other interface persists what it observes. """ from __future__ import annotations diff --git a/utils/proxy/core.py b/utils/proxy/core.py index b892ea40bb2..001ac455682 100644 --- a/utils/proxy/core.py +++ b/utils/proxy/core.py @@ -133,8 +133,6 @@ def __init__(self) -> None: self.log_folder = os.environ["SYSTEM_TESTS_LOG_FOLDER"] - self.mocked_backend = os.environ.get("SYSTEM_TESTS_MOCKED_BACKEND") == "True" - self.tracing_agent_target_host = os.environ.get("PROXY_TRACING_AGENT_TARGET_HOST", "agent") self.tracing_agent_target_port = int(os.environ.get("PROXY_TRACING_AGENT_TARGET_PORT", "8127")) @@ -178,8 +176,6 @@ def _store_mocked_reponses(self, flow: HTTPFlow, target: Literal["tracer", "back flow.response = http.Response.make(200, b"Ok") async def running(self) -> None: - if not self.mocked_backend: - return ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) ssl_ctx.load_cert_chain(_MITMPROXY_CA_PEM) self._mock_upstream_server = await asyncio.start_server( @@ -190,7 +186,7 @@ async def running(self) -> None: def http_connect(self, flow: HTTPFlow) -> None: proxy_port = flow.client_conn.sockname[1] logger.info(f"Flow {flow.id}: CONNECT {flow.request.host}:{flow.request.port} using proxy port {proxy_port}") - if proxy_port in _MOCKED_BACKEND_PORTS and self.mocked_backend: + if proxy_port in _MOCKED_BACKEND_PORTS: # Redirect to local stub TLS server so mitmproxy can always complete tunnel setup. # Without this, CONNECT handshake is performed to the backend, and if ever it fails, # request() never fires. @@ -254,7 +250,7 @@ def request(self, flow: HTTPFlow): logger.info(f"Flow {flow.id}: reverse proxy to {flow.request.pretty_url}") - elif proxy_port == ProxyPorts.otel_collector and self.mocked_backend: + elif proxy_port == ProxyPorts.otel_collector: flow.response = http.Response.make(200, b"Ok") # TODO : response accepted by collector elif proxy_port in ( @@ -271,7 +267,7 @@ def request(self, flow: HTTPFlow): ) flow.request.scheme = "http" logger.info(f"Flow {flow.id}: reverse proxy to {flow.request.pretty_url}") - elif proxy_port in _MOCKED_BACKEND_PORTS and self.mocked_backend: + elif proxy_port in _MOCKED_BACKEND_PORTS: # Since we are faking the backend (generating responses from # scratch), the logic is that the first mock satisfying the # condition wins. Consequently, we check runtime mocks (controlled @@ -425,15 +421,14 @@ def start_proxy() -> None: loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) listen_host = "::" if os.environ.get("SYSTEM_TESTS_IPV6") == "True" else "0.0.0.0" # noqa: S104 - mocked_backend = os.environ.get("SYSTEM_TESTS_MOCKED_BACKEND") == "True" opts = options.Options( mode=modes, listen_host=listen_host, confdir="/app/utils/proxy/.mitmproxy", # When mocking, generate TLS certs from SNI (no upstream fetch needed) and don't # verify the stub server's self-signed cert. - upstream_cert=not mocked_backend, - ssl_insecure=mocked_backend, + upstream_cert=False, + ssl_insecure=True, ) proxy = master.Master(opts, event_loop=loop) proxy.addons.add(*default_addons()) diff --git a/utils/scripts/libraries_and_scenarios_rules.yml b/utils/scripts/libraries_and_scenarios_rules.yml index 33275871daf..c13d5c566d2 100644 --- a/utils/scripts/libraries_and_scenarios_rules.yml +++ b/utils/scripts/libraries_and_scenarios_rules.yml @@ -311,7 +311,7 @@ patterns: utils/mocked_backend/ffe.py: scenario_groups: agentless scenarios: PARAMETRIC - utils/mocked_backend/*: # generic mocked backend, also used by interfaces.backend_v2 + utils/mocked_backend/*: # generic mocked backend, also used by interfaces.mocked_backend scenario_groups: agentless scenarios: [PARAMETRIC, APM_TRACING_E2E_OTEL, APM_TRACING_E2E_SINGLE_SPAN]