|
9 | 9 | from lightkube import AsyncClient |
10 | 10 | from lightkube import operators as op |
11 | 11 | from lightkube.resources.core_v1 import Pod, Service |
| 12 | +from prometheus_client.parser import text_string_to_metric_families |
12 | 13 |
|
13 | 14 | from .fixtures.data import ESSData |
14 | | -from .lib.helpers import wait_for_endpoint_ready |
| 15 | +from .lib.helpers import run_pod_with_args, wait_for_endpoint_ready |
15 | 16 | from .lib.utils import read_service_monitor_kind |
16 | 17 |
|
17 | 18 |
|
@@ -162,3 +163,58 @@ async def test_pods_monitored( |
162 | 163 | assert all_monitorable_pods == monitored_pods, ( |
163 | 164 | f"Some pods are not monitored : {', '.join(list(set(all_monitorable_pods) ^ set(monitored_pods)))}" |
164 | 165 | ) |
| 166 | + |
| 167 | + |
| 168 | + |
| 169 | +@pytest.mark.skipif( |
| 170 | + os.environ.get("SKIP_SERVICE_MONITORS_CRDS", "false") == "true", reason="ServiceMonitors not deployed" |
| 171 | +) |
| 172 | +@pytest.mark.asyncio_cooperative |
| 173 | +@pytest.mark.usefixtures("matrix_stack") |
| 174 | +async def test_service_monitors_point_to_metrics( |
| 175 | + kube_client: AsyncClient, |
| 176 | + generated_data: ESSData, |
| 177 | +): |
| 178 | + async for service_monitor in kube_client.list( |
| 179 | + await read_service_monitor_kind(kube_client), |
| 180 | + namespace=generated_data.ess_namespace, |
| 181 | + labels={"app.kubernetes.io/part-of": op.in_(["matrix-stack"])}, |
| 182 | + ): |
| 183 | + async for service in kube_client.list( |
| 184 | + Service, namespace=generated_data.ess_namespace, labels=service_monitor["spec"]["selector"]["matchLabels"] |
| 185 | + ): |
| 186 | + assert service.metadata, f"Encountered a service without metadata : {service}" |
| 187 | + assert service.spec, f"Encountered a service without spec : {service}" |
| 188 | + assert service.spec.ports, f"Ecountered a service without port : {service}" |
| 189 | + assert service.spec.selector, f"Ecountered a service without selectors : {service}" |
| 190 | + |
| 191 | + for endpoint in service_monitor["spec"]["endpoints"]: |
| 192 | + service_port_names = [port.name for port in service.spec.ports if port.name] |
| 193 | + if endpoint["port"] in service_port_names: |
| 194 | + break |
| 195 | + # This Service does not have the named port. Potentially there's another Service that covers it |
| 196 | + else: |
| 197 | + continue |
| 198 | + assert await has_actual_metrics_on_endpoint( |
| 199 | + kube_client, generated_data, service, service_monitor["spec"]["endpoints"] |
| 200 | + ) |
| 201 | + |
| 202 | + |
| 203 | +async def has_actual_metrics_on_endpoint( |
| 204 | + kube_client: AsyncClient, generated_data: ESSData, service: Service, endpoints |
| 205 | +): |
| 206 | + found_metrics = False |
| 207 | + for endpoint in endpoints: |
| 208 | + for port_spec in service.spec.ports: |
| 209 | + if port_spec.name == endpoint["port"]: |
| 210 | + metrics_data = await run_pod_with_args( |
| 211 | + kube_client, |
| 212 | + generated_data.ess_namespace, |
| 213 | + "curlimages/curl:latest", |
| 214 | + "curl", |
| 215 | + ["-s", f"http://{service.metadata.name}.{generated_data.ess_namespace}.svc.cluster.local:{port_spec.port}/metrics"], |
| 216 | + ) |
| 217 | + for metric_family in text_string_to_metric_families(metrics_data): |
| 218 | + assert metric_family.name, "Metric family has no name" |
| 219 | + found_metrics = True |
| 220 | + return found_metrics |
0 commit comments