Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DNSPolicy health check tests #573

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 39 additions & 1 deletion testsuite/kuadrant/policy/dns.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
"""Module for DNSPolicy related classes"""

from dataclasses import dataclass
from typing import Optional
from typing import Optional, Literal

from testsuite.gateway import Referencable
from testsuite.kubernetes import KubernetesObject
from testsuite.kubernetes.client import KubernetesClient
from testsuite.kuadrant.policy import Policy
from testsuite.utils import asdict, check_condition
Expand Down Expand Up @@ -31,6 +32,33 @@ class LoadBalancing:
weight: Optional[int] = None


@dataclass
class AdditionalHeadersRef:
"""Object representing DNSPolicy additionalHeadersRef field"""

name: str


@dataclass
class HealthCheck: # pylint: disable=invalid-name
"""Object representing DNSPolicy health check specification"""

additionalHeadersRef: Optional[AdditionalHeadersRef] = None
path: Optional[str] = None
failureThreshold: Optional[int] = None
interval: Optional[str] = None
port: Optional[int] = None
protocol: Literal["HTTP", "HTTPS"] = "HTTP"


class DNSHealthCheckProbe(KubernetesObject):
"""DNSHealthCheckProbe object"""

def is_healthy(self) -> bool:
"""Returns True if DNSHealthCheckProbe endpoint is healthy"""
return self.refresh().model.status.healthy


class DNSPolicy(Policy):
"""DNSPolicy object"""

