Publish curated Unraid-AppOps-Gateway source from 84f2a9958b2bdf1c1c13553925026d75f32703c3
This commit is contained in:
1 parent
8dd4b40252
commit
5d598db0df
14 files changed
+2765
-46
No files matched your search
@@ -24,6 +24,81 @@ spec.loader.exec_module(module)
|
||||
REVISION = "a" * 40
|
||||
IMAGE_ID = "sha256:" + "b" * 64
|
||||
ORIGINAL_COMPOSE = b"name: gitea-deploy-runners\nservices:\n deploy-control:\n image: immutable-controller\n"
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def compose_config_root(monkeypatch, tmp_path):
|
||||
# Production uses the fixed /tmp tmpfs; tests never write outside their tree.
|
||||
monkeypatch.setattr(module, "_COMPOSE_CONFIG_ROOT", tmp_path)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("operation", ["config", "stop", "up"])
|
||||
def test_compose_uses_private_ephemeral_cli_config_with_readonly_root(
|
||||
monkeypatch, tmp_path, operation,
|
||||
):
|
||||
directories = []
|
||||
|
||||
def run(arguments, *, data=None, diagnostic_action=None, **kwargs):
|
||||
# Compose up attempts to mkdir /root/.docker even for a dry run. The
|
||||
# controller promoter must keep its root filesystem read-only.
|
||||
assert arguments[:2] == ["docker", "--config"]
|
||||
directory = Path(arguments[2])
|
||||
directories.append(directory)
|
||||
assert directory.parent == tmp_path
|
||||
assert directory.name.startswith("itworx-controller-compose-")
|
||||
assert directory.is_dir() and not directory.is_symlink()
|
||||
if os.name == "posix":
|
||||
assert stat.S_IMODE(directory.stat().st_mode) == 0o700
|
||||
assert directory.stat().st_uid == os.getuid()
|
||||
assert arguments[3] == "compose"
|
||||
assert diagnostic_action == f"compose_{operation}"
|
||||
assert data == b"captured-private-compose"
|
||||
assert arguments[-1] == operation
|
||||
assert arguments[arguments.index("--env-file") + 1] == "/dev/null"
|
||||
assert arguments[arguments.index("-f") + 1] == "-"
|
||||
(directory / "generated-client-state").write_bytes(b"private-client-state")
|
||||
return b"ok"
|
||||
|
||||
monkeypatch.setattr(module, "_run", run)
|
||||
for _ in range(2):
|
||||
assert module._compose([operation], b"captured-private-compose") == b"ok"
|
||||
assert directories[0] != directories[1]
|
||||
assert all(not directory.exists() for directory in directories)
|
||||
|
||||
|
||||
def test_compose_private_cli_config_is_cleaned_after_command_failure(monkeypatch):
|
||||
directories = []
|
||||
failure = module.VolumeTransitionError(
|
||||
"controller_volume_command_failed",
|
||||
command_failure=("compose_up", "exit_1", "mount_read_only"),
|
||||
)
|
||||
|
||||
def run(arguments, **kwargs):
|
||||
directory = Path(arguments[2])
|
||||
directories.append(directory)
|
||||
(directory / "client-state").write_bytes(b"private-state")
|
||||
raise failure
|
||||
|
||||
monkeypatch.setattr(module, "_run", run)
|
||||
with pytest.raises(module.VolumeTransitionError) as caught:
|
||||
module._compose(["up"], b"private-compose")
|
||||
assert caught.value is failure
|
||||
assert directories and all(not directory.exists() for directory in directories)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("action", ["compose_config", "compose_stop", "compose_up", "image_inspect"])
|
||||
def test_compose_boundary_diagnostic_never_discloses_stderr(monkeypatch, action):
|
||||
stderr = b"mkdir /root/.docker: read-only file system fixture-secret-token"
|
||||
monkeypatch.setattr(module.subprocess, "run", lambda *args, **kwargs: types.SimpleNamespace(
|
||||
returncode=1, stdout=b"", stderr=stderr,
|
||||
))
|
||||
with pytest.raises(module.VolumeTransitionError) as caught:
|
||||
module._run(["docker", "fixed-operation"], diagnostic_action=action)
|
||||
diagnostic = module._safe_command_diagnostic(caught.value.command_failure)
|
||||
assert diagnostic == f"{action}_exit_1_mount_read_only"
|
||||
assert "fixture-secret-token" not in diagnostic
|
||||
assert "/root/.docker" not in diagnostic
|
||||
|
||||
# Frozen historical layouts; these fixtures must not follow the acceptance registry.
|
||||
HISTORICAL_PRE_CANDIDATE_RELEASE_FILES = (
|
||||
"controller_paths.py", "mcp_hub_release_store.py", "deploy.py",
|
||||
@@ -716,7 +791,8 @@ def test_compose_uses_protected_code_and_two_config_views(compose):
|
||||
assert rendered["services"]["runner"] == baseline["services"]["runner"]
|
||||
assert service["environment"] == baseline["services"]["deploy-control"]["environment"]
|
||||
compose_calls = [
|
||||
arguments for arguments, _ in calls if arguments[:2] == ["docker", "compose"]
|
||||
arguments for arguments, _ in calls
|
||||
if arguments[:2] == ["docker", "--config"] and arguments[3] == "compose"
|
||||
]
|
||||
assert compose_calls
|
||||
assert all("--project-directory" in arguments for arguments in compose_calls)
|
||||
@@ -1696,14 +1772,17 @@ def test_promoted_compose_actions_use_only_stdin_and_fixed_service(compose):
|
||||
assert baseline["name"] == "gitea-deploy-runners"
|
||||
|
||||
|
||||
def test_rollback_uses_no_dependencies_when_recreating_prior_controller(compose, tmp_path, monkeypatch):
|
||||
@pytest.mark.parametrize("phase", ["stopped", "activated"])
|
||||
def test_rollback_uses_no_dependencies_when_recreating_prior_controller(
|
||||
compose, tmp_path, monkeypatch, phase,
|
||||
):
|
||||
_baseline, calls = compose
|
||||
previous = REVISION
|
||||
target = "c" * 40
|
||||
previous_compose = module.rendered_model(ORIGINAL_COMPOSE, previous, IMAGE_ID)
|
||||
target_compose = module.rendered_model(ORIGINAL_COMPOSE, target, IMAGE_ID)
|
||||
receipt = {
|
||||
"phase": "activated",
|
||||
"phase": phase,
|
||||
"imageId": IMAGE_ID,
|
||||
"previousRevision": previous,
|
||||
"sourceRevision": target,
|
||||
@@ -1739,7 +1818,7 @@ def test_rollback_uses_no_dependencies_when_recreating_prior_controller(compose,
|
||||
|
||||
up_calls = [
|
||||
arguments for arguments, _data in calls
|
||||
if arguments[:2] == ["docker", "compose"] and "up" in arguments
|
||||
if arguments[:2] == ["docker", "--config"] and arguments[3] == "compose" and "up" in arguments
|
||||
]
|
||||
assert len(up_calls) == 1
|
||||
up_index = up_calls[0].index("up")
|
||||
|
||||
Reference in new issue
Block a user