infrahub-server 1.2.10__py3-none-any.whl → 1.3.0a0__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.
Files changed (134) hide show
  1. infrahub/actions/constants.py +86 -0
  2. infrahub/actions/gather.py +114 -0
  3. infrahub/actions/models.py +241 -0
  4. infrahub/actions/parsers.py +104 -0
  5. infrahub/actions/schema.py +382 -0
  6. infrahub/actions/tasks.py +126 -0
  7. infrahub/actions/triggers.py +21 -0
  8. infrahub/cli/db.py +1 -2
  9. infrahub/config.py +9 -0
  10. infrahub/core/account.py +24 -47
  11. infrahub/core/attribute.py +10 -12
  12. infrahub/core/constants/infrahubkind.py +8 -0
  13. infrahub/core/constraint/node/runner.py +1 -1
  14. infrahub/core/convert_object_type/__init__.py +0 -0
  15. infrahub/core/convert_object_type/conversion.py +122 -0
  16. infrahub/core/convert_object_type/schema_mapping.py +56 -0
  17. infrahub/core/diff/query/all_conflicts.py +1 -5
  18. infrahub/core/diff/query/artifact.py +10 -20
  19. infrahub/core/diff/query/diff_get.py +3 -6
  20. infrahub/core/diff/query/field_summary.py +2 -4
  21. infrahub/core/diff/query/merge.py +70 -123
  22. infrahub/core/diff/query/save.py +20 -32
  23. infrahub/core/diff/query/summary_counts_enricher.py +34 -54
  24. infrahub/core/diff/query_parser.py +5 -1
  25. infrahub/core/diff/tasks.py +3 -3
  26. infrahub/core/manager.py +14 -11
  27. infrahub/core/migrations/graph/m003_relationship_parent_optional.py +1 -2
  28. infrahub/core/migrations/graph/m013_convert_git_password_credential.py +2 -4
  29. infrahub/core/migrations/graph/m019_restore_rels_to_time.py +11 -22
  30. infrahub/core/migrations/graph/m020_duplicate_edges.py +3 -6
  31. infrahub/core/migrations/graph/m021_missing_hierarchy_merge.py +1 -2
  32. infrahub/core/migrations/graph/m024_missing_hierarchy_backfill.py +1 -2
  33. infrahub/core/migrations/query/attribute_add.py +1 -2
  34. infrahub/core/migrations/query/attribute_rename.py +3 -6
  35. infrahub/core/migrations/query/delete_element_in_schema.py +3 -6
  36. infrahub/core/migrations/query/node_duplicate.py +3 -6
  37. infrahub/core/migrations/query/relationship_duplicate.py +3 -6
  38. infrahub/core/migrations/schema/node_attribute_remove.py +3 -6
  39. infrahub/core/migrations/schema/node_remove.py +3 -6
  40. infrahub/core/models.py +29 -2
  41. infrahub/core/node/__init__.py +18 -4
  42. infrahub/core/node/create.py +211 -0
  43. infrahub/core/protocols.py +51 -0
  44. infrahub/core/protocols_base.py +3 -0
  45. infrahub/core/query/__init__.py +2 -2
  46. infrahub/core/query/diff.py +26 -32
  47. infrahub/core/query/ipam.py +10 -20
  48. infrahub/core/query/node.py +28 -46
  49. infrahub/core/query/relationship.py +51 -28
  50. infrahub/core/query/resource_manager.py +1 -2
  51. infrahub/core/query/subquery.py +2 -4
  52. infrahub/core/relationship/model.py +3 -0
  53. infrahub/core/schema/__init__.py +2 -1
  54. infrahub/core/schema/attribute_parameters.py +36 -0
  55. infrahub/core/schema/attribute_schema.py +83 -8
  56. infrahub/core/schema/basenode_schema.py +25 -1
  57. infrahub/core/schema/definitions/core/__init__.py +21 -0
  58. infrahub/core/schema/definitions/internal.py +13 -3
  59. infrahub/core/schema/generated/attribute_schema.py +9 -3
  60. infrahub/core/schema/schema_branch.py +12 -7
  61. infrahub/core/validators/__init__.py +5 -1
  62. infrahub/core/validators/attribute/choices.py +1 -2
  63. infrahub/core/validators/attribute/enum.py +1 -2
  64. infrahub/core/validators/attribute/kind.py +1 -2
  65. infrahub/core/validators/attribute/length.py +13 -6
  66. infrahub/core/validators/attribute/optional.py +1 -2
  67. infrahub/core/validators/attribute/regex.py +5 -5
  68. infrahub/core/validators/attribute/unique.py +1 -3
  69. infrahub/core/validators/determiner.py +18 -2
  70. infrahub/core/validators/enum.py +7 -0
  71. infrahub/core/validators/node/hierarchy.py +3 -6
  72. infrahub/core/validators/query.py +1 -3
  73. infrahub/core/validators/relationship/count.py +6 -12
  74. infrahub/core/validators/relationship/optional.py +2 -4
  75. infrahub/core/validators/relationship/peer.py +3 -8
  76. infrahub/core/validators/tasks.py +1 -1
  77. infrahub/core/validators/uniqueness/query.py +5 -9
  78. infrahub/database/__init__.py +1 -3
  79. infrahub/events/group_action.py +1 -0
  80. infrahub/graphql/analyzer.py +139 -18
  81. infrahub/graphql/app.py +1 -1
  82. infrahub/graphql/loaders/node.py +1 -1
  83. infrahub/graphql/loaders/peers.py +1 -1
  84. infrahub/graphql/manager.py +4 -0
  85. infrahub/graphql/mutations/action.py +164 -0
  86. infrahub/graphql/mutations/convert_object_type.py +62 -0
  87. infrahub/graphql/mutations/main.py +24 -175
  88. infrahub/graphql/mutations/proposed_change.py +21 -18
  89. infrahub/graphql/queries/convert_object_type_mapping.py +36 -0
  90. infrahub/graphql/queries/relationship.py +1 -1
  91. infrahub/graphql/resolvers/many_relationship.py +4 -4
  92. infrahub/graphql/resolvers/resolver.py +4 -4
  93. infrahub/graphql/resolvers/single_relationship.py +2 -2
  94. infrahub/graphql/schema.py +6 -0
  95. infrahub/graphql/subscription/graphql_query.py +2 -2
  96. infrahub/graphql/types/branch.py +1 -1
  97. infrahub/menu/menu.py +31 -0
  98. infrahub/message_bus/messages/__init__.py +0 -10
  99. infrahub/message_bus/operations/__init__.py +0 -8
  100. infrahub/message_bus/operations/refresh/registry.py +1 -1
  101. infrahub/patch/queries/consolidate_duplicated_nodes.py +3 -6
  102. infrahub/patch/queries/delete_duplicated_edges.py +5 -10
  103. infrahub/prefect_server/models.py +1 -19
  104. infrahub/proposed_change/models.py +68 -3
  105. infrahub/proposed_change/tasks.py +907 -30
  106. infrahub/task_manager/models.py +10 -6
  107. infrahub/telemetry/database.py +1 -1
  108. infrahub/telemetry/tasks.py +1 -1
  109. infrahub/trigger/catalogue.py +2 -0
  110. infrahub/trigger/models.py +18 -2
  111. infrahub/trigger/tasks.py +3 -1
  112. infrahub/workflows/catalogue.py +76 -0
  113. {infrahub_server-1.2.10.dist-info → infrahub_server-1.3.0a0.dist-info}/METADATA +2 -2
  114. {infrahub_server-1.2.10.dist-info → infrahub_server-1.3.0a0.dist-info}/RECORD +121 -118
  115. infrahub_testcontainers/container.py +0 -1
  116. infrahub_testcontainers/docker-compose.test.yml +1 -1
  117. infrahub_testcontainers/helpers.py +8 -2
  118. infrahub/message_bus/messages/check_generator_run.py +0 -26
  119. infrahub/message_bus/messages/finalize_validator_execution.py +0 -15
  120. infrahub/message_bus/messages/proposed_change/base_with_diff.py +0 -16
  121. infrahub/message_bus/messages/proposed_change/request_proposedchange_refreshartifacts.py +0 -11
  122. infrahub/message_bus/messages/request_generatordefinition_check.py +0 -20
  123. infrahub/message_bus/messages/request_proposedchange_pipeline.py +0 -23
  124. infrahub/message_bus/operations/check/__init__.py +0 -3
  125. infrahub/message_bus/operations/check/generator.py +0 -156
  126. infrahub/message_bus/operations/finalize/__init__.py +0 -3
  127. infrahub/message_bus/operations/finalize/validator.py +0 -133
  128. infrahub/message_bus/operations/requests/__init__.py +0 -9
  129. infrahub/message_bus/operations/requests/generator_definition.py +0 -140
  130. infrahub/message_bus/operations/requests/proposed_change.py +0 -629
  131. /infrahub/{message_bus/messages/proposed_change → actions}/__init__.py +0 -0
  132. {infrahub_server-1.2.10.dist-info → infrahub_server-1.3.0a0.dist-info}/LICENSE.txt +0 -0
  133. {infrahub_server-1.2.10.dist-info → infrahub_server-1.3.0a0.dist-info}/WHEEL +0 -0
  134. {infrahub_server-1.2.10.dist-info → infrahub_server-1.3.0a0.dist-info}/entry_points.txt +0 -0
