mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2025-07-03 23:52:04 +02:00
Updated user logic
This commit is contained in:
parent
9cf18cae0e
commit
03db141316
10
Makefile
10
Makefile
@ -1,7 +1,7 @@
|
|||||||
ROLES_DIR := ./roles
|
ROLES_DIR := ./roles
|
||||||
APPLICATIONS_OUT := ./group_vars/all/03_applications.yml
|
APPLICATIONS_OUT := ./group_vars/all/04_applications.yml
|
||||||
APPLICATIONS_SCRIPT := ./cli/generate-applications-defaults.py
|
APPLICATIONS_SCRIPT := ./cli/generate-applications-defaults.py
|
||||||
USERS_OUT := ./group_vars/all/10_users.yml
|
USERS_OUT := ./group_vars/all/03_users.yml
|
||||||
USERS_SCRIPT := ./cli/generate_users.py
|
USERS_SCRIPT := ./cli/generate_users.py
|
||||||
INCLUDES_OUT := ./tasks/utils/docker-roles.yml
|
INCLUDES_OUT := ./tasks/utils/docker-roles.yml
|
||||||
INCLUDES_SCRIPT := ./cli/generate_playbook.py
|
INCLUDES_SCRIPT := ./cli/generate_playbook.py
|
||||||
@ -16,13 +16,11 @@ EXTRA_USERS := $(shell \
|
|||||||
|
|
||||||
build:
|
build:
|
||||||
@echo "🔧 Generating applications defaults → $(APPLICATIONS_OUT) from roles in $(ROLES_DIR)…"
|
@echo "🔧 Generating applications defaults → $(APPLICATIONS_OUT) from roles in $(ROLES_DIR)…"
|
||||||
@mkdir -p $(dir $(APPLICATIONS_OUT))
|
python3 $(USERS_SCRIPT) --roles-dir $(ROLES_DIR) --output $(USERS_OUT) --extra-users "$(EXTRA_USERS)"
|
||||||
|
@echo "✅ Users defaults written to $(USERS_OUT)\n"
|
||||||
python3 $(APPLICATIONS_SCRIPT) --roles-dir $(ROLES_DIR) --output-file $(APPLICATIONS_OUT)
|
python3 $(APPLICATIONS_SCRIPT) --roles-dir $(ROLES_DIR) --output-file $(APPLICATIONS_OUT)
|
||||||
@echo "✅ Applications defaults written to $(APPLICATIONS_OUT)\n"
|
@echo "✅ Applications defaults written to $(APPLICATIONS_OUT)\n"
|
||||||
@echo "🔧 Generating users defaults → $(USERS_OUT) from roles in $(ROLES_DIR)…"
|
@echo "🔧 Generating users defaults → $(USERS_OUT) from roles in $(ROLES_DIR)…"
|
||||||
@mkdir -p $(dir $(USERS_OUT))
|
|
||||||
python3 $(USERS_SCRIPT) --roles-dir $(ROLES_DIR) --output $(USERS_OUT) --extra-users "$(EXTRA_USERS)"
|
|
||||||
@echo "✅ Users defaults written to $(USERS_OUT)\n"
|
|
||||||
@echo "🔧 Generating Docker role includes → $(INCLUDES_OUT)…"
|
@echo "🔧 Generating Docker role includes → $(INCLUDES_OUT)…"
|
||||||
@mkdir -p $(dir $(INCLUDES_OUT))
|
@mkdir -p $(dir $(INCLUDES_OUT))
|
||||||
python3 $(INCLUDES_SCRIPT) $(ROLES_DIR) -o $(INCLUDES_OUT) -p docker-
|
python3 $(INCLUDES_SCRIPT) $(ROLES_DIR) -o $(INCLUDES_OUT) -p docker-
|
||||||
|
@ -13,20 +13,31 @@ def load_yaml_file(path):
|
|||||||
with path.open("r", encoding="utf-8") as f:
|
with path.open("r", encoding="utf-8") as f:
|
||||||
return yaml.safe_load(f) or {}
|
return yaml.safe_load(f) or {}
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description="Generate defaults_applications YAML from docker roles.")
|
parser = argparse.ArgumentParser(
|
||||||
parser.add_argument("--roles-dir", default="roles", help="Path to the roles directory (default: roles)")
|
description="Generate defaults_applications YAML from docker roles and include users meta data for each role."
|
||||||
parser.add_argument("--output-file", default="group_vars/all/03_applications.yml", help="Path to output YAML file")
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--roles-dir",
|
||||||
|
help="Path to the roles directory (default: roles)"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--output-file",
|
||||||
|
help="Path to output YAML file"
|
||||||
|
)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
cwd = Path.cwd()
|
cwd = Path.cwd()
|
||||||
roles_dir = (cwd / args.roles_dir).resolve()
|
roles_dir = (cwd / args.roles_dir).resolve()
|
||||||
output_file = (cwd / args.output_file).resolve()
|
output_file = (cwd / args.output_file).resolve()
|
||||||
|
# Ensure output directory exists
|
||||||
output_file.parent.mkdir(parents=True, exist_ok=True)
|
output_file.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
# Initialize result structure
|
||||||
result = {"defaults_applications": {}}
|
result = {"defaults_applications": {}}
|
||||||
|
|
||||||
|
# Process each role for application configs
|
||||||
for role_dir in sorted(roles_dir.iterdir()):
|
for role_dir in sorted(roles_dir.iterdir()):
|
||||||
role_name = role_dir.name
|
role_name = role_dir.name
|
||||||
vars_main = role_dir / "vars" / "main.yml"
|
vars_main = role_dir / "vars" / "main.yml"
|
||||||
@ -40,9 +51,10 @@ def main():
|
|||||||
try:
|
try:
|
||||||
application_id = vars_data.get("application_id")
|
application_id = vars_data.get("application_id")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# print the exception message
|
print(
|
||||||
print(f"Warning: failed to read application_id from {vars_data} in {vars_main}.\nException: {e}", file=sys.stderr)
|
f"Warning: failed to read application_id from {vars_main}\nException: {e}",
|
||||||
# exit with status 0
|
file=sys.stderr
|
||||||
|
)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if not application_id:
|
if not application_id:
|
||||||
@ -56,7 +68,19 @@ def main():
|
|||||||
config_data = load_yaml_file(config_file)
|
config_data = load_yaml_file(config_file)
|
||||||
if config_data:
|
if config_data:
|
||||||
result["defaults_applications"][application_id] = config_data
|
result["defaults_applications"][application_id] = config_data
|
||||||
|
users_meta_file = role_dir / "meta" / "users.yml"
|
||||||
|
transformed_users = {}
|
||||||
|
if users_meta_file.exists():
|
||||||
|
users_meta = load_yaml_file(users_meta_file)
|
||||||
|
users_data = users_meta.get("users", {})
|
||||||
|
for user, role_user_attrs in users_data.items():
|
||||||
|
transformed_users[user] = f"{{{{ users[\"{user}\"] }}}}"
|
||||||
|
|
||||||
|
# Attach transformed users under each application
|
||||||
|
if transformed_users:
|
||||||
|
result["defaults_applications"][application_id]["users"] = transformed_users
|
||||||
|
|
||||||
|
# Write out result YAML
|
||||||
with output_file.open("w", encoding="utf-8") as f:
|
with output_file.open("w", encoding="utf-8") as f:
|
||||||
yaml.dump(result, f, sort_keys=False)
|
yaml.dump(result, f, sort_keys=False)
|
||||||
|
|
||||||
@ -65,5 +89,6 @@ def main():
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
print(f"✅ Generated: {output_file}")
|
print(f"✅ Generated: {output_file}")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
@ -93,7 +93,7 @@ def build_users(defs, primary_domain, start_id, become_pwd):
|
|||||||
|
|
||||||
def load_user_defs(roles_dir):
|
def load_user_defs(roles_dir):
|
||||||
"""
|
"""
|
||||||
Scan all roles/*/vars/configuration.yml files and extract 'users:' sections.
|
Scan all roles/*/meta/users.yml files and extract 'users:' sections.
|
||||||
|
|
||||||
Raises an exception if conflicting definitions are found.
|
Raises an exception if conflicting definitions are found.
|
||||||
|
|
||||||
@ -106,7 +106,7 @@ def load_user_defs(roles_dir):
|
|||||||
Raises:
|
Raises:
|
||||||
ValueError: On invalid format or conflicting field values.
|
ValueError: On invalid format or conflicting field values.
|
||||||
"""
|
"""
|
||||||
pattern = os.path.join(roles_dir, '*/vars/configuration.yml')
|
pattern = os.path.join(roles_dir, '*/meta/users.yml')
|
||||||
files = sorted(glob.glob(pattern))
|
files = sorted(glob.glob(pattern))
|
||||||
merged = OrderedDict()
|
merged = OrderedDict()
|
||||||
|
|
||||||
@ -151,11 +151,11 @@ def dictify(data):
|
|||||||
|
|
||||||
def parse_args():
|
def parse_args():
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description='Generate a users.yml by merging all roles/*/vars/configuration.yml users sections.'
|
description='Generate a users.yml by merging all roles/*/meta/users.yml users sections.'
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--roles-dir', '-r', required=True,
|
'--roles-dir', '-r', required=True,
|
||||||
help='Directory containing roles (e.g., roles/*/vars/configuration.yml).'
|
help='Directory containing roles (e.g., roles/*/meta/users.yml).'
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--output', '-o', required=True,
|
'--output', '-o', required=True,
|
||||||
|
3
roles/docker-bluesky/meta/users.yml
Normal file
3
roles/docker-bluesky/meta/users.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
users:
|
||||||
|
administrator:
|
||||||
|
email: "administrator@{{ primary_domain }}"
|
@ -1,6 +1,3 @@
|
|||||||
users:
|
|
||||||
administrator:
|
|
||||||
email: "administrator@{{ primary_domain }}"
|
|
||||||
images:
|
images:
|
||||||
pds: "ghcr.io/bluesky-social/pds:latest"
|
pds: "ghcr.io/bluesky-social/pds:latest"
|
||||||
pds:
|
pds:
|
||||||
|
6
roles/docker-espocrm/meta/users.yml
Normal file
6
roles/docker-espocrm/meta/users.yml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
users:
|
||||||
|
administrator:
|
||||||
|
username: "administrator"
|
||||||
|
contact:
|
||||||
|
description: "General contact account"
|
||||||
|
username: "contact"
|
@ -1,11 +1,5 @@
|
|||||||
images:
|
images:
|
||||||
espocrm: "espocrm/espocrm:latest"
|
espocrm: "espocrm/espocrm:latest"
|
||||||
users:
|
|
||||||
administrator:
|
|
||||||
username: "administrator"
|
|
||||||
contact:
|
|
||||||
description: "General contact account"
|
|
||||||
username: "contact"
|
|
||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: false
|
css: false
|
||||||
|
3
roles/docker-keycloak/meta/users.yml
Normal file
3
roles/docker-keycloak/meta/users.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
users:
|
||||||
|
administrator:
|
||||||
|
username: "administrator"
|
@ -1,8 +1,5 @@
|
|||||||
images:
|
images:
|
||||||
keycloak: "quay.io/keycloak/keycloak:latest"
|
keycloak: "quay.io/keycloak/keycloak:latest"
|
||||||
users:
|
|
||||||
administrator:
|
|
||||||
username: "administrator"
|
|
||||||
import_realm: True # If True realm will be imported. If false skip.
|
import_realm: True # If True realm will be imported. If false skip.
|
||||||
credentials:
|
credentials:
|
||||||
features:
|
features:
|
||||||
|
3
roles/docker-ldap/meta/users.yml
Normal file
3
roles/docker-ldap/meta/users.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
users:
|
||||||
|
administrator:
|
||||||
|
username: "administrator"
|
@ -6,9 +6,6 @@ network:
|
|||||||
public: False # Set to true in inventory file if you want to expose the LDAP port to the internet
|
public: False # Set to true in inventory file if you want to expose the LDAP port to the internet
|
||||||
hostname: "ldap" # Hostname of the LDAP Server in the central_ldap network
|
hostname: "ldap" # Hostname of the LDAP Server in the central_ldap network
|
||||||
webinterface: "lam" # The webinterface which should be used. Possible: lam and phpldapadmin
|
webinterface: "lam" # The webinterface which should be used. Possible: lam and phpldapadmin
|
||||||
users:
|
|
||||||
administrator:
|
|
||||||
username: "administrator"
|
|
||||||
credentials:
|
credentials:
|
||||||
features:
|
features:
|
||||||
ldap: true
|
ldap: true
|
7
roles/docker-listmonk/meta/users.yml
Normal file
7
roles/docker-listmonk/meta/users.yml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
users:
|
||||||
|
administrator:
|
||||||
|
username: "administrator"
|
||||||
|
bounce:
|
||||||
|
username: "bounce"
|
||||||
|
newsletter:
|
||||||
|
username: "newsletter"
|
@ -1,12 +1,5 @@
|
|||||||
images:
|
images:
|
||||||
listmonk: "listmonk/listmonk:latest"
|
listmonk: "listmonk/listmonk:latest"
|
||||||
users:
|
|
||||||
administrator:
|
|
||||||
username: "administrator"
|
|
||||||
bounce:
|
|
||||||
username: "bounce"
|
|
||||||
newsletter:
|
|
||||||
username: "newsletter"
|
|
||||||
public_api_activated: False # Security hole. Can be used for spaming
|
public_api_activated: False # Security hole. Can be used for spaming
|
||||||
version: "latest" # Docker Image version
|
version: "latest" # Docker Image version
|
||||||
features:
|
features:
|
||||||
|
3
roles/docker-mailu/meta/users.yml
Normal file
3
roles/docker-mailu/meta/users.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
users:
|
||||||
|
administrator:
|
||||||
|
email: "administrator@{{ primary_domain }}" # Administrator Email for DNS Records
|
@ -1,7 +1,4 @@
|
|||||||
version: "2024.06" # Docker Image Version
|
version: "2024.06" # Docker Image Version
|
||||||
users:
|
|
||||||
administrator:
|
|
||||||
email: "administrator@{{ primary_domain }}" # Administrator Email for DNS Records
|
|
||||||
oidc:
|
oidc:
|
||||||
email_by_username: true # If true, then the mail is set by the username. If wrong then the OIDC user email is used
|
email_by_username: true # If true, then the mail is set by the username. If wrong then the OIDC user email is used
|
||||||
enable_user_creation: true # Users will be created if not existing
|
enable_user_creation: true # Users will be created if not existing
|
||||||
|
3
roles/docker-matrix/meta/users.yml
Normal file
3
roles/docker-matrix/meta/users.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
users:
|
||||||
|
administrator:
|
||||||
|
username: "administrator"
|
@ -1,9 +1,6 @@
|
|||||||
images:
|
images:
|
||||||
synapse: "matrixdotorg/synapse:latest"
|
synapse: "matrixdotorg/synapse:latest"
|
||||||
element: "vectorim/element-web:latest"
|
element: "vectorim/element-web:latest"
|
||||||
users:
|
|
||||||
administrator:
|
|
||||||
username: "administrator"
|
|
||||||
playbook_tags: "setup-all,start" # For the initial update use: install-all,ensure-matrix-users-created,start
|
playbook_tags: "setup-all,start" # For the initial update use: install-all,ensure-matrix-users-created,start
|
||||||
server_name: "{{primary_domain}}" # Adress for the account names etc.
|
server_name: "{{primary_domain}}" # Adress for the account names etc.
|
||||||
synapse:
|
synapse:
|
||||||
|
3
roles/docker-moodle/meta/users.yml
Normal file
3
roles/docker-moodle/meta/users.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
users:
|
||||||
|
administrator:
|
||||||
|
username: "administrator"
|
@ -1,7 +1,4 @@
|
|||||||
site_titel: "Academy on {{primary_domain}}"
|
site_titel: "Academy on {{primary_domain}}"
|
||||||
users:
|
|
||||||
administrator:
|
|
||||||
username: "administrator"
|
|
||||||
version: "4.5" # Latest LTS - Necessary for OIDC
|
version: "4.5" # Latest LTS - Necessary for OIDC
|
||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
|
5
roles/docker-nextcloud/meta/users.yml
Normal file
5
roles/docker-nextcloud/meta/users.yml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
users:
|
||||||
|
administrator:
|
||||||
|
username: "administrator"
|
||||||
|
no-reply:
|
||||||
|
username: "no-reply"
|
@ -27,11 +27,6 @@ features:
|
|||||||
ldap: true
|
ldap: true
|
||||||
oidc: true
|
oidc: true
|
||||||
central_database: true
|
central_database: true
|
||||||
users:
|
|
||||||
administrator:
|
|
||||||
username: "administrator"
|
|
||||||
no-reply:
|
|
||||||
username: "no-reply"
|
|
||||||
default_quota: '1000000000' # Quota to assign if no quota is specified in the OIDC response (bytes)
|
default_quota: '1000000000' # Quota to assign if no quota is specified in the OIDC response (bytes)
|
||||||
legacy_login_mask:
|
legacy_login_mask:
|
||||||
enabled: False # If true, then legacy login mask is shown. Otherwise just SSO
|
enabled: False # If true, then legacy login mask is shown. Otherwise just SSO
|
||||||
|
3
roles/docker-pgadmin/meta/users.yml
Normal file
3
roles/docker-pgadmin/meta/users.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
users:
|
||||||
|
administrator:
|
||||||
|
email: "administrator@{{ primary_domain }}"
|
@ -1,9 +1,6 @@
|
|||||||
version: "latest"
|
version: "latest"
|
||||||
server_mode: False # If true then the preconfigured database file is loaded. Recommended False. True is a security risk.
|
server_mode: False # If true then the preconfigured database file is loaded. Recommended False. True is a security risk.
|
||||||
master_password_required: True # Master password is required. Recommended True. False is a security risk.
|
master_password_required: True # Master password is required. Recommended True. False is a security risk.
|
||||||
users:
|
|
||||||
administrator:
|
|
||||||
email: "administrator@{{ primary_domain }}"
|
|
||||||
oauth2_proxy:
|
oauth2_proxy:
|
||||||
application: "application"
|
application: "application"
|
||||||
port: "80"
|
port: "80"
|
||||||
|
4
roles/docker-wordpress/meta/users.yml
Normal file
4
roles/docker-wordpress/meta/users.yml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
users: # Credentials
|
||||||
|
administrator: # Wordpress administrator
|
||||||
|
username: "administrator"
|
||||||
|
email: "administrator@{{ primary_domain }}"
|
@ -1,8 +1,4 @@
|
|||||||
title: "Blog" # Wordpress titel
|
title: "Blog" # Wordpress titel
|
||||||
users: # Credentials
|
|
||||||
administrator: # Wordpress administrator
|
|
||||||
username: "administrator"
|
|
||||||
email: "administrator@{{ primary_domain }}"
|
|
||||||
plugins:
|
plugins:
|
||||||
wp-discourse:
|
wp-discourse:
|
||||||
enabled: "{{ 'discourse' in group_names | lower }}"
|
enabled: "{{ 'discourse' in group_names | lower }}"
|
||||||
|
3
roles/docker-yourls/meta/users.yml
Normal file
3
roles/docker-yourls/meta/users.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
users:
|
||||||
|
administrator:
|
||||||
|
username: "administrator"
|
@ -1,6 +1,3 @@
|
|||||||
users:
|
|
||||||
administrator:
|
|
||||||
username: "administrator"
|
|
||||||
version: "latest"
|
version: "latest"
|
||||||
oauth2_proxy:
|
oauth2_proxy:
|
||||||
application: "application"
|
application: "application"
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
users:
|
|
||||||
sld:
|
|
||||||
description: "Auto Generated Account to reserve the SLD"
|
|
||||||
username: "{{ primary_domain.split('.')[0] }}"
|
|
||||||
tld:
|
|
||||||
description: "Auto Generated Account to reserve the TLD"
|
|
||||||
username: "{{ primary_domain.split('.')[1] }}"
|
|
@ -1,5 +1,11 @@
|
|||||||
# Reserved usernames
|
# Reserved usernames
|
||||||
users:
|
users:
|
||||||
|
sld:
|
||||||
|
description: "Auto Generated Account to reserve the SLD"
|
||||||
|
username: "{{ primary_domain.split('.')[0] }}"
|
||||||
|
tld:
|
||||||
|
description: "Auto Generated Account to reserve the TLD"
|
||||||
|
username: "{{ primary_domain.split('.')[1] }}"
|
||||||
root:
|
root:
|
||||||
username: root
|
username: root
|
||||||
uid: 0
|
uid: 0
|
@ -12,7 +12,7 @@ class TestDomainUniqueness(unittest.TestCase):
|
|||||||
and assert that no domain appears more than once.
|
and assert that no domain appears more than once.
|
||||||
"""
|
"""
|
||||||
repo_root = Path(__file__).resolve().parents[2]
|
repo_root = Path(__file__).resolve().parents[2]
|
||||||
yaml_file = repo_root / 'group_vars' / 'all' / '03_applications.yml'
|
yaml_file = repo_root / 'group_vars' / 'all' / '04_applications.yml'
|
||||||
|
|
||||||
# Generate the file if it doesn't exist
|
# Generate the file if it doesn't exist
|
||||||
if not yaml_file.exists():
|
if not yaml_file.exists():
|
||||||
|
@ -8,7 +8,7 @@ class TestOAuth2ProxyPorts(unittest.TestCase):
|
|||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
# Set up root paths and load oauth2_proxy ports mapping
|
# Set up root paths and load oauth2_proxy ports mapping
|
||||||
cls.ROOT = Path(__file__).parent.parent.parent.resolve()
|
cls.ROOT = Path(__file__).parent.parent.parent.resolve()
|
||||||
cls.PORTS_FILE = cls.ROOT / 'group_vars' / 'all' / '08_ports.yml'
|
cls.PORTS_FILE = cls.ROOT / 'group_vars' / 'all' / '09_ports.yml'
|
||||||
with cls.PORTS_FILE.open() as f:
|
with cls.PORTS_FILE.open() as f:
|
||||||
data = yaml.safe_load(f)
|
data = yaml.safe_load(f)
|
||||||
cls.oauth2_ports = (
|
cls.oauth2_ports = (
|
||||||
@ -50,7 +50,7 @@ class TestOAuth2ProxyPorts(unittest.TestCase):
|
|||||||
if app_id not in self.oauth2_ports:
|
if app_id not in self.oauth2_ports:
|
||||||
self.fail(
|
self.fail(
|
||||||
f"Missing oauth2_proxy port mapping for application '{app_id}' "
|
f"Missing oauth2_proxy port mapping for application '{app_id}' "
|
||||||
f"in group_vars/all/08_ports.yml"
|
f"in group_vars/all/09_ports.yml"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
65
tests/unit/test_generate_applications_defaults_users.py
Normal file
65
tests/unit/test_generate_applications_defaults_users.py
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import os
|
||||||
|
import unittest
|
||||||
|
import tempfile
|
||||||
|
import shutil
|
||||||
|
import yaml
|
||||||
|
from pathlib import Path
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
class TestGenerateDefaultApplicationsUsers(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
# Setup temporary roles directory
|
||||||
|
self.temp_dir = Path(tempfile.mkdtemp())
|
||||||
|
self.roles_dir = self.temp_dir / "roles"
|
||||||
|
self.roles_dir.mkdir()
|
||||||
|
|
||||||
|
# Sample role with users meta
|
||||||
|
self.role = self.roles_dir / "docker-app-with-users"
|
||||||
|
(self.role / "vars").mkdir(parents=True)
|
||||||
|
(self.role / "meta").mkdir(parents=True)
|
||||||
|
|
||||||
|
# Write application_id and configuration
|
||||||
|
(self.role / "vars" / "main.yml").write_text("application_id: app_with_users\n")
|
||||||
|
(self.role / "vars" / "configuration.yml").write_text("setting: value\n")
|
||||||
|
|
||||||
|
# Write users meta
|
||||||
|
users_meta = {
|
||||||
|
'users': {
|
||||||
|
'alice': {'uid': 2001, 'gid': 2001},
|
||||||
|
'bob': {'uid': 2002, 'gid': 2002}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
with (self.role / "meta" / "users.yml").open('w', encoding='utf-8') as f:
|
||||||
|
yaml.dump(users_meta, f)
|
||||||
|
|
||||||
|
# Output file path
|
||||||
|
self.output_file = self.temp_dir / "output.yml"
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
shutil.rmtree(self.temp_dir)
|
||||||
|
|
||||||
|
def test_users_injection(self):
|
||||||
|
"""
|
||||||
|
When a users.yml exists with defined users, the script should inject a 'users'
|
||||||
|
mapping in the generated YAML, mapping each username to a Jinja2 reference.
|
||||||
|
"""
|
||||||
|
script_path = Path(__file__).resolve().parents[2] / "cli" / "generate-applications-defaults.py"
|
||||||
|
result = subprocess.run([
|
||||||
|
"python3", str(script_path),
|
||||||
|
"--roles-dir", str(self.roles_dir),
|
||||||
|
"--output-file", str(self.output_file)
|
||||||
|
], capture_output=True, text=True)
|
||||||
|
self.assertEqual(result.returncode, 0, msg=result.stderr)
|
||||||
|
data = yaml.safe_load(self.output_file.read_text())
|
||||||
|
|
||||||
|
apps = data.get('defaults_applications', {})
|
||||||
|
# Only the app with users should be present
|
||||||
|
self.assertIn('app_with_users', apps)
|
||||||
|
|
||||||
|
# 'users' section should be present and correct
|
||||||
|
users_map = apps['app_with_users']['users']
|
||||||
|
expected = {'alice': '{{ users["alice"] }}', 'bob': '{{ users["bob"] }}'}
|
||||||
|
self.assertEqual(users_map, expected)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
@ -23,7 +23,7 @@ class TestGenerateDefaultApplications(unittest.TestCase):
|
|||||||
(self.sample_role / "vars" / "configuration.yml").write_text("foo: bar\nbaz: 123\n")
|
(self.sample_role / "vars" / "configuration.yml").write_text("foo: bar\nbaz: 123\n")
|
||||||
|
|
||||||
# Output file path
|
# Output file path
|
||||||
self.output_file = self.temp_dir / "group_vars" / "all" / "03_applications.yml"
|
self.output_file = self.temp_dir / "group_vars" / "all" / "04_applications.yml"
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
shutil.rmtree(self.temp_dir)
|
shutil.rmtree(self.temp_dir)
|
||||||
|
@ -114,18 +114,18 @@ class TestGenerateUsers(unittest.TestCase):
|
|||||||
# create temp roles structure
|
# create temp roles structure
|
||||||
tmp = tempfile.mkdtemp()
|
tmp = tempfile.mkdtemp()
|
||||||
try:
|
try:
|
||||||
os.makedirs(os.path.join(tmp, 'role1/vars'))
|
os.makedirs(os.path.join(tmp, 'role1/meta'))
|
||||||
os.makedirs(os.path.join(tmp, 'role2/vars'))
|
os.makedirs(os.path.join(tmp, 'role2/meta'))
|
||||||
# role1 defines user x
|
# role1 defines user x
|
||||||
with open(os.path.join(tmp, 'role1/vars/configuration.yml'), 'w') as f:
|
with open(os.path.join(tmp, 'role1/meta/users.yml'), 'w') as f:
|
||||||
yaml.safe_dump({'users': {'x': {'email': 'x@a'}}}, f)
|
yaml.safe_dump({'users': {'x': {'email': 'x@a'}}}, f)
|
||||||
# role2 defines same user x with same value
|
# role2 defines same user x with same value
|
||||||
with open(os.path.join(tmp, 'role2/vars/configuration.yml'), 'w') as f:
|
with open(os.path.join(tmp, 'role2/meta/users.yml'), 'w') as f:
|
||||||
yaml.safe_dump({'users': {'x': {'email': 'x@a'}}}, f)
|
yaml.safe_dump({'users': {'x': {'email': 'x@a'}}}, f)
|
||||||
defs = generate_users.load_user_defs(tmp)
|
defs = generate_users.load_user_defs(tmp)
|
||||||
self.assertIn('x', defs)
|
self.assertIn('x', defs)
|
||||||
# now conflict definition
|
# now conflict definition
|
||||||
with open(os.path.join(tmp, 'role2/vars/configuration.yml'), 'w') as f:
|
with open(os.path.join(tmp, 'role2/meta/users.yml'), 'w') as f:
|
||||||
yaml.safe_dump({'users': {'x': {'email': 'x@b'}}}, f)
|
yaml.safe_dump({'users': {'x': {'email': 'x@b'}}}, f)
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
generate_users.load_user_defs(tmp)
|
generate_users.load_user_defs(tmp)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user