From 192526fe0e9dc442720ba25def99550bb5069bba Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ale=C5=A1=20Mr=C3=A1zek?= Date: Thu, 11 Sep 2025 11:27:21 +0200 Subject: [PATCH] client: convert: allow combination of config files --- doc/user/manager-client.rst | 14 ++++--- .../knot_resolver/client/commands/convert.py | 37 +++++++++++-------- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/doc/user/manager-client.rst b/doc/user/manager-client.rst index 6ab8d2bf5..68acc9dcf 100644 --- a/doc/user/manager-client.rst +++ b/doc/user/manager-client.rst @@ -285,20 +285,22 @@ single ``kresctl`` command. which generates a rule database based on ``views``, ``local-data``, and ``forward`` configuration - .. option:: - - File with the declarative configuration in YAML or JSON format. - - .. option:: [output_file] + .. option:: [-o, --output ] Optional. The output file for converted Lua configuration. If not specified, the converted configuration is printed into ``stdout``. + .. option:: [ ...] + + :default: /etc/knot-resolver/config.yaml + + Optional, file or combination of files with configuration in YAML or JSON format. + .. code-block:: bash - $ kresctl convert input-config.yaml output-script.lua + $ kresctl convert -o output-script.lua input-config.yaml .. option:: reload diff --git a/python/knot_resolver/client/commands/convert.py b/python/knot_resolver/client/commands/convert.py index eea383e1f..359330ef9 100644 --- a/python/knot_resolver/client/commands/convert.py +++ b/python/knot_resolver/client/commands/convert.py @@ -1,13 +1,15 @@ import argparse import sys from pathlib import Path -from typing import List, Optional, Tuple, Type +from typing import Any, Dict, List, Optional, 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 @@ -35,17 +37,21 @@ class ConvertCommand(Command): "--type", help="The type of Lua script to generate", choices=["worker", "policy-loader"], default="worker" ) convert.add_argument( - "input_file", - type=str, - help="File with configuration in YAML or JSON format.", - ) - convert.add_argument( - "output_file", + "-o", + "--output", type=str, nargs="?", help="Optional, output file for converted configuration in Lua script. If not specified, converted configuration is printed.", + dest="output_file", default=None, ) + convert.add_argument( + "input_file", + type=str, + nargs="*", + help="File or combination of files with configuration in YAML or JSON format.", + default=[CONFIG_FILE], + ) return convert, ConvertCommand @staticmethod @@ -53,20 +59,21 @@ class ConvertCommand(Command): return comp_get_words(args, parser) def run(self, args: CommandArgs) -> None: - with open(self.input_file, "r") as f: - data = f.read() - + data: Dict[str, Any] = {} try: - parsed = try_to_parse(data) - set_global_validation_context(Context(Path(Path(self.input_file).parent), self.strict)) + 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(Path(self.input_file[0]).parent), self.strict)) if self.type == "worker": - lua = KresConfig(parsed).render_lua() + lua = KresConfig(data).render_lua() elif self.type == "policy-loader": - lua = KresConfig(parsed).render_lua_policy() + lua = KresConfig(data).render_lua_policy() else: raise ValueError(f"Invalid self.type={self.type}") - reset_global_validation_context() except (DataParsingError, DataValidationError) as e: print(e, file=sys.stderr) -- 2.47.3