"""File generation using Jinja2 templates.""" import sys from pathlib import Path from jinja2 import Environment, BaseLoader, TemplateNotFound from models import HostConfig class PackageTemplateLoader(BaseLoader): """Custom Jinja2 loader that works with both dev and installed packages.""" def __init__(self): # Try to find templates in multiple locations self.template_dirs = [] # Location 1: Development (scripts/create-host/templates) dev_dir = Path(__file__).parent / "templates" if dev_dir.exists(): self.template_dirs.append(dev_dir) # Location 2: Installed via Nix (../share/create-host/templates from bin dir) # When installed via Nix, __file__ is in lib/python3.X/site-packages/ # and templates are in ../../../share/create-host/templates for site_path in sys.path: site_dir = Path(site_path) # Try to find the Nix store path if "site-packages" in str(site_dir): # Go up to the package root (e.g., /nix/store/xxx-create-host-0.1.0) pkg_root = site_dir.parent.parent.parent share_templates = pkg_root / "share" / "create-host" / "templates" if share_templates.exists(): self.template_dirs.append(share_templates) # Location 3: Fallback - sys.path templates for site_path in sys.path: site_templates = Path(site_path) / "templates" if site_templates.exists(): self.template_dirs.append(site_templates) def get_source(self, environment, template): for template_dir in self.template_dirs: template_path = template_dir / template if template_path.exists(): mtime = template_path.stat().st_mtime source = template_path.read_text() return source, str(template_path), lambda: mtime == template_path.stat().st_mtime raise TemplateNotFound(template) def generate_host_files(config: HostConfig, repo_root: Path) -> None: """ Generate host configuration files from templates. Args: config: Host configuration repo_root: Path to repository root """ # Setup Jinja2 environment with custom loader env = Environment( loader=PackageTemplateLoader(), trim_blocks=True, lstrip_blocks=True, ) # Create host directory host_dir = repo_root / "hosts" / config.hostname host_dir.mkdir(parents=True, exist_ok=True) # Generate default.nix default_template = env.get_template("default.nix.j2") default_content = default_template.render(hostname=config.hostname) (host_dir / "default.nix").write_text(default_content) # Generate configuration.nix config_template = env.get_template("configuration.nix.j2") config_content = config_template.render( hostname=config.hostname, domain=config.domain, nameservers=config.nameservers, is_static_ip=config.is_static_ip, ip=config.ip, gateway=config.gateway, state_version=config.state_version, ) (host_dir / "configuration.nix").write_text(config_content)