What happened
When the Infrahub adapter updates an existing node, attribution metadata
(source / owner) is written to changed attributes but never to changed
relationships. A relationship modified by a sync ends up with no
source/owner, while attributes changed in the same sync are attributed
correctly.
This is asymmetric with the create path, which does attribute
relationships: InfrahubModel.create builds its payload with
generate_payload_create(..., source=source_id, owner=owner_id, is_protected=True),
and that SDK function stamps the metadata onto attributes and onto both
cardinality-one and cardinality-many relationships.
Expected behavior
A relationship changed during an update carries the same source / owner
attribution as attributes changed in the same update (matching the create path).
Actual behavior
The changed relationship has its new peer wired up but no source / owner
attribution. Concretely, in an update that changes both a position attribute
and a location relationship, position is attributed and location is not.
Steps to reproduce
- Configure a sync with
source (and/or owner) set (e.g. a CoreAccount /
CoreAccountGroup).
- Match an existing destination node and, in an update (not a create),
change both an attribute and a cardinality-one relationship — e.g. a device
whose position (attribute) and location (relationship to a rack) both
change.
- Inspect the updated node's relationship metadata (UI metadata view or the
GraphQL relationship properties).
Result: the attribute has source/owner; the relationship does not.
Environment
- infrahub-sync: present in 1.5.6, 2.0.0, and 2.0.1 (
update_node is
byte-identical across 2.0.0/2.0.1 in this region)
- Infrahub server version: N/A — logic bug in the sync adapter, independent
of server version
- OS / Python: N/A — platform- and runtime-independent
Additional context
Location: infrahub_sync/adapters/infrahub.py, update_node() (v2.0.1 lines):
for attr_name, attr_value in attrs.items():
if attr_name in node._schema.attribute_names:
attr = getattr(node, attr_name)
attr.value = attr_value
if source:
attr.source = NodeProperty(data=source) # L121 ← attributed
if owner:
attr.owner = NodeProperty(data=owner) # L123 ← attributed
if attr_name in node._schema.relationship_names:
for rel_schema in node._schema.relationships:
...
if rel_schema.cardinality == "one":
if attr_value:
peer_node = resolve_peer_node(...)
setattr(node, attr_name, peer_node) # L144 ← NO source/owner
elif rel_schema.cardinality == "many":
... attr_manager.add(new_id) / .remove(existing_id) ... # NO source/owner
The docstring itself scopes it to attributes: "source: Optional source ID to
set on updated attributes."
Impact: relationships changed by a sync have no lineage back to the sync
source/owner. This is most visible for update-only flows (object matched
and only its relationships/attributes updated, never created), since such
relationships never traverse the attributing create path.
Suggested fix: mirror the attribute logic onto relationships in
update_node, assigning peers with metadata rather than the bare peer. The SDK's
RelatedNode accepts source / owner / is_protected in its data dict:
# cardinality == "one"
rel_data = {"id": peer_node.id}
if source:
rel_data["source"] = source
if owner:
rel_data["owner"] = owner
setattr(node, attr_name, rel_data)
# cardinality == "many": pass the same dict shape per added peer id
Happy to open a PR if this direction looks right.
What happened
When the Infrahub adapter updates an existing node, attribution metadata
(
source/owner) is written to changed attributes but never to changedrelationships. A relationship modified by a sync ends up with no
source/owner, while attributes changed in the same sync are attributedcorrectly.
This is asymmetric with the create path, which does attribute
relationships:
InfrahubModel.createbuilds its payload withgenerate_payload_create(..., source=source_id, owner=owner_id, is_protected=True),and that SDK function stamps the metadata onto attributes and onto both
cardinality-one and cardinality-many relationships.
Expected behavior
A relationship changed during an update carries the same
source/ownerattribution as attributes changed in the same update (matching the create path).
Actual behavior
The changed relationship has its new peer wired up but no
source/ownerattribution. Concretely, in an update that changes both a
positionattributeand a
locationrelationship,positionis attributed andlocationis not.Steps to reproduce
source(and/orowner) set (e.g. aCoreAccount/CoreAccountGroup).change both an attribute and a cardinality-one relationship — e.g. a device
whose
position(attribute) andlocation(relationship to a rack) bothchange.
GraphQL relationship properties).
Result: the attribute has
source/owner; the relationship does not.Environment
update_nodeisbyte-identical across 2.0.0/2.0.1 in this region)
of server version
Additional context
Location:
infrahub_sync/adapters/infrahub.py,update_node()(v2.0.1 lines):The docstring itself scopes it to attributes: "source: Optional source ID to
set on updated attributes."
Impact: relationships changed by a sync have no lineage back to the sync
source/owner. This is most visible for update-only flows (object matchedand only its relationships/attributes updated, never created), since such
relationships never traverse the attributing create path.
Suggested fix: mirror the attribute logic onto relationships in
update_node, assigning peers with metadata rather than the bare peer. The SDK'sRelatedNodeacceptssource/owner/is_protectedin its data dict:Happy to open a PR if this direction looks right.