From db8b798f2ee09be0fc44da607a256a49095fa43e Mon Sep 17 00:00:00 2001 From: Mikhail Yohman Date: Fri, 6 Mar 2026 05:25:25 +0000 Subject: [PATCH] fix: resolve from_pool string names to pool IDs in object spec processing When loading objects via YAML spec files, attributes using `from_pool` with a plain string pool name (e.g. `{"from_pool": "my-vlan-pool"}`) were passed through as-is, causing failures because the API expects `{"from_pool": {"id": ""}}`. Add `_resolve_attribute_pool` to `InfrahubObjectFileData` which looks up the pool by HFID and replaces the string with the resolved `{id: uuid}` form before creating the node. Currently supports Number attributes via `CoreNumberPool`. Co-Authored-By: Claude Sonnet 4.6 --- infrahub_sdk/spec/object.py | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/infrahub_sdk/spec/object.py b/infrahub_sdk/spec/object.py index 30d9f93d..89287e78 100644 --- a/infrahub_sdk/spec/object.py +++ b/infrahub_sdk/spec/object.py @@ -18,6 +18,10 @@ from ..node import InfrahubNode from ..schema import MainSchemaTypesAPI, RelationshipSchema +_ATTRIBUTE_KIND_TO_POOL_KIND: dict[str, str] = { + "Number": "CoreNumberPool", +} + def validate_list_of_scalars(value: list[Any]) -> bool: return all(isinstance(item, (str, int, float, bool)) for item in value) @@ -426,6 +430,30 @@ async def validate_related_nodes( def enrich_node(cls, data: dict, context: dict) -> dict: # noqa: ARG003 return data + @classmethod + async def _resolve_attribute_pool( + cls, + client: InfrahubClient, + schema: MainSchemaTypesAPI, + name: str, + value: Any, + branch: str | None = None, + ) -> Any: + """If an attribute value has from_pool as a plain string name, resolve it to {id: uuid}.""" + if not isinstance(value, dict) or "from_pool" not in value: + return value + from_pool = value["from_pool"] + if not isinstance(from_pool, str): + return value + attr_schema = schema.get_attribute_or_none(name=name) + if attr_schema is None: + return value + pool_kind = _ATTRIBUTE_KIND_TO_POOL_KIND.get(attr_schema.kind) + if pool_kind is None: + return value + pool = await client.get(kind=pool_kind, hfid=[from_pool], branch=branch, raise_when_missing=True) + return {**value, "from_pool": {"id": pool.id}} + @classmethod async def create_node( cls, @@ -463,7 +491,9 @@ async def create_node( for key, value in data.items(): if key in schema.attribute_names: - clean_data[key] = value + clean_data[key] = await cls._resolve_attribute_pool( + client=client, schema=schema, name=key, value=value, branch=branch + ) continue if key in schema.relationship_names: