Initial server source import

This commit is contained in:
sashatrask
2026-09-30 20:30:56 +03:00
commit 170dd941b9
498 changed files with 261563 additions and 0 deletions
+195
View File
@@ -0,0 +1,195 @@
import hashlib
import json
import os
from pathlib import Path
import sys
import tempfile
import unittest
import uuid
from unittest import mock
ROOT = Path(__file__).resolve().parents[1]
APP_DIR = ROOT / 'app'
sys.path.insert(0, str(APP_DIR))
import host_agent_state
from host_agent_protocol import HostAgentAction, HostAgentRequest
class HostAgentStateTests(unittest.TestCase):
def request(self, *, operation_id=None):
return HostAgentRequest(
operation_id=operation_id or str(uuid.uuid4()),
action=HostAgentAction.APPLY_BOTH,
active_config_sha256=hashlib.sha256(b'old config').hexdigest(),
active_secrets_sha256=hashlib.sha256(b'old secrets').hexdigest(),
candidate_config_sha256=hashlib.sha256(b'new config').hexdigest(),
candidate_secrets_sha256=hashlib.sha256(b'new secrets').hexdigest(),
)
def store(self):
temporary = tempfile.TemporaryDirectory()
root = Path(temporary.name)
state = root / 'state'
operations = state / 'operations'
results = state / 'results'
state.mkdir(mode=0o700)
operations.mkdir(mode=0o700)
results.mkdir(mode=0o750)
for path, mode in ((state, 0o700), (operations, 0o700), (results, 0o750)):
os.chmod(path, mode)
details = os.stat(root)
patch = mock.patch.multiple(
host_agent_state,
HOST_ROOT_UID=getattr(details, 'st_uid', 0),
HOST_ROOT_GID=getattr(details, 'st_gid', 0),
HOST_RUNTIME_GID=getattr(details, 'st_gid', 0),
HOST_STATE_ROOT=state,
HOST_OPERATION_DIRECTORY=operations,
HOST_RESULT_DIRECTORY=results,
HOST_FAILED_HOLD_PATH=state / 'failed-hold.json',
)
return temporary, root, patch
def test_persists_canonical_phase_and_exact_terminal_result(self):
temporary, root, patch = self.store()
with temporary, patch:
request = self.request()
state = host_agent_state.HostOperationState(request)
prepared = state.initialize()
self.assertEqual(prepared['phase'], 'prepared')
state.advance('prepared', 'forward_started', 'original')
identity = {
'active_config_sha256': request.candidate_config_sha256,
'active_secrets_sha256': request.candidate_secrets_sha256,
}
state.advance('forward_started', 'succeeded', 'candidate')
expected = state.publish_result(
'succeeded', safe_category=None, safe_detail=None,
resulting_identity=identity,
)
replay = host_agent_state.HostOperationState(request)
self.assertEqual(replay.initialize()['phase'], 'succeeded')
self.assertEqual(replay.terminal_result(), expected)
payload = replay.result_path.read_bytes()
self.assertEqual(
payload,
json.dumps(
expected, sort_keys=True, separators=(',', ':'),
).encode('ascii'),
)
def test_result_replay_is_exact_and_conflicting_bytes_are_rejected(self):
temporary, _root, patch = self.store()
with temporary, patch:
request = self.request()
state = host_agent_state.HostOperationState(request)
state.initialize()
identity = {
'active_config_sha256': request.active_config_sha256,
'active_secrets_sha256': request.active_secrets_sha256,
}
state.publish_result(
'rolled_back', safe_category='health_check_failed',
safe_detail='health_check_failed', resulting_identity=identity,
)
state.publish_result(
'rolled_back', safe_category='health_check_failed',
safe_detail='health_check_failed', resulting_identity=identity,
)
with self.assertRaises(host_agent_state.HostStateError) as raised:
state.publish_result(
'rolled_back', safe_category='restart_failed',
safe_detail='restart_failed', resulting_identity=identity,
)
self.assertEqual(raised.exception.category, 'conflict')
def test_failed_hold_is_durable_and_fences_new_operations(self):
temporary, _root, patch = self.store()
with temporary, patch:
request = self.request()
state = host_agent_state.HostOperationState(request)
state.initialize('partial')
state.advance(
'prepared', 'rollback_started', 'partial',
forward_category='apply_failed',
)
state.publish_failed_hold(
forward_category='apply_failed', publication_state='partial',
containment_confirmed=True,
)
state.advance(
'rollback_started', 'failed_hold', 'partial',
forward_category='apply_failed', safe_detail='rollback_failed',
containment_confirmed=True,
)
self.assertEqual(
host_agent_state.failed_hold_operation(), request.operation_id,
)
self.assertEqual(
host_agent_state.HostOperationState(request).initialize()['phase'],
'failed_hold',
)
with self.assertRaises(host_agent_state.HostStateError) as raised:
host_agent_state.HostOperationState(self.request()).initialize()
self.assertEqual(raised.exception.category, 'failed_hold')
def test_post_replace_phase_write_is_reported_as_uncertain(self):
temporary, _root, patch = self.store()
with temporary, patch:
request = self.request()
state = host_agent_state.HostOperationState(request)
state.initialize()
with mock.patch.object(
host_agent_state, 'fsync_directory',
side_effect=OSError('sync detail'),
):
with self.assertRaises(host_agent_state.HostStateError) as raised:
state.advance('prepared', 'forward_started', 'original')
self.assertEqual(raised.exception.category, 'uncertain')
self.assertEqual(state._read_phase()['phase'], 'forward_started')
def test_post_replace_cancellation_is_retained_as_uncertain(self):
temporary, _root, patch = self.store()
with temporary, patch:
request = self.request()
state = host_agent_state.HostOperationState(request)
state.initialize()
cancellation = KeyboardInterrupt()
with mock.patch.object(
host_agent_state, 'fsync_directory',
side_effect=cancellation,
):
with self.assertRaises(host_agent_state.HostStateError) as raised:
state.advance('prepared', 'forward_started', 'original')
self.assertEqual(raised.exception.category, 'uncertain')
self.assertIs(raised.exception.cancellation, cancellation)
self.assertEqual(state._read_phase()['phase'], 'forward_started')
def test_phase_request_identity_and_transition_are_closed(self):
temporary, _root, patch = self.store()
with temporary, patch:
request = self.request()
state = host_agent_state.HostOperationState(request)
state.initialize()
with self.assertRaises(host_agent_state.HostStateError):
state.advance('prepared', 'succeeded', 'candidate')
altered = HostAgentRequest(
operation_id=request.operation_id,
action=request.action,
active_config_sha256=request.active_config_sha256,
active_secrets_sha256=request.active_secrets_sha256,
candidate_config_sha256='f' * 64,
candidate_secrets_sha256=request.candidate_secrets_sha256,
)
with self.assertRaises(host_agent_state.HostStateError) as raised:
host_agent_state.HostOperationState(altered).initialize()
self.assertEqual(raised.exception.category, 'evidence')
if __name__ == '__main__':
unittest.main()