#!/bin/sh # forge-dns-render — manage cloud DX forge shortnames (mcforge for magic-civilization, # ctforge for cocottetech/lilithplatform, ...) in /etc/hosts as part of the shared # net-tools infra installers for dev DX. # # Reads current FORGE_IP from ~/.vault/*_forge_creds (maintained by the per-project # ./run forge:up / forge:dns in @magic-civilization and @cocottetech). # # Emits a marked, idempotently-replaceable block. `net sync` (and manual # mesh-hosts-render + host-apply) now also converges the DX forge shortcuts. # Per-project `./run forge:dns` prefers this central renderer when available. # # The block lives at the bottom (after the prepended mesh-hosts fleet block). # Loose hand-managed lines for these names are adopted (removed) on --install. # # Usage: # forge-dns-render # print the block (default) # forge-dns-render --install # splice/replace in /etc/hosts (sudo) # forge-dns-render --diff # show what --install would do # # Exit codes match mesh-hosts-render (0 success, 2 needs root). set -eu mode=print case "${1:-}" in ""|--print) mode=print ;; --install) mode=install ;; --diff) mode=diff ;; *) echo "forge-dns-render: unknown arg '$1' (use --print|--install|--diff)" >&2; exit 1 ;; esac BEGIN='# >>> dx-forges (managed by net-tools/bin/forge-dns-render)' END='# <<< dx-forges' HOSTS_FILE=/etc/hosts VAULT_DIR="${HOME}/.vault" # Map vault basename -> the short hostname users type for :3000 map_short() { case "$1" in mc_forge_creds) echo mcforge ;; cocotte_forge_creds) echo ctforge ;; *) echo "" ;; esac } render_block() { printf '%s\n' "$BEGIN" printf '# Cloud DX Forgejo /etc/hosts shortcuts (mcforge, ctforge, ...).\n' printf '# IPs from ~/.vault/*_forge_creds FORGE_IP (refreshed by project ./run forge:up).\n' printf '# Re-run after any forge:up (droplet gets a new IP on restore-from-snapshot).\n' printf '# http://:3000 — also kept fresh by net-tools infra (net sync).\n' had=0 for f in "$VAULT_DIR"/mc_forge_creds "$VAULT_DIR"/cocotte_forge_creds; do [ -f "$f" ] || continue base=$(basename "$f") short=$(map_short "$base") [ -n "$short" ] || continue ip=$(grep -E '^FORGE_IP=' "$f" 2>/dev/null | head -1 | cut -d= -f2- | tr -d ' \t\r\n') [ -n "$ip" ] || continue printf '%s\t%s\n' "$ip" "$short" had=1 done if [ "$had" -eq 0 ]; then printf '# (no active DX forges — ./run forge:up in the relevant project(s) first)\n' fi printf '%s\n' "$END" } block=$(render_block) if [ "$mode" = "print" ]; then printf '%s\n' "$block" exit 0 fi # All shortnames we own (for adoption of stale loose lines). managed=$(printf '%s\n' "$block" | awk '!/^#/ && NF >= 2 { for (i = 2; i <= NF; i++) print $i }' | sort -u | tr '\n' ' ') current=$(cat "$HOSTS_FILE" 2>/dev/null || true) # Strip any previous copy of our block. stripped=$(printf '%s\n' "$current" | awk -v b="$BEGIN" -v e="$END" ' $0 == b { skip = 1 } skip != 1 { print } $0 == e { skip = 0 } ') # Adopt (remove) any loose lines or name tokens that match our managed forges. # (Same policy as mesh-hosts-render: the tool owns these names now.) stripped=$(printf '%s\n' "$stripped" | awk -v names="$managed" ' BEGIN { n = split(names, a, /[[:space:]]+/); for (i = 1; i <= n; i++) if (a[i] != "") set[a[i]] = 1 } /^[[:space:]]*#/ || NF < 2 { print; next } { kept = ""; removed = 0 for (i = 2; i <= NF; i++) { if ($i in set) removed++ else kept = kept " " $i } if (removed == 0) { print; next } if (kept == "") next print $1 kept } ') # Trim leading/trailing blank lines that accumulate from repeated splices. stripped=$(printf '%s\n' "$stripped" | awk 'NF {f=1; p=NR} f {l[NR]=$0} END {for(i=1;i<=p;i++) if (i in l) print l[i]}') # Append the dx-forges block at the bottom (mesh-hosts block is prepended at top). new=$(printf '%s\n\n%s\n' "$stripped" "$block") if [ "$mode" = "diff" ]; then if command -v diff >/dev/null 2>&1; then printf '%s\n' "$new" | diff -u "$HOSTS_FILE" - || true else printf '%s\n' "$new" fi exit 0 fi # --install if printf '%s\n' "$new" | cmp -s - "$HOSTS_FILE"; then echo "forge-dns-render: $HOSTS_FILE already up to date" exit 0 fi SUDO="" if [ "$(id -u)" -ne 0 ]; then if command -v sudo >/dev/null 2>&1; then SUDO="sudo" else echo "forge-dns-render: --install needs root" >&2 exit 2 fi fi printf '%s\n' "$new" | $SUDO tee "$HOSTS_FILE" >/dev/null echo "forge-dns-render: updated $HOSTS_FILE"