from __future__ import annotations from pathlib import Path import yaml ROOT = Path(__file__).resolve().parents[3] MANIFEST = ROOT / "k8s" / "observability" / "event-exporter.yaml" def test_event_exporter_watches_only_events_and_namespaces() -> None: documents = [ doc for doc in yaml.safe_load_all(MANIFEST.read_text(encoding="utf-8")) if doc ] role = next(doc for doc in documents if doc["kind"] == "ClusterRole") rules = role["rules"] assert rules == [ { "apiGroups": [""], "resources": ["events"], "verbs": ["get", "watch", "list"], }, { "apiGroups": [""], "resources": ["namespaces"], "verbs": ["get", "watch", "list"], }, ] def test_event_exporter_metadata_rules_never_write_or_delete() -> None: documents = [ doc for doc in yaml.safe_load_all(MANIFEST.read_text(encoding="utf-8")) if doc ] role = next(doc for doc in documents if doc["kind"] == "ClusterRole") forbidden = {"create", "update", "patch", "delete", "deletecollection"} assert not any(forbidden.intersection(rule["verbs"]) for rule in role["rules"]) def _event_exporter_config() -> dict: documents = [ doc for doc in yaml.safe_load_all(MANIFEST.read_text(encoding="utf-8")) if doc ] configmap = next(doc for doc in documents if doc["kind"] == "ConfigMap") return yaml.safe_load(configmap["data"]["config.yaml"]) def test_event_exporter_webhook_emits_a_real_otlp_json_envelope() -> None: config = _event_exporter_config() receivers = config["receivers"] assert [receiver["name"] for receiver in receivers] == ["signoz-otlp"] webhook = receivers[0]["webhook"] assert webhook["endpoint"].endswith("/v1/logs") assert webhook["headers"]["Content-Type"] == "application/json" resource_logs = webhook["layout"]["resourceLogs"] log_record = resource_logs[0]["scopeLogs"][0]["logRecords"][0] assert log_record["body"]["stringValue"] == "{{ .Message }}" assert log_record["severityText"] == "{{ .Type }}" attribute_keys = {item["key"] for item in log_record["attributes"]} assert { "k8s.event.reason", "k8s.event.type", "k8s.namespace.name", "k8s.object.kind", "k8s.object.name", } <= attribute_keys def test_event_exporter_has_one_route_and_drops_only_known_normal_noise() -> None: config = _event_exporter_config() routes = config["route"]["routes"] assert len(routes) == 1 assert routes[0]["match"] == [{"receiver": "signoz-otlp"}] assert {item["type"] for item in routes[0]["drop"]} == {"Normal"} assert {item["reason"] for item in routes[0]["drop"]} == { "Scheduled", "Pulling", "Pulled", "Created", "Started", } def test_event_exporter_keeps_late_events_without_object_lookups() -> None: config = _event_exporter_config() assert config["omitLookup"] is True assert config["maxEventAgeSeconds"] == 120