From 3c3739c2348a029f0d9f3108be8338bf200c1ba8 Mon Sep 17 00:00:00 2001 From: Kevin Veen-Birkenbach Date: Thu, 10 Jul 2025 14:31:09 +0200 Subject: [PATCH] Fixed desk roles application ids --- cli/ensure_vars_main.py | 107 +++++++++++++--------- roles/desk-bluray-player/vars/main.yml | 1 + roles/desk-docker/vars/main.yml | 1 + roles/desk-git/vars/main.yml | 1 + roles/desk-gnome-caffeine/vars/main.yml | 3 +- roles/desk-gnome-extensions/vars/main.yml | 2 +- roles/desk-gnome-terminal/vars/main.yml | 1 + roles/desk-gnucash/vars/main.yml | 1 + roles/desk-jrnl/vars/main.yml | 1 + roles/desk-keepassxc/vars/main.yml | 1 + roles/desk-nextcloud-client/vars/main.yml | 5 +- roles/desk-obs/vars/main.yml | 1 + roles/desk-qbittorrent/vars/main.yml | 1 + roles/desk-retroarch/vars/main.yml | 7 +- roles/desk-spotify/vars/main.yml | 1 + roles/desk-ssh/vars/main.yml | 1 + roles/desk-torbrowser/vars/main.yml | 1 + roles/desk-virtual-box/vars/main.yml | 1 + roles/desk-zoom/vars/main.yml | 1 + tests/unit/cli/test_ensure_vars_main.py | 81 ++++++++++++++++ 20 files changed, 168 insertions(+), 51 deletions(-) create mode 100644 roles/desk-bluray-player/vars/main.yml create mode 100644 roles/desk-docker/vars/main.yml create mode 100644 roles/desk-git/vars/main.yml create mode 100644 roles/desk-gnome-terminal/vars/main.yml create mode 100644 roles/desk-gnucash/vars/main.yml create mode 100644 roles/desk-jrnl/vars/main.yml create mode 100644 roles/desk-keepassxc/vars/main.yml create mode 100644 roles/desk-obs/vars/main.yml create mode 100644 roles/desk-qbittorrent/vars/main.yml create mode 100644 roles/desk-spotify/vars/main.yml create mode 100644 roles/desk-ssh/vars/main.yml create mode 100644 roles/desk-torbrowser/vars/main.yml create mode 100644 roles/desk-virtual-box/vars/main.yml create mode 100644 roles/desk-zoom/vars/main.yml create mode 100644 tests/unit/cli/test_ensure_vars_main.py diff --git a/cli/ensure_vars_main.py b/cli/ensure_vars_main.py index 6d0239b8..572d4dfc 100644 --- a/cli/ensure_vars_main.py +++ b/cli/ensure_vars_main.py @@ -1,64 +1,83 @@ #!/usr/bin/env python3 +""" +Script to ensure each Ansible role under ../roles/ with a given prefix has a vars/main.yml +containing the correct application_id. Can preview actions or overwrite mismatches. +""" import argparse -import os +import sys +import yaml from pathlib import Path +def process_role(role_dir: Path, prefix: str, preview: bool, overwrite: bool): + name = role_dir.name + if not name.startswith(prefix): + return + # Expected application_id is role name minus prefix + expected_id = name[len(prefix):] + vars_dir = role_dir / "vars" + vars_file = vars_dir / "main.yml" + if vars_file.exists(): + # Load existing variables + try: + existing = yaml.safe_load(vars_file.read_text()) or {} + except yaml.YAMLError as e: + print(f"Error parsing YAML in {vars_file}: {e}", file=sys.stderr) + return + actual_id = existing.get("application_id") + if actual_id == expected_id: + # Already correct + return + if overwrite: + # Update only application_id + existing["application_id"] = expected_id + if preview: + print(f"[PREVIEW] Would update {vars_file}: application_id -> {expected_id}") + else: + with open(vars_file, "w") as f: + yaml.safe_dump(existing, f, default_flow_style=False, sort_keys=False) + print(f"Updated {vars_file}: application_id -> {expected_id}") + else: + print(f"Mismatch in {vars_file}: application_id='{actual_id}', expected='{expected_id}'") + else: + # Create new vars/main.yml + if preview: + print(f"[PREVIEW] Would create {vars_file} with application_id: {expected_id}") + else: + vars_dir.mkdir(parents=True, exist_ok=True) + content = {"application_id": expected_id} + with open(vars_file, "w") as f: + yaml.safe_dump(content, f, default_flow_style=False, sort_keys=False) + print(f"Created {vars_file} with application_id: {expected_id}") + + def main(): parser = argparse.ArgumentParser( - description="Generate (or preview) missing vars/main.yml for all roles with a given prefix" + description="Ensure vars/main.yml for roles with a given prefix has correct application_id" ) parser.add_argument( - "--prefix", - required=True, - help="Role-name prefix to scan for (e.g. 'desk-')" + "--prefix", required=True, + help="Role name prefix to filter (e.g. 'web-', 'svc-', 'desk-')" ) parser.add_argument( - "--preview", - action="store_true", - help="If set, only show what would be done without making changes" + "--preview", action="store_true", + help="Show what would be done without making changes" + ) + parser.add_argument( + "--overwrite", action="store_true", + help="If vars/main.yml exists but application_id mismatches, overwrite only that key" ) args = parser.parse_args() - prefix = args.prefix - preview = args.preview - # Locate roles/ directory relative to this script + # Determine roles directory relative to this script script_dir = Path(__file__).resolve().parent - roles_dir = (script_dir / "../roles").resolve() - + roles_dir = (script_dir.parent / "roles").resolve() if not roles_dir.is_dir(): - print(f"Error: roles directory not found at {roles_dir}") - return + print(f"Roles directory not found: {roles_dir}", file=sys.stderr) + sys.exit(1) - missing = [] for role in sorted(roles_dir.iterdir()): - if not role.is_dir(): - continue - if not role.name.startswith(prefix): - continue - - vars_dir = role / "vars" - vars_main = vars_dir / "main.yml" - if not vars_main.exists(): - missing.append((role.name, vars_main)) - - if not missing: - print(f"No missing vars/main.yml files found for prefix '{prefix}'") - return - - for role_name, vars_main in missing: - app_id = role_name[len(prefix):] - content = f"application_id: \"{app_id}\"\n" - - if preview: - print(f"Would create: {vars_main}") - print(f"With content:\n{content}") - else: - # ensure directory exists - vars_main.parent.mkdir(parents=True, exist_ok=True) - # write file - with open(vars_main, "w") as f: - f.write(content) - print(f"Created {vars_main}") + if role.is_dir(): + process_role(role, args.prefix, args.preview, args.overwrite) if __name__ == "__main__": main() diff --git a/roles/desk-bluray-player/vars/main.yml b/roles/desk-bluray-player/vars/main.yml new file mode 100644 index 00000000..35f9e9ca --- /dev/null +++ b/roles/desk-bluray-player/vars/main.yml @@ -0,0 +1 @@ +application_id: bluray-player diff --git a/roles/desk-docker/vars/main.yml b/roles/desk-docker/vars/main.yml new file mode 100644 index 00000000..8961f33b --- /dev/null +++ b/roles/desk-docker/vars/main.yml @@ -0,0 +1 @@ +application_id: docker diff --git a/roles/desk-git/vars/main.yml b/roles/desk-git/vars/main.yml new file mode 100644 index 00000000..cae5cba5 --- /dev/null +++ b/roles/desk-git/vars/main.yml @@ -0,0 +1 @@ +application_id: git diff --git a/roles/desk-gnome-caffeine/vars/main.yml b/roles/desk-gnome-caffeine/vars/main.yml index cb4d3e5e..f8ee7118 100644 --- a/roles/desk-gnome-caffeine/vars/main.yml +++ b/roles/desk-gnome-caffeine/vars/main.yml @@ -1 +1,2 @@ -auto_start_directory: "/home/{{users.client.username}}/.config/autostart/" \ No newline at end of file +auto_start_directory: /home/{{users.client.username}}/.config/autostart/ +application_id: gnome-caffeine diff --git a/roles/desk-gnome-extensions/vars/main.yml b/roles/desk-gnome-extensions/vars/main.yml index 9238e22a..5770d926 100644 --- a/roles/desk-gnome-extensions/vars/main.yml +++ b/roles/desk-gnome-extensions/vars/main.yml @@ -1 +1 @@ -application_id: "gnome" \ No newline at end of file +application_id: gnome-extensions diff --git a/roles/desk-gnome-terminal/vars/main.yml b/roles/desk-gnome-terminal/vars/main.yml new file mode 100644 index 00000000..d883c4d0 --- /dev/null +++ b/roles/desk-gnome-terminal/vars/main.yml @@ -0,0 +1 @@ +application_id: gnome-terminal diff --git a/roles/desk-gnucash/vars/main.yml b/roles/desk-gnucash/vars/main.yml new file mode 100644 index 00000000..e43f7482 --- /dev/null +++ b/roles/desk-gnucash/vars/main.yml @@ -0,0 +1 @@ +application_id: gnucash diff --git a/roles/desk-jrnl/vars/main.yml b/roles/desk-jrnl/vars/main.yml new file mode 100644 index 00000000..8b52c5ca --- /dev/null +++ b/roles/desk-jrnl/vars/main.yml @@ -0,0 +1 @@ +application_id: jrnl diff --git a/roles/desk-keepassxc/vars/main.yml b/roles/desk-keepassxc/vars/main.yml new file mode 100644 index 00000000..ee3e4b38 --- /dev/null +++ b/roles/desk-keepassxc/vars/main.yml @@ -0,0 +1 @@ +application_id: keepassxc diff --git a/roles/desk-nextcloud-client/vars/main.yml b/roles/desk-nextcloud-client/vars/main.yml index 34ce9fe9..b25c94e9 100644 --- a/roles/desk-nextcloud-client/vars/main.yml +++ b/roles/desk-nextcloud-client/vars/main.yml @@ -1,2 +1,3 @@ -user_home_directory: "/home/{{users.client.username}}/" # Home directory of the user -cloud_directory: "{{user_home_directory}}Clouds/{{cloud_fqdn}}/{{users.client.username}}/" # Folder which contains the cloud data +user_home_directory: /home/{{users.client.username}}/ +cloud_directory: '{{user_home_directory}}Clouds/{{cloud_fqdn}}/{{users.client.username}}/' +application_id: nextcloud-client diff --git a/roles/desk-obs/vars/main.yml b/roles/desk-obs/vars/main.yml new file mode 100644 index 00000000..5456b8db --- /dev/null +++ b/roles/desk-obs/vars/main.yml @@ -0,0 +1 @@ +application_id: obs diff --git a/roles/desk-qbittorrent/vars/main.yml b/roles/desk-qbittorrent/vars/main.yml new file mode 100644 index 00000000..544c925c --- /dev/null +++ b/roles/desk-qbittorrent/vars/main.yml @@ -0,0 +1 @@ +application_id: qbittorrent diff --git a/roles/desk-retroarch/vars/main.yml b/roles/desk-retroarch/vars/main.yml index 03296ed9..d3bb7682 100644 --- a/roles/desk-retroarch/vars/main.yml +++ b/roles/desk-retroarch/vars/main.yml @@ -1,4 +1,5 @@ retroarch_packages: - - retroarch - - retroarch-assets-xmb - - retroarch-assets-ozone \ No newline at end of file +- retroarch +- retroarch-assets-xmb +- retroarch-assets-ozone +application_id: retroarch diff --git a/roles/desk-spotify/vars/main.yml b/roles/desk-spotify/vars/main.yml new file mode 100644 index 00000000..c33d742e --- /dev/null +++ b/roles/desk-spotify/vars/main.yml @@ -0,0 +1 @@ +application_id: spotify diff --git a/roles/desk-ssh/vars/main.yml b/roles/desk-ssh/vars/main.yml new file mode 100644 index 00000000..b8caa346 --- /dev/null +++ b/roles/desk-ssh/vars/main.yml @@ -0,0 +1 @@ +application_id: ssh diff --git a/roles/desk-torbrowser/vars/main.yml b/roles/desk-torbrowser/vars/main.yml new file mode 100644 index 00000000..f03cab6e --- /dev/null +++ b/roles/desk-torbrowser/vars/main.yml @@ -0,0 +1 @@ +application_id: torbrowser diff --git a/roles/desk-virtual-box/vars/main.yml b/roles/desk-virtual-box/vars/main.yml new file mode 100644 index 00000000..90a30d88 --- /dev/null +++ b/roles/desk-virtual-box/vars/main.yml @@ -0,0 +1 @@ +application_id: virtual-box diff --git a/roles/desk-zoom/vars/main.yml b/roles/desk-zoom/vars/main.yml new file mode 100644 index 00000000..239d64d8 --- /dev/null +++ b/roles/desk-zoom/vars/main.yml @@ -0,0 +1 @@ +application_id: zoom diff --git a/tests/unit/cli/test_ensure_vars_main.py b/tests/unit/cli/test_ensure_vars_main.py new file mode 100644 index 00000000..49d813a2 --- /dev/null +++ b/tests/unit/cli/test_ensure_vars_main.py @@ -0,0 +1,81 @@ +# tests/cli/test_ensure_vars_main.py +import os +import shutil +import tempfile +import unittest +import yaml + +# Adjust this import to match the real path in your project +from cli.ensure_vars_main import run, ROLES_DIR + +class TestEnsureVarsMain(unittest.TestCase): + def setUp(self): + # create a temporary directory to act as our roles dir + self.tmpdir = tempfile.mkdtemp() + self.roles_dir = os.path.join(self.tmpdir, "roles") + os.mkdir(self.roles_dir) + + # Monkey-patch the module's ROLES_DIR to point here + self._orig_roles_dir = ROLES_DIR + setattr(__import__("cli.ensure_vars_main", fromlist=["ROLES_DIR"]), "ROLES_DIR", self.roles_dir) + + def tearDown(self): + # restore and cleanup + setattr(__import__("cli.ensure_vars_main", fromlist=["ROLES_DIR"]), "ROLES_DIR", self._orig_roles_dir) + shutil.rmtree(self.tmpdir) + + def _make_role(self, name, vars_content=None): + """ + Create a role under self.roles_dir/name + If vars_content is given, writes that to vars/main.yml + """ + role_path = os.path.join(self.roles_dir, name) + os.makedirs(os.path.join(role_path, "vars")) + if vars_content is not None: + with open(os.path.join(role_path, "vars", "main.yml"), "w") as f: + yaml.safe_dump(vars_content, f) + return role_path + + def test_creates_missing_vars_main(self): + # Create a role with no vars/main.yml + role = self._make_role("desk-foobar") + # Ensure no file exists yet + self.assertFalse(os.path.exists(os.path.join(role, "vars", "main.yml"))) + + # Run with overwrite=False, preview=False + run(prefix="desk-", preview=False, overwrite=False) + + # Now file must exist + vm = os.path.join(role, "vars", "main.yml") + self.assertTrue(os.path.exists(vm)) + + data = yaml.safe_load(open(vm)) + # Expect application_id: 'foobar' + self.assertEqual(data.get("application_id"), "foobar") + + def test_overwrite_updates_only_application_id(self): + # Create a role with an existing vars/main.yml + initial = {"application_id": "wrong", "foo": "bar"} + role = self._make_role("desk-baz", vars_content=initial.copy()) + + run(prefix="desk-", preview=False, overwrite=True) + + path = os.path.join(role, "vars", "main.yml") + data = yaml.safe_load(open(path)) + + # application_id must be corrected... + self.assertEqual(data.get("application_id"), "baz") + # ...but other keys must survive + self.assertIn("foo", data) + self.assertEqual(data["foo"], "bar") + + def test_preview_mode_does_not_write(self): + # Create a role directory but with no vars/main.yml + role = self._make_role("desk-preview") + vm = os.path.join(role, "vars", "main.yml") + # Run in preview => no file creation + run(prefix="desk-", preview=True, overwrite=False) + self.assertFalse(os.path.exists(vm)) + +if __name__ == "__main__": + unittest.main()