infrahub-server 1.4.12__py3-none-any.whl → 1.5.0__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/internal.py +2 -0
- infrahub/api/query.py +2 -0
- infrahub/api/schema.py +27 -3
- infrahub/auth.py +5 -5
- infrahub/cli/__init__.py +2 -0
- infrahub/cli/db.py +160 -157
- infrahub/cli/dev.py +118 -0
- infrahub/cli/tasks.py +46 -0
- infrahub/cli/upgrade.py +56 -9
- infrahub/computed_attribute/tasks.py +19 -7
- infrahub/config.py +7 -2
- infrahub/core/attribute.py +35 -24
- infrahub/core/branch/enums.py +1 -1
- infrahub/core/branch/models.py +9 -5
- infrahub/core/branch/needs_rebase_status.py +11 -0
- infrahub/core/branch/tasks.py +72 -10
- infrahub/core/changelog/models.py +2 -10
- infrahub/core/constants/__init__.py +4 -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/calculator.py +2 -2
- infrahub/core/diff/model/path.py +4 -0
- infrahub/core/diff/payload_builder.py +1 -1
- infrahub/core/diff/query/artifact.py +1 -0
- infrahub/core/diff/query/delete_query.py +9 -5
- infrahub/core/diff/query/field_summary.py +1 -0
- infrahub/core/diff/query/merge.py +39 -23
- infrahub/core/graph/__init__.py +1 -1
- infrahub/core/initialization.py +7 -4
- infrahub/core/manager.py +3 -81
- infrahub/core/migrations/__init__.py +3 -0
- infrahub/core/migrations/exceptions.py +4 -0
- infrahub/core/migrations/graph/__init__.py +13 -10
- infrahub/core/migrations/graph/load_schema_branch.py +21 -0
- infrahub/core/migrations/graph/m013_convert_git_password_credential.py +1 -1
- infrahub/core/migrations/graph/m037_index_attr_vals.py +11 -30
- infrahub/core/migrations/graph/m039_ipam_reconcile.py +9 -7
- infrahub/core/migrations/graph/m041_deleted_dup_edges.py +149 -0
- infrahub/core/migrations/graph/m042_profile_attrs_in_db.py +147 -0
- infrahub/core/migrations/graph/m043_create_hfid_display_label_in_db.py +164 -0
- infrahub/core/migrations/graph/m044_backfill_hfid_display_label_in_db.py +864 -0
- infrahub/core/migrations/query/__init__.py +7 -8
- infrahub/core/migrations/query/attribute_add.py +8 -6
- infrahub/core/migrations/query/attribute_remove.py +134 -0
- infrahub/core/migrations/runner.py +54 -0
- infrahub/core/migrations/schema/attribute_kind_update.py +9 -3
- infrahub/core/migrations/schema/attribute_supports_profile.py +90 -0
- infrahub/core/migrations/schema/node_attribute_add.py +26 -5
- infrahub/core/migrations/schema/node_attribute_remove.py +13 -109
- infrahub/core/migrations/schema/node_kind_update.py +2 -1
- infrahub/core/migrations/schema/node_remove.py +2 -1
- infrahub/core/migrations/schema/placeholder_dummy.py +3 -2
- infrahub/core/migrations/shared.py +66 -19
- infrahub/core/models.py +2 -2
- infrahub/core/node/__init__.py +207 -54
- infrahub/core/node/create.py +53 -49
- infrahub/core/node/lock_utils.py +124 -0
- infrahub/core/node/node_property_attribute.py +230 -0
- infrahub/core/node/resource_manager/ip_address_pool.py +2 -1
- infrahub/core/node/resource_manager/ip_prefix_pool.py +2 -1
- infrahub/core/node/resource_manager/number_pool.py +2 -1
- infrahub/core/node/standard.py +1 -1
- infrahub/core/property.py +11 -0
- infrahub/core/protocols.py +8 -1
- infrahub/core/query/attribute.py +82 -15
- infrahub/core/query/diff.py +61 -16
- infrahub/core/query/ipam.py +16 -4
- infrahub/core/query/node.py +92 -212
- infrahub/core/query/relationship.py +44 -26
- infrahub/core/query/subquery.py +0 -8
- infrahub/core/relationship/model.py +69 -24
- infrahub/core/schema/__init__.py +56 -0
- infrahub/core/schema/attribute_schema.py +4 -2
- infrahub/core/schema/basenode_schema.py +42 -2
- infrahub/core/schema/definitions/core/__init__.py +2 -0
- infrahub/core/schema/definitions/core/check.py +1 -1
- 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/core/transform.py +1 -1
- infrahub/core/schema/definitions/internal.py +12 -3
- infrahub/core/schema/generated/attribute_schema.py +2 -2
- infrahub/core/schema/generated/base_node_schema.py +6 -1
- infrahub/core/schema/manager.py +3 -0
- infrahub/core/schema/node_schema.py +1 -0
- infrahub/core/schema/relationship_schema.py +0 -1
- infrahub/core/schema/schema_branch.py +295 -10
- infrahub/core/schema/schema_branch_display.py +135 -0
- infrahub/core/schema/schema_branch_hfid.py +120 -0
- infrahub/core/validators/aggregated_checker.py +1 -1
- infrahub/database/graph.py +21 -0
- 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 +192 -0
- infrahub/display_labels/triggers.py +22 -0
- infrahub/events/branch_action.py +27 -1
- 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 +42 -2
- infrahub/git/integrator.py +22 -14
- infrahub/git/tasks.py +52 -2
- infrahub/graphql/analyzer.py +9 -0
- infrahub/graphql/api/dependencies.py +2 -4
- infrahub/graphql/api/endpoints.py +16 -6
- infrahub/graphql/app.py +2 -4
- infrahub/graphql/initialization.py +2 -3
- infrahub/graphql/manager.py +213 -137
- infrahub/graphql/middleware.py +12 -0
- infrahub/graphql/mutations/branch.py +16 -0
- infrahub/graphql/mutations/computed_attribute.py +110 -3
- infrahub/graphql/mutations/convert_object_type.py +44 -13
- infrahub/graphql/mutations/display_label.py +118 -0
- infrahub/graphql/mutations/generator.py +25 -7
- infrahub/graphql/mutations/hfid.py +125 -0
- infrahub/graphql/mutations/ipam.py +73 -41
- infrahub/graphql/mutations/main.py +61 -178
- infrahub/graphql/mutations/profile.py +195 -0
- infrahub/graphql/mutations/proposed_change.py +8 -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/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/graphql/schema_sort.py +170 -0
- infrahub/graphql/types/branch.py +4 -1
- infrahub/graphql/types/enums.py +3 -0
- 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 +191 -0
- infrahub/hfid/triggers.py +22 -0
- infrahub/lock.py +119 -42
- infrahub/locks/__init__.py +0 -0
- infrahub/locks/tasks.py +37 -0
- infrahub/message_bus/types.py +1 -0
- infrahub/patch/plan_writer.py +2 -2
- infrahub/permissions/constants.py +2 -0
- 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 +98 -0
- infrahub/profiles/tasks.py +63 -0
- infrahub/proposed_change/tasks.py +67 -14
- infrahub/repositories/__init__.py +0 -0
- infrahub/repositories/create_repository.py +113 -0
- infrahub/server.py +9 -1
- infrahub/services/__init__.py +8 -5
- infrahub/services/adapters/http/__init__.py +5 -0
- infrahub/services/adapters/workflow/worker.py +14 -3
- infrahub/task_manager/event.py +5 -0
- infrahub/task_manager/models.py +7 -0
- infrahub/task_manager/task.py +73 -0
- infrahub/tasks/registry.py +6 -4
- infrahub/trigger/catalogue.py +4 -0
- infrahub/trigger/models.py +2 -0
- infrahub/trigger/setup.py +13 -4
- infrahub/trigger/tasks.py +6 -0
- infrahub/webhook/models.py +1 -1
- infrahub/workers/dependencies.py +3 -1
- infrahub/workers/infrahub_async.py +10 -2
- infrahub/workflows/catalogue.py +118 -3
- infrahub/workflows/initialization.py +21 -0
- infrahub/workflows/models.py +17 -2
- infrahub/workflows/utils.py +2 -1
- infrahub_sdk/branch.py +17 -8
- infrahub_sdk/checks.py +1 -1
- infrahub_sdk/client.py +376 -95
- infrahub_sdk/config.py +29 -2
- infrahub_sdk/convert_object_type.py +61 -0
- infrahub_sdk/ctl/branch.py +3 -0
- infrahub_sdk/ctl/check.py +2 -3
- infrahub_sdk/ctl/cli_commands.py +20 -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 +40 -10
- infrahub_sdk/ctl/task.py +110 -0
- 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/node/relationship.py +1 -3
- 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 +70 -4
- infrahub_sdk/schema/main.py +1 -0
- infrahub_sdk/schema/repository.py +8 -0
- infrahub_sdk/spec/models.py +7 -0
- infrahub_sdk/spec/object.py +54 -6
- infrahub_sdk/spec/processors/__init__.py +0 -0
- infrahub_sdk/spec/processors/data_processor.py +10 -0
- infrahub_sdk/spec/processors/factory.py +34 -0
- infrahub_sdk/spec/processors/range_expand_processor.py +56 -0
- infrahub_sdk/spec/range_expansion.py +118 -0
- infrahub_sdk/task/models.py +6 -4
- infrahub_sdk/timestamp.py +18 -6
- infrahub_sdk/transforms.py +1 -1
- {infrahub_server-1.4.12.dist-info → infrahub_server-1.5.0.dist-info}/METADATA +9 -10
- {infrahub_server-1.4.12.dist-info → infrahub_server-1.5.0.dist-info}/RECORD +233 -176
- infrahub_testcontainers/container.py +114 -2
- infrahub_testcontainers/docker-compose-cluster.test.yml +5 -0
- infrahub_testcontainers/docker-compose.test.yml +5 -0
- 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.12.dist-info → infrahub_server-1.5.0.dist-info}/LICENSE.txt +0 -0
- {infrahub_server-1.4.12.dist-info → infrahub_server-1.5.0.dist-info}/WHEEL +0 -0
- {infrahub_server-1.4.12.dist-info → infrahub_server-1.5.0.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:
|
|
@@ -610,6 +623,7 @@ class NodeListGetAttributeQuery(Query):
|
|
|
610
623
|
|
|
611
624
|
async def query_init(self, db: InfrahubDatabase, **kwargs) -> None: # noqa: ARG002
|
|
612
625
|
self.params["ids"] = self.ids
|
|
626
|
+
self.params["profile_relationship_name"] = PROFILE_NODE_RELATIONSHIP_IDENTIFIER
|
|
613
627
|
|
|
614
628
|
branch_filter, branch_params = self.branch.get_query_filter_path(
|
|
615
629
|
at=self.at, branch_agnostic=self.branch_agnostic
|
|
@@ -618,6 +632,7 @@ class NodeListGetAttributeQuery(Query):
|
|
|
618
632
|
|
|
619
633
|
query = """
|
|
620
634
|
MATCH (n:Node) WHERE n.uuid IN $ids
|
|
635
|
+
WITH n, exists((n)-[:IS_RELATED]-(:Relationship {name: $profile_relationship_name})) AS might_use_profile
|
|
621
636
|
MATCH (n)-[:HAS_ATTRIBUTE]-(a:Attribute)
|
|
622
637
|
"""
|
|
623
638
|
if self.fields:
|
|
@@ -627,61 +642,87 @@ class NodeListGetAttributeQuery(Query):
|
|
|
627
642
|
self.add_to_query(query)
|
|
628
643
|
|
|
629
644
|
query = """
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
645
|
+
CALL (n, a) {
|
|
646
|
+
MATCH (n)-[r:HAS_ATTRIBUTE]-(a:Attribute)
|
|
647
|
+
WHERE %(branch_filter)s
|
|
648
|
+
RETURN r AS r1
|
|
649
|
+
ORDER BY r.branch_level DESC, r.from DESC
|
|
650
|
+
LIMIT 1
|
|
651
|
+
}
|
|
652
|
+
WITH n, r1, a, might_use_profile
|
|
653
|
+
WHERE r1.status = "active"
|
|
654
|
+
WITH n, r1, a, might_use_profile
|
|
655
|
+
CALL (a, might_use_profile) {
|
|
656
|
+
OPTIONAL MATCH (a)-[r:HAS_SOURCE]->(:CoreProfile)
|
|
657
|
+
WHERE might_use_profile = TRUE AND %(branch_filter)s
|
|
658
|
+
RETURN r.status = "active" AS has_active_profile
|
|
659
|
+
ORDER BY r.branch_level DESC, r.from DESC, r.status ASC
|
|
660
|
+
LIMIT 1
|
|
661
|
+
}
|
|
662
|
+
WITH *, has_active_profile = TRUE AS is_from_profile
|
|
663
|
+
CALL (a) {
|
|
664
|
+
MATCH (a)-[r:HAS_VALUE]-(av:AttributeValue)
|
|
665
|
+
WHERE %(branch_filter)s
|
|
666
|
+
RETURN r as r2, av
|
|
667
|
+
ORDER BY r.branch_level DESC, r.from DESC
|
|
668
|
+
LIMIT 1
|
|
669
|
+
}
|
|
670
|
+
WITH n, r1, a, r2, av, is_from_profile
|
|
671
|
+
WHERE r2.status = "active"
|
|
652
672
|
""" % {"branch_filter": branch_filter}
|
|
653
673
|
self.add_to_query(query)
|
|
654
674
|
|
|
655
|
-
self.return_labels = ["n", "a", "av", "r1", "r2"]
|
|
675
|
+
self.return_labels = ["n", "a", "av", "r1", "r2", "is_from_profile"]
|
|
656
676
|
|
|
657
677
|
# Add Is_Protected and Is_visible
|
|
658
|
-
rel_isv_branch_filter, _ = self.branch.get_query_filter_path(
|
|
659
|
-
at=self.at, branch_agnostic=self.branch_agnostic, variable_name="rel_isv"
|
|
660
|
-
)
|
|
661
|
-
rel_isp_branch_filter, _ = self.branch.get_query_filter_path(
|
|
662
|
-
at=self.at, branch_agnostic=self.branch_agnostic, variable_name="rel_isp"
|
|
663
|
-
)
|
|
664
678
|
query = """
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
679
|
+
CALL (a) {
|
|
680
|
+
MATCH (a)-[r:IS_VISIBLE]-(isv:Boolean)
|
|
681
|
+
WHERE (%(branch_filter)s)
|
|
682
|
+
RETURN r AS rel_isv, isv
|
|
683
|
+
ORDER BY rel_isv.branch_level DESC, rel_isv.from DESC, rel_isv.status ASC
|
|
684
|
+
LIMIT 1
|
|
685
|
+
}
|
|
686
|
+
CALL (a) {
|
|
687
|
+
MATCH (a)-[r:IS_PROTECTED]-(isp:Boolean)
|
|
688
|
+
WHERE (%(branch_filter)s)
|
|
689
|
+
RETURN r AS rel_isp, isp
|
|
690
|
+
ORDER BY rel_isp.branch_level DESC, rel_isp.from DESC, rel_isp.status ASC
|
|
691
|
+
LIMIT 1
|
|
692
|
+
}
|
|
693
|
+
""" % {"branch_filter": branch_filter}
|
|
669
694
|
self.add_to_query(query)
|
|
670
695
|
|
|
671
696
|
self.return_labels.extend(["isv", "isp", "rel_isv", "rel_isp"])
|
|
672
697
|
|
|
673
698
|
if self.include_source:
|
|
674
699
|
query = """
|
|
675
|
-
|
|
676
|
-
|
|
700
|
+
CALL (a) {
|
|
701
|
+
OPTIONAL MATCH (a)-[rel_source:HAS_SOURCE]-(source)
|
|
702
|
+
WHERE all(r IN [rel_source] WHERE ( %(branch_filter)s ))
|
|
703
|
+
RETURN source, rel_source
|
|
704
|
+
ORDER BY rel_source.branch_level DESC, rel_source.from DESC, rel_source.status ASC
|
|
705
|
+
LIMIT 1
|
|
706
|
+
}
|
|
707
|
+
WITH *,
|
|
708
|
+
CASE WHEN rel_source.status = "active" THEN source ELSE NULL END AS source,
|
|
709
|
+
CASE WHEN rel_source.status = "active" THEN rel_source ELSE NULL END AS rel_source
|
|
677
710
|
""" % {"branch_filter": branch_filter}
|
|
678
711
|
self.add_to_query(query)
|
|
679
712
|
self.return_labels.extend(["source", "rel_source"])
|
|
680
713
|
|
|
681
714
|
if self.include_owner:
|
|
682
715
|
query = """
|
|
683
|
-
|
|
684
|
-
|
|
716
|
+
CALL (a) {
|
|
717
|
+
OPTIONAL MATCH (a)-[rel_owner:HAS_OWNER]-(owner)
|
|
718
|
+
WHERE all(r IN [rel_owner] WHERE ( %(branch_filter)s ))
|
|
719
|
+
RETURN owner, rel_owner
|
|
720
|
+
ORDER BY rel_owner.branch_level DESC, rel_owner.from DESC, rel_owner.status ASC
|
|
721
|
+
LIMIT 1
|
|
722
|
+
}
|
|
723
|
+
WITH *,
|
|
724
|
+
CASE WHEN rel_owner.status = "active" THEN owner ELSE NULL END AS owner,
|
|
725
|
+
CASE WHEN rel_owner.status = "active" THEN rel_owner ELSE NULL END AS rel_owner
|
|
685
726
|
""" % {"branch_filter": branch_filter}
|
|
686
727
|
self.add_to_query(query)
|
|
687
728
|
self.return_labels.extend(["owner", "rel_owner"])
|
|
@@ -712,6 +753,7 @@ class NodeListGetAttributeQuery(Query):
|
|
|
712
753
|
def _extract_attribute_data(self, result: QueryResult) -> AttributeFromDB:
|
|
713
754
|
attr = result.get_node("a")
|
|
714
755
|
attr_value = result.get_node("av")
|
|
756
|
+
is_from_profile = result.get_as_type(label="is_from_profile", return_type=bool)
|
|
715
757
|
|
|
716
758
|
data = AttributeFromDB(
|
|
717
759
|
name=attr.get("name"),
|
|
@@ -723,6 +765,7 @@ class NodeListGetAttributeQuery(Query):
|
|
|
723
765
|
updated_at=result.get_rel("r2").get("from"),
|
|
724
766
|
value=attr_value.get("value"),
|
|
725
767
|
is_default=attr_value.get("is_default"),
|
|
768
|
+
is_from_profile=is_from_profile,
|
|
726
769
|
content=attr_value._properties,
|
|
727
770
|
branch=self.branch.name,
|
|
728
771
|
flag_properties={
|
|
@@ -878,6 +921,7 @@ class NodeListGetRelationshipsQuery(Query):
|
|
|
878
921
|
RETURN DISTINCT n_uuid, rel_name, peer_uuid, direction
|
|
879
922
|
""" % {"filters": rels_filter}
|
|
880
923
|
self.add_to_query(query)
|
|
924
|
+
self.order_by = ["n_uuid", "rel_name", "peer_uuid", "direction"]
|
|
881
925
|
self.return_labels = ["n_uuid", "rel_name", "peer_uuid", "direction"]
|
|
882
926
|
|
|
883
927
|
def get_peers_group_by_node(self) -> GroupedPeerNodes:
|
|
@@ -946,6 +990,8 @@ class NodeListGetInfoQuery(Query):
|
|
|
946
990
|
at=self.at, branch_agnostic=self.branch_agnostic
|
|
947
991
|
)
|
|
948
992
|
self.params.update(branch_params)
|
|
993
|
+
self.params["ids"] = self.ids
|
|
994
|
+
self.order_by = ["n.uuid"]
|
|
949
995
|
|
|
950
996
|
query = """
|
|
951
997
|
MATCH p = (root:Root)<-[:IS_PART_OF]-(n:Node)
|
|
@@ -959,16 +1005,11 @@ class NodeListGetInfoQuery(Query):
|
|
|
959
1005
|
}
|
|
960
1006
|
WITH n1 as n, r1 as rb
|
|
961
1007
|
WHERE rb.status = "active"
|
|
962
|
-
OPTIONAL MATCH profile_path = (n)-[:IS_RELATED]->(profile_r:Relationship)<-[:IS_RELATED]-(profile:Node)-[:IS_PART_OF]->(:Root)
|
|
963
|
-
WHERE profile_r.name = "node__profile"
|
|
964
|
-
AND profile.namespace = "Profile"
|
|
965
|
-
AND all(r in relationships(profile_path) WHERE %(branch_filter)s and r.status = "active")
|
|
966
1008
|
""" % {"branch_filter": branch_filter}
|
|
967
1009
|
|
|
968
1010
|
self.add_to_query(query)
|
|
969
|
-
self.params["ids"] = self.ids
|
|
970
1011
|
|
|
971
|
-
self.return_labels = ["
|
|
1012
|
+
self.return_labels = ["n", "rb"]
|
|
972
1013
|
|
|
973
1014
|
async def get_nodes(self, db: InfrahubDatabase, duplicate: bool = False) -> AsyncIterator[NodeToProcess]:
|
|
974
1015
|
"""Return all the node objects as NodeToProcess."""
|
|
@@ -982,24 +1023,11 @@ class NodeListGetInfoQuery(Query):
|
|
|
982
1023
|
schema=schema,
|
|
983
1024
|
node_id=result.get_node("n").element_id,
|
|
984
1025
|
node_uuid=result.get_node("n").get("uuid"),
|
|
985
|
-
profile_uuids=[str(puuid) for puuid in result.get("profile_uuids")],
|
|
986
1026
|
updated_at=result.get_rel("rb").get("from"),
|
|
987
1027
|
branch=node_branch,
|
|
988
1028
|
labels=list(result.get_node("n").labels),
|
|
989
1029
|
)
|
|
990
1030
|
|
|
991
|
-
def get_profile_ids_by_node_id(self) -> dict[str, list[str]]:
|
|
992
|
-
profile_id_map: dict[str, list[str]] = {}
|
|
993
|
-
for result in self.results:
|
|
994
|
-
node_id = result.get_node("n").get("uuid")
|
|
995
|
-
profile_ids = result.get("profile_uuids")
|
|
996
|
-
if not node_id or not profile_ids:
|
|
997
|
-
continue
|
|
998
|
-
if node_id not in profile_id_map:
|
|
999
|
-
profile_id_map[node_id] = []
|
|
1000
|
-
profile_id_map[node_id].extend(profile_ids)
|
|
1001
|
-
return profile_id_map
|
|
1002
|
-
|
|
1003
1031
|
|
|
1004
1032
|
class FieldAttributeRequirementType(Enum):
|
|
1005
1033
|
FILTER = "filter"
|
|
@@ -1016,7 +1044,7 @@ class FieldAttributeRequirement:
|
|
|
1016
1044
|
types: list[FieldAttributeRequirementType] = dataclass_field(default_factory=list)
|
|
1017
1045
|
|
|
1018
1046
|
@property
|
|
1019
|
-
def
|
|
1047
|
+
def is_attribute_value(self) -> bool:
|
|
1020
1048
|
return bool(self.field and self.field.is_attribute and self.field_attr_name in ("value", "values", "isnull"))
|
|
1021
1049
|
|
|
1022
1050
|
@property
|
|
@@ -1027,26 +1055,10 @@ class FieldAttributeRequirement:
|
|
|
1027
1055
|
def is_order(self) -> bool:
|
|
1028
1056
|
return FieldAttributeRequirementType.ORDER in self.types
|
|
1029
1057
|
|
|
1030
|
-
@property
|
|
1031
|
-
def is_default_query_variable(self) -> str:
|
|
1032
|
-
return f"attr{self.index}_is_default"
|
|
1033
|
-
|
|
1034
1058
|
@property
|
|
1035
1059
|
def node_value_query_variable(self) -> str:
|
|
1036
1060
|
return f"attr{self.index}_node_value"
|
|
1037
1061
|
|
|
1038
|
-
@property
|
|
1039
|
-
def profile_value_query_variable(self) -> str:
|
|
1040
|
-
return f"attr{self.index}_profile_value"
|
|
1041
|
-
|
|
1042
|
-
@property
|
|
1043
|
-
def profile_final_value_query_variable(self) -> str:
|
|
1044
|
-
return f"attr{self.index}_final_profile_value"
|
|
1045
|
-
|
|
1046
|
-
@property
|
|
1047
|
-
def final_value_query_variable(self) -> str:
|
|
1048
|
-
return f"attr{self.index}_final_value"
|
|
1049
|
-
|
|
1050
1062
|
@property
|
|
1051
1063
|
def comparison_operator(self) -> str:
|
|
1052
1064
|
if self.field_attr_name == "isnull":
|
|
@@ -1182,7 +1194,6 @@ class NodeGetListQuery(Query):
|
|
|
1182
1194
|
self.params["node_ids"] = self.filters["ids"]
|
|
1183
1195
|
|
|
1184
1196
|
field_attribute_requirements = self._get_field_requirements(disable_order=disable_order)
|
|
1185
|
-
use_profiles = any(far for far in field_attribute_requirements if far.supports_profile)
|
|
1186
1197
|
await self._add_node_filter_attributes(
|
|
1187
1198
|
db=db, field_attribute_requirements=field_attribute_requirements, branch_filter=branch_filter
|
|
1188
1199
|
)
|
|
@@ -1194,21 +1205,11 @@ class NodeGetListQuery(Query):
|
|
|
1194
1205
|
for far in field_attribute_requirements:
|
|
1195
1206
|
if not far.is_order:
|
|
1196
1207
|
continue
|
|
1197
|
-
if far.supports_profile:
|
|
1198
|
-
self.order_by.append(far.final_value_query_variable)
|
|
1199
|
-
continue
|
|
1200
1208
|
self.order_by.append(far.node_value_query_variable)
|
|
1201
1209
|
|
|
1202
1210
|
# Always order by uuid to guarantee pagination, see https://github.com/opsmill/infrahub/pull/4704.
|
|
1203
1211
|
self.order_by.append("n.uuid")
|
|
1204
1212
|
|
|
1205
|
-
if use_profiles:
|
|
1206
|
-
await self._add_profiles_per_node_query(db=db, branch_filter=branch_filter)
|
|
1207
|
-
await self._add_profile_attributes(
|
|
1208
|
-
db=db, field_attribute_requirements=field_attribute_requirements, branch_filter=branch_filter
|
|
1209
|
-
)
|
|
1210
|
-
await self._add_profile_rollups(field_attribute_requirements=field_attribute_requirements)
|
|
1211
|
-
|
|
1212
1213
|
self._add_final_filter(field_attribute_requirements=field_attribute_requirements)
|
|
1213
1214
|
|
|
1214
1215
|
async def _add_node_filter_attributes(
|
|
@@ -1226,8 +1227,6 @@ class NodeGetListQuery(Query):
|
|
|
1226
1227
|
|
|
1227
1228
|
for far in field_attribute_requirements:
|
|
1228
1229
|
extra_tail_properties = {far.node_value_query_variable: "value"}
|
|
1229
|
-
if far.supports_profile:
|
|
1230
|
-
extra_tail_properties[far.is_default_query_variable] = "is_default"
|
|
1231
1230
|
subquery, subquery_params, subquery_result_name = await build_subquery_filter(
|
|
1232
1231
|
db=db,
|
|
1233
1232
|
field=far.field,
|
|
@@ -1238,7 +1237,6 @@ class NodeGetListQuery(Query):
|
|
|
1238
1237
|
branch=self.branch,
|
|
1239
1238
|
subquery_idx=far.index,
|
|
1240
1239
|
partial_match=self.partial_match,
|
|
1241
|
-
support_profiles=far.supports_profile,
|
|
1242
1240
|
extra_tail_properties=extra_tail_properties,
|
|
1243
1241
|
)
|
|
1244
1242
|
for query_var in extra_tail_properties:
|
|
@@ -1278,9 +1276,6 @@ class NodeGetListQuery(Query):
|
|
|
1278
1276
|
for far in field_attribute_requirements:
|
|
1279
1277
|
if far.field is None:
|
|
1280
1278
|
continue
|
|
1281
|
-
extra_tail_properties = {}
|
|
1282
|
-
if far.supports_profile:
|
|
1283
|
-
extra_tail_properties[far.is_default_query_variable] = "is_default"
|
|
1284
1279
|
|
|
1285
1280
|
subquery, subquery_params, _ = await build_subquery_order(
|
|
1286
1281
|
db=db,
|
|
@@ -1291,11 +1286,7 @@ class NodeGetListQuery(Query):
|
|
|
1291
1286
|
branch=self.branch,
|
|
1292
1287
|
subquery_idx=far.index,
|
|
1293
1288
|
result_prefix=far.node_value_query_variable,
|
|
1294
|
-
support_profiles=far.supports_profile,
|
|
1295
|
-
extra_tail_properties=extra_tail_properties,
|
|
1296
1289
|
)
|
|
1297
|
-
for query_var in extra_tail_properties:
|
|
1298
|
-
self._track_variable(query_var)
|
|
1299
1290
|
self._track_variable(far.node_value_query_variable)
|
|
1300
1291
|
with_str = ", ".join(self._get_tracked_variables())
|
|
1301
1292
|
|
|
@@ -1309,122 +1300,11 @@ class NodeGetListQuery(Query):
|
|
|
1309
1300
|
self.add_to_query(sort_query)
|
|
1310
1301
|
self.params.update(sort_params)
|
|
1311
1302
|
|
|
1312
|
-
async def _add_profiles_per_node_query(self, db: InfrahubDatabase, branch_filter: str) -> None:
|
|
1313
|
-
with_str = ", ".join(self._get_tracked_variables())
|
|
1314
|
-
froms_str = db.render_list_comprehension(items="relationships(profile_path)", item_name="from")
|
|
1315
|
-
profiles_per_node_query = (
|
|
1316
|
-
"""
|
|
1317
|
-
CALL (n) {
|
|
1318
|
-
OPTIONAL MATCH profile_path = (n)-[:IS_RELATED]->(profile_r:Relationship)<-[:IS_RELATED]-(maybe_profile_n:Node)-[:IS_PART_OF]->(:Root)
|
|
1319
|
-
WHERE profile_r.name = "node__profile"
|
|
1320
|
-
AND all(r in relationships(profile_path) WHERE %(branch_filter)s)
|
|
1321
|
-
WITH
|
|
1322
|
-
maybe_profile_n,
|
|
1323
|
-
profile_path,
|
|
1324
|
-
reduce(br_lvl = 0, r in relationships(profile_path) | br_lvl + r.branch_level) AS branch_level,
|
|
1325
|
-
%(froms_str)s AS froms,
|
|
1326
|
-
all(r in relationships(profile_path) WHERE r.status = "active") AS is_active
|
|
1327
|
-
RETURN maybe_profile_n, is_active, branch_level, froms
|
|
1328
|
-
}
|
|
1329
|
-
WITH %(with_str)s, maybe_profile_n, branch_level, froms, is_active
|
|
1330
|
-
ORDER BY n.uuid, maybe_profile_n.uuid, branch_level DESC, froms[-1] DESC, froms[-2] DESC, froms[-3] DESC
|
|
1331
|
-
WITH %(with_str)s, maybe_profile_n, collect(is_active) as ordered_is_actives
|
|
1332
|
-
WITH %(with_str)s, CASE
|
|
1333
|
-
WHEN ordered_is_actives[0] = True THEN maybe_profile_n ELSE NULL
|
|
1334
|
-
END AS profile_n
|
|
1335
|
-
CALL (profile_n) {
|
|
1336
|
-
OPTIONAL MATCH profile_priority_path = (profile_n)-[pr1:HAS_ATTRIBUTE]->(a:Attribute)-[pr2:HAS_VALUE]->(av:AttributeValue)
|
|
1337
|
-
WHERE a.name = "profile_priority"
|
|
1338
|
-
AND all(r in relationships(profile_priority_path) WHERE %(branch_filter)s and r.status = "active")
|
|
1339
|
-
RETURN av.value as profile_priority
|
|
1340
|
-
ORDER BY pr1.branch_level + pr2.branch_level DESC, pr2.from DESC, pr1.from DESC
|
|
1341
|
-
LIMIT 1
|
|
1342
|
-
}
|
|
1343
|
-
WITH %(with_str)s, profile_n, profile_priority
|
|
1344
|
-
"""
|
|
1345
|
-
) % {"branch_filter": branch_filter, "with_str": with_str, "froms_str": froms_str}
|
|
1346
|
-
self.add_to_query(profiles_per_node_query)
|
|
1347
|
-
self._track_variable("profile_n")
|
|
1348
|
-
self._track_variable("profile_priority")
|
|
1349
|
-
|
|
1350
|
-
async def _add_profile_attributes(
|
|
1351
|
-
self, db: InfrahubDatabase, field_attribute_requirements: list[FieldAttributeRequirement], branch_filter: str
|
|
1352
|
-
) -> None:
|
|
1353
|
-
attributes_queries: list[str] = []
|
|
1354
|
-
attributes_params: dict[str, Any] = {}
|
|
1355
|
-
profile_attributes = [far for far in field_attribute_requirements if far.supports_profile]
|
|
1356
|
-
|
|
1357
|
-
for profile_attr in profile_attributes:
|
|
1358
|
-
if not profile_attr.field:
|
|
1359
|
-
continue
|
|
1360
|
-
subquery, subquery_params, _ = await build_subquery_order(
|
|
1361
|
-
db=db,
|
|
1362
|
-
field=profile_attr.field,
|
|
1363
|
-
node_alias="profile_n",
|
|
1364
|
-
name=profile_attr.field_name,
|
|
1365
|
-
order_by=profile_attr.field_attr_name,
|
|
1366
|
-
branch_filter=branch_filter,
|
|
1367
|
-
branch=self.branch,
|
|
1368
|
-
subquery_idx=profile_attr.index,
|
|
1369
|
-
result_prefix=profile_attr.profile_value_query_variable,
|
|
1370
|
-
support_profiles=False,
|
|
1371
|
-
)
|
|
1372
|
-
attributes_params.update(subquery_params)
|
|
1373
|
-
self._track_variable(profile_attr.profile_value_query_variable)
|
|
1374
|
-
with_str = ", ".join(self._get_tracked_variables())
|
|
1375
|
-
|
|
1376
|
-
attributes_queries.append("CALL (profile_n) {")
|
|
1377
|
-
attributes_queries.append(subquery)
|
|
1378
|
-
attributes_queries.append("}")
|
|
1379
|
-
attributes_queries.append(f"WITH {with_str}")
|
|
1380
|
-
|
|
1381
|
-
self.add_to_query(attributes_queries)
|
|
1382
|
-
self.params.update(attributes_params)
|
|
1383
|
-
|
|
1384
|
-
async def _add_profile_rollups(self, field_attribute_requirements: list[FieldAttributeRequirement]) -> None:
|
|
1385
|
-
profile_attributes = [far for far in field_attribute_requirements if far.supports_profile]
|
|
1386
|
-
profile_value_collects = []
|
|
1387
|
-
for profile_attr in profile_attributes:
|
|
1388
|
-
self._untrack_variable(profile_attr.profile_value_query_variable)
|
|
1389
|
-
profile_value_collects.append(
|
|
1390
|
-
f"""head(
|
|
1391
|
-
reduce(
|
|
1392
|
-
non_null_values = [], v in collect({profile_attr.profile_value_query_variable}) |
|
|
1393
|
-
CASE WHEN v IS NOT NULL AND v <> "NULL" THEN non_null_values + [v] ELSE non_null_values END
|
|
1394
|
-
)
|
|
1395
|
-
) as {profile_attr.profile_final_value_query_variable}"""
|
|
1396
|
-
)
|
|
1397
|
-
self._untrack_variable("profile_n")
|
|
1398
|
-
self._untrack_variable("profile_priority")
|
|
1399
|
-
profile_rollup_with_str = ", ".join(self._get_tracked_variables() + profile_value_collects)
|
|
1400
|
-
profile_rollup_query = f"""
|
|
1401
|
-
ORDER BY n.uuid, profile_priority ASC, profile_n.uuid ASC
|
|
1402
|
-
WITH {profile_rollup_with_str}
|
|
1403
|
-
"""
|
|
1404
|
-
self.add_to_query(profile_rollup_query)
|
|
1405
|
-
for profile_attr in profile_attributes:
|
|
1406
|
-
self._track_variable(profile_attr.profile_final_value_query_variable)
|
|
1407
|
-
|
|
1408
|
-
final_value_with = []
|
|
1409
|
-
for profile_attr in profile_attributes:
|
|
1410
|
-
final_value_with.append(f"""
|
|
1411
|
-
CASE
|
|
1412
|
-
WHEN {profile_attr.is_default_query_variable} AND {profile_attr.profile_final_value_query_variable} IS NOT NULL
|
|
1413
|
-
THEN {profile_attr.profile_final_value_query_variable}
|
|
1414
|
-
ELSE {profile_attr.node_value_query_variable}
|
|
1415
|
-
END AS {profile_attr.final_value_query_variable}
|
|
1416
|
-
""")
|
|
1417
|
-
self._untrack_variable(profile_attr.is_default_query_variable)
|
|
1418
|
-
self._untrack_variable(profile_attr.profile_final_value_query_variable)
|
|
1419
|
-
self._untrack_variable(profile_attr.node_value_query_variable)
|
|
1420
|
-
final_value_with_str = ", ".join(self._get_tracked_variables() + final_value_with)
|
|
1421
|
-
self.add_to_query(f"WITH {final_value_with_str}")
|
|
1422
|
-
|
|
1423
1303
|
def _add_final_filter(self, field_attribute_requirements: list[FieldAttributeRequirement]) -> None:
|
|
1424
1304
|
where_parts = []
|
|
1425
1305
|
where_str = ""
|
|
1426
1306
|
for far in field_attribute_requirements:
|
|
1427
|
-
if not far.is_filter or not far.
|
|
1307
|
+
if not far.is_filter or not far.is_attribute_value:
|
|
1428
1308
|
continue
|
|
1429
1309
|
var_name = f"final_attr_value{far.index}"
|
|
1430
1310
|
self.params[var_name] = far.field_attr_comparison_value
|
|
@@ -1433,11 +1313,11 @@ class NodeGetListQuery(Query):
|
|
|
1433
1313
|
# If the any filter is an array/list
|
|
1434
1314
|
var_array = f"{var_name}_array"
|
|
1435
1315
|
where_parts.append(
|
|
1436
|
-
f"any({var_array} IN ${var_name} WHERE toLower(toString({far.
|
|
1316
|
+
f"any({var_array} IN ${var_name} WHERE toLower(toString({far.node_value_query_variable})) CONTAINS toLower({var_array}))"
|
|
1437
1317
|
)
|
|
1438
1318
|
else:
|
|
1439
1319
|
where_parts.append(
|
|
1440
|
-
f"toLower(toString({far.
|
|
1320
|
+
f"toLower(toString({far.node_value_query_variable})) CONTAINS toLower(toString(${var_name}))"
|
|
1441
1321
|
)
|
|
1442
1322
|
continue
|
|
1443
1323
|
if far.field and isinstance(far.field, AttributeSchema) and far.field.kind == "List":
|
|
@@ -1446,10 +1326,10 @@ class NodeGetListQuery(Query):
|
|
|
1446
1326
|
else:
|
|
1447
1327
|
self.params[var_name] = build_regex_attrs(values=[far.field_attr_comparison_value])
|
|
1448
1328
|
|
|
1449
|
-
where_parts.append(f"toString({far.
|
|
1329
|
+
where_parts.append(f"toString({far.node_value_query_variable}) =~ ${var_name}")
|
|
1450
1330
|
continue
|
|
1451
1331
|
|
|
1452
|
-
where_parts.append(f"{far.
|
|
1332
|
+
where_parts.append(f"{far.node_value_query_variable} {far.comparison_operator} ${var_name}")
|
|
1453
1333
|
if where_parts:
|
|
1454
1334
|
where_str = "WHERE " + " AND ".join(where_parts)
|
|
1455
1335
|
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 = """
|
|
@@ -1019,6 +1036,7 @@ class RelationshipCountPerNodeQuery(Query):
|
|
|
1019
1036
|
""" % {"branch_filter": branch_filter, "path": path}
|
|
1020
1037
|
|
|
1021
1038
|
self.add_to_query(query)
|
|
1039
|
+
self.order_by = ["peer_node.uuid"]
|
|
1022
1040
|
self.return_labels = ["peer_node.uuid", "COUNT(peer_node.uuid) as nbr_peers"]
|
|
1023
1041
|
|
|
1024
1042
|
async def get_count_per_peer(self) -> dict[str, int]:
|
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
|
|