]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
manager: datamodel: types: allow root-zone in DomainName
authorAleš Mrázek <ales.mrazek@nic.cz>
Wed, 13 Apr 2022 14:57:36 +0000 (16:57 +0200)
committerAleš Mrázek <ales.mrazek@nic.cz>
Wed, 13 Apr 2022 14:57:36 +0000 (16:57 +0200)
manager/knot_resolver_manager/datamodel/cache_schema.py
manager/knot_resolver_manager/datamodel/types/types.py
manager/tests/unit/datamodel/types/test_custom_types.py

index 49346480734ab5fe125ccf40fe36b8a6670d7ca8..bb99ce4102c9d9a8e3870e942ce8c732bafa397c 100644 (file)
@@ -21,7 +21,7 @@ class PrefillSchema(SchemaNode):
     ca_file: Optional[CheckedPath] = None
 
     def _validate(self) -> None:
-        if self.origin != ".":
+        if str(self.origin) != ".":
             raise ValueError("cache prefilling is not yet supported for non-root zones")
 
 
index 185924e3a39f0711fffb5fbfbdf5ef0261ba282a..42f8296316658ab84e2713b4cdbc2ef27f28e79f 100644 (file)
@@ -60,20 +60,22 @@ class DomainName(StrBase):
     Fully or partially qualified domain name.
     """
 
+    _punycode: str
     _re = re.compile(
         r"(?=^.{,253}\.?$)"  # max 253 chars
-        r"^(?!\.)"  # do not start name with dot
+        r"(^(?!\.)"  # do not start name with dot
         r"((?!-)"  # do not start label with hyphen
         r"\.?[a-zA-Z0-9-]{,62}"  # max 63 chars in label
         r"[a-zA-Z0-9])+"  # do not end label with hyphen
-        r"\.?$"  # end with or without '.'
+        r"\.?$)"  # end with or without '.'
+        r"|^\.$"  # allow root-zone
     )
 
     def __init__(self, source_value: Any, object_path: str = "/") -> None:
         super().__init__(source_value)
         if isinstance(source_value, str):
             try:
-                punycode = source_value.encode("idna").decode("utf-8")
+                punycode = source_value.encode("idna").decode("utf-8") if source_value != "." else "."
             except ValueError:
                 raise SchemaException(
                     f"conversion of '{source_value}' to IDN punycode representation failed",
@@ -82,6 +84,7 @@ class DomainName(StrBase):
 
             if type(self)._re.match(punycode):
                 self._value = source_value
+                self._punycode = punycode
             else:
                 raise SchemaException(
                     f"'{source_value}' represented in punycode '{punycode}' does not match '{self._re.pattern}' pattern",
@@ -100,7 +103,7 @@ class DomainName(StrBase):
         return hash(f"{self._value}.")
 
     def punycode(self) -> str:
-        return self._value.encode("idna").decode("utf-8")
+        return self._punycode
 
     @classmethod
     def json_schema(cls: Type["DomainName"]) -> Dict[Any, Any]:
index 4980a5f57a4afc13f432c36625866ff5a0387e2b..a18910c8a39ec79a06c9f1e4096069b7ad9f00f0 100644 (file)
@@ -94,6 +94,7 @@ def test_checked_path():
 @pytest.mark.parametrize(
     "val",
     [
+        ".",
         "example.com",
         "this.is.example.com.",
         "test.example.com",
@@ -108,7 +109,7 @@ def test_domain_name_valid(val: str):
     o = DomainName(val)
     assert str(o) == val
     assert o == DomainName(val)
-    assert o.punycode() == val.encode("idna").decode("utf-8")
+    assert o.punycode() == val.encode("idna").decode("utf-8") if val != "." else "."
 
 
 @pytest.mark.parametrize(