Files
computer-playbook/tests/unit/python/plugins/lookup/test_alert_rule_roles.py
T
kevinveenbirkenbachandClaude Opus 5.5 3610e7b9ef fix(code-scanning): resolve the alerts that describe real code
Of the 76 open code scanning alerts, 39 point at code that can change.

svc-ai-mcp-adapter:
- A path argument that is empty or made only of dots is refused.
  Percent-encoding keeps a separator inside its segment, but "." and ".."
  need none, so an upstream that resolves dot segments could answer from a
  path the contract does not name.
- parse_duration splits on the units. The pattern it used before rescanned
  a long run of digits from every start position.

Tests and the README generators:
- Every Jinja environment built with autoescape=False and a "noqa: S701"
  uses select_autoescape now, as six test modules and
  utils/templating/jinja.py already did. It escapes templates named
  *.html, *.htm and *.xml, which none of these call sites loads.
- Dead code goes: a doubled "rel" block in the email lint, an unread
  _SKIP_DIRS, and a module that _resolve returned to no caller.
- Two "except ...: pass" blocks become contextlib.suppress and
  assertRaises.
- Nine test modules import unittest.mock one way instead of two, and one
  lookup test imports its module once.

Closes #807

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-06 09:18:00 +02:00

113 lines
4.0 KiB
Python

"""Unit tests for plugins/lookup/alert_rule_roles.py.
Mocks the Ansible-side machinery and asserts the plugin returns exactly the
scraped roles that ship a ``templates/prometheus/alert_rules.yml.j2``.
Activation is delegated to ``native_metrics_apps`` rather than re-derived here,
so these tests stub that lookup and assert the intersection. A role that is
deployed but not scraped must not contribute rules: its alert would fire on
``absent()`` forever.
"""
from __future__ import annotations
import tempfile
import unittest
import unittest.mock as mock
from pathlib import Path
import plugins.lookup.alert_rule_roles as module
class _Templar:
def __init__(self, vars_=None):
self.available_variables = vars_ or {}
def template(self, value, **_):
return value
def _make_lookup(vars_=None):
lm = module.LookupModule()
lm._templar = _Templar(vars_ or {})
lm._loader = mock.MagicMock()
return lm
def _seed_roles(tmp_path, roles_with_template, roles_without_template=()):
for role_id in roles_with_template:
target = tmp_path / role_id / "templates" / "prometheus"
target.mkdir(parents=True)
(target / "alert_rules.yml.j2").write_text(" - name: probe\n")
for role_id in roles_without_template:
(tmp_path / role_id / "templates").mkdir(parents=True)
class TestAlertRuleRolesLookup(unittest.TestCase):
def setUp(self):
self._roles_dir = mock.patch.object(module, "ROLES_DIR")
self.roles_dir = self._roles_dir.start()
self.addCleanup(self._roles_dir.stop)
def _patch_scraped(self, scraped):
"""Stand in for the native_metrics_apps lookup."""
inner = mock.MagicMock()
inner.run.return_value = [list(scraped)]
loader = mock.patch.object(module, "lookup_loader")
started = loader.start()
started.get.return_value = inner
self.addCleanup(loader.stop)
def test_raises_when_positional_terms_supplied(self):
self._patch_scraped([])
lm = _make_lookup({"group_names": []})
with self.assertRaises(ValueError):
lm.run(["unexpected"], variables=lm._templar.available_variables)
def test_returns_only_scraped_roles_that_ship_a_template(self):
with tempfile.TemporaryDirectory() as td:
tmp_path = Path(td)
_seed_roles(
tmp_path,
roles_with_template=["web-app-openbao", "svc-db-postgres"],
roles_without_template=["web-app-matomo"],
)
module.ROLES_DIR = tmp_path
self._patch_scraped(["web-app-matomo", "web-app-openbao"])
lm = _make_lookup({})
self.assertEqual(lm.run([], variables={}), [["web-app-openbao"]])
def test_a_deployed_role_that_is_not_scraped_contributes_no_rules(self):
"""The whole point of moving the filter out of the fragments.
svc-db-postgres ships a template here but native_metrics_apps does not
list it, so its rules must not reach the file.
"""
with tempfile.TemporaryDirectory() as td:
tmp_path = Path(td)
_seed_roles(tmp_path, roles_with_template=["svc-db-postgres"])
module.ROLES_DIR = tmp_path
self._patch_scraped([])
lm = _make_lookup({})
self.assertEqual(lm.run([], variables={}), [[]])
def test_result_is_sorted_and_deduplicated(self):
with tempfile.TemporaryDirectory() as td:
tmp_path = Path(td)
_seed_roles(tmp_path, roles_with_template=["b-role", "a-role"])
module.ROLES_DIR = tmp_path
self._patch_scraped(["b-role", "a-role", "b-role"])
lm = _make_lookup({})
self.assertEqual(lm.run([], variables={}), [["a-role", "b-role"]])
def test_returns_empty_list_when_nothing_is_scraped(self):
with tempfile.TemporaryDirectory() as td:
module.ROLES_DIR = Path(td)
self._patch_scraped([])
lm = _make_lookup({})
self.assertEqual(lm.run([], variables={}), [[]])