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
9 changes: 5 additions & 4 deletions backend/infrahub/core/schema/schema_branch_display.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import hashlib
from copy import deepcopy
from dataclasses import dataclass, field
from dataclasses import dataclass, field, replace

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL about replace()

from typing import TYPE_CHECKING

if TYPE_CHECKING:
Expand Down Expand Up @@ -125,9 +125,10 @@ def get_related_template(self, related_kind: str, target_kind: str) -> TemplateL
for applicable_kinds in relationship_trigger.attributes.values():
for relationship_identifier in applicable_kinds:
if target_kind == relationship_identifier.kind:
template_label = self.get_template_node(kind=target_kind)
template_label.filter_key = relationship_identifier.filter_key
return template_label
# Copy so the cached template keeps its own-id filter for self recomputes.
return replace(
self.get_template_node(kind=target_kind), filter_key=relationship_identifier.filter_key
)

raise ValueError(
f"Unable to find registered template for {target_kind} registered on related node {related_kind}"
Expand Down
9 changes: 5 additions & 4 deletions backend/infrahub/core/schema/schema_branch_hfid.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import hashlib
from copy import deepcopy
from dataclasses import dataclass, field
from dataclasses import dataclass, field, replace
from typing import TYPE_CHECKING

if TYPE_CHECKING:
Expand Down Expand Up @@ -111,9 +111,10 @@ def get_related_definition(self, related_kind: str, target_kind: str) -> HFIDDef
for applicable_kinds in relationship_trigger.attributes.values():
for relationship_identifier in applicable_kinds:
if target_kind == relationship_identifier.kind:
template_label = self.get_node_definition(kind=target_kind)
template_label.filter_key = relationship_identifier.filter_key
return template_label
# Copy so the cached definition keeps its own-id filter for self recomputes.
return replace(
self.get_node_definition(kind=target_kind), filter_key=relationship_identifier.filter_key
)

raise ValueError(
f"Unable to find registered template for {target_kind} registered on related node {related_kind}"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""Resolving a cross-node derived value must not corrupt the cached own-id filter.

Display labels and HFIDs cache one template per kind. The self getter and the related (cross-node)
getter share that cached instance, so the related getter must return a copy rather than overwrite the
cached ``filter_key`` - otherwise a later own-id recompute queries with the relationship filter and
silently matches nothing.
"""

from __future__ import annotations

from copy import deepcopy

from infrahub.core.schema.schema_branch import SchemaBranch
from tests.helpers.merge_recompute.dataset import PROFILE_NODE_KIND, PROFILE_PEER_KIND, build_profile_schema


def _profile_schema_branch(*, hfid_reads_peer: bool = False) -> SchemaBranch:
schema = deepcopy(build_profile_schema())
if hfid_reads_peer:
node = next(node for node in schema.nodes if node.kind == PROFILE_NODE_KIND)
node.human_friendly_id = ["name__value", "peer__name__value"]
schema_branch = SchemaBranch(cache={}, name="test")
schema_branch.load_schema(schema=schema)
schema_branch.process()
return schema_branch


def test_get_related_template_does_not_mutate_cached_filter_key() -> None:
display_labels = _profile_schema_branch().display_labels

related = display_labels.get_related_template(related_kind=PROFILE_PEER_KIND, target_kind=PROFILE_NODE_KIND)

assert related.filter_key == "peer__ids"
assert display_labels.get_template_node(kind=PROFILE_NODE_KIND).filter_key == "ids"


def test_get_related_definition_does_not_mutate_cached_filter_key() -> None:
hfids = _profile_schema_branch(hfid_reads_peer=True).hfids

related = hfids.get_related_definition(related_kind=PROFILE_PEER_KIND, target_kind=PROFILE_NODE_KIND)

assert related.filter_key == "peer__ids"
assert hfids.get_node_definition(kind=PROFILE_NODE_KIND).filter_key == "ids"
1 change: 1 addition & 0 deletions changelog/+display-label-hfid-own-id-filter.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed display labels and human-friendly ids that read across a relationship not refreshing when they were recomputed by their own id. Resolving a cross-node template overwrote the cached own-id filter in place, so a later self recompute queried with the relationship filter, matched no node, and left the stored value stale.
Loading