Skip to content

Commit

Permalink
Add gateway listener editing support
Browse files Browse the repository at this point in the history
Signed-off-by: Alex Zgabur <[email protected]>
  • Loading branch information
azgabur committed Sep 17, 2024
1 parent aa8594d commit 44db6b7
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 115 deletions.
40 changes: 40 additions & 0 deletions testsuite/gateway/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,46 @@ def remove_all_backend(self):
"""Sets match for a specific backend"""


@dataclass
class GatewayListener:
"""
Dataclass of Gateway listener object
If used in Gateway creation `.create_instance()` function the `name` parameter is mandatory.
If used in `.add_listener()` function, you can omit the `name` parameter and a unique parameter will be generated.
"""

hostname: str
name: Optional[str] = None
port: int = 80
protocol: str = "HTTP"
allowedRoutes = {"namespaces": {"from": "All"}}


@dataclass(kw_only=True)
class GatewayListenerTls(GatewayListener):
"""
Dataclass for Gateway listener supporting TLS.
If used in Gateway creation `.create_instance()` function the `name` parameter is mandatory.
If used in `.add_listener()` function, you can omit the `name` parameter and a unique parameter will be generated.
"""

gateway_name: str
mode: str = "Terminate"
port: int = 443
protocol: str = "HTTPS"

def asdict(self):
"""Custom asdict to easily add tls certificateRefs"""
return {
"name": self.name,
"hostname": self.hostname,
"port": self.port,
"protocol": self.protocol,
"allowedRoutes": self.allowedRoutes,
"tls": {"mode": self.mode, "certificateRefs": [{"name": f"{self.gateway_name}-tls", "kind": "Secret"}]},
}


class Hostname(ABC):
"""
Abstraction layer on top of externally exposed hostname
Expand Down
54 changes: 23 additions & 31 deletions testsuite/gateway/gateway_api/gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,55 +5,47 @@
import openshift_client as oc

from testsuite.certificates import Certificate
from testsuite.gateway import Gateway
from testsuite.gateway import Gateway, GatewayListener
from testsuite.kubernetes.client import KubernetesClient
from testsuite.kubernetes import KubernetesObject
from testsuite.kubernetes import KubernetesObject, modify
from testsuite.kuadrant.policy import Policy
from testsuite.utils import check_condition
from testsuite.utils import check_condition, asdict


class KuadrantGateway(KubernetesObject, Gateway):
"""Gateway object for Kuadrant"""

# Used to make unique listener names
listener_counter = 1

@classmethod
def create_instance(cls, cluster: KubernetesClient, name, hostname, labels, tls=False):
def create_instance(cls, cluster: KubernetesClient, name, listener: GatewayListener, labels):
"""Creates new instance of Gateway"""

model: dict[Any, Any] = {
"apiVersion": "gateway.networking.k8s.io/v1beta1",
"kind": "Gateway",
"metadata": {"name": name, "labels": labels},
"spec": {
"gatewayClassName": "istio",
"listeners": [
{
"name": "api",
"port": 80,
"protocol": "HTTP",
"hostname": hostname,
"allowedRoutes": {"namespaces": {"from": "All"}},
}
],
},
"spec": {"gatewayClassName": "istio", "listeners": [asdict(listener)]},
}

if tls:
model["spec"]["listeners"] = [
{
"name": "api",
"port": 443,
"protocol": "HTTPS",
"hostname": hostname,
"allowedRoutes": {"namespaces": {"from": "All"}},
"tls": {
"mode": "Terminate",
"certificateRefs": [{"name": f"{name}-tls", "kind": "Secret"}],
},
}
]

return cls(model, context=cluster.context)

@modify
def add_listener(self, listener: GatewayListener):
"""Adds a listener to Gateway. If the argument doesn't contain name, generate new sequential one."""
if listener.name is None:
listener.name = f"api{self.listener_counter}"
self.listener_counter += 1
self.model.spec.listeners.append(asdict(listener))

@modify
def remove_listener(self, hostname: GatewayListener | str):
"""Removes a listener based on hostname"""
if isinstance(hostname, GatewayListener):
hostname = hostname.hostname
self.model.spec.listeners = list(filter(lambda i: i["hostname"] != hostname, self.model.spec.listeners))

