import paramiko import yaml import os CLEAN_METADATA_KEYS = {'uid', 'resourceVersion', 'generation', 'creationTimestamp', 'managedFields', 'selfLink'} CLEAN_ANNOTATIONS_PREFIXES = { 'kubectl.kubernetes.io/last-applied-configuration', 'deployment.kubernetes.io/revision', 'field.cattle.io/publicEndpoints' } def clean_doc(doc): if not isinstance(doc, dict): return doc doc.pop('status', None) meta = doc.get('metadata', {}) for k in CLEAN_METADATA_KEYS: meta.pop(k, None) ann = meta.get('annotations', {}) keys_to_del = [k for k in ann if any(k.startswith(p) for p in CLEAN_ANNOTATIONS_PREFIXES)] for k in keys_to_del: ann.pop(k, None) if not ann: meta.pop('annotations', None) return doc def dump_resources(ssh, query_cmd, out_file): print(f"Querying: {query_cmd}") _, out, err = ssh.exec_command(query_cmd) raw = out.read().decode('utf-8', errors='replace') if not raw.strip(): print(f" Warning: No resources found for {query_cmd}") return docs = yaml.safe_load_all(raw) cleaned = [] for d in docs: if not d: continue if d.get('kind') == 'List': for item in d.get('items', []): cleaned.append(clean_doc(item)) else: cleaned.append(clean_doc(d)) if cleaned: os.makedirs(os.path.dirname(out_file), exist_ok=True) with open(out_file, 'w', encoding='utf-8') as fp: yaml.dump_all(cleaned, fp, default_flow_style=False, sort_keys=False) print(f" Saved {len(cleaned)} resources -> {out_file}") # 1. Connect to Spaceport print("\n--- Connecting to Spaceport (140.44.4.41) ---") ssh_sp = paramiko.SSHClient() ssh_sp.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh_sp.connect('140.44.4.41', username='root', key_filename=r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet', timeout=10) base_sp = r"c:\Users\Snarf\OneDrive\Desktop\code\SnarfCode\homelab-gitops-repo\manifests\spaceport" # Homepage dump_resources(ssh_sp, "kubectl get deploy,svc,ing,cm -n infrastructure -l app.kubernetes.io/name=homepage-2-1744068158 -o yaml", os.path.join(base_sp, "homepage", "homepage.yaml")) # Jenkins dump_resources(ssh_sp, "kubectl get sts,svc,ing -n infrastructure -l app.kubernetes.io/name=jenkins -o yaml", os.path.join(base_sp, "jenkins", "jenkins.yaml")) # Semaphore dump_resources(ssh_sp, "kubectl get deploy,svc,ing,cm -n infrastructure -l app.kubernetes.io/name=semaphore -o yaml", os.path.join(base_sp, "semaphore", "semaphore.yaml")) # Coder dump_resources(ssh_sp, "kubectl get deploy,svc,ing -n infrastructure -l app.kubernetes.io/name=coder -o yaml", os.path.join(base_sp, "coder", "coder.yaml")) # Gitea dump_resources(ssh_sp, "kubectl get deploy,sts,svc,ing,cm -n infrastructure -l app.kubernetes.io/instance=gitea -o yaml", os.path.join(base_sp, "gitea", "gitea.yaml")) # Zabbix dump_resources(ssh_sp, "kubectl get deploy,sts,svc,ing -n monitoring -l app.kubernetes.io/instance=zabbix -o yaml", os.path.join(base_sp, "zabbix", "zabbix.yaml")) ssh_sp.close() # 2. Connect to Aerodrome print("\n--- Connecting to Aerodrome (140.44.4.11) ---") ssh_ae = paramiko.SSHClient() ssh_ae.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh_ae.connect('140.44.4.11', username='root', key_filename=r'C:\Users\Snarf\.ssh\id_ed25519_snarfnet', timeout=10) base_ae = r"c:\Users\Snarf\OneDrive\Desktop\code\SnarfCode\homelab-gitops-repo\manifests\aerodrome" # Grafana dump_resources(ssh_ae, "kubectl get deploy,svc,ing -n default -l app.kubernetes.io/name=grafana -o yaml", os.path.join(base_ae, "grafana", "grafana.yaml")) # Uptime Kuma dump_resources(ssh_ae, "kubectl get deploy,svc,ing -n monitoring -l app.kubernetes.io/name=uptime-kuma -o yaml", os.path.join(base_ae, "uptime-kuma", "uptime-kuma.yaml")) # AWX dump_resources(ssh_ae, "kubectl get awx,deploy,svc,ing -n awx -o yaml", os.path.join(base_ae, "awx", "awx.yaml")) # Authentik dump_resources(ssh_ae, "kubectl get deploy,sts,svc,ing -n infra -l app.kubernetes.io/instance=authentik -o yaml", os.path.join(base_ae, "authentik", "authentik.yaml")) ssh_ae.close() print("\nManifest extraction complete!")