import unittest from dataclasses import dataclass, field from datetime import datetime, timezone from dns_sync.adapters import ( CERTIFICATES, DNS_RECORDS, PROXY_HOSTS, Capability, CapabilityOperation, Endpoint, EndpointPlan, NormalizedObject, PlanAction, PlanOperation, ) from dns_sync.executor import execute_endpoint_plans from dns_sync.persistence import SQLiteStateStore NOW = datetime(2026, 9, 19, 23, 15, tzinfo=timezone.utc) def object_for( object_type: str, logical_key: str, ) -> NormalizedObject: if object_type == DNS_RECORDS: payload = { "hostname": logical_key, "ip": "192.168.1.101", "record_type": "A", "wildcard": False, } elif object_type == CERTIFICATES: payload = { "domain_names": [logical_key], "expires_on": "2026-12-15T00:00:00+00:00", } else: payload = { "domain_names": [logical_key], "forward_scheme": "http", "forward_host": "192.168.1.50", "forward_port": 8080, "enabled": True, } return NormalizedObject( object_type=object_type, logical_key=logical_key, payload=payload, ) def action( endpoint_id: str, operation: PlanOperation, object_type: str = DNS_RECORDS, logical_key: str = "app.example.com", ) -> PlanAction: return PlanAction( endpoint_id=endpoint_id, operation=operation, desired=object_for(object_type, logical_key), ) def capabilities( *object_types: str, verify: bool = True, ) -> frozenset[Capability]: result = { Capability( object_type, CapabilityOperation.APPLY, ) for object_type in object_types } if verify: result.update( Capability( object_type, CapabilityOperation.VERIFY, ) for object_type in object_types ) return frozenset(result) @dataclass class FakeAdapter: endpoint: Endpoint capabilities: frozenset[Capability] verify_result: bool = True apply_error: Exception | None = None verify_error: Exception | None = None events: list[tuple[str, str, str]] = field( default_factory=list ) def apply(self, plan_action): desired = plan_action.desired self.events.append( ( "apply", desired.object_type, desired.logical_key, ) ) if self.apply_error is not None: raise self.apply_error return "test detail" def verify(self, object): self.events.append( ( "verify", object.object_type, object.logical_key, ) ) if self.verify_error is not None: raise self.verify_error return self.verify_result class ExecutionTests(unittest.TestCase): def test_successful_actions_are_applied_verified_and_persisted(self): endpoint = Endpoint("verizon", "192.168.1.1:443") adapter = FakeAdapter( endpoint, capabilities(DNS_RECORDS), ) plan = EndpointPlan( endpoint.identity, ( action( endpoint.identity, PlanOperation.CREATE, logical_key="add.example.com", ), action( endpoint.identity, PlanOperation.NOOP, logical_key="keep.example.com", ), action( endpoint.identity, PlanOperation.UPDATE, logical_key="update.example.com", ), ), ) with SQLiteStateStore(":memory:") as store: result = execute_endpoint_plans( [adapter], [plan], store, executed_at=NOW, ) persisted = store.load_applied_state( endpoint.identity, DNS_RECORDS, ) self.assertEqual(len(result.applied), 2) self.assertEqual(len(result.skipped), 1) self.assertTrue(all(row.is_verified for row in persisted)) self.assertEqual( {row.object.logical_key for row in persisted}, {"add.example.com", "update.example.com"}, ) self.assertEqual( tuple(event[0] for event in adapter.events), ("apply", "verify", "apply", "verify"), ) def test_failed_verification_is_persisted_and_raises(self): endpoint = Endpoint("verizon", "192.168.1.1:443") adapter = FakeAdapter( endpoint, capabilities(DNS_RECORDS), verify_result=False, ) plan = EndpointPlan( endpoint.identity, ( action( endpoint.identity, PlanOperation.CREATE, ), ), ) with SQLiteStateStore(":memory:") as store: with self.assertRaisesRegex( RuntimeError, "verification failed", ): execute_endpoint_plans( [adapter], [plan], store, executed_at=NOW, ) persisted = store.load_applied_state() self.assertEqual(len(persisted), 1) self.assertFalse(persisted[0].is_verified) self.assertEqual( persisted[0].verification_error, "adapter returned false", ) def test_apply_failure_does_not_record_applied_state(self): endpoint = Endpoint("verizon", "192.168.1.1:443") adapter = FakeAdapter( endpoint, capabilities(DNS_RECORDS), apply_error=RuntimeError("write failed"), ) plan = EndpointPlan( endpoint.identity, ( action( endpoint.identity, PlanOperation.CREATE, ), ), ) with SQLiteStateStore(":memory:") as store: with self.assertRaisesRegex(RuntimeError, "write failed"): execute_endpoint_plans( [adapter], [plan], store, executed_at=NOW, ) self.assertEqual(store.load_applied_state(), []) def test_preflight_requires_verify_before_any_mutation(self): endpoint = Endpoint("verizon", "192.168.1.1:443") adapter = FakeAdapter( endpoint, capabilities(DNS_RECORDS, verify=False), ) plan = EndpointPlan( endpoint.identity, ( action( endpoint.identity, PlanOperation.CREATE, ), ), ) with SQLiteStateStore(":memory:") as store: with self.assertRaisesRegex( RuntimeError, "lacks verify capability", ): execute_endpoint_plans( [adapter], [plan], store, executed_at=NOW, ) self.assertEqual(adapter.events, []) def test_certificates_execute_before_proxy_hosts(self): events: list[tuple[str, str, str]] = [] endpoint = Endpoint("npm", "192.168.1.4:81") adapter = FakeAdapter( endpoint, capabilities(CERTIFICATES, PROXY_HOSTS), events=events, ) plan = EndpointPlan( endpoint.identity, ( action( endpoint.identity, PlanOperation.CREATE, PROXY_HOSTS, "app.example.com", ), action( endpoint.identity, PlanOperation.CREATE, CERTIFICATES, "app.example.com", ), ), ) with SQLiteStateStore(":memory:") as store: execute_endpoint_plans( [adapter], [plan], store, executed_at=NOW, ) self.assertEqual( tuple((event[0], event[1]) for event in events), ( ("apply", CERTIFICATES), ("verify", CERTIFICATES), ("apply", PROXY_HOSTS), ("verify", PROXY_HOSTS), ), ) def test_invalid_plan_fails_preflight_without_mutation(self): endpoint = Endpoint("verizon", "192.168.1.1:443") adapter = FakeAdapter( endpoint, capabilities(DNS_RECORDS), ) invalid = EndpointPlan( endpoint.identity, ( action( "verizon://different:443", PlanOperation.CREATE, ), ), ) with SQLiteStateStore(":memory:") as store: with self.assertRaisesRegex( RuntimeError, "does not match", ): execute_endpoint_plans( [adapter], [invalid], store, executed_at=NOW, ) self.assertEqual(adapter.events, []) if __name__ == "__main__": unittest.main()