Files
minerops/backend/tests/test_legacy_agent_production_postgres.py
T

224 lines
7.4 KiB
Python

"""Fresh-chain production compatibility contract for the legacy Plexus Agent."""
import asyncio
import json
import os
import unittest
from uuid import UUID
import psycopg
from starlette.requests import Request
from app.agent_auth.exceptions import (
AgentAuthenticationFailed,
AgentIdentityUnauthorized,
)
from app.agent_auth.repository import AgentAuthRepository
from app.agent_auth.service import AgentAuthService, hash_agent_secret
from app.agent_zones.repository import AgentZoneRepository
from app.agent_zones.service import AgentZoneService
from app.config import settings
from app.main import (
minerops_agent_known_miners,
minerops_agent_miner_snapshots,
)
SITE_A = UUID("00000000-0000-4000-8000-000000001901")
SITE_B = UUID("00000000-0000-4000-8000-000000001902")
MINER_A = UUID("00000000-0000-4000-8000-000000001911")
MINER_B = UUID("00000000-0000-4000-8000-000000001912")
LEGACY_AGENT = "legacy-plexus-production"
NEW_AGENT = "enrolled-agent-production-contract"
NEW_SECRET = "new-agent-production-contract-secret"
def connect():
return psycopg.connect(
host=settings.postgres_host,
port=settings.postgres_port,
dbname=settings.postgres_db,
user=settings.postgres_user,
password=settings.postgres_password,
connect_timeout=5,
)
def json_request(payload):
body = json.dumps(payload).encode("utf-8")
delivered = False
async def receive():
nonlocal delivered
if delivered:
return {"type": "http.request", "body": b"", "more_body": False}
delivered = True
return {"type": "http.request", "body": body, "more_body": False}
return Request(
{
"type": "http",
"asgi": {"version": "3.0"},
"http_version": "1.1",
"method": "POST",
"scheme": "http",
"path": "/api/agent/miner-snapshots",
"raw_path": b"/api/agent/miner-snapshots",
"query_string": b"",
"headers": [(b"content-type", b"application/json")],
"client": ("testclient", 12345),
"server": ("testserver", 80),
},
receive,
)
class LegacyAgentProductionPostgresTests(unittest.TestCase):
@classmethod
def setUpClass(cls):
if os.environ.get("MINEROPS_LEGACY_PRODUCTION_DISPOSABLE") != "1":
raise unittest.SkipTest(
"Legacy production contract requires its disposable PostgreSQL runner"
)
if settings.minerops_agent_id != LEGACY_AGENT:
raise AssertionError("Runner did not bind the configured legacy identity")
cls.auth = AgentAuthService(AgentAuthRepository(connect))
cls.zones = AgentZoneService(AgentZoneRepository(connect))
connection = connect()
try:
with connection.cursor() as cur:
cur.execute(
"""
SELECT agent_zone_id
FROM minerops_site_agents
WHERE agent_id = %s
""",
(LEGACY_AGENT,),
)
cls.zone_a = cur.fetchone()[0]
cur.execute(
"""
SELECT id
FROM agent_zones
WHERE site_id = %s AND name = 'Default Zone'
""",
(SITE_B,),
)
cls.zone_b = cur.fetchone()[0]
cur.execute(
"""
INSERT INTO minerops_site_agents (
agent_id, site_id, agent_zone_id, site_name,
agent_secret_hash, credential_created_at,
legacy_auth_disabled_at
)
VALUES (
%s, %s, %s, 'Enrolled Contract Agent', %s, now(), now()
)
""",
(
NEW_AGENT,
SITE_B,
cls.zone_b,
hash_agent_secret(NEW_SECRET),
),
)
connection.commit()
finally:
connection.close()
def test_secret_only_auth_is_bounded_to_legacy_identity(self):
self.assertEqual(
self.auth.authenticate(None, settings.minerops_agent_shared_secret),
LEGACY_AGENT,
)
with self.assertRaises(AgentIdentityUnauthorized):
self.auth.authenticate(
"unknown-agent", settings.minerops_agent_shared_secret
)
with self.assertRaises(AgentAuthenticationFailed):
self.auth.authenticate(
NEW_AGENT, settings.minerops_agent_shared_secret
)
self.assertEqual(
self.auth.authenticate(NEW_AGENT, NEW_SECRET),
NEW_AGENT,
)
def test_migrated_legacy_agent_has_correct_site_and_zone(self):
routing = self.zones.routing_context(LEGACY_AGENT)
self.assertIsNone(routing.routing_reason)
self.assertEqual(routing.site_id, SITE_A)
self.assertEqual(routing.agent_zone_id, self.zone_a)
def test_known_miners_and_telemetry_remain_zone_scoped(self):
known = asyncio.run(
minerops_agent_known_miners(LEGACY_AGENT, self.zones)
)
self.assertEqual(
[row["miner_id"] for row in known["miners"]],
[str(MINER_A)],
)
result = asyncio.run(
minerops_agent_miner_snapshots(
json_request(
{
"agent_id": LEGACY_AGENT,
"site_name": "Plexus",
"miners": [
{
"miner_id": str(MINER_A),
"ip_address": "192.0.2.191",
"online": False,
},
{
"miner_id": str(MINER_B),
"ip_address": "192.0.2.192",
"online": False,
},
],
}
),
LEGACY_AGENT,
self.zones,
)
)
self.assertEqual(result["agent_zone_id"], str(self.zone_a))
self.assertEqual(result["apply_result"]["applied"], 1)
self.assertIn(
{"miner_id": str(MINER_B), "error": "agent_zone_conflict"},
result["apply_result"]["errors"],
)
connection = connect()
try:
with connection.cursor() as cur:
cur.execute(
"SELECT status FROM miners WHERE id = %s",
(MINER_A,),
)
self.assertEqual(cur.fetchone()[0], "offline")
cur.execute(
"SELECT status FROM miners WHERE id = %s",
(MINER_B,),
)
self.assertEqual(cur.fetchone()[0], "online")
cur.execute(
"""
SELECT count(*)
FROM minerops_agent_snapshots
WHERE agent_id = %s AND agent_zone_id = %s
""",
(LEGACY_AGENT, self.zone_a),
)
self.assertGreaterEqual(cur.fetchone()[0], 1)
finally:
connection.close()
if __name__ == "__main__":
unittest.main()