From: Aleš Mrázek Date: Mon, 28 Aug 2023 11:16:03 +0000 (+0200) Subject: datamodel: local-data/rules: 'records' added X-Git-Tag: v6.0.3~7^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b609aa7f3bd5b19de49bd88e4a8c36c337d79433;p=thirdparty%2Fknot-resolver.git datamodel: local-data/rules: 'records' added --- diff --git a/manager/knot_resolver_manager/datamodel/local_data_schema.py b/manager/knot_resolver_manager/datamodel/local_data_schema.py index 8d7ff0697..e891601ce 100644 --- a/manager/knot_resolver_manager/datamodel/local_data_schema.py +++ b/manager/knot_resolver_manager/datamodel/local_data_schema.py @@ -16,37 +16,40 @@ from knot_resolver_manager.utils.modeling import ConfigSchema class RuleSchema(ConfigSchema): """ - Local data rule configuration. + Local data advanced rule configuration. --- name: Hostname(s). + subtree: Type of subtree. address: Address(es) to pair with hostname(s). file: Path to file(s) with hostname and IP address(es) pairs in '/etc/hosts' like format. - subtree: Type of subtree. + records: Direct addition of records in DNS zone file format. tags: Tags to link with other policy rules. ttl: Optional, TTL value used for these answers. nodata: Optional, use NODATA synthesis. NODATA will be synthesised for matching name, but mismatching type(e.g. AAAA query when only A exists). """ name: Optional[ListOrItem[DomainName]] = None - address: Optional[ListOrItem[IPAddress]] = None subtree: Optional[Literal["empty", "nxdomain", "redirect"]] = None + address: Optional[ListOrItem[IPAddress]] = None file: Optional[ListOrItem[File]] = None + records: Optional[EscapedStr] = None tags: Optional[List[IDPattern]] = None ttl: Optional[TimeUnit] = None nodata: Optional[bool] = None def _validate(self) -> None: - options_sum = sum([bool(self.address), bool(self.subtree), bool(self.file)]) + options_sum = sum([bool(self.address), bool(self.subtree), bool(self.file), bool(self.records)]) if options_sum == 2 and bool(self.address) and self.subtree in {"empty", "redirect"}: - pass # these combinations still make sense + pass # these combinations still make sense elif options_sum > 1: raise ValueError("only one of 'address', 'subtree' or 'file' can be configured") elif options_sum < 1: - raise ValueError("one of 'address', 'subtree' or 'file' must be configured") + raise ValueError("one of 'address', 'subtree', 'file' or 'records' must be configured") - if bool(self.file) == bool(self.name): - raise ValueError("one of 'file' or 'name' must be configured") + options_sum2 = sum([bool(self.name), bool(self.file), bool(self.records)]) + if options_sum2 != 1: + raise ValueError("one of 'name', 'file or 'records' must be configured") if bool(self.nodata) and bool(self.subtree) and not bool(self.address): raise ValueError("'nodata' defined but unused with 'subtree'") diff --git a/manager/knot_resolver_manager/datamodel/templates/macros/local_data_macros.lua.j2 b/manager/knot_resolver_manager/datamodel/templates/macros/local_data_macros.lua.j2 index 92e010df3..d3596490f 100644 --- a/manager/knot_resolver_manager/datamodel/templates/macros/local_data_macros.lua.j2 +++ b/manager/knot_resolver_manager/datamodel/templates/macros/local_data_macros.lua.j2 @@ -94,6 +94,8 @@ assert(C.kr_rule_local_subtree(todname('{{ name }}'), {% for file in item.file %} {{ kr_rule_local_hosts(file, nodata if item.nodata is none else item.nodata, item.ttl or ttl, item.tags) }} {% endfor %} +{% elif item.records %} +{{ local_data_records(item.records, false, item.ttl or ttl, nodata if item.nodata is none else item.nodata, tags) }} {% endif %} {% endfor %} {%- endmacro %} diff --git a/manager/tests/unit/datamodel/test_local_data.py b/manager/tests/unit/datamodel/test_local_data.py index 710fac153..9842b0b2d 100644 --- a/manager/tests/unit/datamodel/test_local_data.py +++ b/manager/tests/unit/datamodel/test_local_data.py @@ -10,11 +10,13 @@ from knot_resolver_manager.utils.modeling.exceptions import DataValidationError @pytest.mark.parametrize( "val", [ - {"name": ["sub2.example.org"], "subtree": "empty"}, + {"name": ["sub2.example.org"], "subtree": "empty", "tags": ["t01"]}, {"name": ["sub3.example.org", "sub5.example.net."], "subtree": "nxdomain", "ttl": "1h"}, {"name": ["sub4.example.org"], "subtree": "redirect"}, {"name": ["sub5.example.org"], "address": ["127.0.0.1"]}, + {"name": ["sub6.example.org"], "subtree": "redirect", "address": ["127.0.0.1"]}, {"file": "/etc/hosts", "ttl": "20m", "nodata": True}, + {"records": "", "ttl": "20m", "nodata": True}, ], ) def test_subtree_valid(val: Any): @@ -26,7 +28,7 @@ def test_subtree_valid(val: Any): [ {"subtree": "empty"}, {"name": ["sub2.example.org"], "file": "/etc/hosts"}, - {"name": ["sub4.example.org"], "address": ["127.0.0.1"], "subtree": "empty"}, + {"name": ["sub4.example.org"], "address": ["127.0.0.1"], "subtree": "nxdomain"}, {"name": ["sub4.example.org"], "subtree": "redirect", "file": "/etc/hosts"}, ], )