]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
manager: datamodel: config validation strictness
authorAleš Mrázek <ales.mrazek@nic.cz>
Fri, 16 Jun 2023 12:38:33 +0000 (14:38 +0200)
committerAleš Mrázek <ales.mrazek@nic.cz>
Mon, 19 Jun 2023 11:34:28 +0000 (13:34 +0200)
The new global variable is intended to
distinguish between strict and normal validation.

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

index c2ec48cbee2ccbb32204057f5abc365aefbb1349..610323fa06d1ad649365488a6eed7a68161faa4b 100644 (file)
@@ -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
index 6fff73aec0555bd6fe4c6df0339bd3ccb92e2423..99fd8c21f5480eb5917a378423d09fd75c7c4ff2 100644 (file)
@@ -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")
index 80e3b61ddfd5762ec4a619a4dba835db8e9ff15b..a36fcc955b23518916c6f1e08917a5f85392119a 100644 (file)
@@ -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.