Skip to content

Commit 840d98a

Browse files
authored
IHS-147: Fix schema load failure exception (#555)
* Fix schema load failure exception * Add towncrier housekeeping message
1 parent 471bfac commit 840d98a

File tree

3 files changed

+73
-1
lines changed

3 files changed

+73
-1
lines changed

changelog/464.housekeeping.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Handle error gracefully when loading schema instead of failing with an exception

infrahub_sdk/ctl/schema.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,18 @@ def display_schema_load_errors(response: dict[str, Any], schemas_data: list[Sche
7777

7878
elif len(loc_path) > 6:
7979
loc_type = loc_path[5]
80-
input_label = node[loc_type][loc_path[6]].get("name", None)
80+
error_data = node[loc_type]
81+
attribute = loc_path[6]
82+
83+
if isinstance(attribute, str):
84+
input_label = None
85+
for data in error_data:
86+
if data.get(attribute) is not None:
87+
input_label = data.get("name", None)
88+
break
89+
else:
90+
input_label = error_data[attribute].get("name", None)
91+
8192
input_str = error.get("input", None)
8293
error_message = f"{loc_type[:-1].title()}: {input_label} ({input_str}) | {error['msg']} ({error['type']})"
8394
console.print(f" Node: {node.get('namespace', None)}{node.get('name', None)} | {error_message}")

tests/unit/sdk/test_schema.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,3 +392,63 @@ async def test_display_schema_load_errors_details_namespace(mock_get_node) -> No
392392
Node: OuTInstance | namespace (OuT) | String should match pattern '^[A-Z]+$' (string_pattern_mismatch)
393393
"""
394394
assert output == expected_console
395+
396+
397+
@mock.patch(
398+
"infrahub_sdk.ctl.schema.get_node",
399+
return_value={
400+
"name": "TailscaleSSHRule",
401+
"namespace": "Security",
402+
"icon": "mdi:security",
403+
"inherit_from": ["SecurityRule"],
404+
"attributes": [
405+
{
406+
"name": "check_period",
407+
"kind": "Number",
408+
"optional": True,
409+
"default_value": 720,
410+
"min_value": 0,
411+
"max_value": 10080,
412+
},
413+
{"name": "accept_env", "kind": "List", "optional": True},
414+
{
415+
"name": "action",
416+
"optional": True,
417+
"kind": "Dropdown",
418+
"default_value": "allow",
419+
"choices": [
420+
{"label": "allow", "name": "allow"},
421+
{"label": "check", "name": "check"},
422+
],
423+
},
424+
],
425+
},
426+
)
427+
async def test_display_schema_load_errors_details_when_error_is_in_attribute_or_relationship(mock_get_node) -> None:
428+
"""Validate error message with details when loading schema and errors are in attribute or relationship."""
429+
error = {
430+
"detail": [
431+
{
432+
"type": "extra_forbidden",
433+
"loc": ["body", "schemas", 0, "nodes", 4, "attributes", "min_value"],
434+
"msg": "Extra inputs are not permitted",
435+
"input": 0,
436+
},
437+
{
438+
"type": "extra_forbidden",
439+
"loc": ["body", "schemas", 0, "nodes", 4, "attributes", "max_value"],
440+
"msg": "Extra inputs are not permitted",
441+
"input": 10080,
442+
},
443+
]
444+
}
445+
446+
with mock.patch("infrahub_sdk.ctl.schema.console", Console(file=StringIO(), width=1000)) as console:
447+
display_schema_load_errors(response=error, schemas_data=[])
448+
assert mock_get_node.call_count == 2
449+
output = console.file.getvalue()
450+
expected_console = """Unable to load the schema:
451+
Node: SecurityTailscaleSSHRule | Attribute: check_period (0) | Extra inputs are not permitted (extra_forbidden)
452+
Node: SecurityTailscaleSSHRule | Attribute: check_period (10080) | Extra inputs are not permitted (extra_forbidden)
453+
"""
454+
assert output == expected_console

0 commit comments

Comments
 (0)