infrahub-server 1.2.12__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.
Files changed (205) hide show
  1. infrahub/actions/constants.py +130 -0
  2. infrahub/actions/gather.py +114 -0
  3. infrahub/actions/models.py +243 -0
  4. infrahub/actions/parsers.py +104 -0
  5. infrahub/actions/schema.py +393 -0
  6. infrahub/actions/tasks.py +119 -0
  7. infrahub/actions/triggers.py +21 -0
  8. infrahub/branch/__init__.py +0 -0
  9. infrahub/branch/tasks.py +29 -0
  10. infrahub/branch/triggers.py +22 -0
  11. infrahub/cli/db.py +3 -4
  12. infrahub/computed_attribute/gather.py +3 -1
  13. infrahub/computed_attribute/tasks.py +23 -29
  14. infrahub/core/account.py +24 -47
  15. infrahub/core/attribute.py +13 -15
  16. infrahub/core/constants/__init__.py +10 -0
  17. infrahub/core/constants/infrahubkind.py +9 -0
  18. infrahub/core/constraint/node/runner.py +3 -1
  19. infrahub/core/convert_object_type/__init__.py +0 -0
  20. infrahub/core/convert_object_type/conversion.py +124 -0
  21. infrahub/core/convert_object_type/schema_mapping.py +56 -0
  22. infrahub/core/diff/coordinator.py +8 -1
  23. infrahub/core/diff/query/all_conflicts.py +1 -5
  24. infrahub/core/diff/query/artifact.py +10 -20
  25. infrahub/core/diff/query/delete_query.py +8 -4
  26. infrahub/core/diff/query/diff_get.py +3 -6
  27. infrahub/core/diff/query/field_specifiers.py +1 -1
  28. infrahub/core/diff/query/field_summary.py +2 -4
  29. infrahub/core/diff/query/merge.py +72 -125
  30. infrahub/core/diff/query/save.py +28 -43
  31. infrahub/core/diff/query/summary_counts_enricher.py +34 -54
  32. infrahub/core/diff/query/time_range_query.py +0 -1
  33. infrahub/core/diff/repository/repository.py +4 -0
  34. infrahub/core/manager.py +14 -11
  35. infrahub/core/migrations/graph/m003_relationship_parent_optional.py +1 -2
  36. infrahub/core/migrations/graph/m012_convert_account_generic.py +1 -1
  37. infrahub/core/migrations/graph/m013_convert_git_password_credential.py +2 -6
  38. infrahub/core/migrations/graph/m015_diff_format_update.py +1 -2
  39. infrahub/core/migrations/graph/m016_diff_delete_bug_fix.py +1 -2
  40. infrahub/core/migrations/graph/m019_restore_rels_to_time.py +11 -22
  41. infrahub/core/migrations/graph/m020_duplicate_edges.py +3 -6
  42. infrahub/core/migrations/graph/m021_missing_hierarchy_merge.py +1 -2
  43. infrahub/core/migrations/graph/m023_deduplicate_cardinality_one_relationships.py +2 -2
  44. infrahub/core/migrations/graph/m024_missing_hierarchy_backfill.py +1 -2
  45. infrahub/core/migrations/graph/m028_delete_diffs.py +1 -2
  46. infrahub/core/migrations/graph/m029_duplicates_cleanup.py +30 -48
  47. infrahub/core/migrations/graph/m030_illegal_edges.py +1 -2
  48. infrahub/core/migrations/query/attribute_add.py +1 -2
  49. infrahub/core/migrations/query/attribute_rename.py +6 -11
  50. infrahub/core/migrations/query/delete_element_in_schema.py +19 -17
  51. infrahub/core/migrations/query/node_duplicate.py +19 -21
  52. infrahub/core/migrations/query/relationship_duplicate.py +19 -18
  53. infrahub/core/migrations/schema/node_attribute_remove.py +4 -8
  54. infrahub/core/migrations/schema/node_remove.py +19 -20
  55. infrahub/core/models.py +29 -2
  56. infrahub/core/node/__init__.py +131 -28
  57. infrahub/core/node/base.py +1 -1
  58. infrahub/core/node/create.py +211 -0
  59. infrahub/core/node/resource_manager/number_pool.py +31 -5
  60. infrahub/core/node/standard.py +6 -1
  61. infrahub/core/path.py +15 -1
  62. infrahub/core/protocols.py +57 -0
  63. infrahub/core/protocols_base.py +3 -0
  64. infrahub/core/query/__init__.py +2 -2
  65. infrahub/core/query/delete.py +3 -3
  66. infrahub/core/query/diff.py +19 -32
  67. infrahub/core/query/ipam.py +10 -20
  68. infrahub/core/query/node.py +29 -47
  69. infrahub/core/query/relationship.py +55 -34
  70. infrahub/core/query/resource_manager.py +1 -2
  71. infrahub/core/query/standard_node.py +19 -5
  72. infrahub/core/query/subquery.py +2 -4
  73. infrahub/core/relationship/constraints/count.py +10 -9
  74. infrahub/core/relationship/constraints/interface.py +2 -1
  75. infrahub/core/relationship/constraints/peer_kind.py +2 -1
  76. infrahub/core/relationship/constraints/peer_parent.py +56 -0
  77. infrahub/core/relationship/constraints/peer_relatives.py +72 -0
  78. infrahub/core/relationship/constraints/profiles_kind.py +1 -1
  79. infrahub/core/relationship/model.py +4 -1
  80. infrahub/core/schema/__init__.py +2 -1
  81. infrahub/core/schema/attribute_parameters.py +160 -0
  82. infrahub/core/schema/attribute_schema.py +130 -7
  83. infrahub/core/schema/basenode_schema.py +27 -3
  84. infrahub/core/schema/definitions/core/__init__.py +29 -1
  85. infrahub/core/schema/definitions/core/group.py +45 -0
  86. infrahub/core/schema/definitions/core/resource_pool.py +9 -0
  87. infrahub/core/schema/definitions/internal.py +43 -5
  88. infrahub/core/schema/generated/attribute_schema.py +16 -3
  89. infrahub/core/schema/generated/relationship_schema.py +11 -1
  90. infrahub/core/schema/manager.py +7 -2
  91. infrahub/core/schema/schema_branch.py +104 -9
  92. infrahub/core/validators/__init__.py +15 -2
  93. infrahub/core/validators/attribute/choices.py +1 -3
  94. infrahub/core/validators/attribute/enum.py +1 -3
  95. infrahub/core/validators/attribute/kind.py +1 -3
  96. infrahub/core/validators/attribute/length.py +13 -7
  97. infrahub/core/validators/attribute/min_max.py +118 -0
  98. infrahub/core/validators/attribute/number_pool.py +106 -0
  99. infrahub/core/validators/attribute/optional.py +1 -4
  100. infrahub/core/validators/attribute/regex.py +5 -6
  101. infrahub/core/validators/attribute/unique.py +1 -3
  102. infrahub/core/validators/determiner.py +18 -2
  103. infrahub/core/validators/enum.py +12 -0
  104. infrahub/core/validators/node/hierarchy.py +3 -6
  105. infrahub/core/validators/query.py +1 -3
  106. infrahub/core/validators/relationship/count.py +6 -12
  107. infrahub/core/validators/relationship/optional.py +2 -4
  108. infrahub/core/validators/relationship/peer.py +177 -12
  109. infrahub/core/validators/tasks.py +1 -1
  110. infrahub/core/validators/uniqueness/query.py +5 -9
  111. infrahub/database/__init__.py +12 -4
  112. infrahub/database/validation.py +1 -2
  113. infrahub/dependencies/builder/constraint/grouped/node_runner.py +4 -0
  114. infrahub/dependencies/builder/constraint/relationship_manager/peer_parent.py +8 -0
  115. infrahub/dependencies/builder/constraint/relationship_manager/peer_relatives.py +8 -0
  116. infrahub/dependencies/builder/constraint/schema/aggregated.py +2 -0
  117. infrahub/dependencies/builder/constraint/schema/relationship_peer.py +8 -0
  118. infrahub/dependencies/builder/diff/deserializer.py +1 -1
  119. infrahub/dependencies/registry.py +4 -0
  120. infrahub/events/group_action.py +1 -0
  121. infrahub/events/models.py +1 -1
  122. infrahub/git/base.py +5 -3
  123. infrahub/git/integrator.py +96 -5
  124. infrahub/git/tasks.py +1 -0
  125. infrahub/graphql/analyzer.py +139 -18
  126. infrahub/graphql/manager.py +4 -0
  127. infrahub/graphql/mutations/action.py +164 -0
  128. infrahub/graphql/mutations/convert_object_type.py +71 -0
  129. infrahub/graphql/mutations/main.py +24 -175
  130. infrahub/graphql/mutations/proposed_change.py +20 -17
  131. infrahub/graphql/mutations/relationship.py +32 -0
  132. infrahub/graphql/mutations/resource_manager.py +63 -7
  133. infrahub/graphql/queries/convert_object_type_mapping.py +34 -0
  134. infrahub/graphql/queries/resource_manager.py +7 -1
  135. infrahub/graphql/resolvers/many_relationship.py +1 -1
  136. infrahub/graphql/resolvers/resolver.py +2 -2
  137. infrahub/graphql/resolvers/single_relationship.py +1 -1
  138. infrahub/graphql/schema.py +6 -0
  139. infrahub/menu/menu.py +34 -2
  140. infrahub/message_bus/messages/__init__.py +0 -10
  141. infrahub/message_bus/operations/__init__.py +0 -8
  142. infrahub/message_bus/operations/refresh/registry.py +3 -6
  143. infrahub/patch/queries/delete_duplicated_edges.py +10 -15
  144. infrahub/pools/models.py +14 -0
  145. infrahub/pools/number.py +5 -3
  146. infrahub/pools/registration.py +22 -0
  147. infrahub/pools/tasks.py +126 -0
  148. infrahub/prefect_server/models.py +1 -19
  149. infrahub/proposed_change/models.py +68 -3
  150. infrahub/proposed_change/tasks.py +911 -34
  151. infrahub/schema/__init__.py +0 -0
  152. infrahub/schema/tasks.py +27 -0
  153. infrahub/schema/triggers.py +23 -0
  154. infrahub/task_manager/models.py +10 -6
  155. infrahub/trigger/catalogue.py +6 -0
  156. infrahub/trigger/models.py +23 -6
  157. infrahub/trigger/setup.py +26 -2
  158. infrahub/trigger/tasks.py +4 -2
  159. infrahub/types.py +6 -0
  160. infrahub/webhook/tasks.py +4 -8
  161. infrahub/workflows/catalogue.py +103 -1
  162. infrahub_sdk/client.py +43 -10
  163. infrahub_sdk/ctl/generator.py +4 -4
  164. infrahub_sdk/ctl/repository.py +1 -1
  165. infrahub_sdk/node/__init__.py +39 -0
  166. infrahub_sdk/node/attribute.py +122 -0
  167. infrahub_sdk/node/constants.py +21 -0
  168. infrahub_sdk/{node.py → node/node.py} +158 -803
  169. infrahub_sdk/node/parsers.py +15 -0
  170. infrahub_sdk/node/property.py +24 -0
  171. infrahub_sdk/node/related_node.py +266 -0
  172. infrahub_sdk/node/relationship.py +302 -0
  173. infrahub_sdk/protocols.py +112 -0
  174. infrahub_sdk/protocols_base.py +34 -2
  175. infrahub_sdk/pytest_plugin/items/python_transform.py +2 -1
  176. infrahub_sdk/query_groups.py +17 -5
  177. infrahub_sdk/schema/main.py +1 -0
  178. infrahub_sdk/schema/repository.py +16 -0
  179. infrahub_sdk/spec/object.py +1 -1
  180. infrahub_sdk/store.py +1 -1
  181. infrahub_sdk/testing/schemas/car_person.py +1 -0
  182. infrahub_sdk/utils.py +7 -20
  183. infrahub_sdk/yaml.py +6 -5
  184. {infrahub_server-1.2.12.dist-info → infrahub_server-1.3.0.dist-info}/METADATA +3 -3
  185. {infrahub_server-1.2.12.dist-info → infrahub_server-1.3.0.dist-info}/RECORD +192 -166
  186. infrahub_testcontainers/container.py +0 -1
  187. infrahub_testcontainers/docker-compose.test.yml +1 -1
  188. infrahub_testcontainers/helpers.py +8 -2
  189. infrahub/message_bus/messages/check_generator_run.py +0 -26
  190. infrahub/message_bus/messages/finalize_validator_execution.py +0 -15
  191. infrahub/message_bus/messages/proposed_change/base_with_diff.py +0 -16
  192. infrahub/message_bus/messages/proposed_change/request_proposedchange_refreshartifacts.py +0 -11
  193. infrahub/message_bus/messages/request_generatordefinition_check.py +0 -20
  194. infrahub/message_bus/messages/request_proposedchange_pipeline.py +0 -23
  195. infrahub/message_bus/operations/check/__init__.py +0 -3
  196. infrahub/message_bus/operations/check/generator.py +0 -156
  197. infrahub/message_bus/operations/finalize/__init__.py +0 -3
  198. infrahub/message_bus/operations/finalize/validator.py +0 -133
  199. infrahub/message_bus/operations/requests/__init__.py +0 -9
  200. infrahub/message_bus/operations/requests/generator_definition.py +0 -140
  201. infrahub/message_bus/operations/requests/proposed_change.py +0 -629
  202. /infrahub/{message_bus/messages/proposed_change → actions}/__init__.py +0 -0
  203. {infrahub_server-1.2.12.dist-info → infrahub_server-1.3.0.dist-info}/LICENSE.txt +0 -0
  204. {infrahub_server-1.2.12.dist-info → infrahub_server-1.3.0.dist-info}/WHEEL +0 -0
  205. {infrahub_server-1.2.12.dist-info → infrahub_server-1.3.0.dist-info}/entry_points.txt +0 -0
