Basic fixes for synology

This commit is contained in:
Adam Outler
2026-01-08 22:56:15 +00:00
parent e6194564b8
commit 739f17474f
8 changed files with 401 additions and 28 deletions

View File

@@ -6,6 +6,7 @@ They run in NETALERTX_CHECK_ONLY mode to avoid starting long-running services.
from __future__ import annotations
import base64
import os
import subprocess
import uuid
@@ -28,6 +29,27 @@ def _run_root_entrypoint(
) -> subprocess.CompletedProcess[str]:
name = f"netalertx-test-puidpgid-{uuid.uuid4().hex[:8]}".lower()
env_vars = dict(env or {})
processed_volumes: list[str] = []
proc_mounts_b64: str | None = None
if volumes:
for volume in volumes:
parts = volume.split(":")
if len(parts) >= 2 and os.path.normpath(parts[1]) == "/proc/mounts":
source_path = parts[0]
try:
with open(source_path, "rb") as fh:
proc_mounts_b64 = base64.b64encode(fh.read()).decode("ascii")
except OSError as exc:
raise RuntimeError(f"Failed to read mock /proc/mounts source: {source_path}") from exc
continue
else:
processed_volumes.append(volume)
if proc_mounts_b64 and "NETALERTX_PROC_MOUNTS_B64" not in env_vars:
env_vars["NETALERTX_PROC_MOUNTS_B64"] = proc_mounts_b64
cmd = [
"docker",
"run",
@@ -66,12 +88,12 @@ def _run_root_entrypoint(
if user:
cmd.extend(["--user", user])
if volumes:
for volume in volumes:
if processed_volumes:
for volume in processed_volumes:
cmd.extend(["-v", volume])
if env:
for key, value in env.items():
if env_vars:
for key, value in env_vars.items():
cmd.extend(["-e", f"{key}={value}"])
cmd.extend(["--entrypoint", "/root-entrypoint.sh"])
@@ -212,6 +234,95 @@ def test_synology_like_fresh_volume_is_primed() -> None:
print(result.stderr) # DO NOT REMOVE OR MODIFY - MANDATORY LOGGING FOR DEBUGGING & CI.
@pytest.mark.feature_complete
def test_aufs_explicit_root_no_warning() -> None:
"""Verify that explicitly setting PUID=0 on AUFS doesn't trigger the non-root warning."""
volume = f"nax_test_data_aufs_root_{uuid.uuid4().hex[:8]}".lower()
try:
subprocess.run(["docker", "volume", "create", volume], check=True, capture_output=True, text=True, timeout=15)
# Mock AUFS environment
mock_mounts_content = "none / aufs rw,relatime 0 0\n"
mock_file_path = f"/tmp/mock_mounts_{uuid.uuid4().hex[:8]}"
with open(mock_file_path, "w") as f:
f.write(mock_mounts_content)
# Run with explicit PUID=0 - should not warn about non-root
result = _run_root_entrypoint(
env={"PUID": "0", "PGID": "0", "SKIP_TESTS": "1"},
volumes=[f"{volume}:/data", f"{mock_file_path}:/proc/mounts:ro"],
)
combined = (result.stdout or "") + (result.stderr or "")
assert result.returncode == 0, f"Container should start: {combined}"
assert "Running as root (PUID=0)" in combined, f"Should confirm running as root: {combined}"
# Should NOT have the AUFS reduced functionality warning when running as root
assert "Reduced functionality (AUFS + non-root user)" not in combined, f"Should not warn when explicitly using root: {combined}"
# Clean up mock file
os.unlink(mock_file_path)
finally:
subprocess.run(["docker", "volume", "rm", "-f", volume], check=False, capture_output=True, text=True, timeout=15)
@pytest.mark.feature_complete
def test_aufs_non_root_warns() -> None:
"""Verify that AUFS hosts warn when running as a non-root PUID."""
volume = f"nax_test_data_aufs_warn_{uuid.uuid4().hex[:8]}".lower()
try:
subprocess.run(["docker", "volume", "create", volume], check=True, capture_output=True, text=True, timeout=15)
mock_mounts_content = "none / aufs rw,relatime 0 0\n"
mock_file_path = f"/tmp/mock_mounts_{uuid.uuid4().hex[:8]}"
with open(mock_file_path, "w") as f:
f.write(mock_mounts_content)
result = _run_root_entrypoint(
env={"PUID": "20211", "PGID": "20211"},
volumes=[f"{volume}:/data", f"{mock_file_path}:/proc/mounts:ro"],
)
combined = (result.stdout or "") + (result.stderr or "")
assert result.returncode == 0, f"Container should continue with warnings: {combined}"
assert "Reduced functionality (AUFS + non-root user)" in combined, f"AUFS warning missing: {combined}"
assert "aufs-capabilities" in combined, "Warning should link to troubleshooting guide"
os.unlink(mock_file_path)
finally:
subprocess.run(["docker", "volume", "rm", "-f", volume], check=False, capture_output=True, text=True, timeout=15)
@pytest.mark.feature_complete
def test_non_aufs_defaults_to_20211() -> None:
"""Verify that non-AUFS storage drivers default to PUID=20211."""
volume = f"nax_test_data_nonaufs_{uuid.uuid4().hex[:8]}".lower()
try:
subprocess.run(["docker", "volume", "create", volume], check=True, capture_output=True, text=True, timeout=15)
# Run with NO PUID set and normal storage driver - should default to 20211
result = _run_root_entrypoint(
env={"SKIP_TESTS": "1"},
volumes=[f"{volume}:/data"],
)
combined = (result.stdout or "") + (result.stderr or "")
assert result.returncode == 0, f"Container should start: {combined}"
# Should NOT mention AUFS
assert "AUFS" not in combined and "aufs" not in combined, f"Should not detect AUFS: {combined}"
# Should not auto-default to root
assert "Auto-defaulting to PUID=0" not in combined, f"Should not auto-default to root: {combined}"
finally:
subprocess.run(["docker", "volume", "rm", "-f", volume], check=False, capture_output=True, text=True, timeout=15)
@pytest.mark.feature_complete
def test_missing_cap_chown_fails_priming() -> None:
"""Verify that priming fails when CAP_CHOWN is missing and ownership change is needed."""