]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
datamodel: types: listen: port is not required for 'ip' and 'interface'
authorAleš <ales.mrazek@nic.cz>
Wed, 22 Dec 2021 00:29:18 +0000 (01:29 +0100)
committerAleš Mrázek <ales.mrazek@nic.cz>
Fri, 8 Apr 2022 14:17:53 +0000 (16:17 +0200)
- FlagsEnum moved to types module
- datamodel: network: default listening ports based on 'kind'

manager/knot_resolver_manager/datamodel/forward_zone.py
manager/knot_resolver_manager/datamodel/network_schema.py
manager/knot_resolver_manager/datamodel/policy_schema.py
manager/knot_resolver_manager/datamodel/rpz_schema.py
manager/knot_resolver_manager/datamodel/stub_zone_schema.py
manager/knot_resolver_manager/datamodel/templates/macros/network_macros.lua.j2
manager/knot_resolver_manager/datamodel/types.py
manager/knot_resolver_manager/datamodel/view_schema.py
manager/knot_resolver_manager/server.py
manager/tests/unit/datamodel/test_datamodel_types.py

index 88331f4b24f82da213938cb35767feb96783bbf4..9c245c8d3975bedc5935380f59b95dceef38944e 100644 (file)
@@ -1,7 +1,6 @@
 from typing import List, Optional, Union
 
-from knot_resolver_manager.datamodel.types import CheckedPath, DomainName, IPAddressPort
-from knot_resolver_manager.datamodel.view_schema import FlagsEnum
+from knot_resolver_manager.datamodel.types import CheckedPath, DomainName, FlagsEnum, IPAddressPort
 from knot_resolver_manager.utils import SchemaNode
 
 
index d9638d77663e345ffd32ae1122fdde457552295e..212d76cc4e05e3e698f6dd2b9fdc0c529406fefb 100644 (file)
@@ -16,9 +16,26 @@ KindEnum = LiteralEnum["dns", "xdp", "dot", "doh"]
 
 
 class InterfaceSchema(SchemaNode):
+    class Raw(SchemaNode):
+        listen: Listen
+        kind: KindEnum = "dns"
+        freebind: bool = False
+
+    _PREVIOUS_SCHEMA = Raw
+
     listen: Listen
-    kind: KindEnum = "dns"
-    freebind: bool = False
+    kind: KindEnum
+    freebind: bool
+
+    def _listen(self, origin: Raw):
+        if not origin.listen.port:
+            if origin.kind == "dot":
+                origin.listen.port = 853
+            elif origin.kind == "doh":
+                origin.listen.port = 443
+            else:
+                origin.listen.port = 53
+        return origin.listen
 
 
 class EdnsBufferSizeSchema(SchemaNode):
index e4fb1e81decee6fba0ca5ee9a177cd9a3aca55f8..97f43c630ab1d677616ae4100d424ade2f85fb15 100644 (file)
@@ -1,8 +1,7 @@
 from typing import List, Optional
 
 from knot_resolver_manager.datamodel.network_schema import AddressRenumberingSchema
-from knot_resolver_manager.datamodel.types import ActionEnum, IPAddressPort, RecordTypeEnum, TimeUnit
-from knot_resolver_manager.datamodel.view_schema import FlagsEnum
+from knot_resolver_manager.datamodel.types import ActionEnum, FlagsEnum, IPAddressPort, RecordTypeEnum, TimeUnit
 from knot_resolver_manager.utils import SchemaNode
 
 
index 3372d5379222277feb09b054557241042645a70c..a1ad204acfca415f4d3319bcdb9121105de3ce29 100644 (file)
@@ -1,8 +1,7 @@
 from typing import List, Optional
 
 from knot_resolver_manager.datamodel.policy_schema import ActionEnum
-from knot_resolver_manager.datamodel.types import CheckedPath
-from knot_resolver_manager.datamodel.view_schema import FlagsEnum
+from knot_resolver_manager.datamodel.types import CheckedPath, FlagsEnum
 from knot_resolver_manager.utils import SchemaNode
 
 
index ffd43bc787d9412a4d4b70cd4d5c7a2447304871..f9fb452e7d59eb4cf200dfdd915582e7f3fbf423 100644 (file)
@@ -1,7 +1,6 @@
 from typing import List, Optional, Union
 
-from knot_resolver_manager.datamodel.types import IPAddressPort
-from knot_resolver_manager.datamodel.view_schema import FlagsEnum
+from knot_resolver_manager.datamodel.types import FlagsEnum, IPAddressPort
 from knot_resolver_manager.utils import SchemaNode
 
 
