Merge pull request #1478 from adamoutler/first-run-auto-configure-scan_subnets

First run auto configure scan subnets
This commit is contained in:
Jokob @NetAlertX
2026-02-01 16:00:36 +11:00
committed by GitHub
4 changed files with 109 additions and 14 deletions

View File

@@ -937,6 +937,23 @@ def test_missing_app_conf_triggers_seed(tmp_path: pathlib.Path) -> None:
volume_specs=[f"{vol}:/data"],
sleep_seconds=15,
)
# Verify the generated configuration contains the dynamic subnet detection
# (check that it didn't fall back to default '--localnet')
check_conf = subprocess.run(
[
"docker", "run", "--rm", "-v", f"{vol}:/data",
"alpine:3.22", "cat", "/data/config/app.conf"
],
capture_output=True, text=True, timeout=SUBPROCESS_TIMEOUT_SECONDS
)
assert check_conf.returncode == 0, f"Failed to read config. Stderr: {check_conf.stderr}, Stdout: {check_conf.stdout}"
match = re.search(r"SCAN_SUBNETS\s*=\s*(.*)", check_conf.stdout)
if match:
val = match.group(1)
assert "interface=" in val, f"SCAN_SUBNETS should have interface: {val}"
assert val != "['--localnet']", "SCAN_SUBNETS should not be default localnet"
finally:
_docker_volume_rm(vol)
# The key assertion: config seeding happened
@@ -945,6 +962,48 @@ def test_missing_app_conf_triggers_seed(tmp_path: pathlib.Path) -> None:
# test passes if the config file was created. Full startup success is tested elsewhere.
def test_first_run_dynamic_subnet(tmp_path: pathlib.Path) -> None:
"""Test dynamic subnet detection during first run config generation.
Ensures that when app.conf is generated, it detects the actual network interfaces
instead of defaulting to '--localnet'.
"""
paths = _setup_mount_tree(tmp_path, "dynamic_subnet", seed_config=False)
mount_args = _build_volume_args_for_keys(paths, CONTAINER_TARGETS.keys())
result_container = _run_container(
"dyn-subnet",
volumes=mount_args,
sleep_seconds=15,
user="0:0",
)
assert result_container.returncode == 0, f"Container failed: {result_container.output}"
# Use docker to read the file to avoid permission issues (file is 600 root:root)
# paths["app_config"] is the host absolute path
cmd = [
"docker", "run", "--rm",
"-v", f"{paths['app_config']}:/mnt",
"alpine:3.22",
"cat", "/mnt/app.conf"
]
read_result = subprocess.run(cmd, capture_output=True, text=True, timeout=SUBPROCESS_TIMEOUT_SECONDS)
assert read_result.returncode == 0, f"Could not read app.conf. Stderr: {read_result.stderr}, Stdout: {read_result.stdout}"
content = read_result.stdout
# Check that SCAN_SUBNETS was set to something other than the default fallback
# The default fallback in the script is ['--localnet'] if no interfaces found.
# But in test environment (and prod), we expect interfaces.
match = re.search(r"SCAN_SUBNETS\s*=\s*(.*)", content)
assert match, "SCAN_SUBNETS not found in config"
val = match.group(1)
# verify it contains an interface definition
assert "interface=" in val, f"SCAN_SUBNETS should contain interface spec, got: {val}"
assert val != "['--localnet']", "SCAN_SUBNETS should not be default localnet"
def test_missing_app_db_triggers_seed(tmp_path: pathlib.Path) -> None:
"""Test missing database file seeding - simulates corrupted/missing app.db.