diff --git a/testsuite/gateway/__init__.py b/testsuite/gateway/__init__.py index f1098a6f..5c02ff8b 100644 --- a/testsuite/gateway/__init__.py +++ b/testsuite/gateway/__init__.py @@ -97,9 +97,8 @@ class QueryParamsMatch: @dataclass class RouteMatch: """ - Abstract Dataclass for HTTPRouteMatch. - API specification consists of two layers: HTTPRouteMatch which can contain 4 matchers (see offsprings). - We merged this to a single Matcher representation for simplicity, which is why we need custom `asdict` methods. + HTTPRouteMatch defines the predicate used to match requests to a given action. + Multiple match types are ANDed together, i.e. the match will evaluate to true only if all conditions are satisfied. https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteMatch """ @@ -163,6 +162,14 @@ def remove_hostname(self, hostname: str): def remove_all_hostnames(self): """Remove all hostnames from the Route""" + @abstractmethod + def add_rule(self, backend: "Httpbin", *route_matches: RouteMatch): + """Adds rule to the Route""" + + @abstractmethod + def remove_all_rules(self): + """Remove all rules from the Route""" + @abstractmethod def add_backend(self, backend: "Httpbin", prefix): """Adds another backend to the Route, with specific prefix""" diff --git a/testsuite/gateway/gateway_api/route.py b/testsuite/gateway/gateway_api/route.py index bf04fc76..83206d6c 100644 --- a/testsuite/gateway/gateway_api/route.py +++ b/testsuite/gateway/gateway_api/route.py @@ -5,9 +5,10 @@ from httpx import Client from testsuite.httpx import KuadrantClient -from testsuite.gateway import Gateway, GatewayRoute +from testsuite.gateway import Gateway, GatewayRoute, PathMatch, MatchType, RouteMatch from testsuite.openshift.client import OpenShiftClient from testsuite.openshift import OpenShiftObject, modify +from testsuite.utils import asdict if typing.TYPE_CHECKING: from testsuite.openshift.httpbin import Httpbin @@ -73,17 +74,20 @@ def remove_all_hostnames(self): self.model.spec.hostnames = [] @modify - def set_match(self, backend: "Httpbin", path_prefix: str = None): - """Limits HTTPRoute to a certain path""" - match = {} - if path_prefix: - match["path"] = {"value": path_prefix, "type": "PathPrefix"} - for rule in self.model.spec.rules: - for ref in rule.backendRefs: - if backend.reference["name"] == ref["name"]: - rule["matches"] = [match] - return - raise NameError("This backend is not assigned to this Route") + def add_rule(self, backend: "Httpbin", *route_matches: RouteMatch): + """Adds rule to the Route""" + rules = {"backendRefs": [backend.reference]} + matches = list(route_matches) + if len(matches) == 0: + matches.append(RouteMatch(path=PathMatch(type=MatchType.PATH_PREFIX, value="/"))) + + rules["matches"] = [asdict(match) for match in matches] + self.model.spec.rules.append(rules) + + @modify + def remove_all_rules(self): + """Remove all rules from the Route""" + self.model.spec.rules = [] @modify def add_backend(self, backend: "Httpbin", prefix="/"): diff --git a/testsuite/policy/rate_limit_policy.py b/testsuite/policy/rate_limit_policy.py index 1e547bb2..26110c78 100644 --- a/testsuite/policy/rate_limit_policy.py +++ b/testsuite/policy/rate_limit_policy.py @@ -25,7 +25,7 @@ class Limit: class RouteSelector: """ RouteSelector is an object composed of a set of HTTPRouteMatch objects (from Gateway API - - HTRTPPathMatch, HTTPHeaderMatch, HTTPQueryParamMatch, HTTPMethodMatch), + HTTPPathMatch, HTTPHeaderMatch, HTTPQueryParamMatch, HTTPMethodMatch), and an additional hostnames field. https://docs.kuadrant.io/kuadrant-operator/doc/reference/route-selectors/#routeselector """ diff --git a/testsuite/tests/kuadrant/reconciliation/test_httproute_matches.py b/testsuite/tests/kuadrant/reconciliation/test_httproute_matches.py index 601a2833..85229b12 100644 --- a/testsuite/tests/kuadrant/reconciliation/test_httproute_matches.py +++ b/testsuite/tests/kuadrant/reconciliation/test_httproute_matches.py @@ -1,4 +1,5 @@ """Tests that HTTPRoute spec.routes.matches changes are reconciled when changed.""" +from testsuite.gateway import RouteMatch, PathMatch def test_matches(client, backend, route, resilient_request): @@ -12,7 +13,8 @@ def test_matches(client, backend, route, resilient_request): response = client.get("/get") assert response.status_code == 200 - route.set_match(backend, path_prefix="/anything") + route.remove_all_rules() + route.add_rule(backend, RouteMatch(path=PathMatch(value="/anything"))) response = resilient_request("/get", expected_status=404) assert response.status_code == 404, "Matches were not reconciled"