infrahub-server 1.2.9rc0__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.
- infrahub/actions/constants.py +86 -0
- infrahub/actions/gather.py +114 -0
- infrahub/actions/models.py +241 -0
- infrahub/actions/parsers.py +104 -0
- infrahub/actions/schema.py +382 -0
- infrahub/actions/tasks.py +126 -0
- infrahub/actions/triggers.py +21 -0
- infrahub/cli/db.py +1 -2
- infrahub/computed_attribute/models.py +13 -0
- infrahub/computed_attribute/tasks.py +48 -26
- infrahub/config.py +9 -0
- infrahub/core/account.py +24 -47
- infrahub/core/attribute.py +53 -14
- infrahub/core/branch/models.py +8 -9
- infrahub/core/branch/tasks.py +0 -2
- infrahub/core/constants/infrahubkind.py +8 -0
- infrahub/core/constraint/node/runner.py +1 -1
- infrahub/core/convert_object_type/__init__.py +0 -0
- infrahub/core/convert_object_type/conversion.py +122 -0
- infrahub/core/convert_object_type/schema_mapping.py +56 -0
- infrahub/core/diff/calculator.py +65 -11
- infrahub/core/diff/combiner.py +38 -31
- infrahub/core/diff/coordinator.py +44 -28
- infrahub/core/diff/data_check_synchronizer.py +3 -2
- infrahub/core/diff/enricher/hierarchy.py +36 -27
- infrahub/core/diff/ipam_diff_parser.py +5 -4
- infrahub/core/diff/merger/merger.py +46 -16
- infrahub/core/diff/merger/serializer.py +1 -0
- infrahub/core/diff/model/field_specifiers_map.py +64 -0
- infrahub/core/diff/model/path.py +58 -58
- infrahub/core/diff/parent_node_adder.py +14 -16
- infrahub/core/diff/query/all_conflicts.py +1 -5
- infrahub/core/diff/query/artifact.py +10 -20
- infrahub/core/diff/query/diff_get.py +3 -6
- infrahub/core/diff/query/drop_nodes.py +42 -0
- infrahub/core/diff/query/field_specifiers.py +8 -7
- infrahub/core/diff/query/field_summary.py +2 -4
- infrahub/core/diff/query/filters.py +15 -1
- infrahub/core/diff/query/merge.py +284 -101
- infrahub/core/diff/query/save.py +26 -34
- infrahub/core/diff/query/summary_counts_enricher.py +34 -54
- infrahub/core/diff/query_parser.py +55 -65
- infrahub/core/diff/repository/deserializer.py +38 -24
- infrahub/core/diff/repository/repository.py +31 -12
- infrahub/core/diff/tasks.py +3 -3
- infrahub/core/graph/__init__.py +1 -1
- infrahub/core/manager.py +14 -11
- infrahub/core/migrations/graph/__init__.py +2 -0
- infrahub/core/migrations/graph/m003_relationship_parent_optional.py +1 -2
- infrahub/core/migrations/graph/m013_convert_git_password_credential.py +2 -4
- infrahub/core/migrations/graph/m019_restore_rels_to_time.py +11 -22
- infrahub/core/migrations/graph/m020_duplicate_edges.py +3 -6
- infrahub/core/migrations/graph/m021_missing_hierarchy_merge.py +1 -2
- infrahub/core/migrations/graph/m024_missing_hierarchy_backfill.py +1 -2
- infrahub/core/migrations/graph/m027_delete_isolated_nodes.py +50 -0
- infrahub/core/migrations/graph/m028_delete_diffs.py +38 -0
- infrahub/core/migrations/query/attribute_add.py +1 -2
- infrahub/core/migrations/query/attribute_rename.py +3 -6
- infrahub/core/migrations/query/delete_element_in_schema.py +3 -6
- infrahub/core/migrations/query/node_duplicate.py +3 -6
- infrahub/core/migrations/query/relationship_duplicate.py +3 -6
- infrahub/core/migrations/schema/node_attribute_remove.py +3 -6
- infrahub/core/migrations/schema/node_remove.py +3 -6
- infrahub/core/models.py +29 -2
- infrahub/core/node/__init__.py +18 -4
- infrahub/core/node/create.py +211 -0
- infrahub/core/protocols.py +51 -0
- infrahub/core/protocols_base.py +3 -0
- infrahub/core/query/__init__.py +2 -2
- infrahub/core/query/branch.py +27 -17
- infrahub/core/query/diff.py +186 -81
- infrahub/core/query/ipam.py +10 -20
- infrahub/core/query/node.py +65 -49
- infrahub/core/query/relationship.py +156 -58
- infrahub/core/query/resource_manager.py +1 -2
- infrahub/core/query/subquery.py +4 -6
- infrahub/core/relationship/model.py +4 -1
- infrahub/core/schema/__init__.py +2 -1
- infrahub/core/schema/attribute_parameters.py +36 -0
- infrahub/core/schema/attribute_schema.py +83 -8
- infrahub/core/schema/basenode_schema.py +25 -1
- infrahub/core/schema/definitions/core/__init__.py +21 -0
- infrahub/core/schema/definitions/internal.py +13 -3
- infrahub/core/schema/generated/attribute_schema.py +9 -3
- infrahub/core/schema/schema_branch.py +15 -7
- infrahub/core/validators/__init__.py +5 -1
- infrahub/core/validators/attribute/choices.py +1 -2
- infrahub/core/validators/attribute/enum.py +1 -2
- infrahub/core/validators/attribute/kind.py +1 -2
- infrahub/core/validators/attribute/length.py +13 -6
- infrahub/core/validators/attribute/optional.py +1 -2
- infrahub/core/validators/attribute/regex.py +5 -5
- infrahub/core/validators/attribute/unique.py +1 -3
- infrahub/core/validators/determiner.py +18 -2
- infrahub/core/validators/enum.py +7 -0
- infrahub/core/validators/node/hierarchy.py +3 -6
- infrahub/core/validators/query.py +1 -3
- infrahub/core/validators/relationship/count.py +6 -12
- infrahub/core/validators/relationship/optional.py +2 -4
- infrahub/core/validators/relationship/peer.py +3 -8
- infrahub/core/validators/tasks.py +1 -1
- infrahub/core/validators/uniqueness/query.py +12 -9
- infrahub/database/__init__.py +1 -3
- infrahub/events/group_action.py +1 -0
- infrahub/graphql/analyzer.py +139 -18
- infrahub/graphql/app.py +1 -1
- infrahub/graphql/loaders/node.py +1 -1
- infrahub/graphql/loaders/peers.py +1 -1
- infrahub/graphql/manager.py +4 -0
- infrahub/graphql/mutations/action.py +164 -0
- infrahub/graphql/mutations/convert_object_type.py +62 -0
- infrahub/graphql/mutations/main.py +24 -175
- infrahub/graphql/mutations/proposed_change.py +21 -18
- infrahub/graphql/queries/convert_object_type_mapping.py +36 -0
- infrahub/graphql/queries/diff/tree.py +2 -1
- infrahub/graphql/queries/relationship.py +1 -1
- infrahub/graphql/resolvers/many_relationship.py +4 -4
- infrahub/graphql/resolvers/resolver.py +4 -4
- infrahub/graphql/resolvers/single_relationship.py +2 -2
- infrahub/graphql/schema.py +6 -0
- infrahub/graphql/subscription/graphql_query.py +2 -2
- infrahub/graphql/types/branch.py +1 -1
- infrahub/menu/menu.py +31 -0
- infrahub/message_bus/messages/__init__.py +0 -10
- infrahub/message_bus/operations/__init__.py +0 -8
- infrahub/message_bus/operations/refresh/registry.py +1 -1
- infrahub/patch/queries/consolidate_duplicated_nodes.py +3 -6
- infrahub/patch/queries/delete_duplicated_edges.py +5 -10
- infrahub/prefect_server/models.py +1 -19
- infrahub/proposed_change/models.py +68 -3
- infrahub/proposed_change/tasks.py +907 -30
- infrahub/task_manager/models.py +10 -6
- infrahub/telemetry/database.py +1 -1
- infrahub/telemetry/tasks.py +1 -1
- infrahub/trigger/catalogue.py +2 -0
- infrahub/trigger/models.py +29 -3
- infrahub/trigger/setup.py +51 -15
- infrahub/trigger/tasks.py +4 -5
- infrahub/types.py +1 -1
- infrahub/webhook/models.py +2 -1
- infrahub/workflows/catalogue.py +85 -0
- infrahub/workflows/initialization.py +1 -3
- infrahub_sdk/timestamp.py +2 -2
- {infrahub_server-1.2.9rc0.dist-info → infrahub_server-1.3.0a0.dist-info}/METADATA +4 -4
- {infrahub_server-1.2.9rc0.dist-info → infrahub_server-1.3.0a0.dist-info}/RECORD +153 -146
- infrahub_testcontainers/container.py +0 -1
- infrahub_testcontainers/docker-compose.test.yml +4 -4
- infrahub_testcontainers/helpers.py +8 -2
- infrahub_testcontainers/performance_test.py +6 -3
- infrahub/message_bus/messages/check_generator_run.py +0 -26
- infrahub/message_bus/messages/finalize_validator_execution.py +0 -15
- infrahub/message_bus/messages/proposed_change/base_with_diff.py +0 -16
- infrahub/message_bus/messages/proposed_change/request_proposedchange_refreshartifacts.py +0 -11
- infrahub/message_bus/messages/request_generatordefinition_check.py +0 -20
- infrahub/message_bus/messages/request_proposedchange_pipeline.py +0 -23
- infrahub/message_bus/operations/check/__init__.py +0 -3
- infrahub/message_bus/operations/check/generator.py +0 -156
- infrahub/message_bus/operations/finalize/__init__.py +0 -3
- infrahub/message_bus/operations/finalize/validator.py +0 -133
- infrahub/message_bus/operations/requests/__init__.py +0 -9
- infrahub/message_bus/operations/requests/generator_definition.py +0 -140
- infrahub/message_bus/operations/requests/proposed_change.py +0 -629
- /infrahub/{message_bus/messages/proposed_change → actions}/__init__.py +0 -0
- {infrahub_server-1.2.9rc0.dist-info → infrahub_server-1.3.0a0.dist-info}/LICENSE.txt +0 -0
- {infrahub_server-1.2.9rc0.dist-info → infrahub_server-1.3.0a0.dist-info}/WHEEL +0 -0
- {infrahub_server-1.2.9rc0.dist-info → infrahub_server-1.3.0a0.dist-info}/entry_points.txt +0 -0
infrahub/core/query/diff.py
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Generator
|
|
4
5
|
|
|
5
6
|
from infrahub import config
|
|
6
|
-
from infrahub.core.constants import GLOBAL_BRANCH_NAME, BranchSupportType
|
|
7
|
+
from infrahub.core.constants import GLOBAL_BRANCH_NAME, BranchSupportType, DiffAction, RelationshipStatus
|
|
7
8
|
from infrahub.core.query import Query, QueryType
|
|
8
9
|
from infrahub.core.timestamp import Timestamp
|
|
9
10
|
|
|
10
11
|
if TYPE_CHECKING:
|
|
11
12
|
from infrahub.core.branch import Branch
|
|
13
|
+
from infrahub.core.diff.model.field_specifiers_map import NodeFieldSpecifierMap
|
|
12
14
|
from infrahub.database import InfrahubDatabase
|
|
13
15
|
|
|
14
16
|
|
|
@@ -106,8 +108,8 @@ class DiffCalculationQuery(DiffQuery):
|
|
|
106
108
|
self,
|
|
107
109
|
base_branch: Branch,
|
|
108
110
|
diff_branch_from_time: Timestamp,
|
|
109
|
-
current_node_field_specifiers:
|
|
110
|
-
new_node_field_specifiers:
|
|
111
|
+
current_node_field_specifiers: NodeFieldSpecifierMap | None = None,
|
|
112
|
+
new_node_field_specifiers: NodeFieldSpecifierMap | None = None,
|
|
111
113
|
**kwargs: Any,
|
|
112
114
|
):
|
|
113
115
|
self.base_branch = base_branch
|
|
@@ -119,20 +121,20 @@ class DiffCalculationQuery(DiffQuery):
|
|
|
119
121
|
|
|
120
122
|
previous_base_path_query = """
|
|
121
123
|
WITH DISTINCT diff_path AS diff_path, has_more_data
|
|
122
|
-
CALL {
|
|
123
|
-
WITH diff_path
|
|
124
|
-
WITH
|
|
125
|
-
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
|
|
126
127
|
// -------------------------------------
|
|
127
128
|
// add base branch paths before branched_from, if they exist
|
|
128
129
|
// -------------------------------------
|
|
129
130
|
WITH n, attr_rel, r_node, r_prop
|
|
131
|
+
// 'base_n' instead of 'n' here to get previous value for node with a migrated kind/inheritance
|
|
130
132
|
OPTIONAL MATCH latest_base_path = (:Root)<-[base_r_root:IS_PART_OF {branch: $base_branch_name}]
|
|
131
|
-
-(n)-[base_r_node {branch: $base_branch_name}]
|
|
133
|
+
-(base_n {uuid: n.uuid})-[base_r_node {branch: $base_branch_name}]
|
|
132
134
|
-(attr_rel)-[base_r_prop {branch: $base_branch_name}]->(base_prop)
|
|
133
135
|
WHERE type(base_r_node) = type(r_node)
|
|
134
136
|
AND type(base_r_prop) = type(r_prop)
|
|
135
|
-
AND [%(id_func)s(
|
|
137
|
+
AND [%(id_func)s(base_n), type(base_r_node)] <> [%(id_func)s(base_prop), type(base_r_prop)]
|
|
136
138
|
AND all(
|
|
137
139
|
r in relationships(latest_base_path)
|
|
138
140
|
WHERE r.from < $branch_from_time
|
|
@@ -142,7 +144,7 @@ CALL {
|
|
|
142
144
|
// the migration leaves two nodes with the same UUID linked to the same Relationship
|
|
143
145
|
// ------------------------
|
|
144
146
|
AND (
|
|
145
|
-
|
|
147
|
+
base_n.uuid IS NULL OR base_prop.uuid IS NULL OR base_n.uuid <> base_prop.uuid
|
|
146
148
|
OR type(base_r_node) <> "IS_RELATED" OR type(base_r_prop) <> "IS_RELATED"
|
|
147
149
|
)
|
|
148
150
|
WITH latest_base_path, base_r_root, base_r_node, base_r_prop
|
|
@@ -155,10 +157,9 @@ CALL {
|
|
|
155
157
|
WITH diff_path, latest_base_path, has_more_data
|
|
156
158
|
UNWIND [diff_path, latest_base_path] AS penultimate_path
|
|
157
159
|
WITH DISTINCT penultimate_path, has_more_data
|
|
158
|
-
CALL {
|
|
159
|
-
WITH penultimate_path
|
|
160
|
-
WITH
|
|
161
|
-
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
|
|
162
163
|
// -------------------------------------
|
|
163
164
|
// Add peer-side of any relationships to get the peer's ID
|
|
164
165
|
// -------------------------------------
|
|
@@ -198,6 +199,13 @@ WITH reduce(
|
|
|
198
199
|
diff_rel_paths = [], item IN [penultimate_path, peer_path] |
|
|
199
200
|
CASE WHEN item IS NULL THEN diff_rel_paths ELSE diff_rel_paths + [item] END
|
|
200
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
|
|
201
209
|
"""
|
|
202
210
|
|
|
203
211
|
def get_previous_base_path_query(self, db: InfrahubDatabase) -> str:
|
|
@@ -231,10 +239,10 @@ class DiffNodePathsQuery(DiffCalculationQuery):
|
|
|
231
239
|
self.params.update(params_dict)
|
|
232
240
|
self.params.update(
|
|
233
241
|
{
|
|
234
|
-
"new_node_ids_list":
|
|
242
|
+
"new_node_ids_list": self.new_node_field_specifiers.get_uuids_list()
|
|
235
243
|
if self.new_node_field_specifiers
|
|
236
244
|
else None,
|
|
237
|
-
"current_node_ids_list":
|
|
245
|
+
"current_node_ids_list": self.current_node_field_specifiers.get_uuids_list()
|
|
238
246
|
if self.current_node_field_specifiers
|
|
239
247
|
else None,
|
|
240
248
|
}
|
|
@@ -276,7 +284,7 @@ WITH p, q, diff_rel, CASE
|
|
|
276
284
|
WHEN $new_node_ids_list IS NOT NULL AND p.uuid IN $new_node_ids_list THEN $branch_from_time
|
|
277
285
|
ELSE $from_time
|
|
278
286
|
END AS row_from_time
|
|
279
|
-
ORDER BY p
|
|
287
|
+
ORDER BY %(id_func)s(p) DESC
|
|
280
288
|
SKIP $offset
|
|
281
289
|
LIMIT $limit
|
|
282
290
|
// -------------------------------------
|
|
@@ -289,8 +297,7 @@ WITH one_result[0] AS p, one_result[1] AS q, one_result[2] AS diff_rel, one_resu
|
|
|
289
297
|
// -------------------------------------
|
|
290
298
|
// Exclude nodes added then removed on branch within timeframe
|
|
291
299
|
// -------------------------------------
|
|
292
|
-
CALL {
|
|
293
|
-
WITH p, q, row_from_time
|
|
300
|
+
CALL (p, q, row_from_time) {
|
|
294
301
|
OPTIONAL MATCH (q)<-[is_part_of:IS_PART_OF {branch: $branch_name}]-(p)
|
|
295
302
|
WHERE row_from_time <= is_part_of.from < $to_time
|
|
296
303
|
WITH DISTINCT is_part_of.status AS rel_status
|
|
@@ -302,8 +309,7 @@ WHERE intra_branch_update = FALSE
|
|
|
302
309
|
// -------------------------------------
|
|
303
310
|
// Get every path on this branch under each node
|
|
304
311
|
// -------------------------------------
|
|
305
|
-
CALL {
|
|
306
|
-
WITH p, q, diff_rel, row_from_time
|
|
312
|
+
CALL (p, q, diff_rel, row_from_time) {
|
|
307
313
|
OPTIONAL MATCH path = (
|
|
308
314
|
(q)<-[top_diff_rel:IS_PART_OF]-(p)-[r_node]-(node)-[r_prop]-(prop)
|
|
309
315
|
)
|
|
@@ -313,15 +319,15 @@ CALL {
|
|
|
313
319
|
AND node.branch_support IN [$branch_aware, $branch_agnostic]
|
|
314
320
|
AND type(r_prop) IN ["IS_VISIBLE", "IS_PROTECTED", "HAS_SOURCE", "HAS_OWNER", "HAS_VALUE", "IS_RELATED"]
|
|
315
321
|
AND any(l in labels(prop) WHERE l in ["Boolean", "Node", "AttributeValue"])
|
|
316
|
-
AND ALL(
|
|
317
|
-
r in [r_node, r_prop]
|
|
318
|
-
WHERE r.from < $to_time AND r.branch = top_diff_rel.branch
|
|
319
|
-
)
|
|
320
322
|
AND (top_diff_rel.to IS NULL OR top_diff_rel.to >= r_node.from)
|
|
321
323
|
AND (r_node.to IS NULL OR r_node.to >= r_prop.from)
|
|
322
324
|
AND [%(id_func)s(p), type(r_node)] <> [%(id_func)s(prop), type(r_prop)]
|
|
323
|
-
AND
|
|
324
|
-
AND
|
|
325
|
+
AND r_node.from < $to_time
|
|
326
|
+
AND r_node.branch = top_diff_rel.branch
|
|
327
|
+
AND r_node.status = top_diff_rel.status
|
|
328
|
+
AND r_prop.from < $to_time
|
|
329
|
+
AND r_prop.branch = top_diff_rel.branch
|
|
330
|
+
AND r_prop.status = top_diff_rel.status
|
|
325
331
|
// ------------------------
|
|
326
332
|
// special handling for nodes that had their kind updated,
|
|
327
333
|
// the migration leaves two nodes with the same UUID linked to the same Relationship
|
|
@@ -330,12 +336,11 @@ CALL {
|
|
|
330
336
|
p.uuid IS NULL OR prop.uuid IS NULL OR p.uuid <> prop.uuid
|
|
331
337
|
OR type(r_node) <> "IS_RELATED" OR type(r_prop) <> "IS_RELATED"
|
|
332
338
|
)
|
|
333
|
-
WITH path,
|
|
339
|
+
WITH path, node, prop, r_prop, r_node, type(r_node) AS rel_type, row_from_time
|
|
334
340
|
// -------------------------------------
|
|
335
341
|
// Exclude attributes/relationships added then removed on branch within timeframe
|
|
336
342
|
// -------------------------------------
|
|
337
|
-
CALL {
|
|
338
|
-
WITH p, rel_type, node, row_from_time
|
|
343
|
+
CALL (p, rel_type, node, row_from_time) {
|
|
339
344
|
OPTIONAL MATCH (p)-[rel_to_check {branch: $branch_name}]-(node)
|
|
340
345
|
WHERE row_from_time <= rel_to_check.from < $to_time
|
|
341
346
|
AND type(rel_to_check) = rel_type
|
|
@@ -371,15 +376,16 @@ class DiffFieldPathsQuery(DiffCalculationQuery):
|
|
|
371
376
|
|
|
372
377
|
self.params.update(
|
|
373
378
|
{
|
|
374
|
-
"
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
379
|
+
"current_node_ids_list": self.current_node_field_specifiers.get_uuids_list()
|
|
380
|
+
if self.current_node_field_specifiers
|
|
381
|
+
else None,
|
|
382
|
+
"new_node_ids_list": self.new_node_field_specifiers.get_uuids_list()
|
|
383
|
+
if self.new_node_field_specifiers
|
|
384
|
+
else None,
|
|
385
|
+
"current_node_field_specifiers_map": self.current_node_field_specifiers.get_uuid_field_names_map()
|
|
378
386
|
if self.current_node_field_specifiers is not None
|
|
379
387
|
else None,
|
|
380
|
-
"new_node_field_specifiers_map":
|
|
381
|
-
node_uuid: list(field_names) for node_uuid, field_names in self.new_node_field_specifiers.items()
|
|
382
|
-
}
|
|
388
|
+
"new_node_field_specifiers_map": self.new_node_field_specifiers.get_uuid_field_names_map()
|
|
383
389
|
if self.new_node_field_specifiers is not None
|
|
384
390
|
else None,
|
|
385
391
|
}
|
|
@@ -400,16 +406,16 @@ AND (r_root.to IS NULL OR diff_rel.branch <> r_root.branch OR r_root.to >= diff_
|
|
|
400
406
|
// node ID and field name filtering first pass
|
|
401
407
|
AND (
|
|
402
408
|
(
|
|
403
|
-
$
|
|
404
|
-
AND
|
|
409
|
+
$current_node_ids_list IS NOT NULL
|
|
410
|
+
AND p.uuid IN $current_node_ids_list
|
|
405
411
|
AND q.name IN $current_node_field_specifiers_map[p.uuid]
|
|
406
412
|
) OR (
|
|
407
|
-
$
|
|
408
|
-
AND
|
|
413
|
+
$new_node_ids_list IS NOT NULL
|
|
414
|
+
AND p.uuid IN $new_node_ids_list
|
|
409
415
|
AND q.name IN $new_node_field_specifiers_map[p.uuid]
|
|
410
416
|
) OR (
|
|
411
|
-
$
|
|
412
|
-
AND $
|
|
417
|
+
$new_node_ids_list IS NULL
|
|
418
|
+
AND $current_node_ids_list IS NULL
|
|
413
419
|
)
|
|
414
420
|
)
|
|
415
421
|
// node ID and field name filtering second pass
|
|
@@ -417,8 +423,12 @@ AND (
|
|
|
417
423
|
// time-based filters for nodes already included in the diff or fresh changes
|
|
418
424
|
(
|
|
419
425
|
(
|
|
420
|
-
(
|
|
421
|
-
|
|
426
|
+
(
|
|
427
|
+
$current_node_ids_list IS NOT NULL
|
|
428
|
+
AND p.uuid IN $current_node_ids_list
|
|
429
|
+
AND q.name IN $current_node_field_specifiers_map[p.uuid]
|
|
430
|
+
)
|
|
431
|
+
OR ($current_node_ids_list IS NULL AND $new_node_ids_list IS NULL)
|
|
422
432
|
)
|
|
423
433
|
AND (r_root.from < $from_time OR p.branch_support = $branch_agnostic)
|
|
424
434
|
AND (
|
|
@@ -428,7 +438,11 @@ AND (
|
|
|
428
438
|
)
|
|
429
439
|
// time-based filters for new nodes
|
|
430
440
|
OR (
|
|
431
|
-
(
|
|
441
|
+
(
|
|
442
|
+
$new_node_ids_list IS NOT NULL
|
|
443
|
+
AND p.uuid IN $new_node_ids_list
|
|
444
|
+
AND q.name IN $new_node_field_specifiers_map[p.uuid]
|
|
445
|
+
)
|
|
432
446
|
AND (r_root.from < $branch_from_time OR p.branch_support = $branch_agnostic)
|
|
433
447
|
AND (
|
|
434
448
|
($branch_from_time <= diff_rel.from < $to_time AND (diff_rel.to IS NULL OR diff_rel.to > $to_time))
|
|
@@ -454,15 +468,18 @@ WITH one_result[0] AS root, one_result[1] AS r_root, one_result[2] AS p, one_res
|
|
|
454
468
|
// Add correct from_time for row
|
|
455
469
|
// -------------------------------------
|
|
456
470
|
WITH root, r_root, p, diff_rel, q, has_more_data, CASE
|
|
457
|
-
WHEN
|
|
471
|
+
WHEN
|
|
472
|
+
$new_node_ids_list IS NOT NULL
|
|
473
|
+
AND p.uuid IN $new_node_ids_list
|
|
474
|
+
AND q.name IN $new_node_field_specifiers_map[p.uuid]
|
|
475
|
+
THEN $branch_from_time
|
|
458
476
|
ELSE $from_time
|
|
459
477
|
END AS row_from_time
|
|
460
478
|
// -------------------------------------
|
|
461
479
|
// Exclude attributes/relationship under nodes deleted on this branch in the timeframe
|
|
462
480
|
// because those were all handled above at the node level
|
|
463
481
|
// -------------------------------------
|
|
464
|
-
CALL {
|
|
465
|
-
WITH root, p, row_from_time
|
|
482
|
+
CALL (root, p, row_from_time) {
|
|
466
483
|
OPTIONAL MATCH (root)<-[r_root_deleted:IS_PART_OF {branch: $branch_name}]-(p)
|
|
467
484
|
WHERE row_from_time <= r_root_deleted.from < $to_time
|
|
468
485
|
WITH r_root_deleted
|
|
@@ -476,8 +493,7 @@ WHERE node_deleted = FALSE
|
|
|
476
493
|
// Exclude relationships added and deleted within the timeframe
|
|
477
494
|
// -------------------------------------
|
|
478
495
|
WITH root, r_root, p, diff_rel, q, has_more_data, row_from_time, type(diff_rel) AS rel_type
|
|
479
|
-
CALL {
|
|
480
|
-
WITH p, rel_type, q, row_from_time
|
|
496
|
+
CALL (p, rel_type, q, row_from_time) {
|
|
481
497
|
OPTIONAL MATCH (p)-[rel_to_check {branch: $branch_name}]-(q)
|
|
482
498
|
WHERE row_from_time <= rel_to_check.from < $to_time
|
|
483
499
|
AND type(rel_to_check) = rel_type
|
|
@@ -490,8 +506,7 @@ WHERE intra_branch_update = FALSE
|
|
|
490
506
|
// -------------------------------------
|
|
491
507
|
// Get every path on this branch under each attribute/relationship
|
|
492
508
|
// -------------------------------------
|
|
493
|
-
CALL {
|
|
494
|
-
WITH root, r_root, p, diff_rel, q
|
|
509
|
+
CALL (root, r_root, p, diff_rel, q) {
|
|
495
510
|
OPTIONAL MATCH path = (
|
|
496
511
|
(root:Root)<-[mid_r_root:IS_PART_OF]-(p)-[mid_diff_rel]-(q)-[r_prop]-(prop)
|
|
497
512
|
)
|
|
@@ -526,8 +541,7 @@ CALL {
|
|
|
526
541
|
// Exclude properties added and deleted within the timeframe
|
|
527
542
|
// -------------------------------------
|
|
528
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
|
|
529
|
-
CALL {
|
|
530
|
-
WITH q, rel_type, prop, row_from_time
|
|
544
|
+
CALL (q, rel_type, prop, row_from_time) {
|
|
531
545
|
OPTIONAL MATCH (q)-[rel_to_check {branch: $branch_name}]-(prop)
|
|
532
546
|
WHERE row_from_time <= rel_to_check.from < $to_time
|
|
533
547
|
AND type(rel_to_check) = rel_type
|
|
@@ -554,15 +568,16 @@ class DiffPropertyPathsQuery(DiffCalculationQuery):
|
|
|
554
568
|
|
|
555
569
|
self.params.update(
|
|
556
570
|
{
|
|
557
|
-
"
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
571
|
+
"current_node_ids_list": self.current_node_field_specifiers.get_uuids_list()
|
|
572
|
+
if self.current_node_field_specifiers
|
|
573
|
+
else None,
|
|
574
|
+
"new_node_ids_list": self.new_node_field_specifiers.get_uuids_list()
|
|
575
|
+
if self.new_node_field_specifiers
|
|
576
|
+
else None,
|
|
577
|
+
"current_node_field_specifiers_map": self.current_node_field_specifiers.get_uuid_field_names_map()
|
|
561
578
|
if self.current_node_field_specifiers is not None
|
|
562
579
|
else None,
|
|
563
|
-
"new_node_field_specifiers_map":
|
|
564
|
-
node_uuid: list(field_names) for node_uuid, field_names in self.new_node_field_specifiers.items()
|
|
565
|
-
}
|
|
580
|
+
"new_node_field_specifiers_map": self.new_node_field_specifiers.get_uuid_field_names_map()
|
|
566
581
|
if self.new_node_field_specifiers is not None
|
|
567
582
|
else None,
|
|
568
583
|
}
|
|
@@ -580,16 +595,16 @@ AND type(r_node) IN ["HAS_ATTRIBUTE", "IS_RELATED"]
|
|
|
580
595
|
// node ID and field name filtering first pass
|
|
581
596
|
AND (
|
|
582
597
|
(
|
|
583
|
-
$
|
|
584
|
-
AND
|
|
598
|
+
$current_node_ids_list IS NOT NULL
|
|
599
|
+
AND n.uuid IN $current_node_ids_list
|
|
585
600
|
AND p.name IN $current_node_field_specifiers_map[n.uuid]
|
|
586
601
|
) OR (
|
|
587
|
-
$
|
|
588
|
-
AND
|
|
602
|
+
$new_node_ids_list IS NOT NULL
|
|
603
|
+
AND n.uuid IN $new_node_ids_list
|
|
589
604
|
AND p.name IN $new_node_field_specifiers_map[n.uuid]
|
|
590
605
|
) OR (
|
|
591
|
-
$
|
|
592
|
-
AND $
|
|
606
|
+
$new_node_ids_list IS NULL
|
|
607
|
+
AND $current_node_ids_list IS NULL
|
|
593
608
|
)
|
|
594
609
|
)
|
|
595
610
|
// node ID and field name filtering second pass
|
|
@@ -597,8 +612,12 @@ AND (
|
|
|
597
612
|
// time-based filters for nodes already included in the diff or fresh changes
|
|
598
613
|
(
|
|
599
614
|
(
|
|
600
|
-
(
|
|
601
|
-
|
|
615
|
+
(
|
|
616
|
+
$current_node_ids_list IS NOT NULL
|
|
617
|
+
AND n.uuid IN $current_node_ids_list
|
|
618
|
+
AND p.name IN $current_node_field_specifiers_map[n.uuid]
|
|
619
|
+
)
|
|
620
|
+
OR ($current_node_ids_list IS NULL AND $new_node_ids_list IS NULL)
|
|
602
621
|
)
|
|
603
622
|
AND (
|
|
604
623
|
($from_time <= diff_rel.from < $to_time AND (diff_rel.to IS NULL OR diff_rel.to > $to_time))
|
|
@@ -612,7 +631,11 @@ AND (
|
|
|
612
631
|
)
|
|
613
632
|
// time-based filters for new nodes
|
|
614
633
|
OR (
|
|
615
|
-
(
|
|
634
|
+
(
|
|
635
|
+
$new_node_ids_list IS NOT NULL
|
|
636
|
+
AND n.uuid IN $new_node_ids_list
|
|
637
|
+
AND p.name IN $new_node_field_specifiers_map[n.uuid]
|
|
638
|
+
)
|
|
616
639
|
AND (
|
|
617
640
|
($branch_from_time <= diff_rel.from < $to_time AND (diff_rel.to IS NULL OR diff_rel.to > $to_time))
|
|
618
641
|
OR ($branch_from_time <= diff_rel.to < $to_time)
|
|
@@ -667,7 +690,11 @@ WITH one_result[0] AS diff_rel_path, one_result[1] AS r_root, one_result[2] AS n
|
|
|
667
690
|
// Add correct from_time for row
|
|
668
691
|
// -------------------------------------
|
|
669
692
|
WITH diff_rel_path, r_root, n, r_node, p, diff_rel, has_more_data, CASE
|
|
670
|
-
WHEN
|
|
693
|
+
WHEN
|
|
694
|
+
$new_node_ids_list IS NOT NULL
|
|
695
|
+
AND n.uuid IN $new_node_ids_list
|
|
696
|
+
AND p.name IN $new_node_field_specifiers_map[n.uuid]
|
|
697
|
+
THEN $branch_from_time
|
|
671
698
|
ELSE $from_time
|
|
672
699
|
END AS row_from_time
|
|
673
700
|
WITH diff_rel_path, r_root, n, r_node, p, diff_rel, has_more_data, row_from_time
|
|
@@ -681,24 +708,21 @@ ORDER BY
|
|
|
681
708
|
r_node.from DESC,
|
|
682
709
|
r_root.from DESC
|
|
683
710
|
WITH n, p, row_from_time, diff_rel, diff_rel_path, has_more_data
|
|
684
|
-
CALL {
|
|
711
|
+
CALL (n, p, row_from_time){
|
|
685
712
|
// -------------------------------------
|
|
686
713
|
// Exclude properties under nodes and attributes/relationships deleted
|
|
687
714
|
// on this branch in the timeframe because those were all handled above
|
|
688
715
|
// -------------------------------------
|
|
689
|
-
|
|
690
|
-
CALL {
|
|
691
|
-
WITH n, row_from_time
|
|
716
|
+
CALL (n, row_from_time) {
|
|
692
717
|
OPTIONAL MATCH (root:Root)<-[r_root_deleted:IS_PART_OF {branch: $branch_name}]-(n)
|
|
693
|
-
WHERE
|
|
718
|
+
WHERE r_root_deleted.from < $to_time
|
|
694
719
|
WITH r_root_deleted
|
|
695
720
|
ORDER BY r_root_deleted.status DESC
|
|
696
721
|
LIMIT 1
|
|
697
722
|
RETURN COALESCE(r_root_deleted.status = "deleted", FALSE) AS node_deleted
|
|
698
723
|
}
|
|
699
|
-
WITH
|
|
700
|
-
CALL {
|
|
701
|
-
WITH n, p, row_from_time
|
|
724
|
+
WITH node_deleted
|
|
725
|
+
CALL (n, p, row_from_time) {
|
|
702
726
|
OPTIONAL MATCH (n)-[r_node_deleted {branch: $branch_name}]-(p)
|
|
703
727
|
WHERE row_from_time <= r_node_deleted.from < $to_time
|
|
704
728
|
AND type(r_node_deleted) IN ["HAS_ATTRIBUTE", "IS_RELATED"]
|
|
@@ -718,3 +742,84 @@ WITH n, p, type(diff_rel) AS drt, head(collect(diff_rel_path)) AS diff_path, has
|
|
|
718
742
|
self.add_to_query(self.get_relationship_peer_side_query(db=db))
|
|
719
743
|
self.add_to_query("UNWIND diff_rel_paths AS diff_path")
|
|
720
744
|
self.return_labels = ["DISTINCT diff_path AS diff_path", "has_more_data"]
|
|
745
|
+
|
|
746
|
+
|
|
747
|
+
@dataclass
|
|
748
|
+
class MigratedKindNode:
|
|
749
|
+
uuid: str
|
|
750
|
+
kind: str
|
|
751
|
+
db_id: str
|
|
752
|
+
from_time: Timestamp
|
|
753
|
+
action: DiffAction
|
|
754
|
+
has_more_data: bool
|
|
755
|
+
|
|
756
|
+
|
|
757
|
+
class DiffMigratedKindNodesQuery(DiffCalculationQuery):
|
|
758
|
+
name = "diff_migrated_kind_nodes_query"
|
|
759
|
+
|
|
760
|
+
async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None: # noqa: ARG002
|
|
761
|
+
params_dict = self.get_params()
|
|
762
|
+
self.params.update(params_dict)
|
|
763
|
+
migrated_kind_nodes_query = """
|
|
764
|
+
// -------------------------------------
|
|
765
|
+
// Identify nodes added/removed on branch in the time frame
|
|
766
|
+
// -------------------------------------
|
|
767
|
+
MATCH (:Root)<-[diff_rel:IS_PART_OF {branch: $branch_name}]-(n:Node)
|
|
768
|
+
WHERE (
|
|
769
|
+
($from_time <= diff_rel.from < $to_time AND (diff_rel.to IS NULL OR diff_rel.to > $to_time))
|
|
770
|
+
OR ($from_time <= diff_rel.to < $to_time)
|
|
771
|
+
)
|
|
772
|
+
AND n.branch_support = $branch_aware
|
|
773
|
+
WITH DISTINCT n.uuid AS node_uuid, %(id_func)s(n) AS db_id
|
|
774
|
+
WITH node_uuid, count(*) AS num_nodes_with_uuid
|
|
775
|
+
WHERE num_nodes_with_uuid > 1
|
|
776
|
+
// -------------------------------------
|
|
777
|
+
// Limit the number of nodes
|
|
778
|
+
// -------------------------------------
|
|
779
|
+
WITH node_uuid
|
|
780
|
+
ORDER BY node_uuid
|
|
781
|
+
SKIP $offset
|
|
782
|
+
LIMIT $limit
|
|
783
|
+
WITH collect(node_uuid) AS node_uuids
|
|
784
|
+
WITH node_uuids, size(node_uuids) = $limit AS has_more_data
|
|
785
|
+
MATCH (:Root)<-[diff_rel:IS_PART_OF {branch: $branch_name}]-(n:Node)
|
|
786
|
+
WHERE n.uuid IN node_uuids
|
|
787
|
+
AND (
|
|
788
|
+
($from_time <= diff_rel.from < $to_time AND (diff_rel.to IS NULL OR diff_rel.to > $to_time))
|
|
789
|
+
OR ($from_time <= diff_rel.to < $to_time)
|
|
790
|
+
)
|
|
791
|
+
// -------------------------------------
|
|
792
|
+
// Ignore node created and deleted on this branch
|
|
793
|
+
// -------------------------------------
|
|
794
|
+
CALL (n) {
|
|
795
|
+
OPTIONAL MATCH (:Root)<-[diff_rel:IS_PART_OF {branch: $branch_name}]-(n)
|
|
796
|
+
WITH diff_rel
|
|
797
|
+
ORDER BY diff_rel.from ASC
|
|
798
|
+
WITH collect(diff_rel.status) AS statuses
|
|
799
|
+
RETURN statuses = ["active", "deleted"] AS intra_branch_update
|
|
800
|
+
}
|
|
801
|
+
WITH n.uuid AS uuid, n.kind AS kind, %(id_func)s(n) AS db_id, diff_rel.from_time AS from_time, diff_rel.status AS status, has_more_data
|
|
802
|
+
WHERE intra_branch_update = FALSE
|
|
803
|
+
""" % {"id_func": db.get_id_function_name()}
|
|
804
|
+
self.add_to_query(query=migrated_kind_nodes_query)
|
|
805
|
+
self.return_labels = [
|
|
806
|
+
"uuid",
|
|
807
|
+
"kind",
|
|
808
|
+
"db_id",
|
|
809
|
+
"from_time",
|
|
810
|
+
"status",
|
|
811
|
+
"has_more_data",
|
|
812
|
+
]
|
|
813
|
+
|
|
814
|
+
def get_migrated_kind_nodes(self) -> Generator[MigratedKindNode, None, None]:
|
|
815
|
+
for result in self.get_results():
|
|
816
|
+
yield MigratedKindNode(
|
|
817
|
+
uuid=result.get_as_type("uuid", return_type=str),
|
|
818
|
+
kind=result.get_as_type("kind", return_type=str),
|
|
819
|
+
db_id=result.get_as_type("db_id", return_type=str),
|
|
820
|
+
from_time=result.get_as_type("from_time", return_type=Timestamp),
|
|
821
|
+
action=DiffAction.REMOVED
|
|
822
|
+
if result.get_as_type("status", return_type=str).lower() == RelationshipStatus.DELETED.value
|
|
823
|
+
else DiffAction.ADDED,
|
|
824
|
+
has_more_data=result.get_as_type("has_more_data", bool),
|
|
825
|
+
)
|
infrahub/core/query/ipam.py
CHANGED
|
@@ -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 |
|