mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2025-07-18 06:24:25 +02:00
Fixed desk roles application ids
This commit is contained in:
parent
e794da47e2
commit
3c3739c234
@ -1,64 +1,83 @@
|
|||||||
#!/usr/bin/env python3
|
#!/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 argparse
|
||||||
import os
|
import sys
|
||||||
|
import yaml
|
||||||
from pathlib import Path
|
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():
|
def main():
|
||||||
parser = argparse.ArgumentParser(
|
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(
|
parser.add_argument(
|
||||||
"--prefix",
|
"--prefix", required=True,
|
||||||
required=True,
|
help="Role name prefix to filter (e.g. 'web-', 'svc-', 'desk-')"
|
||||||
help="Role-name prefix to scan for (e.g. 'desk-')"
|
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--preview",
|
"--preview", action="store_true",
|
||||||
action="store_true",
|
help="Show what would be done without making changes"
|
||||||
help="If set, only 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()
|
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
|
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():
|
if not roles_dir.is_dir():
|
||||||
print(f"Error: roles directory not found at {roles_dir}")
|
print(f"Roles directory not found: {roles_dir}", file=sys.stderr)
|
||||||
return
|
sys.exit(1)
|
||||||
|
|
||||||
missing = []
|
|
||||||
for role in sorted(roles_dir.iterdir()):
|
for role in sorted(roles_dir.iterdir()):
|
||||||
if not role.is_dir():
|
if role.is_dir():
|
||||||
continue
|
process_role(role, args.prefix, args.preview, args.overwrite)
|
||||||
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 __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
1
roles/desk-bluray-player/vars/main.yml
Normal file
1
roles/desk-bluray-player/vars/main.yml
Normal file
@ -0,0 +1 @@
|
|||||||
|
application_id: bluray-player
|
1
roles/desk-docker/vars/main.yml
Normal file
1
roles/desk-docker/vars/main.yml
Normal file
@ -0,0 +1 @@
|
|||||||
|
application_id: docker
|
1
roles/desk-git/vars/main.yml
Normal file
1
roles/desk-git/vars/main.yml
Normal file
@ -0,0 +1 @@
|
|||||||
|
application_id: git
|
@ -1 +1,2 @@
|
|||||||
auto_start_directory: "/home/{{users.client.username}}/.config/autostart/"
|
auto_start_directory: /home/{{users.client.username}}/.config/autostart/
|
||||||
|
application_id: gnome-caffeine
|
||||||
|
@ -1 +1 @@
|
|||||||
application_id: "gnome"
|
application_id: gnome-extensions
|
||||||
|
1
roles/desk-gnome-terminal/vars/main.yml
Normal file
1
roles/desk-gnome-terminal/vars/main.yml
Normal file
@ -0,0 +1 @@
|
|||||||
|
application_id: gnome-terminal
|
1
roles/desk-gnucash/vars/main.yml
Normal file
1
roles/desk-gnucash/vars/main.yml
Normal file
@ -0,0 +1 @@
|
|||||||
|
application_id: gnucash
|
1
roles/desk-jrnl/vars/main.yml
Normal file
1
roles/desk-jrnl/vars/main.yml
Normal file
@ -0,0 +1 @@
|
|||||||
|
application_id: jrnl
|
1
roles/desk-keepassxc/vars/main.yml
Normal file
1
roles/desk-keepassxc/vars/main.yml
Normal file
@ -0,0 +1 @@
|
|||||||
|
application_id: keepassxc
|
@ -1,2 +1,3 @@
|
|||||||
user_home_directory: "/home/{{users.client.username}}/" # Home directory of the user
|
user_home_directory: /home/{{users.client.username}}/
|
||||||
cloud_directory: "{{user_home_directory}}Clouds/{{cloud_fqdn}}/{{users.client.username}}/" # Folder which contains the cloud data
|
cloud_directory: '{{user_home_directory}}Clouds/{{cloud_fqdn}}/{{users.client.username}}/'
|
||||||
|
application_id: nextcloud-client
|
||||||
|
1
roles/desk-obs/vars/main.yml
Normal file
1
roles/desk-obs/vars/main.yml
Normal file
@ -0,0 +1 @@
|
|||||||
|
application_id: obs
|
1
roles/desk-qbittorrent/vars/main.yml
Normal file
1
roles/desk-qbittorrent/vars/main.yml
Normal file
@ -0,0 +1 @@
|
|||||||
|
application_id: qbittorrent
|
@ -1,4 +1,5 @@
|
|||||||
retroarch_packages:
|
retroarch_packages:
|
||||||
- retroarch
|
- retroarch
|
||||||
- retroarch-assets-xmb
|
- retroarch-assets-xmb
|
||||||
- retroarch-assets-ozone
|
- retroarch-assets-ozone
|
||||||
|
application_id: retroarch
|
||||||
|
1
roles/desk-spotify/vars/main.yml
Normal file
1
roles/desk-spotify/vars/main.yml
Normal file
@ -0,0 +1 @@
|
|||||||
|
application_id: spotify
|
1
roles/desk-ssh/vars/main.yml
Normal file
1
roles/desk-ssh/vars/main.yml
Normal file
@ -0,0 +1 @@
|
|||||||
|
application_id: ssh
|
1
roles/desk-torbrowser/vars/main.yml
Normal file
1
roles/desk-torbrowser/vars/main.yml
Normal file
@ -0,0 +1 @@
|
|||||||
|
application_id: torbrowser
|
1
roles/desk-virtual-box/vars/main.yml
Normal file
1
roles/desk-virtual-box/vars/main.yml
Normal file
@ -0,0 +1 @@
|
|||||||
|
application_id: virtual-box
|
1
roles/desk-zoom/vars/main.yml
Normal file
1
roles/desk-zoom/vars/main.yml
Normal file
@ -0,0 +1 @@
|
|||||||
|
application_id: zoom
|
81
tests/unit/cli/test_ensure_vars_main.py
Normal file
81
tests/unit/cli/test_ensure_vars_main.py
Normal file
@ -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()
|
Loading…
x
Reference in New Issue
Block a user