Foundations for network-drift healing: - ipInSubnet(ip, cidr): prefix-aware CIDR membership (pure bash), so stored IPs can be checked against docker's real subnet. Honours the actual prefix, so a healthy /16-subnet + /24-ip-range install is not mistaken for drift. - dockerInstallApp now accepts reset_network="ip": re-roll the static IP from the current subnet but PRESERVE published host ports (clears only IP rows; LIBREPORTAL_RESET_IP_ONLY keeps port_allocate reusing existing ports). This is the heal path — a subnet move strands the IP, not the port, so we don't churn bookmarks/forwards/proxy upstreams. reset="true" still re-rolls both. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
85 lines
3.8 KiB
Bash
Executable File
85 lines
3.8 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
dockerInstallApp()
|
|
{
|
|
local app_name="$1"
|
|
local config_variables="$2"
|
|
local reset_network="$3"
|
|
|
|
local app_name_ucfirst="$(tr '[:lower:]' '[:upper:]' <<< ${app_name:0:1})${app_name:1}"
|
|
local installFuncName="install${app_name_ucfirst}"
|
|
|
|
# App slugs are lowercase (e.g. "libreportal"), but installer functions keep
|
|
# their own internal capitalisation (e.g. installLibrePortal) — capitalising
|
|
# only the first letter can't reproduce that camelCase. If the naive name
|
|
# isn't a defined function, resolve it case-insensitively against the real
|
|
# function table so any compound brand/app name (LibrePortal, …) just works.
|
|
if ! declare -F "$installFuncName" >/dev/null 2>&1; then
|
|
local _resolved
|
|
_resolved="$(compgen -A function | grep -ixF "install${app_name}" | head -n1)"
|
|
[[ -n "$_resolved" ]] && installFuncName="$_resolved"
|
|
fi
|
|
|
|
if ! declare -F "$installFuncName" >/dev/null 2>&1; then
|
|
# No per-app install function (no containers/<app>/<app>.sh defining
|
|
# one). Fall through to the generic installApp driver — it does the
|
|
# standard 10-step sequence and picks up any <slug>_install_* hooks
|
|
# the app declares in tools/<slug>_tools.sh. This is the path taken
|
|
# by every app that doesn't need bespoke install code: their
|
|
# <app>.sh has been deleted and the dispatcher routes them here.
|
|
if declare -F installApp >/dev/null 2>&1; then
|
|
installApp "$app_name" "$config_variables"
|
|
return $?
|
|
fi
|
|
isError "No installer function found for app '${app_name}' (looked for ${installFuncName}; installApp fallback unavailable)."
|
|
return 1
|
|
fi
|
|
|
|
# reset_network: "true" = re-roll IPs AND host ports; "ip" = re-roll the
|
|
# static IP only and PRESERVE published ports (the network-heal path — a
|
|
# subnet move strands the IP, not the port, so don't churn bookmarks /
|
|
# forwards / proxy upstreams). Anything else = preserve both (normal reuse).
|
|
if [[ "$reset_network" == "true" || "$reset_network" == "ip" ]]; then
|
|
export LIBREPORTAL_RESET_NETWORK=1
|
|
[[ "$reset_network" == "ip" ]] && export LIBREPORTAL_RESET_IP_ONLY=1
|
|
if declare -f ipRemoveFromDatabase >/dev/null 2>&1; then
|
|
ipRemoveFromDatabase "$app_name"
|
|
fi
|
|
if [[ "$reset_network" != "ip" ]] && declare -f portsRemoveFromDatabase >/dev/null 2>&1; then
|
|
portsRemoveFromDatabase "$app_name"
|
|
fi
|
|
if [[ "$reset_network" == "ip" ]]; then
|
|
isNotice "Network reset (IP-only): cleared previous IP allocation for $app_name; ports preserved."
|
|
else
|
|
isNotice "Network reset: cleared previous IP/port allocations for $app_name."
|
|
fi
|
|
fi
|
|
|
|
# Silently update the template config so apps.json regen reflects the saved
|
|
# values. The visible "Updated CFG_X" lines come from the deployed-config
|
|
# pass inside dockerConfigSetupToContainer.
|
|
if [[ -n "$config_variables" ]]; then
|
|
local template_config="$install_containers_dir$app_name/$app_name.config"
|
|
if [[ -f "$template_config" ]]; then
|
|
IFS='|' read -ra config_pairs <<< "$config_variables"
|
|
for pair in "${config_pairs[@]}"; do
|
|
if [[ "$pair" =~ ^(CFG_[A-Z0-9_]+)=(.*)$ ]]; then
|
|
local _value="${BASH_REMATCH[2]//%7C/|}"
|
|
updateConfigOption "${BASH_REMATCH[1]}" "$_value" "$template_config" >/dev/null
|
|
fi
|
|
done
|
|
fi
|
|
fi
|
|
|
|
# Create a variable with the name of $app_name and set its value to "i"
|
|
declare "${app_name}=i"
|
|
|
|
"${installFuncName}" "$config_variables"
|
|
|
|
if declare -f webuiGenerateLibrePortalConfig >/dev/null 2>&1; then
|
|
webuiGenerateLibrePortalConfig >/dev/null 2>&1 || true
|
|
fi
|
|
|
|
unset LIBREPORTAL_RESET_NETWORK LIBREPORTAL_RESET_IP_ONLY
|
|
}
|