# -*- coding: utf-8 -*- """ manifest.py — Сборка и управление манифестом переноса """ import json import os from datetime import datetime from core.color import info, warn, success, subheader, divider def build_manifest(docker_data, nginx_data, sidecars, host_network, systemd_units, cron_jobs, extra_hints): """ Собирает единый manifest dict. """ manifest = { "meta": { "created": datetime.now().isoformat(), "hostname": os.popen("hostname").read().strip(), "version": "1.0", }, "service": { "name": docker_data.get("container_name"), "image": docker_data.get("image"), "status": docker_data.get("status"), }, "docker": { "container_id": docker_data.get("container_id"), "compose_file": docker_data.get("compose_file"), "env_file": docker_data.get("env_file"), "mounts": docker_data.get("mounts", []), "ports": docker_data.get("ports", {}), "networks": docker_data.get("networks", []), "host_config": docker_data.get("host_config", {}), "labels": docker_data.get("labels", {}), }, "nginx": nginx_data, "sidecars": sidecars, "host_network": host_network, "systemd_units": systemd_units, "cron_jobs": cron_jobs, "extra_hints": extra_hints or [], } return manifest def save_manifest(manifest, path): with open(path, "w", encoding="utf-8") as f: json.dump(manifest, f, indent=2, ensure_ascii=False) success(f"Manifest сохранён: {path}") def load_manifest(path): with open(path, "r", encoding="utf-8") as f: return json.load(f) def review_manifest(manifest): """ Показывает пользователю обзор манифеста перед подтверждением. """ subheader("ОБЗОР МАНИФЕСТА (что будет перенесено)") divider() svc = manifest.get("service", {}) print(f" Сервис: {svc.get('name', '?')}") print(f" Образ: {svc.get('image', '?')}") docker = manifest.get("docker", {}) print(f"\n Compose: {docker.get('compose_file') or '(не найден)'}") print(f" .env: {docker.get('env_file') or '(не найден)'}") mounts = docker.get("mounts", []) print(f"\n Mounts/volumes ({len(mounts)}):") for m in mounts: print(f" - [{m.get('type')}] {m.get('source')} → {m.get('destination')} ({m.get('mode')})") ports = docker.get("ports", {}) if ports: print(f"\n Опубликованные порты:") for host, container in ports.items(): print(f" {host} → {container}") nets = docker.get("networks", []) print(f"\n Docker сети: {', '.join(nets) or '—'}") hc = docker.get("host_config", {}) if hc.get("network_mode"): print(f" network_mode: {hc['network_mode']}") if hc.get("privileged"): print(f" privileged: {hc['privileged']}") if hc.get("cap_add"): print(f" cap_add: {hc['cap_add']}") nginx = manifest.get("nginx", []) print(f"\n Nginx связи ({len(nginx)}):") for n in nginx: print(f" - {n.get('file') or n.get('method', '?')} | server_name={n.get('server_name')} | proxy_pass={n.get('proxy_pass')}") if n.get("ssl_certificate"): print(f" SSL cert: {n['ssl_certificate']}") print(f" SSL key: {n['ssl_certificate_key']}") sidecars = manifest.get("sidecars", []) if sidecars: print(f"\n Sidecar / loopback зависимости ({len(sidecars)}):") for s in sidecars: print(f" - {s.get('type')}: {s.get('host_process', '?')} (pid={s.get('host_pid', '?')}, port={s.get('container_port_target', '?')})") units = manifest.get("systemd_units", []) if units: print(f"\n Systemd units ({len(units)}):") for u in units: print(f" - {u.get('name')} ({u.get('path')})") crons = manifest.get("cron_jobs", []) if crons: print(f"\n Cron ({len(crons)}):") for c in crons[:3]: print(f" - {c.get('file') or c.get('user', '?')}: {c.get('line', c.get('content', '?'))[:80]}") hostnet = manifest.get("host_network", {}) if hostnet.get("ip_routes"): print(f"\n Маршруты: {len(hostnet['ip_routes'])} записей") if hostnet.get("ip_rules"): print(f" Policy rules: {len(hostnet['ip_rules'])} записей") divider()