infrahub-server 1.4.10__py3-none-any.whl → 1.5.0b1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- infrahub/actions/tasks.py +208 -16
- infrahub/api/artifact.py +3 -0
- infrahub/api/diff/diff.py +1 -1
- infrahub/api/query.py +2 -0
- infrahub/api/schema.py +3 -0
- infrahub/auth.py +5 -5
- infrahub/cli/db.py +26 -2
- infrahub/cli/db_commands/clean_duplicate_schema_fields.py +212 -0
- infrahub/config.py +7 -2
- infrahub/core/attribute.py +25 -22
- infrahub/core/branch/models.py +2 -2
- infrahub/core/branch/needs_rebase_status.py +11 -0
- infrahub/core/branch/tasks.py +4 -3
- infrahub/core/changelog/models.py +4 -12
- infrahub/core/constants/__init__.py +1 -0
- infrahub/core/constants/infrahubkind.py +1 -0
- infrahub/core/convert_object_type/object_conversion.py +201 -0
- infrahub/core/convert_object_type/repository_conversion.py +89 -0
- infrahub/core/convert_object_type/schema_mapping.py +27 -3
- infrahub/core/diff/model/path.py +4 -0
- infrahub/core/diff/payload_builder.py +1 -1
- infrahub/core/diff/query/artifact.py +1 -1
- infrahub/core/graph/__init__.py +1 -1
- infrahub/core/initialization.py +2 -2
- infrahub/core/ipam/utilization.py +1 -1
- infrahub/core/manager.py +9 -84
- infrahub/core/migrations/graph/__init__.py +6 -0
- infrahub/core/migrations/graph/m040_profile_attrs_in_db.py +166 -0
- infrahub/core/migrations/graph/m041_create_hfid_display_label_in_db.py +97 -0
- infrahub/core/migrations/graph/m042_backfill_hfid_display_label_in_db.py +86 -0
- infrahub/core/migrations/schema/node_attribute_add.py +5 -2
- infrahub/core/migrations/shared.py +5 -6
- infrahub/core/node/__init__.py +165 -42
- infrahub/core/node/constraints/attribute_uniqueness.py +3 -1
- infrahub/core/node/create.py +67 -35
- infrahub/core/node/lock_utils.py +98 -0
- infrahub/core/node/node_property_attribute.py +230 -0
- infrahub/core/node/standard.py +1 -1
- infrahub/core/property.py +11 -0
- infrahub/core/protocols.py +8 -1
- infrahub/core/query/attribute.py +27 -15
- infrahub/core/query/node.py +61 -185
- infrahub/core/query/relationship.py +43 -26
- infrahub/core/query/subquery.py +0 -8
- infrahub/core/registry.py +2 -2
- infrahub/core/relationship/constraints/count.py +1 -1
- infrahub/core/relationship/model.py +60 -20
- infrahub/core/schema/attribute_schema.py +0 -2
- infrahub/core/schema/basenode_schema.py +42 -2
- infrahub/core/schema/definitions/core/__init__.py +2 -0
- infrahub/core/schema/definitions/core/generator.py +2 -0
- infrahub/core/schema/definitions/core/group.py +16 -2
- infrahub/core/schema/definitions/core/repository.py +7 -0
- infrahub/core/schema/definitions/internal.py +14 -1
- infrahub/core/schema/generated/base_node_schema.py +6 -1
- infrahub/core/schema/node_schema.py +5 -2
- infrahub/core/schema/relationship_schema.py +0 -1
- infrahub/core/schema/schema_branch.py +137 -2
- infrahub/core/schema/schema_branch_display.py +123 -0
- infrahub/core/schema/schema_branch_hfid.py +114 -0
- infrahub/core/validators/aggregated_checker.py +1 -1
- infrahub/core/validators/determiner.py +12 -1
- infrahub/core/validators/relationship/peer.py +1 -1
- infrahub/core/validators/tasks.py +1 -1
- infrahub/display_labels/__init__.py +0 -0
- infrahub/display_labels/gather.py +48 -0
- infrahub/display_labels/models.py +240 -0
- infrahub/display_labels/tasks.py +186 -0
- infrahub/display_labels/triggers.py +22 -0
- infrahub/events/group_action.py +1 -1
- infrahub/events/node_action.py +1 -1
- infrahub/generators/constants.py +7 -0
- infrahub/generators/models.py +38 -12
- infrahub/generators/tasks.py +34 -16
- infrahub/git/base.py +38 -1
- infrahub/git/integrator.py +22 -14
- infrahub/graphql/analyzer.py +1 -1
- infrahub/graphql/api/dependencies.py +2 -4
- infrahub/graphql/api/endpoints.py +2 -2
- infrahub/graphql/app.py +2 -4
- infrahub/graphql/initialization.py +2 -3
- infrahub/graphql/manager.py +212 -137
- infrahub/graphql/middleware.py +12 -0
- infrahub/graphql/mutations/branch.py +11 -0
- infrahub/graphql/mutations/computed_attribute.py +110 -3
- infrahub/graphql/mutations/convert_object_type.py +34 -13
- infrahub/graphql/mutations/display_label.py +111 -0
- infrahub/graphql/mutations/generator.py +25 -7
- infrahub/graphql/mutations/hfid.py +118 -0
- infrahub/graphql/mutations/ipam.py +21 -8
- infrahub/graphql/mutations/main.py +37 -153
- infrahub/graphql/mutations/profile.py +195 -0
- infrahub/graphql/mutations/proposed_change.py +2 -1
- infrahub/graphql/mutations/relationship.py +2 -2
- infrahub/graphql/mutations/repository.py +22 -83
- infrahub/graphql/mutations/resource_manager.py +2 -2
- infrahub/graphql/mutations/schema.py +5 -5
- infrahub/graphql/mutations/webhook.py +1 -1
- infrahub/graphql/queries/resource_manager.py +1 -1
- infrahub/graphql/registry.py +173 -0
- infrahub/graphql/resolvers/resolver.py +2 -0
- infrahub/graphql/schema.py +8 -1
- infrahub/groups/tasks.py +1 -1
- infrahub/hfid/__init__.py +0 -0
- infrahub/hfid/gather.py +48 -0
- infrahub/hfid/models.py +240 -0
- infrahub/hfid/tasks.py +185 -0
- infrahub/hfid/triggers.py +22 -0
- infrahub/lock.py +67 -30
- infrahub/locks/__init__.py +0 -0
- infrahub/locks/tasks.py +37 -0
- infrahub/middleware.py +26 -1
- infrahub/patch/plan_writer.py +2 -2
- infrahub/profiles/__init__.py +0 -0
- infrahub/profiles/node_applier.py +101 -0
- infrahub/profiles/queries/__init__.py +0 -0
- infrahub/profiles/queries/get_profile_data.py +99 -0
- infrahub/profiles/tasks.py +63 -0
- infrahub/proposed_change/tasks.py +10 -1
- infrahub/repositories/__init__.py +0 -0
- infrahub/repositories/create_repository.py +113 -0
- infrahub/server.py +16 -3
- infrahub/services/__init__.py +8 -5
- infrahub/tasks/registry.py +6 -4
- infrahub/trigger/catalogue.py +4 -0
- infrahub/trigger/models.py +2 -0
- infrahub/trigger/tasks.py +3 -0
- infrahub/webhook/models.py +1 -1
- infrahub/workflows/catalogue.py +110 -3
- infrahub/workflows/initialization.py +16 -0
- infrahub/workflows/models.py +17 -2
- infrahub_sdk/branch.py +5 -8
- infrahub_sdk/checks.py +1 -1
- infrahub_sdk/client.py +364 -84
- infrahub_sdk/convert_object_type.py +61 -0
- infrahub_sdk/ctl/check.py +2 -3
- infrahub_sdk/ctl/cli_commands.py +18 -12
- infrahub_sdk/ctl/config.py +8 -2
- infrahub_sdk/ctl/generator.py +6 -3
- infrahub_sdk/ctl/graphql.py +184 -0
- infrahub_sdk/ctl/repository.py +39 -1
- infrahub_sdk/ctl/schema.py +18 -3
- infrahub_sdk/ctl/utils.py +4 -0
- infrahub_sdk/ctl/validate.py +5 -3
- infrahub_sdk/diff.py +4 -5
- infrahub_sdk/exceptions.py +2 -0
- infrahub_sdk/generator.py +7 -1
- infrahub_sdk/graphql/__init__.py +12 -0
- infrahub_sdk/graphql/constants.py +1 -0
- infrahub_sdk/graphql/plugin.py +85 -0
- infrahub_sdk/graphql/query.py +77 -0
- infrahub_sdk/{graphql.py → graphql/renderers.py} +88 -75
- infrahub_sdk/graphql/utils.py +40 -0
- infrahub_sdk/node/attribute.py +2 -0
- infrahub_sdk/node/node.py +28 -20
- infrahub_sdk/playback.py +1 -2
- infrahub_sdk/protocols.py +54 -6
- infrahub_sdk/pytest_plugin/plugin.py +7 -4
- infrahub_sdk/pytest_plugin/utils.py +40 -0
- infrahub_sdk/repository.py +1 -2
- infrahub_sdk/schema/__init__.py +38 -0
- infrahub_sdk/schema/main.py +1 -0
- infrahub_sdk/schema/repository.py +8 -0
- infrahub_sdk/spec/object.py +120 -7
- infrahub_sdk/spec/range_expansion.py +118 -0
- infrahub_sdk/timestamp.py +18 -6
- infrahub_sdk/transforms.py +1 -1
- {infrahub_server-1.4.10.dist-info → infrahub_server-1.5.0b1.dist-info}/METADATA +9 -11
- {infrahub_server-1.4.10.dist-info → infrahub_server-1.5.0b1.dist-info}/RECORD +177 -134
- infrahub_testcontainers/container.py +1 -1
- infrahub_testcontainers/docker-compose-cluster.test.yml +1 -1
- infrahub_testcontainers/docker-compose.test.yml +1 -1
- infrahub_testcontainers/models.py +2 -2
- infrahub_testcontainers/performance_test.py +4 -4
- infrahub/core/convert_object_type/conversion.py +0 -134
- {infrahub_server-1.4.10.dist-info → infrahub_server-1.5.0b1.dist-info}/LICENSE.txt +0 -0
- {infrahub_server-1.4.10.dist-info → infrahub_server-1.5.0b1.dist-info}/WHEEL +0 -0
- {infrahub_server-1.4.10.dist-info → infrahub_server-1.5.0b1.dist-info}/entry_points.txt +0 -0
infrahub/core/query/node.py
CHANGED
|
@@ -11,6 +11,7 @@ from infrahub import config
|
|
|
11
11
|
from infrahub.core import registry
|
|
12
12
|
from infrahub.core.constants import (
|
|
13
13
|
GLOBAL_BRANCH_NAME,
|
|
14
|
+
PROFILE_NODE_RELATIONSHIP_IDENTIFIER,
|
|
14
15
|
AttributeDBNodeType,
|
|
15
16
|
RelationshipDirection,
|
|
16
17
|
RelationshipHierarchyDirection,
|
|
@@ -43,7 +44,6 @@ class NodeToProcess:
|
|
|
43
44
|
|
|
44
45
|
node_id: str
|
|
45
46
|
node_uuid: str
|
|
46
|
-
profile_uuids: list[str]
|
|
47
47
|
|
|
48
48
|
updated_at: str
|
|
49
49
|
|
|
@@ -142,9 +142,22 @@ class NodeCreateAllQuery(NodeQuery):
|
|
|
142
142
|
attributes_ipnetwork: list[AttributeCreateData] = []
|
|
143
143
|
attributes_indexed: list[AttributeCreateData] = []
|
|
144
144
|
|
|
145
|
+
if self.node.has_display_label():
|
|
146
|
+
attributes_indexed.append(
|
|
147
|
+
self.node._display_label.get_node_attribute(node=self.node, at=at).get_create_data(
|
|
148
|
+
node_schema=self.node.get_schema()
|
|
149
|
+
)
|
|
150
|
+
)
|
|
151
|
+
if self.node.has_human_friendly_id():
|
|
152
|
+
attributes_indexed.append(
|
|
153
|
+
self.node._human_friendly_id.get_node_attribute(node=self.node, at=at).get_create_data(
|
|
154
|
+
node_schema=self.node.get_schema()
|
|
155
|
+
)
|
|
156
|
+
)
|
|
157
|
+
|
|
145
158
|
for attr_name in self.node._attributes:
|
|
146
159
|
attr: BaseAttribute = getattr(self.node, attr_name)
|
|
147
|
-
attr_data = attr.get_create_data()
|
|
160
|
+
attr_data = attr.get_create_data(node_schema=self.node.get_schema())
|
|
148
161
|
node_type = attr.get_db_node_type()
|
|
149
162
|
|
|
150
163
|
if AttributeDBNodeType.IPHOST in node_type:
|
|
@@ -606,6 +619,7 @@ class NodeListGetAttributeQuery(Query):
|
|
|
606
619
|
|
|
607
620
|
async def query_init(self, db: InfrahubDatabase, **kwargs) -> None: # noqa: ARG002
|
|
608
621
|
self.params["ids"] = self.ids
|
|
622
|
+
self.params["profile_relationship_name"] = PROFILE_NODE_RELATIONSHIP_IDENTIFIER
|
|
609
623
|
|
|
610
624
|
branch_filter, branch_params = self.branch.get_query_filter_path(
|
|
611
625
|
at=self.at, branch_agnostic=self.branch_agnostic
|
|
@@ -614,6 +628,7 @@ class NodeListGetAttributeQuery(Query):
|
|
|
614
628
|
|
|
615
629
|
query = """
|
|
616
630
|
MATCH (n:Node) WHERE n.uuid IN $ids
|
|
631
|
+
WITH n, exists((n)-[:IS_RELATED]-(:Relationship {name: $profile_relationship_name})) AS might_use_profile
|
|
617
632
|
MATCH (n)-[:HAS_ATTRIBUTE]-(a:Attribute)
|
|
618
633
|
"""
|
|
619
634
|
if self.fields:
|
|
@@ -626,15 +641,23 @@ class NodeListGetAttributeQuery(Query):
|
|
|
626
641
|
CALL (n, a) {
|
|
627
642
|
MATCH (n)-[r:HAS_ATTRIBUTE]-(a:Attribute)
|
|
628
643
|
WHERE %(branch_filter)s
|
|
629
|
-
RETURN
|
|
644
|
+
RETURN r AS r1
|
|
630
645
|
ORDER BY r.branch_level DESC, r.from DESC
|
|
631
646
|
LIMIT 1
|
|
632
647
|
}
|
|
633
|
-
WITH
|
|
648
|
+
WITH n, r1, a, might_use_profile
|
|
634
649
|
WHERE r1.status = "active"
|
|
635
|
-
WITH n, r1, a
|
|
650
|
+
WITH n, r1, a, might_use_profile
|
|
636
651
|
MATCH (a)-[r:HAS_VALUE]-(av:AttributeValue)
|
|
637
652
|
WHERE %(branch_filter)s
|
|
653
|
+
CALL (a, might_use_profile) {
|
|
654
|
+
OPTIONAL MATCH (a)-[r:HAS_SOURCE]->(:CoreProfile)
|
|
655
|
+
WHERE might_use_profile = TRUE AND %(branch_filter)s
|
|
656
|
+
RETURN r.status = "active" AS has_active_profile
|
|
657
|
+
ORDER BY r.branch_level DESC, r.from DESC, r.status ASC
|
|
658
|
+
LIMIT 1
|
|
659
|
+
}
|
|
660
|
+
WITH *, has_active_profile = TRUE AS is_from_profile
|
|
638
661
|
CALL (a, av) {
|
|
639
662
|
MATCH (a)-[r:HAS_VALUE]-(av:AttributeValue)
|
|
640
663
|
WHERE %(branch_filter)s
|
|
@@ -642,13 +665,13 @@ class NodeListGetAttributeQuery(Query):
|
|
|
642
665
|
ORDER BY r.branch_level DESC, r.from DESC
|
|
643
666
|
LIMIT 1
|
|
644
667
|
}
|
|
645
|
-
WITH n, r1, a1 as a, r2, av1 as av
|
|
668
|
+
WITH n, r1, a1 as a, r2, av1 as av, is_from_profile
|
|
646
669
|
WHERE r2.status = "active"
|
|
647
|
-
WITH n, a, av, r1, r2
|
|
670
|
+
WITH n, a, av, r1, r2, is_from_profile
|
|
648
671
|
""" % {"branch_filter": branch_filter}
|
|
649
672
|
self.add_to_query(query)
|
|
650
673
|
|
|
651
|
-
self.return_labels = ["n", "a", "av", "r1", "r2"]
|
|
674
|
+
self.return_labels = ["n", "a", "av", "r1", "r2", "is_from_profile"]
|
|
652
675
|
|
|
653
676
|
# Add Is_Protected and Is_visible
|
|
654
677
|
rel_isv_branch_filter, _ = self.branch.get_query_filter_path(
|
|
@@ -668,16 +691,32 @@ class NodeListGetAttributeQuery(Query):
|
|
|
668
691
|
|
|
669
692
|
if self.include_source:
|
|
670
693
|
query = """
|
|
671
|
-
|
|
672
|
-
|
|
694
|
+
CALL (a) {
|
|
695
|
+
OPTIONAL MATCH (a)-[rel_source:HAS_SOURCE]-(source)
|
|
696
|
+
WHERE all(r IN [rel_source] WHERE ( %(branch_filter)s ))
|
|
697
|
+
RETURN source, rel_source
|
|
698
|
+
ORDER BY rel_source.branch_level DESC, rel_source.from DESC, rel_source.status ASC
|
|
699
|
+
LIMIT 1
|
|
700
|
+
}
|
|
701
|
+
WITH *,
|
|
702
|
+
CASE WHEN rel_source.status = "active" THEN source ELSE NULL END AS source,
|
|
703
|
+
CASE WHEN rel_source.status = "active" THEN rel_source ELSE NULL END AS rel_source
|
|
673
704
|
""" % {"branch_filter": branch_filter}
|
|
674
705
|
self.add_to_query(query)
|
|
675
706
|
self.return_labels.extend(["source", "rel_source"])
|
|
676
707
|
|
|
677
708
|
if self.include_owner:
|
|
678
709
|
query = """
|
|
679
|
-
|
|
680
|
-
|
|
710
|
+
CALL (a) {
|
|
711
|
+
OPTIONAL MATCH (a)-[rel_owner:HAS_OWNER]-(owner)
|
|
712
|
+
WHERE all(r IN [rel_owner] WHERE ( %(branch_filter)s ))
|
|
713
|
+
RETURN owner, rel_owner
|
|
714
|
+
ORDER BY rel_owner.branch_level DESC, rel_owner.from DESC, rel_owner.status ASC
|
|
715
|
+
LIMIT 1
|
|
716
|
+
}
|
|
717
|
+
WITH *,
|
|
718
|
+
CASE WHEN rel_owner.status = "active" THEN owner ELSE NULL END AS owner,
|
|
719
|
+
CASE WHEN rel_owner.status = "active" THEN rel_owner ELSE NULL END AS rel_owner
|
|
681
720
|
""" % {"branch_filter": branch_filter}
|
|
682
721
|
self.add_to_query(query)
|
|
683
722
|
self.return_labels.extend(["owner", "rel_owner"])
|
|
@@ -708,6 +747,7 @@ class NodeListGetAttributeQuery(Query):
|
|
|
708
747
|
def _extract_attribute_data(self, result: QueryResult) -> AttributeFromDB:
|
|
709
748
|
attr = result.get_node("a")
|
|
710
749
|
attr_value = result.get_node("av")
|
|
750
|
+
is_from_profile = result.get_as_type(label="is_from_profile", return_type=bool)
|
|
711
751
|
|
|
712
752
|
data = AttributeFromDB(
|
|
713
753
|
name=attr.get("name"),
|
|
@@ -719,6 +759,7 @@ class NodeListGetAttributeQuery(Query):
|
|
|
719
759
|
updated_at=result.get_rel("r2").get("from"),
|
|
720
760
|
value=attr_value.get("value"),
|
|
721
761
|
is_default=attr_value.get("is_default"),
|
|
762
|
+
is_from_profile=is_from_profile,
|
|
722
763
|
content=attr_value._properties,
|
|
723
764
|
branch=self.branch.name,
|
|
724
765
|
flag_properties={
|
|
@@ -942,6 +983,7 @@ class NodeListGetInfoQuery(Query):
|
|
|
942
983
|
at=self.at, branch_agnostic=self.branch_agnostic
|
|
943
984
|
)
|
|
944
985
|
self.params.update(branch_params)
|
|
986
|
+
self.params["ids"] = self.ids
|
|
945
987
|
|
|
946
988
|
query = """
|
|
947
989
|
MATCH p = (root:Root)<-[:IS_PART_OF]-(n:Node)
|
|
@@ -955,16 +997,11 @@ class NodeListGetInfoQuery(Query):
|
|
|
955
997
|
}
|
|
956
998
|
WITH n1 as n, r1 as rb
|
|
957
999
|
WHERE rb.status = "active"
|
|
958
|
-
OPTIONAL MATCH profile_path = (n)-[:IS_RELATED]->(profile_r:Relationship)<-[:IS_RELATED]-(profile:Node)-[:IS_PART_OF]->(:Root)
|
|
959
|
-
WHERE profile_r.name = "node__profile"
|
|
960
|
-
AND profile.namespace = "Profile"
|
|
961
|
-
AND all(r in relationships(profile_path) WHERE %(branch_filter)s and r.status = "active")
|
|
962
1000
|
""" % {"branch_filter": branch_filter}
|
|
963
1001
|
|
|
964
1002
|
self.add_to_query(query)
|
|
965
|
-
self.params["ids"] = self.ids
|
|
966
1003
|
|
|
967
|
-
self.return_labels = ["
|
|
1004
|
+
self.return_labels = ["n", "rb"]
|
|
968
1005
|
|
|
969
1006
|
async def get_nodes(self, db: InfrahubDatabase, duplicate: bool = False) -> AsyncIterator[NodeToProcess]:
|
|
970
1007
|
"""Return all the node objects as NodeToProcess."""
|
|
@@ -978,24 +1015,11 @@ class NodeListGetInfoQuery(Query):
|
|
|
978
1015
|
schema=schema,
|
|
979
1016
|
node_id=result.get_node("n").element_id,
|
|
980
1017
|
node_uuid=result.get_node("n").get("uuid"),
|
|
981
|
-
profile_uuids=[str(puuid) for puuid in result.get("profile_uuids")],
|
|
982
1018
|
updated_at=result.get_rel("rb").get("from"),
|
|
983
1019
|
branch=node_branch,
|
|
984
1020
|
labels=list(result.get_node("n").labels),
|
|
985
1021
|
)
|
|
986
1022
|
|
|
987
|
-
def get_profile_ids_by_node_id(self) -> dict[str, list[str]]:
|
|
988
|
-
profile_id_map: dict[str, list[str]] = {}
|
|
989
|
-
for result in self.results:
|
|
990
|
-
node_id = result.get_node("n").get("uuid")
|
|
991
|
-
profile_ids = result.get("profile_uuids")
|
|
992
|
-
if not node_id or not profile_ids:
|
|
993
|
-
continue
|
|
994
|
-
if node_id not in profile_id_map:
|
|
995
|
-
profile_id_map[node_id] = []
|
|
996
|
-
profile_id_map[node_id].extend(profile_ids)
|
|
997
|
-
return profile_id_map
|
|
998
|
-
|
|
999
1023
|
|
|
1000
1024
|
class FieldAttributeRequirementType(Enum):
|
|
1001
1025
|
FILTER = "filter"
|
|
@@ -1012,7 +1036,7 @@ class FieldAttributeRequirement:
|
|
|
1012
1036
|
types: list[FieldAttributeRequirementType] = dataclass_field(default_factory=list)
|
|
1013
1037
|
|
|
1014
1038
|
@property
|
|
1015
|
-
def
|
|
1039
|
+
def is_attribute_value(self) -> bool:
|
|
1016
1040
|
return bool(self.field and self.field.is_attribute and self.field_attr_name in ("value", "values", "isnull"))
|
|
1017
1041
|
|
|
1018
1042
|
@property
|
|
@@ -1023,26 +1047,10 @@ class FieldAttributeRequirement:
|
|
|
1023
1047
|
def is_order(self) -> bool:
|
|
1024
1048
|
return FieldAttributeRequirementType.ORDER in self.types
|
|
1025
1049
|
|
|
1026
|
-
@property
|
|
1027
|
-
def is_default_query_variable(self) -> str:
|
|
1028
|
-
return f"attr{self.index}_is_default"
|
|
1029
|
-
|
|
1030
1050
|
@property
|
|
1031
1051
|
def node_value_query_variable(self) -> str:
|
|
1032
1052
|
return f"attr{self.index}_node_value"
|
|
1033
1053
|
|
|
1034
|
-
@property
|
|
1035
|
-
def profile_value_query_variable(self) -> str:
|
|
1036
|
-
return f"attr{self.index}_profile_value"
|
|
1037
|
-
|
|
1038
|
-
@property
|
|
1039
|
-
def profile_final_value_query_variable(self) -> str:
|
|
1040
|
-
return f"attr{self.index}_final_profile_value"
|
|
1041
|
-
|
|
1042
|
-
@property
|
|
1043
|
-
def final_value_query_variable(self) -> str:
|
|
1044
|
-
return f"attr{self.index}_final_value"
|
|
1045
|
-
|
|
1046
1054
|
@property
|
|
1047
1055
|
def comparison_operator(self) -> str:
|
|
1048
1056
|
if self.field_attr_name == "isnull":
|
|
@@ -1178,7 +1186,6 @@ class NodeGetListQuery(Query):
|
|
|
1178
1186
|
self.params["node_ids"] = self.filters["ids"]
|
|
1179
1187
|
|
|
1180
1188
|
field_attribute_requirements = self._get_field_requirements(disable_order=disable_order)
|
|
1181
|
-
use_profiles = any(far for far in field_attribute_requirements if far.supports_profile)
|
|
1182
1189
|
await self._add_node_filter_attributes(
|
|
1183
1190
|
db=db, field_attribute_requirements=field_attribute_requirements, branch_filter=branch_filter
|
|
1184
1191
|
)
|
|
@@ -1190,21 +1197,11 @@ class NodeGetListQuery(Query):
|
|
|
1190
1197
|
for far in field_attribute_requirements:
|
|
1191
1198
|
if not far.is_order:
|
|
1192
1199
|
continue
|
|
1193
|
-
if far.supports_profile:
|
|
1194
|
-
self.order_by.append(far.final_value_query_variable)
|
|
1195
|
-
continue
|
|
1196
1200
|
self.order_by.append(far.node_value_query_variable)
|
|
1197
1201
|
|
|
1198
1202
|
# Always order by uuid to guarantee pagination, see https://github.com/opsmill/infrahub/pull/4704.
|
|
1199
1203
|
self.order_by.append("n.uuid")
|
|
1200
1204
|
|
|
1201
|
-
if use_profiles:
|
|
1202
|
-
await self._add_profiles_per_node_query(db=db, branch_filter=branch_filter)
|
|
1203
|
-
await self._add_profile_attributes(
|
|
1204
|
-
db=db, field_attribute_requirements=field_attribute_requirements, branch_filter=branch_filter
|
|
1205
|
-
)
|
|
1206
|
-
await self._add_profile_rollups(field_attribute_requirements=field_attribute_requirements)
|
|
1207
|
-
|
|
1208
1205
|
self._add_final_filter(field_attribute_requirements=field_attribute_requirements)
|
|
1209
1206
|
|
|
1210
1207
|
async def _add_node_filter_attributes(
|
|
@@ -1222,8 +1219,6 @@ class NodeGetListQuery(Query):
|
|
|
1222
1219
|
|
|
1223
1220
|
for far in field_attribute_requirements:
|
|
1224
1221
|
extra_tail_properties = {far.node_value_query_variable: "value"}
|
|
1225
|
-
if far.supports_profile:
|
|
1226
|
-
extra_tail_properties[far.is_default_query_variable] = "is_default"
|
|
1227
1222
|
subquery, subquery_params, subquery_result_name = await build_subquery_filter(
|
|
1228
1223
|
db=db,
|
|
1229
1224
|
field=far.field,
|
|
@@ -1234,7 +1229,6 @@ class NodeGetListQuery(Query):
|
|
|
1234
1229
|
branch=self.branch,
|
|
1235
1230
|
subquery_idx=far.index,
|
|
1236
1231
|
partial_match=self.partial_match,
|
|
1237
|
-
support_profiles=far.supports_profile,
|
|
1238
1232
|
extra_tail_properties=extra_tail_properties,
|
|
1239
1233
|
)
|
|
1240
1234
|
for query_var in extra_tail_properties:
|
|
@@ -1274,9 +1268,6 @@ class NodeGetListQuery(Query):
|
|
|
1274
1268
|
for far in field_attribute_requirements:
|
|
1275
1269
|
if far.field is None:
|
|
1276
1270
|
continue
|
|
1277
|
-
extra_tail_properties = {}
|
|
1278
|
-
if far.supports_profile:
|
|
1279
|
-
extra_tail_properties[far.is_default_query_variable] = "is_default"
|
|
1280
1271
|
|
|
1281
1272
|
subquery, subquery_params, _ = await build_subquery_order(
|
|
1282
1273
|
db=db,
|
|
@@ -1287,11 +1278,7 @@ class NodeGetListQuery(Query):
|
|
|
1287
1278
|
branch=self.branch,
|
|
1288
1279
|
subquery_idx=far.index,
|
|
1289
1280
|
result_prefix=far.node_value_query_variable,
|
|
1290
|
-
support_profiles=far.supports_profile,
|
|
1291
|
-
extra_tail_properties=extra_tail_properties,
|
|
1292
1281
|
)
|
|
1293
|
-
for query_var in extra_tail_properties:
|
|
1294
|
-
self._track_variable(query_var)
|
|
1295
1282
|
self._track_variable(far.node_value_query_variable)
|
|
1296
1283
|
with_str = ", ".join(self._get_tracked_variables())
|
|
1297
1284
|
|
|
@@ -1305,122 +1292,11 @@ class NodeGetListQuery(Query):
|
|
|
1305
1292
|
self.add_to_query(sort_query)
|
|
1306
1293
|
self.params.update(sort_params)
|
|
1307
1294
|
|
|
1308
|
-
async def _add_profiles_per_node_query(self, db: InfrahubDatabase, branch_filter: str) -> None:
|
|
1309
|
-
with_str = ", ".join(self._get_tracked_variables())
|
|
1310
|
-
froms_str = db.render_list_comprehension(items="relationships(profile_path)", item_name="from")
|
|
1311
|
-
profiles_per_node_query = (
|
|
1312
|
-
"""
|
|
1313
|
-
CALL (n) {
|
|
1314
|
-
OPTIONAL MATCH profile_path = (n)-[:IS_RELATED]->(profile_r:Relationship)<-[:IS_RELATED]-(maybe_profile_n:Node)-[:IS_PART_OF]->(:Root)
|
|
1315
|
-
WHERE profile_r.name = "node__profile"
|
|
1316
|
-
AND all(r in relationships(profile_path) WHERE %(branch_filter)s)
|
|
1317
|
-
WITH
|
|
1318
|
-
maybe_profile_n,
|
|
1319
|
-
profile_path,
|
|
1320
|
-
reduce(br_lvl = 0, r in relationships(profile_path) | br_lvl + r.branch_level) AS branch_level,
|
|
1321
|
-
%(froms_str)s AS froms,
|
|
1322
|
-
all(r in relationships(profile_path) WHERE r.status = "active") AS is_active
|
|
1323
|
-
RETURN maybe_profile_n, is_active, branch_level, froms
|
|
1324
|
-
}
|
|
1325
|
-
WITH %(with_str)s, maybe_profile_n, branch_level, froms, is_active
|
|
1326
|
-
ORDER BY n.uuid, maybe_profile_n.uuid, branch_level DESC, froms[-1] DESC, froms[-2] DESC, froms[-3] DESC
|
|
1327
|
-
WITH %(with_str)s, maybe_profile_n, collect(is_active) as ordered_is_actives
|
|
1328
|
-
WITH %(with_str)s, CASE
|
|
1329
|
-
WHEN ordered_is_actives[0] = True THEN maybe_profile_n ELSE NULL
|
|
1330
|
-
END AS profile_n
|
|
1331
|
-
CALL (profile_n) {
|
|
1332
|
-
OPTIONAL MATCH profile_priority_path = (profile_n)-[pr1:HAS_ATTRIBUTE]->(a:Attribute)-[pr2:HAS_VALUE]->(av:AttributeValue)
|
|
1333
|
-
WHERE a.name = "profile_priority"
|
|
1334
|
-
AND all(r in relationships(profile_priority_path) WHERE %(branch_filter)s and r.status = "active")
|
|
1335
|
-
RETURN av.value as profile_priority
|
|
1336
|
-
ORDER BY pr1.branch_level + pr2.branch_level DESC, pr2.from DESC, pr1.from DESC
|
|
1337
|
-
LIMIT 1
|
|
1338
|
-
}
|
|
1339
|
-
WITH %(with_str)s, profile_n, profile_priority
|
|
1340
|
-
"""
|
|
1341
|
-
) % {"branch_filter": branch_filter, "with_str": with_str, "froms_str": froms_str}
|
|
1342
|
-
self.add_to_query(profiles_per_node_query)
|
|
1343
|
-
self._track_variable("profile_n")
|
|
1344
|
-
self._track_variable("profile_priority")
|
|
1345
|
-
|
|
1346
|
-
async def _add_profile_attributes(
|
|
1347
|
-
self, db: InfrahubDatabase, field_attribute_requirements: list[FieldAttributeRequirement], branch_filter: str
|
|
1348
|
-
) -> None:
|
|
1349
|
-
attributes_queries: list[str] = []
|
|
1350
|
-
attributes_params: dict[str, Any] = {}
|
|
1351
|
-
profile_attributes = [far for far in field_attribute_requirements if far.supports_profile]
|
|
1352
|
-
|
|
1353
|
-
for profile_attr in profile_attributes:
|
|
1354
|
-
if not profile_attr.field:
|
|
1355
|
-
continue
|
|
1356
|
-
subquery, subquery_params, _ = await build_subquery_order(
|
|
1357
|
-
db=db,
|
|
1358
|
-
field=profile_attr.field,
|
|
1359
|
-
node_alias="profile_n",
|
|
1360
|
-
name=profile_attr.field_name,
|
|
1361
|
-
order_by=profile_attr.field_attr_name,
|
|
1362
|
-
branch_filter=branch_filter,
|
|
1363
|
-
branch=self.branch,
|
|
1364
|
-
subquery_idx=profile_attr.index,
|
|
1365
|
-
result_prefix=profile_attr.profile_value_query_variable,
|
|
1366
|
-
support_profiles=False,
|
|
1367
|
-
)
|
|
1368
|
-
attributes_params.update(subquery_params)
|
|
1369
|
-
self._track_variable(profile_attr.profile_value_query_variable)
|
|
1370
|
-
with_str = ", ".join(self._get_tracked_variables())
|
|
1371
|
-
|
|
1372
|
-
attributes_queries.append("CALL (profile_n) {")
|
|
1373
|
-
attributes_queries.append(subquery)
|
|
1374
|
-
attributes_queries.append("}")
|
|
1375
|
-
attributes_queries.append(f"WITH {with_str}")
|
|
1376
|
-
|
|
1377
|
-
self.add_to_query(attributes_queries)
|
|
1378
|
-
self.params.update(attributes_params)
|
|
1379
|
-
|
|
1380
|
-
async def _add_profile_rollups(self, field_attribute_requirements: list[FieldAttributeRequirement]) -> None:
|
|
1381
|
-
profile_attributes = [far for far in field_attribute_requirements if far.supports_profile]
|
|
1382
|
-
profile_value_collects = []
|
|
1383
|
-
for profile_attr in profile_attributes:
|
|
1384
|
-
self._untrack_variable(profile_attr.profile_value_query_variable)
|
|
1385
|
-
profile_value_collects.append(
|
|
1386
|
-
f"""head(
|
|
1387
|
-
reduce(
|
|
1388
|
-
non_null_values = [], v in collect({profile_attr.profile_value_query_variable}) |
|
|
1389
|
-
CASE WHEN v IS NOT NULL AND v <> "NULL" THEN non_null_values + [v] ELSE non_null_values END
|
|
1390
|
-
)
|
|
1391
|
-
) as {profile_attr.profile_final_value_query_variable}"""
|
|
1392
|
-
)
|
|
1393
|
-
self._untrack_variable("profile_n")
|
|
1394
|
-
self._untrack_variable("profile_priority")
|
|
1395
|
-
profile_rollup_with_str = ", ".join(self._get_tracked_variables() + profile_value_collects)
|
|
1396
|
-
profile_rollup_query = f"""
|
|
1397
|
-
ORDER BY n.uuid, profile_priority ASC, profile_n.uuid ASC
|
|
1398
|
-
WITH {profile_rollup_with_str}
|
|
1399
|
-
"""
|
|
1400
|
-
self.add_to_query(profile_rollup_query)
|
|
1401
|
-
for profile_attr in profile_attributes:
|
|
1402
|
-
self._track_variable(profile_attr.profile_final_value_query_variable)
|
|
1403
|
-
|
|
1404
|
-
final_value_with = []
|
|
1405
|
-
for profile_attr in profile_attributes:
|
|
1406
|
-
final_value_with.append(f"""
|
|
1407
|
-
CASE
|
|
1408
|
-
WHEN {profile_attr.is_default_query_variable} AND {profile_attr.profile_final_value_query_variable} IS NOT NULL
|
|
1409
|
-
THEN {profile_attr.profile_final_value_query_variable}
|
|
1410
|
-
ELSE {profile_attr.node_value_query_variable}
|
|
1411
|
-
END AS {profile_attr.final_value_query_variable}
|
|
1412
|
-
""")
|
|
1413
|
-
self._untrack_variable(profile_attr.is_default_query_variable)
|
|
1414
|
-
self._untrack_variable(profile_attr.profile_final_value_query_variable)
|
|
1415
|
-
self._untrack_variable(profile_attr.node_value_query_variable)
|
|
1416
|
-
final_value_with_str = ", ".join(self._get_tracked_variables() + final_value_with)
|
|
1417
|
-
self.add_to_query(f"WITH {final_value_with_str}")
|
|
1418
|
-
|
|
1419
1295
|
def _add_final_filter(self, field_attribute_requirements: list[FieldAttributeRequirement]) -> None:
|
|
1420
1296
|
where_parts = []
|
|
1421
1297
|
where_str = ""
|
|
1422
1298
|
for far in field_attribute_requirements:
|
|
1423
|
-
if not far.is_filter or not far.
|
|
1299
|
+
if not far.is_filter or not far.is_attribute_value:
|
|
1424
1300
|
continue
|
|
1425
1301
|
var_name = f"final_attr_value{far.index}"
|
|
1426
1302
|
self.params[var_name] = far.field_attr_comparison_value
|
|
@@ -1429,11 +1305,11 @@ class NodeGetListQuery(Query):
|
|
|
1429
1305
|
# If the any filter is an array/list
|
|
1430
1306
|
var_array = f"{var_name}_array"
|
|
1431
1307
|
where_parts.append(
|
|
1432
|
-
f"any({var_array} IN ${var_name} WHERE toLower(toString({far.
|
|
1308
|
+
f"any({var_array} IN ${var_name} WHERE toLower(toString({far.node_value_query_variable})) CONTAINS toLower({var_array}))"
|
|
1433
1309
|
)
|
|
1434
1310
|
else:
|
|
1435
1311
|
where_parts.append(
|
|
1436
|
-
f"toLower(toString({far.
|
|
1312
|
+
f"toLower(toString({far.node_value_query_variable})) CONTAINS toLower(toString(${var_name}))"
|
|
1437
1313
|
)
|
|
1438
1314
|
continue
|
|
1439
1315
|
if far.field and isinstance(far.field, AttributeSchema) and far.field.kind == "List":
|
|
@@ -1442,10 +1318,10 @@ class NodeGetListQuery(Query):
|
|
|
1442
1318
|
else:
|
|
1443
1319
|
self.params[var_name] = build_regex_attrs(values=[far.field_attr_comparison_value])
|
|
1444
1320
|
|
|
1445
|
-
where_parts.append(f"toString({far.
|
|
1321
|
+
where_parts.append(f"toString({far.node_value_query_variable}) =~ ${var_name}")
|
|
1446
1322
|
continue
|
|
1447
1323
|
|
|
1448
|
-
where_parts.append(f"{far.
|
|
1324
|
+
where_parts.append(f"{far.node_value_query_variable} {far.comparison_operator} ${var_name}")
|
|
1449
1325
|
if where_parts:
|
|
1450
1326
|
where_str = "WHERE " + " AND ".join(where_parts)
|
|
1451
1327
|
self.add_to_query(where_str)
|
|
@@ -350,17 +350,20 @@ class RelationshipUpdatePropertyQuery(RelationshipQuery):
|
|
|
350
350
|
|
|
351
351
|
def __init__(
|
|
352
352
|
self,
|
|
353
|
-
|
|
354
|
-
|
|
353
|
+
rel_node_id: str,
|
|
354
|
+
flag_properties_to_update: dict[str, bool],
|
|
355
|
+
node_properties_to_update: dict[str, str],
|
|
355
356
|
**kwargs,
|
|
356
357
|
):
|
|
357
|
-
self.
|
|
358
|
-
|
|
359
|
-
|
|
358
|
+
self.rel_node_id = rel_node_id
|
|
359
|
+
if not flag_properties_to_update and not node_properties_to_update:
|
|
360
|
+
raise ValueError("Either flag_properties_to_update or node_properties_to_update must be set")
|
|
361
|
+
self.flag_properties_to_update = flag_properties_to_update
|
|
362
|
+
self.node_properties_to_update = node_properties_to_update
|
|
360
363
|
super().__init__(**kwargs)
|
|
361
364
|
|
|
362
365
|
async def query_init(self, db: InfrahubDatabase, **kwargs) -> None: # noqa: ARG002
|
|
363
|
-
self.params["rel_node_id"] = self.
|
|
366
|
+
self.params["rel_node_id"] = self.rel_node_id
|
|
364
367
|
self.params["branch"] = self.branch.name
|
|
365
368
|
self.params["branch_level"] = self.branch.hierarchy_level
|
|
366
369
|
self.params["at"] = self.at.to_string()
|
|
@@ -370,36 +373,51 @@ class RelationshipUpdatePropertyQuery(RelationshipQuery):
|
|
|
370
373
|
"""
|
|
371
374
|
self.add_to_query(query)
|
|
372
375
|
|
|
373
|
-
self.query_add_all_flag_property_merge()
|
|
374
376
|
self.query_add_all_node_property_merge()
|
|
377
|
+
self.query_add_all_flag_property_merge()
|
|
375
378
|
|
|
376
|
-
self.query_add_all_flag_property_create()
|
|
377
379
|
self.query_add_all_node_property_create()
|
|
380
|
+
self.query_add_all_flag_property_create()
|
|
378
381
|
|
|
379
382
|
def query_add_all_flag_property_merge(self) -> None:
|
|
380
|
-
for prop_name in self.
|
|
381
|
-
|
|
382
|
-
self.query_add_flag_property_merge(name=prop_name)
|
|
383
|
+
for prop_name, prop_value in self.flag_properties_to_update.items():
|
|
384
|
+
self.query_add_flag_property_merge(name=prop_name, value=prop_value)
|
|
383
385
|
|
|
384
|
-
def query_add_flag_property_merge(self, name: str) -> None:
|
|
386
|
+
def query_add_flag_property_merge(self, name: str, value: bool) -> None:
|
|
385
387
|
self.add_to_query("MERGE (prop_%s:Boolean { value: $prop_%s })" % (name, name))
|
|
386
|
-
self.params[f"prop_{name}"] =
|
|
388
|
+
self.params[f"prop_{name}"] = value
|
|
387
389
|
self.return_labels.append(f"prop_{name}")
|
|
388
390
|
|
|
389
391
|
def query_add_all_node_property_merge(self) -> None:
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
self.query_add_node_property_merge(name=prop_name)
|
|
392
|
+
branch_filter, branch_params = self.branch.get_query_filter_path(at=self.at)
|
|
393
|
+
self.params.update(branch_params)
|
|
393
394
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
395
|
+
for prop_name, prop_value in self.node_properties_to_update.items():
|
|
396
|
+
self.params[f"prop_{prop_name}"] = prop_value
|
|
397
|
+
if self.branch.is_default or self.branch.is_global:
|
|
398
|
+
node_query = """
|
|
399
|
+
MATCH (prop_%(prop_name)s:Node {uuid: $prop_%(prop_name)s })-[r_%(prop_name)s:IS_PART_OF]->(:Root)
|
|
400
|
+
WHERE r_%(prop_name)s.branch IN $branch0
|
|
401
|
+
AND r_%(prop_name)s.status = "active"
|
|
402
|
+
AND r_%(prop_name)s.from <= $at AND (r_%(prop_name)s.to IS NULL OR r_%(prop_name)s.to > $at)
|
|
403
|
+
WITH *
|
|
404
|
+
LIMIT 1
|
|
405
|
+
""" % {"prop_name": prop_name}
|
|
406
|
+
else:
|
|
407
|
+
node_query = """
|
|
408
|
+
MATCH (prop_%(prop_name)s:Node {uuid: $prop_%(prop_name)s })-[r_%(prop_name)s:IS_PART_OF]->(:Root)
|
|
409
|
+
WHERE all(r in [r_%(prop_name)s] WHERE %(branch_filter)s)
|
|
410
|
+
ORDER BY r_%(prop_name)s.branch_level DESC, r_%(prop_name)s.from DESC, r_%(prop_name)s.status ASC
|
|
411
|
+
LIMIT 1
|
|
412
|
+
WITH *
|
|
413
|
+
WHERE r_%(prop_name)s.status = "active"
|
|
414
|
+
""" % {"branch_filter": branch_filter, "prop_name": prop_name}
|
|
415
|
+
self.add_to_query(node_query)
|
|
416
|
+
self.return_labels.append(f"prop_{prop_name}")
|
|
398
417
|
|
|
399
418
|
def query_add_all_flag_property_create(self) -> None:
|
|
400
|
-
for prop_name in self.
|
|
401
|
-
|
|
402
|
-
self.query_add_flag_property_create(name=prop_name)
|
|
419
|
+
for prop_name in self.flag_properties_to_update:
|
|
420
|
+
self.query_add_flag_property_create(name=prop_name)
|
|
403
421
|
|
|
404
422
|
def query_add_flag_property_create(self, name: str) -> None:
|
|
405
423
|
query = """
|
|
@@ -411,9 +429,8 @@ class RelationshipUpdatePropertyQuery(RelationshipQuery):
|
|
|
411
429
|
self.add_to_query(query)
|
|
412
430
|
|
|
413
431
|
def query_add_all_node_property_create(self) -> None:
|
|
414
|
-
for prop_name in self.
|
|
415
|
-
|
|
416
|
-
self.query_add_node_property_create(name=prop_name)
|
|
432
|
+
for prop_name in self.node_properties_to_update:
|
|
433
|
+
self.query_add_node_property_create(name=prop_name)
|
|
417
434
|
|
|
418
435
|
def query_add_node_property_create(self, name: str) -> None:
|
|
419
436
|
query = """
|
infrahub/core/query/subquery.py
CHANGED
|
@@ -25,12 +25,8 @@ async def build_subquery_filter(
|
|
|
25
25
|
partial_match: bool = False,
|
|
26
26
|
optional_match: bool = False,
|
|
27
27
|
result_prefix: str = "filter",
|
|
28
|
-
support_profiles: bool = False,
|
|
29
28
|
extra_tail_properties: dict[str, str] | None = None,
|
|
30
29
|
) -> tuple[str, dict[str, Any], str]:
|
|
31
|
-
support_profiles = (
|
|
32
|
-
support_profiles and field and field.is_attribute and filter_name in ("value", "values", "isnull")
|
|
33
|
-
)
|
|
34
30
|
params = {}
|
|
35
31
|
prefix = f"{result_prefix}{subquery_idx}"
|
|
36
32
|
|
|
@@ -52,7 +48,6 @@ async def build_subquery_filter(
|
|
|
52
48
|
param_prefix=prefix,
|
|
53
49
|
db=db,
|
|
54
50
|
partial_match=partial_match,
|
|
55
|
-
support_profiles=support_profiles,
|
|
56
51
|
)
|
|
57
52
|
params.update(field_params)
|
|
58
53
|
|
|
@@ -109,10 +104,8 @@ async def build_subquery_order(
|
|
|
109
104
|
branch: Branch = None,
|
|
110
105
|
subquery_idx: int = 1,
|
|
111
106
|
result_prefix: str | None = None,
|
|
112
|
-
support_profiles: bool = False,
|
|
113
107
|
extra_tail_properties: dict[str, str] | None = None,
|
|
114
108
|
) -> tuple[str, dict[str, Any], str]:
|
|
115
|
-
support_profiles = support_profiles and field and field.is_attribute and order_by in ("value", "values")
|
|
116
109
|
params = {}
|
|
117
110
|
prefix = result_prefix or f"order{subquery_idx}"
|
|
118
111
|
|
|
@@ -124,7 +117,6 @@ async def build_subquery_order(
|
|
|
124
117
|
filter_value=None,
|
|
125
118
|
branch=branch,
|
|
126
119
|
param_prefix=prefix,
|
|
127
|
-
support_profiles=support_profiles,
|
|
128
120
|
)
|
|
129
121
|
params.update(field_params)
|
|
130
122
|
|
infrahub/core/registry.py
CHANGED
|
@@ -113,8 +113,8 @@ class Registry:
|
|
|
113
113
|
return True
|
|
114
114
|
return False
|
|
115
115
|
|
|
116
|
-
def get_node_schema(self, name: str, branch: Branch | str | None = None) -> NodeSchema:
|
|
117
|
-
return self.schema.get_node_schema(name=name, branch=branch)
|
|
116
|
+
def get_node_schema(self, name: str, branch: Branch | str | None = None, duplicate: bool = False) -> NodeSchema:
|
|
117
|
+
return self.schema.get_node_schema(name=name, branch=branch, duplicate=duplicate)
|
|
118
118
|
|
|
119
119
|
def get_data_type(self, name: str) -> type[InfrahubDataType]:
|
|
120
120
|
if name not in self.data_type:
|
|
@@ -40,7 +40,7 @@ class RelationshipCountConstraint(RelationshipManagerConstraintInterface):
|
|
|
40
40
|
# peer_ids_present_database_only:
|
|
41
41
|
# relationship to be deleted, need to check if the schema on the other side has a min_count defined
|
|
42
42
|
# TODO see how to manage Generic node
|
|
43
|
-
peer_schema = registry.schema.get(name=relm.schema.peer, branch=branch)
|
|
43
|
+
peer_schema = registry.schema.get(name=relm.schema.peer, branch=branch, duplicate=False)
|
|
44
44
|
peer_rels = peer_schema.get_relationships_by_identifier(id=relm.schema.get_identifier())
|
|
45
45
|
if not peer_rels:
|
|
46
46
|
return
|