@@ -121,10 +121,9 @@ class DiffCalculationQuery(DiffQuery):
121
121
 
122
122
  previous_base_path_query = """
123
123
  WITH DISTINCT diff_path AS diff_path, has_more_data
124
- CALL {
125
- WITH diff_path
126
- WITH diff_path, nodes(diff_path) AS d_nodes, relationships(diff_path) AS d_rels
127
- WITH diff_path, d_rels[0] AS r_root, d_nodes[1] AS n, d_rels[1] AS r_node, d_nodes[2] AS attr_rel, d_rels[2] AS r_prop
124
+ CALL (diff_path) {
125
+ WITH nodes(diff_path) AS d_nodes, relationships(diff_path) AS d_rels
126
+ WITH d_rels[0] AS r_root, d_nodes[1] AS n, d_rels[1] AS r_node, d_nodes[2] AS attr_rel, d_rels[2] AS r_prop
128
127
  // -------------------------------------
129
128
  // add base branch paths before branched_from, if they exist
130
129
  // -------------------------------------
@@ -158,10 +157,9 @@ CALL {
158
157
  WITH diff_path, latest_base_path, has_more_data
159
158
  UNWIND [diff_path, latest_base_path] AS penultimate_path
160
159
  WITH DISTINCT penultimate_path, has_more_data
161
- CALL {
162
- WITH penultimate_path
163
- WITH penultimate_path, nodes(penultimate_path) AS d_nodes, relationships(penultimate_path) AS d_rels
164
- WITH penultimate_path, d_rels[0] AS r_root, d_nodes[1] AS n, d_rels[1] AS r_node, d_nodes[2] AS attr_rel, d_rels[2] AS r_prop
160
+ CALL (penultimate_path) {
161
+ WITH nodes(penultimate_path) AS d_nodes, relationships(penultimate_path) AS d_rels
162
+ WITH d_rels[0] AS r_root, d_nodes[1] AS n, d_rels[1] AS r_node, d_nodes[2] AS attr_rel, d_rels[2] AS r_prop
165
163
  // -------------------------------------
166
164
  // Add peer-side of any relationships to get the peer's ID
167
165
  // -------------------------------------
@@ -201,6 +199,13 @@ WITH reduce(
201
199
  diff_rel_paths = [], item IN [penultimate_path, peer_path] |
202
200
  CASE WHEN item IS NULL THEN diff_rel_paths ELSE diff_rel_paths + [item] END
203
201
  ) AS diff_rel_paths, has_more_data
202
+ // ------------------------
203
+ // make sure we still include has_more_data if diff_rel_paths is empty
204
+ // ------------------------
205
+ WITH CASE
206
+ WHEN diff_rel_paths = [] THEN [NULL]
207
+ ELSE diff_rel_paths
208
+ END AS diff_rel_paths, has_more_data
204
209
  """
