import os import tempfile import textwrap import unittest from pathlib import Path from types import SimpleNamespace from unittest.mock import patch from dns_sync.adapters import Endpoint from dns_sync.registry import ( enabled_plugins, load_adapter, ) class PluginRegistryTests(unittest.TestCase): def test_default_enabled_plugin_is_npm(self): with patch.dict(os.environ, {}, clear=True): self.assertEqual( enabled_plugins(), frozenset({"npm"}), ) def test_enabled_plugins_are_explicit(self): with patch.dict( os.environ, { "ENABLED_PLUGINS": ( "npm,verizon" ) }, clear=True, ): self.assertEqual( enabled_plugins(), frozenset( { "npm", "verizon", } ), ) def test_duplicate_enabled_plugin_is_rejected(self): with patch.dict( os.environ, { "ENABLED_PLUGINS": "npm,npm", }, clear=True, ): with self.assertRaisesRegex( RuntimeError, "duplicate plugin", ): enabled_plugins() def test_disabled_adapter_is_not_loaded(self): config = SimpleNamespace() endpoint = Endpoint( "verizon", "192.168.1.1:443", ) with patch.dict( os.environ, { "ENABLED_PLUGINS": "npm", }, clear=True, ): with self.assertRaisesRegex( RuntimeError, "is not enabled", ): load_adapter( "verizon", config, endpoint, ) def test_external_adapter_is_loaded(self): with tempfile.TemporaryDirectory() as directory: root = Path(directory) plugin = root / "example" plugin.mkdir() (plugin / "__init__.py").write_text( textwrap.dedent( """ class Plugin: name = "example" def __init__( self, config, endpoint, ): self.config = config self.endpoint = endpoint """ ) ) config = SimpleNamespace() endpoint = Endpoint( "example", "example.test:443", ) with patch.dict( os.environ, { "ENABLED_PLUGINS": ( "example" ), "DNS_SYNC_PLUGIN_PATH": ( directory ), }, clear=True, ): adapter = load_adapter( "example", config, endpoint, ) self.assertEqual( adapter.name, "example", ) self.assertEqual( adapter.endpoint, endpoint, ) def test_external_adapter_can_import_plugin_submodule(self): with tempfile.TemporaryDirectory() as directory: root = Path(directory) plugin = root / "example_package" plugin.mkdir() (plugin / "helper.py").write_text( "VALUE = 'loaded-from-submodule'\n" ) (plugin / "__init__.py").write_text( textwrap.dedent( """ from .helper import VALUE class Plugin: name = "example_package" def __init__( self, config, endpoint, ): self.config = config self.endpoint = endpoint self.value = VALUE """ ) ) config = SimpleNamespace() endpoint = Endpoint( "example_package", "example.test:443", ) with patch.dict( os.environ, { "ENABLED_PLUGINS": ( "example_package" ), "DNS_SYNC_PLUGIN_PATH": directory, }, clear=True, ): adapter = load_adapter( "example_package", config, endpoint, ) self.assertEqual( adapter.value, "loaded-from-submodule", ) def test_missing_enabled_adapter_fails_closed(self): with tempfile.TemporaryDirectory() as directory: config = SimpleNamespace() endpoint = Endpoint( "missing", "example.test:443", ) with patch.dict( os.environ, { "ENABLED_PLUGINS": "missing", "DNS_SYNC_PLUGIN_PATH": ( directory ), }, clear=True, ): with self.assertRaisesRegex( RuntimeError, "Unknown adapter plugin", ): load_adapter( "missing", config, endpoint, ) if __name__ == "__main__": unittest.main()