computer-playbook/tests/integration/test_dependency_application_id.py

83 lines
3.0 KiB
Python

import os
import unittest
import yaml
import glob
class TestDependencyApplicationId(unittest.TestCase):
def test_application_id_matches_folder_for_dependent_roles(self):
"""
For any role A that depends on role B (listed under A/meta/main.yml → dependencies),
if both A and B have vars/main.yml with application_id defined,
then application_id must equal the role's folder name for both.
"""
base_dir = os.path.dirname(__file__)
roles_dir = os.path.abspath(os.path.join(base_dir, '..', '..', 'roles'))
violations = []
# Helper to load application_id if present
def load_app_id(role_path):
vars_file = os.path.join(role_path, 'vars', 'main.yml')
if not os.path.isfile(vars_file):
return None
with open(vars_file, encoding='utf-8') as f:
data = yaml.safe_load(f) or {}
return data.get('application_id')
# Iterate all roles
for role_path in glob.glob(os.path.join(roles_dir, '*')):
if not os.path.isdir(role_path):
continue
role_name = os.path.basename(role_path)
meta_file = os.path.join(role_path, 'meta', 'main.yml')
if not os.path.isfile(meta_file):
continue
with open(meta_file, encoding='utf-8') as f:
meta = yaml.safe_load(f) or {}
deps = meta.get('dependencies', [])
if not isinstance(deps, list):
continue
# collect just the role names this role depends on
dep_names = []
for item in deps:
if isinstance(item, dict) and 'role' in item:
dep_names.append(item['role'])
elif isinstance(item, str):
dep_names.append(item)
# load application_id for this role once
app_id_role = load_app_id(role_path)
for dep_name in dep_names:
dep_path = os.path.join(roles_dir, dep_name)
if not os.path.isdir(dep_path):
continue
app_id_dep = load_app_id(dep_path)
# only check if both app_ids are defined
if app_id_role is None or app_id_dep is None:
continue
# check role A
if app_id_role != role_name:
violations.append(
f"{role_name}: application_id='{app_id_role}' ≠ folder name '{role_name}'"
)
# check role B
if app_id_dep != dep_name:
violations.append(
f"{dep_name}: application_id='{app_id_dep}' ≠ folder name '{dep_name}'"
)
if violations:
self.fail(
"application_id mismatches between role folder names and vars/main.yml:\n"
+ "\n".join(violations)
)
if __name__ == '__main__':
unittest.main()