index 390241926fe26daeb76cbc0ab529c60f34d7dcbf..758fac2a76910e5d1eb5a8c657318fb7a8f8eb0d 100644 (file)
@@ -1,3 +1,17 @@
 {% macro net_listen(interface) -%}
-net.listen('{{ interface.listen.ip|string }}', {{ interface.listen.port|int }}, { kind='{{ 'tls' if interface.kind == 'dot' else interface.kind }}', freebind={{ 'true' if interface.freebind else 'false'}} })
+net.listen(
+{%- if interface.listen.ip -%}
+'{{ interface.listen.ip|string }}',
+{%- if interface.listen.port -%}
+{{ interface.listen.port|int }},
+{%- endif -%}
+{%- elif interface.listen.unix_socket -%}
+'{{ interface.listen.unix_socket|string }}',nil,
+{%- elif interface.listen.interface -%}
+net.{{ interface.listen.interface|string }},
+{%- if interface.listen.port -%}
+{{ interface.listen.port|int }},
+{%- endif -%}
+{%- endif -%}
+{kind='{{ 'tls' if interface.kind == 'dot' else interface.kind }}',freebind={{ 'true' if interface.freebind else 'false'}}})
 {%- endmacro %}
\ No newline at end of file
index d61e5f015ff6aec9f93e59cca2ac0060552fcc7e..de4238f54ed4b94df41e4780e9b8ef172c6b6f9b 100644 (file)
@@ -30,6 +30,46 @@ ActionEnum = LiteralEnum[
     "reqtrace",
 ]
 
+# FLAGS from https://knot-resolver.readthedocs.io/en/stable/lib.html?highlight=options#c.kr_qflags
+FlagsEnum = LiteralEnum[
+    "no-minimize",
+    "no-ipv4",
+    "no-ipv6",
+    "tcp",
+    "resolved",
+    "await-ipv4",
+    "await-ipv6",
+    "await-cut",
+    "no-edns",
+    "cached",
+    "no-cache",
+    "expiring",
+    "allow_local",
+    "dnssec-want",
+    "dnssec-bogus",
+    "dnssec-insecure",
+    "dnssec-cd",
+    "stub",
+    "always-cut",
+    "dnssec-wexpand",
+    "permissive",
+    "strict",
+    "badcookie-again",
+    "cname",
+    "reorder-rr",
+    "trace",
+    "no-0x20",
+    "dnssec-nods",
+    "dnssec-optout",
+    "nonauth",
+    "forward",
+    "dns64-mark",
+    "cache-tried",
+    "no-ns-found",
+    "pkt-is-sane",
+    "dns64-disable",
+]
+
 # DNS record types from 'kres.type' table
 RecordTypeEnum = LiteralEnum[
     "A",
@@ -533,9 +573,9 @@ class IPv6Network96(CustomValueType):
 
 
 class ListenType(Enum):
-    IP_AND_PORT = auto()
+    IP = auto()
     UNIX_SOCKET = auto()
-    INTERFACE_AND_PORT = auto()
+    INTERFACE = auto()
 
 
 class Listen(SchemaNode, Serializable):
@@ -561,12 +601,12 @@ class Listen(SchemaNode, Serializable):
             "interface" if origin.interface is not None else ...,
         }
 
-        if present == {"ip", "port", ...}:
-            return ListenType.IP_AND_PORT
+        if present == {"ip", ...} or present == {"ip", "port", ...}:
+            return ListenType.IP
         elif present == {"unix_socket", ...}:
             return ListenType.UNIX_SOCKET
-        elif present == {"interface", "port", ...}:
-            return ListenType.INTERFACE_AND_PORT
+        elif present == {"interface", ...} or present == {"interface", "port", ...}:
+            return ListenType.INTERFACE
         else:
             raise ValueError(
                 "Listen configuration contains multiple incompatible options at once. "
@@ -585,11 +625,11 @@ class Listen(SchemaNode, Serializable):
         pass
 
     def __str__(self) -> str:
-        if self.typ is ListenType.IP_AND_PORT:
+        if self.typ is ListenType.IP:
             return f"{self.ip} @ {self.port}"
         elif self.typ is ListenType.UNIX_SOCKET:
             return f"{self.unix_socket}"
-        elif self.typ is ListenType.INTERFACE_AND_PORT:
+        elif self.typ is ListenType.INTERFACE:
             return f"{self.interface} @ {self.port}"
         else:
             raise NotImplementedError()
@@ -607,11 +647,11 @@ class Listen(SchemaNode, Serializable):
         )
 
     def to_dict(self) -> Dict[Any, Any]:
