]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
manager initialization: verify rundir existance and block changes
authorVasek Sraier <git@vakabus.cz>
Thu, 18 Nov 2021 17:46:36 +0000 (18:46 +0100)
committerAleš Mrázek <ales.mrazek@nic.cz>
Fri, 8 Apr 2022 14:17:53 +0000 (16:17 +0200)
related to #26 and #27

manager/knot_resolver_manager/datamodel/types.py
manager/knot_resolver_manager/server.py

index 9a222082b777b8fa4ced6c0ee3bba7cf8326a044..712b56eb481a9be136c9babd19076e2e8a7a1112 100644 (file)
@@ -115,8 +115,11 @@ class AnyPath(CustomValueType):
     def __str__(self) -> str:
         return str(self._value)
 
-    def __eq__(self, _o: object) -> bool:
-        raise RuntimeError("Path's cannot be simply compared for equality")
+    def __eq__(self, o: object) -> bool:
+        if not isinstance(o, AnyPath):
+            return False
+        
+        return o._value == self._value
 
     def __int__(self) -> int:
         raise RuntimeError("Path cannot be converted to type <int>")
index eb0ee5f1367e9ddfe4e16874c8e257d83cd34d13..22bdb6bcddb4e7cf4add83eeb852d8b19c2da310 100644 (file)
@@ -21,6 +21,7 @@ from knot_resolver_manager.exceptions import DataException, KresdManagerExceptio
 from knot_resolver_manager.kresd_controller import get_controller_by_name
 from knot_resolver_manager.kresd_controller.interface import SubprocessController
 from knot_resolver_manager.utils.async_utils import readfile
+from knot_resolver_manager.utils.functional import Result
 from knot_resolver_manager.utils.parsing import ParsedTree, parse, parse_yaml
 from knot_resolver_manager.utils.types import NoneType
 
@@ -242,11 +243,7 @@ async def _init_config_store(config: Union[Path, ParsedTree, _DefaultSentinel])
         config = DEFAULT_MANAGER_CONFIG_FILE
     if isinstance(config, Path):
         if not config.exists():
-            logger.error(
-                "Manager is configured to load config file at %s on startup, but the file does not exist.",
-                config,
-            )
-            sys.exit(1)
+            raise KresdManagerException(f"Manager is configured to load config file at {config} on startup, but the file does not exist.")
         else:
             logger.info("Loading initial configuration from %s", config)
             config = parse_yaml(await readfile(config))
@@ -263,34 +260,48 @@ async def _init_manager(config_store: ConfigStore) -> KresManager:
     """
     Called asynchronously when the application initializes.
     """
-    try:
-        # if configured, create a subprocess controller manually
-        controller: Optional[SubprocessController] = None
-        if config_store.get().server.management.backend != "auto":
-            controller = await get_controller_by_name(config_store.get(), config_store.get().server.management.backend)
-
-        # Create KresManager. This will perform autodetection of available service managers and
-        # select the most appropriate to use (or use the one configured directly)
-        manager = await KresManager.create(controller, config_store)
-
-        logger.info("Initial configuration applied. Process manager initialized...")
-        return manager
-    except BaseException:
-        logger.error("Manager initialization failed... Shutting down!", exc_info=True)
-        sys.exit(1)
+    # if configured, create a subprocess controller manually
+    controller: Optional[SubprocessController] = None
+    if config_store.get().server.management.backend != "auto":
+        controller = await get_controller_by_name(config_store.get(), config_store.get().server.management.backend)
+
+    # Create KresManager. This will perform autodetection of available service managers and
+    # select the most appropriate to use (or use the one configured directly)
+    manager = await KresManager.create(controller, config_store)
+
+    logger.info("Initial configuration applied. Process manager initialized...")
+    return manager
+
 
+async def _validate_working_directory(config_old: KresConfig, config_new: KresConfig) -> Result[None, str]:
+    if config_old.server.management.rundir != config_new.server.management.rundir:
+        return Result.err("Changing manager's `rundir` during runtime is not allowed.")
+    
+    if not config_new.server.management.rundir.to_path().exists():
+        return Result.err(f"Configured `rundir` directory ({config_new.server.management.rundir}) does not exist!")
 
-def _set_working_directory(config: KresConfig):
+    return Result.ok(None)
+
+
+async def _set_working_directory(config: KresConfig):
     os.chdir(config.server.management.rundir.to_path())
 
 
 async def start_server(config: Union[Path, ParsedTree, _DefaultSentinel] = _DEFAULT_SENTINEL):
     start_time = time()
 
-    # before starting server, initialize the subprocess controller etc.
-    config_store = await _init_config_store(config)
-    _set_working_directory(config_store.get())
-    manager = await _init_manager(config_store)
+    # before starting server, initialize the subprocess controller etc. Any errors during inicialization are fatal
+    try:
+        config_store = await _init_config_store(config)
+        await config_store.register_verifier(_validate_working_directory)
+        await config_store.register_on_change_callback(_set_working_directory)
+        manager = await _init_manager(config_store)
+    except KresdManagerException as e:
+        logger.error(e)
+        sys.exit(1)
+    except BaseException as e:
+        logger.error("Uncaught generic exception during manager inicialization..." , exc_info=True)
+        sys.exit(1)
 
     server = Server(config_store)
     await server.start()