mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2025-07-17 22:14:25 +02:00
Solved collection dependency bug
This commit is contained in:
parent
b2e32aacf3
commit
e174523fc6
@ -9,12 +9,12 @@ defaults_service_provider:
|
|||||||
city: "Cybertown"
|
city: "Cybertown"
|
||||||
postal_code: "00001"
|
postal_code: "00001"
|
||||||
country: "Nexusland"
|
country: "Nexusland"
|
||||||
logo: "{{ applications['asset'].url ~ '/img/logo.png' }}"
|
logo: "{{ applications['web-svc-asset'].url ~ '/img/logo.png' }}"
|
||||||
platform:
|
platform:
|
||||||
titel: "CyMaIS"
|
titel: "CyMaIS"
|
||||||
subtitel: "One login. Infinite applications."
|
subtitel: "One login. Infinite applications."
|
||||||
logo: "{{ applications['asset'].url ~ '/img/logo.png' }}"
|
logo: "{{ applications['web-svc-asset'].url ~ '/img/logo.png' }}"
|
||||||
favicon: "{{ applications['asset'].url ~ '/img/favicon.ico' }}"
|
favicon: "{{ applications['web-svc-asset'].url ~ '/img/favicon.ico' }}"
|
||||||
contact:
|
contact:
|
||||||
bluesky: >-
|
bluesky: >-
|
||||||
{{ ('@' ~ users.contact.username ~ '.' ~ domains.bluesky.api)
|
{{ ('@' ~ users.contact.username ~ '.' ~ domains.bluesky.api)
|
||||||
@ -30,4 +30,4 @@ defaults_service_provider:
|
|||||||
legal:
|
legal:
|
||||||
editorial_responsible: "Johannes Gutenberg"
|
editorial_responsible: "Johannes Gutenberg"
|
||||||
source_code: "https://github.com/kevinveenbirkenbach/cymais"
|
source_code: "https://github.com/kevinveenbirkenbach/cymais"
|
||||||
imprint: "{{web_protocol}}://{{ domains | get_domain('html') }}/imprint.html"
|
imprint: "{{web_protocol}}://{{ domains | get_domain('web-svc-html') }}/imprint.html"
|
@ -1 +1 @@
|
|||||||
application_id: bluray-player
|
application_id: desk-bluray-player
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
|
|
||||||
application_id: "chromium"
|
application_id: "desk-chromium"
|
||||||
|
|
||||||
chromium_package: "{{ 'chromium-browser' if ansible_os_family == 'Debian' else 'chromium' }}"
|
chromium_package: "{{ 'chromium-browser' if ansible_os_family == 'Debian' else 'chromium' }}"
|
@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
# Default variables for the pc-firefox role
|
# Default variables for the pc-firefox role
|
||||||
|
|
||||||
application_id: "firefox"
|
application_id: "desk-firefox"
|
||||||
|
|
||||||
# Package name for Firefox on Arch Linux
|
# Package name for Firefox on Arch Linux
|
||||||
firefox_package: firefox
|
firefox_package: firefox
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
auto_start_directory: /home/{{users.client.username}}/.config/autostart/
|
auto_start_directory: /home/{{users.client.username}}/.config/autostart/
|
||||||
application_id: gnome-caffeine
|
application_id: desk-gnome-caffeine
|
||||||
|
@ -1 +1 @@
|
|||||||
application_id: gnome-extensions
|
application_id: desk-gnome-extensions
|
||||||
|
@ -1 +1 @@
|
|||||||
application_id: gnome-terminal
|
application_id: desk-gnome-terminal
|
||||||
|
@ -1 +1 @@
|
|||||||
application_id: gnome
|
application_id: desk-gnome
|
@ -1 +1 @@
|
|||||||
application_id: gnucash
|
application_id: desk-gnucash
|
||||||
|
@ -1 +1 @@
|
|||||||
application_id: jrnl
|
application_id: desk-jrnl
|
||||||
|
@ -1 +1 @@
|
|||||||
application_id: keepassxc
|
application_id: desk-keepassxc
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
community.general.pacman:
|
community.general.pacman:
|
||||||
name:
|
name:
|
||||||
- ttf-liberation
|
- ttf-liberation
|
||||||
- "libreoffice-{{ applications.libreoffice.flavor }}"
|
- "libreoffice-{{ applications['desk-libreoffice'].flavor }}"
|
||||||
state: present
|
state: present
|
||||||
|
|
||||||
- name: install libreoffice language packages
|
- name: install libreoffice language packages
|
||||||
community.general.pacman:
|
community.general.pacman:
|
||||||
name: "libreoffice-{{ applications.libreoffice.flavor }}-{{ item }}"
|
name: "libreoffice-{{ applications['desk-libreoffice'].flavor }}-{{ item }}"
|
||||||
state: present
|
state: present
|
||||||
loop: "{{libreoffice_languages}}"
|
loop: "{{libreoffice_languages}}"
|
||||||
|
@ -1 +1 @@
|
|||||||
application_id: "libreoffice"
|
application_id: "desk-libreoffice"
|
@ -1,3 +1,3 @@
|
|||||||
user_home_directory: /home/{{users.client.username}}/
|
user_home_directory: /home/{{users.client.username}}/
|
||||||
cloud_directory: '{{user_home_directory}}Clouds/{{cloud_fqdn}}/{{users.client.username}}/'
|
cloud_directory: '{{user_home_directory}}Clouds/{{cloud_fqdn}}/{{users.client.username}}/'
|
||||||
application_id: nextcloud-client
|
application_id: desk-nextcloud-client
|
||||||
|
@ -1 +1 @@
|
|||||||
application_id: obs
|
application_id: desk-obs
|
||||||
|
@ -1 +1 @@
|
|||||||
application_id: qbittorrent
|
application_id: desk-qbittorrent
|
||||||
|
@ -2,4 +2,4 @@ retroarch_packages:
|
|||||||
- retroarch
|
- retroarch
|
||||||
- retroarch-assets-xmb
|
- retroarch-assets-xmb
|
||||||
- retroarch-assets-ozone
|
- retroarch-assets-ozone
|
||||||
application_id: retroarch
|
application_id: desk-retroarch
|
||||||
|
@ -1 +1 @@
|
|||||||
application_id: spotify
|
application_id: desk-spotify
|
||||||
|
@ -1 +1 @@
|
|||||||
application_id: ssh
|
application_id: desk-ssh
|
||||||
|
@ -1 +1 @@
|
|||||||
application_id: torbrowser
|
application_id: desk-torbrowser
|
||||||
|
@ -1 +1 @@
|
|||||||
application_id: virtual-box
|
application_id: desk-virtual-box
|
||||||
|
@ -1 +1 @@
|
|||||||
application_id: zoom
|
application_id: desk-zoom
|
||||||
|
@ -1 +1 @@
|
|||||||
application_id: java
|
application_id: dev-java
|
||||||
|
@ -1 +1 @@
|
|||||||
application_id: make
|
application_id: dev-make
|
@ -1 +1 @@
|
|||||||
application_id: hunspell
|
application_id: gen-hunspell
|
||||||
|
@ -1 +1 @@
|
|||||||
application_id: wireguard-core
|
application_id: net-wireguard-core
|
||||||
|
@ -1 +1 @@
|
|||||||
application_id: wireguard-firewalled
|
application_id: net-wireguard-firewalled
|
||||||
|
@ -1 +1 @@
|
|||||||
application_id: wireguard-plain
|
application_id: net-wireguard-plain
|
||||||
|
@ -1 +1 @@
|
|||||||
application_id: browser
|
application_id: util-desk-browser
|
||||||
|
@ -1 +1 @@
|
|||||||
application_id: design
|
application_id: util-desk-design
|
||||||
|
@ -1 +1 @@
|
|||||||
application_id: dev-arduino
|
application_id: util-desk-dev-arduino
|
||||||
|
@ -1 +1 @@
|
|||||||
application_id: dev-core
|
application_id: util-desk-dev-core
|
||||||
|
@ -1 +1 @@
|
|||||||
application_id: dev-java
|
application_id: util-desk-dev-java
|
||||||
|
@ -1 +1 @@
|
|||||||
application_id: dev-php
|
application_id: util-desk-dev-php
|
||||||
|
@ -1 +1 @@
|
|||||||
application_id: dev-python
|
application_id: util-desk-dev-python
|
@ -1 +1 @@
|
|||||||
application_id: dev-shell
|
application_id: util-desk-dev-shell
|
||||||
|
@ -1 +1 @@
|
|||||||
application_id: game-compose
|
application_id: util-desk-game-compose
|
||||||
|
@ -5,4 +5,4 @@ gamer_default_games:
|
|||||||
- gnuchess
|
- gnuchess
|
||||||
- sauerbraten
|
- sauerbraten
|
||||||
- mari0
|
- mari0
|
||||||
application_id: game-os
|
application_id: util-desk-game-os
|
||||||
|
@ -1 +1 @@
|
|||||||
application_id: game-windows
|
application_id: util-desk-game-windows
|
||||||
|
@ -1 +1 @@
|
|||||||
application_id: office-tools
|
application_id: util-desk-office-tools
|
||||||
|
@ -1 +1 @@
|
|||||||
application_id: dev-admin-network
|
application_id: util-dev-admin-network
|
||||||
|
@ -1 +1 @@
|
|||||||
application_id: dev-admin
|
application_id: util-dev-admin
|
||||||
|
@ -1 +1 @@
|
|||||||
application_id: corporate-identity
|
application_id: util-srv-corporate-identity
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
application_id: "portfolio"
|
application_id: "web-app-portfolio"
|
||||||
docker_repository_address: "https://github.com/kevinveenbirkenbach/portfolio"
|
docker_repository_address: "https://github.com/kevinveenbirkenbach/portfolio"
|
||||||
config_inventory_path: "{{ inventory_dir }}/files/{{ inventory_hostname }}/docker/portfolio/config.yaml.j2"
|
config_inventory_path: "{{ inventory_dir }}/files/{{ inventory_hostname }}/docker/portfolio/config.yaml.j2"
|
||||||
docker_repository: true
|
docker_repository: true
|
@ -1,3 +1,3 @@
|
|||||||
application_id: "asset" # Application identifier
|
application_id: "web-svc-asset" # Application identifier
|
||||||
source_directory: "{{ applications[application_id].source_directory }}/" # Source directory from which the files are coming from
|
source_directory: "{{ applications[application_id].source_directory }}/" # Source directory from which the files are coming from
|
||||||
target_directory: "{{ nginx.directories.data.files }}assets" # Directory to which the files will be copied
|
target_directory: "{{ nginx.directories.data.files }}assets" # Directory to which the files will be copied
|
||||||
|
@ -4,4 +4,6 @@ features:
|
|||||||
portfolio_iframe: true
|
portfolio_iframe: true
|
||||||
domains:
|
domains:
|
||||||
canonical:
|
canonical:
|
||||||
|
- "file.{{ primary_domain }}"
|
||||||
|
alias:
|
||||||
- "files.{{ primary_domain }}"
|
- "files.{{ primary_domain }}"
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
application_id: "file"
|
application_id: "web-svc-file"
|
||||||
domain: "{{ domains | get_domain(application_id) }}"
|
domain: "{{ domains | get_domain(application_id) }}"
|
||||||
|
@ -1,4 +1,2 @@
|
|||||||
application_id: "html"
|
application_id: "web-svc-html"
|
||||||
domain: "{{domains | get_domain(application_id)}}"
|
domain: "{{domains | get_domain(application_id)}}"
|
||||||
features:
|
|
||||||
portfolio_iframe: true # Necessary for imprint loading
|
|
@ -1 +1 @@
|
|||||||
application_id: "legal"
|
application_id: "web-svc-legal"
|
@ -48,7 +48,7 @@
|
|||||||
# The following mapping is necessary to define the exceptions for domains which are created, but which aren't used
|
# The following mapping is necessary to define the exceptions for domains which are created, but which aren't used
|
||||||
redirect_domain_mappings: "{{
|
redirect_domain_mappings: "{{
|
||||||
[] |
|
[] |
|
||||||
add_redirect_if_group('asset', domains | get_domain('asset'), domains | get_domain('file'), group_names) |
|
add_redirect_if_group('web-svc-asset', domains | get_domain('web-svc-asset'), domains | get_domain('web-svc-file'), group_names) |
|
||||||
merge_mapping(redirect_domain_mappings| default([]), 'source')
|
merge_mapping(redirect_domain_mappings| default([]), 'source')
|
||||||
}}"
|
}}"
|
||||||
|
|
||||||
|
79
tests/integration/test_dependency_application_id.py
Normal file
79
tests/integration/test_dependency_application_id.py
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
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
|
||||||
|
data = yaml.safe_load(open(vars_file, encoding='utf-8')) 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
|
||||||
|
|
||||||
|
meta = yaml.safe_load(open(meta_file, encoding='utf-8')) 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()
|
@ -18,25 +18,25 @@ class TestApplicationsIfGroupAndDeps(unittest.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.filter = FilterModule().applications_if_group_and_deps
|
self.filter = FilterModule().applications_if_group_and_deps
|
||||||
self.sample_apps = {
|
self.sample_apps = {
|
||||||
'html': {},
|
'web-svc-html': {},
|
||||||
'legal': {},
|
'web-svc-legal': {},
|
||||||
'file': {},
|
'web-svc-file': {},
|
||||||
'asset': {},
|
'web-svc-asset': {},
|
||||||
'portfolio': {},
|
'web-app-portfolio': {},
|
||||||
'corporate-identity': {},
|
'util-srv-corporate-identity': {},
|
||||||
}
|
}
|
||||||
|
|
||||||
def test_direct_group(self):
|
def test_direct_group(self):
|
||||||
result = self.filter(self.sample_apps, ['html'])
|
result = self.filter(self.sample_apps, ['web-svc-html'])
|
||||||
self.assertIn('html', result)
|
self.assertIn('web-svc-html', result)
|
||||||
self.assertNotIn('legal', result)
|
self.assertNotIn('web-svc-legal', result)
|
||||||
|
|
||||||
def test_recursive_deps(self):
|
def test_recursive_deps(self):
|
||||||
# html -> depends on none, but corporate-identity pulls in web-svc-legal -> web-svc-html -> legal
|
# html -> depends on none, but util-srv-corporate-identity pulls in web-svc-legal -> web-svc-html -> legal
|
||||||
result = self.filter(self.sample_apps, ['util-srv-corporate-identity'])
|
result = self.filter(self.sample_apps, ['util-srv-corporate-identity'])
|
||||||
self.assertIn('corporate-identity', result)
|
self.assertIn('util-srv-corporate-identity', result)
|
||||||
self.assertIn('legal', result) # via web-svc-legal
|
self.assertIn('web-svc-legal', result) # via web-svc-legal
|
||||||
self.assertIn('html', result) # via web-svc-legal -> html
|
self.assertIn('web-svc-html', result) # via web-svc-legal -> html
|
||||||
|
|
||||||
def test_real_vars_files(self):
|
def test_real_vars_files(self):
|
||||||
# load real vars to get application_id
|
# load real vars to get application_id
|
||||||
|
Loading…
x
Reference in New Issue
Block a user