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
@@ -30,8 +30,7 @@ class EnrichedDiffRootsUpsertQuery(Query):
30
30
  query = """
31
31
  UNWIND $diff_root_list AS diff_root_map
32
32
  WITH diff_root_map
33
- CALL {
34
- WITH diff_root_map
33
+ CALL (diff_root_map) {
35
34
  MERGE (diff_root:DiffRoot {uuid: diff_root_map.uuid})
36
35
  SET diff_root.base_branch = diff_root_map.base_branch
37
36
  SET diff_root.diff_branch = diff_root_map.diff_branch
@@ -43,8 +42,7 @@ CALL {
43
42
  WITH DISTINCT diff_root AS diff_root
44
43
  WITH collect(diff_root) AS diff_roots
45
44
  WHERE SIZE(diff_roots) = 2
46
- CALL {
47
- WITH diff_roots
45
+ CALL (diff_roots) {
48
46
  WITH diff_roots[0] AS base_diff_node, diff_roots[1] AS branch_diff_node
49
47
  MERGE (base_diff_node)-[:DIFF_HAS_PARTNER]-(branch_diff_node)
50
48
  SET (base_diff_node).partner_uuid = (branch_diff_node).uuid
@@ -98,7 +96,7 @@ SET
98
96
  diff_node.is_node_kind_migration = node_map.node_properties.is_node_kind_migration,
99
97
  diff_node.path_identifier = node_map.node_properties.path_identifier
100
98
  WITH root_uuid, node_map, diff_node, has_node_conflict
101
- CALL {
99
+ CALL (diff_node) {
102
100
  // -------------------------
103
101
  // delete parent-child relationships for included nodes, they will be added in EnrichedNodesLinkQuery
104
102
  // -------------------------
@@ -107,43 +105,38 @@ CALL {
107
105
  DELETE parent_rel
108
106
  }
109
107
  OPTIONAL MATCH (diff_node)-[:DIFF_HAS_CONFLICT]->(current_node_conflict:DiffConflict)
110
- CALL {
108
+ CALL (diff_node, current_node_conflict, has_node_conflict) {
111
109
  // -------------------------
112
110
  // create a node-level conflict, if necessary
113
111
  // -------------------------
114
112
  WITH diff_node, current_node_conflict, has_node_conflict
115
- WITH diff_node, current_node_conflict, has_node_conflict
116
113
  WHERE current_node_conflict IS NULL AND has_node_conflict = TRUE
117
114
  CREATE (diff_node)-[:DIFF_HAS_CONFLICT]->(:DiffConflict)
118
115
  }
119
- CALL {
116
+ CALL (current_node_conflict, has_node_conflict) {
120
117
  // -------------------------
121
118
  // delete a node-level conflict, if necessary
122
119
  // -------------------------
123
120
  WITH current_node_conflict, has_node_conflict
124
- WITH current_node_conflict, has_node_conflict
125
121
  WHERE current_node_conflict IS NOT NULL AND has_node_conflict = FALSE
126
122
  DETACH DELETE current_node_conflict
127
123
  }
128
124
  WITH root_uuid, node_map, diff_node, has_node_conflict, node_map.conflict_params AS node_conflict_params
129
- CALL {
125
+ CALL (diff_node, has_node_conflict, node_conflict_params) {
130
126
  // -------------------------
131
127
  // set the properties of the node-level conflict, if necessary
132
128
  // -------------------------
133
129
  WITH diff_node, has_node_conflict, node_conflict_params
134
- WITH diff_node, has_node_conflict, node_conflict_params
135
130
  WHERE has_node_conflict = TRUE
136
131
  OPTIONAL MATCH (diff_node)-[:DIFF_HAS_CONFLICT]->(node_conflict:DiffConflict)
137
132
  SET node_conflict = node_conflict_params
138
133
  }
139
- CALL {
134
+ CALL (diff_node, node_map) {
140
135
  // -------------------------
141
136
  // remove stale attributes for this node
142
137
  // -------------------------
143
- WITH diff_node, node_map
144
- CALL {
145
- WITH diff_node, node_map
146
- WITH diff_node, %(attr_name_list_comp)s AS attr_names
138
+ CALL (diff_node, node_map) {
139
+ WITH %(attr_name_list_comp)s AS attr_names
147
140
  OPTIONAL MATCH (diff_node)-[:DIFF_HAS_ATTRIBUTE]->(attr_to_delete:DiffAttribute)
148
141
  WHERE NOT (attr_to_delete.name IN attr_names)
149
142
  OPTIONAL MATCH (attr_to_delete)-[*..6]->(next_to_delete)
@@ -163,9 +156,8 @@ CALL {
163
156
  // -------------------------
164
157
  // remove stale properties for this attribute
165
158
  // -------------------------
166
- CALL {
167
- WITH diff_attribute, node_attribute
168
- WITH diff_attribute, %(attr_props_list_comp)s AS prop_types
159
+ CALL (diff_attribute, node_attribute) {
160
+ WITH %(attr_props_list_comp)s AS prop_types
169
161
  OPTIONAL MATCH (diff_attribute)-[:DIFF_HAS_PROPERTY]->(prop_to_delete:DiffProperty)
170
162
  WHERE NOT (prop_to_delete.property_type IN prop_types)
171
163
  OPTIONAL MATCH (prop_to_delete)-[*..4]->(next_to_delete)
@@ -192,9 +184,8 @@ CALL {
192
184
  // -------------------------
193
185
  // remove stale relationships for this node
194
186
  // -------------------------
195
- CALL {
196
- WITH diff_node, node_map
197
- WITH diff_node, %(rel_name_list_comp)s AS rel_names
187
+ CALL (diff_node, node_map) {
188
+ WITH %(rel_name_list_comp)s AS rel_names
198
189
  OPTIONAL MATCH (diff_node)-[:DIFF_HAS_RELATIONSHIP]->(rel_to_delete:DiffRelationship)
199
190
  WHERE NOT (rel_to_delete.name IN rel_names)
200
191
  OPTIONAL MATCH (rel_to_delete)-[*..8]->(next_to_delete)
@@ -212,9 +203,8 @@ SET diff_relationship = node_relationship.node_properties
212
203
  // remove stale elements for this relationship group
213
204
  // -------------------------
214
205
  WITH diff_relationship, node_relationship
215
- CALL {
216
- WITH diff_relationship, node_relationship
217
- WITH diff_relationship, %(rel_peers_list_comp)s AS rel_peers
206
+ CALL (diff_relationship, node_relationship) {
207
+ WITH %(rel_peers_list_comp)s AS rel_peers
218
208
  OPTIONAL MATCH (diff_relationship)-[:DIFF_HAS_ELEMENT]->(element_to_delete:DiffRelationshipElement)
219
209
  WHERE NOT (element_to_delete.peer_id IN rel_peers)
220
210
  OPTIONAL MATCH (element_to_delete)-[*..6]->(next_to_delete)
@@ -247,9 +237,8 @@ FOREACH (i in CASE WHEN has_element_conflict = TRUE THEN [1] ELSE [] END |
247
237
  // remove stale properties for this relationship element
248
238
  // -------------------------
249
239
  WITH diff_relationship_element, node_single_relationship
250
- CALL {
251
- WITH diff_relationship_element, node_single_relationship
252
- WITH diff_relationship_element, %(element_props_list_comp)s AS element_props
240
+ CALL (diff_relationship_element, node_single_relationship) {
241
+ WITH %(element_props_list_comp)s AS element_props
253
242
  OPTIONAL MATCH (diff_relationship_element)-[:DIFF_HAS_PROPERTY]->(property_to_delete:DiffProperty)
254
243
  WHERE NOT (property_to_delete.property_type IN element_props)
255
244
  OPTIONAL MATCH (property_to_delete)-[*..4]->(next_to_delete)
@@ -451,10 +440,9 @@ WITH keys($parent_node_map) AS child_node_uuids
451
440
  MATCH (diff_root:DiffRoot {uuid: $root_uuid})
452
441
  MATCH (diff_root)-[:DIFF_HAS_NODE]->(child_node:DiffNode)
453
442
  WHERE child_node.uuid IN child_node_uuids
454
- CALL {
455
- WITH diff_root, child_node
456
- WITH diff_root, child_node, $parent_node_map[child_node.uuid] AS sub_map
457
- WITH diff_root, child_node, sub_map, keys(sub_map) AS relationship_names
443
+ CALL (diff_root, child_node) {
444
+ WITH $parent_node_map[child_node.uuid] AS sub_map
445
+ WITH sub_map, keys(sub_map) AS relationship_names
458
446
  MATCH (child_node)-[:DIFF_HAS_RELATIONSHIP]->(diff_rel_group:DiffRelationship)
459
447
  WHERE diff_rel_group.name IN relationship_names
460
448
  WITH diff_root, diff_rel_group, toString(sub_map[diff_rel_group.name]) AS parent_uuid
@@ -46,70 +46,59 @@ WHERE ($diff_id IS NOT NULL AND root.uuid = $diff_id)
46
46
  OR ($tracking_id IS NOT NULL AND root.tracking_id = $tracking_id AND root.diff_branch = $diff_branch_name)
47
47
  MATCH (root)-[:DIFF_HAS_NODE]->(dn:DiffNode)
48
48
  WHERE $node_uuids IS NULL OR dn.uuid IN $node_uuids
49
- CALL {
49
+ CALL (dn) {
50
50
  // ----------------------
51
51
  // handle attribute count updates
52
52
  // ----------------------
53
- WITH dn
54
53
  MATCH (dn)-[:DIFF_HAS_ATTRIBUTE]->(da:DiffAttribute)
55
- CALL {
56
- WITH da
54
+ CALL (da) {
57
55
  OPTIONAL MATCH (da)-[:DIFF_HAS_PROPERTY]->(dp:DiffProperty)-[:DIFF_HAS_CONFLICT]->(dc:DiffConflict)
58
- WITH da, count(dc) AS num_conflicts
56
+ WITH count(dc) AS num_conflicts
59
57
  SET da.num_conflicts = num_conflicts
60
58
  SET da.contains_conflict = (num_conflicts > 0)
61
59
  }
62
- CALL {
63
- WITH da
60
+ CALL (da) {
64
61
  OPTIONAL MATCH (da)-[:DIFF_HAS_PROPERTY]->(dp:DiffProperty {action: "added"})
65
- WITH da, count(dp.action) AS num_added
62
+ WITH count(dp.action) AS num_added
66
63
  SET da.num_added = num_added
67
64
  }
68
- CALL {
69
- WITH da
65
+ CALL (da) {
70
66
  OPTIONAL MATCH (da)-[:DIFF_HAS_PROPERTY]->(dp:DiffProperty {action: "updated"})
71
- WITH da, count(dp.action) AS num_updated
67
+ WITH count(dp.action) AS num_updated
72
68
  SET da.num_updated = num_updated
73
69
  }
74
- CALL {
75
- WITH da
70
+ CALL (da) {
76
71
  OPTIONAL MATCH (da)-[:DIFF_HAS_PROPERTY]->(dp:DiffProperty {action: "removed"})
77
- WITH da, count(dp.action) AS num_removed
72
+ WITH count(dp.action) AS num_removed
78
73
  SET da.num_removed = num_removed
79
74
  }
80
75
  }
81
- CALL {
82
- WITH dn
76
+ CALL (dn) {
83
77
  MATCH (dn)-[:DIFF_HAS_RELATIONSHIP]->(dr:DiffRelationship)
84
- CALL {
78
+ CALL (dr) {
85
79
  // ----------------------
86
80
  // handle relationship element count updates
87
81
  // ----------------------
88
- WITH dr
89
82
  MATCH (dr)-[:DIFF_HAS_ELEMENT]->(dre:DiffRelationshipElement)
90
- CALL {
91
- WITH dre
83
+ CALL (dre) {
92
84
  OPTIONAL MATCH (dre)-[*..4]->(dc:DiffConflict)
93
- WITH dre, count(dc) AS num_conflicts
85
+ WITH count(dc) AS num_conflicts
94
86
  SET dre.num_conflicts = num_conflicts
95
87
  SET dre.contains_conflict = (num_conflicts > 0)
96
88
  }
97
- CALL {
98
- WITH dre
89
+ CALL (dre) {
99
90
  OPTIONAL MATCH (dre)-[:DIFF_HAS_PROPERTY]->(dp:DiffProperty {action: "added"})
100
- WITH dre, count(dp.action) AS num_added
91
+ WITH count(dp.action) AS num_added
101
92
  SET dre.num_added = num_added
102
93
  }
103
- CALL {
104
- WITH dre
94
+ CALL (dre) {
105
95
  OPTIONAL MATCH (dre)-[:DIFF_HAS_PROPERTY]->(dp:DiffProperty {action: "updated"})
106
- WITH dre, count(dp.action) AS num_updated
96
+ WITH count(dp.action) AS num_updated
107
97
  SET dre.num_updated = num_updated
108
98
  }
109
- CALL {
110
- WITH dre
99
+ CALL (dre) {
111
100
  OPTIONAL MATCH (dre)-[:DIFF_HAS_PROPERTY]->(dp:DiffProperty {action: "removed"})
112
- WITH dre, count(dp.action) AS num_removed
101
+ WITH count(dp.action) AS num_removed
113
102
  SET dre.num_removed = num_removed
114
103
  }
115
104
  }
@@ -121,22 +110,19 @@ CALL {
121
110
  SET dr.num_conflicts = num_conflicts
122
111
  SET dr.contains_conflict = (num_conflicts > 0)
123
112
  WITH dr
124
- CALL {
125
- WITH dr
113
+ CALL (dr) {
126
114
  OPTIONAL MATCH (dr)-[:DIFF_HAS_ELEMENT]->(dre:DiffRelationshipElement {action: "added"})
127
- WITH dr, count(dre.action) AS num_added
115
+ WITH count(dre.action) AS num_added
128
116
  SET dr.num_added = num_added
129
117
  }
130
- CALL {
131
- WITH dr
118
+ CALL (dr) {
132
119
  OPTIONAL MATCH (dr)-[:DIFF_HAS_ELEMENT]->(dre:DiffRelationshipElement {action: "updated"})
133
- WITH dr, count(dre.action) AS num_updated
120
+ WITH count(dre.action) AS num_updated
134
121
  SET dr.num_updated = num_updated
135
122
  }
136
- CALL {
137
- WITH dr
123
+ CALL (dr) {
138
124
  OPTIONAL MATCH (dr)-[:DIFF_HAS_ELEMENT]->(dre:DiffRelationshipElement {action: "removed"})
139
- WITH dr, count(dre.action) AS num_removed
125
+ WITH count(dre.action) AS num_removed
140
126
  SET dr.num_removed = num_removed
141
127
  }
142
128
  }
@@ -189,19 +175,16 @@ WHERE $node_uuids IS NULL OR dn.uuid IN $node_uuids
189
175
  // handle node count updates
190
176
  // ----------------------
191
177
  WITH root, dn, coalesce(dn.num_conflicts, 0) AS previous_num_conflicts
192
- CALL {
178
+ CALL (dn) {
193
179
  // ----------------------
194
180
  // handle node num_conflicts update
195
181
  // ----------------------
196
- WITH dn
197
182
  OPTIONAL MATCH (dn)-[:DIFF_HAS_ATTRIBUTE]->(da:DiffAttribute {contains_conflict: TRUE})
198
183
  RETURN sum(da.num_conflicts) AS num_conflicts
199
184
  UNION ALL
200
- WITH dn
201
185
  OPTIONAL MATCH (dn)-[:DIFF_HAS_RELATIONSHIP]->(dr:DiffRelationship {contains_conflict: TRUE})
202
186
  RETURN sum(dr.num_conflicts) AS num_conflicts
203
187
  UNION ALL
204
- WITH dn
205
188
  OPTIONAL MATCH (dn)-[:DIFF_HAS_CONFLICT]->(dc:DiffConflict)
206
189
  RETURN count(dc) AS num_conflicts
207
190
  }
@@ -209,17 +192,16 @@ WITH root, dn, previous_num_conflicts, sum(num_conflicts) AS updated_num_conflic
209
192
  SET dn.num_conflicts = updated_num_conflicts
210
193
  SET dn.contains_conflict = (updated_num_conflicts > 0)
211
194
  WITH root, dn, updated_num_conflicts - previous_num_conflicts AS num_conflicts_delta
212
- CALL {
195
+ CALL (dn) {
213
196
  // ----------------------
214
197
  // handle node added/updated/removed updates
215
198
  // ----------------------
216
- WITH dn
217
199
  OPTIONAL MATCH (dn)-[:DIFF_HAS_ATTRIBUTE]->(da:DiffAttribute)
218
- WITH dn, collect(da.action) AS attr_actions
200
+ WITH collect(da.action) AS attr_actions
219
201
  OPTIONAL MATCH (dn)-[:DIFF_HAS_RELATIONSHIP]->(dr:DiffRelationship)
220
- WITH dn, attr_actions, collect(dr.action) AS rel_actions
221
- WITH dn, attr_actions + rel_actions AS actions
222
- WITH dn, reduce(counts = [0,0,0], a IN actions |
202
+ WITH attr_actions, collect(dr.action) AS rel_actions
203
+ WITH attr_actions + rel_actions AS actions
204
+ WITH reduce(counts = [0,0,0], a IN actions |
223
205
  CASE
224
206
  WHEN a = "added" THEN [counts[0] + 1, counts[1], counts[2]]
225
207
  WHEN a = "updated" THEN [counts[0], counts[1] + 1, counts[2]]
@@ -227,7 +209,7 @@ CALL {
227
209
  ELSE counts
228
210
  END
229
211
  ) AS action_counts
230
- WITH dn, action_counts[0] AS num_added, action_counts[1] AS num_updated, action_counts[2] AS num_removed
212
+ WITH action_counts[0] AS num_added, action_counts[1] AS num_updated, action_counts[2] AS num_removed
231
213
  SET dn.num_added = num_added
232
214
  SET dn.num_updated = num_updated
233
215
  SET dn.num_removed = num_removed
@@ -236,8 +218,7 @@ CALL {
236
218
  // handle conflict updates for parent nodes
237
219
  // ----------------------
238
220
  WITH root, dn, num_conflicts_delta
239
- CALL {
240
- WITH dn, num_conflicts_delta
221
+ CALL (dn, num_conflicts_delta) {
241
222
  OPTIONAL MATCH (dn)-[:DIFF_HAS_RELATIONSHIP|DIFF_HAS_NODE*1..]->(parent_node:DiffNode)
242
223
  SET parent_node.num_conflicts = parent_node.num_conflicts + num_conflicts_delta
243
224
  SET parent_node.contains_conflict = (parent_node.num_conflicts > 0)
@@ -246,8 +227,7 @@ CALL {
246
227
  // handle root count updates
247
228
  // ----------------------
248
229
  WITH root, sum(num_conflicts_delta) AS total_conflicts_delta
249
- CALL {
250
- WITH root, total_conflicts_delta
230
+ CALL (root, total_conflicts_delta) {
251
231
  SET root.num_conflicts = coalesce(root.num_conflicts, 0) + total_conflicts_delta
252
232
  SET root.contains_conflict = root.num_conflicts > 0
253
233
  WITH root
@@ -526,7 +526,11 @@ class DiffQueryParser:
526
526
  return self._current_node_field_specifiers
527
527
 
528
528
  def read_result(self, query_result: QueryResult) -> None:
529
- path = query_result.get_path(label="diff_path")
529
+ try:
530
+ path = query_result.get_path(label="diff_path")
531
+ except ValueError:
532
+ # the path was null, so nothing to read
533
+ return
530
534
  database_path = DatabasePath.from_cypher_path(cypher_path=path)
531
535
  self._parse_path(database_path=database_path)
532
536
  self._current_node_field_specifiers = None
@@ -20,7 +20,7 @@ log = get_logger()
20
20
  async def update_diff(model: RequestDiffUpdate, service: InfrahubServices) -> None:
21
21
  await add_tags(branches=[model.branch_name])
22
22
 
23
- async with service.database.start_session() as db:
23
+ async with service.database.start_session(read_only=False) as db:
24
24
  component_registry = get_component_registry()
25
25
  base_branch = await registry.get_branch(db=db, branch=registry.default_branch)
26
26
  diff_branch = await registry.get_branch(db=db, branch=model.branch_name)
@@ -40,7 +40,7 @@ async def update_diff(model: RequestDiffUpdate, service: InfrahubServices) -> No
40
40
  async def refresh_diff(branch_name: str, diff_id: str, service: InfrahubServices) -> None:
41
41
  await add_tags(branches=[branch_name])
42
42
 
43
- async with service.database.start_session() as db:
43
+ async with service.database.start_session(read_only=False) as db:
44
44
  component_registry = get_component_registry()
45
45
  base_branch = await registry.get_branch(db=db, branch=registry.default_branch)
46
46
  diff_branch = await registry.get_branch(db=db, branch=branch_name)
@@ -53,7 +53,7 @@ async def refresh_diff(branch_name: str, diff_id: str, service: InfrahubServices
53
53
  async def refresh_diff_all(branch_name: str, context: InfrahubContext, service: InfrahubServices) -> None:
54
54
  await add_tags(branches=[branch_name])
55
55
 
56
- async with service.database.start_session() as db:
56
+ async with service.database.start_session(read_only=True) as db:
57
57
  component_registry = get_component_registry()
58
58
  default_branch = registry.get_branch_from_registry()
59
59
  diff_repository = await component_registry.get_component(DiffRepository, db=db, branch=default_branch)
infrahub/core/manager.py CHANGED
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from copy import copy
3
4
  from functools import reduce
4
5
  from typing import TYPE_CHECKING, Any, Iterable, Literal, TypeVar, overload
5
6
 
@@ -1339,22 +1340,24 @@ class NodeManager:
1339
1340
  nodes: list[Node],
1340
1341
  branch: Branch | str | None = None,
1341
1342
  at: Timestamp | str | None = None,
1343
+ cascade_delete: bool = True,
1342
1344
  ) -> list[Node]:
1343
1345
  """Returns list of deleted nodes because of cascading deletes"""
1344
1346
  branch = await registry.get_branch(branch=branch, db=db)
1345
- node_delete_validator = NodeDeleteValidator(db=db, branch=branch)
1346
- ids_to_delete = await node_delete_validator.get_ids_to_delete(nodes=nodes, at=at)
1347
- node_ids = {node.get_id() for node in nodes}
1348
- missing_ids_to_delete = ids_to_delete - node_ids
1349
- if missing_ids_to_delete:
1350
- node_map = await cls.get_many(db=db, ids=list(missing_ids_to_delete), branch=branch, at=at)
1351
- nodes += list(node_map.values())
1352
- deleted_nodes = []
1353
- for node in nodes:
1347
+ nodes_to_delete = copy(nodes)
1348
+ if cascade_delete:
1349
+ node_delete_validator = NodeDeleteValidator(db=db, branch=branch)
1350
+ ids_to_delete = await node_delete_validator.get_ids_to_delete(nodes=nodes, at=at)
1351
+ node_ids = {node.get_id() for node in nodes}
1352
+ missing_ids_to_delete = ids_to_delete - node_ids
1353
+ if missing_ids_to_delete:
1354
+ node_map = await cls.get_many(db=db, ids=list(missing_ids_to_delete), branch=branch, at=at)
1355
+ nodes_to_delete += list(node_map.values())
1356
+
1357
+ for node in nodes_to_delete:
1354
1358
  await node.delete(db=db, at=at)
1355
- deleted_nodes.append(node)
1356
1359
 
1357
- return deleted_nodes
1360
+ return nodes_to_delete
1358
1361
 
1359
1362
 
1360
1363
  def _get_cardinality_one_identifiers_by_kind(
@@ -26,8 +26,7 @@ class Migration003Query01(Query):
26
26
  query = """
