mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-10 04:36:40 +00:00
Merge branch 'feature/updater' into feature/store-i18n
Five conflicts, resolved by what each side is for rather than by taking a
side:
- sys-service/01_prune.yml and sys-service-terminator/02_unlock.yml take
the incoming single `systemctl` invocation over four module loops. The
unlock side also drops an unmask step: the list it runs on is built with
`reject('search', ' masked')`, so it never held a masked unit and the
step did nothing.
- sys-stk-front-proxy/tasks/main.yml keeps this branch's version. The block
the other side still carries there moved into vhost.yml, which runs it
once per network sibling; taking theirs would have duplicated it.
vhost.yml holds every task of that block, the global injection and the
TLS layer included.
- web-app-matomo/08_reinject_consumers.yml likewise keeps the per-vhost
loop, which re-renders the injection for every network sibling and passes
matomo_token_override.
- utils/cache/domains.py combines both: the incoming side rendered
DOMAIN_PRIMARY with the real templar and variables, which is right, but
added a second renderer beside the module's own. _render_plain now takes
that context optionally, so the other two call sites stay as they were.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
commit
0af8ee5992
21 files changed
+223
-235
No files matched your search
@@ -201,6 +201,46 @@ class TestCertPlanLookup(unittest.TestCase):
|
||||
"/etc/infinito.nexus/selfsigned/web-app-b/b.example/privkey.pem",
|
||||
)
|
||||
|
||||
def test_primary_domain_term_matches_the_application_term(self):
|
||||
cases = [
|
||||
("web-app-a", "a.example", dict(self.vars, CERTBOT_FLAVOR="san")),
|
||||
("web-app-a", "a.example", dict(self.vars, CERTBOT_FLAVOR="dedicated")),
|
||||
("web-app-a", "a.example", dict(self.vars, CERTBOT_FLAVOR="wildcard")),
|
||||
("web-app-b", "b.example", dict(self.vars)),
|
||||
("web-app-b", "b.example", dict(self.vars, TLS_SELFSIGNED_SCOPE="app")),
|
||||
("web-app-c", "c.example", dict(self.vars, TLS_SELFSIGNED_SCOPE="app")),
|
||||
]
|
||||
for app_id, primary, v in cases:
|
||||
by_app = self.lookup.run([app_id, "files"], variables=v)[0]
|
||||
by_domain = self.lookup.run([primary, "files"], variables=v)[0]
|
||||
self.assertEqual(by_domain, by_app, (app_id, primary))
|
||||
|
||||
def test_selfsigned_app_scope_secondary_domain_uses_the_app_leaf(self):
|
||||
v = dict(self.vars, TLS_SELFSIGNED_SCOPE="app")
|
||||
cases = [
|
||||
("b-alt.example", "/etc/infinito.nexus/selfsigned/web-app-b/b.example"),
|
||||
("api.c.example", "/etc/infinito.nexus/selfsigned/web-app-c/c.example"),
|
||||
]
|
||||
for term, leaf in cases:
|
||||
out = self.lookup.run([term, "files"], variables=v)[0]
|
||||
self.assertEqual(out["cert"], f"{leaf}/fullchain.pem")
|
||||
self.assertEqual(out["key"], f"{leaf}/privkey.pem")
|
||||
|
||||
def test_letsencrypt_secondary_domain_gets_its_own_lineage_link(self):
|
||||
v = dict(
|
||||
self.vars,
|
||||
applications=dict(self.applications, **{"web-app-b": {}}),
|
||||
)
|
||||
out = self.lookup.run(["b-alt.example", "files.cert"], variables=v)[0]
|
||||
self.assertEqual(out, "/etc/letsencrypt/live/b-alt.example/fullchain.pem")
|
||||
|
||||
def test_letsencrypt_onion_domain_keeps_the_app_lineage(self):
|
||||
domains = dict(self.domains, **{"web-app-a": ["a.example", "a.node.onion"]})
|
||||
for flavor in ("san", "dedicated", "wildcard"):
|
||||
v = dict(self.vars, CERTBOT_FLAVOR=flavor, domains=domains)
|
||||
out = self.lookup.run(["a.node.onion", "files.cert"], variables=v)[0]
|
||||
self.assertEqual(out, "/etc/letsencrypt/live/a.example/fullchain.pem")
|
||||
|
||||
def test_selfsigned_san_override(self):
|
||||
v = dict(self.vars)
|
||||
v["TLS_SELFSIGNED_SCOPE"] = "app"
|
||||
|
||||
@@ -1,13 +1,3 @@
|
||||
#
|
||||
# Unit tests for plugins/lookup/unit_name.py using Python's built-in unittest.
|
||||
#
|
||||
# Run with:
|
||||
# python -m unittest -v
|
||||
#
|
||||
# Notes:
|
||||
# - These tests do NOT require a full Ansible runtime; we mock the templar.
|
||||
# - They validate the naming format and error handling.
|
||||
|
||||
import unittest
|
||||
|
||||
from ansible.errors import AnsibleError
|
||||
@@ -16,73 +6,54 @@ from plugins.lookup.unit_name import LookupModule
|
||||
|
||||
|
||||
class DummyTemplar:
|
||||
"""Minimal templar stub to satisfy the lookup plugin."""
|
||||
|
||||
def __init__(self, available_variables=None, version="1.2.3"):
|
||||
def __init__(self, available_variables=None, rendered=None):
|
||||
self.available_variables = available_variables or {}
|
||||
self._version = version
|
||||
self._rendered = rendered or {}
|
||||
|
||||
def template(self, s: str, **kwargs):
|
||||
if "lookup('version')" in s:
|
||||
return self._version
|
||||
if "{{ SOFTWARE_NAME | lower }}" in s:
|
||||
return str(self.available_variables.get("SOFTWARE_NAME", "")).lower()
|
||||
return s
|
||||
return self._rendered.get(s, s)
|
||||
|
||||
|
||||
class UnitNameLookupTests(unittest.TestCase):
|
||||
def _mk_lookup(
|
||||
self, software_domain="infinito.nexus", version="1.2.3"
|
||||
) -> LookupModule:
|
||||
def _mk_lookup(self, version_suffix=".2.0.0.infinito.nexus", rendered=None):
|
||||
lm = LookupModule()
|
||||
|
||||
lm._templar = DummyTemplar(
|
||||
available_variables={"SOFTWARE_DOMAIN": software_domain},
|
||||
version=version,
|
||||
available_variables={"SYS_SERVICE_VERSION_SUFFIX": version_suffix},
|
||||
rendered=rendered,
|
||||
)
|
||||
|
||||
lm.set_options = lambda *args, **kwargs: None
|
||||
|
||||
return lm
|
||||
|
||||
def test_default_suffix_service(self):
|
||||
lm = self._mk_lookup(software_domain="Infinito.Nexus", version="2.0.0")
|
||||
res = lm.run(["svc-foo"])
|
||||
res = self._mk_lookup().run(["svc-foo"])
|
||||
self.assertEqual(res, ["svc-foo.2.0.0.infinito.nexus.service"])
|
||||
|
||||
def test_sys_ctl_prefix_is_removed(self):
|
||||
lm = self._mk_lookup(software_domain="Infinito.Nexus", version="2.0.0")
|
||||
res = lm.run(["sys-ctl-cln-bkps"])
|
||||
res = self._mk_lookup().run(["sys-ctl-cln-bkps"])
|
||||
self.assertEqual(res, ["cln-bkps.2.0.0.infinito.nexus.service"])
|
||||
|
||||
def test_explicit_timer_suffix_with_dot(self):
|
||||
lm = self._mk_lookup(software_domain="infinito.nexus", version="2.0.0")
|
||||
res = lm.run(["svc-foo"], suffix=".timer")
|
||||
res = self._mk_lookup().run(["svc-foo"], suffix=".timer")
|
||||
self.assertEqual(res, ["svc-foo.2.0.0.infinito.nexus.timer"])
|
||||
|
||||
def test_explicit_timer_suffix_without_dot(self):
|
||||
lm = self._mk_lookup(software_domain="infinito.nexus", version="2.0.0")
|
||||
res = lm.run(["svc-foo"], suffix="timer")
|
||||
res = self._mk_lookup().run(["svc-foo"], suffix="timer")
|
||||
self.assertEqual(res, ["svc-foo.2.0.0.infinito.nexus.timer"])
|
||||
|
||||
def test_suffix_false_means_no_suffix(self):
|
||||
lm = self._mk_lookup(software_domain="infinito.nexus", version="2.0.0")
|
||||
res = lm.run(["svc-foo"], suffix=False)
|
||||
res = self._mk_lookup().run(["svc-foo"], suffix=False)
|
||||
self.assertEqual(res, ["svc-foo.2.0.0.infinito.nexus"])
|
||||
|
||||
def test_template_unit_id_endswith_at(self):
|
||||
lm = self._mk_lookup(software_domain="infinito.nexus", version="2.0.0")
|
||||
res = lm.run(["alarm@"])
|
||||
res = self._mk_lookup().run(["alarm@"])
|
||||
self.assertEqual(res, ["alarm.2.0.0.infinito.nexus@.service"])
|
||||
|
||||
def test_template_unit_id_endswith_at_with_sys_ctl_prefix(self):
|
||||
lm = self._mk_lookup(software_domain="infinito.nexus", version="2.0.0")
|
||||
res = lm.run(["sys-ctl-alm-compose@"], suffix=False)
|
||||
res = self._mk_lookup().run(["sys-ctl-alm-compose@"], suffix=False)
|
||||
self.assertEqual(res, ["alm-compose.2.0.0.infinito.nexus@"])
|
||||
|
||||
def test_multiple_terms(self):
|
||||
lm = self._mk_lookup(software_domain="infinito.nexus", version="2.0.0")
|
||||
res = lm.run(["a", "b"], suffix=".timer")
|
||||
res = self._mk_lookup().run(["a", "b"], suffix=".timer")
|
||||
self.assertEqual(
|
||||
res,
|
||||
[
|
||||
@@ -92,63 +63,41 @@ class UnitNameLookupTests(unittest.TestCase):
|
||||
)
|
||||
|
||||
def test_missing_terms_raises(self):
|
||||
lm = self._mk_lookup()
|
||||
with self.assertRaises(AnsibleError) as ctx:
|
||||
lm.run([])
|
||||
self._mk_lookup().run([])
|
||||
self.assertIn("at least one term", str(ctx.exception))
|
||||
|
||||
def test_missing_software_name_raises(self):
|
||||
def test_missing_version_suffix_raises(self):
|
||||
lm = LookupModule()
|
||||
lm._templar = DummyTemplar(available_variables={}, version="1.2.3")
|
||||
lm._templar = DummyTemplar(available_variables={})
|
||||
lm.set_options = lambda *args, **kwargs: None
|
||||
|
||||
with self.assertRaises(AnsibleError) as ctx:
|
||||
lm.run(["svc-foo"])
|
||||
self.assertIn("SOFTWARE_DOMAIN is not defined", str(ctx.exception))
|
||||
self.assertIn("SYS_SERVICE_VERSION_SUFFIX is not defined", str(ctx.exception))
|
||||
|
||||
def test_empty_version_raises(self):
|
||||
lm = self._mk_lookup(software_domain="infinito.nexus", version=" ")
|
||||
with self.assertRaises(AnsibleError) as ctx:
|
||||
lm.run(["svc-foo"])
|
||||
self.assertIn("lookup('version') returned an empty value", str(ctx.exception))
|
||||
|
||||
def test_templated_software_domain_is_rendered(self):
|
||||
lm = LookupModule()
|
||||
lm._templar = DummyTemplar(
|
||||
available_variables={
|
||||
"SOFTWARE_DOMAIN": "{{ SOFTWARE_NAME | lower }}",
|
||||
"SOFTWARE_NAME": "Infinito.Nexus",
|
||||
},
|
||||
version="2.0.0",
|
||||
)
|
||||
lm.set_options = lambda *args, **kwargs: None
|
||||
|
||||
res = lm.run(["svc-foo"])
|
||||
self.assertEqual(res, ["svc-foo.2.0.0.infinito.nexus.service"])
|
||||
|
||||
def test_unresolved_software_domain_template_raises(self):
|
||||
lm = LookupModule()
|
||||
lm._templar = DummyTemplar(
|
||||
available_variables={"SOFTWARE_DOMAIN": "{{ UNKNOWN_VAR | lower }}"},
|
||||
version="2.0.0",
|
||||
)
|
||||
lm.set_options = lambda *args, **kwargs: None
|
||||
|
||||
with self.assertRaises(AnsibleError) as ctx:
|
||||
lm.run(["svc-foo"])
|
||||
self.assertIn("unresolved template for 'SOFTWARE_DOMAIN'", str(ctx.exception))
|
||||
|
||||
def test_version_fallback_direct_lookup_plugin(self):
|
||||
def test_templated_version_suffix_is_rendered_and_lowered(self):
|
||||
template = ".{{ lookup('version') | lower }}.{{ SOFTWARE_DOMAIN }}"
|
||||
lm = self._mk_lookup(
|
||||
software_domain="infinito.nexus", version="{{ lookup('version') }}"
|
||||
version_suffix=template,
|
||||
rendered={template: ".2.0.0.Infinito.Nexus"},
|
||||
)
|
||||
res = lm.run(["svc-foo"])
|
||||
self.assertEqual(lm.run(["svc-foo"]), ["svc-foo.2.0.0.infinito.nexus.service"])
|
||||
|
||||
self.assertRegex(
|
||||
res[0],
|
||||
r"^svc-foo\.[0-9A-Za-z._+-]+\.infinito\.nexus\.service$",
|
||||
def test_unresolved_version_suffix_template_raises(self):
|
||||
lm = self._mk_lookup(version_suffix="{{ UNKNOWN_VAR }}")
|
||||
with self.assertRaises(AnsibleError) as ctx:
|
||||
lm.run(["svc-foo"])
|
||||
self.assertIn(
|
||||
"unresolved template for 'SYS_SERVICE_VERSION_SUFFIX'", str(ctx.exception)
|
||||
)
|
||||
|
||||
def test_malformed_version_suffix_raises(self):
|
||||
for malformed in ("2.0.0.infinito.nexus", "..infinito.nexus"):
|
||||
lm = self._mk_lookup(version_suffix=malformed)
|
||||
with self.assertRaises(AnsibleError) as ctx:
|
||||
lm.run(["svc-foo"])
|
||||
self.assertIn("must read '.<version>.<domain>'", str(ctx.exception))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user