feature/integracion-panel-restore-targets

This commit is contained in:
2026-06-05 12:28:04 -06:00
parent afb76ce4a6
commit 072be5b5db
4 changed files with 176 additions and 31 deletions

View File

@@ -11,6 +11,7 @@ asignado, get_target_for_database devuelve None y el worker deja el job en cola
reintentar; nunca se restaura con datos inciertos.
"""
import os
from typing import Optional
from urllib.parse import urlparse, quote
@@ -21,6 +22,18 @@ from ..utils.logger import app_logger
# Timeout (connect, read) en segundos para las llamadas al PANEL.
DEFAULT_TIMEOUT = (5, 10)
def _http_verify(verify_ssl: Optional[bool] = None) -> bool:
"""Verificación TLS para requests. Por defecto False (panel dev con cert propio)."""
if verify_ssl is not None:
return verify_ssl
env = os.getenv("CLOUDRESTORE_PANEL_VERIFY_SSL", "").strip().lower()
if env in ("1", "true", "yes"):
return True
if env in ("0", "false", "no"):
return False
return False
# Campos obligatorios del servidor devuelto por el endpoint (modo hub central + SFTP).
REQUIRED_TARGET_FIELDS = (
"server",
@@ -109,7 +122,9 @@ def get_target_for_database(
headers = {"Authorization": f"Bearer {api_token.strip()}"}
try:
resp = requests.get(url, headers=headers, timeout=DEFAULT_TIMEOUT)
resp = requests.get(
url, headers=headers, timeout=DEFAULT_TIMEOUT, verify=_http_verify()
)
except requests.exceptions.RequestException as e:
app_logger.error(f"PANEL no accesible al consultar servidor de la base '{db_name}': {e}")
return None
@@ -158,7 +173,9 @@ def list_restore_target_names(api_url: str, api_token: str) -> list[str]:
headers = {"Authorization": f"Bearer {api_token.strip()}"}
try:
resp = requests.get(url, headers=headers, timeout=DEFAULT_TIMEOUT)
resp = requests.get(
url, headers=headers, timeout=DEFAULT_TIMEOUT, verify=_http_verify()
)
except requests.exceptions.RequestException as e:
app_logger.error(f"PANEL no accesible al consultar catálogo de servidores: {e}")
return []
@@ -221,7 +238,9 @@ def resolve_route(
headers = {"Authorization": f"Bearer {api_token.strip()}"}
try:
resp = requests.get(url, headers=headers, timeout=DEFAULT_TIMEOUT)
resp = requests.get(
url, headers=headers, timeout=DEFAULT_TIMEOUT, verify=_http_verify()
)
except requests.exceptions.RequestException as e:
app_logger.error(f"PANEL no accesible al resolver ruta para '{filename}': {e}")
return None
@@ -313,7 +332,9 @@ def report_instance_config(
payload["instance_key"] = key
try:
resp = requests.post(url, json=payload, headers=headers, timeout=DEFAULT_TIMEOUT)
resp = requests.post(
url, json=payload, headers=headers, timeout=DEFAULT_TIMEOUT, verify=_http_verify()
)
except requests.exceptions.RequestException as e:
app_logger.error(f"No se pudo reportar la carpeta de entrada al PANEL: {e}")
return False
@@ -360,7 +381,9 @@ def report_job_result(
}
try:
resp = requests.post(url, json=payload, headers=headers, timeout=DEFAULT_TIMEOUT)
resp = requests.post(
url, json=payload, headers=headers, timeout=DEFAULT_TIMEOUT, verify=_http_verify()
)
except requests.exceptions.RequestException as e:
app_logger.error(f"No se pudo reportar el resultado del job al PANEL: {e}")
return False
@@ -390,7 +413,9 @@ def test_connection(api_url: str, api_token: str) -> tuple[bool, Optional[str]]:
url = f"{base}/api/restore/target-for?database={quote('__cloudrestore_ping__')}"
headers = {"Authorization": f"Bearer {api_token.strip()}"}
try:
resp = requests.get(url, headers=headers, timeout=DEFAULT_TIMEOUT)
resp = requests.get(
url, headers=headers, timeout=DEFAULT_TIMEOUT, verify=_http_verify()
)
except requests.exceptions.RequestException as e:
return False, f"No se pudo conectar al PANEL: {e}"