#!/usr/bin/env python3 """Spec 037b — provision-zone cria zona do cliente na CF Ligbox.""" from pathlib import Path ROUTER = Path("/opt/ligbox-wizard/backend/app/routers/onboarding.py") REGISTRY = Path("/opt/ligbox-wizard/backend/app/services/dns_account_registry.py") CF = Path("/opt/ligbox-wizard/backend/app/services/cloudflare.py") # --- cloudflare ensure_zone account_id --- cf_text = CF.read_text(encoding="utf-8") OLD_ENSURE = """ def ensure_zone(self, domain: str) -> dict: \"\"\"Garante que a zona existe na conta Ibytera; cria se necessário.\"\"\" zone = self.get_zone_by_name(domain) if zone: return {"zone": zone, "created": False} zone = self.create_zone(domain) return {"zone": zone, "created": True}""" NEW_ENSURE = """ def ensure_zone(self, domain: str, account_id: str | None = None) -> dict: \"\"\"Garante que a zona existe na conta CF; cria se necessário.\"\"\" zone = self.get_zone_by_name(domain) if zone: return {"zone": zone, "created": False} zone = self.create_zone(domain, account_id=account_id) return {"zone": zone, "created": True}""" if "account_id: str | None = None" not in cf_text: cf_text = cf_text.replace(OLD_ENSURE, NEW_ENSURE) CF.write_text(cf_text, encoding="utf-8") print("cloudflare.py patched") # --- registry: ensure pick_provision_account exists (copy from monorepo if needed) --- # handled via scp separately # --- onboarding import --- text = ROUTER.read_text(encoding="utf-8") if "provision_ligbox_zone" not in text: text = text.replace( "from app.services.dns_account_registry import resolve_ligbox_zone, resolve_payload", "from app.services.dns_account_registry import (\n pick_provision_account,\n provision_ligbox_zone,\n resolve_ligbox_zone,\n resolve_payload,\n)", ) OLD_BLOCK = ''' match = resolve_ligbox_zone(domain) if match: activity_log.info( f"Zona {domain} já na conta {match.account.id} — sem create", source="cloudflare", ) payload = _portal_onboarding_payload(domain, zone_created=False) payload["zone_id"] = match.zone_id payload["ligbox_account_id"] = match.account.id payload["dns_mode"] = match.dns_mode payload["message"] = ( f"Domínio {domain} já está na Cloudflare Ligbox ({match.account.label})." ) if nameservers := wizard_nameservers(match.zone): payload["nameservers"] = nameservers payload["status"]["nameservers"] = nameservers return payload raise HTTPException( status_code=422, detail={ "code": "zone_not_in_ligbox_accounts", "domain": domain, "message": ( "Domínio não está nas contas Ligbox (ligit, itecnologys, ibytera). " "Use API Token da sua Cloudflare ou apontamentos no registrador." ), "paths_available": ["byo", "external"], }, ) cf = CloudflareDNS() try: activity_log.info(f"Criar zona Cloudflare: {domain}", source="cloudflare") cf.verify_token() result = cf.ensure_zone(domain)''' NEW_BLOCK = ''' provision_acct = pick_provision_account() if not provision_acct: raise HTTPException( 400, "Nenhuma conta Cloudflare Ligbox configurada. Ver dns-accounts.yaml e secrets/.", ) try: activity_log.info( f"Provision zona cliente {domain} (conta Ligbox {provision_acct.id})", source="cloudflare", ) provision_acct.client().verify_token() result = provision_ligbox_zone(domain, account=provision_acct) match = result["account"] cf = match.client() result = {"zone": result["zone"], "created": result["created"]}''' if "provision_ligbox_zone(domain" not in text: text = text.replace(OLD_BLOCK, NEW_BLOCK) # fix variable shadowing - after replace, need to fix zone/created extraction text = text.replace( " match = result["account"]\n cf = match.client()\n result = {"zone": result["zone"], "created": result["created"]}", " ligbox_acct = result["account"]\n cf = ligbox_acct.client()\n zone = result["zone"]\n created = result["created"]", ) # Remove duplicate zone = result["zone"] if the old code still has it - read and fix text = text.replace( " zone = result[\"zone\"]\n created = result[\"created\"]\n zone = result[\"zone\"]\n created = result[\"created\"]", " zone = result[\"zone\"]\n created = result[\"created\"]", ) # Add ligbox_account_id to payload after zone created if 'payload["ligbox_account_id"]' not in text.split("provision_cloudflare_zone")[1][:2500]: text = text.replace( ' payload["zone_id"] = zone.get("id")\n payload["sandbox"] = sandbox', ' payload["zone_id"] = zone.get("id")\n payload["ligbox_account_id"] = ligbox_acct.id\n payload["dns_mode"] = f"ligbox_cf_{ligbox_acct.id}"\n payload["sandbox"] = sandbox', ) ROUTER.write_text(text, encoding="utf-8") print("onboarding.py provision-zone patched OK")