File the owner's containers on the mirror during onboard, with the icon resolved where the Emby key is
This commit is contained in:
@@ -454,6 +454,31 @@ deploy_xml_stack() {
|
||||
#
|
||||
# Usage: ensure_stack_networks_on_remote "$MIRROR_IP" "$MIRROR_SSH_KEY"
|
||||
# ==============================================================================================
|
||||
# ==============================================================================================
|
||||
# ── Container names this onboard deploys, read from the templates it deploys them from ────────
|
||||
#
|
||||
# Echoes one name per line. The <Name> element is the same value deploy_xml_stack() passes to
|
||||
# `docker create --name`, so this is the deployed set by construction rather than by asking the
|
||||
# mirror what it ended up with — which would also pick up whatever the mirror already ran.
|
||||
#
|
||||
# Usage: mapfile -t names < <(deployed_stack_container_names)
|
||||
# ==============================================================================================
|
||||
deployed_stack_container_names() {
|
||||
local -a xml_names=()
|
||||
[[ ${#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 cname
|
||||
for xml_name in "${xml_names[@]}"; do
|
||||
[[ -z "$xml_name" ]] && continue
|
||||
xml_file="${TEMPLATES_DIR}/${xml_name}"
|
||||
[[ -f "$xml_file" ]] || continue
|
||||
cname=$(awk 'match($0,/<Name>([^<]+)<\/Name>/,a){print a[1];exit}' "$xml_file")
|
||||
[[ -n "$cname" ]] && echo "$cname"
|
||||
done
|
||||
}
|
||||
|
||||
ensure_stack_networks_on_remote() {
|
||||
local remote_ip="$1" ssh_key="$2"
|
||||
local -a xml_names=() nets=()
|
||||
|
||||
@@ -40,7 +40,8 @@
|
||||
// Icon resolution failing never blocks the folder: no image is a cosmetic loss, no folder is not.
|
||||
//
|
||||
// REQUEST
|
||||
// fallback_folder.php --host=HOST2 [--containers=A,B,C] [--dry-run]
|
||||
// fallback_folder.php --host=HOST2 [--containers=A,B,C] [--icon=URL] [--dry-run]
|
||||
// fallback_folder.php --host=HOST2 --icon-only resolve and print the icon URL, write nothing
|
||||
//
|
||||
// CONFIGURATION
|
||||
// HOST1/HOST2… master.conf — the hostname the folder is named after
|
||||
@@ -57,9 +58,10 @@ require_once $pluginDir . '/include/config.php';
|
||||
define('FV3_JSON', '/boot/config/plugins/folder.view3/docker.json');
|
||||
|
||||
// ── Args ──────────────────────────────────────────────────────────────────────
|
||||
$opts = ['host' => '', 'containers' => '', 'dry-run' => false];
|
||||
$opts = ['host' => '', 'containers' => '', 'icon' => '', 'dry-run' => false, 'icon-only' => false];
|
||||
foreach (array_slice($argv, 1) as $a) {
|
||||
if ($a === '--dry-run') { $opts['dry-run'] = true; continue; }
|
||||
if ($a === '--dry-run') { $opts['dry-run'] = true; continue; }
|
||||
if ($a === '--icon-only'){ $opts['icon-only'] = true; continue; }
|
||||
if (preg_match('/^--([a-z-]+)=(.*)$/', $a, $m)) $opts[$m[1]] = $m[2];
|
||||
}
|
||||
$hostId = strtoupper(trim($opts['host']));
|
||||
@@ -72,6 +74,7 @@ $vars = vv_conf_vars();
|
||||
$hostname = trim($vars[$hostId] ?? '');
|
||||
if ($hostname === '') { fwrite(STDERR, "$hostId is not set in master.conf\n"); exit(1); }
|
||||
|
||||
|
||||
// derive_short_name() in common.sh: lowercase, strip a leading "unraid-", capitalise.
|
||||
$short = preg_replace('/^unraid-/i', '', $hostname);
|
||||
$short = ucfirst($short);
|
||||
@@ -124,9 +127,40 @@ function vv_closest_emby_icon(string $short, array $vars, string $meId): array {
|
||||
}
|
||||
|
||||
$meId = strtoupper(vv_detect_host());
|
||||
[$icon, $iconNote] = vv_closest_emby_icon($short, $vars, $meId);
|
||||
|
||||
// --icon= skips the lookup entirely. The mirror needs this: it is being given a folder named
|
||||
// after the OWNER, and the avatar lives in the owner's Emby — which the mirror has no key for and
|
||||
// may not run at all. So the owner resolves the URL with --icon-only and hands it over, rather
|
||||
// than the mirror guessing from a userbase it cannot see.
|
||||
if (trim($opts['icon']) !== '') {
|
||||
$icon = trim($opts['icon']);
|
||||
$iconNote = 'supplied by caller';
|
||||
} else {
|
||||
[$icon, $iconNote] = vv_closest_emby_icon($short, $vars, $meId);
|
||||
}
|
||||
|
||||
// --icon-only: resolve and print, touch nothing. Exits non-zero when there is no icon, so a
|
||||
// caller can tell "no image" from "empty string because something broke".
|
||||
if ($opts['icon-only']) {
|
||||
if ($icon === '') { fwrite(STDERR, "no icon: $iconNote\n"); exit(1); }
|
||||
echo $icon . "\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// ── Upsert the folder ─────────────────────────────────────────────────────────
|
||||
// A host does not keep a fallback folder for itself — the folder means "containers I run on
|
||||
// SOMEONE ELSE's behalf", so naming it after this machine is always wrong. Checked here rather
|
||||
// than at argument parsing, because --icon-only legitimately asks for THIS host's own avatar:
|
||||
// the owner resolves its own picture to hand to the mirror, which is the whole point of that mode.
|
||||
//
|
||||
// Refused rather than created, because the failure is otherwise silent — an empty folder named
|
||||
// after yourself looks plausible enough to survive a glance. One appeared on HOST1 exactly this
|
||||
// way, when an older copy of this script ignored an unrecognised flag and ran the upsert anyway.
|
||||
if (strcasecmp($hostId, strtoupper(vv_detect_host())) === 0) {
|
||||
fwrite(STDERR, "$hostId is this host — a fallback folder is named after the PARTNER, not self\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if (!file_exists(FV3_JSON)) {
|
||||
echo "folder.view3 is not installed — nothing to do\n";
|
||||
exit(0);
|
||||
|
||||
Reference in New Issue
Block a user