From 1b85380fa57a59a06b965c40e8e9a4e11dce11c1 Mon Sep 17 00:00:00 2001 From: Jakub Smolar Date: Thu, 22 Feb 2024 15:19:11 +0100 Subject: [PATCH 1/2] Add tests for Reconcile Sub Component Limitador CR --- testsuite/openshift/kuadrant.py | 32 ++++++++++++++ testsuite/tests/conftest.py | 32 +++++++++----- .../cr_configuration/__init__.py | 0 .../test_reconcile_limitador.py | 43 +++++++++++++++++++ .../reconciliation/httproute/__init__.py | 0 5 files changed, 97 insertions(+), 10 deletions(-) create mode 100644 testsuite/openshift/kuadrant.py create mode 100644 testsuite/tests/kuadrant/reconciliation/cr_configuration/__init__.py create mode 100644 testsuite/tests/kuadrant/reconciliation/cr_configuration/test_reconcile_limitador.py create mode 100644 testsuite/tests/kuadrant/reconciliation/httproute/__init__.py diff --git a/testsuite/openshift/kuadrant.py b/testsuite/openshift/kuadrant.py new file mode 100644 index 00000000..0836510d --- /dev/null +++ b/testsuite/openshift/kuadrant.py @@ -0,0 +1,32 @@ +"""Kuadrant CR object""" + +from openshift_client import selector + +from testsuite.openshift import OpenShiftObject, modify + + +class KuadrantCR(OpenShiftObject): + """Represents Kuadrant CR objects""" + + LIMITADOR = "limitador-limitador" + + @property + def limitador(self) -> dict: + """Returns spec.limitador from Kuadrant object""" + return self.model.spec.get("limitador", {}) + + @modify + def update_limitador(self, replicas: dict): + """Configure Limitador spec via Kuadrant object""" + self.model.spec.setdefault("limitador", {}) + self.model.spec["limitador"].update(replicas) + + def delete(self, ignore_not_found=True, cmd_args=None): + """Don't delete please.""" + raise TypeError("Don't delete Kuadrant CR") + + @property + def limitador_deployment(self): + """Returns Deployment object for this Authorino""" + with self.context: + return selector(f"deployment/{self.LIMITADOR}").object() diff --git a/testsuite/tests/conftest.py b/testsuite/tests/conftest.py index 0d9ca055..cf11f9e7 100644 --- a/testsuite/tests/conftest.py +++ b/testsuite/tests/conftest.py @@ -6,22 +6,24 @@ import pytest from dynaconf import ValidationError from keycloak import KeycloakAuthenticationError +from openshift_client import selector, OpenShiftPythonException +from testsuite.backend.httpbin import Httpbin from testsuite.capabilities import has_kuadrant from testsuite.certificates import CFSSLClient from testsuite.config import settings -from testsuite.httpx import KuadrantClient -from testsuite.mockserver import Mockserver -from testsuite.tracing import TracingClient from testsuite.gateway import Gateway, GatewayRoute, Hostname, Exposer -from testsuite.oidc import OIDCProvider -from testsuite.oidc.auth0 import Auth0Provider -from testsuite.backend.httpbin import Httpbin -from testsuite.oidc.rhsso import RHSSO from testsuite.gateway.envoy import Envoy from testsuite.gateway.envoy.route import EnvoyVirtualRoute from testsuite.gateway.gateway_api.gateway import KuadrantGateway from testsuite.gateway.gateway_api.route import HTTPRoute +from testsuite.httpx import KuadrantClient +from testsuite.mockserver import Mockserver +from testsuite.oidc import OIDCProvider +from testsuite.oidc.auth0 import Auth0Provider +from testsuite.oidc.rhsso import RHSSO +from testsuite.openshift.kuadrant import KuadrantCR +from testsuite.tracing import TracingClient from testsuite.utils import randomize, _whoami @@ -265,13 +267,23 @@ def module_label(label): @pytest.fixture(scope="session") -def kuadrant(request): +def kuadrant(request, testconfig): """Returns Kuadrant instance if exists, or None""" if request.config.getoption("--standalone"): return None - # TODO: Return actual Kuadrant object - return True + ocp = settings["service_protection"]["project"] + project = settings["service_protection"]["system_project"] + kuadrant_openshift = ocp.change_project(project) + + try: + with kuadrant_openshift.context: + kuadrant = selector("kuadrant").object(cls=KuadrantCR) + kuadrant.committed = True + except OpenShiftPythonException: + pytest.fail("Running Kuadrant tests, but Kuadrant resource was not found") + + return kuadrant @pytest.fixture(scope="session") diff --git a/testsuite/tests/kuadrant/reconciliation/cr_configuration/__init__.py b/testsuite/tests/kuadrant/reconciliation/cr_configuration/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/testsuite/tests/kuadrant/reconciliation/cr_configuration/test_reconcile_limitador.py b/testsuite/tests/kuadrant/reconciliation/cr_configuration/test_reconcile_limitador.py new file mode 100644 index 00000000..a662934a --- /dev/null +++ b/testsuite/tests/kuadrant/reconciliation/cr_configuration/test_reconcile_limitador.py @@ -0,0 +1,43 @@ +"""Tests for Kuadrant sub component - Limitador CR configuration via Kuadrant CR""" + +import pytest + +pytestmark = [pytest.mark.kuadrant_only] + + +REPLICAS_1 = {"replicas": 1} +REPLICAS_2 = {"replicas": 2} + + +@pytest.fixture(scope="module", autouse=True) +def kuadrant_clean_up(request, kuadrant): + """Return the number of replicas for Limitador back to 1""" + request.addfinalizer(lambda: kuadrant.update_limitador(REPLICAS_1)) + + +def test_spec_config(kuadrant): + """ + Test: + - assert that Limitador deployment replicas is equal to 1 + - change replicas field to 2 in Kuadrant CR + - assert that Kuadrant CR Limitador replicas is equal to 2 + - assert that Limitador deployment replicas is equal to 2 + """ + assert kuadrant.limitador["replicas"] == 1, "The number of Limitador replicas in KuadrantCR should be 1 " + assert kuadrant.limitador_deployment.model.spec.replicas == 1, "Limitador deployment should use 1 replica" + + kuadrant.update_limitador(REPLICAS_2) + + assert kuadrant.limitador["replicas"] == 2 + assert kuadrant.limitador_deployment.model.spec.replicas == 2 + + +def test_unsupported_spec_field(kuadrant): + """ + Tests that unsupported field is not reconciled + """ + kuadrant.update_limitador({"test": "test"}) + kuadrant.refresh() + + assert "test" not in kuadrant.limitador + assert "test" not in kuadrant.limitador_deployment.model.spec diff --git a/testsuite/tests/kuadrant/reconciliation/httproute/__init__.py b/testsuite/tests/kuadrant/reconciliation/httproute/__init__.py new file mode 100644 index 00000000..e69de29b From 1ac4b9b1767dcaf1bc73d8c928859b087c5f9537 Mon Sep 17 00:00:00 2001 From: Jakub Smolar Date: Fri, 26 Apr 2024 15:13:33 +0200 Subject: [PATCH 2/2] Remove authorization from cr configuration tests --- testsuite/openshift/kuadrant.py | 17 ++--- .../test_reconcile_limitador.py | 64 ++++++++++++------- .../reconciliation/httproute/__init__.py | 0 3 files changed, 49 insertions(+), 32 deletions(-) delete mode 100644 testsuite/tests/kuadrant/reconciliation/httproute/__init__.py diff --git a/testsuite/openshift/kuadrant.py b/testsuite/openshift/kuadrant.py index 0836510d..01e8ea4e 100644 --- a/testsuite/openshift/kuadrant.py +++ b/testsuite/openshift/kuadrant.py @@ -3,6 +3,7 @@ from openshift_client import selector from testsuite.openshift import OpenShiftObject, modify +from testsuite.openshift.deployment import Deployment class KuadrantCR(OpenShiftObject): @@ -13,20 +14,16 @@ class KuadrantCR(OpenShiftObject): @property def limitador(self) -> dict: """Returns spec.limitador from Kuadrant object""" - return self.model.spec.get("limitador", {}) + return self.model.spec.setdefault("limitador", {}) + @limitador.setter @modify - def update_limitador(self, replicas: dict): - """Configure Limitador spec via Kuadrant object""" - self.model.spec.setdefault("limitador", {}) - self.model.spec["limitador"].update(replicas) - - def delete(self, ignore_not_found=True, cmd_args=None): - """Don't delete please.""" - raise TypeError("Don't delete Kuadrant CR") + def limitador(self, value: dict): + """Sets the value of spec.limitador""" + self.model.spec["limitador"] = value @property def limitador_deployment(self): """Returns Deployment object for this Authorino""" with self.context: - return selector(f"deployment/{self.LIMITADOR}").object() + return selector(f"deployment/{self.LIMITADOR}").object(cls=Deployment) diff --git a/testsuite/tests/kuadrant/reconciliation/cr_configuration/test_reconcile_limitador.py b/testsuite/tests/kuadrant/reconciliation/cr_configuration/test_reconcile_limitador.py index a662934a..045261d6 100644 --- a/testsuite/tests/kuadrant/reconciliation/cr_configuration/test_reconcile_limitador.py +++ b/testsuite/tests/kuadrant/reconciliation/cr_configuration/test_reconcile_limitador.py @@ -5,39 +5,59 @@ pytestmark = [pytest.mark.kuadrant_only] -REPLICAS_1 = {"replicas": 1} -REPLICAS_2 = {"replicas": 2} +@pytest.fixture() +def commit(): + """Omitting authorization and rate limiting as it is not needed""" -@pytest.fixture(scope="module", autouse=True) +@pytest.fixture(autouse=True) def kuadrant_clean_up(request, kuadrant): - """Return the number of replicas for Limitador back to 1""" - request.addfinalizer(lambda: kuadrant.update_limitador(REPLICAS_1)) + """ + Return fields to default values. + This can be simplified once https://github.com/Kuadrant/kuadrant-operator/issues/617 is fixed. + """ + + def _finalize(): + kuadrant.limitador = {"replicas": 1, "resourceRequirements": {"requests": {"cpu": "250m", "memory": "32Mi"}}} + + request.addfinalizer(_finalize) -def test_spec_config(kuadrant): +@pytest.mark.parametrize( + "field, value", + [ + pytest.param("replicas", 2, id="replicas"), + pytest.param( + "resourceRequirements", {"requests": {"cpu": "300m", "memory": "40Mi"}}, id="resourceRequirements" + ), + ], +) +def test_fields_to_reconcile(kuadrant, field, value): """ Test: - - assert that Limitador deployment replicas is equal to 1 - - change replicas field to 2 in Kuadrant CR - - assert that Kuadrant CR Limitador replicas is equal to 2 - - assert that Limitador deployment replicas is equal to 2 + - change specific `field` to `value` in Kuadrant CR + - assert that `field` in Kuadrant CR Limitador is equal to `value` + - assert that `field` in Limitador deployment is equal to `value` """ - assert kuadrant.limitador["replicas"] == 1, "The number of Limitador replicas in KuadrantCR should be 1 " - assert kuadrant.limitador_deployment.model.spec.replicas == 1, "Limitador deployment should use 1 replica" + kuadrant.limitador = {field: value} - kuadrant.update_limitador(REPLICAS_2) + assert value == kuadrant.limitador[field] + assert str(value) in str(kuadrant.limitador_deployment.model.spec) - assert kuadrant.limitador["replicas"] == 2 - assert kuadrant.limitador_deployment.model.spec.replicas == 2 - -def test_unsupported_spec_field(kuadrant): +@pytest.mark.xfail +@pytest.mark.issue("https://github.com/Kuadrant/kuadrant-operator/issues/617") +def test_blank_fields_wont_reconcile(kuadrant): """ - Tests that unsupported field is not reconciled + Test: + - setup limitador with replicas and resourceRequirements != default + - change replicas to 3 + - assert replicas field is 3 for limitador deployment + - assert blank field resourceRequirements is returned to default for limitador deployment """ - kuadrant.update_limitador({"test": "test"}) - kuadrant.refresh() + kuadrant.limitador = {"replicas": 2, "resourceRequirements": {"requests": {"cpu": "300m", "memory": "40Mi"}}} + + kuadrant.limitador = {"replicas": 3} - assert "test" not in kuadrant.limitador - assert "test" not in kuadrant.limitador_deployment.model.spec + assert kuadrant.limitador_deployment.model.spec.replicas == 3 + assert "'cpu': '250m', 'memory': '32Mi'" in str(kuadrant.limitador_deployment.model.spec) diff --git a/testsuite/tests/kuadrant/reconciliation/httproute/__init__.py b/testsuite/tests/kuadrant/reconciliation/httproute/__init__.py deleted file mode 100644 index e69de29b..00000000