From: Aleš Mrázek Date: Fri, 16 Jun 2023 12:38:33 +0000 (+0200) Subject: manager: datamodel: config validation strictness X-Git-Tag: v6.0.1~2^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0ec937d997086dcc86a9528cc7aecab68e34a7bb;p=thirdparty%2Fknot-resolver.git manager: datamodel: config validation strictness The new global variable is intended to distinguish between strict and normal validation. --- diff --git a/manager/knot_resolver_manager/datamodel/globals.py b/manager/knot_resolver_manager/datamodel/globals.py index c2ec48cbe..610323fa0 100644 --- a/manager/knot_resolver_manager/datamodel/globals.py +++ b/manager/knot_resolver_manager/datamodel/globals.py @@ -22,13 +22,15 @@ from typing import Optional class Context: - resolve_directory: Path + resolve_root: Optional[Path] + strict_validation: bool - def __init__(self, resolve_directory: Path) -> None: - self.resolve_directory = resolve_directory + def __init__(self, resolve_root: Optional[Path], strict_validation: bool = True) -> None: + self.resolve_root = resolve_root + self.strict_validation = strict_validation -_global_context: Optional[Context] = None +_global_context: Context = Context(None) def set_global_validation_context(context: Context) -> None: @@ -38,13 +40,18 @@ def set_global_validation_context(context: Context) -> None: def reset_global_validation_context() -> None: global _global_context - _global_context = None + _global_context = Context(None) -def get_global_validation_context() -> Context: - if _global_context is None: +def get_resolve_root() -> Path: + if _global_context.resolve_root is None: raise RuntimeError( - "Global validation context is not set! Before validation, you have to call `set_global_validation_context()` function!" + "Global validation context 'resolve_root' is not set!" + " Before validation, you have to set it using `set_global_validation_context()` function!" ) - return _global_context + return _global_context.resolve_root + + +def get_strict_validation() -> bool: + return _global_context.strict_validation diff --git a/manager/knot_resolver_manager/datamodel/types/files.py b/manager/knot_resolver_manager/datamodel/types/files.py index 6fff73aec..99fd8c21f 100644 --- a/manager/knot_resolver_manager/datamodel/types/files.py +++ b/manager/knot_resolver_manager/datamodel/types/files.py @@ -1,7 +1,7 @@ from pathlib import Path from typing import Any, Dict, Tuple, Type, TypeVar -from knot_resolver_manager.datamodel.globals import get_global_validation_context +from knot_resolver_manager.datamodel.globals import get_resolve_root, get_strict_validation from knot_resolver_manager.utils.modeling.base_value_type import BaseValueType @@ -19,6 +19,7 @@ class UncheckedPath(BaseValueType): super().__init__(source_value, object_path=object_path) self._object_path: str = object_path self._parents: Tuple[UncheckedPath, ...] = parents + self.strict_validation: bool = get_strict_validation() if isinstance(source_value, str): # we do not load global validation context if the path is absolute @@ -26,7 +27,7 @@ class UncheckedPath(BaseValueType): if source_value.startswith("/"): resolve_root = Path("/") else: - resolve_root = get_global_validation_context().resolve_directory + resolve_root = get_resolve_root() self._raw_value: str = source_value if self._parents: @@ -84,7 +85,7 @@ class Dir(UncheckedPath): self, source_value: Any, parents: Tuple["UncheckedPath", ...] = tuple(), object_path: str = "/" ) -> None: super().__init__(source_value, parents=parents, object_path=object_path) - if not self._value.is_dir(): + if self.strict_validation and not self._value.is_dir(): raise ValueError(f"path '{self._value}' does not point to an existing directory") @@ -99,7 +100,7 @@ class AbsoluteDir(Dir): self, source_value: Any, parents: Tuple["UncheckedPath", ...] = tuple(), object_path: str = "/" ) -> None: super().__init__(source_value, parents=parents, object_path=object_path) - if not self._value.is_absolute(): + if self.strict_validation and not self._value.is_absolute(): raise ValueError("path not absolute") @@ -113,9 +114,9 @@ class File(UncheckedPath): self, source_value: Any, parents: Tuple["UncheckedPath", ...] = tuple(), object_path: str = "/" ) -> None: super().__init__(source_value, parents=parents, object_path=object_path) - if not self._value.exists(): + if self.strict_validation and not self._value.exists(): raise ValueError("file does not exist") - if not self._value.is_file(): + if self.strict_validation and not self._value.is_file(): raise ValueError("path is not a file") @@ -131,7 +132,7 @@ class FilePath(UncheckedPath): ) -> None: super().__init__(source_value, parents=parents, object_path=object_path) p = self._value.parent - if not p.exists() or not p.is_dir(): + if self.strict_validation and not p.exists() or not p.is_dir(): raise ValueError(f"path '{self._value}' does not point inside an existing directory") - if self._value.is_dir(): + if self.strict_validation and self._value.is_dir(): raise ValueError("path points to a directory when we expected a file") diff --git a/manager/knot_resolver_manager/server.py b/manager/knot_resolver_manager/server.py index 80e3b61dd..a36fcc955 100644 --- a/manager/knot_resolver_manager/server.py +++ b/manager/knot_resolver_manager/server.py @@ -480,7 +480,7 @@ async def start_server(config: Path = DEFAULT_MANAGER_CONFIG_FILE) -> int: config = config.absolute() # before processing any configuration, set validation context - # - resolve_directory = root against which all relative paths will be resolved + # - resolve_root = root against which all relative paths will be resolved set_global_validation_context(Context(resolve_directory=config.parent)) # Preprocess config - load from file or in general take it to the last step before validation.