Create the networks our own pushed templates name, instead of trusting a fresh mirror to have uncommented them

This commit is contained in:
Gmer4Lfe
2026-08-16 20:50:10 -04:00
parent cf67393db6
commit 23825a824d
2 changed files with 96 additions and 0 deletions
+15
View File
@@ -639,6 +639,21 @@ fi
echo "" echo ""
echo "━━━ Step 1b — Docker Network (Mirror) ━━━" echo "━━━ Step 1b — Docker Network (Mirror) ━━━"
# Two halves, and the first is the one that matters for a fresh mirror.
#
# ensure_stack_networks_on_remote reads the networks out of the XMLs this onboard is about to
# push and creates any that are missing on the mirror. It does not consult the mirror's conf,
# because on a fresh node that array is the template default — a single commented-out entry —
# and an empty list is indistinguishable from "no networks needed". The result was every
# container in both stacks created against a network that did not exist.
#
# docker_network_connect.sh still runs afterwards: it is what *connects* the mirror's own
# listed containers to its own listed networks, which is a different job and remains the
# mirror's to declare.
if ! ensure_stack_networks_on_remote "$MIRROR_IP" "$MIRROR_SSH_KEY"; then
warn "One or more stack networks could not be prepared on $MIRROR — deploys below may fail"
fi
_net_script="${SCRIPTS_ROOT}/Docker_Essentials/docker_network_connect.sh" _net_script="${SCRIPTS_ROOT}/Docker_Essentials/docker_network_connect.sh"
if [[ "$DRY_RUN" == true ]]; then if [[ "$DRY_RUN" == true ]]; then
warn "DRY RUN — would run docker_network_connect.sh on $MIRROR" warn "DRY RUN — would run docker_network_connect.sh on $MIRROR"
+81
View File
@@ -416,6 +416,87 @@ deploy_xml_stack() {
done done
} }
# ==============================================================================================
# ── Ensure the networks our pushed templates reference exist on a remote host ─────────────────
#
# The owner deploys the mirror's containers from the owner's own XMLs, and those XMLs name a
# network. `docker create` fails outright if that network is missing, so the network has to
# exist on the mirror before any stack is deployed.
#
# This used to be left entirely to docker_network_connect.sh running on the mirror, which
# iterates the *mirror's* NETWORK_CONNECT_NETWORKS. host.conf.template ships that array with its
# only entry commented out, so on a fresh node it is empty — nothing was created, and every
# container in both stacks was created against a network that did not exist and could never
# start. Twelve containers stuck in `Created`, reported as "0 deployed, 8 failed" and
# "0 deployed, 5 failed" as though each container had its own problem.
#
# The owner knows what it is about to push, so it derives the requirement from the templates
# rather than trusting the mirror's conf to have been filled in.
#
# Only bridge networks are created. br0 and friends are ipvlan/macvlan bound to real host
# hardware — the parent interface cannot be inferred from here, and guessing one would attach
# the mirror's containers to the wrong segment.
#
# Usage: ensure_stack_networks_on_remote "$MIRROR_IP" "$MIRROR_SSH_KEY"
# ==============================================================================================
ensure_stack_networks_on_remote() {
local remote_ip="$1" ssh_key="$2"
local -a xml_names=() nets=()
[[ ${#PARTNERSHIP_AUTH_STACK[@]} -gt 0 ]] && xml_names+=("${PARTNERSHIP_AUTH_STACK[@]}")
[[ ${#PARTNERSHIP_ARR_STACK[@]} -gt 0 ]] && xml_names+=("${PARTNERSHIP_ARR_STACK[@]}")
[[ ${#PARTNERSHIP_SERVICES_STACK[@]} -gt 0 ]] && xml_names+=("${PARTNERSHIP_SERVICES_STACK[@]}")
local xml_name xml_file net n seen
for xml_name in "${xml_names[@]}"; do
[[ -z "$xml_name" ]] && continue
xml_file="${TEMPLATES_DIR}/${xml_name}"
[[ -f "$xml_file" ]] || continue
net=$(sed -n 's/.*<Network>\([^<]*\)<\/Network>.*/\1/p' "$xml_file" 2>/dev/null | head -1)
net="${net//[[:space:]]/}"
# Built-ins exist on every host; br* is host hardware, handled above.
case "$net" in ''|bridge|host|none|br[0-9]*) continue ;; esac
seen=false
for n in "${nets[@]}"; do [[ "$n" == "$net" ]] && { seen=true; break; }; done
[[ "$seen" == false ]] && nets+=("$net")
done
if [[ ${#nets[@]} -eq 0 ]]; then
log "No custom networks referenced by the pushed templates"
return 0
fi
local rc=0 driver
for net in "${nets[@]}"; do
driver=$(timeout "${DOCKER_TIMEOUT:-30}" docker network inspect "$net" \
--format '{{.Driver}}' 2>/dev/null)
if [[ -z "$driver" ]]; then
warn "$net is referenced by a pushed template but does not exist here either — skipping"
rc=1
continue
fi
if [[ "$driver" != "bridge" ]]; then
warn "$net is $driver here, not bridge — create it on $MIRROR by hand, its parent interface is host-specific"
rc=1
continue
fi
if [[ "$DRY_RUN" == true ]]; then
warn "DRY RUN — would ensure network '$net' (bridge) exists on $MIRROR"
continue
fi
if timeout "$SSH_TIMEOUT" ssh -i "$ssh_key" \
-o ConnectTimeout="$SSH_TIMEOUT" -o BatchMode=yes -o StrictHostKeyChecking=no \
root@"$remote_ip" \
"docker network inspect $(printf '%q' "$net") >/dev/null 2>&1 \
|| docker network create --driver bridge $(printf '%q' "$net") >/dev/null" 2>/dev/null; then
echo " network $net (bridge) ready on $MIRROR"
else
warn " could not ensure network $net on $MIRROR — its containers will not start"
rc=1
fi
done
return "$rc"
}
# ============================================================================================== # ==============================================================================================
# ── Remove owner-deployed containers from a remote host ────────────────────────────────────── # ── Remove owner-deployed containers from a remote host ──────────────────────────────────────
# #