27
27
  MATCH path = (av2:AttributeValue)-[:HAS_VALUE]-(:Attribute {name: "optional"})-[:HAS_ATTRIBUTE]-(n:SchemaRelationship)-[:HAS_ATTRIBUTE]-(:Attribute {name: "kind"})-[:HAS_VALUE]-(av1:AttributeValue)
28
28
  WHERE av1.value = "Parent" AND av2.value = true AND all(r IN relationships(path) WHERE ( %(filters)s ))
29
- CALL {
30
- WITH n
29
+ CALL (n) {
31
30
  MATCH path22 = (av22:AttributeValue)-[r22:HAS_VALUE]-(a2:Attribute {name: "optional"})-[:HAS_ATTRIBUTE]-(n:SchemaRelationship)-[:HAS_ATTRIBUTE]-(:Attribute {name:"kind"})-[:HAS_VALUE]-(av11:AttributeValue)
32
31
  WHERE av11.value = "Parent" AND av22.value = true AND all(r IN relationships(path22) WHERE ( %(filters)s ))
33
32
  RETURN av22 as av2_sub, r22, a2, path22 as path2
@@ -98,8 +98,7 @@ class Migration013ConvertCoreRepositoryWithCred(Query):
98
98
  // --------------------------------
99
99
  MATCH (git_repo)-[:HAS_ATTRIBUTE]-(git_attr_name:Attribute)-[:HAS_VALUE]->(git_name_value:AttributeValue)
100
100
  WHERE git_attr_name.name = "name"
101
- CALL {
102
- WITH git_repo
101
+ CALL (git_repo) {
103
102
  MATCH path1 = (git_repo)-[r1:HAS_ATTRIBUTE]-(git_attr_name2:Attribute)-[r2:HAS_VALUE]->(git_name_value2:AttributeValue)
104
103
  WHERE git_attr_name2.name = "name"
105
104
  AND all(r IN relationships(path1) WHERE %(filters)s)
@@ -204,8 +203,7 @@ class Migration013ConvertCoreRepositoryWithoutCred(Query):
204
203
  WHERE a.name in ["username", "password"]
205
204
  AND av.value = "NULL"
206
205
  AND all(r IN relationships(path) WHERE %(filters)s AND r.status = "active")
207
- CALL {
208
- WITH node
206
+ CALL (node) {
209
207
  MATCH (root:Root)<-[r:IS_PART_OF]-(node)
210
208
  WHERE %(filters)s
211
209
  RETURN node as n1, r as r1
@@ -97,8 +97,7 @@ class DeleteNodesRelsQuery(Query):
97
97
  // - on deleted edge branch
98
98
  // - or on any branch and deleted node is agnostic
99
99
  // - or deleted node is aware and rel is agnostic
100
- CALL {
101
- WITH rel, deleted_edge
100
+ CALL (rel, deleted_edge) {
102
101
  OPTIONAL MATCH (rel)-[peer_active_edge {status: "active"}]-(peer_1)
103
102
  WHERE (peer_active_edge.branch = deleted_edge.branch OR (rel.branch_support <> $branch_agnostic AND deleted_edge.branch = $global_branch))
104
103
  AND peer_active_edge.to IS NULL
@@ -160,62 +159,52 @@ class DeleteNodesRelsQuery(Query):
160
159
  // Below CALL subqueries are called once for each rel-peer_2 pair for which we want to create a deleted edge.
161
160
  // Note that with current infrahub relationships edges design, only one of this CALL should be matched per pair.
162
161
 
163
- CALL {
164
- WITH rel, peer_2, branch, branch_level, deleted_time
162
+ CALL (rel, peer_2, branch, branch_level, deleted_time) {
165
163
  MATCH (rel)-[:IS_RELATED]->(peer_2)
166
164
  MERGE (rel)-[:IS_RELATED {status: "deleted", branch: branch, branch_level: branch_level, from: deleted_time}]->(peer_2)
167
165
  }
168
166
 
169
- CALL {
170
- WITH rel, peer_2, branch, branch_level, deleted_time
167
+ CALL (rel, peer_2, branch, branch_level, deleted_time) {
171
168
  MATCH (rel)-[:IS_PROTECTED]->(peer_2)
172
169
  MERGE (rel)-[:IS_PROTECTED {status: "deleted", branch: branch, branch_level: branch_level, from: deleted_time}]->(peer_2)
173
170
  }
174
171
 
175
- CALL {
176
- WITH rel, peer_2, branch, branch_level, deleted_time
172
+ CALL (rel, peer_2, branch, branch_level, deleted_time) {
177
173
  MATCH (rel)-[:IS_VISIBLE]->(peer_2)
178
174
  MERGE (rel)-[:IS_VISIBLE {status: "deleted", branch: branch, branch_level: branch_level, from: deleted_time}]->(peer_2)
179
175
  }
180
176
 
181
- CALL {
182
- WITH rel, peer_2, branch, branch_level, deleted_time
177
+ CALL (rel, peer_2, branch, branch_level, deleted_time) {
183
178
  MATCH (rel)-[:HAS_OWNER]->(peer_2)
184
179
  MERGE (rel)-[:HAS_OWNER {status: "deleted", branch: branch, branch_level: branch_level, from: deleted_time}]->(peer_2)
185
180
  }
186
181
 
187
- CALL {
188
- WITH rel, peer_2, branch, branch_level, deleted_time
182
+ CALL (rel, peer_2, branch, branch_level, deleted_time) {
189
183
  MATCH (rel)-[:HAS_SOURCE]->(peer_2)
190
184
  MERGE (rel)-[:HAS_SOURCE {status: "deleted", branch: branch, branch_level: branch_level, from: deleted_time}]->(peer_2)
191
185
  }
192
186
 
193
- CALL {
194
- WITH rel, peer_2, branch, branch_level, deleted_time
187
+ CALL (rel, peer_2, branch, branch_level, deleted_time) {
195
188
  MATCH (rel)<-[:IS_RELATED]-(peer_2)
196
189
  MERGE (rel)<-[:IS_RELATED {status: "deleted", branch: branch, branch_level: branch_level, from: deleted_time}]-(peer_2)
197
190
  }
198
191
 
199
- CALL {
200
- WITH rel, peer_2, branch, branch_level, deleted_time
192
+ CALL (rel, peer_2, branch, branch_level, deleted_time) {
201
193
  MATCH (rel)<-[:IS_PROTECTED]-(peer_2)
202
194
  MERGE (rel)<-[:IS_PROTECTED {status: "deleted", branch: branch, branch_level: branch_level, from: deleted_time}]-(peer_2)
203
195
  }
204
196
 
205
- CALL {
206
- WITH rel, peer_2, branch, branch_level, deleted_time
197
+ CALL (rel, peer_2, branch, branch_level, deleted_time) {
207
198
  MATCH (rel)<-[:IS_VISIBLE]-(peer_2)
208
199
  MERGE (rel)<-[:IS_VISIBLE {status: "deleted", branch: branch, branch_level: branch_level, from: deleted_time}]-(peer_2)
209
200
  }
210
201
 
211
- CALL {
212
- WITH rel, peer_2, branch, branch_level, deleted_time
202
+ CALL (rel, peer_2, branch, branch_level, deleted_time) {
213
203
  MATCH (rel)<-[:HAS_OWNER]-(peer_2)
214
204
  MERGE (rel)<-[:HAS_OWNER {status: "deleted", branch: branch, branch_level: branch_level, from: deleted_time}]-(peer_2)
215
205
  }
216
206
 
217
- CALL {
218
- WITH rel, peer_2, branch, branch_level, deleted_time
207
+ CALL (rel, peer_2, branch, branch_level, deleted_time) {
219
208
  MATCH (rel)<-[:HAS_SOURCE]-(peer_2)
220
209
  MERGE (rel)<-[:HAS_SOURCE {status: "deleted", branch: branch, branch_level: branch_level, from: deleted_time}]-(peer_2)
221
210
  }
@@ -33,8 +33,7 @@ WHERE num_duplicate_edges > 1
33
33
  // -------------------
34
34
  WITH DISTINCT a, branch, branch_level, status, from, to, attr_val, attr_default
35
35
  WITH attr_val, attr_default, collect([a, branch, branch_level, status, from, to]) AS details_list
36
- CALL {
37
- WITH attr_val, attr_default
36
+ CALL (attr_val, attr_default) {
38
37
  MATCH (av:AttributeValue {value: attr_val, is_default: attr_default})
39
38
  RETURN av AS the_one_av
40
39
  ORDER by %(id_func)s(av) ASC
@@ -53,11 +52,10 @@ WITH a, branch, status, from, to, attr_val, attr_default, %(id_func)s(fresh_e) A
53
52
  // -------------------
54
53
  // get the identical edges for a given set of Attribute node, edge properties, AttributeValue.value
55
54
  // -------------------
56
- CALL {
55
+ CALL (a, branch, status, from, to, attr_val, attr_default, e_id_to_keep) {
57
56
  // -------------------
58
57
  // delete the duplicate edges a given set of Attribute node, edge properties, AttributeValue.value
59
58
  // -------------------
60
- WITH a, branch, status, from, to, attr_val, attr_default, e_id_to_keep
61
59
  MATCH (a)-[e:HAS_VALUE]->(av:AttributeValue {value: attr_val, is_default: attr_default})
62
60
  WHERE %(id_func)s(e) <> e_id_to_keep
63
61
  AND e.branch = branch AND e.status = status AND e.from = from
@@ -99,8 +97,7 @@ WITH DISTINCT a, branch, branch_level, status, from, to, b
99
97
  CREATE (a)-[fresh_e:%(edge_type)s {branch: branch, branch_level: branch_level, status: status, from: from}]->(b)
100
98
  SET fresh_e.to = to
101
99
  WITH a, branch, status, from, to, b, %(id_func)s(fresh_e) AS e_id_to_keep
102
- CALL {
103
- WITH a, branch, status, from, to, b, e_id_to_keep
100
+ CALL (a, branch, status, from, to, b, e_id_to_keep) {
104
101
  MATCH (a)-[e:%(edge_type)s]->(b)
105
102
  WHERE %(id_func)s(e) <> e_id_to_keep
106
103
  AND e.branch = branch AND e.status = status AND e.from = from
@@ -24,8 +24,7 @@ class SetMissingHierarchyQuery(Query):
24
24
  WITH r.default_branch AS default_branch
25
25
  MATCH (n:Node)-[main_e:IS_RELATED {branch: default_branch}]-(rel:Relationship)
26
26
  WHERE main_e.hierarchy IS NULL
27
- CALL {
28
- WITH n, main_e, rel
27
+ CALL (n, main_e, rel) {
29
28
  MATCH (n)-[branch_e:IS_RELATED]-(rel)
30
29
  WHERE branch_e.hierarchy IS NOT NULL
31
30
  AND branch_e.branch <> main_e.branch
@@ -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
@@ -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:Root)<-[r1:IS_PART_OF]-(n)
67
66
  OPTIONAL MATCH (n)-[r2:HAS_ATTRIBUTE]-(:Attribute { name: $attr_name })
68
67
  WHERE all(r in [r1, r2] WHERE (%(branch_filter)s))
@@ -126,8 +126,7 @@ class AttributeRenameQuery(Query):
126
126
 
127
127
  add_uuid = db.render_uuid_generation(node_label="new_attr", node_attr="uuid")
128
128
  query = """
129
- CALL {
130
- WITH node
129
+ CALL (node) {
131
130
  MATCH (root:Root)<-[r:IS_PART_OF]-(node)
132
131
  WHERE %(branch_filter)s
133
132
  RETURN node as n1, r as r1
@@ -137,8 +136,7 @@ class AttributeRenameQuery(Query):
137
136
  WITH n1 as active_node, r1 as rb
138
137
  WHERE rb.status = "active"
139
138
  // Find all the attributes that need to be updated
140
- CALL {
141
- WITH active_node
139
+ CALL (active_node) {
142
140
  MATCH (active_node)-[r:HAS_ATTRIBUTE]-(attr:Attribute { name: $prev_attr.name })
143
141
  WHERE %(branch_filter)s
144
142
  RETURN active_node as n1, r as r1, attr as attr1
@@ -151,8 +149,7 @@ class AttributeRenameQuery(Query):
151
149
  %(add_uuid)s
152
150
  WITH active_attr, new_attr
153
151
  MATCH (active_attr)-[]-(peer)
154
- CALL {
155
- WITH active_attr, peer
152
+ CALL (active_attr, peer) {
156
153
  MATCH (active_attr)-[r]-(peer)
157
154
  WHERE %(branch_filter)s
158
155
  RETURN active_attr as a1, r as r1, peer as p1
@@ -116,8 +116,7 @@ class DeleteElementInSchemaQuery(Query):
116
116
 
117
117
  # ruff: noqa: E501
118
118
  query = """
119
- CALL {
120
- WITH attr_node
119
+ CALL (attr_node) {
121
120
  MATCH (root:Root)<-[r:IS_PART_OF]-(attr_node)
122
121
  WHERE %(branch_filter)s
123
122
  RETURN attr_node as n1, r as r1
@@ -130,8 +129,7 @@ class DeleteElementInSchemaQuery(Query):
130
129
 
131
130
  // Process Outbound Relationship
132
131
  MATCH (element_to_delete)-[]->(peer)
133
- CALL {
134
- WITH element_to_delete, peer
132
+ CALL (element_to_delete, peer) {
135
133
  MATCH (element_to_delete)-[r]->(peer)
136
134
  WHERE %(branch_filter)s
137
135
  RETURN element_to_delete as n1, r as rel_outband1, peer as p1
@@ -150,8 +148,7 @@ class DeleteElementInSchemaQuery(Query):
150
148
  WITH DISTINCT(element_to_delete) AS element_to_delete
151
149
  // Process Inbound Relationship
152
150
  MATCH (element_to_delete)<-[]-(peer)
153
- CALL {
154
- WITH element_to_delete, peer
151
+ CALL (element_to_delete, peer) {
155
152
  MATCH (element_to_delete)<-[r]-(peer)
156
153
  WHERE %(branch_filter)s
157
154
  RETURN element_to_delete as n1, r as rel_inband1, peer as p1