mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-08 11:46:35 +00:00
The entity name keys a role's instance directory, its compose project and its container name, and was derived only by stripping the longest matching category prefix. Two roles under different categories whose names share a suffix therefore collapse onto one entity and overwrite each other's rendered stack, which no provides: can repair. A literal entity_name in vars/main.yml now wins over the derivation. web-app-seaweedfs-console takes its shorter name back and declares the entity seaweedfs-console, which frees the seaweedfs key in its own services map for the engine consumer and removes the provides:, covers: and alias entries that stood in for it. A new lint pairs the declaration with the primary key it has to match, because a drift between them would drop the role from the provider set in silence. Compared across all 288 roles, exactly one entity changes, and it restores what main already keeps on disk, so no instance directory moves. The function and the filter lose their get_ prefix. Two lints read that prefix as the discriminator between the variable and the filter that fills it; both discriminate on the pipe now. Ansible's templar resolves a filter and a same-named variable independently, verified against ansible-core 2.20.2. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
120 lines
4.0 KiB
Python
120 lines
4.0 KiB
Python
"""Tests for the native_metrics_target lookup.
|
|
|
|
The lookup delegates host resolution to scrape_target, so these run the real
|
|
scrape_target rather than a stub: the regression being guarded is that swarm
|
|
must not receive a compose container name, and only the delegation proves it.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import unittest
|
|
from typing import Any
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
from ansible.errors import AnsibleError
|
|
|
|
from plugins.lookup.native_metrics_target import LookupModule
|
|
from plugins.lookup.scrape_target import LookupModule as ScrapeTargetLookup
|
|
|
|
ENTITIES = {"web-app-matrix": "matrix", "web-app-gitea": "gitea"}
|
|
|
|
|
|
class _Templar:
|
|
def __init__(self, vars_=None):
|
|
self.available_variables = vars_ or {}
|
|
|
|
def template(self, value, **_):
|
|
return value
|
|
|
|
|
|
def _apps(native_metrics: dict[str, Any]) -> dict[str, Any]:
|
|
return {
|
|
"web-app-matrix": {
|
|
"services": {
|
|
"prometheus": {"native_metrics": native_metrics},
|
|
"synapse": {
|
|
"name": "matrix-synapse",
|
|
"ports": {"internal": {"http": 8008}},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
|
|
def _run(terms, *, mode, apps):
|
|
variables = {"DEPLOYMENT_MODE": mode}
|
|
lookup = LookupModule()
|
|
lookup._templar = _Templar(variables)
|
|
lookup._loader = MagicMock()
|
|
|
|
def _dispatch(name, **_kwargs):
|
|
if name == "applications":
|
|
return MagicMock(run=lambda *_a, **_k: [apps])
|
|
scrape = ScrapeTargetLookup()
|
|
scrape._templar = _Templar(variables)
|
|
scrape._loader = MagicMock()
|
|
return scrape
|
|
|
|
with (
|
|
patch(
|
|
"plugins.lookup.native_metrics_target.lookup_loader"
|
|
) as native_loader_mock,
|
|
patch("plugins.lookup.scrape_target.lookup_loader") as scrape_loader_mock,
|
|
patch(
|
|
"plugins.lookup.native_metrics_target.entity_name",
|
|
side_effect=lambda app_id: ENTITIES.get(app_id, ""),
|
|
),
|
|
patch(
|
|
"plugins.lookup.scrape_target.entity_name",
|
|
side_effect=lambda app_id: ENTITIES.get(app_id, ""),
|
|
),
|
|
):
|
|
native_loader_mock.get.side_effect = _dispatch
|
|
scrape_loader_mock.get.return_value = MagicMock(run=lambda *_a, **_k: [apps])
|
|
return lookup.run(terms, variables=variables)
|
|
|
|
|
|
class TestNativeMetricsTargetLookup(unittest.TestCase):
|
|
def test_swarm_uses_per_task_dns_not_the_container_name(self):
|
|
apps = _apps({"port": 9000, "service_key": "synapse"})
|
|
result = _run(["web-app-matrix"], mode="swarm", apps=apps)
|
|
self.assertEqual(result, ["tasks.matrix_synapse:9000"])
|
|
|
|
def test_compose_uses_the_container_name(self):
|
|
apps = _apps({"port": 9000, "service_key": "synapse"})
|
|
result = _run(["web-app-matrix"], mode="compose", apps=apps)
|
|
self.assertEqual(result, ["matrix-synapse:9000"])
|
|
|
|
def test_service_key_defaults_to_the_entity_name(self):
|
|
apps = {
|
|
"web-app-gitea": {
|
|
"services": {
|
|
"prometheus": {"native_metrics": {"port": 3000}},
|
|
"gitea": {
|
|
"name": "gitea",
|
|
"ports": {"internal": {"http": 3000}},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
result = _run(["web-app-gitea"], mode="swarm", apps=apps)
|
|
self.assertEqual(result, ["tasks.gitea_gitea:3000"])
|
|
|
|
def test_native_metrics_port_takes_precedence_over_the_internal_port(self):
|
|
apps = _apps({"port": 9000, "service_key": "synapse"})
|
|
result = _run(["web-app-matrix"], mode="compose", apps=apps)
|
|
self.assertNotIn("8008", result[0])
|
|
|
|
def test_missing_port_raises(self):
|
|
apps = _apps({"service_key": "synapse"})
|
|
with self.assertRaises(AnsibleError):
|
|
_run(["web-app-matrix"], mode="compose", apps=apps)
|
|
|
|
def test_missing_application_id_raises(self):
|
|
with self.assertRaises(AnsibleError):
|
|
_run([], mode="compose", apps=_apps({"port": 9000}))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|