]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
manager: fixed error handling in SIGHUP handler
authorVasek Sraier <git@vakabus.cz>
Tue, 11 Jan 2022 12:03:57 +0000 (13:03 +0100)
committerAleš Mrázek <ales.mrazek@nic.cz>
Fri, 8 Apr 2022 14:17:53 +0000 (16:17 +0200)
manager/knot_resolver_manager/config_store.py
manager/knot_resolver_manager/exceptions.py
manager/knot_resolver_manager/server.py
manager/knot_resolver_manager/utils/async_utils.py

index 6b68db6be492b5e850b8dadad5453be9284bfddc..cfc505d828af37d577bd479d3e906045918da5ea 100644 (file)
@@ -3,7 +3,7 @@ from asyncio import Lock
 from typing import Any, Awaitable, Callable, List, Tuple
 
 from knot_resolver_manager.datamodel import KresConfig
-from knot_resolver_manager.exceptions import DataException, KresdManagerException
+from knot_resolver_manager.exceptions import DataException, KresManagerException
 from knot_resolver_manager.utils.functional import Result
 
 VerifyCallback = Callable[[KresConfig, KresConfig], Awaitable[Result[None, str]]]
@@ -25,7 +25,7 @@ class ConfigStore:
         err_res = filter(lambda r: r.is_err(), results)
         errs = list(map(lambda r: r.unwrap_err(), err_res))
         if len(errs) > 0:
-            raise KresdManagerException("Validation of the new config failed. The reasons are:", *errs)
+            raise KresManagerException("Validation of the new config failed. The reasons are:", *errs)
 
         async with self._update_lock:
             # update the stored config with the new version
index ed7de7804b27bcaae929b752eb599b384c0fc4ee..a57d70c52398b8ed9c2d37fb2e4b30cbfef72339 100644 (file)
@@ -1,14 +1,14 @@
-class KresdManagerException(Exception):
+class KresManagerException(Exception):
     """
     Base class for all custom exceptions we use in our code
     """
 
 
-class SubprocessControllerException(KresdManagerException):
+class SubprocessControllerException(KresManagerException):
     pass
 
 
-class TreeException(KresdManagerException):
+class TreeException(KresManagerException):
     def __init__(self, msg: str, tree_path: str) -> None:
         super().__init__(msg)
         self._tree_path = tree_path
@@ -24,9 +24,9 @@ class SchemaException(TreeException):
     pass
 
 
-class DataException(KresdManagerException):
+class DataException(KresManagerException):
     pass
 
 
-class ParsingException(KresdManagerException):
+class ParsingException(KresManagerException):
     pass
index da478da5cd2f200a6fc440631f39eed0c6e1914c..05f185bd4ea75eeb3dc930d70636c377c8afe04a 100644 (file)
@@ -20,7 +20,7 @@ from knot_resolver_manager.config_store import ConfigStore
 from knot_resolver_manager.constants import DEFAULT_MANAGER_CONFIG_FILE
 from knot_resolver_manager.datamodel.config_schema import KresConfig
 from knot_resolver_manager.datamodel.types import Listen, ListenType
-from knot_resolver_manager.exceptions import DataException, KresdManagerException, TreeException
+from knot_resolver_manager.exceptions import DataException, KresManagerException, SchemaException, TreeException
 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
@@ -44,7 +44,7 @@ async def error_handler(request: web.Request, handler: Any):
 
     try:
         return await handler(request)
-    except KresdManagerException as e:
+    except KresManagerException as e:
         if isinstance(e, TreeException):
             return web.Response(
                 text=f"Configuration validation failed @ '{e.where()}': {e}", status=HTTPStatus.BAD_REQUEST
@@ -98,13 +98,23 @@ class Server:
         if self._config_path is None:
             logger.warning("The manager was started with inlined configuration - can't reload")
         else:
-            data = await readfile(self._config_path)
-            config = KresConfig(parse_yaml(data))
-
             try:
+                data = await readfile(self._config_path)
+                config = KresConfig(parse_yaml(data))
                 await self.config_store.update(config)
-            except KresdManagerException as e:
-                logger.error(f"Reloading of the configuration file failed. {e}")
+                logger.info("Configuration file successfully reloaded")
+            except FileNotFoundError:
+                logger.error(
+                    f"Configuration file was not found at '{self._config_path}'."
+                    " Something must have happened to it while we were running."
+                )
+                logger.error("Configuration have NOT been changed.")
+            except SchemaException as e:
+                logger.error(f"Failed to parse the updated configuration file: {e}")
+                logger.error("Configuration have NOT been changed.")
+            except KresManagerException as e:
+                logger.error(f"Reloading of the configuration file failed: {e}")
+                logger.error("Configuration have NOT been changed.")
 
     async def start(self):
         self._setup_routes()
@@ -216,7 +226,7 @@ class Server:
                 nsite = web.TCPSite(self.runner, str(mgn.listen.ip), mgn.listen.port)
                 logger.info(f"Starting API HTTP server on http://{mgn.listen.ip}:{mgn.listen.port}")
             else:
-                raise KresdManagerException(f"Requested API on unsupported configuration format {mgn.listen.typ}")
+                raise KresManagerException(f"Requested API on unsupported configuration format {mgn.listen.typ}")
             await nsite.start()
 
             # stop the old listen
@@ -242,7 +252,7 @@ async def _load_raw_config(config: Union[Path, ParsedTree]) -> ParsedTree:
     # Initial configuration of the manager
     if isinstance(config, Path):
         if not config.exists():
-            raise KresdManagerException(
+            raise KresManagerException(
                 f"Manager is configured to load config file at {config} on startup, but the file does not exist."
             )
         else:
@@ -293,7 +303,7 @@ def _set_working_directory(config_raw: ParsedTree):
     config = KresConfig(config_raw)
 
     if not config.server.rundir.to_path().exists():
-        raise KresdManagerException(f"`rundir` directory ({config.server.rundir}) does not exist!")
+        raise KresManagerException(f"`rundir` directory ({config.server.rundir}) does not exist!")
 
     os.chdir(config.server.rundir.to_path())
 
@@ -337,7 +347,7 @@ async def start_server(config: Union[Path, ParsedTree] = DEFAULT_MANAGER_CONFIG_
 
         # After we have loaded the configuration, we can start worring about subprocess management.
         manager = await _init_manager(config_store)
-    except KresdManagerException as e:
+    except KresManagerException as e:
         logger.error(e)
         sys.exit(1)
     except BaseException:
index 67d1490aab7b5bcb4412e5a6146fd86c4a6aeeda..23b6f36082ea04b8e5cbdb9de405b5d31d199185 100644 (file)
@@ -5,7 +5,7 @@ import time
 from asyncio import create_subprocess_exec, create_subprocess_shell
 from pathlib import PurePath
 from threading import Thread
-from typing import Generic, List, Optional, TypeVar, Union
+from typing import Any, Dict, Generic, List, Optional, TypeVar, Union
 
 from knot_resolver_manager.compat.asyncio import to_thread
 
@@ -16,7 +16,7 @@ async def call(
     """
     custom async alternative to subprocess.call()
     """
-    kwargs = {}
+    kwargs: Dict[str, Any] = {}
     if discard_output:
         kwargs["stdout"] = asyncio.subprocess.DEVNULL
         kwargs["stderr"] = asyncio.subprocess.DEVNULL