From 146addd23596819af5764ba4306690772b4aa740 Mon Sep 17 00:00:00 2001 From: Alexander Rickardsson Date: Fri, 18 Aug 2023 11:46:10 +0200 Subject: [PATCH] client: handle references in user config schema Currently the client is not able to deal with references in the user config schema, but will throw key errors. This will improve the situation by traversing the original object until the actual definition is found --- aiven/client/cli.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/aiven/client/cli.py b/aiven/client/cli.py index bfa49f36..2ac2d8c8 100644 --- a/aiven/client/cli.py +++ b/aiven/client/cli.py @@ -177,11 +177,29 @@ def add_args(self, parser: ArgumentParser) -> None: help="Wait for up to N seconds for a response to a request (default: infinite)", ) + def _find_reference(self, obj_def: Mapping[str, Any], spec: Mapping[str, Any]) -> Mapping[str, Any] | None: + ref_prefix = "#/definitions/" + + def traverse_obj(obj_def: Mapping[str, Any], spec: Mapping[str, Any]) -> Mapping[str, Any] | None: + if "definitions" not in obj_def: + return None + ref = spec["$ref"].removeprefix(ref_prefix) + return obj_def["definitions"][ref] + + if "$ref" in spec: + return traverse_obj(obj_def, spec) + for entry in spec.get("allOf", []): + return traverse_obj(obj_def, entry) + def collect_user_config_options(self, obj_def: Mapping[str, Any], prefixes: list[str] | None = None) -> dict[str, Any]: opts = {} for prop, spec in sorted(obj_def.get("properties", {}).items()): full_prop = prefixes + [prop] if prefixes else [prop] full_name = ".".join(full_prop) + if "type" not in spec: + # It is possible this is a reference, and if so we need to find the actual entry + if not (spec := self._find_reference(obj_def, spec)): + continue types = spec["type"] if not isinstance(types, list): types = [types]