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/diff/model/path.py
CHANGED
|
@@ -81,6 +81,21 @@ def deserialize_tracking_id(tracking_id_str: str) -> TrackingId:
|
|
|
81
81
|
raise ValueError(f"{tracking_id_str} is not a valid TrackingId")
|
|
82
82
|
|
|
83
83
|
|
|
84
|
+
@dataclass
|
|
85
|
+
class NodeIdentifier:
|
|
86
|
+
"""Uniquely identifying nodes that have had their kind or inheritance updated requires all of these fields"""
|
|
87
|
+
|
|
88
|
+
uuid: str
|
|
89
|
+
kind: str
|
|
90
|
+
db_id: str
|
|
91
|
+
|
|
92
|
+
def __hash__(self) -> int:
|
|
93
|
+
return hash(f"{self.uuid}:{self.kind}:{self.db_id}")
|
|
94
|
+
|
|
95
|
+
def __str__(self) -> str:
|
|
96
|
+
return f"{self.kind} '{self.uuid}' ({self.db_id})"
|
|
97
|
+
|
|
98
|
+
|
|
84
99
|
@dataclass
|
|
85
100
|
class NodeDiffFieldSummary:
|
|
86
101
|
kind: str
|
|
@@ -307,18 +322,26 @@ class ParentNodeInfo:
|
|
|
307
322
|
|
|
308
323
|
@dataclass
|
|
309
324
|
class EnrichedDiffNode(BaseSummary):
|
|
310
|
-
|
|
311
|
-
kind: str
|
|
325
|
+
identifier: NodeIdentifier
|
|
312
326
|
label: str
|
|
313
327
|
path_identifier: str = field(default="", kw_only=True)
|
|
314
328
|
changed_at: Timestamp | None = field(default=None, kw_only=True)
|
|
315
329
|
action: DiffAction
|
|
330
|
+
is_node_kind_migration: bool = field(default=False)
|
|
316
331
|
conflict: EnrichedDiffConflict | None = field(default=None)
|
|
317
332
|
attributes: set[EnrichedDiffAttribute] = field(default_factory=set)
|
|
318
333
|
relationships: set[EnrichedDiffRelationship] = field(default_factory=set)
|
|
319
334
|
|
|
320
335
|
def __hash__(self) -> int:
|
|
321
|
-
return hash(self.
|
|
336
|
+
return hash(self.identifier)
|
|
337
|
+
|
|
338
|
+
@property
|
|
339
|
+
def uuid(self) -> str:
|
|
340
|
+
return self.identifier.uuid
|
|
341
|
+
|
|
342
|
+
@property
|
|
343
|
+
def kind(self) -> str:
|
|
344
|
+
return self.identifier.kind
|
|
322
345
|
|
|
323
346
|
@property
|
|
324
347
|
def num_properties(self) -> int:
|
|
@@ -402,11 +425,11 @@ class EnrichedDiffNode(BaseSummary):
|
|
|
402
425
|
@classmethod
|
|
403
426
|
def from_calculated_node(cls, calculated_node: DiffNode) -> EnrichedDiffNode:
|
|
404
427
|
return EnrichedDiffNode(
|
|
405
|
-
|
|
406
|
-
kind=calculated_node.kind,
|
|
428
|
+
identifier=calculated_node.identifier,
|
|
407
429
|
label="",
|
|
408
430
|
changed_at=calculated_node.changed_at,
|
|
409
431
|
action=calculated_node.action,
|
|
432
|
+
is_node_kind_migration=calculated_node.is_node_kind_migration,
|
|
410
433
|
attributes={
|
|
411
434
|
EnrichedDiffAttribute.from_calculated_attribute(calculated_attribute=attr)
|
|
412
435
|
for attr in calculated_node.attributes
|
|
@@ -473,24 +496,24 @@ class EnrichedDiffRoot(EnrichedDiffRootMetadata):
|
|
|
473
496
|
nodes_with_parent_uuids |= {child_n.uuid for child_n in r.nodes}
|
|
474
497
|
return {node for node in self.nodes if node.uuid not in nodes_with_parent_uuids}
|
|
475
498
|
|
|
476
|
-
def get_node(self,
|
|
499
|
+
def get_node(self, node_identifier: NodeIdentifier) -> EnrichedDiffNode:
|
|
477
500
|
for n in self.nodes:
|
|
478
|
-
if n.
|
|
501
|
+
if n.identifier == node_identifier:
|
|
479
502
|
return n
|
|
480
|
-
raise ValueError(f"No node {
|
|
503
|
+
raise ValueError(f"No node {node_identifier} in diff root")
|
|
481
504
|
|
|
482
|
-
def has_node(self,
|
|
505
|
+
def has_node(self, node_identifier: NodeIdentifier) -> bool:
|
|
483
506
|
try:
|
|
484
|
-
self.get_node(
|
|
507
|
+
self.get_node(node_identifier=node_identifier)
|
|
485
508
|
return True
|
|
486
509
|
except ValueError:
|
|
487
510
|
return False
|
|
488
511
|
|
|
489
|
-
def get_node_map(self, node_uuids: set[str] | None = None) -> dict[
|
|
512
|
+
def get_node_map(self, node_uuids: set[str] | None = None) -> dict[NodeIdentifier, EnrichedDiffNode]:
|
|
490
513
|
node_map = {}
|
|
491
514
|
for node in self.nodes:
|
|
492
|
-
if node_uuids is None or node.uuid in node_uuids:
|
|
493
|
-
node_map[node.
|
|
515
|
+
if node_uuids is None or node.identifier.uuid in node_uuids:
|
|
516
|
+
node_map[node.identifier] = node
|
|
494
517
|
return node_map
|
|
495
518
|
|
|
496
519
|
def get_all_conflicts(self) -> dict[str, EnrichedDiffConflict]:
|
|
@@ -522,49 +545,6 @@ class EnrichedDiffRoot(EnrichedDiffRootMetadata):
|
|
|
522
545
|
nodes={EnrichedDiffNode.from_calculated_node(calculated_node=n) for n in calculated_diff.nodes},
|
|
523
546
|
)
|
|
524
547
|
|
|
525
|
-
def add_parent(
|
|
526
|
-
self,
|
|
527
|
-
node_id: str,
|
|
528
|
-
parent_id: str,
|
|
529
|
-
parent_kind: str,
|
|
530
|
-
parent_label: str,
|
|
531
|
-
parent_rel_name: str,
|
|
532
|
-
parent_rel_identifier: str,
|
|
533
|
-
parent_rel_cardinality: RelationshipCardinality,
|
|
534
|
-
parent_rel_label: str = "",
|
|
535
|
-
) -> EnrichedDiffNode:
|
|
536
|
-
node = self.get_node(node_uuid=node_id)
|
|
537
|
-
if not self.has_node(node_uuid=parent_id):
|
|
538
|
-
parent = EnrichedDiffNode(
|
|
539
|
-
uuid=parent_id,
|
|
540
|
-
kind=parent_kind,
|
|
541
|
-
label=parent_label,
|
|
542
|
-
action=DiffAction.UNCHANGED,
|
|
543
|
-
changed_at=None,
|
|
544
|
-
)
|
|
545
|
-
self.nodes.add(parent)
|
|
546
|
-
|
|
547
|
-
else:
|
|
548
|
-
parent = self.get_node(node_uuid=parent_id)
|
|
549
|
-
|
|
550
|
-
if node.has_relationship(name=parent_rel_name):
|
|
551
|
-
rel = node.get_relationship(name=parent_rel_name)
|
|
552
|
-
rel.nodes.add(parent)
|
|
553
|
-
else:
|
|
554
|
-
node.relationships.add(
|
|
555
|
-
EnrichedDiffRelationship(
|
|
556
|
-
name=parent_rel_name,
|
|
557
|
-
identifier=parent_rel_identifier,
|
|
558
|
-
label=parent_rel_label,
|
|
559
|
-
cardinality=parent_rel_cardinality,
|
|
560
|
-
changed_at=None,
|
|
561
|
-
action=DiffAction.UNCHANGED,
|
|
562
|
-
nodes={parent},
|
|
563
|
-
)
|
|
564
|
-
)
|
|
565
|
-
|
|
566
|
-
return parent
|
|
567
|
-
|
|
568
548
|
|
|
569
549
|
@dataclass
|
|
570
550
|
class EnrichedDiffsMetadata:
|
|
@@ -650,6 +630,14 @@ class EnrichedDiffs(EnrichedDiffsMetadata):
|
|
|
650
630
|
def branch_node_uuids(self) -> set[str]:
|
|
651
631
|
return {n.uuid for n in self.diff_branch_diff.nodes}
|
|
652
632
|
|
|
633
|
+
@property
|
|
634
|
+
def base_node_identifiers(self) -> set[NodeIdentifier]:
|
|
635
|
+
return {n.identifier for n in self.base_branch_diff.nodes}
|
|
636
|
+
|
|
637
|
+
@property
|
|
638
|
+
def branch_node_identifiers(self) -> set[NodeIdentifier]:
|
|
639
|
+
return {n.identifier for n in self.diff_branch_diff.nodes}
|
|
640
|
+
|
|
653
641
|
|
|
654
642
|
@dataclass
|
|
655
643
|
class CalculatedDiffs:
|
|
@@ -697,13 +685,21 @@ class DiffRelationship:
|
|
|
697
685
|
|
|
698
686
|
@dataclass
|
|
699
687
|
class DiffNode:
|
|
700
|
-
|
|
701
|
-
kind: str
|
|
688
|
+
identifier: NodeIdentifier
|
|
702
689
|
changed_at: Timestamp
|
|
703
690
|
action: DiffAction
|
|
691
|
+
is_node_kind_migration: bool = field(default=False)
|
|
704
692
|
attributes: list[DiffAttribute] = field(default_factory=list)
|
|
705
693
|
relationships: list[DiffRelationship] = field(default_factory=list)
|
|
706
694
|
|
|
695
|
+
@property
|
|
696
|
+
def uuid(self) -> str:
|
|
697
|
+
return self.identifier.uuid
|
|
698
|
+
|
|
699
|
+
@property
|
|
700
|
+
def kind(self) -> str:
|
|
701
|
+
return self.identifier.kind
|
|
702
|
+
|
|
707
703
|
|
|
708
704
|
@dataclass
|
|
709
705
|
class DiffRoot:
|
|
@@ -780,6 +776,10 @@ class DatabasePath:
|
|
|
780
776
|
def node_db_id(self) -> str:
|
|
781
777
|
return self.node_node.element_id
|
|
782
778
|
|
|
779
|
+
@property
|
|
780
|
+
def node_labels(self) -> frozenset[str]:
|
|
781
|
+
return self.node_node.labels
|
|
782
|
+
|
|
783
783
|
@property
|
|
784
784
|
def node_kind(self) -> str:
|
|
785
785
|
return str(self.node_node.get("kind"))
|
|
@@ -2,14 +2,13 @@ from dataclasses import dataclass, field
|
|
|
2
2
|
|
|
3
3
|
from infrahub.core.constants import DiffAction, RelationshipCardinality
|
|
4
4
|
|
|
5
|
-
from .model.path import EnrichedDiffNode, EnrichedDiffRelationship, EnrichedDiffRoot
|
|
5
|
+
from .model.path import EnrichedDiffNode, EnrichedDiffRelationship, EnrichedDiffRoot, NodeIdentifier
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
@dataclass
|
|
9
9
|
class ParentNodeAddRequest:
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
parent_kind: str
|
|
10
|
+
node_identifier: NodeIdentifier
|
|
11
|
+
parent_identifier: NodeIdentifier
|
|
13
12
|
parent_label: str
|
|
14
13
|
parent_rel_name: str
|
|
15
14
|
parent_rel_identifier: str
|
|
@@ -20,7 +19,7 @@ class ParentNodeAddRequest:
|
|
|
20
19
|
class DiffParentNodeAdder:
|
|
21
20
|
def __init__(self) -> None:
|
|
22
21
|
self._diff_root: EnrichedDiffRoot | None = None
|
|
23
|
-
self._node_map: dict[
|
|
22
|
+
self._node_map: dict[NodeIdentifier, EnrichedDiffNode] = {}
|
|
24
23
|
|
|
25
24
|
def initialize(self, enriched_diff_root: EnrichedDiffRoot) -> None:
|
|
26
25
|
self._diff_root = enriched_diff_root
|
|
@@ -31,33 +30,32 @@ class DiffParentNodeAdder:
|
|
|
31
30
|
raise RuntimeError("Must call initialize before using")
|
|
32
31
|
return self._diff_root
|
|
33
32
|
|
|
34
|
-
def get_node(self,
|
|
35
|
-
return self._node_map[
|
|
33
|
+
def get_node(self, identifier: NodeIdentifier) -> EnrichedDiffNode:
|
|
34
|
+
return self._node_map[identifier]
|
|
36
35
|
|
|
37
|
-
def has_node(self,
|
|
38
|
-
return
|
|
36
|
+
def has_node(self, identifier: NodeIdentifier) -> bool:
|
|
37
|
+
return identifier in self._node_map
|
|
39
38
|
|
|
40
39
|
def add_node(self, node: EnrichedDiffNode) -> None:
|
|
41
|
-
if node.
|
|
40
|
+
if node.identifier in self._node_map:
|
|
42
41
|
return
|
|
43
|
-
self._node_map[node.
|
|
42
|
+
self._node_map[node.identifier] = node
|
|
44
43
|
self.get_root().nodes.add(node)
|
|
45
44
|
|
|
46
45
|
def add_parent(self, parent_request: ParentNodeAddRequest) -> EnrichedDiffNode:
|
|
47
46
|
if not self._diff_root:
|
|
48
47
|
raise RuntimeError("Must call initialize before using")
|
|
49
|
-
node = self.get_node(
|
|
50
|
-
if not self.has_node(
|
|
48
|
+
node = self.get_node(identifier=parent_request.node_identifier)
|
|
49
|
+
if not self.has_node(identifier=parent_request.parent_identifier):
|
|
51
50
|
parent = EnrichedDiffNode(
|
|
52
|
-
|
|
53
|
-
kind=parent_request.parent_kind,
|
|
51
|
+
identifier=parent_request.parent_identifier,
|
|
54
52
|
label=parent_request.parent_label,
|
|
55
53
|
action=DiffAction.UNCHANGED,
|
|
56
54
|
changed_at=None,
|
|
57
55
|
)
|
|
58
56
|
self.add_node(parent)
|
|
59
57
|
else:
|
|
60
|
-
parent = self.get_node(
|
|
58
|
+
parent = self.get_node(identifier=parent_request.parent_identifier)
|
|
61
59
|
|
|
62
60
|
try:
|
|
63
61
|
rel = node.get_relationship(name=parent_request.parent_rel_name)
|
|
@@ -37,22 +37,18 @@ AND (
|
|
|
37
37
|
($diff_id IS NOT NULL AND root.uuid = $diff_id)
|
|
38
38
|
OR ($tracking_id IS NOT NULL AND root.tracking_id = $tracking_id AND root.diff_branch = $diff_branch_name)
|
|
39
39
|
)
|
|
40
|
-
CALL {
|
|
41
|
-
WITH root
|
|
40
|
+
CALL (root) {
|
|
42
41
|
MATCH (root)-[:DIFF_HAS_NODE]->(node:DiffNode)-[:DIFF_HAS_CONFLICT]->(node_conflict:DiffConflict)
|
|
43
42
|
RETURN node.path_identifier AS path_identifier, node_conflict AS conflict
|
|
44
43
|
UNION
|
|
45
|
-
WITH root
|
|
46
44
|
MATCH (root)-[:DIFF_HAS_NODE]->(node:DiffNode)-[:DIFF_HAS_ATTRIBUTE]->(:DiffAttribute)
|
|
47
45
|
-[:DIFF_HAS_PROPERTY]->(property:DiffProperty)-[:DIFF_HAS_CONFLICT]->(attr_property_conflict:DiffConflict)
|
|
48
46
|
RETURN property.path_identifier AS path_identifier, attr_property_conflict AS conflict
|
|
49
47
|
UNION
|
|
50
|
-
WITH root
|
|
51
48
|
MATCH (root)-[:DIFF_HAS_NODE]->(node:DiffNode)-[:DIFF_HAS_RELATIONSHIP]->(:DiffRelationship)
|
|
52
49
|
-[:DIFF_HAS_ELEMENT]->(element:DiffRelationshipElement)-[:DIFF_HAS_CONFLICT]->(rel_element_conflict:DiffConflict)
|
|
53
50
|
RETURN element.path_identifier AS path_identifier, rel_element_conflict AS conflict
|
|
54
51
|
UNION
|
|
55
|
-
WITH root
|
|
56
52
|
MATCH (root)-[:DIFF_HAS_NODE]->(node:DiffNode)-[:DIFF_HAS_RELATIONSHIP]->(:DiffRelationship)
|
|
57
53
|
-[:DIFF_HAS_ELEMENT]->(:DiffRelationshipElement)-[:DIFF_HAS_PROPERTY]->(property:DiffProperty)
|
|
58
54
|
-[:DIFF_HAS_CONFLICT]->(rel_property_conflict:DiffConflict)
|
|
@@ -40,8 +40,7 @@ class ArtifactDiffQuery(Query):
|
|
|
40
40
|
// -----------------------
|
|
41
41
|
MATCH (source_artifact:%(artifact_kind)s)-[r:IS_PART_OF]->(:Root)
|
|
42
42
|
WHERE r.branch IN [$source_branch_name, $target_branch_name]
|
|
43
|
-
CALL {
|
|
44
|
-
WITH source_artifact
|
|
43
|
+
CALL (source_artifact) {
|
|
45
44
|
MATCH (source_artifact)-[r:IS_PART_OF]->(:Root)
|
|
46
45
|
WHERE %(source_branch_filter)s
|
|
47
46
|
RETURN r AS root_rel
|
|
@@ -50,13 +49,11 @@ CALL {
|
|
|
50
49
|
}
|
|
51
50
|
WITH source_artifact, root_rel
|
|
52
51
|
WHERE root_rel.status = "active"
|
|
53
|
-
CALL {
|
|
54
|
-
WITH source_artifact
|
|
52
|
+
CALL (source_artifact) {
|
|
55
53
|
// -----------------------
|
|
56
54
|
// get the artifact's target node
|
|
57
55
|
// -----------------------
|
|
58
|
-
CALL {
|
|
59
|
-
WITH source_artifact
|
|
56
|
+
CALL (source_artifact) {
|
|
60
57
|
OPTIONAL MATCH (source_artifact)-[rrel1:IS_RELATED]-(rel_node:Relationship)-[rrel2:IS_RELATED]-(target_node:Node)
|
|
61
58
|
WHERE rel_node.name = $target_rel_identifier
|
|
62
59
|
AND all(r IN [rrel1, rrel2] WHERE ( %(source_branch_filter)s ))
|
|
@@ -70,8 +67,7 @@ CALL {
|
|
|
70
67
|
// -----------------------
|
|
71
68
|
// get the artifact's definition node
|
|
72
69
|
// -----------------------
|
|
73
|
-
CALL {
|
|
74
|
-
WITH source_artifact
|
|
70
|
+
CALL (source_artifact) {
|
|
75
71
|
OPTIONAL MATCH (source_artifact)-[rrel1:IS_RELATED]-(rel_node:Relationship)-[rrel2:IS_RELATED]-(definition_node:Node)
|
|
76
72
|
WHERE rel_node.name = $definition_rel_identifier
|
|
77
73
|
AND all(r IN [rrel1, rrel2] WHERE ( %(source_branch_filter)s ))
|
|
@@ -85,8 +81,7 @@ CALL {
|
|
|
85
81
|
// -----------------------
|
|
86
82
|
// get the artifact's checksum
|
|
87
83
|
// -----------------------
|
|
88
|
-
CALL {
|
|
89
|
-
WITH source_artifact
|
|
84
|
+
CALL (source_artifact) {
|
|
90
85
|
OPTIONAL MATCH (source_artifact)-[attr_rel:HAS_ATTRIBUTE]->(attr:Attribute)-[value_rel:HAS_VALUE]->(attr_val:AttributeValue)
|
|
91
86
|
WHERE attr.name = "checksum"
|
|
92
87
|
AND all(r IN [attr_rel, value_rel] WHERE ( %(source_branch_filter)s ))
|
|
@@ -100,8 +95,7 @@ CALL {
|
|
|
100
95
|
// -----------------------
|
|
101
96
|
// get the artifact's storage_id
|
|
102
97
|
// -----------------------
|
|
103
|
-
CALL {
|
|
104
|
-
WITH source_artifact
|
|
98
|
+
CALL (source_artifact) {
|
|
105
99
|
OPTIONAL MATCH (source_artifact)-[attr_rel:HAS_ATTRIBUTE]->(attr:Attribute)-[value_rel:HAS_VALUE]->(attr_val:AttributeValue)
|
|
106
100
|
WHERE attr.name = "storage_id"
|
|
107
101
|
AND all(r IN [attr_rel, value_rel] WHERE ( %(source_branch_filter)s ))
|
|
@@ -137,13 +131,11 @@ CALL {
|
|
|
137
131
|
ELSE NULL
|
|
138
132
|
END AS source_storage_id
|
|
139
133
|
}
|
|
140
|
-
CALL {
|
|
134
|
+
CALL (target_node, definition_node){
|
|
141
135
|
// -----------------------
|
|
142
136
|
// get the corresponding artifact on the target branch, if it exists
|
|
143
137
|
// -----------------------
|
|
144
|
-
|
|
145
|
-
CALL {
|
|
146
|
-
WITH target_node, definition_node
|
|
138
|
+
CALL (target_node, definition_node) {
|
|
147
139
|
OPTIONAL MATCH path = (target_node)-[trel1:IS_RELATED]-(trel_node:Relationship)-[trel2:IS_RELATED]-
|
|
148
140
|
(target_artifact:%(artifact_kind)s)-[drel1:IS_RELATED]-(drel_node:Relationship)-[drel2:IS_RELATED]-(definition_node)
|
|
149
141
|
WHERE trel_node.name = $target_rel_identifier
|
|
@@ -165,8 +157,7 @@ CALL {
|
|
|
165
157
|
// -----------------------
|
|
166
158
|
// get the artifact's checksum on target branch
|
|
167
159
|
// -----------------------
|
|
168
|
-
CALL {
|
|
169
|
-
WITH target_artifact
|
|
160
|
+
CALL (target_artifact) {
|
|
170
161
|
OPTIONAL MATCH (target_artifact)-[attr_rel:HAS_ATTRIBUTE]->(attr:Attribute)-[value_rel:HAS_VALUE]->(attr_val:AttributeValue)
|
|
171
162
|
WHERE attr.name = "checksum"
|
|
172
163
|
AND attr_rel.branch = $target_branch_name
|
|
@@ -178,8 +169,7 @@ CALL {
|
|
|
178
169
|
// -----------------------
|
|
179
170
|
// get the artifact's storage_id on target branch
|
|
180
171
|
// -----------------------
|
|
181
|
-
CALL {
|
|
182
|
-
WITH target_artifact
|
|
172
|
+
CALL (target_artifact) {
|
|
183
173
|
OPTIONAL MATCH (target_artifact)-[attr_rel:HAS_ATTRIBUTE]->(attr:Attribute)-[value_rel:HAS_VALUE]->(attr_val:AttributeValue)
|
|
184
174
|
WHERE attr.name = "storage_id"
|
|
185
175
|
AND attr_rel.branch = $target_branch_name
|
|
@@ -96,8 +96,7 @@ class EnrichedDiffGetQuery(Query):
|
|
|
96
96
|
// -------------------------------------
|
|
97
97
|
// Retrieve Parents
|
|
98
98
|
// -------------------------------------
|
|
99
|
-
CALL {
|
|
100
|
-
WITH diff_node
|
|
99
|
+
CALL (diff_node) {
|
|
101
100
|
OPTIONAL MATCH parents_path = (diff_node)-[:DIFF_HAS_RELATIONSHIP|DIFF_HAS_NODE*1..%(max_depth)s]->(:DiffNode)
|
|
102
101
|
RETURN parents_path
|
|
103
102
|
ORDER BY size(nodes(parents_path)) DESC
|
|
@@ -112,8 +111,7 @@ class EnrichedDiffGetQuery(Query):
|
|
|
112
111
|
// -------------------------------------
|
|
113
112
|
// Retrieve Attributes
|
|
114
113
|
// -------------------------------------
|
|
115
|
-
CALL {
|
|
116
|
-
WITH diff_node
|
|
114
|
+
CALL (diff_node) {
|
|
117
115
|
OPTIONAL MATCH (diff_node)-[:DIFF_HAS_ATTRIBUTE]->(diff_attribute:DiffAttribute)
|
|
118
116
|
WITH diff_attribute
|
|
119
117
|
OPTIONAL MATCH (diff_attribute)-[:DIFF_HAS_PROPERTY]->(diff_attr_property:DiffProperty)
|
|
@@ -126,8 +124,7 @@ class EnrichedDiffGetQuery(Query):
|
|
|
126
124
|
// -------------------------------------
|
|
127
125
|
// Retrieve Relationships
|
|
128
126
|
// -------------------------------------
|
|
129
|
-
CALL {
|
|
130
|
-
WITH diff_node
|
|
127
|
+
CALL (diff_node) {
|
|
131
128
|
OPTIONAL MATCH (diff_node)-[:DIFF_HAS_RELATIONSHIP]->(diff_relationship:DiffRelationship)
|
|
132
129
|
WITH diff_relationship
|
|
133
130
|
OPTIONAL MATCH (diff_relationship)-[:DIFF_HAS_ELEMENT]->(diff_rel_element:DiffRelationshipElement)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from infrahub.core.diff.model.path import NodeIdentifier
|
|
4
|
+
from infrahub.core.query import Query, QueryType
|
|
5
|
+
from infrahub.database import InfrahubDatabase
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class EnrichedDiffDropNodesQuery(Query):
|
|
9
|
+
name = "enriched_diff_drop_nodes"
|
|
10
|
+
type = QueryType.WRITE
|
|
11
|
+
insert_return = False
|
|
12
|
+
|
|
13
|
+
def __init__(self, enriched_diff_uuid: str, node_identifiers: list[NodeIdentifier], **kwargs: Any) -> None:
|
|
14
|
+
super().__init__(**kwargs)
|
|
15
|
+
self.enriched_diff_uuid = enriched_diff_uuid
|
|
16
|
+
self.node_identifiers = node_identifiers
|
|
17
|
+
|
|
18
|
+
async def query_init(self, db: InfrahubDatabase, **kwargs: Any) -> None: # noqa: ARG002
|
|
19
|
+
self.params = {
|
|
20
|
+
"diff_root_uuid": self.enriched_diff_uuid,
|
|
21
|
+
"node_uuids": [ni.uuid for ni in self.node_identifiers],
|
|
22
|
+
"node_identifiers_map": {ni.uuid: ni.kind for ni in self.node_identifiers},
|
|
23
|
+
}
|
|
24
|
+
query = """
|
|
25
|
+
MATCH (d_root:DiffRoot {uuid: $diff_root_uuid})
|
|
26
|
+
MATCH (d_root)-[:DIFF_HAS_NODE]->(dn:DiffNode)
|
|
27
|
+
WHERE dn.uuid IN $node_uuids
|
|
28
|
+
AND dn.kind IN $node_identifiers_map[dn.uuid]
|
|
29
|
+
OPTIONAL MATCH (dn)-[:DIFF_HAS_ATTRIBUTE]-(da:DiffAttribute)
|
|
30
|
+
OPTIONAL MATCH (da)-[*]->(diff_thing)
|
|
31
|
+
DETACH DELETE diff_thing
|
|
32
|
+
DETACH DELETE da
|
|
33
|
+
WITH dn
|
|
34
|
+
OPTIONAL MATCH (dn)-[:DIFF_HAS_RELATIONSHIP]->(dr:DiffRelationship)
|
|
35
|
+
OPTIONAL MATCH (dr)-[:DIFF_HAS_ELEMENT]->(dre:DiffRelationshipElement)
|
|
36
|
+
OPTIONAL MATCH (dre)-[*]->(diff_thing)
|
|
37
|
+
DETACH DELETE diff_thing
|
|
38
|
+
DETACH DELETE dre
|
|
39
|
+
DETACH DELETE dr
|
|
40
|
+
DETACH DELETE dn
|
|
41
|
+
"""
|
|
42
|
+
self.add_to_query(query=query)
|
|
@@ -18,20 +18,21 @@ class EnrichedDiffFieldSpecifiersQuery(Query):
|
|
|
18
18
|
CALL {
|
|
19
19
|
MATCH (root:DiffRoot {uuid: $diff_id})-[:DIFF_HAS_NODE]->(node:DiffNode)-[:DIFF_HAS_ATTRIBUTE]->(attr:DiffAttribute)
|
|
20
20
|
WHERE (root.is_merged IS NULL OR root.is_merged <> TRUE)
|
|
21
|
-
RETURN node.uuid AS node_uuid, attr.name AS field_name
|
|
21
|
+
RETURN node.uuid AS node_uuid, node.kind AS node_kind, attr.name AS field_name
|
|
22
22
|
UNION
|
|
23
23
|
MATCH (root:DiffRoot {uuid: $diff_id})-[:DIFF_HAS_NODE]->(node:DiffNode)-[:DIFF_HAS_RELATIONSHIP]->(rel:DiffRelationship)
|
|
24
24
|
WHERE (root.is_merged IS NULL OR root.is_merged <> TRUE)
|
|
25
|
-
RETURN node.uuid AS node_uuid, rel.identifier AS field_name
|
|
25
|
+
RETURN node.uuid AS node_uuid, node.kind AS node_kind, rel.identifier AS field_name
|
|
26
26
|
}
|
|
27
27
|
"""
|
|
28
28
|
self.add_to_query(query=query)
|
|
29
|
-
self.return_labels = ["node_uuid", "field_name"]
|
|
30
|
-
self.order_by = ["node_uuid", "field_name"]
|
|
29
|
+
self.return_labels = ["node_uuid", "node_kind", "field_name"]
|
|
30
|
+
self.order_by = ["node_uuid", "node_kind", "field_name"]
|
|
31
31
|
|
|
32
|
-
def get_node_field_specifier_tuples(self) -> Generator[tuple[str, str], None, None]:
|
|
32
|
+
def get_node_field_specifier_tuples(self) -> Generator[tuple[str, str, str], None, None]:
|
|
33
33
|
for result in self.get_results():
|
|
34
34
|
node_uuid = result.get_as_str("node_uuid")
|
|
35
|
+
node_kind = result.get_as_str("node_kind")
|
|
35
36
|
field_name = result.get_as_str("field_name")
|
|
36
|
-
if node_uuid and field_name:
|
|
37
|
-
yield (node_uuid, field_name)
|
|
37
|
+
if node_uuid and node_kind and field_name:
|
|
38
|
+
yield (node_uuid, node_kind, field_name)
|
|
@@ -45,8 +45,7 @@ class EnrichedDiffNodeFieldSummaryQuery(Query):
|
|
|
45
45
|
OPTIONAL MATCH (diff_root)-[:DIFF_HAS_NODE]->(n:DiffNode)
|
|
46
46
|
WHERE n.action <> $unchanged_str
|
|
47
47
|
WITH DISTINCT n.kind AS kind
|
|
48
|
-
CALL {
|
|
49
|
-
WITH kind
|
|
48
|
+
CALL (kind) {
|
|
50
49
|
OPTIONAL MATCH (n:DiffNode {kind: kind})-[:DIFF_HAS_ATTRIBUTE]->(a:DiffAttribute)
|
|
51
50
|
WHERE n.action <> $unchanged_str
|
|
52
51
|
AND a.action <> $unchanged_str
|
|
@@ -54,8 +53,7 @@ class EnrichedDiffNodeFieldSummaryQuery(Query):
|
|
|
54
53
|
RETURN collect(attr_name) AS attr_names
|
|
55
54
|
}
|
|
56
55
|
WITH kind, attr_names
|
|
57
|
-
CALL {
|
|
58
|
-
WITH kind
|
|
56
|
+
CALL (kind) {
|
|
59
57
|
OPTIONAL MATCH (n:DiffNode {kind: kind})-[:DIFF_HAS_RELATIONSHIP]->(r:DiffRelationship)
|
|
60
58
|
WHERE n.action <> $unchanged_str
|
|
61
59
|
AND r.action <> $unchanged_str
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
from collections import defaultdict
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
1
4
|
from pydantic import BaseModel, Field
|
|
2
5
|
|
|
3
6
|
from infrahub.core.constants import DiffAction
|
|
7
|
+
from infrahub.core.diff.model.path import NodeIdentifier
|
|
4
8
|
from infrahub.core.query.utils import filter_and, filter_or
|
|
5
9
|
|
|
6
10
|
|
|
@@ -29,6 +33,7 @@ class IncExclActionFilterOptions(BaseModel):
|
|
|
29
33
|
class EnrichedDiffQueryFilters(BaseModel):
|
|
30
34
|
ids: list[str] = Field(default_factory=list)
|
|
31
35
|
kind: IncExclFilterOptions = IncExclFilterOptions()
|
|
36
|
+
identifiers: list[NodeIdentifier] = Field(default_factory=list)
|
|
32
37
|
namespace: IncExclFilterOptions = IncExclFilterOptions()
|
|
33
38
|
status: IncExclActionFilterOptions = IncExclActionFilterOptions()
|
|
34
39
|
only_conflicted: bool = Field(default=False)
|
|
@@ -37,6 +42,7 @@ class EnrichedDiffQueryFilters(BaseModel):
|
|
|
37
42
|
def is_empty(self) -> bool:
|
|
38
43
|
if (
|
|
39
44
|
not self.ids
|
|
45
|
+
and not self.identifiers
|
|
40
46
|
and self.only_conflicted is False
|
|
41
47
|
and self.kind.is_empty
|
|
42
48
|
and self.namespace.is_empty
|
|
@@ -48,12 +54,20 @@ class EnrichedDiffQueryFilters(BaseModel):
|
|
|
48
54
|
def generate(self) -> tuple[str, dict]:
|
|
49
55
|
default_filter = ""
|
|
50
56
|
|
|
51
|
-
params = {}
|
|
57
|
+
params: dict[str, Any] = {}
|
|
52
58
|
|
|
53
59
|
if self.ids:
|
|
54
60
|
params["ids"] = self.ids
|
|
55
61
|
return "diff_node.uuid in $ids", params
|
|
56
62
|
|
|
63
|
+
if self.identifiers:
|
|
64
|
+
params["ids"] = [n.uuid for n in self.identifiers]
|
|
65
|
+
id_kind_map: dict[str, list[str]] = defaultdict(list)
|
|
66
|
+
for node_identifier in self.identifiers:
|
|
67
|
+
id_kind_map[node_identifier.uuid].append(node_identifier.kind)
|
|
68
|
+
params["id_kind_map"] = id_kind_map
|
|
69
|
+
return "diff_node.uuid in $ids AND diff_node.kind IN $id_kind_map[diff_node.uuid]", params
|
|
70
|
+
|
|
57
71
|
filters_list = []
|
|
58
72
|
|
|
59
73
|
if self.is_empty:
|