infrahub-server 1.2.11__py3-none-any.whl → 1.3.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/constants.py +130 -0
- infrahub/actions/gather.py +114 -0
- infrahub/actions/models.py +243 -0
- infrahub/actions/parsers.py +104 -0
- infrahub/actions/schema.py +393 -0
- infrahub/actions/tasks.py +119 -0
- infrahub/actions/triggers.py +21 -0
- infrahub/branch/__init__.py +0 -0
- infrahub/branch/tasks.py +29 -0
- infrahub/branch/triggers.py +22 -0
- infrahub/cli/db.py +3 -4
- infrahub/computed_attribute/gather.py +3 -1
- infrahub/computed_attribute/tasks.py +23 -29
- infrahub/core/account.py +24 -47
- infrahub/core/attribute.py +13 -15
- infrahub/core/constants/__init__.py +10 -0
- infrahub/core/constants/database.py +1 -0
- infrahub/core/constants/infrahubkind.py +9 -0
- infrahub/core/constraint/node/runner.py +3 -1
- infrahub/core/convert_object_type/__init__.py +0 -0
- infrahub/core/convert_object_type/conversion.py +124 -0
- infrahub/core/convert_object_type/schema_mapping.py +56 -0
- infrahub/core/diff/coordinator.py +8 -1
- infrahub/core/diff/query/all_conflicts.py +1 -5
- infrahub/core/diff/query/artifact.py +10 -20
- infrahub/core/diff/query/delete_query.py +8 -4
- infrahub/core/diff/query/diff_get.py +3 -6
- infrahub/core/diff/query/field_specifiers.py +1 -1
- infrahub/core/diff/query/field_summary.py +2 -4
- infrahub/core/diff/query/merge.py +72 -125
- infrahub/core/diff/query/save.py +83 -68
- infrahub/core/diff/query/summary_counts_enricher.py +34 -54
- infrahub/core/diff/query/time_range_query.py +0 -1
- infrahub/core/diff/repository/repository.py +4 -0
- infrahub/core/graph/__init__.py +1 -1
- infrahub/core/manager.py +14 -11
- infrahub/core/migrations/graph/__init__.py +6 -0
- infrahub/core/migrations/graph/m003_relationship_parent_optional.py +1 -2
- infrahub/core/migrations/graph/m012_convert_account_generic.py +1 -1
- infrahub/core/migrations/graph/m013_convert_git_password_credential.py +2 -6
- infrahub/core/migrations/graph/m015_diff_format_update.py +1 -2
- infrahub/core/migrations/graph/m016_diff_delete_bug_fix.py +1 -2
- infrahub/core/migrations/graph/m019_restore_rels_to_time.py +11 -22
- infrahub/core/migrations/graph/m020_duplicate_edges.py +3 -6
- infrahub/core/migrations/graph/m021_missing_hierarchy_merge.py +1 -2
- infrahub/core/migrations/graph/m023_deduplicate_cardinality_one_relationships.py +2 -2
- infrahub/core/migrations/graph/m024_missing_hierarchy_backfill.py +1 -2
- infrahub/core/migrations/graph/m028_delete_diffs.py +1 -2
- infrahub/core/migrations/graph/m029_duplicates_cleanup.py +662 -0
- infrahub/core/migrations/graph/m030_illegal_edges.py +82 -0
- infrahub/core/migrations/query/attribute_add.py +14 -11
- infrahub/core/migrations/query/attribute_rename.py +6 -11
- infrahub/core/migrations/query/delete_element_in_schema.py +19 -17
- infrahub/core/migrations/query/node_duplicate.py +19 -21
- infrahub/core/migrations/query/relationship_duplicate.py +19 -18
- infrahub/core/migrations/schema/node_attribute_remove.py +4 -8
- infrahub/core/migrations/schema/node_remove.py +19 -20
- infrahub/core/models.py +29 -2
- infrahub/core/node/__init__.py +131 -28
- infrahub/core/node/base.py +1 -1
- infrahub/core/node/create.py +211 -0
- infrahub/core/node/resource_manager/number_pool.py +31 -5
- infrahub/core/node/standard.py +6 -1
- infrahub/core/path.py +15 -1
- infrahub/core/protocols.py +57 -0
- infrahub/core/protocols_base.py +3 -0
- infrahub/core/query/__init__.py +2 -2
- infrahub/core/query/delete.py +3 -3
- infrahub/core/query/diff.py +19 -32
- infrahub/core/query/ipam.py +10 -20
- infrahub/core/query/node.py +29 -47
- infrahub/core/query/relationship.py +55 -34
- infrahub/core/query/resource_manager.py +1 -2
- infrahub/core/query/standard_node.py +19 -5
- infrahub/core/query/subquery.py +2 -4
- infrahub/core/relationship/constraints/count.py +10 -9
- infrahub/core/relationship/constraints/interface.py +2 -1
- infrahub/core/relationship/constraints/peer_kind.py +2 -1
- infrahub/core/relationship/constraints/peer_parent.py +56 -0
- infrahub/core/relationship/constraints/peer_relatives.py +72 -0
- infrahub/core/relationship/constraints/profiles_kind.py +1 -1
- infrahub/core/relationship/model.py +4 -1
- infrahub/core/schema/__init__.py +2 -1
- infrahub/core/schema/attribute_parameters.py +160 -0
- infrahub/core/schema/attribute_schema.py +130 -7
- infrahub/core/schema/basenode_schema.py +27 -3
- infrahub/core/schema/definitions/core/__init__.py +29 -1
- infrahub/core/schema/definitions/core/group.py +45 -0
- infrahub/core/schema/definitions/core/resource_pool.py +9 -0
- infrahub/core/schema/definitions/internal.py +43 -5
- infrahub/core/schema/generated/attribute_schema.py +16 -3
- infrahub/core/schema/generated/relationship_schema.py +11 -1
- infrahub/core/schema/manager.py +7 -2
- infrahub/core/schema/schema_branch.py +109 -12
- infrahub/core/validators/__init__.py +15 -2
- infrahub/core/validators/attribute/choices.py +1 -3
- infrahub/core/validators/attribute/enum.py +1 -3
- infrahub/core/validators/attribute/kind.py +1 -3
- infrahub/core/validators/attribute/length.py +13 -7
- infrahub/core/validators/attribute/min_max.py +118 -0
- infrahub/core/validators/attribute/number_pool.py +106 -0
- infrahub/core/validators/attribute/optional.py +1 -4
- infrahub/core/validators/attribute/regex.py +5 -6
- infrahub/core/validators/attribute/unique.py +1 -3
- infrahub/core/validators/determiner.py +18 -2
- infrahub/core/validators/enum.py +12 -0
- infrahub/core/validators/node/hierarchy.py +3 -6
- infrahub/core/validators/query.py +1 -3
- infrahub/core/validators/relationship/count.py +6 -12
- infrahub/core/validators/relationship/optional.py +2 -4
- infrahub/core/validators/relationship/peer.py +177 -12
- infrahub/core/validators/tasks.py +1 -1
- infrahub/core/validators/uniqueness/query.py +5 -9
- infrahub/database/__init__.py +12 -4
- infrahub/database/validation.py +100 -0
- infrahub/dependencies/builder/constraint/grouped/node_runner.py +4 -0
- infrahub/dependencies/builder/constraint/relationship_manager/peer_parent.py +8 -0
- infrahub/dependencies/builder/constraint/relationship_manager/peer_relatives.py +8 -0
- infrahub/dependencies/builder/constraint/schema/aggregated.py +2 -0
- infrahub/dependencies/builder/constraint/schema/relationship_peer.py +8 -0
- infrahub/dependencies/builder/diff/deserializer.py +1 -1
- infrahub/dependencies/registry.py +4 -0
- infrahub/events/group_action.py +1 -0
- infrahub/events/models.py +1 -1
- infrahub/git/base.py +5 -3
- infrahub/git/integrator.py +96 -5
- infrahub/git/tasks.py +1 -0
- infrahub/graphql/analyzer.py +139 -18
- infrahub/graphql/manager.py +4 -0
- infrahub/graphql/mutations/action.py +164 -0
- infrahub/graphql/mutations/convert_object_type.py +71 -0
- infrahub/graphql/mutations/main.py +25 -176
- infrahub/graphql/mutations/proposed_change.py +20 -17
- infrahub/graphql/mutations/relationship.py +32 -0
- infrahub/graphql/mutations/resource_manager.py +63 -7
- infrahub/graphql/queries/convert_object_type_mapping.py +34 -0
- infrahub/graphql/queries/resource_manager.py +7 -1
- infrahub/graphql/resolvers/many_relationship.py +1 -1
- infrahub/graphql/resolvers/resolver.py +2 -2
- infrahub/graphql/resolvers/single_relationship.py +1 -1
- infrahub/graphql/schema.py +6 -0
- infrahub/menu/menu.py +34 -2
- infrahub/message_bus/messages/__init__.py +0 -10
- infrahub/message_bus/operations/__init__.py +0 -8
- infrahub/message_bus/operations/refresh/registry.py +4 -7
- infrahub/patch/queries/delete_duplicated_edges.py +45 -39
- infrahub/pools/models.py +14 -0
- infrahub/pools/number.py +5 -3
- infrahub/pools/registration.py +22 -0
- infrahub/pools/tasks.py +126 -0
- infrahub/prefect_server/models.py +1 -19
- infrahub/proposed_change/models.py +68 -3
- infrahub/proposed_change/tasks.py +911 -34
- infrahub/schema/__init__.py +0 -0
- infrahub/schema/tasks.py +27 -0
- infrahub/schema/triggers.py +23 -0
- infrahub/task_manager/models.py +10 -6
- infrahub/trigger/catalogue.py +6 -0
- infrahub/trigger/models.py +23 -6
- infrahub/trigger/setup.py +26 -2
- infrahub/trigger/tasks.py +4 -2
- infrahub/types.py +6 -0
- infrahub/webhook/tasks.py +6 -9
- infrahub/workflows/catalogue.py +103 -1
- infrahub_sdk/client.py +43 -10
- infrahub_sdk/ctl/generator.py +4 -4
- infrahub_sdk/ctl/repository.py +1 -1
- infrahub_sdk/node/__init__.py +39 -0
- infrahub_sdk/node/attribute.py +122 -0
- infrahub_sdk/node/constants.py +21 -0
- infrahub_sdk/{node.py → node/node.py} +158 -803
- infrahub_sdk/node/parsers.py +15 -0
- infrahub_sdk/node/property.py +24 -0
- infrahub_sdk/node/related_node.py +266 -0
- infrahub_sdk/node/relationship.py +302 -0
- infrahub_sdk/protocols.py +112 -0
- infrahub_sdk/protocols_base.py +34 -2
- infrahub_sdk/pytest_plugin/items/python_transform.py +2 -1
- infrahub_sdk/query_groups.py +17 -5
- infrahub_sdk/schema/main.py +1 -0
- infrahub_sdk/schema/repository.py +16 -0
- infrahub_sdk/spec/object.py +1 -1
- infrahub_sdk/store.py +1 -1
- infrahub_sdk/testing/schemas/car_person.py +1 -0
- infrahub_sdk/utils.py +7 -20
- infrahub_sdk/yaml.py +6 -5
- {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0.dist-info}/METADATA +5 -5
- {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0.dist-info}/RECORD +197 -168
- {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0.dist-info}/WHEEL +1 -1
- infrahub_testcontainers/container.py +239 -65
- infrahub_testcontainers/docker-compose-cluster.test.yml +321 -0
- infrahub_testcontainers/docker-compose.test.yml +2 -1
- infrahub_testcontainers/helpers.py +23 -3
- infrahub_testcontainers/plugin.py +9 -0
- infrahub/message_bus/messages/check_generator_run.py +0 -26
- infrahub/message_bus/messages/finalize_validator_execution.py +0 -15
- infrahub/message_bus/messages/proposed_change/base_with_diff.py +0 -16
- infrahub/message_bus/messages/proposed_change/request_proposedchange_refreshartifacts.py +0 -11
- infrahub/message_bus/messages/request_generatordefinition_check.py +0 -20
- infrahub/message_bus/messages/request_proposedchange_pipeline.py +0 -23
- infrahub/message_bus/operations/check/__init__.py +0 -3
- infrahub/message_bus/operations/check/generator.py +0 -156
- infrahub/message_bus/operations/finalize/__init__.py +0 -3
- infrahub/message_bus/operations/finalize/validator.py +0 -133
- infrahub/message_bus/operations/requests/__init__.py +0 -9
- infrahub/message_bus/operations/requests/generator_definition.py +0 -140
- infrahub/message_bus/operations/requests/proposed_change.py +0 -629
- infrahub/patch/queries/consolidate_duplicated_nodes.py +0 -109
- /infrahub/{message_bus/messages/proposed_change → actions}/__init__.py +0 -0
- {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0.dist-info}/LICENSE.txt +0 -0
- {infrahub_server-1.2.11.dist-info → infrahub_server-1.3.0.dist-info}/entry_points.txt +0 -0
infrahub/core/query/node.py
CHANGED
|
@@ -207,12 +207,11 @@ class NodeCreateAllQuery(NodeQuery):
|
|
|
207
207
|
attrs_query = """
|
|
208
208
|
WITH distinct n
|
|
209
209
|
UNWIND $attrs AS attr
|
|
210
|
-
CALL {
|
|
211
|
-
WITH n, attr
|
|
210
|
+
CALL (n, attr) {
|
|
212
211
|
CREATE (a:Attribute { uuid: attr.uuid, name: attr.name, branch_support: attr.branch_support })
|
|
213
212
|
CREATE (n)-[:HAS_ATTRIBUTE { branch: attr.branch, branch_level: attr.branch_level, status: attr.status, from: $at }]->(a)
|
|
214
213
|
MERGE (av:AttributeValue { value: attr.content.value, is_default: attr.content.is_default })
|
|
215
|
-
WITH
|
|
214
|
+
WITH av, a
|
|
216
215
|
LIMIT 1
|
|
217
216
|
CREATE (a)-[:HAS_VALUE { branch: attr.branch, branch_level: attr.branch_level, status: attr.status, from: $at }]->(av)
|
|
218
217
|
MERGE (ip:Boolean { value: attr.is_protected })
|
|
@@ -232,13 +231,12 @@ class NodeCreateAllQuery(NodeQuery):
|
|
|
232
231
|
attrs_iphost_query = """
|
|
233
232
|
WITH distinct n
|
|
234
233
|
UNWIND $attrs_iphost AS attr_iphost
|
|
235
|
-
CALL {
|
|
236
|
-
WITH n, attr_iphost
|
|
234
|
+
CALL (n, attr_iphost) {
|
|
237
235
|
WITH n, attr_iphost AS attr
|
|
238
236
|
CREATE (a:Attribute { uuid: attr.uuid, name: attr.name, branch_support: attr.branch_support })
|
|
239
237
|
CREATE (n)-[:HAS_ATTRIBUTE { branch: attr.branch, branch_level: attr.branch_level, status: attr.status, from: $at }]->(a)
|
|
240
238
|
MERGE (av:AttributeValue:AttributeIPHost { %(iphost_prop)s })
|
|
241
|
-
WITH
|
|
239
|
+
WITH attr, av, a
|
|
242
240
|
LIMIT 1
|
|
243
241
|
CREATE (a)-[:HAS_VALUE { branch: attr.branch, branch_level: attr.branch_level, status: attr.status, from: $at }]->(av)
|
|
244
242
|
MERGE (ip:Boolean { value: attr.is_protected })
|
|
@@ -259,13 +257,12 @@ class NodeCreateAllQuery(NodeQuery):
|
|
|
259
257
|
attrs_ipnetwork_query = """
|
|
260
258
|
WITH distinct n
|
|
261
259
|
UNWIND $attrs_ipnetwork AS attr_ipnetwork
|
|
262
|
-
CALL {
|
|
263
|
-
WITH n, attr_ipnetwork
|
|
260
|
+
CALL (n, attr_ipnetwork) {
|
|
264
261
|
WITH n, attr_ipnetwork AS attr
|
|
265
262
|
CREATE (a:Attribute { uuid: attr.uuid, name: attr.name, branch_support: attr.branch_support })
|
|
266
263
|
CREATE (n)-[:HAS_ATTRIBUTE { branch: attr.branch, branch_level: attr.branch_level, status: attr.status, from: $at }]->(a)
|
|
267
264
|
MERGE (av:AttributeValue:AttributeIPNetwork { %(ipnetwork_prop)s })
|
|
268
|
-
WITH
|
|
265
|
+
WITH attr, av, a
|
|
269
266
|
LIMIT 1
|
|
270
267
|
CREATE (a)-[:HAS_VALUE { branch: attr.branch, branch_level: attr.branch_level, status: attr.status, from: $at }]->(av)
|
|
271
268
|
MERGE (ip:Boolean { value: attr.is_protected })
|
|
@@ -286,8 +283,7 @@ class NodeCreateAllQuery(NodeQuery):
|
|
|
286
283
|
rels_bidir_query = """
|
|
287
284
|
WITH distinct n
|
|
288
285
|
UNWIND $rels_bidir AS rel
|
|
289
|
-
CALL {
|
|
290
|
-
WITH n, rel
|
|
286
|
+
CALL (n, rel) {
|
|
291
287
|
MERGE (d:Node { uuid: rel.destination_id })
|
|
292
288
|
CREATE (rl:Relationship { uuid: rel.uuid, name: rel.name, branch_support: rel.branch_support })
|
|
293
289
|
CREATE (n)-[:IS_RELATED %(rel_prop)s ]->(rl)
|
|
@@ -310,8 +306,7 @@ class NodeCreateAllQuery(NodeQuery):
|
|
|
310
306
|
rels_out_query = """
|
|
311
307
|
WITH distinct n
|
|
312
308
|
UNWIND $rels_out AS rel_out
|
|
313
|
-
CALL {
|
|
314
|
-
WITH n, rel_out
|
|
309
|
+
CALL (n, rel_out) {
|
|
315
310
|
WITH n, rel_out as rel
|
|
316
311
|
MERGE (d:Node { uuid: rel.destination_id })
|
|
317
312
|
CREATE (rl:Relationship { uuid: rel.uuid, name: rel.name, branch_support: rel.branch_support })
|
|
@@ -335,8 +330,7 @@ class NodeCreateAllQuery(NodeQuery):
|
|
|
335
330
|
rels_in_query = """
|
|
336
331
|
WITH distinct n
|
|
337
332
|
UNWIND $rels_in AS rel_in
|
|
338
|
-
CALL {
|
|
339
|
-
WITH n, rel_in
|
|
333
|
+
CALL (n, rel_in) {
|
|
340
334
|
WITH n, rel_in AS rel
|
|
341
335
|
MERGE (d:Node { uuid: rel.destination_id })
|
|
342
336
|
CREATE (rl:Relationship { uuid: rel.uuid, name: rel.name, branch_support: rel.branch_support })
|
|
@@ -424,8 +418,7 @@ class NodeDeleteQuery(NodeQuery):
|
|
|
424
418
|
node_filter, node_filter_params = self.branch.get_query_filter_path(at=self.at, variable_name="r")
|
|
425
419
|
node_query_match = """
|
|
426
420
|
MATCH (n:Node { uuid: $uuid })
|
|
427
|
-
CALL {
|
|
428
|
-
WITH n
|
|
421
|
+
CALL (n) {
|
|
429
422
|
MATCH (n)-[r:IS_PART_OF]->(:Root)
|
|
430
423
|
WHERE %(node_filter)s
|
|
431
424
|
RETURN r.status = "active" AS is_active
|
|
@@ -520,8 +513,7 @@ class NodeListGetAttributeQuery(Query):
|
|
|
520
513
|
self.add_to_query(query)
|
|
521
514
|
|
|
522
515
|
query = """
|
|
523
|
-
CALL {
|
|
524
|
-
WITH n, a
|
|
516
|
+
CALL (n, a) {
|
|
525
517
|
MATCH (n)-[r:HAS_ATTRIBUTE]-(a:Attribute)
|
|
526
518
|
WHERE %(branch_filter)s
|
|
527
519
|
RETURN n as n1, r as r1, a as a1
|
|
@@ -533,8 +525,7 @@ class NodeListGetAttributeQuery(Query):
|
|
|
533
525
|
WITH n, r1, a
|
|
534
526
|
MATCH (a)-[r:HAS_VALUE]-(av:AttributeValue)
|
|
535
527
|
WHERE %(branch_filter)s
|
|
536
|
-
CALL {
|
|
537
|
-
WITH a, av
|
|
528
|
+
CALL (a, av) {
|
|
538
529
|
MATCH (a)-[r:HAS_VALUE]-(av:AttributeValue)
|
|
539
530
|
WHERE %(branch_filter)s
|
|
540
531
|
RETURN a as a1, r as r2, av as av1
|
|
@@ -698,14 +689,12 @@ class NodeListGetRelationshipsQuery(Query):
|
|
|
698
689
|
|
|
699
690
|
query = """
|
|
700
691
|
MATCH (n:Node) WHERE n.uuid IN $ids
|
|
701
|
-
CALL {
|
|
702
|
-
WITH n
|
|
692
|
+
CALL (n) {
|
|
703
693
|
MATCH (n)<-[:IS_RELATED]-(rel:Relationship)<-[:IS_RELATED]-(peer)
|
|
704
694
|
WHERE ($inbound_identifiers IS NULL OR rel.name in $inbound_identifiers)
|
|
705
695
|
AND n.uuid <> peer.uuid
|
|
706
696
|
WITH DISTINCT n, rel, peer
|
|
707
|
-
CALL {
|
|
708
|
-
WITH n, rel, peer
|
|
697
|
+
CALL (n, rel, peer) {
|
|
709
698
|
MATCH (n)<-[r:IS_RELATED]-(rel)
|
|
710
699
|
WHERE (%(filters)s)
|
|
711
700
|
WITH n, rel, peer, r
|
|
@@ -729,8 +718,7 @@ class NodeListGetRelationshipsQuery(Query):
|
|
|
729
718
|
WHERE ($outbound_identifiers IS NULL OR rel.name in $outbound_identifiers)
|
|
730
719
|
AND n.uuid <> peer.uuid
|
|
731
720
|
WITH DISTINCT n, rel, peer
|
|
732
|
-
CALL {
|
|
733
|
-
WITH n, rel, peer
|
|
721
|
+
CALL (n, rel, peer) {
|
|
734
722
|
MATCH (n)-[r:IS_RELATED]->(rel)
|
|
735
723
|
WHERE (%(filters)s)
|
|
736
724
|
WITH n, rel, peer, r
|
|
@@ -754,8 +742,7 @@ class NodeListGetRelationshipsQuery(Query):
|
|
|
754
742
|
WHERE ($bidirectional_identifiers IS NULL OR rel.name in $bidirectional_identifiers)
|
|
755
743
|
AND n.uuid <> peer.uuid
|
|
756
744
|
WITH DISTINCT n, rel, peer
|
|
757
|
-
CALL {
|
|
758
|
-
WITH n, rel, peer
|
|
745
|
+
CALL (n, rel, peer) {
|
|
759
746
|
MATCH (n)-[r:IS_RELATED]->(rel)
|
|
760
747
|
WHERE (%(filters)s)
|
|
761
748
|
WITH n, rel, peer, r
|
|
@@ -849,8 +836,7 @@ class NodeListGetInfoQuery(Query):
|
|
|
849
836
|
query = """
|
|
850
837
|
MATCH p = (root:Root)<-[:IS_PART_OF]-(n:Node)
|
|
851
838
|
WHERE n.uuid IN $ids
|
|
852
|
-
CALL {
|
|
853
|
-
WITH root, n
|
|
839
|
+
CALL (root, n) {
|
|
854
840
|
MATCH (root:Root)<-[r:IS_PART_OF]-(n:Node)
|
|
855
841
|
WHERE %(branch_filter)s
|
|
856
842
|
RETURN n as n1, r as r1
|
|
@@ -1046,8 +1032,7 @@ class NodeGetListQuery(Query):
|
|
|
1046
1032
|
if not self.branch.is_default:
|
|
1047
1033
|
topquery = """
|
|
1048
1034
|
MATCH (n:%(node_kind)s)
|
|
1049
|
-
CALL {
|
|
1050
|
-
WITH n
|
|
1035
|
+
CALL (n) {
|
|
1051
1036
|
MATCH (root:Root)<-[r:IS_PART_OF]-(n)
|
|
1052
1037
|
WHERE %(branch_filter)s
|
|
1053
1038
|
RETURN r
|
|
@@ -1152,7 +1137,7 @@ class NodeGetListQuery(Query):
|
|
|
1152
1137
|
)
|
|
1153
1138
|
|
|
1154
1139
|
filter_params.update(subquery_params)
|
|
1155
|
-
filter_query.append("CALL {")
|
|
1140
|
+
filter_query.append("CALL (n) {")
|
|
1156
1141
|
filter_query.append(subquery)
|
|
1157
1142
|
filter_query.append("}")
|
|
1158
1143
|
filter_query.append(f"WITH {with_str}")
|
|
@@ -1201,7 +1186,7 @@ class NodeGetListQuery(Query):
|
|
|
1201
1186
|
with_str = ", ".join(self._get_tracked_variables())
|
|
1202
1187
|
|
|
1203
1188
|
sort_params.update(subquery_params)
|
|
1204
|
-
sort_query.append("CALL {")
|
|
1189
|
+
sort_query.append("CALL (n) {")
|
|
1205
1190
|
sort_query.append(subquery)
|
|
1206
1191
|
sort_query.append("}")
|
|
1207
1192
|
sort_query.append(f"WITH {with_str}")
|
|
@@ -1215,8 +1200,7 @@ class NodeGetListQuery(Query):
|
|
|
1215
1200
|
froms_str = db.render_list_comprehension(items="relationships(profile_path)", item_name="from")
|
|
1216
1201
|
profiles_per_node_query = (
|
|
1217
1202
|
"""
|
|
1218
|
-
CALL {
|
|
1219
|
-
WITH n
|
|
1203
|
+
CALL (n) {
|
|
1220
1204
|
OPTIONAL MATCH profile_path = (n)-[:IS_RELATED]->(profile_r:Relationship)<-[:IS_RELATED]-(maybe_profile_n:Node)-[:IS_PART_OF]->(:Root)
|
|
1221
1205
|
WHERE profile_r.name = "node__profile"
|
|
1222
1206
|
AND all(r in relationships(profile_path) WHERE %(branch_filter)s)
|
|
@@ -1234,8 +1218,7 @@ class NodeGetListQuery(Query):
|
|
|
1234
1218
|
WITH %(with_str)s, CASE
|
|
1235
1219
|
WHEN ordered_is_actives[0] = True THEN maybe_profile_n ELSE NULL
|
|
1236
1220
|
END AS profile_n
|
|
1237
|
-
CALL {
|
|
1238
|
-
WITH profile_n
|
|
1221
|
+
CALL (profile_n) {
|
|
1239
1222
|
OPTIONAL MATCH profile_priority_path = (profile_n)-[pr1:HAS_ATTRIBUTE]->(a:Attribute)-[pr2:HAS_VALUE]->(av:AttributeValue)
|
|
1240
1223
|
WHERE a.name = "profile_priority"
|
|
1241
1224
|
AND all(r in relationships(profile_priority_path) WHERE %(branch_filter)s and r.status = "active")
|
|
@@ -1276,7 +1259,7 @@ class NodeGetListQuery(Query):
|
|
|
1276
1259
|
self._track_variable(profile_attr.profile_value_query_variable)
|
|
1277
1260
|
with_str = ", ".join(self._get_tracked_variables())
|
|
1278
1261
|
|
|
1279
|
-
attributes_queries.append("CALL {")
|
|
1262
|
+
attributes_queries.append("CALL (profile_n) {")
|
|
1280
1263
|
attributes_queries.append(subquery)
|
|
1281
1264
|
attributes_queries.append("}")
|
|
1282
1265
|
attributes_queries.append(f"WITH {with_str}")
|
|
@@ -1457,17 +1440,16 @@ class NodeGetHierarchyQuery(Query):
|
|
|
1457
1440
|
MATCH path = (n:Node { uuid: $uuid } )%(filter)s(peer:Node)
|
|
1458
1441
|
WHERE $hierarchy IN LABELS(peer) and all(r IN relationships(path) WHERE (%(branch_filter)s))
|
|
1459
1442
|
WITH n, collect(last(nodes(path))) AS peers_with_duplicates
|
|
1460
|
-
CALL {
|
|
1461
|
-
WITH peers_with_duplicates
|
|
1443
|
+
CALL (peers_with_duplicates) {
|
|
1462
1444
|
UNWIND peers_with_duplicates AS pwd
|
|
1463
1445
|
RETURN DISTINCT pwd AS peer
|
|
1464
1446
|
}
|
|
1447
|
+
|
|
1465
1448
|
""" % {"filter": filter_str, "branch_filter": branch_filter}
|
|
1466
1449
|
|
|
1467
1450
|
if not self.branch.is_default:
|
|
1468
1451
|
query += """
|
|
1469
|
-
CALL {
|
|
1470
|
-
WITH n, peer
|
|
1452
|
+
CALL (n, peer) {
|
|
1471
1453
|
MATCH path = (n)%(filter)s(peer)
|
|
1472
1454
|
WHERE all(r IN relationships(path) WHERE (%(branch_filter)s))
|
|
1473
1455
|
WITH %(with_clause)s
|
|
@@ -1487,7 +1469,7 @@ class NodeGetHierarchyQuery(Query):
|
|
|
1487
1469
|
|
|
1488
1470
|
clean_filters = extract_field_filters(field_name=self.direction.value, filters=self.filters)
|
|
1489
1471
|
|
|
1490
|
-
if clean_filters and "id" in clean_filters or "ids" in clean_filters:
|
|
1472
|
+
if (clean_filters and "id" in clean_filters) or "ids" in clean_filters:
|
|
1491
1473
|
where_clause.append("peer.uuid IN $peer_ids")
|
|
1492
1474
|
self.params["peer_ids"] = clean_filters.get("ids", [])
|
|
1493
1475
|
if clean_filters.get("id", None):
|
|
@@ -1532,7 +1514,7 @@ class NodeGetHierarchyQuery(Query):
|
|
|
1532
1514
|
[f"{subquery_result_name} as {label}" if label == "peer" else label for label in self.return_labels]
|
|
1533
1515
|
)
|
|
1534
1516
|
|
|
1535
|
-
self.add_subquery(subquery=subquery, with_clause=with_str)
|
|
1517
|
+
self.add_subquery(subquery=subquery, node_alias="peer", with_clause=with_str)
|
|
1536
1518
|
|
|
1537
1519
|
# ----------------------------------------------------------------------------
|
|
1538
1520
|
# ORDER Results
|
|
@@ -1560,7 +1542,7 @@ class NodeGetHierarchyQuery(Query):
|
|
|
1560
1542
|
self.order_by.append(subquery_result_name)
|
|
1561
1543
|
self.params.update(subquery_params)
|
|
1562
1544
|
|
|
1563
|
-
self.add_subquery(subquery=subquery)
|
|
1545
|
+
self.add_subquery(subquery=subquery, node_alias="peer")
|
|
1564
1546
|
|
|
1565
1547
|
order_cnt += 1
|
|
1566
1548
|
else:
|
|
@@ -217,8 +217,7 @@ class RelationshipQuery(Query):
|
|
|
217
217
|
)
|
|
218
218
|
source_query_match = """
|
|
219
219
|
MATCH (s:Node { uuid: $source_id })
|
|
220
|
-
CALL {
|
|
221
|
-
WITH s
|
|
220
|
+
CALL (s) {
|
|
222
221
|
MATCH (s)-[r:IS_PART_OF]->(:Root)
|
|
223
222
|
WHERE %(source_filter)s
|
|
224
223
|
RETURN r.status = "active" AS s_is_active
|
|
@@ -246,8 +245,7 @@ class RelationshipQuery(Query):
|
|
|
246
245
|
)
|
|
247
246
|
destination_query_match = """
|
|
248
247
|
MATCH (d:Node { uuid: $destination_id })
|
|
249
|
-
CALL {
|
|
250
|
-
WITH d
|
|
248
|
+
CALL (d) {
|
|
251
249
|
MATCH (d)-[r:IS_PART_OF]->(:Root)
|
|
252
250
|
WHERE %(destination_filter)s
|
|
253
251
|
RETURN r.status = "active" AS d_is_active
|
|
@@ -524,8 +522,7 @@ class RelationshipDeleteQuery(RelationshipQuery):
|
|
|
524
522
|
CREATE (s)%(r1)s(rl)
|
|
525
523
|
CREATE (rl)%(r2)s(d)
|
|
526
524
|
WITH rl
|
|
527
|
-
CALL {
|
|
528
|
-
WITH rl
|
|
525
|
+
CALL (rl) {
|
|
529
526
|
MATCH (rl)-[edge:IS_VISIBLE]->(visible)
|
|
530
527
|
WHERE %(rel_filter)s AND edge.status = "active"
|
|
531
528
|
WITH rl, edge, visible
|
|
@@ -536,8 +533,7 @@ class RelationshipDeleteQuery(RelationshipQuery):
|
|
|
536
533
|
WHERE edge.branch = $branch
|
|
537
534
|
SET edge.to = $at
|
|
538
535
|
}
|
|
539
|
-
CALL {
|
|
540
|
-
WITH rl
|
|
536
|
+
CALL (rl) {
|
|
541
537
|
MATCH (rl)-[edge:IS_PROTECTED]->(protected)
|
|
542
538
|
WHERE %(rel_filter)s AND edge.status = "active"
|
|
543
539
|
WITH rl, edge, protected
|
|
@@ -548,8 +544,7 @@ class RelationshipDeleteQuery(RelationshipQuery):
|
|
|
548
544
|
WHERE edge.branch = $branch
|
|
549
545
|
SET edge.to = $at
|
|
550
546
|
}
|
|
551
|
-
CALL {
|
|
552
|
-
WITH rl
|
|
547
|
+
CALL (rl) {
|
|
553
548
|
MATCH (rl)-[edge:HAS_OWNER]->(owner_node)
|
|
554
549
|
WHERE %(rel_filter)s AND edge.status = "active"
|
|
555
550
|
WITH rl, edge, owner_node
|
|
@@ -560,8 +555,7 @@ class RelationshipDeleteQuery(RelationshipQuery):
|
|
|
560
555
|
WHERE edge.branch = $branch
|
|
561
556
|
SET edge.to = $at
|
|
562
557
|
}
|
|
563
|
-
CALL {
|
|
564
|
-
WITH rl
|
|
558
|
+
CALL (rl) {
|
|
565
559
|
MATCH (rl)-[edge:HAS_SOURCE]->(source_node)
|
|
566
560
|
WHERE %(rel_filter)s AND edge.status = "active"
|
|
567
561
|
WITH rl, edge, source_node
|
|
@@ -656,8 +650,7 @@ class RelationshipGetPeerQuery(Query):
|
|
|
656
650
|
MATCH (source_node:Node)%(arrow_left_start)s[:IS_RELATED]%(arrow_left_end)s(rl:Relationship { name: $rel_identifier })
|
|
657
651
|
WHERE source_node.uuid IN $source_ids
|
|
658
652
|
WITH DISTINCT source_node, rl
|
|
659
|
-
CALL {
|
|
660
|
-
WITH rl, source_node
|
|
653
|
+
CALL (rl, source_node) {
|
|
661
654
|
MATCH path = (source_node)%(path)s(peer:Node)
|
|
662
655
|
WHERE
|
|
663
656
|
$source_kind IN LABELS(source_node) AND
|
|
@@ -683,7 +676,7 @@ class RelationshipGetPeerQuery(Query):
|
|
|
683
676
|
where_clause = ['all(r IN rels WHERE r.status = "active")']
|
|
684
677
|
clean_filters = extract_field_filters(field_name=self.schema.name, filters=self.filters)
|
|
685
678
|
|
|
686
|
-
if clean_filters and "id" in clean_filters or "ids" in clean_filters:
|
|
679
|
+
if (clean_filters and "id" in clean_filters) or "ids" in clean_filters:
|
|
687
680
|
where_clause.append("peer.uuid IN $peer_ids")
|
|
688
681
|
self.params["peer_ids"] = clean_filters.get("ids", [])
|
|
689
682
|
if clean_filters.get("id", None):
|
|
@@ -726,22 +719,19 @@ class RelationshipGetPeerQuery(Query):
|
|
|
726
719
|
with_str = ", ".join(
|
|
727
720
|
[f"{subquery_result_name} as {label}" if label == "peer" else label for label in self.return_labels]
|
|
728
721
|
)
|
|
729
|
-
self.add_subquery(subquery=subquery, with_clause=with_str)
|
|
730
|
-
|
|
722
|
+
self.add_subquery(subquery=subquery, node_alias="peer", with_clause=with_str)
|
|
731
723
|
# ----------------------------------------------------------------------------
|
|
732
724
|
# QUERY Properties
|
|
733
725
|
# ----------------------------------------------------------------------------
|
|
734
726
|
query = """
|
|
735
|
-
CALL {
|
|
736
|
-
WITH rl
|
|
727
|
+
CALL (rl) {
|
|
737
728
|
MATCH (rl)-[r:IS_VISIBLE]-(is_visible)
|
|
738
729
|
WHERE %(branch_filter)s
|
|
739
730
|
RETURN r AS rel_is_visible, is_visible
|
|
740
731
|
ORDER BY r.branch_level DESC, r.from DESC, r.status ASC
|
|
741
732
|
LIMIT 1
|
|
742
733
|
}
|
|
743
|
-
CALL {
|
|
744
|
-
WITH rl
|
|
734
|
+
CALL (rl) {
|
|
745
735
|
MATCH (rl)-[r:IS_PROTECTED]-(is_protected)
|
|
746
736
|
WHERE %(branch_filter)s
|
|
747
737
|
RETURN r AS rel_is_protected, is_protected
|
|
@@ -758,8 +748,7 @@ class RelationshipGetPeerQuery(Query):
|
|
|
758
748
|
# We must query them one by one otherwise the second one won't return
|
|
759
749
|
for node_prop in ["source", "owner"]:
|
|
760
750
|
query = """
|
|
761
|
-
CALL {
|
|
762
|
-
WITH rl
|
|
751
|
+
CALL (rl) {
|
|
763
752
|
OPTIONAL MATCH (rl)-[r:HAS_%(node_prop_type)s]-(%(node_prop)s)
|
|
764
753
|
WHERE %(branch_filter)s
|
|
765
754
|
RETURN r AS rel_%(node_prop)s, %(node_prop)s
|
|
@@ -800,7 +789,7 @@ class RelationshipGetPeerQuery(Query):
|
|
|
800
789
|
self.order_by.append(subquery_result_name)
|
|
801
790
|
self.params.update(subquery_params)
|
|
802
791
|
|
|
803
|
-
self.add_subquery(subquery=subquery)
|
|
792
|
+
self.add_subquery(subquery=subquery, node_alias="peer")
|
|
804
793
|
|
|
805
794
|
order_cnt += 1
|
|
806
795
|
|
|
@@ -939,8 +928,7 @@ class RelationshipGetByIdentifierQuery(Query):
|
|
|
939
928
|
query = """
|
|
940
929
|
MATCH (rl:Relationship)
|
|
941
930
|
WHERE rl.name IN $identifiers
|
|
942
|
-
CALL {
|
|
943
|
-
WITH rl
|
|
931
|
+
CALL (rl) {
|
|
944
932
|
MATCH (src:Node)-[r1:IS_RELATED]-(rl:Relationship)-[r2:IS_RELATED]-(dst:Node)
|
|
945
933
|
WHERE (size($full_identifiers) = 0 OR [src.kind, rl.name, dst.kind] in $full_identifiers)
|
|
946
934
|
AND NOT src.namespace IN $excluded_namespaces
|
|
@@ -1003,8 +991,7 @@ class RelationshipCountPerNodeQuery(Query):
|
|
|
1003
991
|
query = """
|
|
1004
992
|
MATCH (peer_node:Node)%(path)s(rl:Relationship { name: $rel_identifier })
|
|
1005
993
|
WHERE peer_node.uuid IN $peer_ids AND %(branch_filter)s
|
|
1006
|
-
CALL {
|
|
1007
|
-
WITH rl
|
|
994
|
+
CALL (rl) {
|
|
1008
995
|
MATCH path = (peer_node:Node)%(path)s(rl)
|
|
1009
996
|
WHERE peer_node.uuid IN $peer_ids AND %(branch_filter)s
|
|
1010
997
|
RETURN peer_node as peer, r as r1
|
|
@@ -1048,7 +1035,7 @@ class RelationshipDeleteAllQuery(Query):
|
|
|
1048
1035
|
self.node_id = node_id
|
|
1049
1036
|
super().__init__(**kwargs)
|
|
1050
1037
|
|
|
1051
|
-
async def query_init(self, db: InfrahubDatabase, **kwargs) -> None:
|
|
1038
|
+
async def query_init(self, db: InfrahubDatabase, **kwargs) -> None:
|
|
1052
1039
|
self.params["source_id"] = kwargs["node_id"]
|
|
1053
1040
|
self.params["branch"] = self.branch.name
|
|
1054
1041
|
|
|
@@ -1082,8 +1069,7 @@ class RelationshipDeleteAllQuery(Query):
|
|
|
1082
1069
|
for arrow_left, arrow_right in (("<-", "-"), ("-", "->")):
|
|
1083
1070
|
for edge_type in edge_types:
|
|
1084
1071
|
sub_query = """
|
|
1085
|
-
CALL {
|
|
1086
|
-
WITH rl
|
|
1072
|
+
CALL (rl) {
|
|
1087
1073
|
MATCH (rl)%(arrow_left)s[active_edge:%(edge_type)s]%(arrow_right)s(n)
|
|
1088
1074
|
WHERE %(active_rel_filter)s AND active_edge.status ="active"
|
|
1089
1075
|
CREATE (rl)%(arrow_left)s[deleted_edge:%(edge_type)s $rel_prop]%(arrow_right)s(n)
|
|
@@ -1103,8 +1089,7 @@ class RelationshipDeleteAllQuery(Query):
|
|
|
1103
1089
|
|
|
1104
1090
|
# We only want to return uuid/kind of `Node` connected through `IS_RELATED` edges.
|
|
1105
1091
|
query += """
|
|
1106
|
-
CALL {
|
|
1107
|
-
WITH rl
|
|
1092
|
+
CALL (rl) {
|
|
1108
1093
|
MATCH (rl)-[active_edge:IS_RELATED]->(n)
|
|
1109
1094
|
WHERE %(active_rel_filter)s
|
|
1110
1095
|
WITH rl, active_edge, n
|
|
@@ -1123,7 +1108,6 @@ class RelationshipDeleteAllQuery(Query):
|
|
|
1123
1108
|
"outbound" as rel_direction
|
|
1124
1109
|
|
|
1125
1110
|
UNION
|
|
1126
|
-
|
|
1127
1111
|
WITH rl
|
|
1128
1112
|
MATCH (rl)<-[active_edge:IS_RELATED]-(n)
|
|
1129
1113
|
WHERE %(active_rel_filter)s
|
|
@@ -1193,3 +1177,40 @@ class RelationshipDeleteAllQuery(Query):
|
|
|
1193
1177
|
changelog_mapper.delete_relationship(peer_id=peer_uuid, peer_kind=kind, rel_schema=deleted_rel_schema)
|
|
1194
1178
|
|
|
1195
1179
|
return [changelog_mapper.changelog for changelog_mapper in rel_identifier_to_changelog_mapper.values()]
|
|
1180
|
+
|
|
1181
|
+
|
|
1182
|
+
class GetAllPeersIds(Query):
|
|
1183
|
+
"""
|
|
1184
|
+
Return all peers ids connected to input node. Some peers can be excluded using `exclude_identifiers`.
|
|
1185
|
+
"""
|
|
1186
|
+
|
|
1187
|
+
name = "get_peers_ids"
|
|
1188
|
+
type: QueryType = QueryType.READ
|
|
1189
|
+
insert_return = False
|
|
1190
|
+
|
|
1191
|
+
def __init__(self, node_id: str, exclude_identifiers: list[str], **kwargs):
|
|
1192
|
+
self.node_id = node_id
|
|
1193
|
+
self.exclude_identifiers = exclude_identifiers
|
|
1194
|
+
super().__init__(**kwargs)
|
|
1195
|
+
|
|
1196
|
+
async def query_init(self, db: InfrahubDatabase, **kwargs) -> None: # noqa: ARG002
|
|
1197
|
+
self.params["source_id"] = kwargs["node_id"]
|
|
1198
|
+
self.params["branch"] = self.branch.name
|
|
1199
|
+
self.params["exclude_identifiers"] = self.exclude_identifiers
|
|
1200
|
+
|
|
1201
|
+
active_rel_filter, rel_params = self.branch.get_query_filter_path(
|
|
1202
|
+
at=self.at, variable_name="e1", branch_agnostic=self.branch_agnostic
|
|
1203
|
+
)
|
|
1204
|
+
self.params.update(rel_params)
|
|
1205
|
+
|
|
1206
|
+
query = """
|
|
1207
|
+
MATCH (node:Node { uuid: $source_id })-[e1:IS_RELATED]-(rl:Relationship)-[e2:IS_RELATED]-(peer:Node)
|
|
1208
|
+
WHERE %(active_rel_filter)s AND peer.uuid <> node.uuid AND NOT (rl.name IN $exclude_identifiers)
|
|
1209
|
+
WITH DISTINCT(peer.uuid) as uuid
|
|
1210
|
+
RETURN uuid
|
|
1211
|
+
""" % {"active_rel_filter": active_rel_filter}
|
|
1212
|
+
|
|
1213
|
+
self.add_to_query(query)
|
|
1214
|
+
|
|
1215
|
+
def get_peers_uuids(self) -> list[str]:
|
|
1216
|
+
return [row.data["uuid"] for row in self.results] # type: ignore
|
|
@@ -220,8 +220,7 @@ class NumberPoolGetUsed(Query):
|
|
|
220
220
|
|
|
221
221
|
query = """
|
|
222
222
|
MATCH (pool:%(number_pool)s { uuid: $pool_id })
|
|
223
|
-
CALL {
|
|
224
|
-
WITH pool
|
|
223
|
+
CALL (pool) {
|
|
225
224
|
MATCH (pool)-[res:IS_RESERVED]->(av:AttributeValue)<-[hv:HAS_VALUE]-(attr:Attribute)
|
|
226
225
|
WHERE
|
|
227
226
|
attr.name = $attribute_name
|
|
@@ -3,28 +3,42 @@ from __future__ import annotations
|
|
|
3
3
|
from typing import TYPE_CHECKING, Any
|
|
4
4
|
|
|
5
5
|
from infrahub.core.query import Query, QueryType
|
|
6
|
+
from infrahub.exceptions import InitializationError
|
|
6
7
|
|
|
7
8
|
if TYPE_CHECKING:
|
|
9
|
+
from uuid import UUID
|
|
10
|
+
|
|
8
11
|
from infrahub.core.node.standard import StandardNode
|
|
9
12
|
from infrahub.database import InfrahubDatabase
|
|
10
13
|
|
|
11
14
|
|
|
12
15
|
class StandardNodeQuery(Query):
|
|
13
16
|
def __init__(
|
|
14
|
-
self,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
+
self,
|
|
18
|
+
node: StandardNode | None = None,
|
|
19
|
+
node_id: UUID | None = None,
|
|
20
|
+
node_db_id: str | None = None,
|
|
21
|
+
**kwargs: Any,
|
|
22
|
+
) -> None:
|
|
23
|
+
self._node = node
|
|
17
24
|
self.node_id = node_id
|
|
18
25
|
self.node_db_id = node_db_id
|
|
19
26
|
|
|
20
|
-
if not self.node_id and self.
|
|
27
|
+
if not self.node_id and self._node:
|
|
21
28
|
self.node_id = self.node.uuid
|
|
22
29
|
|
|
23
|
-
if not self.node_db_id and self.
|
|
30
|
+
if not self.node_db_id and self._node:
|
|
24
31
|
self.node_db_id = self.node.id
|
|
25
32
|
|
|
26
33
|
super().__init__(**kwargs)
|
|
27
34
|
|
|
35
|
+
@property
|
|
36
|
+
def node(self) -> StandardNode:
|
|
37
|
+
if self._node:
|
|
38
|
+
return self._node
|
|
39
|
+
|
|
40
|
+
raise InitializationError("The query is not initialized with a node")
|
|
41
|
+
|
|
28
42
|
|
|
29
43
|
class RootNodeCreateQuery(StandardNodeQuery):
|
|
30
44
|
name = "standard_node_create"
|
infrahub/core/query/subquery.py
CHANGED
|
@@ -61,7 +61,7 @@ async def build_subquery_filter(
|
|
|
61
61
|
where_str = " AND ".join(field_where)
|
|
62
62
|
branch_level_str = "reduce(br_lvl = 0, r in relationships(path) | br_lvl + r.branch_level)"
|
|
63
63
|
froms_str = db.render_list_comprehension(items="relationships(path)", item_name="from")
|
|
64
|
-
to_return = f"{
|
|
64
|
+
to_return = f"{prefix}"
|
|
65
65
|
with_extra = ""
|
|
66
66
|
final_with_extra = ""
|
|
67
67
|
is_isnull = filter_name == "isnull"
|
|
@@ -82,7 +82,6 @@ async def build_subquery_filter(
|
|
|
82
82
|
elif field is not None and field.is_attribute:
|
|
83
83
|
is_active_filter = "(latest_node_details[2]).value = 'NULL'"
|
|
84
84
|
query = f"""
|
|
85
|
-
WITH {node_alias}
|
|
86
85
|
{match} path = {filter_str}
|
|
87
86
|
WHERE {where_str}
|
|
88
87
|
WITH
|
|
@@ -94,7 +93,7 @@ async def build_subquery_filter(
|
|
|
94
93
|
ORDER BY branch_level DESC, froms[-1] DESC, froms[-2] DESC
|
|
95
94
|
WITH head(collect([is_active, {node_alias}{with_extra}])) AS latest_node_details
|
|
96
95
|
WHERE {is_active_filter}
|
|
97
|
-
WITH latest_node_details[1] AS {
|
|
96
|
+
WITH latest_node_details[1] AS {prefix}{final_with_extra}
|
|
98
97
|
RETURN {to_return}
|
|
99
98
|
"""
|
|
100
99
|
return query, params, prefix
|
|
@@ -174,7 +173,6 @@ async def build_subquery_order(
|
|
|
174
173
|
to_return_str_parts.append(f"CASE WHEN is_active = TRUE THEN {expression} ELSE NULL END AS {alias}")
|
|
175
174
|
to_return_str = ", ".join(to_return_str_parts)
|
|
176
175
|
query = f"""
|
|
177
|
-
WITH {node_alias}
|
|
178
176
|
OPTIONAL MATCH path = {filter_str}
|
|
179
177
|
WHERE {where_str}
|
|
180
178
|
WITH {with_str_to_alias}
|
|
@@ -3,6 +3,7 @@ from dataclasses import dataclass
|
|
|
3
3
|
from infrahub.core import registry
|
|
4
4
|
from infrahub.core.branch import Branch
|
|
5
5
|
from infrahub.core.constants import RelationshipCardinality, RelationshipDirection
|
|
6
|
+
from infrahub.core.node import Node
|
|
6
7
|
from infrahub.core.query.relationship import RelationshipCountPerNodeQuery
|
|
7
8
|
from infrahub.core.schema import MainSchemaTypes
|
|
8
9
|
from infrahub.database import InfrahubDatabase
|
|
@@ -25,7 +26,7 @@ class RelationshipCountConstraint(RelationshipManagerConstraintInterface):
|
|
|
25
26
|
self.db = db
|
|
26
27
|
self.branch = branch
|
|
27
28
|
|
|
28
|
-
async def check(self, relm: RelationshipManager, node_schema: MainSchemaTypes) -> None: # noqa: ARG002
|
|
29
|
+
async def check(self, relm: RelationshipManager, node_schema: MainSchemaTypes, node: Node) -> None: # noqa: ARG002
|
|
29
30
|
branch = await registry.get_branch(db=self.db) if not self.branch else self.branch
|
|
30
31
|
|
|
31
32
|
# NOTE adding resolve here because we need to retrieve the real ID
|
|
@@ -63,7 +64,7 @@ class RelationshipCountConstraint(RelationshipManagerConstraintInterface):
|
|
|
63
64
|
|
|
64
65
|
query = await RelationshipCountPerNodeQuery.init(
|
|
65
66
|
db=self.db,
|
|
66
|
-
node_ids=[
|
|
67
|
+
node_ids=[n.uuid for n in nodes_to_validate],
|
|
67
68
|
identifier=relm.schema.identifier,
|
|
68
69
|
direction=relm.schema.direction.neighbor_direction,
|
|
69
70
|
branch=branch,
|
|
@@ -74,14 +75,14 @@ class RelationshipCountConstraint(RelationshipManagerConstraintInterface):
|
|
|
74
75
|
# Need to adjust the number based on what we will add / remove
|
|
75
76
|
# +1 for max_count
|
|
76
77
|
# -1 for min_count
|
|
77
|
-
for
|
|
78
|
-
if
|
|
78
|
+
for node_to_validate in nodes_to_validate:
|
|
79
|
+
if node_to_validate.max_count and count_per_peer[node_to_validate.uuid] + 1 > node_to_validate.max_count:
|
|
79
80
|
raise ValidationError(
|
|
80
|
-
f"Node {
|
|
81
|
-
f"for {relm.schema.identifier}, maximum of {
|
|
81
|
+
f"Node {node_to_validate.uuid} has {count_per_peer[node_to_validate.uuid] + 1} peers "
|
|
82
|
+
f"for {relm.schema.identifier}, maximum of {node_to_validate.max_count} allowed",
|
|
82
83
|
)
|
|
83
|
-
if
|
|
84
|
+
if node_to_validate.min_count and count_per_peer[node_to_validate.uuid] - 1 < node_to_validate.min_count:
|
|
84
85
|
raise ValidationError(
|
|
85
|
-
f"Node {
|
|
86
|
-
f"for {relm.schema.identifier}, no fewer than {
|
|
86
|
+
f"Node {node_to_validate.uuid} has {count_per_peer[node_to_validate.uuid] - 1} peers "
|
|
87
|
+
f"for {relm.schema.identifier}, no fewer than {node_to_validate.min_count} allowed",
|
|
87
88
|
)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from abc import ABC, abstractmethod
|
|
2
2
|
|
|
3
|
+
from infrahub.core.node import Node
|
|
3
4
|
from infrahub.core.schema import MainSchemaTypes
|
|
4
5
|
|
|
5
6
|
from ..model import RelationshipManager
|
|
@@ -7,4 +8,4 @@ from ..model import RelationshipManager
|
|
|
7
8
|
|
|
8
9
|
class RelationshipManagerConstraintInterface(ABC):
|
|
9
10
|
@abstractmethod
|
|
10
|
-
async def check(self, relm: RelationshipManager, node_schema: MainSchemaTypes) -> None: ...
|
|
11
|
+
async def check(self, relm: RelationshipManager, node_schema: MainSchemaTypes, node: Node) -> None: ...
|
|
@@ -3,6 +3,7 @@ from dataclasses import dataclass
|
|
|
3
3
|
from infrahub.core import registry
|
|
4
4
|
from infrahub.core.branch import Branch
|
|
5
5
|
from infrahub.core.constants import RelationshipCardinality
|
|
6
|
+
from infrahub.core.node import Node
|
|
6
7
|
from infrahub.core.query.node import NodeListGetInfoQuery
|
|
7
8
|
from infrahub.core.schema import MainSchemaTypes
|
|
8
9
|
from infrahub.core.schema.generic_schema import GenericSchema
|
|
@@ -26,7 +27,7 @@ class RelationshipPeerKindConstraint(RelationshipManagerConstraintInterface):
|
|
|
26
27
|
self.db = db
|
|
27
28
|
self.branch = branch
|
|
28
29
|
|
|
29
|
-
async def check(self, relm: RelationshipManager, node_schema: MainSchemaTypes) -> None: # noqa: ARG002
|
|
30
|
+
async def check(self, relm: RelationshipManager, node_schema: MainSchemaTypes, node: Node) -> None: # noqa: ARG002
|
|
30
31
|
branch = await registry.get_branch(db=self.db) if not self.branch else self.branch
|
|
31
32
|
peer_schema = registry.schema.get(name=relm.schema.peer, branch=branch, duplicate=False)
|
|
32
33
|
if isinstance(peer_schema, GenericSchema):
|