#!/usr/bin/env python3 """ Script for generating Wiki page with applications list from Terraform outputs """ import json import sys import os from datetime import datetime def generate_markdown_table(apps_data): """Generates Markdown table for applications""" # Combine all applications all_apps = [] if 'proxy_apps' in apps_data: for key, app in apps_data['proxy_apps'].items(): all_apps.append({ 'key': key, 'name': app['name'], 'type': app['type'], 'url': app['url'], 'internal_url': app.get('internal_url', '-'), 'group': app['group'], 'description': app['description'], 'icon': app['icon'], 'slug': app['slug'] }) if 'oauth_apps' in apps_data: for key, app in apps_data['oauth_apps'].items(): all_apps.append({ 'key': key, 'name': app['name'], 'type': app['type'], 'url': app['url'], 'internal_url': '-', # OAuth apps don't have internal URLs 'group': app['group'], 'description': app['description'], 'icon': app['icon'], 'slug': app['slug'] }) # Sort by groups, then by name all_apps.sort(key=lambda x: (x['group'], x['name'])) # Generate Markdown markdown = [] markdown.append("# Authentik Applications") markdown.append("") markdown.append(f"*Automatically generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S UTC')}*") markdown.append("") markdown.append("## All Applications") markdown.append("") # Table markdown.append("| Icon | Name | Type | External URL | Internal URL | Group | Description |") markdown.append("|:----:|------|------|--------------|--------------|-------|-------------|") for app in all_apps: # Icon with size constraint if app['icon']: icon = f'{app[' else: icon = "📱" # External URL link external_link = f"[🔗 {app['url'].replace('https://', '').replace('http://', '')}]({app['url']})" if app.get('url') else "-" # Internal URL (only for proxy apps) internal_url = app.get('internal_url', '-') if internal_url != '-': # Shorten internal URL for display internal_display = internal_url.replace('http://', '').replace('https://', '') if len(internal_display) > 30: internal_display = internal_display[:27] + '...' internal_url = f"`{internal_display}`" description = app['description'] if app['description'] else "-" markdown.append(f"| {icon} | **{app['name']}** | {app['type']} | {external_link} | {internal_url} | {app['group']} | {description} |") markdown.append("") # Statistics proxy_count = len(apps_data.get('proxy_apps', {})) oauth_count = len(apps_data.get('oauth_apps', {})) total_count = proxy_count + oauth_count markdown.append("## Statistics") markdown.append("") markdown.append(f"- **Total applications**: {total_count}") markdown.append(f"- **Proxy applications**: {proxy_count}") markdown.append(f"- **OAuth2/OpenID applications**: {oauth_count}") markdown.append("") # Grouping by types groups = {} for app in all_apps: group = app['group'] if group not in groups: groups[group] = {'proxy': 0, 'oauth': 0} if app['type'] == 'Proxy': groups[group]['proxy'] += 1 else: groups[group]['oauth'] += 1 markdown.append("## Applications by Groups") markdown.append("") for group, counts in sorted(groups.items()): total = counts['proxy'] + counts['oauth'] markdown.append(f"- **{group}**: {total} applications (Proxy: {counts['proxy']}, OAuth: {counts['oauth']})") markdown.append("") markdown.append("---") markdown.append("*This page is automatically generated via Terraform CI/CD*") return "\n".join(markdown) def parse_terraform_output(output_data): """Parse Terraform output JSON structure""" # Check if this is a full terraform output (with value, type, sensitive fields) if isinstance(output_data, dict) and 'applications_for_wiki' in output_data: # This is full terraform output format app_output = output_data.get('applications_for_wiki', {}) if isinstance(app_output, dict) and 'value' in app_output: return app_output['value'] else: return app_output else: # This is already the value extracted return output_data def main(): if len(sys.argv) < 2: print("Usage: python3 generate-apps-wiki.py [--debug]") sys.exit(1) output_file = sys.argv[1] debug = "--debug" in sys.argv try: # Check if file exists and has content if not os.path.exists(output_file): print(f"ERROR: File {output_file} not found") sys.exit(1) file_size = os.path.getsize(output_file) if file_size == 0: print(f"ERROR: File {output_file} is empty") sys.exit(1) print(f"📄 Reading Terraform output file: {output_file} ({file_size} bytes)") # Read file content with open(output_file, 'r') as f: content = f.read() if debug: print(f"🔍 File content preview: {content[:200]}...") # Clean content - remove command line if present if content.startswith('[command]'): print("⚠️ Detected command prefix, removing...") lines = content.split('\n', 1) if len(lines) > 1: content = lines[1] if debug: print(f"🔍 Cleaned content preview: {content[:200]}...") else: print("ERROR: File contains only command line, no JSON data") sys.exit(1) # Parse JSON try: terraform_output = json.loads(content) except json.JSONDecodeError as e: print(f"ERROR: Invalid JSON in {output_file}: {e}") print(f"Content starts with: {repr(content[:100])}") # Try to find where JSON starts json_start = content.find('{') if json_start > 0: print(f"Found JSON starting at position {json_start}, retrying...") content = content[json_start:] try: terraform_output = json.loads(content) except json.JSONDecodeError as e2: print(f"ERROR: Still invalid JSON: {e2}") sys.exit(1) else: sys.exit(1) # Extract application data using helper function apps_data = parse_terraform_output(terraform_output) if not apps_data: print("ERROR: No applications data found in Terraform output") if debug: print(f"Full output structure: {json.dumps(terraform_output, indent=2)[:500]}...") sys.exit(1) # Check if we have correct structure if 'proxy_apps' not in apps_data and 'oauth_apps' not in apps_data: print("ERROR: Expected 'proxy_apps' or 'oauth_apps' in output") print(f"Available keys: {list(apps_data.keys())}") if debug and apps_data: print(f"Data structure: {json.dumps(apps_data, indent=2)[:500]}...") sys.exit(1) print(f"📊 Found {len(apps_data.get('proxy_apps', {}))} proxy apps, {len(apps_data.get('oauth_apps', {}))} oauth apps") # Generate Markdown markdown_content = generate_markdown_table(apps_data) # Write result wiki_file = "Applications.md" with open(wiki_file, 'w', encoding='utf-8') as f: f.write(markdown_content) print(f"✅ Wiki page generated: {wiki_file}") print(f"📊 Total applications: {len(apps_data.get('proxy_apps', {})) + len(apps_data.get('oauth_apps', {}))}") except Exception as e: print(f"ERROR: {e}") sys.exit(1) if __name__ == "__main__": main()