mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-09 20:26:33 +00:00
Hard-coded self-path references rot the moment the file moves: a header
comment ``# utils/foo/bar.py`` at the top of a module, a docstring
mentioning ``utils/foo/bar.py``, or a docs entry linking
``utils/foo/bar.py`` from inside ``utils/foo/bar.py`` itself all silently
desync from reality after the next ``git mv``.
The new lint walks every project file, computes its POSIX-style relative
path from PROJECT_ROOT, and reports any line whose text contains that
path as a substring. Files at the repo root (no ``/`` in their relative
path) and setuptools-generated ``*.egg-info/`` artefacts are exempt.
Per-line opt-out via ``# nocheck: self-path-reference`` on the offending
line, registered in the suppression catalog.
Existing offenders cleaned up:
- 72 redundant ``# <self-path>`` header lines removed across roles,
cli, plugins, scripts, tests, and utils.
- 4 prometheus templates that told consumers to "update
<self-template-path>" rewritten to drop the redundant self-reference.
- 8 docstring/comment self-references in cli, plugins, tests, utils,
and the dashboard oidc.js.j2 header rewritten to describe the layout
without naming the file's own path.
- 17 legitimate usage examples (shell scripts, test data lists, one
template self-include doc-block) marked with ``nocheck:
self-path-reference``.
- ``container.sh`` heredoc usage strings switched to ``${0}`` so the
marker stays out of the user-visible help output.
- ``healthcheck/http.yml.j2`` doc-block rewritten to prose because
``{# ... #}`` Jinja comments cannot host an inner ``{# nocheck #}``
(the inner ``#}`` closes the outer comment).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
178 lines
5.9 KiB
Python
178 lines
5.9 KiB
Python
import unittest
|
|
from unittest.mock import patch
|
|
|
|
from ansible.errors import AnsibleError
|
|
|
|
from plugins.lookup.nginx import LookupModule
|
|
|
|
|
|
class _FakeTlsResolveLookup:
|
|
"""
|
|
Minimal fake lookup plugin compatible with the NEW call style:
|
|
- run([domain, "protocols.web"], variables=...)
|
|
"""
|
|
|
|
def __init__(self, protocol: str):
|
|
self._protocol = protocol
|
|
|
|
def run(self, terms, variables=None, **kwargs):
|
|
# New API: second positional term is want-path
|
|
if len(terms) != 2 or terms[1] != "protocols.web":
|
|
raise AssertionError(f"Unexpected terms passed to tls: {terms}")
|
|
|
|
# Legacy kwarg want must be ignored; if it appears, fail (we don't expect it anymore)
|
|
if kwargs.get("want"):
|
|
raise AssertionError(f"Unexpected want kwarg passed to tls: {kwargs}")
|
|
|
|
return [self._protocol]
|
|
|
|
|
|
class TestNginxPathsLookup(unittest.TestCase):
|
|
def setUp(self):
|
|
self.plugin = LookupModule()
|
|
self.variables = {
|
|
"applications": {"svc-prx-openresty": {"docker": {"volumes": {}}}},
|
|
}
|
|
|
|
def _fake_get(self, applications, app_id, key, strict=True):
|
|
if key == "volumes.www":
|
|
return "/opt/mock/www"
|
|
if key == "volumes.nginx":
|
|
return "/opt/mock/nginx"
|
|
raise KeyError(key)
|
|
|
|
def _run(self, terms, **kwargs):
|
|
with patch(
|
|
"plugins.lookup.nginx.get",
|
|
side_effect=self._fake_get,
|
|
):
|
|
return self.plugin.run(terms, variables=self.variables, **kwargs)[0]
|
|
|
|
def test_files_configuration_projection(self):
|
|
out = self._run(["files.configuration"])
|
|
self.assertEqual(out, "/opt/mock/nginx/nginx.conf")
|
|
|
|
def test_directories_configuration_projection(self):
|
|
out = self._run(["directories.configuration.base"])
|
|
self.assertEqual(out, "/opt/mock/nginx/conf.d/")
|
|
|
|
def test_directories_configuration_http_includes(self):
|
|
out = self._run(["directories.configuration.http_includes"])
|
|
self.assertEqual(
|
|
out,
|
|
[
|
|
"/opt/mock/nginx/conf.d/global/",
|
|
"/opt/mock/nginx/conf.d/maps/",
|
|
"/opt/mock/nginx/conf.d/servers/http/",
|
|
"/opt/mock/nginx/conf.d/servers/https/",
|
|
],
|
|
)
|
|
|
|
def test_directories_data_projection(self):
|
|
out = self._run(["directories.data"])
|
|
self.assertEqual(out["www"], "/opt/mock/www/")
|
|
self.assertEqual(out["html"], "/opt/mock/www/public_html/")
|
|
self.assertEqual(out["files"], "/opt/mock/www/public_files/")
|
|
self.assertEqual(out["cdn"], "/opt/mock/www/public_cdn/")
|
|
self.assertEqual(out["global"], "/opt/mock/www/global/")
|
|
self.assertEqual(out["well_known"], "/usr/share/nginx/well-known/")
|
|
|
|
def test_directories_cache_projection(self):
|
|
out = self._run(["directories.cache"])
|
|
self.assertEqual(out["general"], "/tmp/cache_nginx_general/")
|
|
self.assertEqual(out["image"], "/tmp/cache_nginx_image/")
|
|
|
|
def test_directories_ensure_projection(self):
|
|
ensure = self._run(["directories.ensure"])
|
|
self.assertIsInstance(ensure, list)
|
|
|
|
self.assertIn({"path": "/tmp/cache_nginx_general/", "mode": "0700"}, ensure)
|
|
self.assertIn({"path": "/tmp/cache_nginx_image/", "mode": "0700"}, ensure)
|
|
|
|
ensure_paths = self._run(["directories.ensure_paths"])
|
|
self.assertIsInstance(ensure_paths, list)
|
|
self.assertEqual(ensure_paths, [d["path"] for d in ensure])
|
|
|
|
# well_known is container path → must NOT be part of host dir creation
|
|
self.assertNotIn("/usr/share/nginx/well-known/", ensure_paths)
|
|
|
|
def test_domain_uses_tls_when_no_override(self):
|
|
fake_tls = _FakeTlsResolveLookup("https")
|
|
|
|
with (
|
|
patch(
|
|
"plugins.lookup.nginx.get",
|
|
side_effect=self._fake_get,
|
|
),
|
|
patch(
|
|
"plugins.lookup.nginx.lookup_loader.get",
|
|
return_value=fake_tls,
|
|
),
|
|
):
|
|
out = self.plugin.run(
|
|
["files.domain", "example.com"], variables=self.variables
|
|
)[0]
|
|
|
|
self.assertEqual(
|
|
out,
|
|
"/opt/mock/nginx/conf.d/servers/https/example.com.conf",
|
|
)
|
|
|
|
def test_domain_protocol_override_http(self):
|
|
# tls should NOT be consulted when override is present
|
|
with (
|
|
patch(
|
|
"plugins.lookup.nginx.get",
|
|
side_effect=self._fake_get,
|
|
),
|
|
patch(
|
|
"plugins.lookup.nginx.lookup_loader.get",
|
|
side_effect=AssertionError(
|
|
"tls must not be called when protocol override is set"
|
|
),
|
|
),
|
|
):
|
|
out = self.plugin.run(
|
|
["files.domain", "example.com"],
|
|
variables=self.variables,
|
|
protocol="http",
|
|
)[0]
|
|
|
|
self.assertEqual(
|
|
out,
|
|
"/opt/mock/nginx/conf.d/servers/http/example.com.conf",
|
|
)
|
|
|
|
def test_invalid_protocol_override_raises(self):
|
|
with (
|
|
patch(
|
|
"plugins.lookup.nginx.get",
|
|
side_effect=self._fake_get,
|
|
),
|
|
self.assertRaises(AnsibleError),
|
|
):
|
|
self.plugin.run(
|
|
["files.domain", "example.com"],
|
|
variables=self.variables,
|
|
protocol="ftp",
|
|
)
|
|
|
|
def test_invalid_usage_raises(self):
|
|
with patch(
|
|
"plugins.lookup.nginx.get",
|
|
side_effect=self._fake_get,
|
|
):
|
|
# want-path missing
|
|
with self.assertRaises(AnsibleError):
|
|
self.plugin.run([], variables=self.variables)
|
|
|
|
# too many terms
|
|
with self.assertRaises(AnsibleError):
|
|
self.plugin.run(
|
|
["files.domain", "example.com", "extra"], variables=self.variables
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|