Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/27.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix generated GraphQL query when having a relationship to a pool node
18 changes: 12 additions & 6 deletions infrahub_sdk/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,10 +241,10 @@
return self._peer.typename
return self._typename

def _generate_input_data(self) -> dict[str, Any]:
def _generate_input_data(self, allocate_from_pool: bool = False) -> dict[str, Any]:
data: dict[str, Any] = {}

if self.is_resource_pool:
if self.is_resource_pool and allocate_from_pool:
return {"from_pool": {"id": self.id}}

if self.id is not None:
Expand Down Expand Up @@ -424,8 +424,8 @@
def has_update(self) -> bool:
return self._has_update

def _generate_input_data(self) -> list[dict]:
return [peer._generate_input_data() for peer in self.peers]
def _generate_input_data(self, allocate_from_pool: bool = False) -> list[dict]:
return [peer._generate_input_data(allocate_from_pool=allocate_from_pool) for peer in self.peers]

def _generate_mutation_query(self) -> dict[str, Any]:
# Does nothing for now
Expand Down Expand Up @@ -818,6 +818,7 @@
data[item_name] = attr_data

for item_name in self._relationships:
allocate_from_pool = False
rel_schema = self._schema.get_relationship(name=item_name)
if not rel_schema or rel_schema.read_only:
continue
Expand All @@ -836,7 +837,12 @@
if rel is None or not rel.initialized:
continue

rel_data = rel._generate_input_data()
if isinstance(rel, (RelatedNode, RelatedNodeSync)) and rel.is_resource_pool:
# If the relatiionship is a resource pool and the expected schema is different from the one of the pool, this means we expect to get
# a resource from the pool itself
allocate_from_pool = rel_schema.peer != rel.peer._schema.kind

rel_data = rel._generate_input_data(allocate_from_pool=allocate_from_pool)

if rel_data and isinstance(rel_data, dict):
if variable_values := rel_data.get("data"):
Expand Down Expand Up @@ -1426,7 +1432,7 @@
list[InfrahubNode]: The allocated nodes.
"""
if not self.is_resource_pool():
raise ValueError("Allocate resources can only be fetched from resource pool nodes.")
raise ValueError("Allocated resources can only be fetched from resource pool nodes.")

Check warning on line 1435 in infrahub_sdk/node.py

View check run for this annotation

Codecov / codecov/patch

infrahub_sdk/node.py#L1435

Added line #L1435 was not covered by tests

graphql_query_name = "InfrahubResourcePoolAllocated"
node_ids_per_kind: dict[str, list[str]] = {}
Expand Down
10 changes: 9 additions & 1 deletion tests/unit/sdk/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -821,7 +821,15 @@ async def simple_device_schema() -> NodeSchema:
"optional": True,
"cardinality": "one",
"kind": "Attribute",
}
},
{
"name": "ip_address_pool",
"peer": "CoreIPAddressPool",
"label": "Address allocator",
"optional": True,
"cardinality": "one",
"kind": "Attribute",
},
],
}
return NodeSchema(**data) # type: ignore
Expand Down
23 changes: 18 additions & 5 deletions tests/unit/sdk/test_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -1487,7 +1487,9 @@ async def test_create_input_data_with_resource_pool_relationship(
},
)
device = InfrahubNode(
client=client, schema=simple_device_schema, data={"name": "device-01", "primary_address": ip_pool}
client=client,
schema=simple_device_schema,
data={"name": "device-01", "primary_address": ip_pool, "ip_address_pool": ip_pool},
)
else:
ip_prefix = InfrahubNodeSync(client=client, schema=ipam_ipprefix_schema, data=ipam_ipprefix_data)
Expand All @@ -1504,13 +1506,16 @@ async def test_create_input_data_with_resource_pool_relationship(
},
)
device = InfrahubNode(
client=client, schema=simple_device_schema, data={"name": "device-01", "primary_address": ip_pool}
client=client,
schema=simple_device_schema,
data={"name": "device-01", "primary_address": ip_pool, "ip_address_pool": ip_pool},
)

assert device._generate_input_data()["data"] == {
"data": {
"name": {"value": "device-01"},
"primary_address": {"from_pool": {"id": "pppppppp-pppp-pppp-pppp-pppppppppppp"}},
"ip_address_pool": {"id": "pppppppp-pppp-pppp-pppp-pppppppppppp"},
},
}

Expand All @@ -1534,7 +1539,9 @@ async def test_create_mutation_query_with_resource_pool_relationship(
},
)
device = InfrahubNode(
client=client, schema=simple_device_schema, data={"name": "device-01", "primary_address": ip_pool}
client=client,
schema=simple_device_schema,
data={"name": "device-01", "primary_address": ip_pool, "ip_address_pool": ip_pool},
)
else:
ip_prefix = InfrahubNodeSync(client=client, schema=ipam_ipprefix_schema, data=ipam_ipprefix_data)
Expand All @@ -1551,11 +1558,17 @@ async def test_create_mutation_query_with_resource_pool_relationship(
},
)
device = InfrahubNode(
client=client, schema=simple_device_schema, data={"name": "device-01", "primary_address": ip_pool}
client=client,
schema=simple_device_schema,
data={"name": "device-01", "primary_address": ip_pool, "ip_address_pool": ip_pool},
)

assert device._generate_mutation_query() == {
"object": {"id": None, "primary_address": {"node": {"__typename": None, "display_label": None, "id": None}}},
"object": {
"id": None,
"primary_address": {"node": {"__typename": None, "display_label": None, "id": None}},
"ip_address_pool": {"node": {"__typename": None, "display_label": None, "id": None}},
},
"ok": None,
}

Expand Down