mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2025-08-29 15:06:26 +02:00
General code optimations and peertube optimation
This commit is contained in:
@@ -1,79 +0,0 @@
|
||||
import os
|
||||
import argparse
|
||||
import yaml
|
||||
|
||||
def find_roles(roles_dir, prefix=None):
|
||||
"""
|
||||
Yield absolute paths of role directories under roles_dir.
|
||||
Only include roles whose directory name starts with prefix (if given) and contain vars/main.yml.
|
||||
"""
|
||||
for entry in os.listdir(roles_dir):
|
||||
if prefix and not entry.startswith(prefix):
|
||||
continue
|
||||
path = os.path.join(roles_dir, entry)
|
||||
vars_file = os.path.join(path, 'vars', 'main.yml')
|
||||
if os.path.isdir(path) and os.path.isfile(vars_file):
|
||||
yield path, vars_file
|
||||
|
||||
|
||||
def load_application_id(vars_file):
|
||||
"""
|
||||
Load the vars/main.yml and return the value of application_id key.
|
||||
Returns None if not found.
|
||||
"""
|
||||
with open(vars_file, 'r') as f:
|
||||
data = yaml.safe_load(f) or {}
|
||||
return data.get('application_id')
|
||||
|
||||
|
||||
def generate_playbook_entries(roles_dir, prefix=None):
|
||||
entries = []
|
||||
for role_path, vars_file in find_roles(roles_dir, prefix):
|
||||
app_id = load_application_id(vars_file)
|
||||
if not app_id:
|
||||
continue
|
||||
# Derive role name from directory name
|
||||
role_name = os.path.basename(role_path)
|
||||
# entry text
|
||||
entry = (
|
||||
f"- name: setup {app_id}\n"
|
||||
f" when: (\"{app_id}\" in group_names)\n"
|
||||
f" include_role:\n"
|
||||
f" name: {role_name}\n"
|
||||
)
|
||||
entries.append(entry)
|
||||
return entries
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Generate an Ansible playbook include file from Docker roles and application_ids.'
|
||||
)
|
||||
parser.add_argument(
|
||||
'roles_dir',
|
||||
help='Path to directory containing role folders'
|
||||
)
|
||||
parser.add_argument(
|
||||
'-p', '--prefix',
|
||||
help='Only include roles whose names start with this prefix (e.g. docker-, client-)',
|
||||
default=None
|
||||
)
|
||||
parser.add_argument(
|
||||
'-o', '--output',
|
||||
help='Output file path (default: stdout)',
|
||||
default=None
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
entries = generate_playbook_entries(args.roles_dir, args.prefix)
|
||||
output = ''.join(entries)
|
||||
|
||||
if args.output:
|
||||
with open(args.output, 'w') as f:
|
||||
f.write(output)
|
||||
print(f"Playbook entries written to {args.output}")
|
||||
else:
|
||||
print(output)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
140
cli/generate_playbook.py
Normal file
140
cli/generate_playbook.py
Normal file
@@ -0,0 +1,140 @@
|
||||
import os
|
||||
import argparse
|
||||
import yaml
|
||||
|
||||
|
||||
def find_roles(roles_dir, prefix=None):
|
||||
"""
|
||||
Yield absolute paths of role directories under roles_dir.
|
||||
Only include roles whose directory name starts with prefix (if given) and contain meta/main.yml.
|
||||
"""
|
||||
for entry in os.listdir(roles_dir):
|
||||
if prefix and not entry.startswith(prefix):
|
||||
continue
|
||||
path = os.path.join(roles_dir, entry)
|
||||
meta_file = os.path.join(path, 'meta', 'main.yml')
|
||||
if os.path.isdir(path) and os.path.isfile(meta_file):
|
||||
yield path, meta_file
|
||||
|
||||
|
||||
def load_role_order(meta_file):
|
||||
"""
|
||||
Load the meta/main.yml and return the role_run_order field.
|
||||
Returns a dict with 'before' and 'after' keys. Defaults to empty lists if not found.
|
||||
"""
|
||||
with open(meta_file, 'r') as f:
|
||||
data = yaml.safe_load(f) or {}
|
||||
run_order = data.get('role_run_order', {})
|
||||
before = run_order.get('before', [])
|
||||
after = run_order.get('after', [])
|
||||
|
||||
# If "all" is in before or after, treat it as a special value
|
||||
if "all" in before:
|
||||
before.remove("all")
|
||||
before.insert(0, "all") # Treat "all" as the first item
|
||||
if "all" in after:
|
||||
after.remove("all")
|
||||
after.append("all") # Treat "all" as the last item
|
||||
|
||||
return {
|
||||
'before': before,
|
||||
'after': after
|
||||
}
|
||||
|
||||
|
||||
def sort_roles_by_order(roles_dir, prefix=None):
|
||||
roles = []
|
||||
|
||||
# Collect roles and their before/after dependencies
|
||||
for role_path, meta_file in find_roles(roles_dir, prefix):
|
||||
run_order = load_role_order(meta_file)
|
||||
role_name = os.path.basename(role_path)
|
||||
roles.append({
|
||||
'role_name': role_name,
|
||||
'before': run_order['before'],
|
||||
'after': run_order['after'],
|
||||
'path': role_path
|
||||
})
|
||||
|
||||
# Now sort the roles based on before/after relationships
|
||||
sorted_roles = []
|
||||
unresolved_roles = roles[:]
|
||||
|
||||
# First, place roles with "before: all" at the start
|
||||
roles_with_before_all = [role for role in unresolved_roles if "all" in role['before']]
|
||||
sorted_roles.extend(roles_with_before_all)
|
||||
unresolved_roles = [role for role in unresolved_roles if "all" not in role['before']]
|
||||
|
||||
while unresolved_roles:
|
||||
# Find roles with no dependencies in 'before'
|
||||
ready_roles = [role for role in unresolved_roles if not any(dep in [r['role_name'] for r in unresolved_roles] for dep in role['before'])]
|
||||
|
||||
if not ready_roles:
|
||||
raise ValueError("Circular dependency detected in 'before'/'after' fields")
|
||||
|
||||
for role in ready_roles:
|
||||
sorted_roles.append(role)
|
||||
unresolved_roles.remove(role)
|
||||
|
||||
# Remove from the 'before' lists of remaining roles
|
||||
for r in unresolved_roles:
|
||||
r['before'] = [dep for dep in r['before'] if dep != role['role_name']]
|
||||
|
||||
# Finally, place roles with "after: all" at the end
|
||||
roles_with_after_all = [role for role in unresolved_roles if "all" in role['after']]
|
||||
sorted_roles.extend(roles_with_after_all)
|
||||
unresolved_roles = [role for role in unresolved_roles if "all" not in role['after']]
|
||||
|
||||
return sorted_roles
|
||||
|
||||
|
||||
def generate_playbook_entries(roles_dir, prefix=None):
|
||||
entries = []
|
||||
sorted_roles = sort_roles_by_order(roles_dir, prefix)
|
||||
|
||||
for role in sorted_roles:
|
||||
# entry text
|
||||
entry = (
|
||||
f"- name: setup {role['role_name']}\n"
|
||||
f" when: (\"{role['role_name']}\" in group_names)\n"
|
||||
f" include_role:\n"
|
||||
f" name: {role['role_name']}\n"
|
||||
)
|
||||
entries.append(entry)
|
||||
|
||||
return entries
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Generate an Ansible playbook include file from Docker roles and application_ids, sorted by role_run_order.'
|
||||
)
|
||||
parser.add_argument(
|
||||
'roles_dir',
|
||||
help='Path to directory containing role folders'
|
||||
)
|
||||
parser.add_argument(
|
||||
'-p', '--prefix',
|
||||
help='Only include roles whose names start with this prefix (e.g. docker-, client-)',
|
||||
default=None
|
||||
)
|
||||
parser.add_argument(
|
||||
'-o', '--output',
|
||||
help='Output file path (default: stdout)',
|
||||
default=None
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
entries = generate_playbook_entries(args.roles_dir, args.prefix)
|
||||
output = ''.join(entries)
|
||||
|
||||
if args.output:
|
||||
with open(args.output, 'w') as f:
|
||||
f.write(output)
|
||||
print(f"Playbook entries written to {args.output}")
|
||||
else:
|
||||
print(output)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Reference in New Issue
Block a user