Skip to content

Commit 412134f

Browse files
committed
feat: update port offset logic in m4b-config.json and fn_setupApps.py for consistent port assignment; enhance app port assignment function with unified formula and additional parameters
1 parent 5ca4ca7 commit 412134f

2 files changed

Lines changed: 70 additions & 53 deletions

File tree

config/m4b-config.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
},
77
"ports": {
88
"default_port_base": 50000,
9-
"port_offset_per_app": 100,
10-
"port_offset_per_instance": 10
9+
"port_offset_per_app": 1000,
10+
"port_offset_per_instance": 3
1111
},
1212
"system": {
1313
"sleep_time": 3,

utils/fn_setupApps.py

Lines changed: 68 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -170,35 +170,44 @@ def calculate_subnet(base_subnet: str, base_netmask: int, offset: int) -> str:
170170

171171

172172
def assign_app_ports(
173-
app_name: str, app: dict[str, Any], config: dict[str, Any]
173+
app_name: str,
174+
app: dict[str, Any],
175+
config: dict[str, Any],
176+
app_index: int = 0,
177+
instance_number: int = 0,
174178
) -> list[int]:
175179
"""
176-
Assign available ports for an app based on its configuration.
180+
Assign available ports for an app based on its configuration using consistent offset logic.
181+
182+
This function uses a unified formula for both main and multiproxy instances:
183+
port = DEFAULT_PORT_BASE + (app_index * PORT_OFFSET_PER_APP) + (instance_number * PORT_OFFSET_PER_INSTANCE) + port_within_app_offset
177184
178185
Args:
179186
app_name (str): Name of the app
180187
app (dict[str, Any]): App configuration containing compose_config
181188
config (dict[str, Any]): User configuration for the app
189+
app_index (int, optional): Zero-based index of the app in the apps list. Defaults to 0.
190+
instance_number (int, optional): Instance number (0 for main, 1+ for multiproxy). Defaults to 0.
182191
183192
Returns:
184193
list[int]: List of assigned available ports
185194
"""
186195
port_count = len(app["compose_config"]["ports"])
187196
assigned_ports = []
188-
default_ports = [DEFAULT_PORT_BASE + j for j in range(port_count)]
197+
198+
# Calculate the base port for this specific app and instance using the unified formula
199+
base_port_for_app_instance = (
200+
DEFAULT_PORT_BASE
201+
+ (app_index * PORT_OFFSET_PER_APP)
202+
+ (instance_number * PORT_OFFSET_PER_INSTANCE)
203+
)
189204

190205
for i in range(port_count):
191-
starting_port = config.get("ports", default_ports)
192-
# Determine the base port for this index
193-
if isinstance(starting_port, list):
194-
port_base = (
195-
starting_port[i] if i < len(starting_port) else DEFAULT_PORT_BASE + i
196-
)
197-
else:
198-
port_base = DEFAULT_PORT_BASE + i
206+
# For apps with multiple ports, add a small offset for each additional port
207+
port_candidate = base_port_for_app_instance + i
199208

200-
# Find next available port and assign it
201-
available_port = find_next_available_port(port_base)
209+
# Find next available port starting from the calculated candidate
210+
available_port = find_next_available_port(port_candidate)
202211
assigned_ports.append(available_port)
203212

204213
# Log the port assignment
@@ -208,7 +217,9 @@ def assign_app_ports(
208217
and i < len(app["compose_config"]["ports"])
209218
else f"port_{i + 1}"
210219
)
211-
logging.info(f"Port {port_placeholder} for {app_name} set to: {available_port}")
220+
logging.info(
221+
f"Port {port_placeholder} for {app_name} (app_index={app_index}, instance={instance_number}) set to: {available_port}"
222+
)
212223

213224
return assigned_ports
214225

@@ -420,15 +431,25 @@ def collect_user_info(user_config: dict[str, Any], m4b_config: dict[str, Any]) -
420431
logging.info(f"Device name set to: {device_name}")
421432

422433

423-
def _configure_apps(user_config: dict[str, Any], apps: dict, m4b_config: dict):
434+
def _configure_apps(
435+
user_config: dict[str, Any],
436+
apps: dict,
437+
m4b_config: dict,
438+
app_index_offset: int = 0,
439+
):
424440
"""
425441
Configure apps by collecting user inputs.
426442
427443
Args:
428444
user_config (dict): The user configuration dictionary.
429445
apps (dict): The app configuration dictionary.
430446
m4b_config (dict): The m4b configuration dictionary.
447+
app_index_offset (int): Starting port_app_index for this category.
448+
Defaults to 0. Only counts apps WITH ports.
431449
"""
450+
# Track port_app_index separately - only incremented for apps WITH ports
451+
port_app_index = app_index_offset
452+
432453
for app in apps:
433454
app_name = app["name"].lower()
434455
config = user_config["apps"].get(app_name, {})
@@ -463,12 +484,16 @@ def _configure_apps(user_config: dict[str, Any], apps: dict, m4b_config: dict):
463484
else:
464485
logging.error(f"Flag {flag_name} not recognized")
465486

466-
# Port configuration for apps with defined ports (should have a 'ports' key in the compose_config and a <app_name>_ports key in the user_config)
487+
# Port configuration with unified offset logic (instance 0 = main)
467488
if "ports" in app["compose_config"]:
468-
assigned_ports = assign_app_ports(app_name, app, config)
489+
assigned_ports = assign_app_ports(
490+
app_name, app, config, app_index=port_app_index, instance_number=0
491+
)
469492
# Always store as list for consistency
470493
config["ports"] = assigned_ports
471494
logging.info(f"Ports for {app_name} set to: {config['ports']}")
495+
# Only increment port_app_index for apps that actually have ports
496+
port_app_index += 1
472497

473498
user_config["apps"][app_name] = config
474499

@@ -484,7 +509,7 @@ def configure_apps(
484509
app_config (dict): The app configuration dictionary.
485510
m4b_config (dict): The m4b configuration dictionary.
486511
"""
487-
_configure_apps(user_config, app_config["apps"], m4b_config)
512+
_configure_apps(user_config, app_config["apps"], m4b_config, app_index_offset=0)
488513

489514

490515
def configure_extra_apps(
@@ -498,7 +523,14 @@ def configure_extra_apps(
498523
app_config (dict): The app configuration dictionary.
499524
m4b_config (dict): The m4b configuration dictionary.
500525
"""
501-
_configure_apps(user_config, app_config["extra-apps"], m4b_config)
526+
# Extra apps port_app_index starts AFTER regular apps WITH ports
527+
# Count only apps that have ports in compose_config
528+
port_consuming_apps = sum(
529+
1 for app in app_config.get("apps", []) if "ports" in app.get("compose_config", {})
530+
)
531+
_configure_apps(
532+
user_config, app_config["extra-apps"], m4b_config, app_index_offset=port_consuming_apps
533+
)
502534

503535

504536
# Supported services and their URL patterns
@@ -701,8 +733,9 @@ def setup_multiproxy_instances(
701733

702734
instance_m4b_config["network"]["subnet"] = new_subnet
703735

704-
# Update all enabled apps with unique ports to avoid conflicts
705-
app_index = 0
736+
# Update all enabled apps with unique ports using the unified assignment logic
737+
# Track port_app_index separately - only incremented for apps WITH ports
738+
port_app_index = 0
706739
for app_category in ["apps", "extra-apps"]:
707740
for app_details in instance_app_config.get(app_category, []):
708741
app_name = app_details["name"].lower()
@@ -713,7 +746,8 @@ def setup_multiproxy_instances(
713746
app_config_entry and app_config_entry.get("enabled", False)
714747
):
715748
logging.info(
716-
f"Processing port assignments for {app_name} in instance {instance_project_name}"
749+
f"Processing port assignments for {app_name} "
750+
f"in instance {instance_project_name}"
717751
)
718752

719753
# If app isn't in user_config yet, initialize it
@@ -722,42 +756,25 @@ def setup_multiproxy_instances(
722756
app_config_entry = instance_user_config["apps"][app_name]
723757

724758
# Check if this app has ports defined in compose_config
725-
has_ports = False
726759
if (
727760
"compose_config" in app_details
728761
and "ports" in app_details["compose_config"]
729762
):
730-
has_ports = True
731-
732-
# Or check if it already has ports in user_config
733-
if "ports" in app_config_entry:
734-
has_ports = True
735-
736-
# If app uses ports, ensure they're unique for this instance
737-
if has_ports:
738-
# Get base port from user config or default
739-
base_port = app_config_entry.get(
740-
"ports",
741-
[DEFAULT_PORT_BASE + app_index * PORT_OFFSET_PER_APP],
763+
# Use unified port assignment logic (instance number = i+1)
764+
assigned_ports = assign_app_ports(
765+
app_name,
766+
app_details,
767+
app_config_entry,
768+
app_index=port_app_index,
769+
instance_number=i + 1,
742770
)
743-
# Ensure we have a list (handles legacy configs with int)
744-
if not isinstance(base_port, list):
745-
base_port = [base_port]
746-
747-
# Update all ports with unique values for this instance
748-
app_config_entry["ports"] = [
749-
find_next_available_port(
750-
port + (i + 1) * PORT_OFFSET_PER_INSTANCE
751-
)
752-
for port in base_port
753-
]
771+
app_config_entry["ports"] = assigned_ports
754772
logging.info(
755-
f"Updated ports for {app_name} in instance "
756-
f"{instance_project_name} to {app_config_entry['ports']}"
773+
f"Assigned ports for {app_name} in instance "
774+
f"{instance_project_name}: {assigned_ports}"
757775
)
758-
759-
# Increment app index for each enabled app processed
760-
app_index += 1
776+
# Only increment port_app_index for apps that have ports
777+
port_app_index += 1
761778

762779
# Properly disable dashboard for multiproxy instances to avoid port conflicts
763780
if "m4b_dashboard" in instance_user_config:

0 commit comments

Comments
 (0)