-        if self.typ is ListenType.IP_AND_PORT:
+        if self.typ is ListenType.IP:
             return {"port": self.port, "ip": str(self.ip)}
         elif self.typ is ListenType.UNIX_SOCKET:
             return {"unix_socket": str(self.unix_socket)}
-        elif self.typ is ListenType.INTERFACE_AND_PORT:
+        elif self.typ is ListenType.INTERFACE:
             return {"interface": self.interface, "port": self.port}
         else:
             raise NotImplementedError()
index 8bbbbf1e99f47b738ecfaf319259f00cfb156f8a..6a655c74ea9ba43a1061dd2d994a0d4c029af9ec 100644 (file)
@@ -1,48 +1,7 @@
 from typing import List, Optional
 
-from knot_resolver_manager.datamodel.types import IPNetwork
+from knot_resolver_manager.datamodel.types import FlagsEnum, IPNetwork
 from knot_resolver_manager.utils import SchemaNode
-from knot_resolver_manager.utils.types import LiteralEnum
-
-# FLAGS from https://knot-resolver.readthedocs.io/en/stable/lib.html?highlight=options#c.kr_qflags
-FlagsEnum = LiteralEnum[
-    "no-minimize",
-    "no-ipv4",
-    "no-ipv6",
-    "tcp",
-    "resolved",
-    "await-ipv4",
-    "await-ipv6",
-    "await-cut",
-    "no-edns",
-    "cached",
-    "no-cache",
-    "expiring",
-    "allow_local",
-    "dnssec-want",
-    "dnssec-bogus",
-    "dnssec-insecure",
-    "dnssec-cd",
-    "stub",
-    "always-cut",
-    "dnssec-wexpand",
-    "permissive",
-    "strict",
-    "badcookie-again",
-    "cname",
-    "reorder-rr",
-    "trace",
-    "no-0x20",
-    "dnssec-nods",
-    "dnssec-optout",
-    "nonauth",
-    "forward",
-    "dns64-mark",
-    "cache-tried",
-    "no-ns-found",
-    "pkt-is-sane",
-    "dns64-disable",
-]
 
 
 class ViewSchema(SchemaNode):
index c06075ad558b2079008e222ef671501644b01ebd..2b86719b0648d56b6510c8e37b33a726b8f79a88 100644 (file)
@@ -190,7 +190,7 @@ class Server:
             if mgn.listen.typ is ListenType.UNIX_SOCKET:
                 nsite = web.UnixSite(self.runner, str(mgn.listen.unix_socket))
                 logger.info(f"Starting API HTTP server on http+unix://{mgn.listen.unix_socket}")
-            elif mgn.listen.typ is ListenType.IP_AND_PORT:
+            elif mgn.listen.typ is ListenType.IP:
                 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:
@@ -202,7 +202,7 @@ class Server:
             if self.listen is not None and self.site is not None:
                 if self.listen.typ is ListenType.UNIX_SOCKET:
                     logger.info(f"Stopping API HTTP server on http+unix://{mgn.listen.unix_socket}")
-                elif mgn.listen.typ is ListenType.IP_AND_PORT:
+                elif mgn.listen.typ is ListenType.IP:
                     logger.info(f"Stopping API HTTP server on http://{mgn.listen.ip}:{mgn.listen.port}")
                 await self.site.stop()
 
index 874795abbc92af6e59bffd09c8da8482d4c0c2b1..f3eee9eebce8b839a801d0cd82b1fafcd26f6864 100644 (file)
@@ -138,23 +138,25 @@ def test_listen():
 
     o = Listen({"interface": "eth0", "port": 56})
 
-    assert o.typ == ListenType.INTERFACE_AND_PORT
+    assert o.typ == ListenType.INTERFACE
     assert o.ip is None
     assert o.port == 56
     assert o.unix_socket is None
     assert o.interface == "eth0"
 
-    o = Listen({"ip": "123.4.5.6", "port": 56})
+    o = Listen({"ip": "123.4.5.6"})
 
-    assert o.typ == ListenType.IP_AND_PORT
+    assert o.typ == ListenType.IP
     assert o.ip == IPv4Address("123.4.5.6")
-    assert o.port == 56
+    assert o.port == None
     assert o.unix_socket is None
     assert o.interface is None
 
     # check failure
     with raises(KresdManagerException):
         Listen({"unix-socket": "/tmp", "ip": "127.0.0.1"})
+    with raises(KresdManagerException):
+        Listen({"unix-socket": "/tmp", "port": 853})
 
 
 def test_network():