Adapted roles to new architecture

This commit is contained in:
2025-07-17 15:39:31 +02:00
parent 9469452275
commit ad449c3b6a
41 changed files with 665 additions and 101 deletions

View File

@@ -0,0 +1,118 @@
import os
import shutil
import tempfile
import yaml
import unittest
from filter_plugins.get_all_invokable_apps import get_all_invokable_apps
class TestGetAllInvokableApps(unittest.TestCase):
def setUp(self):
"""Create a temporary roles/ directory with categories.yml and some example roles."""
self.test_dir = tempfile.mkdtemp(prefix="invokable_apps_test_")
self.roles_dir = os.path.join(self.test_dir, "roles")
os.makedirs(self.roles_dir, exist_ok=True)
self.categories_file = os.path.join(self.roles_dir, "categories.yml")
# Write a categories.yml with nested invokable/non-invokable paths
categories = {
"roles": {
"web": {
"title": "Web",
"invokable": False,
"app": {
"title": "Applications",
"invokable": True
},
"svc": {
"title": "Services",
"invokable": False
}
},
"update": {
"title": "Update",
"invokable": True
},
"util": {
"title": "Utils",
"invokable": False,
"desk": {
"title": "Desktop Utils",
"invokable": True
}
}
}
}
with open(self.categories_file, 'w') as f:
yaml.safe_dump(categories, f)
# Create roles: some should match invokable paths, some shouldn't
roles = [
('web-app-nextcloud', 'web-app-nextcloud'),
('web-app-matomo', 'matomo-app'), # application_id differs
('web-svc-nginx', None), # should NOT match any invokable path
('update', None), # exact match to invokable path
('util-desk-custom', None) # matches util-desk
]
for rolename, appid in roles:
role_dir = os.path.join(self.roles_dir, rolename)
os.makedirs(os.path.join(role_dir, 'vars'), exist_ok=True)
vars_path = os.path.join(role_dir, 'vars', 'main.yml')
data = {}
if appid:
data['application_id'] = appid
with open(vars_path, 'w') as f:
yaml.safe_dump(data, f)
def tearDown(self):
"""Clean up the temporary test directory after each test."""
shutil.rmtree(self.test_dir)
def test_get_all_invokable_apps(self):
"""Should return only applications whose role paths match invokable paths."""
result = get_all_invokable_apps(
categories_file=self.categories_file,
roles_dir=self.roles_dir
)
expected = sorted([
'web-app-nextcloud', # application_id from role
'matomo-app', # application_id from role
'update', # role directory name
'util-desk-custom' # role directory name
])
self.assertEqual(sorted(result), expected)
def test_empty_when_no_invokable(self):
"""Should return an empty list if there are no invokable paths in categories.yml."""
with open(self.categories_file, 'w') as f:
yaml.safe_dump({"roles": {"foo": {"invokable": False}}}, f)
result = get_all_invokable_apps(
categories_file=self.categories_file,
roles_dir=self.roles_dir
)
self.assertEqual(result, [])
def test_empty_when_no_roles(self):
"""Should return an empty list if there are no roles, but categories.yml exists."""
shutil.rmtree(self.roles_dir)
os.makedirs(self.roles_dir, exist_ok=True)
# Recreate categories.yml after removing roles_dir
with open(self.categories_file, 'w') as f:
yaml.safe_dump({"roles": {"web": {"app": {"invokable": True}}}}, f)
result = get_all_invokable_apps(
categories_file=self.categories_file,
roles_dir=self.roles_dir
)
self.assertEqual(result, [])
def test_error_when_no_categories_file(self):
"""Should raise FileNotFoundError if categories.yml is missing."""
os.remove(self.categories_file)
with self.assertRaises(FileNotFoundError):
get_all_invokable_apps(
categories_file=self.categories_file,
roles_dir=self.roles_dir
)
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,93 @@
import unittest
import tempfile
import shutil
import os
import sys
import yaml
class TestGetEntityNameFilter(unittest.TestCase):
def setUp(self):
# Create a temporary directory for roles and categories.yml
self.temp_dir = tempfile.mkdtemp()
self.roles_dir = os.path.join(self.temp_dir, 'roles')
os.makedirs(self.roles_dir)
self.categories_file = os.path.join(self.roles_dir, 'categories.yml')
# Minimal categories.yml for tests
categories = {
'roles': {
'web': {
'app': {
'title': "Applications",
'invokable': True
},
'svc': {
'title': "Services",
'invokable': True
}
},
'util': {
'desk': {
'dev': {
'title': "Dev Utilities",
'invokable': True
}
}
},
'sys': {
'bkp': {
'title': "Backup",
'invokable': True
},
'hlth': {
'title': "Health",
'invokable': True
}
}
}
}
with open(self.categories_file, 'w', encoding='utf-8') as f:
yaml.safe_dump(categories, f, default_flow_style=False)
# Patch working directory so plugin finds the test categories.yml
self._cwd = os.getcwd()
os.chdir(self.temp_dir)
# Make sure filter_plugins directory is on sys.path
plugin_path = os.path.join(self._cwd, "filter_plugins")
if plugin_path not in sys.path and os.path.isdir(plugin_path):
sys.path.insert(0, plugin_path)
# Import plugin fresh each time
global get_entity_name
from filter_plugins.get_entity_name import get_entity_name
self.get_entity_name = get_entity_name
def tearDown(self):
os.chdir(self._cwd)
shutil.rmtree(self.temp_dir)
def test_entity_name_web_app(self):
self.assertEqual(self.get_entity_name("web-app-snipe-it"), "snipe-it")
self.assertEqual(self.get_entity_name("web-app-nextcloud"), "nextcloud")
self.assertEqual(self.get_entity_name("web-svc-file"), "file")
def test_entity_name_util_desk_dev(self):
self.assertEqual(self.get_entity_name("util-desk-dev-arduino"), "arduino")
self.assertEqual(self.get_entity_name("util-desk-dev-shell"), "shell")
def test_entity_name_sys_bkp(self):
self.assertEqual(self.get_entity_name("sys-bkp-directory-validator"), "directory-validator")
def test_entity_name_sys_hlth(self):
self.assertEqual(self.get_entity_name("sys-hlth-btrfs"), "btrfs")
def test_no_category_match(self):
# Unknown category, should return input
self.assertEqual(self.get_entity_name("foobar-role"), "foobar-role")
def test_exact_category_match(self):
self.assertEqual(self.get_entity_name("web-app"), "")
if __name__ == "__main__":
unittest.main()