From 8daed96b7c95c337d25727986a8b6afe0fcfbf74 Mon Sep 17 00:00:00 2001 From: Miguel Jacq Date: Tue, 6 Jan 2026 12:47:12 +1100 Subject: [PATCH] Attempt to generate Jinja2 templates of systemd unit files and Postfix main.cf (now that JinjaTurtle supports it) --- CHANGELOG.md | 1 + enroll/jinjaturtle.py | 52 +++++++++++++++++++++++++++++++++++++++---- enroll/manifest.py | 8 +++++-- 3 files changed, 55 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dca9314..84f8d23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # 0.4.0 (not yet released) * Introduce `enroll validate` - a tool to validate a harvest against the state schema, or check for missing or orphaned obsolete artifacts in a harvest. + * Attempt to generate Jinja2 templates of systemd unit files and Postfix main.cf (now that JinjaTurtle supports it) # 0.3.0 diff --git a/enroll/jinjaturtle.py b/enroll/jinjaturtle.py index 67f0215..6a13fa1 100644 --- a/enroll/jinjaturtle.py +++ b/enroll/jinjaturtle.py @@ -8,7 +8,45 @@ from pathlib import Path from typing import Optional -SUPPORTED_EXTS = {".ini", ".json", ".toml", ".yaml", ".yml", ".xml"} +SYSTEMD_SUFFIXES = { + ".service", + ".socket", + ".target", + ".timer", + ".path", + ".mount", + ".automount", + ".slice", + ".swap", + ".scope", + ".link", + ".netdev", + ".network", +} + +SUPPORTED_SUFFIXES = { + ".ini", + ".cfg", + ".json", + ".toml", + ".yaml", + ".yml", + ".xml", + ".repo", +} | SYSTEMD_SUFFIXES + + +def infer_other_formats(dest_path: str) -> Optional[str]: + p = Path(dest_path) + name = p.name.lower() + suffix = p.suffix.lower() + # postfix + if name == "main.cf": + return "postfix" + # systemd units + if suffix in SYSTEMD_SUFFIXES: + return "systemd" + return None @dataclass(frozen=True) @@ -22,9 +60,15 @@ def find_jinjaturtle_cmd() -> Optional[str]: return shutil.which("jinjaturtle") -def can_jinjify_path(path: str) -> bool: - p = Path(path) - return p.suffix.lower() in SUPPORTED_EXTS +def can_jinjify_path(dest_path: str) -> bool: + p = Path(dest_path) + suffix = p.suffix.lower() + if infer_other_formats(dest_path): + return True + # allow unambiguous structured formats + if suffix in SUPPORTED_SUFFIXES: + return True + return False def run_jinjaturtle( diff --git a/enroll/manifest.py b/enroll/manifest.py index 9264e4e..1447c0b 100644 --- a/enroll/manifest.py +++ b/enroll/manifest.py @@ -11,8 +11,9 @@ from pathlib import Path from typing import Any, Dict, List, Optional, Set, Tuple from .jinjaturtle import ( - find_jinjaturtle_cmd, can_jinjify_path, + find_jinjaturtle_cmd, + infer_other_formats, run_jinjaturtle, ) @@ -309,7 +310,10 @@ def _jinjify_managed_files( continue try: - res = run_jinjaturtle(jt_exe, artifact_path, role_name=role) + force_fmt = infer_other_formats(dest_path) + res = run_jinjaturtle( + jt_exe, artifact_path, role_name=role, force_format=force_fmt + ) except Exception: # If jinjaturtle cannot process a file for any reason, skip silently. # (Enroll's core promise is to be optimistic and non-interactive.)