- Purge misplaced RFCs, scratch tokens, and node-proprietary assets - Decouple remote provisioning to ci/scripts/init-node.py - Add targeted composition orchestration in actions/compose.py - Add host-side Xray stale socket cleanup in /dev/shm - Add actions/env.py for shell exports and .env synchronization - Harden UFW, backup retention, host tempfiles, and notify dispatcher - Add pyproject.toml and Makefile with 78 passing unit tests
44 lines
1.4 KiB
Python
44 lines
1.4 KiB
Python
# tests/test_tpl.py
|
|
import os
|
|
import shutil
|
|
import tempfile
|
|
import unittest
|
|
|
|
from engine.lib.log import Log
|
|
from engine.lib.tpl import Tpl
|
|
|
|
|
|
class TestTpl(unittest.TestCase):
|
|
def setUp(self):
|
|
self.cfg = tempfile.mkdtemp()
|
|
self.tpl = Tpl(self.cfg, Log())
|
|
|
|
def tearDown(self):
|
|
shutil.rmtree(self.cfg, ignore_errors=True)
|
|
|
|
def _w(self, rel, body):
|
|
p = os.path.join(self.cfg, rel)
|
|
os.makedirs(os.path.dirname(p), exist_ok=True)
|
|
with open(p, "w", encoding="utf-8") as f:
|
|
f.write(body)
|
|
|
|
def test_render_substitutes_known_vars(self):
|
|
self._w("cron/crontab", "root=${APEX_TIER1} node=$APEX_NODE\n")
|
|
out = self.tpl.render("cron/crontab", {"APEX_TIER1": "/mnt/t1", "APEX_NODE": "node1"})
|
|
self.assertEqual(out, "root=/mnt/t1 node=node1\n")
|
|
|
|
def test_render_leaves_shell_command_substitution(self):
|
|
self._w("c", "x $(cat /f) ${APEX_NODE}\n")
|
|
out = self.tpl.render("c", {"APEX_NODE": "d"})
|
|
self.assertEqual(out, "x $(cat /f) d\n") # $(...) survives; ${APEX_NODE} replaced
|
|
|
|
def test_render_dir_returns_relpath_map(self):
|
|
self._w("fail2ban/jail.local", "a=${X}\n")
|
|
self._w("fail2ban/sub/extra.conf", "b=${Y}\n")
|
|
out = self.tpl.render_dir("fail2ban", {"X": "1", "Y": "2"})
|
|
self.assertEqual(out, {"jail.local": "a=1\n", "sub/extra.conf": "b=2\n"})
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|