From 16d3c6eccbb31d58c199574868cee9a10a5dd0c9 Mon Sep 17 00:00:00 2001 From: Jakub Smolar Date: Mon, 24 Jun 2024 18:02:52 +0200 Subject: [PATCH] Add Kuadrant tracing tests --- testsuite/tests/kuadrant/conftest.py | 39 ++++++++++++++++--- .../tests/kuadrant/observability/__init__.py | 0 .../tests/kuadrant/observability/conftest.py | 33 ++++++++++++++++ .../kuadrant/observability/test_tracing.py | 27 +++++++++++++ testsuite/tracing.py | 10 ++++- 5 files changed, 103 insertions(+), 6 deletions(-) create mode 100644 testsuite/tests/kuadrant/observability/__init__.py create mode 100644 testsuite/tests/kuadrant/observability/conftest.py create mode 100644 testsuite/tests/kuadrant/observability/test_tracing.py diff --git a/testsuite/tests/kuadrant/conftest.py b/testsuite/tests/kuadrant/conftest.py index d08a869f..781f982f 100644 --- a/testsuite/tests/kuadrant/conftest.py +++ b/testsuite/tests/kuadrant/conftest.py @@ -2,18 +2,47 @@ all methods are placeholders for now since we do not work with Kuadrant""" import pytest +from openshift_client import selector, OpenShiftPythonException +from testsuite.config import settings +from testsuite.openshift.authorino import AuthorinoCR +from testsuite.openshift.limitador import LimitadorCR from testsuite.policy.authorization.auth_policy import AuthPolicy from testsuite.policy.rate_limit_policy import RateLimitPolicy @pytest.fixture(scope="session") -def authorino(kuadrant): +def system_openshift(): + """Returns client for Kuadrant""" + ocp = settings["service_protection"]["project"] + project = settings["service_protection"]["system_project"] + return ocp.change_project(project) + + +@pytest.fixture(scope="session") +def authorino(system_openshift) -> AuthorinoCR: """Authorino instance when configured through Kuadrant""" - if kuadrant: - # No available modification - return True - return None + try: + with system_openshift.context: + authorino = selector("authorino").object(cls=AuthorinoCR) + authorino.committed = True + except OpenShiftPythonException: + pytest.fail("Running Kuadrant tests, but Authorino resource was not found") + + return authorino + + +@pytest.fixture(scope="session") +def limitador(system_openshift) -> LimitadorCR: + """Returns Limitador CR""" + try: + with system_openshift.context: + limitador = selector("limitador").object(cls=LimitadorCR) + limitador.committed = True + except OpenShiftPythonException: + pytest.fail("Running Kuadrant tests, but Limitador resource was not found") + + return limitador @pytest.fixture(scope="module") diff --git a/testsuite/tests/kuadrant/observability/__init__.py b/testsuite/tests/kuadrant/observability/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/testsuite/tests/kuadrant/observability/conftest.py b/testsuite/tests/kuadrant/observability/conftest.py new file mode 100644 index 00000000..f94db236 --- /dev/null +++ b/testsuite/tests/kuadrant/observability/conftest.py @@ -0,0 +1,33 @@ +"""Conftest for Kuadrant observability tests""" + +import pytest + +from testsuite.httpx.auth import HttpxOidcClientAuth +from testsuite.openshift.authorino import TracingOptions +from testsuite.policy.rate_limit_policy import Limit + + +@pytest.fixture(scope="module") +def auth(oidc_provider): + """Returns RHSSO authentication object for HTTPX""" + return HttpxOidcClientAuth(oidc_provider.get_token, "authorization") + + +@pytest.fixture(scope="module") +def rate_limit(rate_limit): + """Add limit to the policy""" + rate_limit.add_limit("basic", [Limit(5, 60)]) + return rate_limit + + +@pytest.fixture(scope="module", autouse=True) +def enable_tracing(authorino, limitador, tracing): + """Enable tracing for Authorino and Limitador""" + authorino["tracing"] = TracingOptions(tracing.collector_url, insecure=True) + authorino.safe_apply() + authorino.wait_for_ready() + + limitador.refresh() # limitador is not up-to-date, as limit from RLP is added to LimitadorCR + limitador["tracing"] = TracingOptions(tracing.collector_url) + limitador.safe_apply() + limitador.wait_for_ready() diff --git a/testsuite/tests/kuadrant/observability/test_tracing.py b/testsuite/tests/kuadrant/observability/test_tracing.py new file mode 100644 index 00000000..17b4618d --- /dev/null +++ b/testsuite/tests/kuadrant/observability/test_tracing.py @@ -0,0 +1,27 @@ +"""Tests for Kuadrant tracing""" + +import os +from time import sleep + +import pytest + +pytestmark = [pytest.mark.kuadrant_only] + + +def test_tracing(client, auth, tracing): + """ + Tests that traces are collected from Authorino and Limitador + + Trace IDs do not propagate to wasm modules in Istio/Envoy, affecting trace continuity in Limitador: + https://github.com/envoyproxy/envoy/issues/22028 + That is the reason why we set parent trace ID in request. + """ + trace_id = os.urandom(16).hex() + client.get("/get", auth=auth, headers={"Traceparent": f"00-{trace_id}-{os.urandom(8).hex()}-01"}) + sleep(5) # Wait for tracing backend to collect all traces + + trace = tracing.get_trace(trace_id) + assert len(trace) == 1, f"No trace was found in tracing backend with trace_id: {trace_id}" + service_names = [process["serviceName"] for process in trace[0]["processes"].values()] + assert "authorino" in service_names + assert "limitador" in service_names diff --git a/testsuite/tracing.py b/testsuite/tracing.py index c96b8b36..af3a8fa6 100644 --- a/testsuite/tracing.py +++ b/testsuite/tracing.py @@ -15,7 +15,7 @@ def __init__(self, jaeger_backend: bool, collector_url: str, query_url: str, cli self.client = client or KuadrantClient(verify=False) self.query = ApyProxy(query_url, session=self.client) - @backoff.on_predicate(backoff.fibo, lambda x: x == [], max_tries=7, jitter=None) + @backoff.on_predicate(backoff.fibo, lambda x: x == [], max_tries=5, jitter=None) def _get_trace( self, request_id: str, @@ -40,3 +40,11 @@ def find_trace(self, request_id: str, service: str) -> list: def find_tagged_trace(self, request_id: str, service: str, tag: dict) -> list: """Find trace in tracing client by tags service name, authorino request id and tag key-value pair""" return self._get_trace(request_id, service, tag) + + @backoff.on_predicate(backoff.fibo, lambda x: x == [], max_tries=7, jitter=None) + def get_trace(self, trace_id): + """Finds trace by ID""" + if self.jaeger_backend: + return self.query.api.traces._(trace_id).get().json()["data"] + + return self.query.api.traces._(trace_id).get().json()["traces"]