@@ -39,8 +39,7 @@ class BackfillMissingHierarchyQuery(Query):
39
39
  MATCH (rel:Relationship {name: "parent__child"})-[e:IS_RELATED]-(n:Node)
40
40
  WHERE e.hierarchy IS NULL
41
41
  WITH DISTINCT rel, n, default_branch
42
- CALL {
43
- WITH rel, n, default_branch
42
+ CALL (rel, n, default_branch) {
44
43
  MATCH (rel)-[e:IS_RELATED {branch: default_branch}]-(n)
45
44
  RETURN e
46
45
  ORDER BY e.from DESC
@@ -33,6 +33,5 @@ class Migration028(ArbitraryMigration):
33
33
  component_registry = get_component_registry()
34
34
  diff_repo = await component_registry.get_component(DiffRepository, db=db, branch=default_branch)
35
35
 
36
- diff_roots = await diff_repo.get_roots_metadata()
37
- await diff_repo.delete_diff_roots(diff_root_uuids=[d.uuid for d in diff_roots])
36
+ await diff_repo.delete_all_diff_roots()
38
37
  return MigrationResult()
@@ -58,15 +58,14 @@ class CleanUpDuplicatedUuidVertices(Query):
58
58
  r_arrow = ">"
59
59
 
60
60
  query = """
61
- CALL {
61
+ CALL (vertex_to_keep, edge_type, branch, peer, earliest_active_time, latest_deleted_time, all_edges_deleted, edge_to_copy) {
62
62
  // ------------
63
63
  // get or create the active %(edge_type)s edge
64
64
  // ------------
65
- WITH vertex_to_keep, edge_type, branch, peer, earliest_active_time, latest_deleted_time, all_edges_deleted, edge_to_copy
66
- WITH vertex_to_keep, edge_type, branch, peer, earliest_active_time, latest_deleted_time, all_edges_deleted, edge_to_copy
65
+ WITH edge_type
67
66
  WHERE edge_type = "%(edge_type)s"
68
67
  MERGE (vertex_to_keep)%(l_arrow)s-[active_edge:%(edge_type)s {branch: branch, status: "active"}]-%(r_arrow)s(peer)
69
- WITH active_edge, edge_to_copy, earliest_active_time, latest_deleted_time, all_edges_deleted
68
+ WITH active_edge
70
69
  LIMIT 1
71
70
  SET active_edge.to_delete = NULL
72
71
  SET active_edge.from = earliest_active_time
@@ -96,15 +95,14 @@ class CleanUpDuplicatedUuidVertices(Query):
96
95
  l_arrow = ""
97
96
  r_arrow = ">"
98
97
  subquery = """
99
- CALL {
98
+ CALL (vertex_to_keep, edge_type, branch, peer, latest_deleted_time, edge_to_copy) {
100
99
  // ------------
101
100
  // create the deleted %(edge_type)s edge
102
101
  // ------------
103
- WITH vertex_to_keep, edge_type, branch, peer, latest_deleted_time, edge_to_copy
104
- WITH vertex_to_keep, edge_type, branch, peer, latest_deleted_time, edge_to_copy
102
+ WITH edge_type
105
103
  WHERE edge_type = "%(edge_type)s"
106
104
  MERGE (vertex_to_keep)%(l_arrow)s-[deleted_edge:%(edge_type)s {branch: branch, status: "deleted"}]-%(r_arrow)s(peer)
107
- WITH deleted_edge, latest_deleted_time, edge_to_copy
105
+ WITH deleted_edge
108
106
  LIMIT 1
109
107
  SET deleted_edge.to_delete = NULL
110
108
  SET deleted_edge.from = latest_deleted_time
@@ -144,10 +142,8 @@ class CleanUpDuplicatedUuidVertices(Query):
144
142
  //------------
145
143
  // Get every %(direction)s branch, edge_type, peer element_id combinations touching vertices with this uuid/labels combination
146
144
  //------------
147
- CALL {
148
- WITH n_uuid, vertex_element_ids, element_id_to_keep
149
- CALL {
150
- WITH n_uuid, vertex_element_ids
145
+ CALL (n_uuid, vertex_element_ids, element_id_to_keep) {
146
+ CALL (n_uuid, vertex_element_ids) {
151
147
  MATCH (n:%(vertex_label)s {uuid: n_uuid})
152
148
  WHERE %(id_func_name)s(n) IN vertex_element_ids
153
149
  MATCH (n)%(l_arrow)s-[e]-%(r_arrow)s(peer)
@@ -157,8 +153,7 @@ CALL {
157
153
  //------------
158
154
  // Are all of the edges with these with this branch/edge_type/peer_element_id combination deleted?
159
155
  //------------
160
- CALL {
161
- WITH n_uuid, vertex_element_ids, branch, edge_type, peer_element_id
156
+ CALL (n_uuid, vertex_element_ids, branch, edge_type, peer_element_id) {
162
157
  // nodes with this edge_type/branch/peer combo
163
158
  MATCH (node_with_edge:%(vertex_label)s {uuid: n_uuid})%(l_arrow)s-[e {branch: branch}]-%(r_arrow)s(peer)
164
159
  WHERE %(id_func_name)s(node_with_edge) IN vertex_element_ids
@@ -181,8 +176,7 @@ CALL {
181
176
  //------------
182
177
  // What is the earliest active time for this branch/edge_type/peer_element_id/UUID/labels combination?
183
178
  //------------
184
- CALL {
185
- WITH n_uuid, vertex_element_ids, branch, edge_type, peer_element_id
179
+ CALL (n_uuid, vertex_element_ids, branch, edge_type, peer_element_id) {
186
180
  MATCH (n {uuid: n_uuid})%(l_arrow)s-[e {branch: branch, status: "active"}]-%(r_arrow)s(peer)
187
181
  WHERE %(id_func_name)s(n) IN vertex_element_ids
188
182
  AND type(e) = edge_type
@@ -194,8 +188,7 @@ CALL {
194
188
  //------------
195
189
  // What is the latest deleted time for this branch/edge_type/peer_element_id/UUID/labels combination?
196
190
  //------------
197
- CALL {
198
- WITH n_uuid, vertex_element_ids, branch, edge_type, peer_element_id, all_edges_deleted
191
+ CALL (n_uuid, vertex_element_ids, branch, edge_type, peer_element_id, all_edges_deleted) {
199
192
  OPTIONAL MATCH (n {uuid: n_uuid})%(l_arrow)s-[e {branch: branch}]-%(r_arrow)s(peer)
200
193
  WHERE all_edges_deleted = TRUE
201
194
  AND %(id_func_name)s(n) IN vertex_element_ids
@@ -211,9 +204,10 @@ CALL {
211
204
  // ------------
212
205
  // Add the %(direction)s edges to the node we are keeping, if necessary
213
206
  // ------------
214
- CALL {
215
- WITH n_uuid, vertex_element_ids, element_id_to_keep, branch, edge_type, peer_element_id, all_edges_deleted,
216
- earliest_active_time, latest_deleted_time
207
+ CALL (
208
+ n_uuid, vertex_element_ids, element_id_to_keep, branch, edge_type, peer_element_id, all_edges_deleted,
209
+ earliest_active_time, latest_deleted_time
210
+ ) {
217
211
  // get the node we are keeping
218
212
  MATCH (vertex_to_keep {uuid: n_uuid})
219
213
  WHERE %(id_func_name)s(vertex_to_keep) = element_id_to_keep
@@ -221,25 +215,22 @@ CALL {
221
215
  MATCH (n {uuid: n_uuid})%(l_arrow)s-[]-%(r_arrow)s(peer)
222
216
  WHERE %(id_func_name)s(n) IN vertex_element_ids
223
217
  AND %(id_func_name)s(peer) = peer_element_id
224
- WITH n_uuid, vertex_element_ids, element_id_to_keep, vertex_to_keep, branch, edge_type, peer, all_edges_deleted,
225
- earliest_active_time, latest_deleted_time
218
+ WITH peer, vertex_to_keep
226
219
  LIMIT 1
227
220
  // ------------
228
221
  // mark all other edges for this branch/edge_type/peer combination as to be deleted
229
222
  // we will unmark any to keep later
230
223
  // ------------
231
- CALL {
232
- WITH n_uuid, branch, peer, vertex_element_ids, edge_type
224
+ CALL (n_uuid, branch, peer, vertex_element_ids, edge_type) {
233
225
  OPTIONAL MATCH (n {uuid: n_uuid})%(l_arrow)s-[edge_to_delete {branch: branch}]-%(r_arrow)s(peer)
234
226
  WHERE %(id_func_name)s(n) IN vertex_element_ids
235
227
  AND type(edge_to_delete) = edge_type
236
228
  SET edge_to_delete.to_delete = TRUE
237
229
  }
238
- CALL {
230
+ CALL (n_uuid, branch, vertex_element_ids, edge_type, peer) {
239
231
  // ------------
240
232
  // get the edge to copy
241
233
  // ------------
242
- WITH n_uuid, branch, vertex_element_ids, edge_type, peer
243
234
  MATCH (n {uuid: n_uuid})%(l_arrow)s-[e {branch: branch, status: "active"}]-%(r_arrow)s(peer)
244
235
  WHERE %(id_func_name)s(n) IN vertex_element_ids
245
236
  AND type(e) = edge_type
@@ -251,8 +242,7 @@ CALL {
251
242
  // ------------
252
243
  // conditionally create the deleted edges
253
244
  // ------------
254
- WITH n_uuid, vertex_element_ids, vertex_to_keep, branch, edge_type, peer, all_edges_deleted,
255
- latest_deleted_time, edge_to_copy
245
+ WITH vertex_to_keep, peer, edge_to_copy
256
246
  WHERE all_edges_deleted = TRUE
257
247
  %(deleted_edge_subqueries)s
258
248
  }
@@ -283,8 +273,7 @@ ORDER BY node_uuid ASC
283
273
  MATCH (n:%(vertex_label)s {uuid: node_uuid})
284
274
  WITH node_uuid, n, %(id_func_name)s(n) AS element_id
285
275
  ORDER BY node_uuid ASC, element_id ASC
286
- CALL {
287
- WITH n
276
+ CALL (n) {
288
277
  WITH labels(n) AS n_labels
289
278
  UNWIND n_labels AS n_label
290
279
  WITH n_label
@@ -309,8 +298,7 @@ LIMIT $limit
309
298
  //------------
310
299
  // Which node are we going to keep for this UUID/labels combination?
311
300
  //------------
312
- CALL {
313
- WITH vertex_element_ids
301
+ CALL (vertex_element_ids) {
314
302
  UNWIND vertex_element_ids AS element_id
315
303
  WITH element_id
316
304
  ORDER BY element_id ASC
@@ -377,11 +365,10 @@ WITH
377
365
  WITH node_with_dup_edges, edge_type, edge_status, edge_branch, peer, is_outbound, count(*) AS num_dup_edges
378
366
  WHERE num_dup_edges > 1
379
367
  WITH DISTINCT node_with_dup_edges, edge_type, edge_branch, peer, is_outbound
380
- CALL {
368
+ CALL (node_with_dup_edges, edge_type, edge_branch, peer, is_outbound) {
381
369
  // ------------
382
370
  // Get the earliest active and deleted edges for this branch
383
371
  // ------------
384
- WITH node_with_dup_edges, edge_type, edge_branch, peer, is_outbound
385
372
  OPTIONAL MATCH (node_with_dup_edges)-[active_edge {branch: edge_branch, status: "active"}]-(peer)
386
373
  WHERE type(active_edge) = edge_type
387
374
  AND (%(id_func_name)s(startNode(active_edge)) = %(id_func_name)s(node_with_dup_edges) OR is_outbound = FALSE)
@@ -397,8 +384,7 @@ CALL {
397
384
  // ensure one active edge with correct from and to times
398
385
  // set the others to be deleted
399
386
  // ------------
400
- CALL {
401
- WITH node_with_dup_edges, edge_type, edge_branch, peer, is_outbound, active_from, deleted_from
387
+ CALL (node_with_dup_edges, edge_type, edge_branch, peer, is_outbound, active_from, deleted_from) {
402
388
  OPTIONAL MATCH (node_with_dup_edges)-[active_e {branch: edge_branch, status: "active"}]-(peer)
403
389
  WHERE type(active_e) = edge_type
404
390
  AND (%(id_func_name)s(startNode(active_e)) = %(id_func_name)s(node_with_dup_edges) OR is_outbound = FALSE)
@@ -414,8 +400,7 @@ CALL {
414
400
  // ensure one deleted edge with correct from time, if necessary
415
401
  // set the others to be deleted
416
402
  // ------------
417
- CALL {
418
- WITH node_with_dup_edges, edge_type, edge_branch, peer, is_outbound, deleted_from
403
+ CALL (node_with_dup_edges, edge_type, edge_branch, peer, is_outbound, deleted_from) {
419
404
  MATCH (node_with_dup_edges)-[deleted_e {branch: edge_branch, status: "deleted"}]-(peer)
420
405
  WHERE type(deleted_e) = edge_type
421
406
  AND (%(id_func_name)s(startNode(deleted_e)) = %(id_func_name)s(node_with_dup_edges) OR is_outbound = FALSE)
@@ -467,11 +452,9 @@ WITH DISTINCT default_branch, global_branch, r_uuid
467
452
  // Find any IS_RELATED edges on the duplicate Relationships that link to deleted Nodes,
468
453
  // accounting for if the edge was added on a branch after the Node was deleted on main
469
454
  // ------------
470
- CALL {
471
- WITH default_branch, global_branch, r_uuid
455
+ CALL (default_branch, global_branch, r_uuid) {
472
456
  MATCH (:Relationship {uuid: r_uuid})-[is_related:IS_RELATED]-(n:Node)
473
- CALL {
474
- WITH is_related
457
+ CALL (is_related) {
475
458
  MATCH (b:Branch {name: is_related.branch})
476
459
  RETURN b.branched_from AS edge_branched_from_time
477
460
  }
@@ -483,7 +466,7 @@ CALL {
483
466
  // ------------
484
467
  // before the active IS_RELATED edge's from time, then delete the edge
485
468
  // ------------
486
- WITH default_branch, global_branch, is_related, edge_branched_from_time, is_part_of, CASE
469
+ WITH is_related, edge_branched_from_time, is_part_of, CASE
487
470
  WHEN is_part_of.status = "deleted" THEN is_part_of.from
488
471
  ELSE is_part_of.to
489
472
  END AS node_deleted_time
@@ -492,8 +475,7 @@ CALL {
492
475
  DELETE is_related
493
476
  }
494
477
  MATCH (rel:Relationship {uuid: r_uuid})
495
- CALL {
496
- WITH rel
478
+ CALL (rel) {
497
479
  OPTIONAL MATCH (rel)-[:IS_RELATED]-(n:Node)
498
480
  WITH DISTINCT n
499
481
  RETURN count(*) AS num_peers
@@ -553,12 +535,12 @@ class PerformHardDeletes(Query):
553
535
 
554
536
  async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None: # noqa: ARG002
555
537
  query = """
556
- CALL {
538
+ CALL () {
557
539
  MATCH (n)
558
540
  WHERE n.to_delete = TRUE
559
541
  DETACH DELETE n
560
542
  }
561
- CALL {
543
+ CALL () {
562
544
  MATCH ()-[e]-()
563
545
  WHERE e.to_delete = TRUE
564
546
  DELETE e
@@ -42,8 +42,7 @@ WITH DISTINCT n, delete_branch, delete_time, added_e, peer
42
42
  // ------------
43
43
  // get the branched_from for the branch on which the node was deleted
44
44
  // ------------
45
- CALL {
46
- WITH added_e
45
+ CALL (added_e) {
47
46
  MATCH (b:Branch {name: added_e.branch})
48
47
  RETURN b.branched_from AS added_e_branched_from
49
48
  }
@@ -61,8 +61,7 @@ class AttributeAddQuery(Query):
61
61
  MERGE (is_visible_value:Boolean { value: $is_visible_default })
62
62
  WITH av, is_protected_value, is_visible_value
63
63
  MATCH p = (n:%(node_kind)s)
64
- CALL {
65
- WITH n
64
+ CALL (n) {
66
65
  MATCH (:Root)<-[r:IS_PART_OF]-(n)
67
66
  WHERE %(branch_filter)s
68
67
  WITH n, r AS is_part_of_e
@@ -38,7 +38,7 @@ class AttributeRenameQuery(Query):
38
38
  def render_match(self) -> str:
39
39
  query = """
40
40
  // Find all the active nodes
41
- CALL {
41
+ CALL () {
42
42
  MATCH (node:%(node_kind)s)
43
43
  WHERE exists((node)-[:HAS_ATTRIBUTE]-(:Attribute { name: $prev_attr.name }))
44
44
  RETURN node
@@ -55,7 +55,6 @@ class AttributeRenameQuery(Query):
55
55
  @staticmethod
56
56
  def _render_sub_query_per_rel_type_update_active(rel_type: str, rel_def: FieldInfo) -> str:
57
57
  subquery = [
58
- "WITH peer_node, rb, active_attr",
59
58
  "WITH peer_node, rb, active_attr",
60
59
  f'WHERE type(rb) = "{rel_type}"',
61
60
  ]
@@ -72,7 +71,6 @@ class AttributeRenameQuery(Query):
72
71
  @staticmethod
73
72
  def _render_sub_query_per_rel_type_create_new(rel_type: str, rel_def: FieldInfo) -> str:
74
73
  subquery = [
75
- "WITH peer_node, rb, active_attr, new_attr",
76
74
  "WITH peer_node, rb, active_attr, new_attr",
77
75
  f'WHERE type(rb) = "{rel_type}"',
78
76
  ]
@@ -126,8 +124,7 @@ class AttributeRenameQuery(Query):
126
124
 
127
125
  add_uuid = db.render_uuid_generation(node_label="new_attr", node_attr="uuid")
128
126
  query = """
129
- CALL {
130
- WITH node
127
+ CALL (node) {
131
128
  MATCH (root:Root)<-[r:IS_PART_OF]-(node)
132
129
  WHERE %(branch_filter)s
133
130
  RETURN node as n1, r as r1
@@ -137,8 +134,7 @@ class AttributeRenameQuery(Query):
137
134
  WITH n1 as active_node, r1 as rb
138
135
  WHERE rb.status = "active"
139
136
  // Find all the attributes that need to be updated
140
- CALL {
141
- WITH active_node
137
+ CALL (active_node) {
142
138
  MATCH (active_node)-[r:HAS_ATTRIBUTE]-(attr:Attribute { name: $prev_attr.name })
143
139
  WHERE %(branch_filter)s
144
140
  RETURN active_node as n1, r as r1, attr as attr1
@@ -151,8 +147,7 @@ class AttributeRenameQuery(Query):
151
147
  %(add_uuid)s
152
148
  WITH active_attr, new_attr
153
149
  MATCH (active_attr)-[]-(peer)
154
- CALL {
155
- WITH active_attr, peer
150
+ CALL (active_attr, peer) {
156
151
  MATCH (active_attr)-[r]-(peer)
157
152
  WHERE %(branch_filter)s
158
153
  RETURN active_attr as a1, r as r1, peer as p1
@@ -161,7 +156,7 @@ class AttributeRenameQuery(Query):
161
156
  }
162
157
  WITH a1 as active_attr, r1 as rb, p1 as peer_node, new_attr
163
158
  WHERE rb.status = "active"
164
- CALL {
159
+ CALL (peer_node, rb, active_attr, new_attr){
165
160
  %(sub_query_create_all)s
166
161
  }
167
162
  WITH p2 as peer_node, rb, new_attr, active_attr
@@ -170,7 +165,7 @@ class AttributeRenameQuery(Query):
170
165
 
171
166
  if not (self.branch.is_default or self.branch.is_global):
172
167
  query = """
173
- CALL {
168
+ CALL (peer_node, rb, active_attr) {
174
169
  %(sub_query_update_all)s
175
170
  }
176
171
  WITH p2 as peer_node, rb, new_attr
@@ -55,7 +55,6 @@ class DeleteElementInSchemaQuery(Query):
55
55
  @staticmethod
56
56
  def _render_sub_query_per_rel_type(rel_name: str, rel_type: str, direction: GraphRelDirection) -> str:
57
57
  subquery = [
58
- f"WITH peer_node, {rel_name}, element_to_delete",
59
58
  f"WITH peer_node, {rel_name}, element_to_delete",
60
59
  f'WHERE type({rel_name}) = "{rel_type}"',
61
60
  ]
@@ -67,28 +66,32 @@ class DeleteElementInSchemaQuery(Query):
67
66
  return "\n".join(subquery)
68
67
 
69
68
  @classmethod
70
- def _render_sub_query_out(cls) -> str:
69
+ def _render_sub_query_out(cls) -> tuple[str, str]:
70
+ rel_name = "rel_outband"
71
+ sub_query_out_args = f"peer_node, {rel_name}, element_to_delete"
71
72
  sub_queries_out = [
72
73
  cls._render_sub_query_per_rel_type(
73
- rel_name="rel_outband", rel_type=rel_type, direction=GraphRelDirection.OUTBOUND
74
+ rel_name=rel_name, rel_type=rel_type, direction=GraphRelDirection.OUTBOUND
74
75
  )
75
76
  for rel_type, rel_def in GraphNodeRelationships.model_fields.items()
76
77
  if rel_def.default.direction in [GraphRelDirection.OUTBOUND, GraphRelDirection.EITHER]
77
78
  ]
78
79
  sub_query_out = "\nUNION\n".join(sub_queries_out)
79
- return sub_query_out
80
+ return sub_query_out, sub_query_out_args
80
81
 
81
82
  @classmethod
82
- def _render_sub_query_in(cls) -> str:
83
+ def _render_sub_query_in(cls) -> tuple[str, str]:
84
+ rel_name = "rel_inband"
85
+ sub_query_in_args = f"peer_node, {rel_name}, element_to_delete"
83
86
  sub_queries_in = [
84
87
  cls._render_sub_query_per_rel_type(
85
- rel_name="rel_inband", rel_type=rel_type, direction=GraphRelDirection.INBOUND
88
+ rel_name=rel_name, rel_type=rel_type, direction=GraphRelDirection.INBOUND
86
89
  )
87
90
  for rel_type, rel_def in GraphNodeRelationships.model_fields.items()
88
91
  if rel_def.default.direction in [GraphRelDirection.INBOUND, GraphRelDirection.EITHER]
89
92
  ]
90
93
  sub_query_in = "\nUNION\n".join(sub_queries_in)
91
- return sub_query_in
94
+ return sub_query_in, sub_query_in_args
92
95
 
93
96
  async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None: # noqa: ARG002
94
97
  branch_filter, branch_params = self.branch.get_query_filter_path(at=self.at.to_string())
@@ -108,16 +111,15 @@ class DeleteElementInSchemaQuery(Query):
108
111
  "from": self.at.to_string(),
109
112
  }
110
113
 
111
- sub_query_out = self._render_sub_query_out()
112
- sub_query_in = self._render_sub_query_in()
114
+ sub_query_out, sub_query_out_args = self._render_sub_query_out()
115
+ sub_query_in, sub_query_in_args = self._render_sub_query_in()
113
116
 
114
117
  self.add_to_query(self.render_match())
115
118
  self.add_to_query(self.render_where())
116
119
 
117
120
  # ruff: noqa: E501
118
121
  query = """
119
- CALL {
120
- WITH attr_node
122
+ CALL (attr_node) {
121
123
  MATCH (root:Root)<-[r:IS_PART_OF]-(attr_node)
122
124
  WHERE %(branch_filter)s
123
125
  RETURN attr_node as n1, r as r1
@@ -130,8 +132,7 @@ class DeleteElementInSchemaQuery(Query):
130
132
 
131
133
  // Process Outbound Relationship
132
134
  MATCH (element_to_delete)-[]->(peer)
133
- CALL {
134
- WITH element_to_delete, peer
135
+ CALL (element_to_delete, peer) {
135
136
  MATCH (element_to_delete)-[r]->(peer)
136
137
  WHERE %(branch_filter)s
137
138
  RETURN element_to_delete as n1, r as rel_outband1, peer as p1
@@ -140,7 +141,7 @@ class DeleteElementInSchemaQuery(Query):
140
141
  }
141
142
  WITH n1 as element_to_delete, rel_outband1 as rel_outband, p1 as peer_node
142
143
  WHERE rel_outband.status = "active"
143
- CALL {
144
+ CALL (%(sub_query_out_args)s) {
144
145
  %(sub_query_out)s
145
146
  }
146
147
  WITH p2 as peer_node, rel_outband, element_to_delete
@@ -150,8 +151,7 @@ class DeleteElementInSchemaQuery(Query):
150
151
  WITH DISTINCT(element_to_delete) AS element_to_delete
151
152
  // Process Inbound Relationship
152
153
  MATCH (element_to_delete)<-[]-(peer)
153
- CALL {
154
- WITH element_to_delete, peer
154
+ CALL (element_to_delete, peer) {
155
155
  MATCH (element_to_delete)<-[r]-(peer)
156
156
  WHERE %(branch_filter)s
157
157
  RETURN element_to_delete as n1, r as rel_inband1, peer as p1
@@ -160,7 +160,7 @@ class DeleteElementInSchemaQuery(Query):
160
160
  }
161
161
  WITH n1 as element_to_delete, rel_inband1 as rel_inband, p1 as peer_node
162
162
  WHERE rel_inband.status = "active"
163
- CALL {
163
+ CALL (%(sub_query_in_args)s) {
164
164
  %(sub_query_in)s
165
165
  }
166
166
  WITH p2 as peer_node, rel_inband, element_to_delete
@@ -172,5 +172,7 @@ class DeleteElementInSchemaQuery(Query):
172
172
  "branch_filter": branch_filter,
173
173
  "sub_query_out": sub_query_out,
174
174
  "sub_query_in": sub_query_in,
175
+ "sub_query_out_args": sub_query_out_args,
176
+ "sub_query_in_args": sub_query_in_args,
175
177
  }
176
178
  self.add_to_query(query)
@@ -47,7 +47,6 @@ class NodeDuplicateQuery(Query):
47
47
  @staticmethod
48
48
  def _render_sub_query_per_rel_type(rel_name: str, rel_type: str, rel_dir: GraphRelDirection) -> str:
49
49
  subquery = [
50
- f"WITH peer_node, {rel_name}, active_node, new_node",
51
50
  f"WITH peer_node, {rel_name}, active_node, new_node",
52
51
  f'WHERE type({rel_name}) = "{rel_type}"',
53
52
  ]
@@ -81,28 +80,28 @@ class NodeDuplicateQuery(Query):
81
80
  return "\n".join(subquery)
82
81
 
83
82
  @classmethod
84
- def _render_sub_query_out(cls) -> str:
83
+ def _render_sub_query_out(cls) -> tuple[str, str]:
84
+ rel_name = "rel_outband"
85
+ sub_query_out_args = f"peer_node, {rel_name}, active_node, new_node"
85
86
  sub_queries_out = [
86
- cls._render_sub_query_per_rel_type(
87
- rel_name="rel_outband", rel_type=rel_type, rel_dir=GraphRelDirection.OUTBOUND
88
- )
87
+ cls._render_sub_query_per_rel_type(rel_name=rel_name, rel_type=rel_type, rel_dir=GraphRelDirection.OUTBOUND)
89
88
  for rel_type, field_info in GraphNodeRelationships.model_fields.items()
90
89
  if field_info.default.direction in (GraphRelDirection.OUTBOUND, GraphRelDirection.EITHER)
91
90
  ]
92
91
  sub_query_out = "\nUNION\n".join(sub_queries_out)
93
- return sub_query_out
92
+ return sub_query_out, sub_query_out_args
94
93
 
95
94
  @classmethod
96
- def _render_sub_query_in(cls) -> str:
95
+ def _render_sub_query_in(cls) -> tuple[str, str]:
96
+ rel_name = "rel_inband"
97
+ sub_query_in_args = f"peer_node, {rel_name}, active_node, new_node"
97
98
  sub_queries_in = [
98
- cls._render_sub_query_per_rel_type(
99
- rel_name="rel_inband", rel_type=rel_type, rel_dir=GraphRelDirection.INBOUND
100
- )
99
+ cls._render_sub_query_per_rel_type(rel_name=rel_name, rel_type=rel_type, rel_dir=GraphRelDirection.INBOUND)
101
100
  for rel_type, field_info in GraphNodeRelationships.model_fields.items()
102
101
  if field_info.default.direction in (GraphRelDirection.INBOUND, GraphRelDirection.EITHER)
103
102
  ]
104
103
  sub_query_in = "\nUNION\n".join(sub_queries_in)
105
- return sub_query_in
104
+ return sub_query_in, sub_query_in_args
106
105
 
107
106
  async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None: # noqa: ARG002
108
107
  branch_filter, branch_params = self.branch.get_query_filter_path(at=self.at.to_string())
@@ -126,15 +125,14 @@ class NodeDuplicateQuery(Query):
126
125
  "from": self.at.to_string(),
127
126
  }
128
127
 
129
- sub_query_out = self._render_sub_query_out()
130
- sub_query_in = self._render_sub_query_in()
128
+ sub_query_out, sub_query_out_args = self._render_sub_query_out()
129
+ sub_query_in, sub_query_in_args = self._render_sub_query_in()
131
130
 
132
131
  self.add_to_query(self.render_match())
133
132
 
134
133
  # ruff: noqa: E501
135
134
  query = """
136
- CALL {
137
- WITH node
135
+ CALL (node) {
138
136
  MATCH (root:Root)<-[r:IS_PART_OF]-(node)
139
137
  WHERE %(branch_filter)s
140
138
  RETURN node as n1, r as r1
@@ -147,8 +145,7 @@ class NodeDuplicateQuery(Query):
147
145
  WITH active_node, new_node
148
146
  // Process Outbound Relationship
149
147
  MATCH (active_node)-[]->(peer)
150
- CALL {
151
- WITH active_node, peer
148
+ CALL (active_node, peer) {
152
149
  MATCH (active_node)-[r]->(peer)
153
150
  WHERE %(branch_filter)s
154
151
  RETURN active_node as n1, r as rel_outband1, peer as p1
@@ -157,7 +154,7 @@ class NodeDuplicateQuery(Query):
157
154
  }
158
155
  WITH n1 as active_node, rel_outband1 as rel_outband, p1 as peer_node, new_node
159
156
  WHERE rel_outband.status = "active" AND rel_outband.to IS NULL
160
- CALL {
157
+ CALL (%(sub_query_out_args)s) {
161
158
  %(sub_query_out)s
162
159
  }
163
160
  WITH p2 as peer_node, rel_outband, active_node, new_node
@@ -167,8 +164,7 @@ class NodeDuplicateQuery(Query):
167
164
  WITH DISTINCT active_node, new_node
168
165
  // Process Inbound Relationship
169
166
  MATCH (active_node)<-[]-(peer)
170
- CALL {
171
- WITH active_node, peer
167
+ CALL (active_node, peer) {
172
168
  MATCH (active_node)<-[r]-(peer)
173
169
  WHERE %(branch_filter)s
174
170
  RETURN active_node as n1, r as rel_inband1, peer as p1
@@ -177,7 +173,7 @@ class NodeDuplicateQuery(Query):
177
173
  }
178
174
  WITH n1 as active_node, rel_inband1 as rel_inband, p1 as peer_node, new_node
179
175
  WHERE rel_inband.status = "active" AND rel_inband.to IS NULL
180
- CALL {
176
+ CALL (%(sub_query_in_args)s) {
181
177
  %(sub_query_in)s
182
178
  }
183
179
  WITH p2 as peer_node, rel_inband, active_node, new_node
@@ -191,5 +187,7 @@ class NodeDuplicateQuery(Query):
191
187
  "labels": ":".join(self.new_node.labels),
192
188
  "sub_query_out": sub_query_out,
193
189
  "sub_query_in": sub_query_in,
190
+ "sub_query_out_args": sub_query_out_args,
191
+ "sub_query_in_args": sub_query_in_args,
194
192
  }
195
193
  self.add_to_query(query)