import unittest from datetime import datetime, timezone from dns_sync.adapters import ( CERTIFICATES, PROXY_HOSTS, NormalizedObject, Observation, ) from dns_sync.projections import project_proxy_hosts_to_dns from dns_sync.reconciliation import reconcile_observations NOW = datetime(2026, 9, 19, 23, 0, tzinfo=timezone.utc) def proxy_host( endpoint_id: str, local_key: str, domains: list[str], forward_host: str, *, enabled: bool = True, ) -> Observation: return Observation( endpoint_id=endpoint_id, object=NormalizedObject( object_type=PROXY_HOSTS, logical_key=",".join(sorted(domains)), local_key=local_key, payload={ "domain_names": domains, "forward_scheme": "http", "forward_host": forward_host, "forward_port": 8080, "enabled": enabled, }, ), observed_at=NOW, ) class ProxyHostDnsProjectionTests(unittest.TestCase): def test_target_ip_replaces_npm_backend_address(self): source = proxy_host( "npm://192.168.1.3:81", "12", ["app.example.com"], forward_host="192.168.1.50", ) projected = project_proxy_hosts_to_dns( [source], target_ip="192.168.1.101", ) self.assertEqual(len(projected), 1) record = projected[0] self.assertEqual(record.object.logical_key, "app.example.com") self.assertEqual( record.object.payload["ip"], "192.168.1.101", ) self.assertNotEqual( record.object.payload["ip"], source.object.payload["forward_host"], ) self.assertEqual( record.endpoint_id, "npm://192.168.1.3:81", ) self.assertEqual( record.object.local_key, "12:app.example.com", ) self.assertEqual(record.observed_at, NOW) def test_domains_expand_to_individual_dns_records(self): source = proxy_host( "npm://192.168.1.3:81", "12", ["app.example.com", "*.wild.example.com"], forward_host="backend.internal", ) projected = project_proxy_hosts_to_dns( [source], target_ip="192.168.1.101", ) self.assertEqual( tuple(item.object.logical_key for item in projected), ("*.wild.example.com", "app.example.com"), ) wildcard = next( item for item in projected if item.object.logical_key == "*.wild.example.com" ) self.assertTrue(wildcard.object.payload["wildcard"]) self.assertTrue( all( item.object.payload["ip"] == "192.168.1.101" for item in projected ) ) def test_disabled_proxy_hosts_are_optional(self): source = proxy_host( "npm://192.168.1.3:81", "12", ["disabled.example.com"], forward_host="192.168.1.50", enabled=False, ) excluded = project_proxy_hosts_to_dns( [source], target_ip="192.168.1.101", ) included = project_proxy_hosts_to_dns( [source], target_ip="192.168.1.101", include_disabled=True, ) self.assertEqual(excluded, []) self.assertEqual(len(included), 1) def test_non_proxy_observations_are_not_projected(self): certificate = Observation( endpoint_id="npm://192.168.1.3:81", object=NormalizedObject( object_type=CERTIFICATES, logical_key="app.example.com", local_key="67", payload={"domain_names": ["app.example.com"]}, ), observed_at=NOW, ) projected = project_proxy_hosts_to_dns( [certificate], target_ip="192.168.1.101", ) self.assertEqual(projected, []) def test_multiple_npm_nodes_form_one_dns_union(self): observations = [ proxy_host( "npm://192.168.1.3:81", "12", ["one.example.com", "shared.example.com"], forward_host="192.168.1.50", ), proxy_host( "npm://192.168.1.4:81", "22", ["two.example.com", "shared.example.com"], forward_host="192.168.1.60", ), ] projected = project_proxy_hosts_to_dns( observations, target_ip="192.168.1.101", ) desired = reconcile_observations(projected) self.assertEqual( tuple(item.logical_key for item in desired), ( "one.example.com", "shared.example.com", "two.example.com", ), ) self.assertTrue( all( item.payload["ip"] == "192.168.1.101" for item in desired ) ) if __name__ == "__main__": unittest.main()