mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2025-08-29 23:08:06 +02:00
Implemented dict renderer to resolve assets
This commit is contained in:
@@ -1,106 +1,109 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import yaml
|
||||
import sys
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
plugin_path = Path(__file__).resolve().parent / ".." / ".." / ".." /"lookup_plugins"
|
||||
# Ensure project root on PYTHONPATH so utils is importable
|
||||
repo_root = Path(__file__).resolve().parent.parent.parent.parent
|
||||
sys.path.insert(0, str(repo_root))
|
||||
|
||||
# Add lookup_plugins for application_gid
|
||||
plugin_path = repo_root / "lookup_plugins"
|
||||
sys.path.insert(0, str(plugin_path))
|
||||
|
||||
from utils.dict_renderer import DictRenderer
|
||||
from application_gid import LookupModule
|
||||
|
||||
def load_yaml_file(path):
|
||||
"""Load a YAML file if it exists, otherwise return an empty dict."""
|
||||
def load_yaml_file(path: Path) -> dict:
|
||||
if not path.exists():
|
||||
return {}
|
||||
with path.open("r", encoding="utf-8") as f:
|
||||
return yaml.safe_load(f) or {}
|
||||
|
||||
class DefaultsGenerator:
|
||||
def __init__(self, roles_dir: Path, output_file: Path, verbose: bool, timeout: float):
|
||||
self.roles_dir = roles_dir
|
||||
self.output_file = output_file
|
||||
self.verbose = verbose
|
||||
self.renderer = DictRenderer(verbose=verbose, timeout=timeout)
|
||||
self.gid_lookup = LookupModule()
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Generate defaults_applications YAML from docker roles and include users meta data for each role."
|
||||
)
|
||||
parser.add_argument(
|
||||
"--roles-dir",
|
||||
help="Path to the roles directory (default: roles)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--output-file",
|
||||
help="Path to output YAML file"
|
||||
)
|
||||
def log(self, message: str):
|
||||
if self.verbose:
|
||||
print(f"[DefaultsGenerator] {message}")
|
||||
|
||||
def run(self):
|
||||
result = {"defaults_applications": {}}
|
||||
|
||||
for role_dir in sorted(self.roles_dir.iterdir()):
|
||||
role_name = role_dir.name
|
||||
vars_main = role_dir / "vars" / "main.yml"
|
||||
config_file = role_dir / "config" / "main.yml"
|
||||
|
||||
if not vars_main.exists():
|
||||
self.log(f"Skipping {role_name}: vars/main.yml missing")
|
||||
continue
|
||||
|
||||
vars_data = load_yaml_file(vars_main)
|
||||
application_id = vars_data.get("application_id")
|
||||
if not application_id:
|
||||
self.log(f"Skipping {role_name}: application_id not defined")
|
||||
continue
|
||||
|
||||
if not config_file.exists():
|
||||
self.log(f"Skipping {role_name}: config/main.yml missing")
|
||||
continue
|
||||
|
||||
config_data = load_yaml_file(config_file)
|
||||
if config_data:
|
||||
try:
|
||||
gid_number = self.gid_lookup.run([application_id], roles_dir=str(self.roles_dir))[0]
|
||||
except Exception as e:
|
||||
print(f"Warning: failed to determine gid for '{application_id}': {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
config_data["group_id"] = gid_number
|
||||
result["defaults_applications"][application_id] = config_data
|
||||
|
||||
# Inject users mapping as Jinja2 references
|
||||
users_meta = load_yaml_file(role_dir / "users" / "main.yml")
|
||||
users_data = users_meta.get("users", {})
|
||||
transformed = {user: f"{{{{ users[\"{user}\"] }}}}" for user in users_data}
|
||||
if transformed:
|
||||
result["defaults_applications"][application_id]["users"] = transformed
|
||||
|
||||
# Render placeholders in entire result context
|
||||
self.log("Starting placeholder rendering...")
|
||||
try:
|
||||
result = self.renderer.render(result)
|
||||
except Exception as e:
|
||||
print(f"Error during rendering: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# Write output
|
||||
self.output_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
with self.output_file.open("w", encoding="utf-8") as f:
|
||||
yaml.dump(result, f, sort_keys=False)
|
||||
|
||||
# Print location of generated file (absolute if not under cwd)
|
||||
try:
|
||||
rel = self.output_file.relative_to(Path.cwd())
|
||||
except ValueError:
|
||||
rel = self.output_file
|
||||
print(f"✅ Generated: {rel}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Generate defaults_applications YAML...")
|
||||
parser.add_argument("--roles-dir", default="roles", help="Path to the roles directory")
|
||||
parser.add_argument("--output-file", required=True, help="Path to output YAML file")
|
||||
parser.add_argument("--verbose", action="store_true", help="Enable verbose logging")
|
||||
parser.add_argument("--timeout", type=float, default=10.0, help="Timeout for rendering")
|
||||
|
||||
args = parser.parse_args()
|
||||
cwd = Path.cwd()
|
||||
roles_dir = (cwd / args.roles_dir).resolve()
|
||||
output_file = (cwd / args.output_file).resolve()
|
||||
# Ensure output directory exists
|
||||
output_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Initialize result structure
|
||||
result = {"defaults_applications": {}}
|
||||
|
||||
gid_lookup = LookupModule()
|
||||
# Process each role for application configs
|
||||
for role_dir in sorted(roles_dir.iterdir()):
|
||||
role_name = role_dir.name
|
||||
vars_main = role_dir / "vars" / "main.yml"
|
||||
config_file = role_dir / "config" / "main.yml"
|
||||
|
||||
if not vars_main.exists():
|
||||
print(f"[!] Skipping {role_name}: vars/main.yml missing")
|
||||
continue
|
||||
|
||||
vars_data = load_yaml_file(vars_main)
|
||||
try:
|
||||
application_id = vars_data.get("application_id")
|
||||
except Exception as e:
|
||||
print(
|
||||
f"Warning: failed to read application_id from {vars_main}\nException: {e}",
|
||||
file=sys.stderr
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
if not application_id:
|
||||
print(f"[!] Skipping {role_name}: application_id not defined in vars/main.yml")
|
||||
continue
|
||||
|
||||
if not config_file.exists():
|
||||
print(f"[!] Skipping {role_name}: config/main.yml missing")
|
||||
continue
|
||||
|
||||
config_data = load_yaml_file(config_file)
|
||||
if config_data:
|
||||
try:
|
||||
gid_number = gid_lookup.run([application_id], roles_dir=str(roles_dir))[0]
|
||||
except Exception as e:
|
||||
print(f"Warning: failed to determine gid for '{application_id}': {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
config_data["group_id"] = gid_number
|
||||
result["defaults_applications"][application_id] = config_data
|
||||
users_meta_file = role_dir / "users" / "main.yml"
|
||||
transformed_users = {}
|
||||
if users_meta_file.exists():
|
||||
users_meta = load_yaml_file(users_meta_file)
|
||||
users_data = users_meta.get("users", {})
|
||||
for user, role_user_attrs in users_data.items():
|
||||
transformed_users[user] = f"{{{{ users[\"{user}\"] }}}}"
|
||||
|
||||
# Attach transformed users under each application
|
||||
if transformed_users:
|
||||
result["defaults_applications"][application_id]["users"] = transformed_users
|
||||
|
||||
# Write out result YAML
|
||||
with output_file.open("w", encoding="utf-8") as f:
|
||||
yaml.dump(result, f, sort_keys=False)
|
||||
|
||||
try:
|
||||
print(f"✅ Generated: {output_file.relative_to(cwd)}")
|
||||
except ValueError:
|
||||
print(f"✅ Generated: {output_file}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
DefaultsGenerator(roles_dir, output_file, args.verbose, args.timeout).run()
|
Reference in New Issue
Block a user