Expand Down Expand Up @@ -61,6 +89,16 @@ def create_instance(

return cls(model, context=cluster.context)

def set_health_check(self, health_check: HealthCheck):
"""Sets health check for DNSPolicy"""
self.model["spec"]["healthCheck"] = asdict(health_check)

def get_dns_health_probe(self) -> DNSHealthCheckProbe:
"""Returns DNSHealthCheckProbe object for the created DNSPolicy"""
with self.context:
dns_probe = self.get_owned("dnsrecords.kuadrant.io")[0].get_owned("DNSHealthCheckProbe")[0]
return DNSHealthCheckProbe(dns_probe.model, context=self.context)

def wait_for_full_enforced(self, timelimit=300):
"""Wait for a Policy to be fully Enforced with increased timelimit for DNSPolicy"""
super().wait_for_full_enforced(timelimit=timelimit)
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
"""Conftest for DNSPolicy health checks"""

import pytest

from testsuite.gateway import Hostname, TLSGatewayListener
from testsuite.gateway.gateway_api.gateway import KuadrantGateway


@pytest.fixture(scope="module")
def subdomain(blame):
"""Subdomain name that will be added to HTTPRoute"""
return blame("hostname")


@pytest.fixture(scope="module")
def hostname(gateway, exposer, subdomain) -> Hostname:
"""Exposed Hostname object"""
return exposer.expose_hostname(subdomain, gateway)


@pytest.fixture(scope="module")
def gateway(request, cluster, blame, base_domain, module_label, subdomain):
"""Returns ready gateway"""
gateway_name = blame("gw")
gw = KuadrantGateway.create_instance(
cluster,
gateway_name,
{"app": module_label},
)
gw.add_listener(TLSGatewayListener(hostname=f"{subdomain}.{base_domain}", gateway_name=gateway_name))
request.addfinalizer(gw.delete)
gw.commit()
gw.wait_for_ready()
return gw


@pytest.fixture(scope="module")
def dns_policy(dns_policy, health_check):
"""Add health check to DNSPolicy"""
dns_policy.set_health_check(health_check)
return dns_policy


@pytest.fixture(scope="module")
def dns_health_probe(dns_policy):
"""Return DNSHealthCheckProbe object for created DNSPolicy"""
return dns_policy.get_dns_health_probe()


@pytest.fixture(scope="module", autouse=True)
def commit(request, route, tls_policy, dns_policy): # pylint: disable=unused-argument
"""Commits dnspolicy"""
for component in [tls_policy, dns_policy]:
request.addfinalizer(component.delete)
component.commit()
component.wait_for_ready()
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""Tests for DNSPolicy health checks - healthy endpoint"""

import pytest

from testsuite.kuadrant.policy.dns import HealthCheck

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


@pytest.fixture(scope="module")
def health_check():
"""Returns healthy endpoint specification for DNSPolicy health check"""
return HealthCheck(
path="/get",
interval="5s",
protocol="HTTPS",
)


def test_healthy_endpoint(dns_health_probe, client, auth):
"""Test healthy endpoint check"""
assert dns_health_probe.is_healthy()

response = client.get("/get", auth=auth)
assert response.status_code == 200
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"""Tests for DNSPolicy health checks with HTTP only endpoint - healthy endpoint"""

import pytest

from testsuite.gateway import GatewayListener
from testsuite.gateway.gateway_api.gateway import KuadrantGateway
from testsuite.kuadrant.policy.dns import HealthCheck

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


@pytest.fixture(scope="module")
def health_check():
"""Returns healthy endpoint specification for DNSPolicy health check"""
return HealthCheck(
path="/get",
interval="5s",
protocol="HTTP",
)


@pytest.fixture(scope="module")
def gateway(request, cluster, blame, base_domain, module_label, subdomain):
"""Create gateway without TLS enabled"""
gw = KuadrantGateway.create_instance(cluster, blame("gw"), {"app": module_label})
gw.add_listener(GatewayListener(hostname=f"{subdomain}.{base_domain}"))
request.addfinalizer(gw.delete)
gw.commit()
gw.wait_for_ready()
return gw


@pytest.fixture(scope="module", autouse=True)
def commit(request, route, dns_policy): # pylint: disable=unused-argument
"""Commits dnspolicy only"""
request.addfinalizer(dns_policy.delete)
dns_policy.commit()
dns_policy.wait_for_ready()


def test_healthy_endpoint_http(dns_health_probe, client):
"""Test healthy endpoint check without TLS enabled"""
assert dns_health_probe.is_healthy()

response = client.get("/get")
assert response.status_code == 200
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"""Tests for DNSPolicy health checks - healthy endpoint"""

import pytest

from testsuite.kuadrant.policy import has_condition
from testsuite.kuadrant.policy.dns import HealthCheck, has_record_condition

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


@pytest.fixture(scope="module")
def health_check():
"""Returns healthy endpoint specification for DNSPolicy health check"""
return HealthCheck(
path="/get",
interval="5s",
protocol="HTTPS",
)


def test_remove_endpoint(backend, dns_policy, dns_health_probe, client, auth):
"""Scale backend replicas to 0 and back to 1, and check if DNSPolicy will remove the unhealthy endpoint"""
assert dns_health_probe.is_healthy()
response = client.get("/get", auth=auth)
assert response.status_code == 200

backend.deployment.self_selector().scale(0)
assert dns_policy.wait_until(has_condition("Enforced", "False"))
assert dns_policy.wait_until(
has_record_condition("Ready", "False", "HealthChecksFailed", "None of the healthchecks succeeded")
)

assert not dns_health_probe.is_healthy()
response = client.get("/get", auth=auth)
assert response.status_code == 503

backend.deployment.self_selector().scale(1)
dns_policy.wait_for_ready()

assert dns_health_probe.is_healthy()
response = client.get("/get", auth=auth)
assert response.status_code == 200
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""Tests for DNSPolicy health checks - unhealthy endpoint"""

import pytest

from testsuite.kuadrant.policy import has_condition
from testsuite.kuadrant.policy.dns import HealthCheck, has_record_condition

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


@pytest.fixture(scope="module")
def health_check():
"""Returns unhealthy endpoint specification for DNSPolicy health check"""
return HealthCheck(
path="/unknown-endpoint",
interval="5s",
protocol="HTTPS",
)


@pytest.fixture(scope="module", autouse=True)
def commit(request, route, tls_policy, dns_policy): # pylint: disable=unused-argument
"""Commits tlspolicy and dnspolicy without waiting for dnspolicy to be enforced"""
request.addfinalizer(tls_policy.delete)
tls_policy.commit()
tls_policy.wait_for_ready()

request.addfinalizer(dns_policy.delete)
dns_policy.commit()


def test_unhealthy_endpoint(dns_policy, dns_health_probe, client, auth):
"""Test unhealthy endpoint check"""
assert not dns_health_probe.is_healthy()
response = client.get("/get", auth=auth)
assert response.has_dns_error()

assert dns_policy.wait_until(has_condition("Enforced", "False"))
assert dns_policy.wait_until(
has_record_condition("Ready", "False", "HealthChecksFailed", "None of the healthchecks succeeded")
)
Loading