#!/bin/sh # Roll the production supervision promotion back to the incumbent detached pair. # # This restores the process-management arrangement that ran production before # the supervision cutover: two nohup'd binaries entered into the anchor # container's network namespace via nsenter, parented to init. # # It performs NO database or schema change, because the promotion it reverses # performs none either. The economy is never at risk here. # # Run with --dry-run first; that prints the exact commands and touches nothing. # # usage: openfut-rollback-detached.sh [--dry-run] set -eu DRY=0 [ "${1:-}" = "--dry-run" ] && DRY=1 ANCHOR=openfut-fut-backend ART=/home/alex/openfut-migration/promote-contract-20260822-184409/artifacts ENVJSON=/home/alex/openfut-migration/promote-contract-20260822-184409/env.json LOGDIR=/home/alex/openfut-promotion/logs run() { if [ "$DRY" -eq 1 ]; then printf ' DRY %s\n' "$*"; else printf ' RUN %s\n' "$*"; sh -c "$*"; fi } echo "== 1. stop and remove supervision (units only; binaries, env and DB untouched) ==" run "systemctl disable --now openfut-host.service openfut-core.service openfut-netns.service openfut-netns-reconcile.timer || true" run "/home/alex/OpenFUT/scripts/systemd/openfut-supervision-install.sh uninstall production" echo "== 2. resolve the anchor's CURRENT namespace (never a remembered pid) ==" if [ "$DRY" -eq 1 ]; then APID="$(docker inspect -f '{{.State.Pid}}' "$ANCHOR" 2>/dev/null || echo '')" echo " DRY anchor $ANCHOR pid=$APID ns=$(readlink "/proc/$APID/ns/net" 2>/dev/null || echo '')" else APID="$(docker inspect -f '{{.State.Pid}}' "$ANCHOR")" [ -n "$APID" ] && [ "$APID" != "0" ] || { echo "anchor $ANCHOR is not running — cannot roll back into its namespace" >&2; exit 1; } echo " anchor $ANCHOR pid=$APID ns=$(readlink "/proc/$APID/ns/net")" fi # The environment is replayed from the captured live process environment, never # retyped. jq renders it as KEY=VALUE pairs for env(1). CORE_ENV="$(jq -r '.core | to_entries[] | "\(.key)=\(.value)"' "$ENVJSON" | tr '\n' ' ')" HOST_ENV="$(jq -r '.host | to_entries[] | "\(.key)=\(.value)"' "$ENVJSON" | tr '\n' ' ')" echo "== 3. relaunch incumbent Core (the writer first) ==" run "mkdir -p $LOGDIR" run "nsenter --net=/proc/$APID/ns/net env $CORE_ENV nohup $ART/openfut-core >> $LOGDIR/prod-core.log 2>&1 &" run "/home/alex/OpenFUT/scripts/systemd/openfut-wait-tcp.sh 127.0.0.1 18080 30" echo "== 4. relaunch incumbent host ==" run "nsenter --net=/proc/$APID/ns/net env $HOST_ENV nohup $ART/openfut-utas-host >> $LOGDIR/prod-host.log 2>&1 &" run "/home/alex/OpenFUT/scripts/systemd/openfut-wait-tcp.sh 127.0.0.1 8099 30" echo "== 5. verify ==" run "pgrep -af 'openfut-core|openfut-utas-host'" echo "Rollback complete. No database or schema change was made."