Optimized logic for database backups and integrated test to verify that database feature is used correct

This commit is contained in:
Kevin Veen-Birkenbach 2025-08-10 15:06:37 +02:00
parent e9ef62b95d
commit 149c563831
No known key found for this signature in database
GPG Key ID: 44D8F11FD62F878E
11 changed files with 100 additions and 32 deletions

View File

@ -16,4 +16,4 @@
when: applications | get_app_conf(application_id, 'features.central_database', False)
- name: "For '{{ application_id }}': Add Entry for Backup Procedure"
include_tasks: "{{ playbook_dir }}/roles/sys-bkp-docker-2-loc/tasks/seed-database-to-backup.yml"
include_tasks: "{{ playbook_dir }}/roles/sys-bkp-docker-2-loc/tasks/03_seed-database-to-backup.yml"

View File

@ -2,7 +2,7 @@
application_id: "svc-prx-openresty"
# Deactivate Database for openresty
database_type: false
database_enabled: false
# Openresty
openresty_image: "openresty/openresty"

View File

@ -0,0 +1 @@
database_enabled: "{{ database_type | default('') | bool }}" # Enables the database backup

View File

@ -0,0 +1,17 @@
- block:
- name: "pkgmgr install {{ bkp_docker_to_local_pkg }}"
include_role:
name: pkgmgr-install
vars:
package_name: "{{ bkp_docker_to_local_pkg }}"
- name: "Retrieve {{ bkp_docker_to_local_pkg }} path from pkgmgr"
command: "pkgmgr path {{ bkp_docker_to_local_pkg }}"
register: pkgmgr_output
changed_when: false
- name: Set fact for backup_docker_to_local_folder
set_fact:
backup_docker_to_local_folder: "{{ pkgmgr_output.stdout }}/"
changed_when: false
when: backup_docker_to_local_folder is not defined

View File

@ -1,4 +1,5 @@
# This file is also used by web-app-matrix
- include_tasks: 01_pkgmgr_routines.yml
when: backup_docker_to_local_folder is not defined
- name: "Display all database variables"
debug:

View File

@ -1,22 +1,9 @@
- block:
- name: "pkgmgr install"
include_role:
name: pkgmgr-install
vars:
package_name: "{{ bkp_docker_to_local_pkg }}"
- name: "Retrieve {{ bkp_docker_to_local_pkg }} path from pkgmgr"
command: "pkgmgr path {{ bkp_docker_to_local_pkg }}"
register: pkgmgr_output
changed_when: false
- name: Set fact for backup_docker_to_local_folder
set_fact:
backup_docker_to_local_folder: "{{ pkgmgr_output.stdout }}/"
changed_when: false
- include_tasks: 01_pkgmgr_routines.yml
when: backup_docker_to_local_folder is not defined
- name: "reset (if enabled)"
include_tasks: reset.yml
include_tasks: 02_reset.yml
when: mode_reset | bool
- name: configure sys-bkp-docker-2-loc-everything.infinito.service
@ -41,15 +28,12 @@
vars:
on_calendar: "{{on_calendar_backup_docker_to_local}}"
- name: run the backup_docker_to_local tasks once
set_fact:
run_once_sys_bkp_docker_2_loc: true
- include_tasks: "{{ playbook_dir }}/tasks/utils/load_handlers.yml"
when:
- run_once_sys_bkp_docker_2_loc is not defined
- database_type is defined and database_type
- database_enabled | bool
- name: "include seed-database-to-backup.yml"
include_tasks: seed-database-to-backup.yml
- name: "include 03_seed-database-to-backup.yml"
include_tasks: 03_seed-database-to-backup.yml
when:
- database_type is defined and database_type
- database_enabled | bool

View File

@ -7,7 +7,7 @@ features:
# @todo fix this
ldap: false
oidc: true
central_database: false
central_database: false # Propably required for backup routines
logout: true
server:
csp:
@ -20,3 +20,9 @@ server:
canonical:
- "meet.{{ primary_domain }}"
credentials: {}
docker:
services:
database:
# This is set to true to pass integration test, doesn't have any other function
enabled: true

View File

@ -3,8 +3,8 @@
include_role:
name: cmp-docker-proxy
- name: "include seed-database-to-backup.yml"
include_tasks: "{{ playbook_dir }}/roles/sys-bkp-docker-2-loc/tasks/seed-database-to-backup.yml"
- name: "include 03_seed-database-to-backup.yml"
include_tasks: "{{ playbook_dir }}/roles/sys-bkp-docker-2-loc/tasks/03_seed-database-to-backup.yml"
- name: configure websocket_upgrade.conf
copy:

View File

@ -9,5 +9,5 @@
name: svc-db-postgres
when: applications | get_app_conf(application_id, 'features.central_database', False)
- name: "include seed-database-to-backup.yml"
include_tasks: "{{ playbook_dir }}/roles/sys-bkp-docker-2-loc/tasks/seed-database-to-backup.yml"
- name: "include 03_seed-database-to-backup.yml"
include_tasks: "{{ playbook_dir }}/roles/sys-bkp-docker-2-loc/tasks/03_seed-database-to-backup.yml"

View File

@ -0,0 +1,59 @@
# tests/integration/test_central_database_config.py
import unittest
from pathlib import Path
import yaml
def load_yaml(path: Path):
"""Load a YAML file and return dict ({} if missing/empty)."""
if not path.exists():
return {}
with path.open("r", encoding="utf-8") as f:
return yaml.safe_load(f) or {}
class TestCentralDatabaseConfig(unittest.TestCase):
def test_central_database_feature_requires_database_service(self):
"""
If features.central_database is defined in either vars/main.yml or config/main.yml,
then config/main.yml must define docker.services.database.
"""
repo_root = Path(__file__).resolve().parents[2]
roles_dir = repo_root / "roles"
violations = []
for role_dir in sorted(roles_dir.glob("*")):
if not role_dir.is_dir():
continue
vars_file = role_dir / "vars" / "main.yml"
cfg_file = role_dir / "config" / "main.yml"
vars_data = load_yaml(vars_file)
cfg_data = load_yaml(cfg_file)
# Check if the feature key is defined in either file (value is irrelevant).
vars_features = vars_data.get("features", {}) if isinstance(vars_data.get("features"), dict) else {}
cfg_features = cfg_data.get("features", {}) if isinstance(cfg_data.get("features"), dict) else {}
central_defined = ("central_database" in vars_features) or ("central_database" in cfg_features)
if not central_defined:
continue
# Require docker.services.database in config/main.yml
docker = cfg_data.get("docker", {})
services = docker.get("services", {}) if isinstance(docker, dict) else {}
if "database" not in services:
violations.append(role_dir.name)
if violations:
self.fail(
"The 'central_database' feature is only available if 'docker.services.database' "
"is defined in config/main.yml. Missing in roles:\n"
+ "\n".join(f"- {name}" for name in violations)
)
if __name__ == "__main__":
unittest.main()