]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
client: validate: allow combination of config files
authorAleš Mrázek <ales.mrazek@nic.cz>
Thu, 11 Sep 2025 09:02:25 +0000 (11:02 +0200)
committerAleš Mrázek <ales.mrazek@nic.cz>
Tue, 30 Sep 2025 12:01:53 +0000 (14:01 +0200)
doc/user/manager-client.rst
python/knot_resolver/client/commands/validate.py

index c0c757c01c01083e0849e6263e5cac763de8049c..6ab8d2bf566fa2ebf70168046216bf18d9f6b734 100644 (file)
@@ -251,13 +251,15 @@ single ``kresctl`` command.
         This is because the validation runs under a different user/group than the resolver
         itself and attempts to access the configured paths directly.
 
-    .. option:: <input_file>
+    .. option:: [<input_file> ...]
 
-        File with the declarative configuration in YAML or JSON format.
+        :default: /etc/knot-resolver/config.yaml
+
+        Optional, file or combination of files with the declarative configuration in YAML or JSON format.
 
     .. code-block:: bash
 
-        $ kresctl validate input-config.json
+        $ kresctl validate config.yaml config.additional.json
 
 
 .. option:: convert
index 2a336db3eb370a4fcb4df6bc788d226e57cfc6e6..0b71983a763631df3f4a3bf463bddc28742c3a7b 100644 (file)
@@ -1,13 +1,15 @@
 import argparse
 import sys
 from pathlib import Path
-from typing import List, Tuple, Type
+from typing import Any, Dict, List, Tuple, Type
 
 from knot_resolver.client.command import Command, CommandArgs, CompWords, comp_get_words, register_command
+from knot_resolver.constants import CONFIG_FILE
 from knot_resolver.datamodel import KresConfig
 from knot_resolver.datamodel.globals import Context, reset_global_validation_context, set_global_validation_context
 from knot_resolver.utils.modeling import try_to_parse
 from knot_resolver.utils.modeling.exceptions import DataParsingError, DataValidationError
+from knot_resolver.utils.modeling.parsing import data_combine
 
 
 @register_command
@@ -32,9 +34,9 @@ class ValidateCommand(Command):
         validate.add_argument(
             "input_file",
             type=str,
-            nargs="?",
-            help="File with configuration in YAML or JSON format.",
-            default=None,
+            nargs="*",
+            help="File or combination of files with the declarative configuration in YAML or JSON format.",
+            default=[CONFIG_FILE],
         )
 
         return validate, ValidateCommand
@@ -44,15 +46,16 @@ class ValidateCommand(Command):
         return comp_get_words(args, parser)
 
     def run(self, args: CommandArgs) -> None:
-        if self.input_file:
-            with open(self.input_file, "r") as f:
-                data = f.read()
-        else:
-            data = input("Type configuration to validate: ")
-
+        data: Dict[str, Any] = {}
         try:
-            set_global_validation_context(Context(Path(self.input_file).parent, self.strict))
-            KresConfig(try_to_parse(data))
+            for file in self.input_file:
+                with open(file, "r") as f:
+                    raw = f.read()
+                parsed = try_to_parse(raw)
+                data = data_combine(data, parsed)
+
+            set_global_validation_context(Context(Path(self.input_file[0]).parent, self.strict))
+            KresConfig(data)
             reset_global_validation_context()
         except (DataParsingError, DataValidationError) as e:
             print(e, file=sys.stderr)