Skip to content

Commit c39f92c

Browse files
authored
Merge pull request #4875 from opsmill/lgu-fix-hfid-related-node-generic
Allow the use of HFID of a node to create a related node on a generc relationship
2 parents 9f79174 + 46a92dd commit c39f92c

File tree

5 files changed

+121
-1
lines changed

5 files changed

+121
-1
lines changed

backend/infrahub/core/relationship/model.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,8 +425,14 @@ async def resolve(self, db: InfrahubDatabase) -> None:
425425
await self.set_peer(value=peer)
426426

427427
if not self.peer_id and self.peer_hfid:
428+
peer_schema = db.schema.get(name=self.schema.peer, branch=self.branch)
429+
kind = (
430+
self.data["kind"]
431+
if isinstance(self.data, dict) and "kind" in self.data and peer_schema.is_generic_schema
432+
else self.schema.peer
433+
)
428434
peer = await registry.manager.get_one_by_hfid(
429-
db=db, hfid=self.peer_hfid, branch=self.branch, kind=self.schema.peer, fields={"display_label": None}
435+
db=db, hfid=self.peer_hfid, branch=self.branch, kind=kind, fields={"display_label": None}
430436
)
431437
if peer:
432438
await self.set_peer(value=peer)

backend/infrahub/graphql/types/attribute.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class GenericPoolInput(InputObjectType):
2020
class RelatedNodeInput(InputObjectType):
2121
id = String(required=False)
2222
hfid = Field(List(of_type=String), required=False)
23+
kind = String(required=False) # Only used to resolve hfid of a related node on a generic relationship, see #4649
2324
from_pool = Field(GenericPoolInput, required=False)
2425
_relation__is_visible = Boolean(required=False)
2526
_relation__is_protected = Boolean(required=False)

backend/tests/unit/conftest.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2947,3 +2947,64 @@ def init_service(db: InfrahubDatabase):
29472947
services.service = InfrahubServices(database=db, workflow=WorkflowLocalExecution())
29482948
yield services.service
29492949
services.service = original
2950+
2951+
2952+
@pytest.fixture
2953+
async def generic_car_person_schema(default_branch: Branch, data_schema):
2954+
schema: dict[str, Any] = {
2955+
"generics": [
2956+
{
2957+
"name": "Car",
2958+
"namespace": "Test",
2959+
"attributes": [
2960+
{
2961+
"kind": "Text",
2962+
"name": "name",
2963+
},
2964+
],
2965+
"relationships": [
2966+
{
2967+
"cardinality": "one",
2968+
"identifier": "person__car",
2969+
"name": "owner",
2970+
"optional": True,
2971+
"peer": "TestPerson",
2972+
}
2973+
],
2974+
}
2975+
],
2976+
"nodes": [
2977+
{
2978+
"name": "ElectricCar",
2979+
"namespace": "Test",
2980+
"human_friendly_id": ["name__value", "color__value"],
2981+
"inherit_from": ["TestCar"],
2982+
"attributes": [
2983+
{
2984+
"kind": "Text",
2985+
"name": "name",
2986+
},
2987+
{
2988+
"kind": "Text",
2989+
"name": "color",
2990+
},
2991+
],
2992+
},
2993+
{
2994+
"name": "Person",
2995+
"namespace": "Test",
2996+
"attributes": [
2997+
{
2998+
"kind": "Text",
2999+
"name": "name",
3000+
},
3001+
],
3002+
"relationships": [
3003+
{"cardinality": "one", "identifier": "person__car", "name": "car", "peer": "TestCar"}
3004+
],
3005+
},
3006+
],
3007+
}
3008+
3009+
schema_root = SchemaRoot(**schema)
3010+
registry.schema.register_schema(schema=schema_root, branch=default_branch.name)

backend/tests/unit/graphql/test_mutation_relationship.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,3 +695,54 @@ async def test_relationship_add_from_pool(
695695
addresses = await p1.ip_addresses.get(db=db)
696696
assert prefixes
697697
assert not addresses
698+
699+
700+
# See #4649
701+
async def test_add_generic_related_node_with_hfid(
702+
db: InfrahubDatabase,
703+
default_branch: Branch,
704+
generic_car_person_schema,
705+
):
706+
electric_car = await Node.init(db=db, schema="TestElectricCar", branch=default_branch)
707+
await electric_car.new(db=db, name="testing-car", color="blue")
708+
await electric_car.save(db=db)
709+
710+
person = await Node.init(db=db, schema="TestPerson", branch=default_branch)
711+
await person.new(db=db, name="testing-person")
712+
await person.save(db=db)
713+
714+
query = """
715+
mutation {
716+
TestPersonUpdate(data: {
717+
id: "%s",
718+
car: {
719+
hfid: ["testing-car", "blue"],
720+
kind: "TestElectricCar"
721+
}
722+
}) {
723+
ok
724+
object {
725+
id
726+
car {
727+
node {
728+
name {
729+
value
730+
}
731+
}
732+
}
733+
}
734+
}
735+
}
736+
""" % (person.id)
737+
738+
gql_params = prepare_graphql_params(db=db, include_subscription=False, branch=default_branch)
739+
740+
result = await graphql(
741+
schema=gql_params.schema,
742+
source=query,
743+
context_value=gql_params.context,
744+
root_value=None,
745+
variable_values={},
746+
)
747+
assert result.errors is None
748+
assert result.data["TestPersonUpdate"]["object"]["car"]["node"]["name"]["value"] == "testing-car"

changelog/4649.added.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add ability to use node HFID to create a related node on a generic relationship

0 commit comments

Comments
 (0)