205
210
 
206
211
  def get_previous_base_path_query(self, db: InfrahubDatabase) -> str:
@@ -292,8 +297,7 @@ WITH one_result[0] AS p, one_result[1] AS q, one_result[2] AS diff_rel, one_resu
292
297
  // -------------------------------------
293
298
  // Exclude nodes added then removed on branch within timeframe
294
299
  // -------------------------------------
295
- CALL {
296
- WITH p, q, row_from_time
300
+ CALL (p, q, row_from_time) {
297
301
  OPTIONAL MATCH (q)<-[is_part_of:IS_PART_OF {branch: $branch_name}]-(p)
298
302
  WHERE row_from_time <= is_part_of.from < $to_time
299
303
  WITH DISTINCT is_part_of.status AS rel_status
@@ -305,8 +309,7 @@ WHERE intra_branch_update = FALSE
305
309
  // -------------------------------------
306
310
  // Get every path on this branch under each node
307
311
  // -------------------------------------
308
- CALL {
309
- WITH p, q, diff_rel, row_from_time
312
+ CALL (p, q, diff_rel, row_from_time) {
310
313
  OPTIONAL MATCH path = (
311
314
  (q)<-[top_diff_rel:IS_PART_OF]-(p)-[r_node]-(node)-[r_prop]-(prop)
312
315
  )
@@ -333,12 +336,11 @@ CALL {
333
336
  p.uuid IS NULL OR prop.uuid IS NULL OR p.uuid <> prop.uuid
334
337
  OR type(r_node) <> "IS_RELATED" OR type(r_prop) <> "IS_RELATED"
335
338
  )
336
- WITH path, p, node, prop, r_prop, r_node, type(r_node) AS rel_type, row_from_time
339
+ WITH path, node, prop, r_prop, r_node, type(r_node) AS rel_type, row_from_time
337
340
  // -------------------------------------
338
341
  // Exclude attributes/relationships added then removed on branch within timeframe
339
342
  // -------------------------------------
340
- CALL {
341
- WITH p, rel_type, node, row_from_time
343
+ CALL (p, rel_type, node, row_from_time) {
342
344
  OPTIONAL MATCH (p)-[rel_to_check {branch: $branch_name}]-(node)
343
345
  WHERE row_from_time <= rel_to_check.from < $to_time
344
346
  AND type(rel_to_check) = rel_type
@@ -477,8 +479,7 @@ END AS row_from_time
477
479
  // Exclude attributes/relationship under nodes deleted on this branch in the timeframe
478
480
  // because those were all handled above at the node level
479
481
  // -------------------------------------
480
- CALL {
481
- WITH root, p, row_from_time
482
+ CALL (root, p, row_from_time) {
482
483
  OPTIONAL MATCH (root)<-[r_root_deleted:IS_PART_OF {branch: $branch_name}]-(p)
483
484
  WHERE row_from_time <= r_root_deleted.from < $to_time
484
485
  WITH r_root_deleted
@@ -492,8 +493,7 @@ WHERE node_deleted = FALSE
492
493
  // Exclude relationships added and deleted within the timeframe
493
494
  // -------------------------------------
494
495
  WITH root, r_root, p, diff_rel, q, has_more_data, row_from_time, type(diff_rel) AS rel_type
495
- CALL {
496
- WITH p, rel_type, q, row_from_time
496
+ CALL (p, rel_type, q, row_from_time) {
497
497
  OPTIONAL MATCH (p)-[rel_to_check {branch: $branch_name}]-(q)
498
498
  WHERE row_from_time <= rel_to_check.from < $to_time
499
499
  AND type(rel_to_check) = rel_type
@@ -506,8 +506,7 @@ WHERE intra_branch_update = FALSE
506
506
  // -------------------------------------
507
507
  // Get every path on this branch under each attribute/relationship
508
508
  // -------------------------------------
509
- CALL {
510
- WITH root, r_root, p, diff_rel, q
509
+ CALL (root, r_root, p, diff_rel, q) {
511
510
  OPTIONAL MATCH path = (
512
511
  (root:Root)<-[mid_r_root:IS_PART_OF]-(p)-[mid_diff_rel]-(q)-[r_prop]-(prop)
513
512
  )
@@ -542,8 +541,7 @@ CALL {
542
541
  // Exclude properties added and deleted within the timeframe
543
542
  // -------------------------------------
544
543
  WITH q, nodes(latest_prop_path)[3] AS prop, type(relationships(latest_prop_path)[2]) AS rel_type, latest_prop_path, has_more_data, row_from_time
545
- CALL {
546
- WITH q, rel_type, prop, row_from_time
544
+ CALL (q, rel_type, prop, row_from_time) {
547
545
  OPTIONAL MATCH (q)-[rel_to_check {branch: $branch_name}]-(prop)
548
546
  WHERE row_from_time <= rel_to_check.from < $to_time
549
547
  AND type(rel_to_check) = rel_type
@@ -710,14 +708,12 @@ ORDER BY
710
708
  r_node.from DESC,
711
709
  r_root.from DESC
712
710
  WITH n, p, row_from_time, diff_rel, diff_rel_path, has_more_data
713
- CALL {
711
+ CALL (n, p, row_from_time){
714
712
  // -------------------------------------
715
713
  // Exclude properties under nodes and attributes/relationships deleted
716
714
  // on this branch in the timeframe because those were all handled above
717
715
  // -------------------------------------
718
- WITH n, p, row_from_time
719
- CALL {
720
- WITH n, row_from_time
716
+ CALL (n, row_from_time) {
721
717
  OPTIONAL MATCH (root:Root)<-[r_root_deleted:IS_PART_OF {branch: $branch_name}]-(n)
722
718
  WHERE r_root_deleted.from < $to_time
723
719
  WITH r_root_deleted
@@ -725,9 +721,8 @@ CALL {
725
721
  LIMIT 1
726
722
  RETURN COALESCE(r_root_deleted.status = "deleted", FALSE) AS node_deleted
727
723
  }
728
- WITH n, p, row_from_time, node_deleted
729
- CALL {
730
- WITH n, p, row_from_time
724
+ WITH node_deleted
725
+ CALL (n, p, row_from_time) {
731
726
  OPTIONAL MATCH (n)-[r_node_deleted {branch: $branch_name}]-(p)
732
727
  WHERE row_from_time <= r_node_deleted.from < $to_time
733
728
  AND type(r_node_deleted) IN ["HAS_ATTRIBUTE", "IS_RELATED"]
@@ -796,8 +791,7 @@ AND (
796
791
  // -------------------------------------
797
792
  // Ignore node created and deleted on this branch
798
793
  // -------------------------------------
799
- CALL {
800
- WITH n
794
+ CALL (n) {
801
795
  OPTIONAL MATCH (:Root)<-[diff_rel:IS_PART_OF {branch: $branch_name}]-(n)
802
796
  WITH diff_rel
803
797
  ORDER BY diff_rel.from ASC
@@ -80,8 +80,7 @@ class IPPrefixSubnetFetch(Query):
80
80
  // First match on IPNAMESPACE
81
81
  MATCH (ns:%(ns_label)s)
82
82
  WHERE ns.uuid = $ns_id
83
- CALL {
84
- WITH ns
83
+ CALL (ns) {
85
84
  MATCH (ns)-[r:IS_PART_OF]-(root:Root)
86
85
  WHERE %(branch_filter)s
87
86
  RETURN ns as ns1, r as r1
@@ -104,8 +103,7 @@ class IPPrefixSubnetFetch(Query):
104
103
  // ---
105
104
  // FIND ALL CHILDREN OF THESE PREFIXES
106
105
  // ---
107
- CALL {
108
- WITH all_prefixes
106
+ CALL (all_prefixes) {
109
107
  UNWIND all_prefixes as prefix
110
108
  OPTIONAL MATCH (prefix)<-[:IS_RELATED]-(ch_rel:Relationship)<-[:IS_RELATED]-(children:BuiltinIPPrefix)
111
109
  WHERE ch_rel.name = "parent__child"
@@ -171,8 +169,7 @@ class IPPrefixIPAddressFetch(Query):
171
169
  // First match on IPNAMESPACE
172
170
  MATCH (ns:%(ns_label)s)
173
171
  WHERE ns.uuid = $ns_id
174
- CALL {
175
- WITH ns
172
+ CALL (ns) {
176
173
  MATCH (ns)-[r:IS_PART_OF]-(root:Root)
177
174
  WHERE %(branch_filter)s
178
175
  RETURN ns as ns1, r as r1
@@ -271,8 +268,7 @@ class IPPrefixUtilization(Query):
271
268
  query = f"""
272
269
  MATCH (pfx:Node)
273
270
  WHERE pfx.uuid IN $ids
274
- CALL {{
275
- WITH pfx
271
+ CALL (pfx) {{
276
272
  MATCH (pfx)-[r_rel1:IS_RELATED]-(rl:Relationship)<-[r_rel2:IS_RELATED]-(child:Node)
277
273
  WHERE rl.name IN [{", ".join(self.allocated_kinds_rel)}]
278
274
  AND any(l IN labels(child) WHERE l IN [{", ".join(self.allocated_kinds)}])
@@ -425,8 +421,7 @@ class IPPrefixReconcileQuery(Query):
425
421
  // ------------------
426
422
  // Get prefix node's current parent, if it exists
427
423
  // ------------------
428
- CALL {
429
- WITH ip_node
424
+ CALL (ip_node) {
430
425
  OPTIONAL MATCH parent_prefix_path = (ip_node)-[r1:IS_RELATED]->(:Relationship {name: "parent__child"})-[r2:IS_RELATED]->(current_parent:%(ip_prefix_kind)s)
431
426
  WHERE all(r IN relationships(parent_prefix_path) WHERE (%(branch_filter)s))
432
427
  RETURN current_parent, (r1.status = "active" AND r2.status = "active") AS parent_is_active
@@ -444,8 +439,7 @@ class IPPrefixReconcileQuery(Query):
444
439
  // ------------------
445
440
  // Get prefix node's current prefix children, if any exist
446
441
  // ------------------
447
- CALL {
448
- WITH ip_node
442
+ CALL (ip_node) {
449
443
  OPTIONAL MATCH child_prefix_path = (ip_node)<-[r1:IS_RELATED]-(:Relationship {name: "parent__child"})<-[r2:IS_RELATED]-(current_prefix_child:%(ip_prefix_kind)s)
450
444
  WHERE all(r IN relationships(child_prefix_path) WHERE (%(branch_filter)s))
451
445
  WITH current_prefix_child, (r1.status = "active" AND r2.status = "active") AS is_active
@@ -457,8 +451,7 @@ class IPPrefixReconcileQuery(Query):
457
451
  // ------------------
458
452
  // Get prefix node's current address children, if any exist
459
453
  // ------------------
460
- CALL {
461
- WITH ip_node
454
+ CALL (ip_node) {
462
455
  OPTIONAL MATCH child_address_path = (ip_node)-[r1:IS_RELATED]-(:Relationship {name: "ip_prefix__ip_address"})-[r2:IS_RELATED]-(current_address_child:%(ip_address_kind)s)
463
456
  WHERE all(r IN relationships(child_address_path) WHERE (%(branch_filter)s))
464
457
  WITH current_address_child, (r1.status = "active" AND r2.status = "active") AS is_active
@@ -480,8 +473,7 @@ class IPPrefixReconcileQuery(Query):
480
473
  // ------------------
481
474
  // Identify the correct parent, if any, for the prefix node
482
475
  // ------------------
483
- CALL {
484
- WITH ip_namespace
476
+ CALL (ip_namespace) {
485
477
  OPTIONAL MATCH parent_path = (ip_namespace)-[pr1:IS_RELATED {status: "active"}]-(ns_rel:Relationship {name: "ip_namespace__ip_prefix"})
486
478
  -[pr2:IS_RELATED {status: "active"}]-(maybe_new_parent:%(ip_prefix_kind)s)
487
479
  -[har:HAS_ATTRIBUTE]->(:Attribute {name: "prefix"})
@@ -517,9 +509,8 @@ class IPPrefixReconcileQuery(Query):
517
509
  // ------------------
518
510
  // Identify the correct children, if any, for the prefix node
519
511
  // ------------------
520
- CALL {
512
+ CALL (ip_namespace, ip_node) {
521
513
  // Get ALL possible children for the prefix node
522
- WITH ip_namespace, ip_node
523
514
  OPTIONAL MATCH child_path = (
524
515
  (ip_namespace)-[r1:IS_RELATED]
525
516
  -(ns_rel:Relationship)-[r2:IS_RELATED]
@@ -558,12 +549,11 @@ class IPPrefixReconcileQuery(Query):
558
549
  WITH ip_namespace, ip_node, current_parent, current_children, new_parent, collect([maybe_new_child, latest_mnc_attribute]) AS maybe_children_ips
559
550
  WITH ip_namespace, ip_node, current_parent, current_children, new_parent, maybe_children_ips, range(0, size(maybe_children_ips) - 1) AS child_indices
560
551
  UNWIND child_indices as ind
561
- CALL {
552
+ CALL (ind, maybe_children_ips) {
562
553
  // ------------------
563
554
  // Filter all possible children to remove those that have a more-specific parent
564
555
  // among the list of all possible children
565
556
  // ------------------
566
- WITH ind, maybe_children_ips
567
557
  WITH ind, maybe_children_ips AS ips
568
558
  RETURN REDUCE(
569
559
  has_more_specific_parent = FALSE, potential_parent IN ips |
@@ -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 n, attr, av, a
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 n, attr, av, a
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 n, attr, av, a
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
@@ -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:
@@ -524,8 +524,7 @@ class RelationshipDeleteQuery(RelationshipQuery):
524
524
  CREATE (s)%(r1)s(rl)
525
525
  CREATE (rl)%(r2)s(d)
526
526
  WITH rl
527
- CALL {
528
- WITH rl
527
+ CALL (rl) {
529
528
  MATCH (rl)-[edge:IS_VISIBLE]->(visible)
530
529
  WHERE %(rel_filter)s AND edge.status = "active"
531
530
  WITH rl, edge, visible
@@ -536,8 +535,7 @@ class RelationshipDeleteQuery(RelationshipQuery):
536
535
  WHERE edge.branch = $branch
537
536
  SET edge.to = $at
538
537
  }
539
- CALL {
540
- WITH rl
538
+ CALL (rl) {
541
539
  MATCH (rl)-[edge:IS_PROTECTED]->(protected)
542
540
  WHERE %(rel_filter)s AND edge.status = "active"
543
541
  WITH rl, edge, protected
@@ -548,8 +546,7 @@ class RelationshipDeleteQuery(RelationshipQuery):
548
546
  WHERE edge.branch = $branch
549
547
  SET edge.to = $at
550
548
  }
551
- CALL {
552
- WITH rl
549
+ CALL (rl) {
553
550
  MATCH (rl)-[edge:HAS_OWNER]->(owner_node)
554
551
  WHERE %(rel_filter)s AND edge.status = "active"
555
552
  WITH rl, edge, owner_node
@@ -560,8 +557,7 @@ class RelationshipDeleteQuery(RelationshipQuery):
560
557
  WHERE edge.branch = $branch
561
558
  SET edge.to = $at
562
559
  }
563
- CALL {
564
- WITH rl
560
+ CALL (rl) {
565
561
  MATCH (rl)-[edge:HAS_SOURCE]->(source_node)
566
562
  WHERE %(rel_filter)s AND edge.status = "active"
567
563
  WITH rl, edge, source_node
@@ -656,8 +652,7 @@ class RelationshipGetPeerQuery(Query):
656
652
  MATCH (source_node:Node)%(arrow_left_start)s[:IS_RELATED]%(arrow_left_end)s(rl:Relationship { name: $rel_identifier })
657
653
  WHERE source_node.uuid IN $source_ids
658
654
  WITH DISTINCT source_node, rl
659
- CALL {
660
- WITH rl, source_node
655
+ CALL (rl, source_node) {
661
656
  MATCH path = (source_node)%(path)s(peer:Node)
662
657
  WHERE
663
658
  $source_kind IN LABELS(source_node) AND
@@ -726,22 +721,19 @@ class RelationshipGetPeerQuery(Query):
726
721
  with_str = ", ".join(
727
722
  [f"{subquery_result_name} as {label}" if label == "peer" else label for label in self.return_labels]
728
723
  )
729
- self.add_subquery(subquery=subquery, with_clause=with_str)
730
-
724
+ self.add_subquery(subquery=subquery, node_alias="peer", with_clause=with_str)
731
725
  # ----------------------------------------------------------------------------
732
726
  # QUERY Properties
733
727
  # ----------------------------------------------------------------------------
734
728
  query = """
735
- CALL {
736
- WITH rl
729
+ CALL (rl) {
737
730
  MATCH (rl)-[r:IS_VISIBLE]-(is_visible)
738
731
  WHERE %(branch_filter)s
739
732
  RETURN r AS rel_is_visible, is_visible
740
733
  ORDER BY r.branch_level DESC, r.from DESC, r.status ASC
741
734
  LIMIT 1
742
735
  }
743
- CALL {
744
- WITH rl
736
+ CALL (rl) {
745
737
  MATCH (rl)-[r:IS_PROTECTED]-(is_protected)
746
738
  WHERE %(branch_filter)s
747
739
  RETURN r AS rel_is_protected, is_protected
@@ -758,8 +750,7 @@ class RelationshipGetPeerQuery(Query):
758
750
  # We must query them one by one otherwise the second one won't return
759
751
  for node_prop in ["source", "owner"]:
760
752
  query = """
761
- CALL {
762
- WITH rl
753
+ CALL (rl) {
763
754
  OPTIONAL MATCH (rl)-[r:HAS_%(node_prop_type)s]-(%(node_prop)s)
764
755
  WHERE %(branch_filter)s
765
756
  RETURN r AS rel_%(node_prop)s, %(node_prop)s
@@ -800,7 +791,7 @@ class RelationshipGetPeerQuery(Query):
800
791
  self.order_by.append(subquery_result_name)
801
792
  self.params.update(subquery_params)
802
793
 
803
- self.add_subquery(subquery=subquery)
794
+ self.add_subquery(subquery=subquery, node_alias="peer")
804
795
 
805
796
  order_cnt += 1
806
797
 
@@ -939,8 +930,7 @@ class RelationshipGetByIdentifierQuery(Query):
939
930
  query = """
940
931
  MATCH (rl:Relationship)
941
932
  WHERE rl.name IN $identifiers
942
- CALL {
943
- WITH rl
933
+ CALL (rl) {
944
934
  MATCH (src:Node)-[r1:IS_RELATED]-(rl:Relationship)-[r2:IS_RELATED]-(dst:Node)
945
935
  WHERE (size($full_identifiers) = 0 OR [src.kind, rl.name, dst.kind] in $full_identifiers)
946
936
  AND NOT src.namespace IN $excluded_namespaces
@@ -1003,8 +993,7 @@ class RelationshipCountPerNodeQuery(Query):
1003
993
  query = """
1004
994
  MATCH (peer_node:Node)%(path)s(rl:Relationship { name: $rel_identifier })
1005
995
  WHERE peer_node.uuid IN $peer_ids AND %(branch_filter)s
1006
- CALL {
1007
- WITH rl
996
+ CALL (rl) {
1008
997
  MATCH path = (peer_node:Node)%(path)s(rl)
1009
998
  WHERE peer_node.uuid IN $peer_ids AND %(branch_filter)s
1010
999
  RETURN peer_node as peer, r as r1
@@ -1082,8 +1071,7 @@ class RelationshipDeleteAllQuery(Query):
1082
1071
  for arrow_left, arrow_right in (("<-", "-"), ("-", "->")):
1083
1072
  for edge_type in edge_types:
1084
1073
  sub_query = """
1085
- CALL {
1086
- WITH rl
1074
+ CALL (rl) {
1087
1075
  MATCH (rl)%(arrow_left)s[active_edge:%(edge_type)s]%(arrow_right)s(n)
1088
1076
  WHERE %(active_rel_filter)s AND active_edge.status ="active"
1089
1077
  CREATE (rl)%(arrow_left)s[deleted_edge:%(edge_type)s $rel_prop]%(arrow_right)s(n)
@@ -1103,8 +1091,7 @@ class RelationshipDeleteAllQuery(Query):
1103
1091
 
1104
1092
  # We only want to return uuid/kind of `Node` connected through `IS_RELATED` edges.
1105
1093
  query += """
1106
- CALL {
1107
- WITH rl
1094
+ CALL (rl) {
1108
1095
  MATCH (rl)-[active_edge:IS_RELATED]->(n)
1109
1096
  WHERE %(active_rel_filter)s
1110
1097
  WITH rl, active_edge, n
@@ -1123,7 +1110,6 @@ class RelationshipDeleteAllQuery(Query):
1123
1110
  "outbound" as rel_direction
1124
1111
 
1125
1112
  UNION
1126
-
1127
1113
  WITH rl
1128
1114
  MATCH (rl)<-[active_edge:IS_RELATED]-(n)
1129
1115
  WHERE %(active_rel_filter)s
@@ -1193,3 +1179,40 @@ class RelationshipDeleteAllQuery(Query):
1193
1179
  changelog_mapper.delete_relationship(peer_id=peer_uuid, peer_kind=kind, rel_schema=deleted_rel_schema)
1194
1180
 
1195
1181
  return [changelog_mapper.changelog for changelog_mapper in rel_identifier_to_changelog_mapper.values()]
1182
+
1183
+
1184
+ class GetAllPeersIds(Query):
1185
+ """
1186
+ Return all peers ids connected to input node. Some peers can be excluded using `exclude_identifiers`.
1187
+ """
1188
+
1189
+ name = "get_peers_ids"
1190
+ type: QueryType = QueryType.READ
1191
+ insert_return = False
1192
+
1193
+ def __init__(self, node_id: str, exclude_identifiers: list[str], **kwargs):
1194
+ self.node_id = node_id
1195
+ self.exclude_identifiers = exclude_identifiers
1196
+ super().__init__(**kwargs)
1197
+
1198
+ async def query_init(self, db: InfrahubDatabase, **kwargs) -> None: # noqa: ARG002
1199
+ self.params["source_id"] = kwargs["node_id"]
1200
+ self.params["branch"] = self.branch.name
1201
+ self.params["exclude_identifiers"] = self.exclude_identifiers
1202
+
1203
+ active_rel_filter, rel_params = self.branch.get_query_filter_path(
1204
+ at=self.at, variable_name="e1", branch_agnostic=self.branch_agnostic
1205
+ )
1206
+ self.params.update(rel_params)
1207
+
1208
+ query = """
1209
+ MATCH (node:Node { uuid: $source_id })-[e1:IS_RELATED]-(rl:Relationship)-[e2:IS_RELATED]-(peer:Node)
1210
+ WHERE %(active_rel_filter)s AND peer.uuid <> node.uuid AND NOT (rl.name IN $exclude_identifiers)
1211
+ WITH DISTINCT(peer.uuid) as uuid
1212
+ RETURN uuid
1213
+ """ % {"active_rel_filter": active_rel_filter}
1214
+
1215
+ self.add_to_query(query)
1216
+
1217
+ def get_peers_uuids(self) -> list[str]:
1218
+ return [row.data["uuid"] for row in self.results] # type: ignore