Added wiki generator
All checks were successful
Update Kubernetes Services Wiki / Generate and Update K8s Wiki (push) Successful in 9s
All checks were successful
Update Kubernetes Services Wiki / Generate and Update K8s Wiki (push) Successful in 9s
This commit is contained in:
298
.gitea/scripts/generate-k8s-wiki.py
Normal file
298
.gitea/scripts/generate-k8s-wiki.py
Normal file
@@ -0,0 +1,298 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Script for generating Wiki page with Kubernetes services from k8s/ directory
|
||||
"""
|
||||
|
||||
import os
|
||||
import yaml
|
||||
import json
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from collections import defaultdict
|
||||
|
||||
class K8sService:
|
||||
def __init__(self, name, category, path):
|
||||
self.name = name
|
||||
self.category = category
|
||||
self.path = path
|
||||
self.namespace = None
|
||||
self.deployment_type = "Unknown"
|
||||
self.helm_charts = []
|
||||
self.services = []
|
||||
self.ingresses = []
|
||||
self.external_secrets = []
|
||||
self.deployments = []
|
||||
self.pvcs = []
|
||||
self.argo_app = None
|
||||
self.files = []
|
||||
|
||||
def __repr__(self):
|
||||
return f"K8sService({self.name}, {self.deployment_type})"
|
||||
|
||||
def parse_yaml_file(filepath):
|
||||
"""Parse YAML file and return content"""
|
||||
try:
|
||||
with open(filepath, 'r') as f:
|
||||
# Load all documents in the file
|
||||
docs = list(yaml.safe_load_all(f))
|
||||
return docs if len(docs) > 1 else docs[0] if docs else None
|
||||
except Exception as e:
|
||||
print(f" ⚠️ Error parsing {filepath}: {e}")
|
||||
return None
|
||||
|
||||
def analyze_service_directory(service_path, service_name, category):
|
||||
"""Analyze a service directory and extract information"""
|
||||
service = K8sService(service_name, category, service_path)
|
||||
|
||||
# List all files
|
||||
for file in os.listdir(service_path):
|
||||
if file.endswith('.yaml') or file.endswith('.yml'):
|
||||
service.files.append(file)
|
||||
filepath = os.path.join(service_path, file)
|
||||
|
||||
# Parse YAML content
|
||||
content = parse_yaml_file(filepath)
|
||||
if not content:
|
||||
continue
|
||||
|
||||
# Handle multiple documents in one file
|
||||
documents = content if isinstance(content, list) else [content]
|
||||
|
||||
for doc in documents:
|
||||
if not isinstance(doc, dict) or 'kind' not in doc:
|
||||
continue
|
||||
|
||||
kind = doc['kind']
|
||||
metadata = doc.get('metadata', {})
|
||||
|
||||
# ArgoCD Application
|
||||
if kind == 'Application' and doc.get('apiVersion', '').startswith('argoproj.io'):
|
||||
service.argo_app = {
|
||||
'name': metadata.get('name', ''),
|
||||
'namespace': doc.get('spec', {}).get('destination', {}).get('namespace', ''),
|
||||
'project': doc.get('spec', {}).get('project', ''),
|
||||
'auto_sync': doc.get('spec', {}).get('syncPolicy', {}).get('automated') is not None
|
||||
}
|
||||
service.namespace = service.argo_app['namespace']
|
||||
|
||||
# Kustomization
|
||||
elif kind == 'Kustomization':
|
||||
if 'helmCharts' in doc:
|
||||
service.deployment_type = "Helm Chart"
|
||||
for chart in doc.get('helmCharts', []):
|
||||
service.helm_charts.append({
|
||||
'name': chart.get('name', ''),
|
||||
'repo': chart.get('repo', ''),
|
||||
'version': chart.get('version', ''),
|
||||
'namespace': chart.get('namespace', service.namespace)
|
||||
})
|
||||
else:
|
||||
service.deployment_type = "Kustomize"
|
||||
|
||||
# Deployment
|
||||
elif kind == 'Deployment':
|
||||
service.deployments.append({
|
||||
'name': metadata.get('name', ''),
|
||||
'namespace': metadata.get('namespace', service.namespace),
|
||||
'replicas': doc.get('spec', {}).get('replicas', 1),
|
||||
'containers': [c.get('name', '') for c in doc.get('spec', {}).get('template', {}).get('spec', {}).get('containers', [])]
|
||||
})
|
||||
if service.deployment_type == "Unknown":
|
||||
service.deployment_type = "YAML Manifests"
|
||||
|
||||
# Service
|
||||
elif kind == 'Service':
|
||||
svc_spec = doc.get('spec', {})
|
||||
service.services.append({
|
||||
'name': metadata.get('name', ''),
|
||||
'type': svc_spec.get('type', 'ClusterIP'),
|
||||
'ports': svc_spec.get('ports', [])
|
||||
})
|
||||
|
||||
# Ingress
|
||||
elif kind == 'Ingress':
|
||||
rules = doc.get('spec', {}).get('rules', [])
|
||||
hosts = []
|
||||
for rule in rules:
|
||||
if 'host' in rule:
|
||||
hosts.append(rule['host'])
|
||||
service.ingresses.append({
|
||||
'name': metadata.get('name', ''),
|
||||
'hosts': hosts
|
||||
})
|
||||
|
||||
# ExternalSecret
|
||||
elif kind == 'ExternalSecret':
|
||||
service.external_secrets.append({
|
||||
'name': metadata.get('name', ''),
|
||||
'store': doc.get('spec', {}).get('secretStoreRef', {}).get('name', '')
|
||||
})
|
||||
|
||||
# PersistentVolumeClaim
|
||||
elif kind == 'PersistentVolumeClaim':
|
||||
service.pvcs.append({
|
||||
'name': metadata.get('name', ''),
|
||||
'size': doc.get('spec', {}).get('resources', {}).get('requests', {}).get('storage', '')
|
||||
})
|
||||
|
||||
# If no specific deployment type found but has YAML files
|
||||
if service.deployment_type == "Unknown" and service.files:
|
||||
service.deployment_type = "YAML Manifests"
|
||||
|
||||
return service
|
||||
|
||||
def generate_markdown_table(services):
|
||||
"""Generate markdown table for services"""
|
||||
markdown = []
|
||||
markdown.append("# Kubernetes Services")
|
||||
markdown.append("")
|
||||
markdown.append(f"*Automatically generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S UTC')}*")
|
||||
markdown.append("")
|
||||
|
||||
# Group by category
|
||||
categories = defaultdict(list)
|
||||
for service in services:
|
||||
categories[service.category].append(service)
|
||||
|
||||
# Statistics
|
||||
markdown.append("## Statistics")
|
||||
markdown.append("")
|
||||
markdown.append(f"- **Total Services**: {len(services)}")
|
||||
markdown.append(f"- **Categories**: {len(categories)}")
|
||||
helm_count = sum(1 for s in services if s.deployment_type == "Helm Chart")
|
||||
kustomize_count = sum(1 for s in services if s.deployment_type == "Kustomize")
|
||||
yaml_count = sum(1 for s in services if s.deployment_type == "YAML Manifests")
|
||||
markdown.append(f"- **Helm Charts**: {helm_count}")
|
||||
markdown.append(f"- **Kustomize**: {kustomize_count}")
|
||||
markdown.append(f"- **YAML Manifests**: {yaml_count}")
|
||||
markdown.append("")
|
||||
|
||||
# Main table
|
||||
markdown.append("## All Services")
|
||||
markdown.append("")
|
||||
markdown.append("| Service | Category | Type | Namespace | Ingresses | Services | Secrets | Auto-Sync |")
|
||||
markdown.append("|---------|----------|------|-----------|-----------|----------|---------|-----------|")
|
||||
|
||||
for category in sorted(categories.keys()):
|
||||
for service in sorted(categories[category], key=lambda x: x.name):
|
||||
# Service name with link to directory
|
||||
name_link = f"[{service.name}](k8s/{service.category}/{service.name}/)"
|
||||
|
||||
# Deployment type with emoji
|
||||
type_emoji = {
|
||||
"Helm Chart": "🎩",
|
||||
"Kustomize": "🔧",
|
||||
"YAML Manifests": "📄",
|
||||
"Unknown": "❓"
|
||||
}
|
||||
type_str = f"{type_emoji.get(service.deployment_type, '')} {service.deployment_type}"
|
||||
|
||||
# Ingresses
|
||||
ingresses = []
|
||||
for ing in service.ingresses:
|
||||
for host in ing['hosts']:
|
||||
ingresses.append(f"[{host}](https://{host})")
|
||||
ingress_str = "<br>".join(ingresses) if ingresses else "-"
|
||||
|
||||
# Services
|
||||
svc_list = []
|
||||
for svc in service.services:
|
||||
ports = [f"{p.get('port', '?')}" for p in svc['ports']]
|
||||
svc_list.append(f"`{svc['name']}:{','.join(ports)}`")
|
||||
svc_str = "<br>".join(svc_list) if svc_list else "-"
|
||||
|
||||
# External Secrets
|
||||
secrets_str = f"{len(service.external_secrets)} secrets" if service.external_secrets else "-"
|
||||
|
||||
# Auto-sync
|
||||
auto_sync = "✅" if service.argo_app and service.argo_app.get('auto_sync') else "❌"
|
||||
|
||||
markdown.append(f"| **{name_link}** | {category} | {type_str} | {service.namespace or '-'} | {ingress_str} | {svc_str} | {secrets_str} | {auto_sync} |")
|
||||
|
||||
markdown.append("")
|
||||
|
||||
# Detailed sections by category
|
||||
for category in sorted(categories.keys()):
|
||||
markdown.append(f"## {category.title()} Services")
|
||||
markdown.append("")
|
||||
|
||||
for service in sorted(categories[category], key=lambda x: x.name):
|
||||
markdown.append(f"### {service.name}")
|
||||
markdown.append("")
|
||||
|
||||
# Basic info
|
||||
markdown.append(f"- **Type**: {service.deployment_type}")
|
||||
markdown.append(f"- **Namespace**: {service.namespace or 'Not specified'}")
|
||||
markdown.append(f"- **Path**: `{service.path}`")
|
||||
|
||||
# Helm charts
|
||||
if service.helm_charts:
|
||||
markdown.append("- **Helm Charts**:")
|
||||
for chart in service.helm_charts:
|
||||
markdown.append(f" - {chart['name']} v{chart['version']} from {chart['repo']}")
|
||||
|
||||
# Deployments
|
||||
if service.deployments:
|
||||
markdown.append("- **Deployments**:")
|
||||
for dep in service.deployments:
|
||||
containers = ', '.join(dep['containers'])
|
||||
markdown.append(f" - {dep['name']} ({dep['replicas']} replicas) - Containers: {containers}")
|
||||
|
||||
# Files
|
||||
if service.files:
|
||||
markdown.append(f"- **Files**: {', '.join(sorted(service.files))}")
|
||||
|
||||
markdown.append("")
|
||||
|
||||
markdown.append("---")
|
||||
markdown.append("*This page is automatically generated from k8s/ directory via CI/CD*")
|
||||
|
||||
return "\n".join(markdown)
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: generate-k8s-wiki.py <k8s-directory> [output-file]")
|
||||
sys.exit(1)
|
||||
|
||||
k8s_dir = sys.argv[1]
|
||||
output_file = sys.argv[2] if len(sys.argv) > 2 else "Kubernetes-Services.md"
|
||||
|
||||
if not os.path.exists(k8s_dir):
|
||||
print(f"❌ Directory {k8s_dir} not found")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"📂 Scanning {k8s_dir}...")
|
||||
|
||||
services = []
|
||||
|
||||
# Scan each category directory
|
||||
for category in ['apps', 'core', 'games']:
|
||||
category_path = os.path.join(k8s_dir, category)
|
||||
if not os.path.exists(category_path):
|
||||
print(f" ⚠️ Category {category} not found")
|
||||
continue
|
||||
|
||||
print(f"📁 Processing {category}/...")
|
||||
|
||||
# Scan each service in category
|
||||
for service_name in os.listdir(category_path):
|
||||
service_path = os.path.join(category_path, service_name)
|
||||
if os.path.isdir(service_path):
|
||||
print(f" 🔍 Analyzing {service_name}...")
|
||||
service = analyze_service_directory(service_path, service_name, category)
|
||||
services.append(service)
|
||||
|
||||
print(f"\n✅ Found {len(services)} services")
|
||||
|
||||
# Generate markdown
|
||||
markdown = generate_markdown_table(services)
|
||||
|
||||
# Write output
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
f.write(markdown)
|
||||
|
||||
print(f"📄 Wiki page generated: {output_file}")
|
||||
print(f"📊 Total services: {len(services)}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Reference in New Issue
Block a user