142 lines
4.3 KiB
Python
142 lines
4.3 KiB
Python
from types import SimpleNamespace
|
|
|
|
import pytest
|
|
|
|
from backend.app.connectors.portainer import PortainerConnector
|
|
from backend.app.core.config import settings
|
|
|
|
CONTROLLER_OWNED_CI_NAMES = (
|
|
"itworx-ci-checks",
|
|
"itworx-ci-backend",
|
|
"itworx-ci-frontend",
|
|
"itworx-ci-security",
|
|
"itworx-ci-browser",
|
|
"itworx-ci-build",
|
|
"itworx-security-runner",
|
|
"itworx-validation-runner-2",
|
|
"itworx-validation-runner-3",
|
|
"itworx-docker-runner",
|
|
"itworx-browser-runner",
|
|
"itworx-validation-runner-burst-1",
|
|
"gitea-runner-dind",
|
|
)
|
|
|
|
|
|
def _connector_with_containers(monkeypatch, containers):
|
|
monkeypatch.setitem(settings.apis, "PORTAINER_URL", "https://portainer.example.test")
|
|
monkeypatch.setitem(settings.apis, "PORTAINER_API_KEY", "test-key")
|
|
monkeypatch.setitem(settings.apis, "PORTAINER_ENDPOINT_ID", "9")
|
|
|
|
connector = PortainerConnector()
|
|
monkeypatch.setattr(
|
|
connector,
|
|
"list_containers",
|
|
lambda: {"status": "ok", "containers": containers},
|
|
)
|
|
calls = []
|
|
|
|
def request(method: str, path: str, **kwargs):
|
|
calls.append((method, path, kwargs))
|
|
return SimpleNamespace(status_code=204)
|
|
|
|
monkeypatch.setattr(connector, "_request", request)
|
|
return connector, calls
|
|
|
|
|
|
def test_restart_request_allows_docker_grace_period_without_shortening_container_timeout(monkeypatch):
|
|
previous = dict(settings.apis)
|
|
settings.apis.update({
|
|
"PORTAINER_URL": "https://portainer.example.test",
|
|
"PORTAINER_API_KEY": "test-key",
|
|
"PORTAINER_ENDPOINT_ID": "9",
|
|
})
|
|
connector = PortainerConnector()
|
|
monkeypatch.setattr(
|
|
connector,
|
|
"list_containers",
|
|
lambda: {
|
|
"status": "ok",
|
|
"containers": [{"id": "user-container-id", "name": "jellyfin", "appId": "jellyfin"}],
|
|
},
|
|
)
|
|
calls: list[tuple[str, str, dict]] = []
|
|
|
|
def request(method: str, path: str, **kwargs):
|
|
calls.append((method, path, kwargs))
|
|
return SimpleNamespace(status_code=204)
|
|
|
|
monkeypatch.setattr(connector, "_request", request)
|
|
try:
|
|
result = connector.restart_container("jellyfin")
|
|
finally:
|
|
settings.apis.clear()
|
|
settings.apis.update(previous)
|
|
|
|
assert result["status"] == "ok"
|
|
assert calls == [(
|
|
"POST",
|
|
"/api/endpoints/9/docker/containers/user-container-id/restart",
|
|
{"timeout": 30.0},
|
|
)]
|
|
|
|
|
|
@pytest.mark.parametrize("container_name", CONTROLLER_OWNED_CI_NAMES)
|
|
def test_restart_blocks_fixed_controller_owned_ci_containers_by_name(monkeypatch, container_name):
|
|
connector, calls = _connector_with_containers(
|
|
monkeypatch,
|
|
[{"id": "0123456789abcdef0123456789abcdef", "name": container_name, "appId": "ci-stack"}],
|
|
)
|
|
|
|
result = connector.restart_container(container_name)
|
|
|
|
assert result == {"status": "blocked", "reason": "controller_owned_ci_lifecycle"}
|
|
assert calls == []
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"target",
|
|
(
|
|
"itworx-ci-backend",
|
|
"0123456789abcdef0123456789abcdef",
|
|
"01234567",
|
|
"backend-ci-stack",
|
|
),
|
|
)
|
|
def test_restart_blocks_controller_owned_container_selected_by_alias(monkeypatch, target):
|
|
connector, calls = _connector_with_containers(
|
|
monkeypatch,
|
|
[{
|
|
"id": "0123456789abcdef0123456789abcdef",
|
|
"name": "itworx-ci-backend",
|
|
"appId": "backend-ci-stack",
|
|
}],
|
|
)
|
|
|
|
result = connector.restart_container(target)
|
|
|
|
assert result == {"status": "blocked", "reason": "controller_owned_ci_lifecycle"}
|
|
assert calls == []
|
|
|
|
|
|
@pytest.mark.parametrize("container_name", ("itworx-unraid-deploy", "jellyfin"))
|
|
def test_restart_still_allows_unrelated_deploy_and_user_containers(monkeypatch, container_name):
|
|
container_id = f"id-{container_name}"
|
|
connector, calls = _connector_with_containers(
|
|
monkeypatch,
|
|
[{"id": container_id, "name": container_name, "appId": container_name}],
|
|
)
|
|
|
|
result = connector.restart_container(container_name)
|
|
|
|
assert result == {
|
|
"status": "ok",
|
|
"container": container_id,
|
|
"target": container_name,
|
|
"action": "container.restart",
|
|
}
|
|
assert calls == [(
|
|
"POST",
|
|
f"/api/endpoints/9/docker/containers/{container_id}/restart",
|
|
{"timeout": 30.0},
|
|
)]
|