Apuntar sync_translations/audio/carta_from_prod.py al Hetzner nuevo
Los tres scripts asumian el CDMON viejo (134.0.10.170, sin Docker): host y password hardcodeados, y el helper PHP ejecutandose directamente en el host. Desde el cutover a Hetzner (Coolify/Docker, 2026-08-03) eso ya no aplica. - FEA_PROD_HOST/FEA_PROD_PASS pasan a FEA_PROD_SSH_HOST/FEA_PROD_SSH_PASS (mismo nombre en los tres scripts; sync_carta_from_prod.py ya los usaba). - Nueva FEA_PROD_DOCKER_CONTAINER: si esta definida, el helper se sube y se ejecuta con "docker exec -i" dentro del contenedor en vez de en el host. - Auth por clave (ed25519 claude-code@feadulta): sshpass solo se usa si FEA_PROD_SSH_PASS no esta vacia. - Fix del gotcha de "docker exec CONTENEDOR cmd < ruta": esa redireccion la resuelve el HOST, no el contenedor. El wrapping va dentro de "sh -c" para que la redireccion se resuelva en el sitio correcto (afecta a la subida del helper y a la verificacion de tamano del mp3 en audio). Verificado: dry-run de los tres contra el WP local, y una lectura real de prod (sync_carta_from_prod.py --carta 55487 --dry-run) que recupero correctamente el cluster de la carta 738 y el contenido de un post concreto. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -29,9 +29,12 @@ DB_NAME = os.environ.get("FEA_DB_NAME", "wordpress_db")
|
||||
DB_USER = os.environ.get("FEA_DB_USER", "wordpress_user")
|
||||
DB_PASS = os.environ.get("FEA_DB_PASS", "wordpress_pass")
|
||||
|
||||
PROD_HOST = os.environ.get("FEA_PROD_HOST", "feadulta@134.0.10.170")
|
||||
PROD_PASS = os.environ.get("FEA_PROD_PASS", "C6c2A!mAl3Wj.BQF")
|
||||
PROD_WPLOAD = os.environ.get("FEA_PROD_WPLOAD", "/web/wp-load.php")
|
||||
PROD_HOST = os.environ.get("FEA_PROD_SSH_HOST", "")
|
||||
PROD_PASS = os.environ.get("FEA_PROD_SSH_PASS", "")
|
||||
PROD_WPLOAD = os.environ.get("FEA_PROD_WPLOAD", "/var/www/html/wp-load.php")
|
||||
# Desde el cutover a Hetzner, WordPress vive dentro de Coolify/Docker. Si se
|
||||
# define, el helper se sube y se ejecuta dentro del contenedor.
|
||||
PROD_DOCKER_CONTAINER = os.environ.get("FEA_PROD_DOCKER_CONTAINER", "")
|
||||
PROD_HELPER = "/tmp/fea_translate_helper.php"
|
||||
|
||||
HELPER_SRC = Path(__file__).resolve().parent / "fea_translate_helper.php"
|
||||
@@ -159,18 +162,41 @@ _prod_ready = False
|
||||
|
||||
|
||||
def _ssh(remote_cmd: str, *, stdin: str | None = None, timeout: int = 120) -> str:
|
||||
cmd = ["sshpass", "-p", PROD_PASS, "ssh", "-o", "StrictHostKeyChecking=accept-new",
|
||||
"-o", "ConnectTimeout=20", PROD_HOST, remote_cmd]
|
||||
# El Hetzner nuevo usa auth por clave (ed25519 claude-code@feadulta); sshpass
|
||||
# solo se antepone si hay contraseña configurada (servidor viejo CDMON).
|
||||
if PROD_PASS:
|
||||
cmd = ["sshpass", "-p", PROD_PASS, "ssh", "-o", "StrictHostKeyChecking=accept-new",
|
||||
"-o", "ConnectTimeout=20", PROD_HOST, remote_cmd]
|
||||
else:
|
||||
cmd = ["ssh", "-o", "StrictHostKeyChecking=accept-new",
|
||||
"-o", "ConnectTimeout=20", PROD_HOST, remote_cmd]
|
||||
return sh(cmd, stdin=stdin, timeout=timeout)
|
||||
|
||||
|
||||
def _remote_wrap(inner_cmd: str) -> str:
|
||||
"""Envuelve un comando para que corra dentro del contenedor Docker de prod
|
||||
si FEA_PROD_DOCKER_CONTAINER está definido; si no, corre en el host tal cual.
|
||||
|
||||
El wrapping (incluidas redirecciones como `< ruta`) debe quedar DENTRO de la
|
||||
shell del contenedor (`sh -c '...'`): `docker exec CONTENEDOR cmd < ruta`
|
||||
resuelve esa redirección en el filesystem del HOST, no en el contenedor.
|
||||
"""
|
||||
if PROD_DOCKER_CONTAINER:
|
||||
return f"docker exec -i {PROD_DOCKER_CONTAINER} sh -c {sh_quote(inner_cmd)}"
|
||||
return inner_cmd
|
||||
|
||||
|
||||
def sh_quote(s: str) -> str:
|
||||
return "'" + s.replace("'", "'\\''") + "'"
|
||||
|
||||
|
||||
def prod_helper(subcmd: str, *args: str, stdin: str | None = None) -> str:
|
||||
global _prod_ready
|
||||
if not _prod_ready:
|
||||
_ssh(f"cat > {PROD_HELPER}", stdin=HELPER_SRC.read_text(encoding="utf-8"))
|
||||
_ssh(_remote_wrap(f"cat > {PROD_HELPER}"), stdin=HELPER_SRC.read_text(encoding="utf-8"))
|
||||
_prod_ready = True
|
||||
inner = f"FEA_WP_LOAD={PROD_WPLOAD} php {PROD_HELPER} {subcmd} " + " ".join(args)
|
||||
return _ssh(inner, stdin=stdin, timeout=180)
|
||||
return _ssh(_remote_wrap(inner), stdin=stdin, timeout=180)
|
||||
|
||||
|
||||
def prod_create(origin: int, lang: str, title: str, content: str) -> int:
|
||||
|
||||
Reference in New Issue
Block a user