From d22d9c32ff71e64fdca0fad50b2791446514fda7 Mon Sep 17 00:00:00 2001 From: Flavien Darche Date: Tue, 10 Mar 2026 19:22:26 +0100 Subject: [PATCH 1/6] part 1 --- .github/workflows/run-end-to-end.yml | 6 - docs/README.md | 2 +- docs/understand/scenarios/README.md | 20 -- tests/appsec/test_alpha.py | 1 - tests/appsec/test_blocking_addresses.py | 41 ---- .../appsec/test_ip_blocking_full_denylist.py | 1 - tests/appsec/test_reports.py | 4 - tests/appsec/test_request_blocking.py | 1 - tests/appsec/test_traces.py | 11 - tests/appsec/test_versions.py | 1 - tests/external_processing/README.md | 14 -- tests/external_processing/__init__.py | 0 tests/external_processing/test_apm.py | 17 -- tests/schemas/test_schemas.py | 3 +- tests/test_config_consistency.py | 1 - tests/test_scrubbing.py | 2 - tests/test_semantic_conventions.py | 2 - tests/test_standard_tags.py | 4 - tests/test_the_test/scenarios.json | 6 +- tests/test_the_test/test_group_rules.py | 2 - utils/_context/_scenarios/__init__.py | 16 -- utils/_context/_scenarios/core.py | 1 - utils/_context/_scenarios/go_proxies.py | 225 ------------------ .../scripts/libraries_and_scenarios_rules.yml | 2 - 24 files changed, 5 insertions(+), 378 deletions(-) delete mode 100644 tests/external_processing/README.md delete mode 100644 tests/external_processing/__init__.py delete mode 100644 tests/external_processing/test_apm.py delete mode 100644 utils/_context/_scenarios/go_proxies.py diff --git a/.github/workflows/run-end-to-end.yml b/.github/workflows/run-end-to-end.yml index 208dfd74611..8c14fbac1a6 100644 --- a/.github/workflows/run-end-to-end.yml +++ b/.github/workflows/run-end-to-end.yml @@ -460,12 +460,6 @@ jobs: - name: Run APPSEC_LAMBDA_INFERRED_SPANS scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_LAMBDA_INFERRED_SPANS"') run: ./run.sh APPSEC_LAMBDA_INFERRED_SPANS - - name: Run GO_PROXIES_DEFAULT scenario - if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"GO_PROXIES_DEFAULT"') - run: ./run.sh GO_PROXIES_DEFAULT --weblog ${{ inputs.weblog }} - - name: Run GO_PROXIES_APPSEC_BLOCKING scenario - if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"GO_PROXIES_APPSEC_BLOCKING"') - run: ./run.sh GO_PROXIES_APPSEC_BLOCKING --weblog ${{ inputs.weblog }} - name: Run OTEL_COLLECTOR scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"OTEL_COLLECTOR"') run: ./run.sh OTEL_COLLECTOR diff --git a/docs/README.md b/docs/README.md index 31bab598ad5..1f11b192f1c 100644 --- a/docs/README.md +++ b/docs/README.md @@ -65,7 +65,7 @@ Deep dives into each scenario type. - **AWS SSI / Onboarding**: [full guide](understand/scenarios/onboarding.md) and [provision structure](understand/scenarios/onboarding_provision_section.md) - **Docker SSI**: [guide](understand/scenarios/docker_ssi.md) - **Kubernetes lib injection**: [overview](understand/scenarios/k8s_library_injection_overview.md), [details](understand/scenarios/k8s_lib_injection.md), and [injector dev](understand/scenarios/k8s_injector_dev.md) -- **Other scenarios**: [AWS Lambda](understand/scenarios/aws_lambda.md), [integration frameworks](understand/scenarios/integration_frameworks.md) (IPv6 and Go proxies are covered in the [scenarios overview](understand/scenarios/README.md)) +- **Other scenarios**: [AWS Lambda](understand/scenarios/aws_lambda.md), [integration frameworks](understand/scenarios/integration_frameworks.md), and [IPv6](understand/scenarios/README.md#ipv6-scenario) ## CI integration diff --git a/docs/understand/scenarios/README.md b/docs/understand/scenarios/README.md index d5968cb93db..ab3248d0962 100644 --- a/docs/understand/scenarios/README.md +++ b/docs/understand/scenarios/README.md @@ -66,26 +66,6 @@ Please note that it requires the docker daemon to support IPv6. It should be ok A user has seen his network function altered after running it on a linux laptop (to be investigated). If it happen, `docker network prune` may solve the issue. -### Go proxies (Envoy and HAProxy) scenario - -```mermaid -flowchart LR -%% Nodes - A("Test runner") - B("Proxy (Envoy or HAProxy)") - C("Go security processor") - D("HTTP app") - E("Proxy") - F("Agent") - G("Backend") - -%% Edge connections between nodes - A --> B --> D - B --> C --> B - C --> E --> F --> G - %% D -- Mermaid js --> I --> J -``` - ## Scenario lifecycle System tests spawn several services before starting. Here is the lifecycle: diff --git a/tests/appsec/test_alpha.py b/tests/appsec/test_alpha.py index 39e0d1420e6..5dc18b9beed 100644 --- a/tests/appsec/test_alpha.py +++ b/tests/appsec/test_alpha.py @@ -6,7 +6,6 @@ @features.threats_alpha_preview -@scenarios.go_proxies_default @scenarios.appsec_lambda_default @scenarios.default class Test_Basic: diff --git a/tests/appsec/test_blocking_addresses.py b/tests/appsec/test_blocking_addresses.py index ce58c6e18ef..b87eb2425ca 100644 --- a/tests/appsec/test_blocking_addresses.py +++ b/tests/appsec/test_blocking_addresses.py @@ -5,9 +5,7 @@ import json from utils import ( - context, interfaces, - missing_feature, rfc, scenarios, weblog, @@ -38,7 +36,6 @@ def wrapper(span: DataDogLibrarySpan): @features.appsec_request_blocking -@scenarios.go_proxies_appsec_blocking @scenarios.appsec_blocking @scenarios.appsec_lambda_blocking class Test_Blocking_client_ip: @@ -67,7 +64,6 @@ def test_blocking_before(self): @features.appsec_request_blocking @scenarios.appsec_blocking @scenarios.appsec_lambda_blocking -@scenarios.go_proxies_appsec_blocking class Test_Blocking_client_ip_with_forwarded: """Test if blocking is supported on http.client_ip address""" @@ -110,7 +106,6 @@ def test_blocking_before(self): @features.appsec_request_blocking @scenarios.appsec_blocking @scenarios.appsec_lambda_blocking -@scenarios.go_proxies_appsec_blocking class Test_Blocking_client_ip_with_K8_private_ip: """Test if blocking is supported on http.client_ip address""" @@ -145,7 +140,6 @@ def test_block_user(self): @rfc("https://datadoghq.atlassian.net/wiki/spaces/APS/pages/2667021177/Suspicious+requests+blocking") @features.appsec_request_blocking -@scenarios.go_proxies_appsec_blocking @scenarios.appsec_blocking @scenarios.appsec_lambda_blocking class Test_Blocking_request_method: @@ -179,10 +173,6 @@ def setup_blocking_before(self): self.set_req1 = weblog.request("GET", path="/tag_value/clean_value_3876/200") self.block_req2 = weblog.request("OPTIONS", path="/tag_value/tainted_value_6512/200") - @missing_feature( - context.scenario is scenarios.go_proxies_appsec_blocking, - reason="The endpoint /tag_value is not implemented in the weblog", - ) def test_blocking_before(self): """Test that blocked requests are blocked before being processed""" # first request should not block and must set the tag in span accordingly @@ -199,7 +189,6 @@ def test_blocking_before(self): @rfc("https://datadoghq.atlassian.net/wiki/spaces/APS/pages/2667021177/Suspicious+requests+blocking") @features.appsec_request_blocking -@scenarios.go_proxies_appsec_blocking @scenarios.appsec_blocking @scenarios.appsec_lambda_blocking class Test_Blocking_request_uri: @@ -244,10 +233,6 @@ def setup_blocking_before(self): self.set_req1 = weblog.get("/tag_value/clean_value_3877/200") self.block_req2 = weblog.get("/tag_value/tainted_value_6512.git/200") - @missing_feature( - context.scenario is scenarios.go_proxies_appsec_blocking, - reason="The endpoint /tag_value is not implemented in the weblog", - ) def test_blocking_before(self): """Test that blocked requests are blocked before being processed""" # first request should not block and must set the tag in span accordingly @@ -264,7 +249,6 @@ def test_blocking_before(self): @rfc("https://datadoghq.atlassian.net/wiki/spaces/APS/pages/2667021177/Suspicious+requests+blocking") @features.appsec_request_blocking -@scenarios.go_proxies_appsec_blocking @scenarios.appsec_blocking @scenarios.appsec_lambda_blocking class Test_Blocking_request_path_params: @@ -302,10 +286,6 @@ def setup_blocking_before(self): self.set_req1 = weblog.get("/tag_value/clean_value_3878/200") self.block_req2 = weblog.get("/tag_value/tainted_value_AiKfOeRcvG45/200") - @missing_feature( - context.scenario is scenarios.go_proxies_appsec_blocking, - reason="The endpoint /param is not implemented in the weblog", - ) def test_blocking_before(self): """Test that blocked requests are blocked before being processed""" # first request should not block and must set the tag in span accordingly @@ -322,7 +302,6 @@ def test_blocking_before(self): @rfc("https://datadoghq.atlassian.net/wiki/spaces/APS/pages/2667021177/Suspicious+requests+blocking") @features.appsec_request_blocking -@scenarios.go_proxies_appsec_blocking @scenarios.appsec_blocking @scenarios.appsec_lambda_blocking class Test_Blocking_request_query: @@ -376,10 +355,6 @@ def setup_blocking_before(self): self.set_req1 = weblog.get("/tag_value/clean_value_3879/200") self.block_req2 = weblog.get("/tag_value/tainted_value_a1b2c3/200?foo=xtrace") - @missing_feature( - context.scenario is scenarios.go_proxies_appsec_blocking, - reason="The endpoint /tag_value is not implemented in the weblog", - ) def test_blocking_before(self): """Test that blocked requests are blocked before being processed""" # first request should not block and must set the tag in span accordingly @@ -396,7 +371,6 @@ def test_blocking_before(self): @rfc("https://datadoghq.atlassian.net/wiki/spaces/APS/pages/2667021177/Suspicious+requests+blocking") @features.appsec_request_blocking -@scenarios.go_proxies_appsec_blocking @scenarios.appsec_blocking @scenarios.appsec_lambda_blocking class Test_Blocking_request_headers: @@ -434,10 +408,6 @@ def setup_blocking_before(self): self.set_req1 = weblog.get("/tag_value/clean_value_3880/200") self.block_req2 = weblog.get("/tag_value/tainted_value_xyz/200", headers={"foo": "asldhkuqwgervf"}) - @missing_feature( - context.scenario is scenarios.go_proxies_appsec_blocking, - reason="The endpoint /tag_value is not implemented in the weblog", - ) def test_blocking_before(self): """Test that blocked requests are blocked before being processed""" # first request should not block and must set the tag in span accordingly @@ -454,7 +424,6 @@ def test_blocking_before(self): @rfc("https://datadoghq.atlassian.net/wiki/spaces/APS/pages/2667021177/Suspicious+requests+blocking") @features.appsec_request_blocking -@scenarios.go_proxies_appsec_blocking @scenarios.appsec_blocking @scenarios.appsec_lambda_blocking class Test_Blocking_request_cookies: @@ -492,10 +461,6 @@ def setup_blocking_before(self): self.set_req1 = weblog.get("/tag_value/clean_value_3881/200") self.block_req2 = weblog.get("/tag_value/tainted_value_cookies/200", cookies={"foo": "jdfoSDGFkivRG_234"}) - @missing_feature( - context.scenario is scenarios.go_proxies_appsec_blocking, - reason="The endpoint /tag_value is not implemented in the weblog", - ) def test_blocking_before(self): """Test that blocked requests are blocked before being processed""" # first request should not block and must set the tag in span accordingly @@ -594,7 +559,6 @@ def test_blocking(self): @rfc("https://datadoghq.atlassian.net/wiki/spaces/APS/pages/2667021177/Suspicious+requests+blocking") @features.appsec_response_blocking -@scenarios.go_proxies_appsec_blocking @scenarios.appsec_blocking @scenarios.appsec_lambda_blocking class Test_Blocking_response_status: @@ -631,10 +595,6 @@ def test_non_blocking(self): def setup_not_found(self): self.rnf_req = weblog.get(path="/finger_print") - @missing_feature( - context.scenario is scenarios.go_proxies_appsec_blocking, - reason="The endpoint /finger_print is not implemented in the weblog", - ) def test_not_found(self): """Can block on server.response.status""" @@ -644,7 +604,6 @@ def test_not_found(self): @rfc("https://datadoghq.atlassian.net/wiki/spaces/APS/pages/2667021177/Suspicious+requests+blocking") @features.appsec_response_blocking -@scenarios.go_proxies_appsec_blocking @scenarios.appsec_blocking @scenarios.appsec_lambda_blocking class Test_Blocking_response_headers: diff --git a/tests/appsec/test_ip_blocking_full_denylist.py b/tests/appsec/test_ip_blocking_full_denylist.py index 1d5dc027516..bbf60ec77f8 100644 --- a/tests/appsec/test_ip_blocking_full_denylist.py +++ b/tests/appsec/test_ip_blocking_full_denylist.py @@ -9,7 +9,6 @@ @rfc("https://docs.google.com/document/d/1GUd8p7HBp9gP0a6PZmDY26dpGrS1Ztef9OYdbK3Vq3M/edit") @features.appsec_client_ip_blocking -@scenarios.go_proxies_default @scenarios.appsec_blocking_full_denylist class Test_AppSecIPBlockingFullDenylist(BaseFullDenyListTest): """A library should block requests from up to 2500 different blocked IP addresses.""" diff --git a/tests/appsec/test_reports.py b/tests/appsec/test_reports.py index e136f4df7dc..7c99220b358 100644 --- a/tests/appsec/test_reports.py +++ b/tests/appsec/test_reports.py @@ -65,7 +65,6 @@ def _check_service(span: DataDogLibrarySpan, appsec_data: dict): # noqa: ARG001 @rfc("https://datadoghq.atlassian.net/wiki/spaces/APS/pages/2186870984/HTTP+header+collection") @features.security_events_metadata -@scenarios.go_proxies_default @scenarios.default @scenarios.appsec_lambda_default class Test_RequestHeaders: @@ -103,7 +102,6 @@ def test_http_request_headers(self): @features.security_events_metadata -@scenarios.go_proxies_default @scenarios.default @scenarios.appsec_lambda_default class Test_TagsFromRule: @@ -131,7 +129,6 @@ def test_category(self): @features.security_events_metadata -@scenarios.go_proxies_default @scenarios.default @scenarios.appsec_lambda_default class Test_ExtraTagsFromRule: @@ -160,7 +157,6 @@ def _get_appsec_triggers(request: HttpResponse): @features.security_events_metadata -@scenarios.go_proxies_default @scenarios.default @scenarios.appsec_lambda_default class Test_AttackTimestamp: diff --git a/tests/appsec/test_request_blocking.py b/tests/appsec/test_request_blocking.py index 1fbe04cc7aa..0dd4873240d 100644 --- a/tests/appsec/test_request_blocking.py +++ b/tests/appsec/test_request_blocking.py @@ -11,7 +11,6 @@ @features.appsec_request_blocking @scenarios.appsec_blocking_full_denylist -@scenarios.go_proxies_default class Test_AppSecRequestBlocking: """A library should block requests when a rule is set to blocking mode.""" diff --git a/tests/appsec/test_traces.py b/tests/appsec/test_traces.py index 8b84611a732..f80d90fa8b7 100644 --- a/tests/appsec/test_traces.py +++ b/tests/appsec/test_traces.py @@ -7,7 +7,6 @@ context, interfaces, rfc, - missing_feature, scenarios, features, ) @@ -20,7 +19,6 @@ @features.security_events_metadata -@scenarios.go_proxies_default @scenarios.default @scenarios.appsec_lambda_default class Test_RetainTraces: @@ -63,7 +61,6 @@ def validate_appsec_event_span_tags(span: DataDogLibrarySpan): @features.security_events_metadata -@scenarios.go_proxies_default @scenarios.default @scenarios.appsec_lambda_default class Test_AppSecEventSpanTags: @@ -134,7 +131,6 @@ def test_root_span_coherence(self): @rfc("https://datadoghq.atlassian.net/wiki/spaces/APS/pages/2365948382/Sensitive+Data+Obfuscation") @features.sensitive_data_obfuscation @features.security_events_metadata -@scenarios.go_proxies_default @scenarios.default @scenarios.appsec_lambda_default class Test_AppSecObfuscator: @@ -270,7 +266,6 @@ def validate_appsec_span_tags(span: DataDogLibrarySpan, appsec_data: dict): # n @rfc("https://datadoghq.atlassian.net/wiki/spaces/APS/pages/2186870984/HTTP+header+collection") @features.security_events_metadata -@scenarios.go_proxies_default @scenarios.default @scenarios.appsec_lambda_default class Test_CollectRespondHeaders: @@ -279,10 +274,6 @@ class Test_CollectRespondHeaders: def setup_header_collection(self): self.r = weblog.get("/headers", headers={"User-Agent": "Arachni/v1", "Content-Type": "text/plain"}) - @missing_feature( - context.scenario is scenarios.go_proxies_default, - reason="The endpoint /headers is not implemented in the weblog", - ) def test_header_collection(self): def assert_header_in_span_meta(span: DataDogLibrarySpan, header: str): if header not in span["meta"]: @@ -298,7 +289,6 @@ def validate_response_headers(span: DataDogLibrarySpan): @rfc("https://datadoghq.atlassian.net/wiki/spaces/APS/pages/2186870984/HTTP+header+collection") @features.security_events_metadata -@scenarios.go_proxies_default @scenarios.default @scenarios.appsec_lambda_default class Test_CollectDefaultRequestHeader: @@ -331,7 +321,6 @@ def test_collect_default_request_headers(self): @rfc("https://docs.google.com/document/d/1xf-s6PtSr6heZxmO_QLUtcFzY_X_rT94lRXNq6-Ghws/edit?pli=1") @features.security_events_metadata -@scenarios.go_proxies_default @scenarios.default @scenarios.appsec_lambda_default class Test_ExternalWafRequestsIdentification: diff --git a/tests/appsec/test_versions.py b/tests/appsec/test_versions.py index 0efb020983a..55ad0a17a13 100644 --- a/tests/appsec/test_versions.py +++ b/tests/appsec/test_versions.py @@ -6,7 +6,6 @@ @features.appsec_miscs_internals -@scenarios.go_proxies_default @scenarios.default @scenarios.appsec_lambda_default class Test_Events: diff --git a/tests/external_processing/README.md b/tests/external_processing/README.md deleted file mode 100644 index e6ab63178fa..00000000000 --- a/tests/external_processing/README.md +++ /dev/null @@ -1,14 +0,0 @@ -Will not work: Automated login events, user ids, events tracking, usage of AppSec SDK -Not tested due to lack of endpoints in the dummy http app: Block user, Block GraphQL, Fingerprinting -Not tested because the test need appsec to be disabled at first (and in the scenario it's DD_APPSEC_ENABLED=1 at the start): Suspicious Attacker Blocking - - - - - - - - - - - diff --git a/tests/external_processing/__init__.py b/tests/external_processing/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/tests/external_processing/test_apm.py b/tests/external_processing/test_apm.py deleted file mode 100644 index 373ed87c9a0..00000000000 --- a/tests/external_processing/test_apm.py +++ /dev/null @@ -1,17 +0,0 @@ -from utils import weblog, interfaces, features, scenarios - - -@scenarios.go_proxies_default -@features.go_proxies -class Test_GoProxies_Tracing: - def setup_correct_span_structure(self): - self.r = weblog.get("/") - - def test_correct_span_structure(self): - assert self.r.status_code == 200 - interfaces.library.assert_trace_exists(self.r) - span = interfaces.library.get_root_span(self.r) - assert span["type"] == "web" - assert span["meta"]["span.kind"] == "server" - assert span["meta"]["http.url"] == "http://localhost:7777/" - assert span["meta"]["http.host"] == "localhost:7777" diff --git a/tests/schemas/test_schemas.py b/tests/schemas/test_schemas.py index 025b8994d7e..5873115065b 100644 --- a/tests/schemas/test_schemas.py +++ b/tests/schemas/test_schemas.py @@ -108,8 +108,7 @@ def test_library(self): SchemaBug( endpoint="/v0.7/config", data_path="$.client.client_tracer", - condition=context.library in ("haproxy", "envoy") - and context.scenario in (scenarios.go_proxies_appsec_blocking, scenarios.go_proxies_default), + condition=context.library in ("haproxy", "envoy"), ticket="APMSP-2590", ), ] diff --git a/tests/test_config_consistency.py b/tests/test_config_consistency.py index 3da2a7808cb..8d644776b5f 100644 --- a/tests/test_config_consistency.py +++ b/tests/test_config_consistency.py @@ -378,7 +378,6 @@ def _get_span_by_tags(spans: list, tags: dict): @features.unified_service_tagging -@scenarios.go_proxies_default @scenarios.tracing_config_nondefault class Test_Config_UnifiedServiceTagging_CustomService: """Verify behavior of http clients and distributed traces""" diff --git a/tests/test_scrubbing.py b/tests/test_scrubbing.py index 1f89f05b44d..5a743170082 100644 --- a/tests/test_scrubbing.py +++ b/tests/test_scrubbing.py @@ -31,7 +31,6 @@ def crawler(data: dict | list | tuple | str | float | bool | None) -> None: # n @rfc("https://datadoghq.atlassian.net/wiki/spaces/APS/pages/2490990623/QueryString+-+Sensitive+Data+Obfuscation") @features.library_scrubbing -@scenarios.go_proxies_default @scenarios.default class Test_UrlQuery: """PII values in query parameter are all removed""" @@ -101,7 +100,6 @@ def validate_report(trace: DataDogLibraryTrace): @features.library_scrubbing -@scenarios.go_proxies_default @scenarios.default class Test_EnvVar: """Environnement variables are not leaked""" diff --git a/tests/test_semantic_conventions.py b/tests/test_semantic_conventions.py index bdcda5ee655..5e639940dd2 100644 --- a/tests/test_semantic_conventions.py +++ b/tests/test_semantic_conventions.py @@ -166,7 +166,6 @@ def get_component_name(span_name: str): @features.runtime_id_in_span_metadata_for_service_entry_spans @optional_uds_feature -@scenarios.go_proxies_default @scenarios.default class Test_Meta: """meta object in spans respect all conventions""" @@ -340,7 +339,6 @@ def validator(span: DataDogLibrarySpan): @features.trace_data_integrity -@scenarios.go_proxies_default @scenarios.default class Test_MetricsStandardTags: """metrics object in spans respect all conventions regarding basic tags""" diff --git a/tests/test_standard_tags.py b/tests/test_standard_tags.py index 68013c16c53..2013746ab7f 100644 --- a/tests/test_standard_tags.py +++ b/tests/test_standard_tags.py @@ -7,7 +7,6 @@ @features.security_events_metadata -@scenarios.go_proxies_default @scenarios.default class Test_StandardTagsMethod: """Tests to verify that libraries annotate spans with correct http.method tags""" @@ -33,7 +32,6 @@ def test_method_trace(self): @rfc("https://datadoghq.atlassian.net/wiki/spaces/APS/pages/2490990623/QueryString+-+Sensitive+Data+Obfuscation") @features.security_events_metadata -@scenarios.go_proxies_default @scenarios.default # Tests for verifying behavior when query string obfuscation is configured can be found in the Test_Config_ObfuscationQueryStringRegexp test classes class Test_StandardTagsUrl: @@ -142,7 +140,6 @@ def test_multiple_matching_substring(self): @features.security_events_metadata -@scenarios.go_proxies_default @scenarios.default class Test_StandardTagsUserAgent: """Tests to verify that libraries annotate spans with correct http.useragent tags""" @@ -206,7 +203,6 @@ def test_route(self): @rfc("https://datadoghq.atlassian.net/wiki/spaces/APS/pages/2118779066/Client+IP+addresses+resolution") @features.security_events_metadata -@scenarios.go_proxies_default @scenarios.default class Test_StandardTagsClientIp: """Tests to verify that libraries annotate spans with correct http.client_ip tags""" diff --git a/tests/test_the_test/scenarios.json b/tests/test_the_test/scenarios.json index 9d4fa1c9eeb..ffeba2bd67d 100644 --- a/tests/test_the_test/scenarios.json +++ b/tests/test_the_test/scenarios.json @@ -3363,8 +3363,8 @@ "tests/docker_ssi/test_docker_ssi_servicenaming.py::TestDockerServiceNaming::test_service_name": [ "DOCKER_SSI_SERVICENAMING" ], - "tests/external_processing/test_apm.py::Test_ExternalProcessing_Tracing::test_correct_span_structure": [ - "EXTERNAL_PROCESSING" + "tests/external_processing/test_apm.py::Test_GoProxies_Tracing::test_correct_span_structure": [ + "DEFAULT" ], "tests/integrations/test_cassandra.py::Test_Cassandra::test_main": [ "INTEGRATIONS" @@ -5938,4 +5938,4 @@ "tests/test_the_test/test_version.py::test_php_version": [ "TEST_THE_TEST" ] -} \ No newline at end of file +} diff --git a/tests/test_the_test/test_group_rules.py b/tests/test_the_test/test_group_rules.py index 86d849ad108..b636ea46a4a 100644 --- a/tests/test_the_test/test_group_rules.py +++ b/tests/test_the_test/test_group_rules.py @@ -39,8 +39,6 @@ def test_tracer_release(): scenarios.docker_ssi_appsec, scenarios.docker_ssi_crashtracking, scenarios.docker_ssi_servicenaming, - scenarios.go_proxies_default, - scenarios.go_proxies_appsec_blocking, scenarios.host_auto_injection_install_script_appsec, scenarios.host_auto_injection_install_script_profiling, scenarios.host_auto_injection_install_script, diff --git a/utils/_context/_scenarios/__init__.py b/utils/_context/_scenarios/__init__.py index 048384bf5d1..358283ca643 100644 --- a/utils/_context/_scenarios/__init__.py +++ b/utils/_context/_scenarios/__init__.py @@ -20,7 +20,6 @@ from .k8s_lib_injection import K8sScenario, K8sSparkScenario from .k8s_injector_dev import K8sInjectorDevScenario from .docker_ssi import DockerSSIScenario -from .go_proxies import GoProxiesScenario from .ipv6 import IPV6Scenario from .appsec_low_waf_timeout import AppsecLowWafTimeout from .integration_frameworks import IntegrationFrameworksScenario @@ -1106,21 +1105,6 @@ class _Scenarios: scenario_groups=[scenario_groups.integrations], ) - go_proxies_default = GoProxiesScenario( - name="GO_PROXIES_DEFAULT", - doc="Default tests for proxies using the security processor.", - rc_api_enabled=True, - scenario_groups=[], - ) - - go_proxies_appsec_blocking = GoProxiesScenario( - name="GO_PROXIES_APPSEC_BLOCKING", - doc="Default tests for proxies using the security processor with appsec blocking rule file", - processor_env={"DD_APPSEC_RULES": "/appsec_blocking_rule.json"}, - processor_volumes={"./tests/appsec/blocking_rule.json": {"bind": "/appsec_blocking_rule.json", "mode": "ro"}}, - scenario_groups=[], - ) - ipv6 = IPV6Scenario("IPV6") runtime_metrics_enabled = EndToEndScenario( diff --git a/utils/_context/_scenarios/core.py b/utils/_context/_scenarios/core.py index b605c2c3a3c..9b63915ed18 100644 --- a/utils/_context/_scenarios/core.py +++ b/utils/_context/_scenarios/core.py @@ -58,7 +58,6 @@ class _ScenarioGroups: simple_onboarding_appsec = ScenarioGroup() docker_ssi = ScenarioGroup() essentials = ScenarioGroup() - go_proxies = ScenarioGroup() remote_config = ScenarioGroup() telemetry = ScenarioGroup() tracing_config = ScenarioGroup() diff --git a/utils/_context/_scenarios/go_proxies.py b/utils/_context/_scenarios/go_proxies.py deleted file mode 100644 index 4df5f66d5f9..00000000000 --- a/utils/_context/_scenarios/go_proxies.py +++ /dev/null @@ -1,225 +0,0 @@ -import json -import os -from pathlib import Path -from typing import Literal - -import pytest - -from utils import interfaces -from utils._context.component_version import Version -from utils._context.containers import ( - AgentContainer, - DummyServerContainer, - EnvoyContainer, - ExternalProcessingContainer, - HAProxyContainer, - StreamProcessingOffloadContainer, -) -from utils._logger import logger -from utils.interfaces._core import ProxyBasedInterfaceValidator - -from .core import ScenarioGroup, scenario_groups as all_scenario_groups -from .endtoend import DockerScenario - - -ProcessorContainer = ExternalProcessingContainer | StreamProcessingOffloadContainer -ProxyRuntimeContainer = EnvoyContainer | HAProxyContainer - - -proxy_component = Literal["envoy", "haproxy"] -""" Possible values for proxy components """ - -# Link each weblog variant to the proxy component it uses -GO_PROXIES_WEBLOGS: dict[str, proxy_component] = { - "envoy": "envoy", - "haproxy-spoa": "haproxy", -} - - -class GoProxiesScenario(DockerScenario): - def __init__( - self, - name: str, - doc: str, - *, - processor_env: dict[str, str | None] | None = None, - processor_volumes: dict[str, dict[str, str]] | None = None, - scenario_groups: list[ScenarioGroup] | None = None, - rc_api_enabled: bool = False, - ) -> None: - self._processor_env = processor_env - self._processor_volumes = processor_volumes - scenario_groups = (scenario_groups or []) + [ - all_scenario_groups.go_proxies, - all_scenario_groups.appsec, - all_scenario_groups.end_to_end, - all_scenario_groups.all, - ] - - super().__init__( - name, - doc=doc, - github_workflow="endtoend", - scenario_groups=scenario_groups, - use_proxy=True, - rc_api_enabled=rc_api_enabled, - ) - - self._base_required_containers = list(self._containers) - - def _build_processor_container(self) -> ProcessorContainer: - if self.proxy_component == "envoy": - return ExternalProcessingContainer(env=self._processor_env, volumes=self._processor_volumes) - return StreamProcessingOffloadContainer(env=self._processor_env, volumes=self._processor_volumes) - - def _build_proxy_runtime_container(self) -> ProxyRuntimeContainer: - if self.proxy_component == "envoy": - return EnvoyContainer() - return HAProxyContainer() - - def configure(self, config: pytest.Config) -> None: - self._set_information(config) - self._init_containers() - - super().configure(config) - - interfaces.library.configure(self.host_log_folder, replay=self.replay) - interfaces.agent.configure(self.host_log_folder, replay=self.replay) - - if not self.replay: - self.warmups.insert(1, self._start_interfaces_watchdog) - self.warmups.append(self._wait_for_app_readiness) - self.warmups.append(lambda: logger.stdout(f"Weblog variant: {self._weblog_variant}")) - self.warmups.append(lambda: logger.stdout(f"Proxy component: {self._proxy_component}")) - self.warmups.append(self._set_components) - - def _start_interfaces_watchdog(self) -> None: - super().start_interfaces_watchdog([interfaces.library, interfaces.agent]) - - def _wait_for_app_readiness(self) -> None: - logger.debug("Wait for app readiness (%s)", self._weblog_variant) - - if not interfaces.library.ready.wait(40): - pytest.exit("Nothing received from the security processor", 1) - logger.debug("Library ready") - - if not interfaces.agent.ready.wait(40): - pytest.exit("Datadog agent not ready", 1) - logger.debug("Agent ready") - - def _set_components(self) -> None: - self.components["agent"] = self._agent_container.agent_version - lib = self.library - self.components["library"] = lib.version - self.components[lib.name] = lib.version - - def post_setup(self, session: pytest.Session) -> None: # noqa: ARG002 - try: - self._wait_and_stop_containers() - finally: - self.close_targets() - - def _wait_and_stop_containers(self) -> None: - if self.replay: - logger.terminal.write_sep("-", "Load all data from logs") - logger.terminal.flush() - - interfaces.library.load_data_from_logs() - interfaces.library.check_deserialization_errors() - - interfaces.agent.load_data_from_logs() - interfaces.agent.check_deserialization_errors() - - else: - self._wait_interface(interfaces.library, 5) - - self._http_app_container.stop() - self._proxy_runtime_container.stop() - self._processor_container.stop() - - interfaces.library.check_deserialization_errors() - - self._agent_container.stop() - interfaces.agent.check_deserialization_errors() - - def _wait_interface(self, interface: ProxyBasedInterfaceValidator, timeout: int) -> None: - logger.terminal.write_sep("-", f"Wait for {interface} ({timeout}s)") - logger.terminal.flush() - - interface.wait(timeout) - - def _init_containers(self) -> None: - self._agent_container = AgentContainer() - self._processor_container = self._build_processor_container() - self._proxy_runtime_container = self._build_proxy_runtime_container() - self._http_app_container = DummyServerContainer() - - self._agent_container.depends_on = [self.proxy_container] - self._processor_container.depends_on = [self.proxy_container] - self._proxy_runtime_container.depends_on = [self._processor_container, self._http_app_container] - - self._containers = [ - *self._base_required_containers, - self._agent_container, - self._processor_container, - self._proxy_runtime_container, - self._http_app_container, - ] - - def _set_information(self, config: pytest.Config) -> None: - requested_weblog_variant = config.option.weblog - version: Version | None = None - - if self.replay: - requested_weblog_variant, version = self._discover_weblog_and_version_from_logs() - - if requested_weblog_variant not in GO_PROXIES_WEBLOGS: - pytest.exit( - f"Unsupported Go proxies weblog variant '{requested_weblog_variant}'. " - "Please set with --weblog. " - f"Supported variants: {', '.join(sorted(GO_PROXIES_WEBLOGS))}", - 1, - ) - - self._weblog_variant = requested_weblog_variant - self._proxy_component = GO_PROXIES_WEBLOGS[self._weblog_variant] - - if version: - self.components["library"] = version - self.components[self._proxy_component] = version - - def _discover_weblog_and_version_from_logs(self) -> tuple[str | None, Version | None]: - weblog_variant = None - version = None - - docker_logs_dir = Path(os.environ.get("SYSTEM_TESTS_HOST_PROJECT_DIR", Path.cwd())) / self.host_log_folder - fp = docker_logs_dir / "feature_parity.json" - - try: - with fp.open(encoding="utf-8") as f: - feature_parity = json.load(f) - except Exception as e: - logger.warning("Replay mode error: %s", e) - return None, None - - weblog_variant = feature_parity.get("variant") - deps = feature_parity.get("testedDependencies") or [] - - for dep in deps: - if isinstance(dep, dict) and dep.get("name") == "library": - version = dep.get("version") - break - - return weblog_variant, Version(version) if version else None - - @property - def weblog_variant(self) -> str: - return self._weblog_variant - - @property - def proxy_component(self) -> proxy_component: - return self._proxy_component - - @property - def library(self): - return self._processor_container.library diff --git a/utils/scripts/libraries_and_scenarios_rules.yml b/utils/scripts/libraries_and_scenarios_rules.yml index 22ff86b0c9d..a1d560e2e82 100644 --- a/utils/scripts/libraries_and_scenarios_rules.yml +++ b/utils/scripts/libraries_and_scenarios_rules.yml @@ -227,8 +227,6 @@ patterns: scenarios: PARAMETRIC utils/_context/_scenarios/profiling.py: scenario_groups: profiling - utils/_context/_scenarios/go_proxies.py: - scenario_groups: go_proxies ############################### Script file rules ############################## From 21d3fba6337d611ec6e1052081e2465cc34728cf Mon Sep 17 00:00:00 2001 From: Flavien Darche Date: Tue, 10 Mar 2026 21:17:33 +0100 Subject: [PATCH 2/6] part2 --- utils/_context/_scenarios/default.py | 5 +- utils/_context/_scenarios/endtoend.py | 53 ++- utils/_context/containers.py | 14 + utils/_context/weblog_infrastructure.py | 417 ++++++++++++++++-- .../scripts/ci_orchestrators/workflow_data.py | 21 +- 5 files changed, 448 insertions(+), 62 deletions(-) diff --git a/utils/_context/_scenarios/default.py b/utils/_context/_scenarios/default.py index 9db9a615826..ff52a566615 100644 --- a/utils/_context/_scenarios/default.py +++ b/utils/_context/_scenarios/default.py @@ -13,7 +13,9 @@ "cpp_nginx": "TODO", "cpp_httpd": "TODO", "dotnet": "TODO", + "envoy": "TODO", "golang": "TODO", + "haproxy": "TODO", "java": ( "SANITIZER:COMMAND_INJECTION:com.datadoghq.system_tests.iast.utils.SecurityControlUtil:sanitize;" "SANITIZER:*:com.datadoghq.system_tests.iast.utils.SecurityControlUtil:sanitizeForAllVulns;" @@ -82,4 +84,5 @@ def configure(self, config: pytest.Config): super().configure(config) library = self.weblog_infra.library_name value = _iast_security_controls_map[library] - self.weblog_container.environment["DD_IAST_SECURITY_CONTROLS_CONFIGURATION"] = value + if value != "TODO": + self.weblog_container.environment["DD_IAST_SECURITY_CONTROLS_CONFIGURATION"] = value diff --git a/utils/_context/_scenarios/endtoend.py b/utils/_context/_scenarios/endtoend.py index d8f5efc34f3..5e5d2af06bb 100644 --- a/utils/_context/_scenarios/endtoend.py +++ b/utils/_context/_scenarios/endtoend.py @@ -17,6 +17,8 @@ AgentContainer, ProxyContainer, BuddyContainer, + ExternalProcessingContainer, + StreamProcessingOffloadContainer, TestedContainer, ) from utils._context.weblog_infrastructure import EndToEndWeblogInfra @@ -29,7 +31,7 @@ class DockerScenario(Scenario): """Scenario that tests docker containers""" - _network: Network = None + _network: Network | None = None def __init__( self, @@ -88,7 +90,9 @@ def get_image_list(self, library: str, weblog: str) -> list[str]: def configure(self, config: pytest.Config): # noqa: ARG002 if not self.replay: docker_info = get_docker_client().info() - self.components["docker.Cgroup"] = docker_info.get("CgroupVersion", None) + cgroup_version = docker_info.get("CgroupVersion") + if cgroup_version is not None: + self.components["docker.Cgroup"] = cgroup_version self.warmups.append(self._create_network) self.warmups.append(self._start_containers) @@ -100,7 +104,7 @@ def configure(self, config: pytest.Config): # noqa: ARG002 def get_container_by_dd_integration_name(self, name: str): for container in self._containers: - if hasattr(container, "dd_integration_service") and container.dd_integration_service == name: + if getattr(container, "dd_integration_service", None) == name: return container return None @@ -155,6 +159,7 @@ def _create_network(self) -> None: def _start_containers(self): logger.stdout("Starting containers...") threads = [] + assert self._network is not None, "Docker network is not initialized" for container in self._containers: threads.append(container.async_start(self._network)) @@ -248,7 +253,6 @@ def __init__( volumes=weblog_volumes, other_containers=other_weblog_containers, ) - self._containers += self.weblog_infra.get_containers() # buddies are a set of weblog app that are not directly the test target # but are used only to test feature that invlove another app with a datadog tracer @@ -284,11 +288,17 @@ def __init__( self.backend_interface_timeout = backend_interface_timeout self._library_interface_timeout = library_interface_timeout + def get_image_list(self, library: str, weblog: str) -> list[str]: + return list( + dict.fromkeys(super().get_image_list(library, weblog) + self.weblog_infra.get_image_list(library, weblog)) + ) + def configure(self, config: pytest.Config): if self._require_api_key and "DD_API_KEY" not in os.environ and not self.replay: pytest.exit("DD_API_KEY is required for this scenario", 1) - self.weblog_infra.configure(config) + self.weblog_infra.configure(config, self.host_log_folder) + self._containers += self.weblog_infra.get_containers() self._set_containers_dependancies() super().configure(config) @@ -307,7 +317,7 @@ def configure(self, config: pytest.Config): if self._library_interface_timeout is None: if library == "java": self.library_interface_timeout = 25 - elif library in ("golang",): + elif library in ("golang", "envoy", "haproxy"): self.library_interface_timeout = 10 elif library in ("nodejs", "ruby"): self.library_interface_timeout = 0 @@ -343,7 +353,7 @@ def _set_containers_dependancies(self) -> None: def _get_weblog_system_info(self): try: - code, (stdout, stderr) = self.weblog_container.exec_run("uname -a", demux=True) + code, (stdout, stderr) = self.weblog_infra.library_container.exec_run("uname -a", demux=True) if code or stdout is None: message = f"Failed to get weblog system info: [{code}] {stderr.decode()} {stdout.decode()}" else: @@ -353,7 +363,7 @@ def _get_weblog_system_info(self): else: logger.stdout(f"Weblog system: {message.strip()}") - if self.weblog_container.environment.get("DD_TRACE_DEBUG") == "true": + if self.weblog_infra.library_container.environment.get("DD_TRACE_DEBUG") == "true": logger.stdout("\t/!\\ Debug logs are activated in weblog") logger.stdout("") @@ -365,7 +375,8 @@ def _start_interfaces_watchdog(self): def _set_weblog_domain(self): if self.enable_ipv6: - self.weblog_container.set_weblog_domain_for_ipv6(self._network) + assert self._network is not None, "Docker network is not initialized" + self.weblog_infra.set_weblog_domain_for_ipv6(self._network) def _set_components(self): self.components["agent"] = self.agent_version @@ -451,8 +462,8 @@ def _wait_interface(self, interface: ProxyBasedInterfaceValidator, timeout: int) interface.wait(timeout) @property - def weblog_container(self) -> WeblogContainer: - return self.weblog_infra.http_container + def weblog_container(self) -> WeblogContainer | ExternalProcessingContainer | StreamProcessingOffloadContainer: + return self.weblog_infra.library_container @property def dd_site(self): @@ -460,7 +471,7 @@ def dd_site(self): @property def library(self): - return self.weblog_container.library + return self.weblog_infra.library @property def agent_version(self): @@ -468,35 +479,35 @@ def agent_version(self): @property def weblog_variant(self): - return self.weblog_container.weblog_variant + return self.weblog_infra.weblog_variant @property def tracer_sampling_rate(self): - return self.weblog_container.tracer_sampling_rate + return self.weblog_infra.tracer_sampling_rate @property def appsec_rules_file(self): - return self.weblog_container.appsec_rules_file + return self.weblog_infra.appsec_rules_file @property def uds_socket(self): - return self.weblog_container.uds_socket + return self.weblog_infra.uds_socket @property def uds_mode(self): - return self.weblog_container.uds_mode + return self.weblog_infra.uds_mode @property def telemetry_heartbeat_interval(self): - return self.weblog_container.telemetry_heartbeat_interval + return self.weblog_infra.telemetry_heartbeat_interval def get_junit_properties(self) -> dict[str, str]: result = super().get_junit_properties() - result["dd_tags[systest.suite.context.agent]"] = self.agent_version + result["dd_tags[systest.suite.context.agent]"] = str(self.agent_version) result["dd_tags[systest.suite.context.library.name]"] = self.library.name - result["dd_tags[systest.suite.context.library.version]"] = self.library.version + result["dd_tags[systest.suite.context.library.version]"] = str(self.library.version) result["dd_tags[systest.suite.context.weblog_variant]"] = self.weblog_variant - result["dd_tags[systest.suite.context.appsec_rules_file]"] = self.weblog_container.appsec_rules_file or "" + result["dd_tags[systest.suite.context.appsec_rules_file]"] = self.appsec_rules_file or "" return result diff --git a/utils/_context/containers.py b/utils/_context/containers.py index 25ee3b0edb3..5b1f5e0a0d7 100644 --- a/utils/_context/containers.py +++ b/utils/_context/containers.py @@ -1659,6 +1659,13 @@ def post_start(self): logger.stdout(f"Library: {self.library}") logger.stdout(f"Image: {self.image.name}") + @property + def trace_agent_port(self): + return ProxyPorts.weblog + + def warmup_request(self, timeout: int = 10): + weblog.get("/", timeout=timeout) + class HAProxyContainer(TestedContainer): def __init__(self) -> None: @@ -1735,3 +1742,10 @@ def post_start(self): logger.stdout(f"Library: {self.library}") logger.stdout(f"Image: {self.image.name}") + + @property + def trace_agent_port(self): + return ProxyPorts.weblog + + def warmup_request(self, timeout: int = 10): + weblog.get("/", timeout=timeout) diff --git a/utils/_context/weblog_infrastructure.py b/utils/_context/weblog_infrastructure.py index b020a4e7363..e2a268fa0be 100644 --- a/utils/_context/weblog_infrastructure.py +++ b/utils/_context/weblog_infrastructure.py @@ -1,37 +1,126 @@ from abc import ABC, abstractmethod +import json +import os +from pathlib import Path +import sys +from docker.models.networks import Network import pytest +from utils._context.component_version import ComponentVersion from utils._context.containers import ( - WeblogContainer, - TestedContainer, - KafkaContainer, - RabbitMqContainer, - PostgresContainer, CassandraContainer, + DummyServerContainer, + EnvoyContainer, + ExternalProcessingContainer, + HAProxyContainer, + KafkaContainer, MongoContainer, - MySqlContainer, MsSqlServerContainer, + MySqlContainer, + PostgresContainer, + RabbitMqContainer, + StreamProcessingOffloadContainer, + TestedContainer, + WeblogContainer, ) +from utils._logger import logger +from utils._weblog import weblog + + +PROXY_WEBLOGS: dict[str, str] = { + "envoy": "envoy", + "haproxy-spoa": "haproxy", +} + +EndToEndHttpContainer = WeblogContainer | EnvoyContainer | HAProxyContainer +EndToEndLibraryContainer = WeblogContainer | ExternalProcessingContainer | StreamProcessingOffloadContainer class WeblogInfra(ABC): """Infrastructure shipping the HTTP app (aka weblog) instrumented by a library.""" @abstractmethod - def configure(self, config: pytest.Config) -> None: + def configure(self, config: pytest.Config, host_log_folder: str) -> None: """Perform any configuration. Executed only if the weblog will be used""" @abstractmethod def stop(self) -> None: """Stop the tested infra""" + @abstractmethod + def get_containers(self) -> tuple[TestedContainer, ...]: + pass + + @abstractmethod + def get_image_list(self, library: str, weblog_variant: str) -> list[str]: + pass + + +class EndToEndInfra(WeblogInfra): + @property + @abstractmethod + def http_container(self) -> EndToEndHttpContainer: + pass + + @property + @abstractmethod + def library_container(self) -> EndToEndLibraryContainer: + pass -class EndToEndWeblogInfra(WeblogInfra): - """Infrastructure shipping the HTTP app (aka weblog) instrumented by a library. - This class is meant to work with EndToEndScenario - """ + @property + @abstractmethod + def library_name(self) -> str: + pass + + @property + def library(self) -> ComponentVersion: + return self.library_container.library + + @property + @abstractmethod + def weblog_variant(self) -> str: + pass + + @property + def tracer_sampling_rate(self) -> float | None: + return getattr(self.library_container, "tracer_sampling_rate", None) + + @property + def appsec_rules_file(self) -> str | None: + return getattr(self.library_container, "appsec_rules_file", None) + @property + def uds_socket(self) -> str | None: + return getattr(self.library_container, "uds_socket", None) + + @property + def uds_mode(self) -> bool: + return getattr(self.library_container, "uds_mode", False) + + @property + def telemetry_heartbeat_interval(self) -> int | float: + return getattr(self.library_container, "telemetry_heartbeat_interval", 2) + + def set_weblog_domain_for_ipv6(self, network: Network) -> None: + set_weblog_domain_for_ipv6 = getattr(self.http_container, "set_weblog_domain_for_ipv6", None) + if callable(set_weblog_domain_for_ipv6): + set_weblog_domain_for_ipv6(network) + return + + if sys.platform == "linux": + weblog.domain = self.http_container.network_ip(network) + logger.info("Linux => Using Container IPv6 address [%s] as weblog domain", weblog.domain) + return + + if sys.platform == "darwin": + logger.info("Mac => Using localhost as weblog domain") + return + + pytest.exit(f"Unsupported platform {sys.platform} with ipv6 enabled", 1) + + +class LibraryEndToEndInfra(EndToEndInfra): def __init__( self, *, @@ -45,7 +134,16 @@ def __init__( volumes: dict | None = None, other_containers: tuple[type[TestedContainer], ...] = (), ) -> None: - self.http_container = WeblogContainer( + self._environment = environment + self._tracer_sampling_rate = tracer_sampling_rate + self._appsec_enabled = appsec_enabled + self._iast_enabled = iast_enabled + self._runtime_metrics_enabled = runtime_metrics_enabled + self._additional_trace_header_tags = additional_trace_header_tags + self._use_proxy = use_proxy + self._volumes = volumes + self._other_container_types = other_containers + self._http_container = WeblogContainer( environment=environment, tracer_sampling_rate=tracer_sampling_rate, appsec_enabled=appsec_enabled, @@ -55,35 +153,292 @@ def __init__( use_proxy=use_proxy, volumes=volumes, ) - self._other_containers = [container() for container in other_containers] - - self.http_container.environment |= { - "INCLUDE_POSTGRES": "true" if PostgresContainer in other_containers else "false", - "INCLUDE_CASSANDRA": "true" if CassandraContainer in other_containers else "false", - "INCLUDE_MONGO": "true" if MongoContainer in other_containers else "false", - "INCLUDE_KAFKA": "true" if KafkaContainer in other_containers else "false", - "INCLUDE_RABBITMQ": "true" if RabbitMqContainer in other_containers else "false", - "INCLUDE_MYSQL": "true" if MySqlContainer in other_containers else "false", - "INCLUDE_SQLSERVER": "true" if MsSqlServerContainer in other_containers else "false", + self._other_containers = [container() for container in self._other_container_types] + + self._http_container.environment |= { + "INCLUDE_POSTGRES": "true" if PostgresContainer in self._other_container_types else "false", + "INCLUDE_CASSANDRA": "true" if CassandraContainer in self._other_container_types else "false", + "INCLUDE_MONGO": "true" if MongoContainer in self._other_container_types else "false", + "INCLUDE_KAFKA": "true" if KafkaContainer in self._other_container_types else "false", + "INCLUDE_RABBITMQ": "true" if RabbitMqContainer in self._other_container_types else "false", + "INCLUDE_MYSQL": "true" if MySqlContainer in self._other_container_types else "false", + "INCLUDE_SQLSERVER": "true" if MsSqlServerContainer in self._other_container_types else "false", } + @property + def http_container(self) -> WeblogContainer: + return self._http_container + + @property + def library_container(self) -> WeblogContainer: + return self._http_container + + @property + def library_name(self) -> str: + return self._http_container.image.labels["system-tests-library"] + + @property + def weblog_variant(self) -> str: + return self._http_container.weblog_variant + def get_containers(self) -> tuple[TestedContainer, ...]: - return (self.http_container, *self._other_containers) + return (self._http_container, *self._other_containers) + + def get_image_list(self, library: str, weblog_variant: str) -> list[str]: + containers: list[TestedContainer] = [ + WeblogContainer( + environment=self._environment, + tracer_sampling_rate=self._tracer_sampling_rate, + appsec_enabled=self._appsec_enabled, + iast_enabled=self._iast_enabled, + runtime_metrics_enabled=self._runtime_metrics_enabled, + additional_trace_header_tags=self._additional_trace_header_tags, + use_proxy=self._use_proxy, + volumes=self._volumes, + ) + ] + containers.extend(container() for container in self._other_container_types) + return [image for container in containers for image in container.get_image_list(library, weblog_variant)] - def configure(self, config: pytest.Config): - self.http_container.depends_on.extend(self._other_containers) + def configure(self, config: pytest.Config, host_log_folder: str) -> None: # noqa: ARG002 + self._http_container.depends_on.extend(self._other_containers) if config.option.force_dd_trace_debug: - self.http_container.environment["DD_TRACE_DEBUG"] = "true" + self._http_container.environment["DD_TRACE_DEBUG"] = "true" if config.option.force_dd_iast_debug: - self.http_container.environment["_DD_IAST_DEBUG"] = "true" # probably not used anymore ? - self.http_container.environment["DD_IAST_DEBUG_ENABLED"] = "true" + self._http_container.environment["_DD_IAST_DEBUG"] = "true" + self._http_container.environment["DD_IAST_DEBUG_ENABLED"] = "true" + + def stop(self) -> None: + self._http_container.flush() + self._http_container.stop() + + +class GoProxiesEndToEndInfra(EndToEndInfra): + def __init__( + self, + weblog_variant: str, + *, + environment: dict[str, str | None] | None = None, + tracer_sampling_rate: float | None = None, + appsec_enabled: bool = True, + runtime_metrics_enabled: bool = False, + additional_trace_header_tags: tuple[str, ...] = (), + volumes: dict | None = None, + other_containers: tuple[type[TestedContainer], ...] = (), + ) -> None: + self._weblog_variant = weblog_variant + self._environment = dict(environment) if environment else {} + self._volumes = volumes + self._other_container_types = other_containers + self._library_container: ExternalProcessingContainer | StreamProcessingOffloadContainer + self._http_container: EnvoyContainer | HAProxyContainer + + if tracer_sampling_rate is not None and "DD_TRACE_SAMPLE_RATE" not in self._environment: + self._environment["DD_TRACE_SAMPLE_RATE"] = str(tracer_sampling_rate) + self._environment["DD_TRACE_SAMPLING_RULES"] = json.dumps([{"sample_rate": tracer_sampling_rate}]) + + if not appsec_enabled and "DD_APPSEC_ENABLED" not in self._environment: + self._environment["DD_APPSEC_ENABLED"] = "false" + + if runtime_metrics_enabled and "DD_RUNTIME_METRICS_ENABLED" not in self._environment: + self._environment["DD_RUNTIME_METRICS_ENABLED"] = "true" + + if additional_trace_header_tags and "DD_TRACE_HEADER_TAGS" not in self._environment: + self._environment["DD_TRACE_HEADER_TAGS"] = ",".join(additional_trace_header_tags) + + if weblog_variant == "envoy": + self._library_container = ExternalProcessingContainer(env=self._environment, volumes=self._volumes) + self._http_container = EnvoyContainer() + else: + self._library_container = StreamProcessingOffloadContainer(env=self._environment, volumes=self._volumes) + self._http_container = HAProxyContainer() + + self._dummy_server = DummyServerContainer() + self._other_containers = [container() for container in self._other_container_types] + + @property + def http_container(self) -> EnvoyContainer | HAProxyContainer: + return self._http_container + + @property + def library_container(self) -> ExternalProcessingContainer | StreamProcessingOffloadContainer: + return self._library_container + + @property + def library_name(self) -> str: + return PROXY_WEBLOGS[self._weblog_variant] + + @property + def weblog_variant(self) -> str: + return self._weblog_variant + + @property + def appsec_rules_file(self) -> str | None: + return self._environment.get("DD_APPSEC_RULES") + + def get_containers(self) -> tuple[TestedContainer, ...]: + return (self._library_container, self._http_container, self._dummy_server, *self._other_containers) + + def get_image_list(self, library: str, weblog_variant: str) -> list[str]: + infra = GoProxiesEndToEndInfra( + weblog_variant, + environment=self._environment, + additional_trace_header_tags=(), + volumes=self._volumes, + other_containers=self._other_container_types, + ) + return [ + image for container in infra.get_containers() for image in container.get_image_list(library, weblog_variant) + ] + + def configure(self, config: pytest.Config, host_log_folder: str) -> None: # noqa: ARG002 + self._http_container.depends_on.extend((self._library_container, self._dummy_server)) + + if config.option.force_dd_trace_debug: + self._library_container.environment["DD_TRACE_DEBUG"] = "true" def stop(self) -> None: - self.http_container.flush() - self.http_container.stop() + self._dummy_server.stop() + self._http_container.stop() + self._library_container.stop() + + +class EndToEndWeblogInfra(EndToEndInfra): + def __init__( + self, + *, + environment: dict[str, str | None] | None = None, + tracer_sampling_rate: float | None = None, + appsec_enabled: bool = True, + iast_enabled: bool = True, + runtime_metrics_enabled: bool = False, + additional_trace_header_tags: tuple[str, ...] = (), + use_proxy: bool = True, + volumes: dict | None = None, + other_containers: tuple[type[TestedContainer], ...] = (), + ) -> None: + self._environment = environment + self._tracer_sampling_rate = tracer_sampling_rate + self._appsec_enabled = appsec_enabled + self._iast_enabled = iast_enabled + self._runtime_metrics_enabled = runtime_metrics_enabled + self._additional_trace_header_tags = additional_trace_header_tags + self._use_proxy = use_proxy + self._volumes = volumes + self._other_containers = other_containers + self._infra: EndToEndInfra = self._build_library_infra() + + @property + def http_container(self) -> EndToEndHttpContainer: + return self._infra.http_container + + @property + def library_container(self) -> EndToEndLibraryContainer: + return self._infra.library_container @property def library_name(self) -> str: - return self.http_container.image.labels["system-tests-library"] + return self._infra.library_name + + @property + def library(self) -> ComponentVersion: + return self._infra.library + + @property + def weblog_variant(self) -> str: + return self._infra.weblog_variant + + @property + def tracer_sampling_rate(self) -> float | None: + return self._infra.tracer_sampling_rate + + @property + def appsec_rules_file(self) -> str | None: + return self._infra.appsec_rules_file + + @property + def uds_socket(self) -> str | None: + return self._infra.uds_socket + + @property + def uds_mode(self) -> bool: + return self._infra.uds_mode + + @property + def telemetry_heartbeat_interval(self) -> int | float: + return self._infra.telemetry_heartbeat_interval + + def get_containers(self) -> tuple[TestedContainer, ...]: + return self._infra.get_containers() + + def get_image_list(self, library: str, weblog_variant: str) -> list[str]: + if weblog_variant in PROXY_WEBLOGS: + return self._build_proxy_infra(weblog_variant).get_image_list(library, weblog_variant) + return self._build_library_infra().get_image_list(library, weblog_variant) + + def configure(self, config: pytest.Config, host_log_folder: str) -> None: + weblog_variant = config.option.weblog + + if weblog_variant is None and config.option.replay: + weblog_variant = self._discover_weblog_variant_from_logs(host_log_folder) + + if weblog_variant is None and config.option.replay: + pytest.exit( + "Unable to determine weblog variant in replay mode. Pass --weblog or provide feature_parity.json", + 1, + ) + + if weblog_variant in PROXY_WEBLOGS: + if not isinstance(self._infra, GoProxiesEndToEndInfra) or self._infra.weblog_variant != weblog_variant: + self._infra = self._build_proxy_infra(weblog_variant) + elif not isinstance(self._infra, LibraryEndToEndInfra): + self._infra = self._build_library_infra() + + self._infra.configure(config, host_log_folder) + + def stop(self) -> None: + self._infra.stop() + + def set_weblog_domain_for_ipv6(self, network: Network) -> None: + self._infra.set_weblog_domain_for_ipv6(network) + + def _build_library_infra(self) -> LibraryEndToEndInfra: + return LibraryEndToEndInfra( + environment=self._environment, + tracer_sampling_rate=self._tracer_sampling_rate, + appsec_enabled=self._appsec_enabled, + iast_enabled=self._iast_enabled, + runtime_metrics_enabled=self._runtime_metrics_enabled, + additional_trace_header_tags=self._additional_trace_header_tags, + use_proxy=self._use_proxy, + volumes=self._volumes, + other_containers=self._other_containers, + ) + + def _build_proxy_infra(self, weblog_variant: str) -> GoProxiesEndToEndInfra: + return GoProxiesEndToEndInfra( + weblog_variant, + environment=self._environment, + tracer_sampling_rate=self._tracer_sampling_rate, + appsec_enabled=self._appsec_enabled, + runtime_metrics_enabled=self._runtime_metrics_enabled, + additional_trace_header_tags=self._additional_trace_header_tags, + volumes=self._volumes, + other_containers=self._other_containers, + ) + + @staticmethod + def _discover_weblog_variant_from_logs(host_log_folder: str) -> str | None: + host_project_dir = os.environ.get("SYSTEM_TESTS_HOST_PROJECT_DIR", str(Path.cwd())) + feature_parity_path = Path(host_project_dir) / host_log_folder / "feature_parity.json" + + try: + with feature_parity_path.open(encoding="utf-8") as file: + feature_parity = json.load(file) + except Exception: + return None + + variant = feature_parity.get("variant") + return variant if isinstance(variant, str) else None diff --git a/utils/scripts/ci_orchestrators/workflow_data.py b/utils/scripts/ci_orchestrators/workflow_data.py index d205c0552a2..c232f1d04c8 100644 --- a/utils/scripts/ci_orchestrators/workflow_data.py +++ b/utils/scripts/ci_orchestrators/workflow_data.py @@ -3,7 +3,15 @@ import json import os from pathlib import Path -from utils._context._scenarios import go_proxies +from utils._context.weblog_infrastructure import PROXY_WEBLOGS + + +PROXY_SUPPORTED_SCENARIOS = { + "DEFAULT", + "APPSEC_BLOCKING", + "APPSEC_BLOCKING_FULL_DENYLIST", + "TRACING_CONFIG_NONDEFAULT", +} def _load_json(file_path: str) -> dict: @@ -323,7 +331,7 @@ def _get_endtoend_weblogs( ) # weblog not related to a docker file - for weblog, lib in go_proxies.GO_PROXIES_WEBLOGS.items(): + for weblog, lib in PROXY_WEBLOGS.items(): if lib == library: result.append(Weblog(name=weblog, require_build=False, artifact_name=binaries_artifact)) @@ -568,13 +576,8 @@ def _is_supported(library: str, weblog: str, scenario: str, _ci_environment: str if scenario not in ("OTEL_INTEGRATIONS",): return False - # Go proxies - if scenario.startswith("GO_PROXIES"): - if go_proxies.GO_PROXIES_WEBLOGS.get(weblog) != library: - return False - if go_proxies.GO_PROXIES_WEBLOGS.get(weblog): - if not scenario.startswith("GO_PROXIES"): - return False + if PROXY_WEBLOGS.get(weblog) == library: + return scenario in PROXY_SUPPORTED_SCENARIOS # otel collector if weblog == "otel_collector" or scenario in ("OTEL_COLLECTOR", "OTEL_COLLECTOR_E2E"): From 279fcf175604e668d932e8822795aa20c3b39627 Mon Sep 17 00:00:00 2001 From: Flavien Darche Date: Tue, 10 Mar 2026 21:51:04 +0100 Subject: [PATCH 3/6] in folder --- utils/_context/weblog_infrastructure.py | 444 ------------------ .../weblog_infrastructure/__init__.py | 15 + utils/_context/weblog_infrastructure/base.py | 101 ++++ .../weblog_infrastructure/go_proxies.py | 112 +++++ .../library_end_to_end.py | 110 +++++ .../weblog_infrastructure/selector.py | 148 ++++++ 6 files changed, 486 insertions(+), 444 deletions(-) delete mode 100644 utils/_context/weblog_infrastructure.py create mode 100644 utils/_context/weblog_infrastructure/__init__.py create mode 100644 utils/_context/weblog_infrastructure/base.py create mode 100644 utils/_context/weblog_infrastructure/go_proxies.py create mode 100644 utils/_context/weblog_infrastructure/library_end_to_end.py create mode 100644 utils/_context/weblog_infrastructure/selector.py diff --git a/utils/_context/weblog_infrastructure.py b/utils/_context/weblog_infrastructure.py deleted file mode 100644 index e2a268fa0be..00000000000 --- a/utils/_context/weblog_infrastructure.py +++ /dev/null @@ -1,444 +0,0 @@ -from abc import ABC, abstractmethod -import json -import os -from pathlib import Path -import sys - -from docker.models.networks import Network -import pytest - -from utils._context.component_version import ComponentVersion -from utils._context.containers import ( - CassandraContainer, - DummyServerContainer, - EnvoyContainer, - ExternalProcessingContainer, - HAProxyContainer, - KafkaContainer, - MongoContainer, - MsSqlServerContainer, - MySqlContainer, - PostgresContainer, - RabbitMqContainer, - StreamProcessingOffloadContainer, - TestedContainer, - WeblogContainer, -) -from utils._logger import logger -from utils._weblog import weblog - - -PROXY_WEBLOGS: dict[str, str] = { - "envoy": "envoy", - "haproxy-spoa": "haproxy", -} - -EndToEndHttpContainer = WeblogContainer | EnvoyContainer | HAProxyContainer -EndToEndLibraryContainer = WeblogContainer | ExternalProcessingContainer | StreamProcessingOffloadContainer - - -class WeblogInfra(ABC): - """Infrastructure shipping the HTTP app (aka weblog) instrumented by a library.""" - - @abstractmethod - def configure(self, config: pytest.Config, host_log_folder: str) -> None: - """Perform any configuration. Executed only if the weblog will be used""" - - @abstractmethod - def stop(self) -> None: - """Stop the tested infra""" - - @abstractmethod - def get_containers(self) -> tuple[TestedContainer, ...]: - pass - - @abstractmethod - def get_image_list(self, library: str, weblog_variant: str) -> list[str]: - pass - - -class EndToEndInfra(WeblogInfra): - @property - @abstractmethod - def http_container(self) -> EndToEndHttpContainer: - pass - - @property - @abstractmethod - def library_container(self) -> EndToEndLibraryContainer: - pass - - @property - @abstractmethod - def library_name(self) -> str: - pass - - @property - def library(self) -> ComponentVersion: - return self.library_container.library - - @property - @abstractmethod - def weblog_variant(self) -> str: - pass - - @property - def tracer_sampling_rate(self) -> float | None: - return getattr(self.library_container, "tracer_sampling_rate", None) - - @property - def appsec_rules_file(self) -> str | None: - return getattr(self.library_container, "appsec_rules_file", None) - - @property - def uds_socket(self) -> str | None: - return getattr(self.library_container, "uds_socket", None) - - @property - def uds_mode(self) -> bool: - return getattr(self.library_container, "uds_mode", False) - - @property - def telemetry_heartbeat_interval(self) -> int | float: - return getattr(self.library_container, "telemetry_heartbeat_interval", 2) - - def set_weblog_domain_for_ipv6(self, network: Network) -> None: - set_weblog_domain_for_ipv6 = getattr(self.http_container, "set_weblog_domain_for_ipv6", None) - if callable(set_weblog_domain_for_ipv6): - set_weblog_domain_for_ipv6(network) - return - - if sys.platform == "linux": - weblog.domain = self.http_container.network_ip(network) - logger.info("Linux => Using Container IPv6 address [%s] as weblog domain", weblog.domain) - return - - if sys.platform == "darwin": - logger.info("Mac => Using localhost as weblog domain") - return - - pytest.exit(f"Unsupported platform {sys.platform} with ipv6 enabled", 1) - - -class LibraryEndToEndInfra(EndToEndInfra): - def __init__( - self, - *, - environment: dict[str, str | None] | None = None, - tracer_sampling_rate: float | None = None, - appsec_enabled: bool = True, - iast_enabled: bool = True, - runtime_metrics_enabled: bool = False, - additional_trace_header_tags: tuple[str, ...] = (), - use_proxy: bool = True, - volumes: dict | None = None, - other_containers: tuple[type[TestedContainer], ...] = (), - ) -> None: - self._environment = environment - self._tracer_sampling_rate = tracer_sampling_rate - self._appsec_enabled = appsec_enabled - self._iast_enabled = iast_enabled - self._runtime_metrics_enabled = runtime_metrics_enabled - self._additional_trace_header_tags = additional_trace_header_tags - self._use_proxy = use_proxy - self._volumes = volumes - self._other_container_types = other_containers - self._http_container = WeblogContainer( - environment=environment, - tracer_sampling_rate=tracer_sampling_rate, - appsec_enabled=appsec_enabled, - iast_enabled=iast_enabled, - runtime_metrics_enabled=runtime_metrics_enabled, - additional_trace_header_tags=additional_trace_header_tags, - use_proxy=use_proxy, - volumes=volumes, - ) - self._other_containers = [container() for container in self._other_container_types] - - self._http_container.environment |= { - "INCLUDE_POSTGRES": "true" if PostgresContainer in self._other_container_types else "false", - "INCLUDE_CASSANDRA": "true" if CassandraContainer in self._other_container_types else "false", - "INCLUDE_MONGO": "true" if MongoContainer in self._other_container_types else "false", - "INCLUDE_KAFKA": "true" if KafkaContainer in self._other_container_types else "false", - "INCLUDE_RABBITMQ": "true" if RabbitMqContainer in self._other_container_types else "false", - "INCLUDE_MYSQL": "true" if MySqlContainer in self._other_container_types else "false", - "INCLUDE_SQLSERVER": "true" if MsSqlServerContainer in self._other_container_types else "false", - } - - @property - def http_container(self) -> WeblogContainer: - return self._http_container - - @property - def library_container(self) -> WeblogContainer: - return self._http_container - - @property - def library_name(self) -> str: - return self._http_container.image.labels["system-tests-library"] - - @property - def weblog_variant(self) -> str: - return self._http_container.weblog_variant - - def get_containers(self) -> tuple[TestedContainer, ...]: - return (self._http_container, *self._other_containers) - - def get_image_list(self, library: str, weblog_variant: str) -> list[str]: - containers: list[TestedContainer] = [ - WeblogContainer( - environment=self._environment, - tracer_sampling_rate=self._tracer_sampling_rate, - appsec_enabled=self._appsec_enabled, - iast_enabled=self._iast_enabled, - runtime_metrics_enabled=self._runtime_metrics_enabled, - additional_trace_header_tags=self._additional_trace_header_tags, - use_proxy=self._use_proxy, - volumes=self._volumes, - ) - ] - containers.extend(container() for container in self._other_container_types) - return [image for container in containers for image in container.get_image_list(library, weblog_variant)] - - def configure(self, config: pytest.Config, host_log_folder: str) -> None: # noqa: ARG002 - self._http_container.depends_on.extend(self._other_containers) - - if config.option.force_dd_trace_debug: - self._http_container.environment["DD_TRACE_DEBUG"] = "true" - - if config.option.force_dd_iast_debug: - self._http_container.environment["_DD_IAST_DEBUG"] = "true" - self._http_container.environment["DD_IAST_DEBUG_ENABLED"] = "true" - - def stop(self) -> None: - self._http_container.flush() - self._http_container.stop() - - -class GoProxiesEndToEndInfra(EndToEndInfra): - def __init__( - self, - weblog_variant: str, - *, - environment: dict[str, str | None] | None = None, - tracer_sampling_rate: float | None = None, - appsec_enabled: bool = True, - runtime_metrics_enabled: bool = False, - additional_trace_header_tags: tuple[str, ...] = (), - volumes: dict | None = None, - other_containers: tuple[type[TestedContainer], ...] = (), - ) -> None: - self._weblog_variant = weblog_variant - self._environment = dict(environment) if environment else {} - self._volumes = volumes - self._other_container_types = other_containers - self._library_container: ExternalProcessingContainer | StreamProcessingOffloadContainer - self._http_container: EnvoyContainer | HAProxyContainer - - if tracer_sampling_rate is not None and "DD_TRACE_SAMPLE_RATE" not in self._environment: - self._environment["DD_TRACE_SAMPLE_RATE"] = str(tracer_sampling_rate) - self._environment["DD_TRACE_SAMPLING_RULES"] = json.dumps([{"sample_rate": tracer_sampling_rate}]) - - if not appsec_enabled and "DD_APPSEC_ENABLED" not in self._environment: - self._environment["DD_APPSEC_ENABLED"] = "false" - - if runtime_metrics_enabled and "DD_RUNTIME_METRICS_ENABLED" not in self._environment: - self._environment["DD_RUNTIME_METRICS_ENABLED"] = "true" - - if additional_trace_header_tags and "DD_TRACE_HEADER_TAGS" not in self._environment: - self._environment["DD_TRACE_HEADER_TAGS"] = ",".join(additional_trace_header_tags) - - if weblog_variant == "envoy": - self._library_container = ExternalProcessingContainer(env=self._environment, volumes=self._volumes) - self._http_container = EnvoyContainer() - else: - self._library_container = StreamProcessingOffloadContainer(env=self._environment, volumes=self._volumes) - self._http_container = HAProxyContainer() - - self._dummy_server = DummyServerContainer() - self._other_containers = [container() for container in self._other_container_types] - - @property - def http_container(self) -> EnvoyContainer | HAProxyContainer: - return self._http_container - - @property - def library_container(self) -> ExternalProcessingContainer | StreamProcessingOffloadContainer: - return self._library_container - - @property - def library_name(self) -> str: - return PROXY_WEBLOGS[self._weblog_variant] - - @property - def weblog_variant(self) -> str: - return self._weblog_variant - - @property - def appsec_rules_file(self) -> str | None: - return self._environment.get("DD_APPSEC_RULES") - - def get_containers(self) -> tuple[TestedContainer, ...]: - return (self._library_container, self._http_container, self._dummy_server, *self._other_containers) - - def get_image_list(self, library: str, weblog_variant: str) -> list[str]: - infra = GoProxiesEndToEndInfra( - weblog_variant, - environment=self._environment, - additional_trace_header_tags=(), - volumes=self._volumes, - other_containers=self._other_container_types, - ) - return [ - image for container in infra.get_containers() for image in container.get_image_list(library, weblog_variant) - ] - - def configure(self, config: pytest.Config, host_log_folder: str) -> None: # noqa: ARG002 - self._http_container.depends_on.extend((self._library_container, self._dummy_server)) - - if config.option.force_dd_trace_debug: - self._library_container.environment["DD_TRACE_DEBUG"] = "true" - - def stop(self) -> None: - self._dummy_server.stop() - self._http_container.stop() - self._library_container.stop() - - -class EndToEndWeblogInfra(EndToEndInfra): - def __init__( - self, - *, - environment: dict[str, str | None] | None = None, - tracer_sampling_rate: float | None = None, - appsec_enabled: bool = True, - iast_enabled: bool = True, - runtime_metrics_enabled: bool = False, - additional_trace_header_tags: tuple[str, ...] = (), - use_proxy: bool = True, - volumes: dict | None = None, - other_containers: tuple[type[TestedContainer], ...] = (), - ) -> None: - self._environment = environment - self._tracer_sampling_rate = tracer_sampling_rate - self._appsec_enabled = appsec_enabled - self._iast_enabled = iast_enabled - self._runtime_metrics_enabled = runtime_metrics_enabled - self._additional_trace_header_tags = additional_trace_header_tags - self._use_proxy = use_proxy - self._volumes = volumes - self._other_containers = other_containers - self._infra: EndToEndInfra = self._build_library_infra() - - @property - def http_container(self) -> EndToEndHttpContainer: - return self._infra.http_container - - @property - def library_container(self) -> EndToEndLibraryContainer: - return self._infra.library_container - - @property - def library_name(self) -> str: - return self._infra.library_name - - @property - def library(self) -> ComponentVersion: - return self._infra.library - - @property - def weblog_variant(self) -> str: - return self._infra.weblog_variant - - @property - def tracer_sampling_rate(self) -> float | None: - return self._infra.tracer_sampling_rate - - @property - def appsec_rules_file(self) -> str | None: - return self._infra.appsec_rules_file - - @property - def uds_socket(self) -> str | None: - return self._infra.uds_socket - - @property - def uds_mode(self) -> bool: - return self._infra.uds_mode - - @property - def telemetry_heartbeat_interval(self) -> int | float: - return self._infra.telemetry_heartbeat_interval - - def get_containers(self) -> tuple[TestedContainer, ...]: - return self._infra.get_containers() - - def get_image_list(self, library: str, weblog_variant: str) -> list[str]: - if weblog_variant in PROXY_WEBLOGS: - return self._build_proxy_infra(weblog_variant).get_image_list(library, weblog_variant) - return self._build_library_infra().get_image_list(library, weblog_variant) - - def configure(self, config: pytest.Config, host_log_folder: str) -> None: - weblog_variant = config.option.weblog - - if weblog_variant is None and config.option.replay: - weblog_variant = self._discover_weblog_variant_from_logs(host_log_folder) - - if weblog_variant is None and config.option.replay: - pytest.exit( - "Unable to determine weblog variant in replay mode. Pass --weblog or provide feature_parity.json", - 1, - ) - - if weblog_variant in PROXY_WEBLOGS: - if not isinstance(self._infra, GoProxiesEndToEndInfra) or self._infra.weblog_variant != weblog_variant: - self._infra = self._build_proxy_infra(weblog_variant) - elif not isinstance(self._infra, LibraryEndToEndInfra): - self._infra = self._build_library_infra() - - self._infra.configure(config, host_log_folder) - - def stop(self) -> None: - self._infra.stop() - - def set_weblog_domain_for_ipv6(self, network: Network) -> None: - self._infra.set_weblog_domain_for_ipv6(network) - - def _build_library_infra(self) -> LibraryEndToEndInfra: - return LibraryEndToEndInfra( - environment=self._environment, - tracer_sampling_rate=self._tracer_sampling_rate, - appsec_enabled=self._appsec_enabled, - iast_enabled=self._iast_enabled, - runtime_metrics_enabled=self._runtime_metrics_enabled, - additional_trace_header_tags=self._additional_trace_header_tags, - use_proxy=self._use_proxy, - volumes=self._volumes, - other_containers=self._other_containers, - ) - - def _build_proxy_infra(self, weblog_variant: str) -> GoProxiesEndToEndInfra: - return GoProxiesEndToEndInfra( - weblog_variant, - environment=self._environment, - tracer_sampling_rate=self._tracer_sampling_rate, - appsec_enabled=self._appsec_enabled, - runtime_metrics_enabled=self._runtime_metrics_enabled, - additional_trace_header_tags=self._additional_trace_header_tags, - volumes=self._volumes, - other_containers=self._other_containers, - ) - - @staticmethod - def _discover_weblog_variant_from_logs(host_log_folder: str) -> str | None: - host_project_dir = os.environ.get("SYSTEM_TESTS_HOST_PROJECT_DIR", str(Path.cwd())) - feature_parity_path = Path(host_project_dir) / host_log_folder / "feature_parity.json" - - try: - with feature_parity_path.open(encoding="utf-8") as file: - feature_parity = json.load(file) - except Exception: - return None - - variant = feature_parity.get("variant") - return variant if isinstance(variant, str) else None diff --git a/utils/_context/weblog_infrastructure/__init__.py b/utils/_context/weblog_infrastructure/__init__.py new file mode 100644 index 00000000000..21637100590 --- /dev/null +++ b/utils/_context/weblog_infrastructure/__init__.py @@ -0,0 +1,15 @@ +from .base import EndToEndHttpContainer, EndToEndInfra, EndToEndLibraryContainer, WeblogInfra +from .go_proxies import GoProxiesEndToEndInfra, PROXY_WEBLOGS +from .library_end_to_end import LibraryEndToEndInfra +from .selector import EndToEndWeblogInfra + +__all__ = [ + "PROXY_WEBLOGS", + "EndToEndHttpContainer", + "EndToEndInfra", + "EndToEndLibraryContainer", + "EndToEndWeblogInfra", + "GoProxiesEndToEndInfra", + "LibraryEndToEndInfra", + "WeblogInfra", +] diff --git a/utils/_context/weblog_infrastructure/base.py b/utils/_context/weblog_infrastructure/base.py new file mode 100644 index 00000000000..b6d1b6ef5d0 --- /dev/null +++ b/utils/_context/weblog_infrastructure/base.py @@ -0,0 +1,101 @@ +from abc import ABC, abstractmethod +import sys + +from docker.models.networks import Network +import pytest + +from utils._context.component_version import ComponentVersion +from utils._context.containers import ( + EnvoyContainer, + ExternalProcessingContainer, + HAProxyContainer, + StreamProcessingOffloadContainer, + TestedContainer, + WeblogContainer, +) +from utils._logger import logger +from utils._weblog import weblog + +EndToEndHttpContainer = WeblogContainer | EnvoyContainer | HAProxyContainer +EndToEndLibraryContainer = WeblogContainer | ExternalProcessingContainer | StreamProcessingOffloadContainer + + +class WeblogInfra(ABC): + @abstractmethod + def configure(self, config: pytest.Config, host_log_folder: str) -> None: + pass + + @abstractmethod + def stop(self) -> None: + pass + + @abstractmethod + def get_containers(self) -> tuple[TestedContainer, ...]: + pass + + @abstractmethod + def get_image_list(self, library: str, weblog_variant: str) -> list[str]: + pass + + +class EndToEndInfra(WeblogInfra): + @property + @abstractmethod + def http_container(self) -> EndToEndHttpContainer: + pass + + @property + @abstractmethod + def library_container(self) -> EndToEndLibraryContainer: + pass + + @property + @abstractmethod + def library_name(self) -> str: + pass + + @property + def library(self) -> ComponentVersion: + return self.library_container.library + + @property + @abstractmethod + def weblog_variant(self) -> str: + pass + + @property + def tracer_sampling_rate(self) -> float | None: + return getattr(self.library_container, "tracer_sampling_rate", None) + + @property + def appsec_rules_file(self) -> str | None: + return getattr(self.library_container, "appsec_rules_file", None) + + @property + def uds_socket(self) -> str | None: + return getattr(self.library_container, "uds_socket", None) + + @property + def uds_mode(self) -> bool: + return getattr(self.library_container, "uds_mode", False) + + @property + def telemetry_heartbeat_interval(self) -> int | float: + return getattr(self.library_container, "telemetry_heartbeat_interval", 2) + + def set_weblog_domain_for_ipv6(self, network: Network) -> None: + set_weblog_domain_for_ipv6 = getattr(self.http_container, "set_weblog_domain_for_ipv6", None) + if callable(set_weblog_domain_for_ipv6): + set_weblog_domain_for_ipv6(network) + return + + if sys.platform == "linux": + weblog.domain = self.http_container.network_ip(network) + logger.info("Linux => Using Container IPv6 address [%s] as weblog domain", weblog.domain) + return + + if sys.platform == "darwin": + logger.info("Mac => Using localhost as weblog domain") + return + + pytest.exit(f"Unsupported platform {sys.platform} with ipv6 enabled", 1) diff --git a/utils/_context/weblog_infrastructure/go_proxies.py b/utils/_context/weblog_infrastructure/go_proxies.py new file mode 100644 index 00000000000..a633052d0b8 --- /dev/null +++ b/utils/_context/weblog_infrastructure/go_proxies.py @@ -0,0 +1,112 @@ +import json + +import pytest + +from utils._context.containers import ( + DummyServerContainer, + EnvoyContainer, + ExternalProcessingContainer, + HAProxyContainer, + StreamProcessingOffloadContainer, + TestedContainer, +) + +from .base import EndToEndInfra + +PROXY_WEBLOGS: dict[str, str] = { + "envoy": "envoy", + "haproxy-spoa": "haproxy", +} + + +class GoProxiesEndToEndInfra(EndToEndInfra): + def __init__( + self, + weblog_variant: str, + *, + environment: dict[str, str | None] | None = None, + tracer_sampling_rate: float | None = None, + appsec_enabled: bool = True, + runtime_metrics_enabled: bool = False, + additional_trace_header_tags: tuple[str, ...] = (), + volumes: dict | None = None, + other_containers: tuple[type[TestedContainer], ...] = (), + ) -> None: + self._weblog_variant = weblog_variant + self._environment = dict(environment) if environment else {} + self._volumes = volumes + self._other_container_types = other_containers + self._library_container: ExternalProcessingContainer | StreamProcessingOffloadContainer + self._http_container: EnvoyContainer | HAProxyContainer + + if tracer_sampling_rate is not None and "DD_TRACE_SAMPLE_RATE" not in self._environment: + self._environment["DD_TRACE_SAMPLE_RATE"] = str(tracer_sampling_rate) + self._environment["DD_TRACE_SAMPLING_RULES"] = json.dumps([{"sample_rate": tracer_sampling_rate}]) + + if not appsec_enabled and "DD_APPSEC_ENABLED" not in self._environment: + self._environment["DD_APPSEC_ENABLED"] = "false" + + if runtime_metrics_enabled and "DD_RUNTIME_METRICS_ENABLED" not in self._environment: + self._environment["DD_RUNTIME_METRICS_ENABLED"] = "true" + + if additional_trace_header_tags and "DD_TRACE_HEADER_TAGS" not in self._environment: + self._environment["DD_TRACE_HEADER_TAGS"] = ",".join(additional_trace_header_tags) + + if weblog_variant == "envoy": + self._library_container = ExternalProcessingContainer(env=self._environment, volumes=self._volumes) + self._http_container = EnvoyContainer() + else: + self._library_container = StreamProcessingOffloadContainer(env=self._environment, volumes=self._volumes) + self._http_container = HAProxyContainer() + + self._dummy_server = DummyServerContainer() + self._other_containers = [container() for container in self._other_container_types] + + @property + def http_container(self) -> EnvoyContainer | HAProxyContainer: + return self._http_container + + @property + def library_container(self) -> ExternalProcessingContainer | StreamProcessingOffloadContainer: + return self._library_container + + @property + def library_name(self) -> str: + return PROXY_WEBLOGS[self._weblog_variant] + + @property + def weblog_variant(self) -> str: + return self._weblog_variant + + @property + def appsec_rules_file(self) -> str | None: + return self._environment.get("DD_APPSEC_RULES") + + def get_containers(self) -> tuple[TestedContainer, ...]: + return (self._library_container, self._http_container, self._dummy_server, *self._other_containers) + + def get_image_list(self, library: str, weblog_variant: str) -> list[str]: + infra = GoProxiesEndToEndInfra( + weblog_variant, + environment=self._environment, + volumes=self._volumes, + other_containers=self._other_container_types, + ) + return [ + image for container in infra.get_containers() for image in container.get_image_list(library, weblog_variant) + ] + + def configure(self, config: pytest.Config, host_log_folder: str) -> None: # noqa: ARG002 + self._http_container.depends_on.extend((self._library_container, self._dummy_server)) + + if config.option.force_dd_trace_debug: + self._library_container.environment["DD_TRACE_DEBUG"] = "true" + + if config.option.force_dd_iast_debug: + self._library_container.environment["_DD_IAST_DEBUG"] = "true" + self._library_container.environment["DD_IAST_DEBUG_ENABLED"] = "true" + + def stop(self) -> None: + self._dummy_server.stop() + self._http_container.stop() + self._library_container.stop() diff --git a/utils/_context/weblog_infrastructure/library_end_to_end.py b/utils/_context/weblog_infrastructure/library_end_to_end.py new file mode 100644 index 00000000000..eb79651ce65 --- /dev/null +++ b/utils/_context/weblog_infrastructure/library_end_to_end.py @@ -0,0 +1,110 @@ +import pytest + +from utils._context.containers import ( + CassandraContainer, + KafkaContainer, + MongoContainer, + MsSqlServerContainer, + MySqlContainer, + PostgresContainer, + RabbitMqContainer, + TestedContainer, + WeblogContainer, +) + +from .base import EndToEndInfra + + +class LibraryEndToEndInfra(EndToEndInfra): + def __init__( + self, + *, + environment: dict[str, str | None] | None = None, + tracer_sampling_rate: float | None = None, + appsec_enabled: bool = True, + iast_enabled: bool = True, + runtime_metrics_enabled: bool = False, + additional_trace_header_tags: tuple[str, ...] = (), + use_proxy: bool = True, + volumes: dict | None = None, + other_containers: tuple[type[TestedContainer], ...] = (), + ) -> None: + self._environment = environment + self._tracer_sampling_rate = tracer_sampling_rate + self._appsec_enabled = appsec_enabled + self._iast_enabled = iast_enabled + self._runtime_metrics_enabled = runtime_metrics_enabled + self._additional_trace_header_tags = additional_trace_header_tags + self._use_proxy = use_proxy + self._volumes = volumes + self._other_container_types = other_containers + self._http_container = WeblogContainer( + environment=environment, + tracer_sampling_rate=tracer_sampling_rate, + appsec_enabled=appsec_enabled, + iast_enabled=iast_enabled, + runtime_metrics_enabled=runtime_metrics_enabled, + additional_trace_header_tags=additional_trace_header_tags, + use_proxy=use_proxy, + volumes=volumes, + ) + self._other_containers = [container() for container in self._other_container_types] + + self._http_container.environment |= { + "INCLUDE_POSTGRES": "true" if PostgresContainer in self._other_container_types else "false", + "INCLUDE_CASSANDRA": "true" if CassandraContainer in self._other_container_types else "false", + "INCLUDE_MONGO": "true" if MongoContainer in self._other_container_types else "false", + "INCLUDE_KAFKA": "true" if KafkaContainer in self._other_container_types else "false", + "INCLUDE_RABBITMQ": "true" if RabbitMqContainer in self._other_container_types else "false", + "INCLUDE_MYSQL": "true" if MySqlContainer in self._other_container_types else "false", + "INCLUDE_SQLSERVER": "true" if MsSqlServerContainer in self._other_container_types else "false", + } + + @property + def http_container(self) -> WeblogContainer: + return self._http_container + + @property + def library_container(self) -> WeblogContainer: + return self._http_container + + @property + def library_name(self) -> str: + return self._http_container.image.labels["system-tests-library"] + + @property + def weblog_variant(self) -> str: + return self._http_container.weblog_variant + + def get_containers(self) -> tuple[TestedContainer, ...]: + return (self._http_container, *self._other_containers) + + def get_image_list(self, library: str, weblog_variant: str) -> list[str]: + containers: list[TestedContainer] = [ + WeblogContainer( + environment=self._environment, + tracer_sampling_rate=self._tracer_sampling_rate, + appsec_enabled=self._appsec_enabled, + iast_enabled=self._iast_enabled, + runtime_metrics_enabled=self._runtime_metrics_enabled, + additional_trace_header_tags=self._additional_trace_header_tags, + use_proxy=self._use_proxy, + volumes=self._volumes, + ) + ] + containers.extend(container() for container in self._other_container_types) + return [image for container in containers for image in container.get_image_list(library, weblog_variant)] + + def configure(self, config: pytest.Config, host_log_folder: str) -> None: # noqa: ARG002 + self._http_container.depends_on.extend(self._other_containers) + + if config.option.force_dd_trace_debug: + self._http_container.environment["DD_TRACE_DEBUG"] = "true" + + if config.option.force_dd_iast_debug: + self._http_container.environment["_DD_IAST_DEBUG"] = "true" + self._http_container.environment["DD_IAST_DEBUG_ENABLED"] = "true" + + def stop(self) -> None: + self._http_container.flush() + self._http_container.stop() diff --git a/utils/_context/weblog_infrastructure/selector.py b/utils/_context/weblog_infrastructure/selector.py new file mode 100644 index 00000000000..3af8fafd192 --- /dev/null +++ b/utils/_context/weblog_infrastructure/selector.py @@ -0,0 +1,148 @@ +import json +import os +from pathlib import Path + +from docker.models.networks import Network +import pytest + +from utils._context.component_version import ComponentVersion +from utils._context.containers import TestedContainer + +from .base import EndToEndHttpContainer, EndToEndInfra, EndToEndLibraryContainer +from .go_proxies import GoProxiesEndToEndInfra, PROXY_WEBLOGS +from .library_end_to_end import LibraryEndToEndInfra + + +class EndToEndWeblogInfra(EndToEndInfra): + def __init__( + self, + *, + environment: dict[str, str | None] | None = None, + tracer_sampling_rate: float | None = None, + appsec_enabled: bool = True, + iast_enabled: bool = True, + runtime_metrics_enabled: bool = False, + additional_trace_header_tags: tuple[str, ...] = (), + use_proxy: bool = True, + volumes: dict | None = None, + other_containers: tuple[type[TestedContainer], ...] = (), + ) -> None: + self._environment = environment + self._tracer_sampling_rate = tracer_sampling_rate + self._appsec_enabled = appsec_enabled + self._iast_enabled = iast_enabled + self._runtime_metrics_enabled = runtime_metrics_enabled + self._additional_trace_header_tags = additional_trace_header_tags + self._use_proxy = use_proxy + self._volumes = volumes + self._other_containers = other_containers + self._infra: EndToEndInfra = self._build_library_infra() + + @property + def http_container(self) -> EndToEndHttpContainer: + return self._infra.http_container + + @property + def library_container(self) -> EndToEndLibraryContainer: + return self._infra.library_container + + @property + def library_name(self) -> str: + return self._infra.library_name + + @property + def library(self) -> ComponentVersion: + return self._infra.library + + @property + def weblog_variant(self) -> str: + return self._infra.weblog_variant + + @property + def tracer_sampling_rate(self) -> float | None: + return self._infra.tracer_sampling_rate + + @property + def appsec_rules_file(self) -> str | None: + return self._infra.appsec_rules_file + + @property + def uds_socket(self) -> str | None: + return self._infra.uds_socket + + @property + def uds_mode(self) -> bool: + return self._infra.uds_mode + + @property + def telemetry_heartbeat_interval(self) -> int | float: + return self._infra.telemetry_heartbeat_interval + + def get_containers(self) -> tuple[TestedContainer, ...]: + return self._infra.get_containers() + + def get_image_list(self, library: str, weblog_variant: str) -> list[str]: + if weblog_variant in PROXY_WEBLOGS: + return self._build_proxy_infra(weblog_variant).get_image_list(library, weblog_variant) + return self._build_library_infra().get_image_list(library, weblog_variant) + + def configure(self, config: pytest.Config, host_log_folder: str) -> None: + weblog_variant = config.option.weblog + + if weblog_variant is None and config.option.replay: + replay_variant = self._discover_weblog_variant_from_logs(host_log_folder) + if replay_variant in PROXY_WEBLOGS: + weblog_variant = replay_variant + + if weblog_variant in PROXY_WEBLOGS: + if not isinstance(self._infra, GoProxiesEndToEndInfra) or self._infra.weblog_variant != weblog_variant: + self._infra = self._build_proxy_infra(weblog_variant) + elif not isinstance(self._infra, LibraryEndToEndInfra): + self._infra = self._build_library_infra() + + self._infra.configure(config, host_log_folder) + + def stop(self) -> None: + self._infra.stop() + + def set_weblog_domain_for_ipv6(self, network: Network) -> None: + self._infra.set_weblog_domain_for_ipv6(network) + + def _build_library_infra(self) -> LibraryEndToEndInfra: + return LibraryEndToEndInfra( + environment=self._environment, + tracer_sampling_rate=self._tracer_sampling_rate, + appsec_enabled=self._appsec_enabled, + iast_enabled=self._iast_enabled, + runtime_metrics_enabled=self._runtime_metrics_enabled, + additional_trace_header_tags=self._additional_trace_header_tags, + use_proxy=self._use_proxy, + volumes=self._volumes, + other_containers=self._other_containers, + ) + + def _build_proxy_infra(self, weblog_variant: str) -> GoProxiesEndToEndInfra: + return GoProxiesEndToEndInfra( + weblog_variant, + environment=self._environment, + tracer_sampling_rate=self._tracer_sampling_rate, + appsec_enabled=self._appsec_enabled, + runtime_metrics_enabled=self._runtime_metrics_enabled, + additional_trace_header_tags=self._additional_trace_header_tags, + volumes=self._volumes, + other_containers=self._other_containers, + ) + + @staticmethod + def _discover_weblog_variant_from_logs(host_log_folder: str) -> str | None: + host_project_dir = os.environ.get("SYSTEM_TESTS_HOST_PROJECT_DIR", str(Path.cwd())) + feature_parity_path = Path(host_project_dir) / host_log_folder / "feature_parity.json" + + try: + with feature_parity_path.open(encoding="utf-8") as file: + feature_parity = json.load(file) + except (OSError, json.JSONDecodeError): + return None + + variant = feature_parity.get("variant") + return variant if isinstance(variant, str) else None From 0f1cb393a43449c36987e7ba691a713bae858aba Mon Sep 17 00:00:00 2001 From: Flavien Darche Date: Tue, 10 Mar 2026 22:58:42 +0100 Subject: [PATCH 4/6] specify weblog for all ci run --- .github/workflows/run-end-to-end.yml | 170 +++++++++++++-------------- 1 file changed, 85 insertions(+), 85 deletions(-) diff --git a/.github/workflows/run-end-to-end.yml b/.github/workflows/run-end-to-end.yml index 8c14fbac1a6..0e92587abd9 100644 --- a/.github/workflows/run-end-to-end.yml +++ b/.github/workflows/run-end-to-end.yml @@ -173,248 +173,248 @@ jobs: run: ./run.sh INTEGRATION_FRAMEWORKS -L ${{ inputs.library }} --weblog ${{ inputs.weblog }} - name: Run APPSEC_STANDALONE scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_STANDALONE"') - run: ./run.sh APPSEC_STANDALONE + run: ./run.sh APPSEC_STANDALONE --weblog ${{ inputs.weblog }} - name: Run APPSEC_STANDALONE_API_SECURITY scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_STANDALONE_API_SECURITY"') - run: ./run.sh APPSEC_STANDALONE_API_SECURITY + run: ./run.sh APPSEC_STANDALONE_API_SECURITY --weblog ${{ inputs.weblog }} - name: Run TRACE_STATS_COMPUTATION scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"TRACE_STATS_COMPUTATION"') - run: ./run.sh TRACE_STATS_COMPUTATION + run: ./run.sh TRACE_STATS_COMPUTATION --weblog ${{ inputs.weblog }} - name: Run IAST_STANDALONE scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"IAST_STANDALONE"') - run: ./run.sh IAST_STANDALONE + run: ./run.sh IAST_STANDALONE --weblog ${{ inputs.weblog }} - name: Run SCA_STANDALONE scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"SCA_STANDALONE"') - run: ./run.sh SCA_STANDALONE + run: ./run.sh SCA_STANDALONE --weblog ${{ inputs.weblog }} - name: Run IAST_DEDUPLICATION scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"IAST_DEDUPLICATION"') - run: ./run.sh IAST_DEDUPLICATION + run: ./run.sh IAST_DEDUPLICATION --weblog ${{ inputs.weblog }} - name: Run DEFAULT scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"DEFAULT"') - run: ./run.sh DEFAULT + run: ./run.sh DEFAULT --weblog ${{ inputs.weblog }} - name: Run GRAPHQL_APPSEC scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"GRAPHQL_APPSEC"') - run: ./run.sh GRAPHQL_APPSEC + run: ./run.sh GRAPHQL_APPSEC --weblog ${{ inputs.weblog }} - name: Run GRAPHQL_ERROR_TRACKING scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"GRAPHQL_ERROR_TRACKING"') - run: ./run.sh GRAPHQL_ERROR_TRACKING + run: ./run.sh GRAPHQL_ERROR_TRACKING --weblog ${{ inputs.weblog }} - name: Run IPV6 scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"IPV6"') - run: ./run.sh IPV6 + run: ./run.sh IPV6 --weblog ${{ inputs.weblog }} - name: Run CROSSED_TRACING_LIBRARIES scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"CROSSED_TRACING_LIBRARIES"') - run: ./run.sh CROSSED_TRACING_LIBRARIES + run: ./run.sh CROSSED_TRACING_LIBRARIES --weblog ${{ inputs.weblog }} - name: Run PROFILING scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"PROFILING"') run: | cat /proc/sys/kernel/perf_event_paranoid sudo sysctl kernel.perf_event_paranoid=1 sudo sysctl -p - ./run.sh PROFILING + ./run.sh PROFILING --weblog ${{ inputs.weblog }} env: DD_API_KEY: ${{ secrets.DD_API_KEY }} - name: Run TRACE_PROPAGATION_STYLE_W3C scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"TRACE_PROPAGATION_STYLE_W3C"') - run: ./run.sh TRACE_PROPAGATION_STYLE_W3C + run: ./run.sh TRACE_PROPAGATION_STYLE_W3C --weblog ${{ inputs.weblog }} - name: Run INTEGRATIONS scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"INTEGRATIONS"') - run: ./run.sh INTEGRATIONS + run: ./run.sh INTEGRATIONS --weblog ${{ inputs.weblog }} - name: Run INTEGRATIONS_AWS scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"INTEGRATIONS_AWS"') - run: ./run.sh INTEGRATIONS_AWS + run: ./run.sh INTEGRATIONS_AWS --weblog ${{ inputs.weblog }} - name: Run APM_TRACING_E2E_OTEL scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APM_TRACING_E2E_OTEL"') - run: ./run.sh APM_TRACING_E2E_OTEL + run: ./run.sh APM_TRACING_E2E_OTEL --weblog ${{ inputs.weblog }} env: DD_API_KEY: ${{ secrets.DD_API_KEY }} DD_APPLICATION_KEY: ${{ secrets.DD_APPLICATION_KEY }} DD_APP_KEY: ${{ secrets.DD_APPLICATION_KEY }} - name: Run APM_TRACING_E2E_SINGLE_SPAN scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APM_TRACING_E2E_SINGLE_SPAN"') - run: ./run.sh APM_TRACING_E2E_SINGLE_SPAN + run: ./run.sh APM_TRACING_E2E_SINGLE_SPAN --weblog ${{ inputs.weblog }} env: DD_API_KEY: ${{ secrets.DD_API_KEY }} DD_APP_KEY: ${{ secrets.DD_APPLICATION_KEY }} - name: Run APM_TRACING_EFFICIENT_PAYLOAD scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APM_TRACING_EFFICIENT_PAYLOAD"') - run: ./run.sh APM_TRACING_EFFICIENT_PAYLOAD + run: ./run.sh APM_TRACING_EFFICIENT_PAYLOAD --weblog ${{ inputs.weblog }} - name: Run LIBRARY_CONF_CUSTOM_HEADER_TAGS scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"LIBRARY_CONF_CUSTOM_HEADER_TAGS"') - run: ./run.sh LIBRARY_CONF_CUSTOM_HEADER_TAGS + run: ./run.sh LIBRARY_CONF_CUSTOM_HEADER_TAGS --weblog ${{ inputs.weblog }} - name: Run LIBRARY_CONF_CUSTOM_HEADER_TAGS_INVALID scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"LIBRARY_CONF_CUSTOM_HEADER_TAGS_INVALID"') - run: ./run.sh LIBRARY_CONF_CUSTOM_HEADER_TAGS_INVALID + run: ./run.sh LIBRARY_CONF_CUSTOM_HEADER_TAGS_INVALID --weblog ${{ inputs.weblog }} - name: Run RUNTIME_METRICS_ENABLED scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"RUNTIME_METRICS_ENABLED"') - run: ./run.sh RUNTIME_METRICS_ENABLED + run: ./run.sh RUNTIME_METRICS_ENABLED --weblog ${{ inputs.weblog }} - name: Run TRACING_CONFIG_EMPTY scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"TRACING_CONFIG_EMPTY"') - run: ./run.sh TRACING_CONFIG_EMPTY + run: ./run.sh TRACING_CONFIG_EMPTY --weblog ${{ inputs.weblog }} - name: Run TRACING_CONFIG_NONDEFAULT scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"TRACING_CONFIG_NONDEFAULT"') - run: ./run.sh TRACING_CONFIG_NONDEFAULT + run: ./run.sh TRACING_CONFIG_NONDEFAULT --weblog ${{ inputs.weblog }} - name: Run TRACING_CONFIG_NONDEFAULT_2 scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"TRACING_CONFIG_NONDEFAULT_2"') - run: ./run.sh TRACING_CONFIG_NONDEFAULT_2 + run: ./run.sh TRACING_CONFIG_NONDEFAULT_2 --weblog ${{ inputs.weblog }} - name: Run TRACING_CONFIG_NONDEFAULT_3 scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"TRACING_CONFIG_NONDEFAULT_3"') - run: ./run.sh TRACING_CONFIG_NONDEFAULT_3 + run: ./run.sh TRACING_CONFIG_NONDEFAULT_3 --weblog ${{ inputs.weblog }} - name: Run TRACING_CONFIG_NONDEFAULT_4 scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"TRACING_CONFIG_NONDEFAULT_4"') - run: ./run.sh TRACING_CONFIG_NONDEFAULT_4 + run: ./run.sh TRACING_CONFIG_NONDEFAULT_4 --weblog ${{ inputs.weblog }} - name: Run REMOTE_CONFIG_MOCKED_BACKEND_ASM_FEATURES scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"REMOTE_CONFIG_MOCKED_BACKEND_ASM_FEATURES"') - run: ./run.sh REMOTE_CONFIG_MOCKED_BACKEND_ASM_FEATURES + run: ./run.sh REMOTE_CONFIG_MOCKED_BACKEND_ASM_FEATURES --weblog ${{ inputs.weblog }} - name: Run REMOTE_CONFIG_MOCKED_BACKEND_LIVE_DEBUGGING scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"REMOTE_CONFIG_MOCKED_BACKEND_LIVE_DEBUGGING"') - run: ./run.sh REMOTE_CONFIG_MOCKED_BACKEND_LIVE_DEBUGGING + run: ./run.sh REMOTE_CONFIG_MOCKED_BACKEND_LIVE_DEBUGGING --weblog ${{ inputs.weblog }} - name: Run REMOTE_CONFIG_MOCKED_BACKEND_ASM_DD scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"REMOTE_CONFIG_MOCKED_BACKEND_ASM_DD"') - run: ./run.sh REMOTE_CONFIG_MOCKED_BACKEND_ASM_DD + run: ./run.sh REMOTE_CONFIG_MOCKED_BACKEND_ASM_DD --weblog ${{ inputs.weblog }} - name: Run REMOTE_CONFIG_MOCKED_BACKEND_ASM_FEATURES_NOCACHE scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"REMOTE_CONFIG_MOCKED_BACKEND_ASM_FEATURES_NOCACHE"') - run: ./run.sh REMOTE_CONFIG_MOCKED_BACKEND_ASM_FEATURES_NOCACHE + run: ./run.sh REMOTE_CONFIG_MOCKED_BACKEND_ASM_FEATURES_NOCACHE --weblog ${{ inputs.weblog }} - name: Run FEATURE_FLAGGING_AND_EXPERIMENTATION scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"FEATURE_FLAGGING_AND_EXPERIMENTATION"') - run: ./run.sh FEATURE_FLAGGING_AND_EXPERIMENTATION + run: ./run.sh FEATURE_FLAGGING_AND_EXPERIMENTATION --weblog ${{ inputs.weblog }} - name: Run AGENT_SUPPORTING_SPAN_EVENTS scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"AGENT_SUPPORTING_SPAN_EVENTS"') - run: ./run.sh AGENT_SUPPORTING_SPAN_EVENTS + run: ./run.sh AGENT_SUPPORTING_SPAN_EVENTS --weblog ${{ inputs.weblog }} - name: Run AGENT_NOT_SUPPORTING_SPAN_EVENTS scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"AGENT_NOT_SUPPORTING_SPAN_EVENTS"') - run: ./run.sh AGENT_NOT_SUPPORTING_SPAN_EVENTS + run: ./run.sh AGENT_NOT_SUPPORTING_SPAN_EVENTS --weblog ${{ inputs.weblog }} - name: Run APPSEC_MISSING_RULES scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_MISSING_RULES"') - run: ./run.sh APPSEC_MISSING_RULES + run: ./run.sh APPSEC_MISSING_RULES --weblog ${{ inputs.weblog }} - name: Run APPSEC_CUSTOM_RULES scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_CUSTOM_RULES"') - run: ./run.sh APPSEC_CUSTOM_RULES + run: ./run.sh APPSEC_CUSTOM_RULES --weblog ${{ inputs.weblog }} - name: Run APPSEC_CORRUPTED_RULES scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_CORRUPTED_RULES"') - run: ./run.sh APPSEC_CORRUPTED_RULES + run: ./run.sh APPSEC_CORRUPTED_RULES --weblog ${{ inputs.weblog }} - name: Run APPSEC_RULES_MONITORING_WITH_ERRORS scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_RULES_MONITORING_WITH_ERRORS"') - run: ./run.sh APPSEC_RULES_MONITORING_WITH_ERRORS + run: ./run.sh APPSEC_RULES_MONITORING_WITH_ERRORS --weblog ${{ inputs.weblog }} - name: Run APPSEC_BLOCKING scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_BLOCKING"') - run: ./run.sh APPSEC_BLOCKING + run: ./run.sh APPSEC_BLOCKING --weblog ${{ inputs.weblog }} - name: Run EVERYTHING_DISABLED scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"EVERYTHING_DISABLED"') - run: ./run.sh EVERYTHING_DISABLED + run: ./run.sh EVERYTHING_DISABLED --weblog ${{ inputs.weblog }} - name: Run APPSEC_LOW_WAF_TIMEOUT scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_LOW_WAF_TIMEOUT"') - run: ./run.sh APPSEC_LOW_WAF_TIMEOUT + run: ./run.sh APPSEC_LOW_WAF_TIMEOUT --weblog ${{ inputs.weblog }} - name: Run APPSEC_CUSTOM_OBFUSCATION scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_CUSTOM_OBFUSCATION"') - run: ./run.sh APPSEC_CUSTOM_OBFUSCATION + run: ./run.sh APPSEC_CUSTOM_OBFUSCATION --weblog ${{ inputs.weblog }} - name: Run APPSEC_RATE_LIMITER scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_RATE_LIMITER"') - run: ./run.sh APPSEC_RATE_LIMITER + run: ./run.sh APPSEC_RATE_LIMITER --weblog ${{ inputs.weblog }} - name: Run APPSEC_BLOCKING_FULL_DENYLIST scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_BLOCKING_FULL_DENYLIST"') - run: ./run.sh APPSEC_BLOCKING_FULL_DENYLIST + run: ./run.sh APPSEC_BLOCKING_FULL_DENYLIST --weblog ${{ inputs.weblog }} - name: Run APPSEC_RUNTIME_ACTIVATION scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_RUNTIME_ACTIVATION"') - run: ./run.sh APPSEC_RUNTIME_ACTIVATION + run: ./run.sh APPSEC_RUNTIME_ACTIVATION --weblog ${{ inputs.weblog }} - name: Run APPSEC_WAF_TELEMETRY scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_WAF_TELEMETRY"') - run: ./run.sh APPSEC_WAF_TELEMETRY + run: ./run.sh APPSEC_WAF_TELEMETRY --weblog ${{ inputs.weblog }} - name: Run APPSEC_API_SECURITY scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_API_SECURITY"') - run: ./run.sh APPSEC_API_SECURITY + run: ./run.sh APPSEC_API_SECURITY --weblog ${{ inputs.weblog }} - name: Run APPSEC_API_SECURITY_RC scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_API_SECURITY_RC"') - run: ./run.sh APPSEC_API_SECURITY_RC + run: ./run.sh APPSEC_API_SECURITY_RC --weblog ${{ inputs.weblog }} - name: Run APPSEC_API_SECURITY_NO_RESPONSE_BODY scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_API_SECURITY_NO_RESPONSE_BODY"') - run: ./run.sh APPSEC_API_SECURITY_NO_RESPONSE_BODY + run: ./run.sh APPSEC_API_SECURITY_NO_RESPONSE_BODY --weblog ${{ inputs.weblog }} - name: Run APPSEC_ATO_SDK scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_ATO_SDK"') - run: ./run.sh APPSEC_ATO_SDK + run: ./run.sh APPSEC_ATO_SDK --weblog ${{ inputs.weblog }} - name: Run APPSEC_API_SECURITY_WITH_SAMPLING scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_API_SECURITY_WITH_SAMPLING"') run: | - ./run.sh APPSEC_API_SECURITY_WITH_SAMPLING + ./run.sh APPSEC_API_SECURITY_WITH_SAMPLING --weblog ${{ inputs.weblog }} cat ./logs_appsec_api_security_with_sampling/tests.log 2>/dev/null | grep "API SECURITY" || true - name: Run APPSEC_AUTO_EVENTS_EXTENDED scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_AUTO_EVENTS_EXTENDED"') - run: ./run.sh APPSEC_AUTO_EVENTS_EXTENDED + run: ./run.sh APPSEC_AUTO_EVENTS_EXTENDED --weblog ${{ inputs.weblog }} - name: Run APPSEC_AUTO_EVENTS_RC scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_AUTO_EVENTS_RC"') - run: ./run.sh APPSEC_AUTO_EVENTS_RC + run: ./run.sh APPSEC_AUTO_EVENTS_RC --weblog ${{ inputs.weblog }} - name: Run APPSEC_RASP scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_RASP"') - run: ./run.sh APPSEC_RASP + run: ./run.sh APPSEC_RASP --weblog ${{ inputs.weblog }} - name: Run APPSEC_RASP_WITHOUT_DOWNSTREAM_BODY_ANALYSIS_USING_SAMPLE_RATE scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_RASP_WITHOUT_DOWNSTREAM_BODY_ANALYSIS_USING_SAMPLE_RATE"') - run: ./run.sh APPSEC_RASP_WITHOUT_DOWNSTREAM_BODY_ANALYSIS_USING_SAMPLE_RATE + run: ./run.sh APPSEC_RASP_WITHOUT_DOWNSTREAM_BODY_ANALYSIS_USING_SAMPLE_RATE --weblog ${{ inputs.weblog }} - name: Run APPSEC_RASP_WITHOUT_DOWNSTREAM_BODY_ANALYSIS_USING_MAX scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_RASP_WITHOUT_DOWNSTREAM_BODY_ANALYSIS_USING_MAX"') - run: ./run.sh APPSEC_RASP_WITHOUT_DOWNSTREAM_BODY_ANALYSIS_USING_MAX + run: ./run.sh APPSEC_RASP_WITHOUT_DOWNSTREAM_BODY_ANALYSIS_USING_MAX --weblog ${{ inputs.weblog }} - name: Run APPSEC_STANDALONE_RASP scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_STANDALONE_RASP"') - run: ./run.sh APPSEC_STANDALONE_RASP + run: ./run.sh APPSEC_STANDALONE_RASP --weblog ${{ inputs.weblog }} - name: Run APPSEC_RASP_NON_BLOCKING scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_RASP_NON_BLOCKING"') - run: ./run.sh APPSEC_RASP_NON_BLOCKING + run: ./run.sh APPSEC_RASP_NON_BLOCKING --weblog ${{ inputs.weblog }} - name: Run APPSEC_META_STRUCT_DISABLED scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_META_STRUCT_DISABLED"') - run: ./run.sh APPSEC_META_STRUCT_DISABLED + run: ./run.sh APPSEC_META_STRUCT_DISABLED --weblog ${{ inputs.weblog }} - name: Run SAMPLING scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"SAMPLING"') - run: ./run.sh SAMPLING + run: ./run.sh SAMPLING --weblog ${{ inputs.weblog }} - name: Run TELEMETRY_APP_STARTED_PRODUCTS_DISABLED scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"TELEMETRY_APP_STARTED_PRODUCTS_DISABLED"') - run: ./run.sh TELEMETRY_APP_STARTED_PRODUCTS_DISABLED + run: ./run.sh TELEMETRY_APP_STARTED_PRODUCTS_DISABLED --weblog ${{ inputs.weblog }} - name: Run TELEMETRY_ENHANCED_CONFIG_REPORTING scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"TELEMETRY_ENHANCED_CONFIG_REPORTING"') - run: ./run.sh TELEMETRY_ENHANCED_CONFIG_REPORTING + run: ./run.sh TELEMETRY_ENHANCED_CONFIG_REPORTING --weblog ${{ inputs.weblog }} - name: Run TELEMETRY_LOG_GENERATION_DISABLED scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"TELEMETRY_LOG_GENERATION_DISABLED"') - run: ./run.sh TELEMETRY_LOG_GENERATION_DISABLED + run: ./run.sh TELEMETRY_LOG_GENERATION_DISABLED --weblog ${{ inputs.weblog }} - name: Run TELEMETRY_METRIC_GENERATION_DISABLED scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"TELEMETRY_METRIC_GENERATION_DISABLED"') - run: ./run.sh TELEMETRY_METRIC_GENERATION_DISABLED + run: ./run.sh TELEMETRY_METRIC_GENERATION_DISABLED --weblog ${{ inputs.weblog }} - name: Run TELEMETRY_DEPENDENCY_LOADED_TEST_FOR_DEPENDENCY_COLLECTION_DISABLED scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"TELEMETRY_DEPENDENCY_LOADED_TEST_FOR_DEPENDENCY_COLLECTION_DISABLED"') - run: ./run.sh TELEMETRY_DEPENDENCY_LOADED_TEST_FOR_DEPENDENCY_COLLECTION_DISABLED + run: ./run.sh TELEMETRY_DEPENDENCY_LOADED_TEST_FOR_DEPENDENCY_COLLECTION_DISABLED --weblog ${{ inputs.weblog }} - name: Run DEBUGGER_PROBES_STATUS scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"DEBUGGER_PROBES_STATUS"') - run: ./run.sh DEBUGGER_PROBES_STATUS + run: ./run.sh DEBUGGER_PROBES_STATUS --weblog ${{ inputs.weblog }} - name: Run DEBUGGER_PROBES_SNAPSHOT scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"DEBUGGER_PROBES_SNAPSHOT"') - run: ./run.sh DEBUGGER_PROBES_SNAPSHOT + run: ./run.sh DEBUGGER_PROBES_SNAPSHOT --weblog ${{ inputs.weblog }} - name: Run DEBUGGER_PROBES_SNAPSHOT_WITH_SCM scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"DEBUGGER_PROBES_SNAPSHOT_WITH_SCM"') - run: ./run.sh DEBUGGER_PROBES_SNAPSHOT_WITH_SCM + run: ./run.sh DEBUGGER_PROBES_SNAPSHOT_WITH_SCM --weblog ${{ inputs.weblog }} - name: Run DEBUGGER_PII_REDACTION scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"DEBUGGER_PII_REDACTION"') - run: ./run.sh DEBUGGER_PII_REDACTION + run: ./run.sh DEBUGGER_PII_REDACTION --weblog ${{ inputs.weblog }} - name: Run DEBUGGER_EXPRESSION_LANGUAGE scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"DEBUGGER_EXPRESSION_LANGUAGE"') - run: ./run.sh DEBUGGER_EXPRESSION_LANGUAGE + run: ./run.sh DEBUGGER_EXPRESSION_LANGUAGE --weblog ${{ inputs.weblog }} - name: Run DEBUGGER_EXCEPTION_REPLAY scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"DEBUGGER_EXCEPTION_REPLAY"') - run: ./run.sh DEBUGGER_EXCEPTION_REPLAY + run: ./run.sh DEBUGGER_EXCEPTION_REPLAY --weblog ${{ inputs.weblog }} - name: Run DEBUGGER_SYMDB scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"DEBUGGER_SYMDB"') - run: ./run.sh DEBUGGER_SYMDB + run: ./run.sh DEBUGGER_SYMDB --weblog ${{ inputs.weblog }} - name: Run DEBUGGER_INPRODUCT_ENABLEMENT scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"DEBUGGER_INPRODUCT_ENABLEMENT"') - run: ./run.sh DEBUGGER_INPRODUCT_ENABLEMENT + run: ./run.sh DEBUGGER_INPRODUCT_ENABLEMENT --weblog ${{ inputs.weblog }} - name: Run DEBUGGER_TELEMETRY scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"DEBUGGER_TELEMETRY"') - run: ./run.sh DEBUGGER_TELEMETRY + run: ./run.sh DEBUGGER_TELEMETRY --weblog ${{ inputs.weblog }} - name: Run OTEL_INTEGRATIONS scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"OTEL_INTEGRATIONS"') - run: ./run.sh OTEL_INTEGRATIONS + run: ./run.sh OTEL_INTEGRATIONS --weblog ${{ inputs.weblog }} env: DD_API_KEY: ${{ secrets.DD_API_KEY }} DD_APPLICATION_KEY: ${{ secrets.DD_APPLICATION_KEY }} DD_APP_KEY: ${{ secrets.DD_APPLICATION_KEY }} - name: Run OTEL_TRACING_E2E scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"OTEL_TRACING_E2E"') - run: ./run.sh OTEL_TRACING_E2E + run: ./run.sh OTEL_TRACING_E2E --weblog ${{ inputs.weblog }} env: DD_API_KEY: ${{ secrets.DD_API_KEY }} DD_APPLICATION_KEY: ${{ secrets.DD_APPLICATION_KEY }} @@ -425,7 +425,7 @@ jobs: DD_APP_KEY_3: ${{ secrets.DD_APP_KEY_3 }} - name: Run OTEL_METRIC_E2E scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"OTEL_METRIC_E2E"') - run: ./run.sh OTEL_METRIC_E2E + run: ./run.sh OTEL_METRIC_E2E --weblog ${{ inputs.weblog }} env: DD_API_KEY: ${{ secrets.DD_API_KEY }} DD_APPLICATION_KEY: ${{ secrets.DD_APPLICATION_KEY }} @@ -436,7 +436,7 @@ jobs: DD_APP_KEY_3: ${{ secrets.DD_APP_KEY_3 }} - name: Run OTEL_LOG_E2E scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"OTEL_LOG_E2E"') - run: ./run.sh OTEL_LOG_E2E + run: ./run.sh OTEL_LOG_E2E --weblog ${{ inputs.weblog }} env: DD_API_KEY: ${{ secrets.DD_API_KEY }} DD_APPLICATION_KEY: ${{ secrets.DD_APPLICATION_KEY }} @@ -447,30 +447,30 @@ jobs: DD_APP_KEY_3: ${{ secrets.DD_APP_KEY_3 }} - name: Run APPSEC_LAMBDA_DEFAULT scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_LAMBDA_DEFAULT"') - run: ./run.sh APPSEC_LAMBDA_DEFAULT + run: ./run.sh APPSEC_LAMBDA_DEFAULT --weblog ${{ inputs.weblog }} - name: Run APPSEC_LAMBDA_BLOCKING scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_LAMBDA_BLOCKING"') - run: ./run.sh APPSEC_LAMBDA_BLOCKING + run: ./run.sh APPSEC_LAMBDA_BLOCKING --weblog ${{ inputs.weblog }} - name: Run APPSEC_LAMBDA_API_SECURITY scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_LAMBDA_API_SECURITY"') - run: ./run.sh APPSEC_LAMBDA_API_SECURITY + run: ./run.sh APPSEC_LAMBDA_API_SECURITY --weblog ${{ inputs.weblog }} - name: Run APPSEC_LAMBDA_RASP scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_LAMBDA_RASP"') - run: ./run.sh APPSEC_LAMBDA_RASP + run: ./run.sh APPSEC_LAMBDA_RASP --weblog ${{ inputs.weblog }} - name: Run APPSEC_LAMBDA_INFERRED_SPANS scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_LAMBDA_INFERRED_SPANS"') - run: ./run.sh APPSEC_LAMBDA_INFERRED_SPANS + run: ./run.sh APPSEC_LAMBDA_INFERRED_SPANS --weblog ${{ inputs.weblog }} - name: Run OTEL_COLLECTOR scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"OTEL_COLLECTOR"') - run: ./run.sh OTEL_COLLECTOR + run: ./run.sh OTEL_COLLECTOR --weblog ${{ inputs.weblog }} - name: Run OTEL_COLLECTOR_E2E scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"OTEL_COLLECTOR_E2E"') - run: ./run.sh OTEL_COLLECTOR_E2E + run: ./run.sh OTEL_COLLECTOR_E2E --weblog ${{ inputs.weblog }} env: DD_API_KEY: ${{ secrets.DD_API_KEY }} - name: Run AI_GUARD scenario if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"AI_GUARD"') - run: ./run.sh AI_GUARD + run: ./run.sh AI_GUARD --weblog ${{ inputs.weblog }} - name: Run all scenarios in replay mode if: success() && steps.build.outcome == 'success' && inputs._enable_replay_scenarios From 04eb502432bddd6e4bb93604e430b1b53f86a021 Mon Sep 17 00:00:00 2001 From: Flavien Darche Date: Wed, 11 Mar 2026 11:52:41 +0100 Subject: [PATCH 5/6] added updated proxies manifests --- manifests/envoy.yml | 61 +++++++++++++++++++++++++++++++++++++----- manifests/haproxy.yml | 62 ++++++++++++++++++++++++++++++++++++++----- 2 files changed, 109 insertions(+), 14 deletions(-) diff --git a/manifests/envoy.yml b/manifests/envoy.yml index 05973ecafea..0130004d256 100644 --- a/manifests/envoy.yml +++ b/manifests/envoy.yml @@ -1,14 +1,37 @@ # yaml-language-server: $schema=https://raw.githubusercontent.com/DataDog/system-tests/refs/heads/main/utils/manifest/schema.json --- manifest: - tests/appsec/api_security/test_endpoints.py: irrelevant (language not implementing this feature) + tests/appsec/api_security/test_api_security_rc.py: v1.72.0 + tests/appsec/api_security/test_api_security_rc.py::Test_API_Security_RC_ASM_DD_processors: v2.0.0 + tests/appsec/api_security/test_api_security_rc.py::Test_API_Security_RC_ASM_DD_scanners: missing_feature (missing /tag_value endpoint in the weblog) + tests/appsec/api_security/test_apisecurity_telemetry.py::Test_API_Security_Telemetry_Metric: missing_feature (weblog does not support set 404 status code and /tag_value endpoint) + tests/appsec/api_security/test_custom_data_classification.py: v2.4.0 + tests/appsec/api_security/test_custom_data_classification.py::Test_API_Security_Custom_Data_Classification_Multiple_Scanners: missing_feature (missing /tag_value endpoint in the weblog) + tests/appsec/api_security/test_custom_data_classification.py::Test_API_Security_Custom_Data_Classification_Negative: missing_feature (missing /tag_value endpoint in the weblog) + tests/appsec/api_security/test_custom_data_classification.py::Test_API_Security_Custom_Data_Classification_Scanner: missing_feature (missing /tag_value endpoint in the weblog) + tests/appsec/api_security/test_schemas.py: v1.72.0 + tests/appsec/api_security/test_schemas.py::Test_Schema_Request_FormUrlEncoded_Body: missing_feature (missing /tag_value endpoint in the weblog) + tests/appsec/api_security/test_schemas.py::Test_Schema_Request_Json_Body: missing_feature (missing /tag_value endpoint in the weblog) + tests/appsec/api_security/test_schemas.py::Test_Schema_Request_Path_Parameters: irrelevant (can only infer the path parameters from the request when using proxies) + tests/appsec/api_security/test_schemas.py::Test_Schema_Response_Body::test_request_method: missing_feature (missing /tag_value endpoint in the weblog) + tests/appsec/api_security/test_schemas.py::Test_Schema_Response_Body_env_var: missing_feature (The endpoint /tag_value is not implemented in the weblog) + tests/appsec/api_security/test_schemas.py::Test_Schema_Response_Headers: missing_feature (missing /tag_value endpoint in the weblog) + tests/appsec/api_security/test_schemas.py::Test_Schema_Response_on_Block::test_request_method: missing_feature (missing /tag_value endpoint in the weblog) tests/appsec/test_alpha.py: v1.72.0 + tests/appsec/test_asm_standalone.py: v1.73.0 + tests/appsec/test_asm_standalone.py::Test_APISecurityStandalone: missing_feature + tests/appsec/test_asm_standalone.py::Test_AppSecStandalone_UpstreamPropagation_V2: missing_feature (weblog does not implement upstream request) + tests/appsec/test_asm_standalone.py::Test_UserEventsStandalone_Automated: irrelevant (Proxies doesn't support login events (go sdk)) + tests/appsec/test_asm_standalone.py::Test_UserEventsStandalone_SDK_V1: irrelevant (Proxies doesn't support login events (go sdk)) + tests/appsec/test_asm_standalone.py::Test_UserEventsStandalone_SDK_V2: irrelevant (Proxies doesn't support login events (go sdk)) + tests/appsec/test_automated_login_events.py::Test_V3_Login_Events_Blocking: irrelevant (Proxies doesn't support login events (go sdk)) + tests/appsec/test_automated_user_and_session_tracking.py: irrelevant (Proxies doesn't support login events (go sdk)) tests/appsec/test_blocking_addresses.py: v1.72.0 tests/appsec/test_blocking_addresses.py::Test_BlockingGraphqlResolvers: irrelevant tests/appsec/test_blocking_addresses.py::Test_Blocking_client_ip_with_K8_private_ip: v2.2.0 tests/appsec/test_blocking_addresses.py::Test_Blocking_client_ip_with_forwarded: v2.3.0 - tests/appsec/test_blocking_addresses.py::Test_Blocking_request_body: missing_feature - tests/appsec/test_blocking_addresses.py::Test_Blocking_request_body_multipart: irrelevant (Body blocking happens through SDK) + tests/appsec/test_blocking_addresses.py::Test_Blocking_request_body: missing_feature (the tests is made using raw text and not json, skiped in proxies) + tests/appsec/test_blocking_addresses.py::Test_Blocking_request_body_multipart: missing_feature tests/appsec/test_blocking_addresses.py::Test_Blocking_request_cookies::test_blocking_before: missing_feature (The endpoint /tag_value is not implemented in the weblog) tests/appsec/test_blocking_addresses.py::Test_Blocking_request_headers::test_blocking_before: missing_feature (The endpoint /tag_value is not implemented in the weblog) tests/appsec/test_blocking_addresses.py::Test_Blocking_request_method::test_blocking_before: missing_feature (The endpoint /tag_value is not implemented in the weblog) @@ -21,16 +44,40 @@ manifest: tests/appsec/test_blocking_addresses.py::Test_Blocking_response_status: missing_feature tests/appsec/test_blocking_addresses.py::Test_Blocking_user_id: irrelevant (not supported on proxies) tests/appsec/test_blocking_addresses.py::Test_Suspicious_Request_Blocking: missing_feature (can't test with set tag) + tests/appsec/test_blocking_addresses.py::Test_Suspicious_Request_Blocking::test_blocking_without_path_params: v2.3.0 tests/appsec/test_client_ip.py: v1.72.0 - tests/appsec/test_ip_blocking_full_denylist.py::Test_AppSecIPBlockingFullDenylist: v1.72.0 + tests/appsec/test_conf.py::Test_ConfigurationVariables: v2.0.0 + tests/appsec/test_conf.py::Test_ConfigurationVariables_New_Obfuscation: v2.1.0 + tests/appsec/test_extended_data_collection.py: v1.72.0 + tests/appsec/test_extended_data_collection.py::Test_ExtendedDataCollectionCapability: missing_feature + tests/appsec/test_extended_data_collection.py::Test_ExtendedRequestBodyCollection: missing_feature + tests/appsec/test_extended_data_collection.py::Test_ExtendedRequestHeadersDataCollection: missing_feature + tests/appsec/test_extended_data_collection.py::Test_ExtendedResponseHeadersDataCollection: missing_feature + tests/appsec/test_extended_header_collection.py::Test_ExtendedHeaderCollection: missing_feature (weblog does not implement /headers endpoint) + tests/appsec/test_fingerprinting.py: v1.72.0 + tests/appsec/test_fingerprinting.py::Test_Fingerprinting_Header_And_Network_Preprocessor::test_fingerprinting_header_blocking: missing_feature (proxies removes the 'connection' header, thus making fails the header fingerprinting rule) + tests/appsec/test_fingerprinting.py::Test_Fingerprinting_Session_Preprocessor::test_session_non_blocking: irrelevant (Proxies doesn't support session fingerprinting) + tests/appsec/test_ip_blocking_full_denylist.py: v1.72.0 + tests/appsec/test_remote_config_rule_changes.py: v1.72.0 + tests/appsec/test_remote_config_rule_changes.py::Test_AsmDdMultiConfiguration: v2.1.0 tests/appsec/test_reports.py: v1.72.0 - tests/appsec/test_request_blocking.py::Test_AppSecRequestBlocking: v1.72.0 + tests/appsec/test_request_blocking.py: v1.72.0 + tests/appsec/test_trace_tagging.py::Test_TraceTaggingRules: v2.1.0 + tests/appsec/test_trace_tagging.py::Test_TraceTaggingRules::test_rule_with_attributes_no_keep_event: irrelevant (Proxies run with appsec standalone by default) + tests/appsec/test_trace_tagging.py::Test_TraceTaggingRules::test_rule_with_attributes_no_keep_no_event: irrelevant (Proxies run with appsec standalone by default) + tests/appsec/test_trace_tagging.py::Test_TraceTaggingRulesRcCapability: v2.1.0 tests/appsec/test_traces.py: v1.72.0 - tests/appsec/test_traces.py::Test_AppSecEventSpanTags::test_header_collection: irrelevant (test) tests/appsec/test_traces.py::Test_CollectRespondHeaders::test_header_collection: missing_feature (The endpoint /headers is not implemented in the weblog) + tests/appsec/test_user_blocking_full_denylist.py::Test_UserBlocking_FullDenylist: missing_feature (no endpoint to test user blocking - auto instrum irrelevant) tests/appsec/test_versions.py::Test_Events: v1.72.0 - tests/parametric/test_otel_span_methods.py::Test_Otel_Span_Methods::test_otel_record_exception_sets_handling_stack_in_go: irrelevant + tests/appsec/waf/test_blocking.py: v1.72.0 + tests/appsec/waf/test_blocking.py::Test_Blocking::test_accept_partial_html: missing_feature (Support for partial html not implemented) + tests/appsec/waf/test_blocking.py::Test_Blocking_strip_response_headers: missing_feature + tests/appsec/waf/test_blocking_security_response_id.py: v2.5.0 + tests/remote_config/test_remote_configuration.py: v1.72.0 + tests/remote_config/test_remote_configuration.py::Test_RemoteConfigurationUpdateSequenceASMDDNoCache: irrelevant (cache is implemented) tests/test_config_consistency.py::Test_Config_UnifiedServiceTagging_CustomService: v1.72.0 + tests/test_resource_renaming.py: v2.4.0 tests/test_scrubbing.py: v1.72.0 tests/test_semantic_conventions.py: v1.72.0 tests/test_semantic_conventions.py::Test_Meta::test_meta_component_tag: v2.3.0 diff --git a/manifests/haproxy.yml b/manifests/haproxy.yml index 8b9d35d9800..5d911f22eff 100644 --- a/manifests/haproxy.yml +++ b/manifests/haproxy.yml @@ -1,12 +1,36 @@ # yaml-language-server: $schema=https://raw.githubusercontent.com/DataDog/system-tests/refs/heads/main/utils/manifest/schema.json --- manifest: - tests/appsec/api_security/test_endpoints.py: irrelevant (language not implementing this feature) + tests/appsec/api_security/test_api_security_rc.py: v2.4.0 + tests/appsec/api_security/test_api_security_rc.py::Test_API_Security_RC_ASM_DD_scanners: missing_feature (missing /tag_value endpoint in the weblog) + tests/appsec/api_security/test_apisecurity_telemetry.py::Test_API_Security_Telemetry_Metric: missing_feature (weblog does not support set 404 status code and /tag_value endpoint) + tests/appsec/api_security/test_custom_data_classification.py: v2.4.0 + tests/appsec/api_security/test_custom_data_classification.py::Test_API_Security_Custom_Data_Classification_Multiple_Scanners: missing_feature (missing /tag_value endpoint in the weblog) + tests/appsec/api_security/test_custom_data_classification.py::Test_API_Security_Custom_Data_Classification_Negative: missing_feature (missing /tag_value endpoint in the weblog) + tests/appsec/api_security/test_custom_data_classification.py::Test_API_Security_Custom_Data_Classification_Scanner: missing_feature (missing /tag_value endpoint in the weblog) + tests/appsec/api_security/test_schemas.py: v2.4.0 + tests/appsec/api_security/test_schemas.py::Test_Schema_Request_FormUrlEncoded_Body: missing_feature (missing /tag_value endpoint in the weblog) + tests/appsec/api_security/test_schemas.py::Test_Schema_Request_Json_Body: missing_feature (missing /tag_value endpoint in the weblog) + tests/appsec/api_security/test_schemas.py::Test_Schema_Request_Path_Parameters: irrelevant (can only infer the path parameters from the request when using proxies) + tests/appsec/api_security/test_schemas.py::Test_Schema_Response_Body::test_request_method: missing_feature (missing /tag_value endpoint in the weblog) + tests/appsec/api_security/test_schemas.py::Test_Schema_Response_Body_env_var: missing_feature (The endpoint /tag_value is not implemented in the weblog) + tests/appsec/api_security/test_schemas.py::Test_Schema_Response_Headers: missing_feature (missing /tag_value endpoint in the weblog) + tests/appsec/api_security/test_schemas.py::Test_Schema_Response_on_Block::test_request_method: missing_feature (missing /tag_value endpoint in the weblog) tests/appsec/test_alpha.py: v2.4.0 + tests/appsec/test_asm_standalone.py: v2.4.0 + tests/appsec/test_asm_standalone.py::Test_APISecurityStandalone: missing_feature + tests/appsec/test_asm_standalone.py::Test_AppSecStandalone_UpstreamPropagation_V2: missing_feature (weblog does not implement upstream request) + tests/appsec/test_asm_standalone.py::Test_UserEventsStandalone_Automated: irrelevant (Proxies doesn't support login events (go sdk)) + tests/appsec/test_asm_standalone.py::Test_UserEventsStandalone_SDK_V1: irrelevant (Proxies doesn't support login events (go sdk)) + tests/appsec/test_asm_standalone.py::Test_UserEventsStandalone_SDK_V2: irrelevant (Proxies doesn't support login events (go sdk)) + tests/appsec/test_automated_login_events.py::Test_V3_Login_Events_Blocking: irrelevant (Proxies doesn't support login events (go sdk)) + tests/appsec/test_automated_user_and_session_tracking.py: irrelevant (Proxies doesn't support login events (go sdk)) tests/appsec/test_blocking_addresses.py: v2.4.0 tests/appsec/test_blocking_addresses.py::Test_BlockingGraphqlResolvers: irrelevant - tests/appsec/test_blocking_addresses.py::Test_Blocking_request_body: missing_feature - tests/appsec/test_blocking_addresses.py::Test_Blocking_request_body_multipart: irrelevant (Body blocking happens through SDK) + tests/appsec/test_blocking_addresses.py::Test_Blocking_client_ip_with_K8_private_ip: v2.4.0 + tests/appsec/test_blocking_addresses.py::Test_Blocking_client_ip_with_forwarded: v2.4.0 + tests/appsec/test_blocking_addresses.py::Test_Blocking_request_body: missing_feature (the tests is made using raw text and not json, skiped in proxies) + tests/appsec/test_blocking_addresses.py::Test_Blocking_request_body_multipart: missing_feature tests/appsec/test_blocking_addresses.py::Test_Blocking_request_cookies::test_blocking_before: missing_feature (The endpoint /tag_value is not implemented in the weblog) tests/appsec/test_blocking_addresses.py::Test_Blocking_request_headers::test_blocking_before: missing_feature (The endpoint /tag_value is not implemented in the weblog) tests/appsec/test_blocking_addresses.py::Test_Blocking_request_method::test_blocking_before: missing_feature (The endpoint /tag_value is not implemented in the weblog) @@ -19,18 +43,42 @@ manifest: tests/appsec/test_blocking_addresses.py::Test_Blocking_response_status: missing_feature tests/appsec/test_blocking_addresses.py::Test_Blocking_user_id: irrelevant (not supported on proxies) tests/appsec/test_blocking_addresses.py::Test_Suspicious_Request_Blocking: missing_feature (can't test with set tag) + tests/appsec/test_blocking_addresses.py::Test_Suspicious_Request_Blocking::test_blocking_without_path_params: v2.4.0 tests/appsec/test_client_ip.py: v2.4.0 - tests/appsec/test_ip_blocking_full_denylist.py::Test_AppSecIPBlockingFullDenylist: v2.4.0 + tests/appsec/test_conf.py::Test_ConfigurationVariables: v2.4.0 + tests/appsec/test_conf.py::Test_ConfigurationVariables_New_Obfuscation: v2.4.0 + tests/appsec/test_extended_data_collection.py: v2.4.0 + tests/appsec/test_extended_data_collection.py::Test_ExtendedDataCollectionCapability: missing_feature + tests/appsec/test_extended_data_collection.py::Test_ExtendedRequestBodyCollection: missing_feature + tests/appsec/test_extended_data_collection.py::Test_ExtendedRequestHeadersDataCollection: missing_feature + tests/appsec/test_extended_data_collection.py::Test_ExtendedResponseHeadersDataCollection: missing_feature + tests/appsec/test_extended_header_collection.py::Test_ExtendedHeaderCollection: missing_feature (weblog does not implement /headers endpoint) + tests/appsec/test_fingerprinting.py: v2.4.0 + tests/appsec/test_fingerprinting.py::Test_Fingerprinting_Header_And_Network_Preprocessor::test_fingerprinting_header_blocking: missing_feature (proxies removes the 'connection' header, thus making fails the header fingerprinting rule) + tests/appsec/test_fingerprinting.py::Test_Fingerprinting_Session_Preprocessor::test_session_non_blocking: irrelevant (Proxies doesn't support session fingerprinting) + tests/appsec/test_ip_blocking_full_denylist.py: v2.4.0 + tests/appsec/test_remote_config_rule_changes.py: v2.4.0 tests/appsec/test_reports.py: v2.4.0 - tests/appsec/test_request_blocking.py::Test_AppSecRequestBlocking: v2.4.0 + tests/appsec/test_request_blocking.py: v2.4.0 + tests/appsec/test_trace_tagging.py::Test_TraceTaggingRules: v2.4.0 + tests/appsec/test_trace_tagging.py::Test_TraceTaggingRules::test_rule_with_attributes_no_keep_event: irrelevant (Proxies run with appsec standalone by default) + tests/appsec/test_trace_tagging.py::Test_TraceTaggingRules::test_rule_with_attributes_no_keep_no_event: irrelevant (Proxies run with appsec standalone by default) + tests/appsec/test_trace_tagging.py::Test_TraceTaggingRulesRcCapability: v2.4.0 tests/appsec/test_traces.py: v2.4.0 - tests/appsec/test_traces.py::Test_AppSecEventSpanTags::test_header_collection: irrelevant (test) tests/appsec/test_traces.py::Test_CollectRespondHeaders::test_header_collection: missing_feature (The endpoint /headers is not implemented in the weblog) + tests/appsec/test_user_blocking_full_denylist.py::Test_UserBlocking_FullDenylist: missing_feature (no endpoint to test user blocking - auto instrum irrelevant) tests/appsec/test_versions.py::Test_Events: v2.4.0 - tests/parametric/test_otel_span_methods.py::Test_Otel_Span_Methods::test_otel_record_exception_sets_handling_stack_in_go: irrelevant + tests/appsec/waf/test_blocking.py: v2.4.0 + tests/appsec/waf/test_blocking.py::Test_Blocking::test_accept_partial_html: missing_feature (Support for partial html not implemented) + tests/appsec/waf/test_blocking.py::Test_Blocking_strip_response_headers: missing_feature + tests/appsec/waf/test_blocking_security_response_id.py: v2.5.0 + tests/remote_config/test_remote_configuration.py: v2.4.0 + tests/remote_config/test_remote_configuration.py::Test_RemoteConfigurationUpdateSequenceASMDDNoCache: irrelevant (cache is implemented) tests/test_config_consistency.py::Test_Config_UnifiedServiceTagging_CustomService: v2.4.0 + tests/test_resource_renaming.py: v2.4.0 tests/test_scrubbing.py: v2.4.0 tests/test_semantic_conventions.py: v2.4.0 + tests/test_semantic_conventions.py::Test_Meta::test_meta_component_tag: v2.4.0 tests/test_standard_tags.py: v2.4.0 tests/test_standard_tags.py::Test_StandardTagsReferrerHostname: missing_feature tests/test_standard_tags.py::Test_StandardTagsUrl::test_multiple_matching_substring: irrelevant (tracer did not yet implemented the new version of query parameters obfuscation regex) From 7848092e0d863c2ef8a848d6ab723a266f1681de Mon Sep 17 00:00:00 2001 From: Flavien Darche Date: Wed, 11 Mar 2026 13:32:16 +0100 Subject: [PATCH 6/6] more updates --- manifests/envoy.yml | 23 +++++++++++++++++++ manifests/haproxy.yml | 23 +++++++++++++++++++ tests/test_the_test/scenarios.json | 3 --- utils/_context/_scenarios/endtoend.py | 4 +--- .../weblog_infrastructure/go_proxies.py | 4 ---- .../scripts/ci_orchestrators/workflow_data.py | 6 ++--- 6 files changed, 50 insertions(+), 13 deletions(-) diff --git a/manifests/envoy.yml b/manifests/envoy.yml index 0130004d256..8f8d9b5785e 100644 --- a/manifests/envoy.yml +++ b/manifests/envoy.yml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=https://raw.githubusercontent.com/DataDog/system-tests/refs/heads/main/utils/manifest/schema.json --- manifest: + tests/ai_guard: irrelevant (no ai guard) tests/appsec/api_security/test_api_security_rc.py: v1.72.0 tests/appsec/api_security/test_api_security_rc.py::Test_API_Security_RC_ASM_DD_processors: v2.0.0 tests/appsec/api_security/test_api_security_rc.py::Test_API_Security_RC_ASM_DD_scanners: missing_feature (missing /tag_value endpoint in the weblog) @@ -17,6 +18,7 @@ manifest: tests/appsec/api_security/test_schemas.py::Test_Schema_Response_Body_env_var: missing_feature (The endpoint /tag_value is not implemented in the weblog) tests/appsec/api_security/test_schemas.py::Test_Schema_Response_Headers: missing_feature (missing /tag_value endpoint in the weblog) tests/appsec/api_security/test_schemas.py::Test_Schema_Response_on_Block::test_request_method: missing_feature (missing /tag_value endpoint in the weblog) + tests/appsec/iast: irrelevant (proxies does not support iast) tests/appsec/test_alpha.py: v1.72.0 tests/appsec/test_asm_standalone.py: v1.73.0 tests/appsec/test_asm_standalone.py::Test_APISecurityStandalone: missing_feature @@ -24,6 +26,7 @@ manifest: tests/appsec/test_asm_standalone.py::Test_UserEventsStandalone_Automated: irrelevant (Proxies doesn't support login events (go sdk)) tests/appsec/test_asm_standalone.py::Test_UserEventsStandalone_SDK_V1: irrelevant (Proxies doesn't support login events (go sdk)) tests/appsec/test_asm_standalone.py::Test_UserEventsStandalone_SDK_V2: irrelevant (Proxies doesn't support login events (go sdk)) + tests/appsec/test_automated_login_events.py: irrelevant (proxies does not support login events) tests/appsec/test_automated_login_events.py::Test_V3_Login_Events_Blocking: irrelevant (Proxies doesn't support login events (go sdk)) tests/appsec/test_automated_user_and_session_tracking.py: irrelevant (Proxies doesn't support login events (go sdk)) tests/appsec/test_blocking_addresses.py: v1.72.0 @@ -48,6 +51,7 @@ manifest: tests/appsec/test_client_ip.py: v1.72.0 tests/appsec/test_conf.py::Test_ConfigurationVariables: v2.0.0 tests/appsec/test_conf.py::Test_ConfigurationVariables_New_Obfuscation: v2.1.0 + tests/appsec/test_event_tracking.py: irrelevant (proxies does not support login events) tests/appsec/test_extended_data_collection.py: v1.72.0 tests/appsec/test_extended_data_collection.py::Test_ExtendedDataCollectionCapability: missing_feature tests/appsec/test_extended_data_collection.py::Test_ExtendedRequestBodyCollection: missing_feature @@ -58,10 +62,15 @@ manifest: tests/appsec/test_fingerprinting.py::Test_Fingerprinting_Header_And_Network_Preprocessor::test_fingerprinting_header_blocking: missing_feature (proxies removes the 'connection' header, thus making fails the header fingerprinting rule) tests/appsec/test_fingerprinting.py::Test_Fingerprinting_Session_Preprocessor::test_session_non_blocking: irrelevant (Proxies doesn't support session fingerprinting) tests/appsec/test_ip_blocking_full_denylist.py: v1.72.0 + tests/appsec/test_logs.py::Test_Standardization: missing_feature + tests/appsec/test_logs.py::Test_StandardizationBlockMode: missing_feature + tests/appsec/test_only_python.py::Test_ImportError: irrelevant (specific tests for python tracer) tests/appsec/test_remote_config_rule_changes.py: v1.72.0 tests/appsec/test_remote_config_rule_changes.py::Test_AsmDdMultiConfiguration: v2.1.0 tests/appsec/test_reports.py: v1.72.0 tests/appsec/test_request_blocking.py: v1.72.0 + tests/appsec/test_shell_execution.py: irrelevant + tests/appsec/test_span_tags_headers.py::Test_Headers_Event_Blocking::test_content_type_event_blocking: missing_feature tests/appsec/test_trace_tagging.py::Test_TraceTaggingRules: v2.1.0 tests/appsec/test_trace_tagging.py::Test_TraceTaggingRules::test_rule_with_attributes_no_keep_event: irrelevant (Proxies run with appsec standalone by default) tests/appsec/test_trace_tagging.py::Test_TraceTaggingRules::test_rule_with_attributes_no_keep_no_event: irrelevant (Proxies run with appsec standalone by default) @@ -70,13 +79,27 @@ manifest: tests/appsec/test_traces.py::Test_CollectRespondHeaders::test_header_collection: missing_feature (The endpoint /headers is not implemented in the weblog) tests/appsec/test_user_blocking_full_denylist.py::Test_UserBlocking_FullDenylist: missing_feature (no endpoint to test user blocking - auto instrum irrelevant) tests/appsec/test_versions.py::Test_Events: v1.72.0 + tests/appsec/waf/test_addresses.py::Test_BodyUrlEncoded::test_body_value: missing_feature (no urlencoded body parsing implemented in proxies) + tests/appsec/waf/test_addresses.py::Test_BodyXml::test_xml_attr_value: missing_feature (no xml body parsing implemented in proxies) + tests/appsec/waf/test_addresses.py::Test_BodyXml::test_xml_content: missing_feature (no xml body parsing implemented in proxies) + tests/appsec/waf/test_addresses.py::Test_FullGrpc::test_main: irrelevant (proxies does not support grpc) + tests/appsec/waf/test_addresses.py::Test_PathParams::test_security_scanner: missing_feature + tests/appsec/waf/test_addresses.py::Test_ResponseStatus::test_basic: missing_feature + tests/appsec/waf/test_addresses.py::Test_gRPC::test_basic: missing_feature (proxies does not support grpc) tests/appsec/waf/test_blocking.py: v1.72.0 + tests/appsec/waf/test_blocking.py::Test_Blocking::test_accept_full_html: missing_feature tests/appsec/waf/test_blocking.py::Test_Blocking::test_accept_partial_html: missing_feature (Support for partial html not implemented) + tests/appsec/waf/test_blocking.py::Test_Blocking::test_html_template_v2: missing_feature tests/appsec/waf/test_blocking.py::Test_Blocking_strip_response_headers: missing_feature tests/appsec/waf/test_blocking_security_response_id.py: v2.5.0 + tests/appsec/waf/test_miscs.py::Test_404::test_404: missing_feature (weblog does not support 404 status code) + tests/integrations/test_dbm.py: irrelevant tests/remote_config/test_remote_configuration.py: v1.72.0 tests/remote_config/test_remote_configuration.py::Test_RemoteConfigurationUpdateSequenceASMDDNoCache: irrelevant (cache is implemented) + tests/serverless: irrelevant tests/test_config_consistency.py::Test_Config_UnifiedServiceTagging_CustomService: v1.72.0 + tests/test_identify.py: irrelevant (proxies does not support custom sdk) + tests/test_protobuf.py: irrelevant tests/test_resource_renaming.py: v2.4.0 tests/test_scrubbing.py: v1.72.0 tests/test_semantic_conventions.py: v1.72.0 diff --git a/manifests/haproxy.yml b/manifests/haproxy.yml index 5d911f22eff..1a0caed34b3 100644 --- a/manifests/haproxy.yml +++ b/manifests/haproxy.yml @@ -1,6 +1,7 @@ # yaml-language-server: $schema=https://raw.githubusercontent.com/DataDog/system-tests/refs/heads/main/utils/manifest/schema.json --- manifest: + tests/ai_guard: irrelevant (no ai guard) tests/appsec/api_security/test_api_security_rc.py: v2.4.0 tests/appsec/api_security/test_api_security_rc.py::Test_API_Security_RC_ASM_DD_scanners: missing_feature (missing /tag_value endpoint in the weblog) tests/appsec/api_security/test_apisecurity_telemetry.py::Test_API_Security_Telemetry_Metric: missing_feature (weblog does not support set 404 status code and /tag_value endpoint) @@ -16,6 +17,7 @@ manifest: tests/appsec/api_security/test_schemas.py::Test_Schema_Response_Body_env_var: missing_feature (The endpoint /tag_value is not implemented in the weblog) tests/appsec/api_security/test_schemas.py::Test_Schema_Response_Headers: missing_feature (missing /tag_value endpoint in the weblog) tests/appsec/api_security/test_schemas.py::Test_Schema_Response_on_Block::test_request_method: missing_feature (missing /tag_value endpoint in the weblog) + tests/appsec/iast: irrelevant (proxies does not support iast) tests/appsec/test_alpha.py: v2.4.0 tests/appsec/test_asm_standalone.py: v2.4.0 tests/appsec/test_asm_standalone.py::Test_APISecurityStandalone: missing_feature @@ -23,6 +25,7 @@ manifest: tests/appsec/test_asm_standalone.py::Test_UserEventsStandalone_Automated: irrelevant (Proxies doesn't support login events (go sdk)) tests/appsec/test_asm_standalone.py::Test_UserEventsStandalone_SDK_V1: irrelevant (Proxies doesn't support login events (go sdk)) tests/appsec/test_asm_standalone.py::Test_UserEventsStandalone_SDK_V2: irrelevant (Proxies doesn't support login events (go sdk)) + tests/appsec/test_automated_login_events.py: irrelevant (proxies does not support login events) tests/appsec/test_automated_login_events.py::Test_V3_Login_Events_Blocking: irrelevant (Proxies doesn't support login events (go sdk)) tests/appsec/test_automated_user_and_session_tracking.py: irrelevant (Proxies doesn't support login events (go sdk)) tests/appsec/test_blocking_addresses.py: v2.4.0 @@ -47,6 +50,7 @@ manifest: tests/appsec/test_client_ip.py: v2.4.0 tests/appsec/test_conf.py::Test_ConfigurationVariables: v2.4.0 tests/appsec/test_conf.py::Test_ConfigurationVariables_New_Obfuscation: v2.4.0 + tests/appsec/test_event_tracking.py: irrelevant (proxies does not support login events) tests/appsec/test_extended_data_collection.py: v2.4.0 tests/appsec/test_extended_data_collection.py::Test_ExtendedDataCollectionCapability: missing_feature tests/appsec/test_extended_data_collection.py::Test_ExtendedRequestBodyCollection: missing_feature @@ -57,9 +61,14 @@ manifest: tests/appsec/test_fingerprinting.py::Test_Fingerprinting_Header_And_Network_Preprocessor::test_fingerprinting_header_blocking: missing_feature (proxies removes the 'connection' header, thus making fails the header fingerprinting rule) tests/appsec/test_fingerprinting.py::Test_Fingerprinting_Session_Preprocessor::test_session_non_blocking: irrelevant (Proxies doesn't support session fingerprinting) tests/appsec/test_ip_blocking_full_denylist.py: v2.4.0 + tests/appsec/test_logs.py::Test_Standardization: missing_feature + tests/appsec/test_logs.py::Test_StandardizationBlockMode: missing_feature + tests/appsec/test_only_python.py::Test_ImportError: irrelevant (specific tests for python tracer) tests/appsec/test_remote_config_rule_changes.py: v2.4.0 tests/appsec/test_reports.py: v2.4.0 tests/appsec/test_request_blocking.py: v2.4.0 + tests/appsec/test_shell_execution.py: irrelevant + tests/appsec/test_span_tags_headers.py::Test_Headers_Event_Blocking::test_content_type_event_blocking: missing_feature tests/appsec/test_trace_tagging.py::Test_TraceTaggingRules: v2.4.0 tests/appsec/test_trace_tagging.py::Test_TraceTaggingRules::test_rule_with_attributes_no_keep_event: irrelevant (Proxies run with appsec standalone by default) tests/appsec/test_trace_tagging.py::Test_TraceTaggingRules::test_rule_with_attributes_no_keep_no_event: irrelevant (Proxies run with appsec standalone by default) @@ -68,13 +77,27 @@ manifest: tests/appsec/test_traces.py::Test_CollectRespondHeaders::test_header_collection: missing_feature (The endpoint /headers is not implemented in the weblog) tests/appsec/test_user_blocking_full_denylist.py::Test_UserBlocking_FullDenylist: missing_feature (no endpoint to test user blocking - auto instrum irrelevant) tests/appsec/test_versions.py::Test_Events: v2.4.0 + tests/appsec/waf/test_addresses.py::Test_BodyUrlEncoded::test_body_value: missing_feature (no urlencoded body parsing implemented in proxies) + tests/appsec/waf/test_addresses.py::Test_BodyXml::test_xml_attr_value: missing_feature (no xml body parsing implemented in proxies) + tests/appsec/waf/test_addresses.py::Test_BodyXml::test_xml_content: missing_feature (no xml body parsing implemented in proxies) + tests/appsec/waf/test_addresses.py::Test_FullGrpc::test_main: irrelevant (proxies does not support grpc) + tests/appsec/waf/test_addresses.py::Test_PathParams::test_security_scanner: missing_feature + tests/appsec/waf/test_addresses.py::Test_ResponseStatus::test_basic: missing_feature + tests/appsec/waf/test_addresses.py::Test_gRPC::test_basic: missing_feature (proxies does not support grpc) tests/appsec/waf/test_blocking.py: v2.4.0 + tests/appsec/waf/test_blocking.py::Test_Blocking::test_accept_full_html: missing_feature tests/appsec/waf/test_blocking.py::Test_Blocking::test_accept_partial_html: missing_feature (Support for partial html not implemented) + tests/appsec/waf/test_blocking.py::Test_Blocking::test_html_template_v2: missing_feature tests/appsec/waf/test_blocking.py::Test_Blocking_strip_response_headers: missing_feature tests/appsec/waf/test_blocking_security_response_id.py: v2.5.0 + tests/appsec/waf/test_miscs.py::Test_404::test_404: missing_feature (weblog does not support 404 status code) + tests/integrations/test_dbm.py: irrelevant tests/remote_config/test_remote_configuration.py: v2.4.0 tests/remote_config/test_remote_configuration.py::Test_RemoteConfigurationUpdateSequenceASMDDNoCache: irrelevant (cache is implemented) + tests/serverless: irrelevant tests/test_config_consistency.py::Test_Config_UnifiedServiceTagging_CustomService: v2.4.0 + tests/test_identify.py: irrelevant (proxies does not support custom sdk) + tests/test_protobuf.py: irrelevant tests/test_resource_renaming.py: v2.4.0 tests/test_scrubbing.py: v2.4.0 tests/test_semantic_conventions.py: v2.4.0 diff --git a/tests/test_the_test/scenarios.json b/tests/test_the_test/scenarios.json index ffeba2bd67d..43886d8564c 100644 --- a/tests/test_the_test/scenarios.json +++ b/tests/test_the_test/scenarios.json @@ -3363,9 +3363,6 @@ "tests/docker_ssi/test_docker_ssi_servicenaming.py::TestDockerServiceNaming::test_service_name": [ "DOCKER_SSI_SERVICENAMING" ], - "tests/external_processing/test_apm.py::Test_GoProxies_Tracing::test_correct_span_structure": [ - "DEFAULT" - ], "tests/integrations/test_cassandra.py::Test_Cassandra::test_main": [ "INTEGRATIONS" ], diff --git a/utils/_context/_scenarios/endtoend.py b/utils/_context/_scenarios/endtoend.py index 5e5d2af06bb..fd3eba19003 100644 --- a/utils/_context/_scenarios/endtoend.py +++ b/utils/_context/_scenarios/endtoend.py @@ -90,9 +90,7 @@ def get_image_list(self, library: str, weblog: str) -> list[str]: def configure(self, config: pytest.Config): # noqa: ARG002 if not self.replay: docker_info = get_docker_client().info() - cgroup_version = docker_info.get("CgroupVersion") - if cgroup_version is not None: - self.components["docker.Cgroup"] = cgroup_version + self.components["docker.Cgroup"] = docker_info.get("CgroupVersion", None) self.warmups.append(self._create_network) self.warmups.append(self._start_containers) diff --git a/utils/_context/weblog_infrastructure/go_proxies.py b/utils/_context/weblog_infrastructure/go_proxies.py index a633052d0b8..574b488a158 100644 --- a/utils/_context/weblog_infrastructure/go_proxies.py +++ b/utils/_context/weblog_infrastructure/go_proxies.py @@ -102,10 +102,6 @@ def configure(self, config: pytest.Config, host_log_folder: str) -> None: # noq if config.option.force_dd_trace_debug: self._library_container.environment["DD_TRACE_DEBUG"] = "true" - if config.option.force_dd_iast_debug: - self._library_container.environment["_DD_IAST_DEBUG"] = "true" - self._library_container.environment["DD_IAST_DEBUG_ENABLED"] = "true" - def stop(self) -> None: self._dummy_server.stop() self._http_container.stop() diff --git a/utils/scripts/ci_orchestrators/workflow_data.py b/utils/scripts/ci_orchestrators/workflow_data.py index c232f1d04c8..501cdefde18 100644 --- a/utils/scripts/ci_orchestrators/workflow_data.py +++ b/utils/scripts/ci_orchestrators/workflow_data.py @@ -5,12 +5,12 @@ from pathlib import Path from utils._context.weblog_infrastructure import PROXY_WEBLOGS - +# TODO: remove and update the envoy/haproxy manifests to fully supports all scenarios PROXY_SUPPORTED_SCENARIOS = { - "DEFAULT", + # "DEFAULT", + # "TRACING_CONFIG_NONDEFAULT", "APPSEC_BLOCKING", "APPSEC_BLOCKING_FULL_DENYLIST", - "TRACING_CONFIG_NONDEFAULT", }