@property
def service_name(self) -> str:
return f"{self.name()}-istio"
Expand Down
11 changes: 9 additions & 2 deletions testsuite/tests/multicluster/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from testsuite.backend.httpbin import Httpbin
from testsuite.certificates import Certificate
from testsuite.gateway import Exposer, CustomReference, Hostname
from testsuite.gateway import GatewayListenerTls
from testsuite.gateway.gateway_api.gateway import KuadrantGateway
from testsuite.gateway.gateway_api.hostname import DNSPolicyExposer
from testsuite.gateway.gateway_api.route import HTTPRoute
Expand Down Expand Up @@ -106,7 +107,10 @@ def routes(request, gateway, gateway2, blame, hostname, backends, module_label)
@pytest.fixture(scope="module")
def gateway(request, cluster, blame, label, wildcard_domain):
"""Deploys Gateway to first Kubernetes cluster"""
gw = KuadrantGateway.create_instance(cluster, blame("gw"), wildcard_domain, {"app": label}, tls=True)
name = blame("gw")
gw = KuadrantGateway.create_instance(
cluster, name, GatewayListenerTls(hostname=wildcard_domain, gateway_name=name, name="api"), {"app": label}
)
request.addfinalizer(gw.delete)
gw.commit()
gw.wait_for_ready()
Expand All @@ -116,7 +120,10 @@ def gateway(request, cluster, blame, label, wildcard_domain):
@pytest.fixture(scope="module")
def gateway2(request, cluster2, blame, label, wildcard_domain):
"""Deploys Gateway to second Kubernetes cluster"""
gw = KuadrantGateway.create_instance(cluster2, blame("gw"), wildcard_domain, {"app": label}, tls=True)
name = blame("gw")
gw = KuadrantGateway.create_instance(
cluster2, name, GatewayListenerTls(hostname=wildcard_domain, gateway_name=name, name="api"), {"app": label}
)
request.addfinalizer(gw.delete)
gw.commit()
gw.wait_for_ready()
Expand Down
4 changes: 2 additions & 2 deletions testsuite/tests/singlecluster/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from openshift_client import selector

from testsuite.backend.httpbin import Httpbin
from testsuite.gateway import GatewayRoute, Gateway, Hostname
from testsuite.gateway import GatewayRoute, Gateway, Hostname, GatewayListener
from testsuite.gateway.envoy import Envoy
from testsuite.gateway.envoy.route import EnvoyVirtualRoute
from testsuite.gateway.gateway_api.gateway import KuadrantGateway
Expand Down Expand Up @@ -130,7 +130,7 @@ def backend(request, cluster, blame, label, testconfig):
def gateway(request, kuadrant, cluster, blame, label, testconfig, wildcard_domain) -> Gateway:
"""Deploys Gateway that wires up the Backend behind the reverse-proxy and Authorino instance"""
if kuadrant:
gw = KuadrantGateway.create_instance(cluster, blame("gw"), wildcard_domain, {"app": label})
gw = KuadrantGateway.create_instance(cluster, blame("gw"), GatewayListener(wildcard_domain), {"app": label})
else:
authorino = request.getfixturevalue("authorino")
gw = Envoy(
Expand Down
10 changes: 8 additions & 2 deletions testsuite/tests/singlecluster/gateway/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import pytest

from testsuite.gateway import Exposer
from testsuite.gateway import Exposer, GatewayListenerTls
from testsuite.gateway.gateway_api.gateway import KuadrantGateway
from testsuite.gateway.gateway_api.hostname import DNSPolicyExposer
from testsuite.httpx.auth import HttpxOidcClientAuth
Expand All @@ -13,7 +13,13 @@
@pytest.fixture(scope="module")
def gateway(request, cluster, blame, wildcard_domain, module_label):
"""Returns ready gateway"""
gw = KuadrantGateway.create_instance(cluster, blame("gw"), wildcard_domain, {"app": module_label}, tls=True)
gateway_name = blame("gw")
gw = KuadrantGateway.create_instance(
cluster,
gateway_name,
GatewayListenerTls(hostname=wildcard_domain, gateway_name=gateway_name, name="api"),
{"app": module_label},
)
request.addfinalizer(gw.delete)
gw.commit()
gw.wait_for_ready()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
from testsuite.kubernetes.secret import Secret
from testsuite.kuadrant.policy import has_condition
from testsuite.kuadrant.policy.dns import has_record_condition
from testsuite.gateway.gateway_api.gateway import KuadrantGateway
from testsuite.gateway.gateway_api.gateway import KuadrantGateway, GatewayListener

pytestmark = [pytest.mark.kuadrant_only, pytest.mark.dnspolicy]


@pytest.fixture(scope="module")
def gateway(request, cluster, blame, wildcard_domain, module_label):
"""Create gateway without TLS enabled"""
gw = KuadrantGateway.create_instance(cluster, blame("gw"), wildcard_domain, {"app": module_label}, tls=False)
gw = KuadrantGateway.create_instance(cluster, blame("gw"), GatewayListener(wildcard_domain, name="api"), {"app": module_label})
request.addfinalizer(gw.delete)
gw.commit()
gw.wait_for_ready()
Expand Down

This file was deleted.

0 comments on commit 44db6b7

Please sign in to comment.