Files
NexaFabric/backend/tests/test_proxmox_provider.py
T
nessi d651a11472 feat: add automatic policy rule cleanup when disabling or switching to audit mode with provider-level rule deletion
Add cluster_provider_targets helper to build target list from all cluster workloads, implement cleanup_policy_provider_rules to delete policy rules across all clusters with per-cluster result tracking, add delete_policy_rules method to ProxmoxProvider that removes rules matching policy ID marker with error collection, extend policy_id_marker and rule_comment_matches_marker helpers for
2026-07-09 21:31:20 +02:00

130 lines
4.5 KiB
Python

import pytest
from app.services.providers import proxmox
from app.services.providers.base import ProviderConnection
from app.services.providers.proxmox import ProxmoxProvider
class FakeResponse:
def __init__(self, data: object) -> None:
self._data = data
def json(self) -> dict:
return {"data": self._data}
def raise_for_status(self) -> None:
return None
class FakeAsyncClient:
deleted_urls: list[str] = []
posted_payloads: list[dict] = []
put_urls: list[str] = []
put_payloads: list[dict] = []
def __init__(self, **_: object) -> None:
return None
async def __aenter__(self) -> "FakeAsyncClient":
return self
async def __aexit__(self, *_: object) -> None:
return None
async def get(self, url: str, **__: object) -> FakeResponse:
if url.endswith("/config"):
return FakeResponse({"net0": "virtio=AA:BB:CC:DD:EE:FF,bridge=vmbr0,firewall=0", "name": "web"})
if url.endswith("/cluster/firewall/options"):
return FakeResponse({"enable": 1})
if url.endswith("/firewall/options"):
return FakeResponse({"enable": 1})
return FakeResponse(
[
{"pos": 0, "comment": "manual rule"},
{"pos": 1, "comment": "NexaFabric policy=policy-1 version=1 rule=1 target=web"},
]
)
async def delete(self, url: str, **__: object) -> FakeResponse:
self.deleted_urls.append(url)
return FakeResponse(None)
async def put(self, url: str, data: dict, **__: object) -> FakeResponse:
self.put_urls.append(url)
self.put_payloads.append(data)
return FakeResponse(None)
async def post(self, _: str, data: dict, **__: object) -> FakeResponse:
self.posted_payloads.append(data)
return FakeResponse({"pos": 1})
@pytest.mark.asyncio
async def test_apply_rules_replaces_only_marked_nexafabric_rules(monkeypatch: pytest.MonkeyPatch) -> None:
FakeAsyncClient.deleted_urls = []
FakeAsyncClient.posted_payloads = []
FakeAsyncClient.put_urls = []
FakeAsyncClient.put_payloads = []
monkeypatch.setattr(proxmox.httpx, "AsyncClient", FakeAsyncClient)
result = await ProxmoxProvider().apply_rules(
ProviderConnection(api_url="https://pve.example:8006", token="user@pve!token=secret", read_only=False),
[
{
"policy_id": "policy-1",
"audit_only": False,
"provider_target": {"node": "pve1", "kind": "qemu", "vmid": "100"},
"provider_rule": {
"type": "in",
"action": "ACCEPT",
"enable": 1,
"proto": "tcp",
"dport": "443",
"comment": "NexaFabric policy=policy-1 version=2 rule=1 target=web",
},
}
],
)
assert result["applied"] is True
assert result["rules_deleted"] == 1
assert FakeAsyncClient.deleted_urls == ["https://pve.example:8006/api2/json/nodes/pve1/qemu/100/firewall/rules/1"]
assert FakeAsyncClient.put_urls == [
"https://pve.example:8006/api2/json/nodes/pve1/qemu/100/firewall/options",
"https://pve.example:8006/api2/json/nodes/pve1/qemu/100/config",
]
assert FakeAsyncClient.put_payloads == [
{"enable": 1},
{"net0": "virtio=AA:BB:CC:DD:EE:FF,bridge=vmbr0,firewall=1"},
]
assert FakeAsyncClient.posted_payloads == [
{
"type": "in",
"action": "ACCEPT",
"enable": 1,
"proto": "tcp",
"dport": "443",
"comment": "NexaFabric policy=policy-1 version=2 rule=1 target=web",
}
]
@pytest.mark.asyncio
async def test_delete_policy_rules_removes_marked_rules(monkeypatch: pytest.MonkeyPatch) -> None:
FakeAsyncClient.deleted_urls = []
FakeAsyncClient.posted_payloads = []
FakeAsyncClient.put_urls = []
FakeAsyncClient.put_payloads = []
monkeypatch.setattr(proxmox.httpx, "AsyncClient", FakeAsyncClient)
result = await ProxmoxProvider().delete_policy_rules(
ProviderConnection(api_url="https://pve.example:8006", token="user@pve!token=secret", read_only=False),
[{"node": "pve1", "kind": "qemu", "vmid": "100"}],
"policy-1",
)
assert result["applied"] is True
assert result["rules_deleted"] == 1
assert FakeAsyncClient.deleted_urls == ["https://pve.example:8006/api2/json/nodes/pve1/qemu/100/firewall/rules/1"]
assert FakeAsyncClient.posted_payloads == []