infrahub-server 1.2.0rc0__py3-none-any.whl → 1.2.1__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/api/dependencies.py +6 -6
- infrahub/api/diff/validation_models.py +7 -7
- infrahub/api/schema.py +1 -1
- infrahub/artifacts/models.py +5 -3
- infrahub/artifacts/tasks.py +3 -5
- infrahub/cli/__init__.py +13 -9
- infrahub/cli/constants.py +3 -0
- infrahub/cli/db.py +165 -183
- infrahub/cli/upgrade.py +146 -0
- infrahub/computed_attribute/gather.py +185 -0
- infrahub/computed_attribute/models.py +240 -12
- infrahub/computed_attribute/tasks.py +77 -441
- infrahub/computed_attribute/triggers.py +13 -47
- infrahub/config.py +43 -32
- infrahub/context.py +14 -0
- infrahub/core/account.py +4 -4
- infrahub/core/attribute.py +58 -58
- infrahub/core/branch/tasks.py +74 -22
- infrahub/core/changelog/diff.py +95 -36
- infrahub/core/changelog/models.py +217 -43
- infrahub/core/constants/__init__.py +28 -0
- infrahub/core/constants/infrahubkind.py +2 -0
- infrahub/core/constants/schema.py +2 -0
- infrahub/core/constraint/node/runner.py +9 -8
- infrahub/core/diff/branch_differ.py +10 -10
- infrahub/core/diff/enricher/cardinality_one.py +5 -0
- infrahub/core/diff/enricher/hierarchy.py +17 -4
- infrahub/core/diff/enricher/labels.py +5 -0
- infrahub/core/diff/enricher/path_identifier.py +4 -0
- infrahub/core/diff/ipam_diff_parser.py +4 -5
- infrahub/core/diff/model/diff.py +27 -27
- infrahub/core/diff/model/path.py +32 -9
- infrahub/core/diff/parent_node_adder.py +78 -0
- infrahub/core/diff/payload_builder.py +13 -2
- infrahub/core/diff/query/filters.py +2 -2
- infrahub/core/diff/query/merge.py +20 -17
- infrahub/core/diff/query/save.py +188 -182
- infrahub/core/diff/query/summary_counts_enricher.py +51 -4
- infrahub/core/diff/query_parser.py +4 -4
- infrahub/core/diff/repository/deserializer.py +8 -3
- infrahub/core/diff/repository/repository.py +156 -38
- infrahub/core/diff/tasks.py +4 -4
- infrahub/core/graph/__init__.py +1 -1
- infrahub/core/graph/index.py +3 -0
- infrahub/core/initialization.py +1 -10
- infrahub/core/ipam/constants.py +3 -4
- infrahub/core/ipam/reconciler.py +12 -12
- infrahub/core/ipam/utilization.py +10 -13
- infrahub/core/manager.py +36 -36
- infrahub/core/merge.py +7 -7
- infrahub/core/migrations/__init__.py +2 -3
- infrahub/core/migrations/graph/__init__.py +12 -3
- infrahub/core/migrations/graph/m017_add_core_profile.py +1 -5
- infrahub/core/migrations/graph/m018_uniqueness_nulls.py +4 -4
- infrahub/core/migrations/graph/m019_restore_rels_to_time.py +256 -0
- infrahub/core/migrations/graph/m020_duplicate_edges.py +160 -0
- infrahub/core/migrations/graph/m021_missing_hierarchy_merge.py +51 -0
- infrahub/core/migrations/graph/m022_add_generate_template_attr.py +48 -0
- infrahub/core/migrations/graph/m023_deduplicate_cardinality_one_relationships.py +96 -0
- infrahub/core/migrations/query/attribute_add.py +2 -2
- infrahub/core/migrations/query/node_duplicate.py +43 -26
- infrahub/core/migrations/query/schema_attribute_update.py +2 -2
- infrahub/core/migrations/schema/models.py +19 -4
- infrahub/core/migrations/schema/node_remove.py +26 -12
- infrahub/core/migrations/schema/tasks.py +2 -2
- infrahub/core/migrations/shared.py +16 -16
- infrahub/core/models.py +15 -6
- infrahub/core/node/__init__.py +43 -39
- infrahub/core/node/base.py +2 -4
- infrahub/core/node/constraints/attribute_uniqueness.py +2 -2
- infrahub/core/node/constraints/grouped_uniqueness.py +99 -47
- infrahub/core/node/constraints/interface.py +1 -2
- infrahub/core/node/delete_validator.py +3 -5
- infrahub/core/node/ipam.py +4 -4
- infrahub/core/node/permissions.py +7 -7
- infrahub/core/node/resource_manager/ip_address_pool.py +6 -6
- infrahub/core/node/resource_manager/ip_prefix_pool.py +6 -6
- infrahub/core/node/resource_manager/number_pool.py +3 -3
- infrahub/core/path.py +12 -12
- infrahub/core/property.py +11 -11
- infrahub/core/protocols.py +7 -0
- infrahub/core/protocols_base.py +21 -21
- infrahub/core/query/__init__.py +33 -33
- infrahub/core/query/attribute.py +6 -4
- infrahub/core/query/diff.py +3 -3
- infrahub/core/query/node.py +82 -32
- infrahub/core/query/relationship.py +228 -40
- infrahub/core/query/resource_manager.py +2 -0
- infrahub/core/query/standard_node.py +3 -3
- infrahub/core/query/subquery.py +9 -9
- infrahub/core/registry.py +13 -15
- infrahub/core/relationship/constraints/count.py +3 -4
- infrahub/core/relationship/constraints/peer_kind.py +3 -4
- infrahub/core/relationship/constraints/profiles_kind.py +2 -2
- infrahub/core/relationship/model.py +51 -59
- infrahub/core/schema/attribute_schema.py +16 -8
- infrahub/core/schema/basenode_schema.py +105 -44
- infrahub/core/schema/computed_attribute.py +3 -3
- infrahub/core/schema/definitions/core/__init__.py +147 -0
- infrahub/core/schema/definitions/core/account.py +171 -0
- infrahub/core/schema/definitions/core/artifact.py +136 -0
- infrahub/core/schema/definitions/core/builtin.py +24 -0
- infrahub/core/schema/definitions/core/check.py +68 -0
- infrahub/core/schema/definitions/core/core.py +17 -0
- infrahub/core/schema/definitions/core/generator.py +100 -0
- infrahub/core/schema/definitions/core/graphql_query.py +79 -0
- infrahub/core/schema/definitions/core/group.py +108 -0
- infrahub/core/schema/definitions/core/ipam.py +193 -0
- infrahub/core/schema/definitions/core/lineage.py +19 -0
- infrahub/core/schema/definitions/core/menu.py +48 -0
- infrahub/core/schema/definitions/core/permission.py +163 -0
- infrahub/core/schema/definitions/core/profile.py +18 -0
- infrahub/core/schema/definitions/core/propose_change.py +97 -0
- infrahub/core/schema/definitions/core/propose_change_comment.py +193 -0
- infrahub/core/schema/definitions/core/propose_change_validator.py +328 -0
- infrahub/core/schema/definitions/core/repository.py +286 -0
- infrahub/core/schema/definitions/core/resource_pool.py +170 -0
- infrahub/core/schema/definitions/core/template.py +27 -0
- infrahub/core/schema/definitions/core/transform.py +96 -0
- infrahub/core/schema/definitions/core/webhook.py +134 -0
- infrahub/core/schema/definitions/internal.py +16 -16
- infrahub/core/schema/dropdown.py +3 -4
- infrahub/core/schema/generated/attribute_schema.py +15 -18
- infrahub/core/schema/generated/base_node_schema.py +12 -14
- infrahub/core/schema/generated/node_schema.py +3 -5
- infrahub/core/schema/generated/relationship_schema.py +9 -11
- infrahub/core/schema/generic_schema.py +2 -2
- infrahub/core/schema/manager.py +20 -9
- infrahub/core/schema/node_schema.py +4 -2
- infrahub/core/schema/relationship_schema.py +14 -6
- infrahub/core/schema/schema_branch.py +292 -144
- infrahub/core/schema/schema_branch_computed.py +41 -4
- infrahub/core/task/task.py +3 -3
- infrahub/core/task/user_task.py +15 -15
- infrahub/core/timestamp.py +3 -3
- infrahub/core/utils.py +20 -18
- infrahub/core/validators/__init__.py +1 -3
- infrahub/core/validators/aggregated_checker.py +2 -2
- infrahub/core/validators/attribute/choices.py +2 -2
- infrahub/core/validators/attribute/enum.py +2 -2
- infrahub/core/validators/attribute/kind.py +2 -2
- infrahub/core/validators/attribute/length.py +2 -2
- infrahub/core/validators/attribute/optional.py +2 -2
- infrahub/core/validators/attribute/regex.py +2 -2
- infrahub/core/validators/attribute/unique.py +2 -2
- infrahub/core/validators/checks_runner.py +25 -2
- infrahub/core/validators/determiner.py +1 -3
- infrahub/core/validators/interface.py +6 -2
- infrahub/core/validators/model.py +22 -3
- infrahub/core/validators/models/validate_migration.py +17 -4
- infrahub/core/validators/node/attribute.py +2 -2
- infrahub/core/validators/node/generate_profile.py +2 -2
- infrahub/core/validators/node/hierarchy.py +3 -5
- infrahub/core/validators/node/inherit_from.py +27 -5
- infrahub/core/validators/node/relationship.py +2 -2
- infrahub/core/validators/relationship/count.py +4 -4
- infrahub/core/validators/relationship/optional.py +2 -2
- infrahub/core/validators/relationship/peer.py +2 -2
- infrahub/core/validators/shared.py +2 -2
- infrahub/core/validators/tasks.py +8 -0
- infrahub/core/validators/uniqueness/checker.py +22 -21
- infrahub/core/validators/uniqueness/index.py +2 -2
- infrahub/core/validators/uniqueness/model.py +11 -11
- infrahub/database/__init__.py +27 -22
- infrahub/database/metrics.py +7 -1
- infrahub/dependencies/builder/constraint/grouped/node_runner.py +1 -3
- infrahub/dependencies/builder/diff/deserializer.py +3 -1
- infrahub/dependencies/builder/diff/enricher/hierarchy.py +3 -1
- infrahub/dependencies/builder/diff/parent_node_adder.py +8 -0
- infrahub/dependencies/component/registry.py +2 -2
- infrahub/events/__init__.py +25 -2
- infrahub/events/artifact_action.py +64 -0
- infrahub/events/branch_action.py +33 -22
- infrahub/events/generator.py +71 -0
- infrahub/events/group_action.py +51 -21
- infrahub/events/models.py +18 -19
- infrahub/events/node_action.py +88 -37
- infrahub/events/repository_action.py +5 -18
- infrahub/events/schema_action.py +4 -9
- infrahub/events/utils.py +16 -0
- infrahub/events/validator_action.py +55 -0
- infrahub/exceptions.py +32 -24
- infrahub/generators/models.py +2 -3
- infrahub/generators/tasks.py +24 -4
- infrahub/git/base.py +7 -7
- infrahub/git/integrator.py +48 -24
- infrahub/git/models.py +101 -9
- infrahub/git/repository.py +3 -3
- infrahub/git/tasks.py +408 -6
- infrahub/git/utils.py +48 -0
- infrahub/git/worktree.py +1 -2
- infrahub/git_credential/askpass.py +1 -2
- infrahub/graphql/analyzer.py +12 -0
- infrahub/graphql/app.py +13 -15
- infrahub/graphql/context.py +39 -0
- infrahub/graphql/initialization.py +3 -0
- infrahub/graphql/loaders/node.py +2 -12
- infrahub/graphql/loaders/peers.py +77 -0
- infrahub/graphql/loaders/shared.py +13 -0
- infrahub/graphql/manager.py +17 -19
- infrahub/graphql/mutations/artifact_definition.py +5 -5
- infrahub/graphql/mutations/branch.py +26 -1
- infrahub/graphql/mutations/computed_attribute.py +9 -5
- infrahub/graphql/mutations/diff.py +23 -11
- infrahub/graphql/mutations/diff_conflict.py +5 -0
- infrahub/graphql/mutations/generator.py +83 -0
- infrahub/graphql/mutations/graphql_query.py +5 -5
- infrahub/graphql/mutations/ipam.py +54 -74
- infrahub/graphql/mutations/main.py +195 -132
- infrahub/graphql/mutations/menu.py +7 -7
- infrahub/graphql/mutations/models.py +2 -4
- infrahub/graphql/mutations/node_getter/by_default_filter.py +10 -10
- infrahub/graphql/mutations/node_getter/by_hfid.py +1 -3
- infrahub/graphql/mutations/node_getter/by_id.py +1 -3
- infrahub/graphql/mutations/node_getter/interface.py +1 -2
- infrahub/graphql/mutations/proposed_change.py +7 -7
- infrahub/graphql/mutations/relationship.py +93 -19
- infrahub/graphql/mutations/repository.py +8 -8
- infrahub/graphql/mutations/resource_manager.py +3 -3
- infrahub/graphql/mutations/schema.py +19 -4
- infrahub/graphql/mutations/webhook.py +137 -0
- infrahub/graphql/parser.py +4 -4
- infrahub/graphql/permissions.py +1 -10
- infrahub/graphql/queries/diff/tree.py +19 -14
- infrahub/graphql/queries/event.py +5 -2
- infrahub/graphql/queries/ipam.py +2 -2
- infrahub/graphql/queries/relationship.py +2 -2
- infrahub/graphql/queries/search.py +2 -2
- infrahub/graphql/resolvers/many_relationship.py +264 -0
- infrahub/graphql/resolvers/resolver.py +13 -110
- infrahub/graphql/schema.py +2 -0
- infrahub/graphql/subscription/graphql_query.py +2 -0
- infrahub/graphql/types/context.py +12 -0
- infrahub/graphql/types/event.py +84 -17
- infrahub/graphql/types/node.py +2 -2
- infrahub/graphql/utils.py +2 -2
- infrahub/groups/ancestors.py +29 -0
- infrahub/groups/parsers.py +107 -0
- infrahub/lock.py +20 -20
- infrahub/menu/constants.py +0 -1
- infrahub/menu/generator.py +9 -21
- infrahub/menu/menu.py +17 -38
- infrahub/menu/models.py +117 -16
- infrahub/menu/repository.py +111 -0
- infrahub/menu/utils.py +5 -8
- infrahub/message_bus/__init__.py +11 -13
- infrahub/message_bus/messages/__init__.py +1 -21
- infrahub/message_bus/messages/check_generator_run.py +3 -3
- infrahub/message_bus/messages/finalize_validator_execution.py +3 -0
- infrahub/message_bus/messages/proposed_change/request_proposedchange_refreshartifacts.py +6 -0
- infrahub/message_bus/messages/request_generatordefinition_check.py +2 -0
- infrahub/message_bus/messages/send_echo_request.py +1 -1
- infrahub/message_bus/operations/__init__.py +1 -10
- infrahub/message_bus/operations/check/__init__.py +2 -2
- infrahub/message_bus/operations/check/generator.py +1 -0
- infrahub/message_bus/operations/event/__init__.py +2 -2
- infrahub/message_bus/operations/event/worker.py +0 -3
- infrahub/message_bus/operations/finalize/validator.py +51 -1
- infrahub/message_bus/operations/requests/__init__.py +0 -2
- infrahub/message_bus/operations/requests/generator_definition.py +21 -23
- infrahub/message_bus/operations/requests/proposed_change.py +14 -10
- infrahub/permissions/globals.py +15 -0
- infrahub/pools/number.py +2 -4
- infrahub/proposed_change/models.py +3 -0
- infrahub/proposed_change/tasks.py +58 -45
- infrahub/pytest_plugin.py +13 -10
- infrahub/server.py +2 -3
- infrahub/services/__init__.py +2 -2
- infrahub/services/adapters/cache/__init__.py +4 -6
- infrahub/services/adapters/cache/nats.py +4 -5
- infrahub/services/adapters/cache/redis.py +3 -7
- infrahub/services/adapters/event/__init__.py +1 -1
- infrahub/services/adapters/message_bus/__init__.py +3 -3
- infrahub/services/adapters/message_bus/local.py +2 -2
- infrahub/services/adapters/message_bus/nats.py +4 -4
- infrahub/services/adapters/message_bus/rabbitmq.py +4 -4
- infrahub/services/adapters/workflow/local.py +2 -2
- infrahub/services/component.py +5 -5
- infrahub/services/protocols.py +7 -7
- infrahub/services/scheduler.py +1 -3
- infrahub/task_manager/event.py +102 -9
- infrahub/task_manager/models.py +27 -7
- infrahub/tasks/artifact.py +7 -6
- infrahub/telemetry/__init__.py +0 -0
- infrahub/telemetry/constants.py +9 -0
- infrahub/telemetry/database.py +86 -0
- infrahub/telemetry/models.py +65 -0
- infrahub/telemetry/task_manager.py +77 -0
- infrahub/{tasks/telemetry.py → telemetry/tasks.py} +49 -56
- infrahub/telemetry/utils.py +11 -0
- infrahub/trace.py +4 -4
- infrahub/transformations/tasks.py +2 -2
- infrahub/trigger/catalogue.py +4 -6
- infrahub/trigger/constants.py +0 -8
- infrahub/trigger/models.py +54 -5
- infrahub/trigger/setup.py +90 -0
- infrahub/trigger/tasks.py +35 -84
- infrahub/utils.py +11 -1
- infrahub/validators/__init__.py +0 -0
- infrahub/validators/events.py +42 -0
- infrahub/validators/tasks.py +41 -0
- infrahub/webhook/gather.py +17 -0
- infrahub/webhook/models.py +176 -44
- infrahub/webhook/tasks.py +154 -155
- infrahub/webhook/triggers.py +31 -7
- infrahub/workers/infrahub_async.py +2 -2
- infrahub/workers/utils.py +2 -2
- infrahub/workflows/catalogue.py +86 -35
- infrahub/workflows/initialization.py +8 -2
- infrahub/workflows/models.py +27 -1
- infrahub/workflows/utils.py +10 -1
- infrahub_sdk/client.py +35 -8
- infrahub_sdk/config.py +3 -0
- infrahub_sdk/context.py +13 -0
- infrahub_sdk/ctl/branch.py +3 -2
- infrahub_sdk/ctl/cli_commands.py +5 -1
- infrahub_sdk/ctl/utils.py +0 -16
- infrahub_sdk/exceptions.py +12 -0
- infrahub_sdk/generator.py +4 -1
- infrahub_sdk/graphql.py +45 -13
- infrahub_sdk/node.py +71 -22
- infrahub_sdk/protocols.py +21 -8
- infrahub_sdk/protocols_base.py +32 -11
- infrahub_sdk/query_groups.py +6 -35
- infrahub_sdk/schema/__init__.py +55 -26
- infrahub_sdk/schema/main.py +8 -0
- infrahub_sdk/task/__init__.py +11 -0
- infrahub_sdk/task/constants.py +3 -0
- infrahub_sdk/task/exceptions.py +25 -0
- infrahub_sdk/task/manager.py +551 -0
- infrahub_sdk/task/models.py +74 -0
- infrahub_sdk/testing/schemas/animal.py +9 -0
- infrahub_sdk/timestamp.py +142 -33
- infrahub_sdk/utils.py +29 -1
- {infrahub_server-1.2.0rc0.dist-info → infrahub_server-1.2.1.dist-info}/METADATA +8 -6
- {infrahub_server-1.2.0rc0.dist-info → infrahub_server-1.2.1.dist-info}/RECORD +349 -293
- {infrahub_server-1.2.0rc0.dist-info → infrahub_server-1.2.1.dist-info}/entry_points.txt +1 -0
- infrahub_testcontainers/constants.py +2 -0
- infrahub_testcontainers/container.py +157 -12
- infrahub_testcontainers/docker-compose.test.yml +31 -6
- infrahub_testcontainers/helpers.py +18 -73
- infrahub_testcontainers/host.py +41 -0
- infrahub_testcontainers/measurements.py +93 -0
- infrahub_testcontainers/models.py +38 -0
- infrahub_testcontainers/performance_test.py +166 -0
- infrahub_testcontainers/plugin.py +136 -0
- infrahub_testcontainers/prometheus.yml +30 -0
- infrahub/core/schema/definitions/core.py +0 -2286
- infrahub/message_bus/messages/check_repository_checkdefinition.py +0 -20
- infrahub/message_bus/messages/check_repository_mergeconflicts.py +0 -16
- infrahub/message_bus/messages/check_repository_usercheck.py +0 -26
- infrahub/message_bus/messages/event_branch_create.py +0 -11
- infrahub/message_bus/messages/event_branch_delete.py +0 -11
- infrahub/message_bus/messages/event_branch_rebased.py +0 -9
- infrahub/message_bus/messages/event_node_mutated.py +0 -15
- infrahub/message_bus/messages/event_schema_update.py +0 -9
- infrahub/message_bus/messages/request_repository_checks.py +0 -12
- infrahub/message_bus/messages/request_repository_userchecks.py +0 -18
- infrahub/message_bus/operations/check/repository.py +0 -293
- infrahub/message_bus/operations/event/node.py +0 -20
- infrahub/message_bus/operations/event/schema.py +0 -17
- infrahub/message_bus/operations/requests/repository.py +0 -133
- infrahub/webhook/constants.py +0 -1
- {infrahub_server-1.2.0rc0.dist-info → infrahub_server-1.2.1.dist-info}/LICENSE.txt +0 -0
- {infrahub_server-1.2.0rc0.dist-info → infrahub_server-1.2.1.dist-info}/WHEEL +0 -0
infrahub/core/manager.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from functools import reduce
|
|
4
|
-
from typing import TYPE_CHECKING, Any, Iterable, Literal,
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Iterable, Literal, TypeVar, overload
|
|
5
5
|
|
|
6
6
|
from infrahub_sdk.utils import deep_merge_dict, is_valid_uuid
|
|
7
7
|
|
|
@@ -93,7 +93,7 @@ class ProfileAttributeIndex:
|
|
|
93
93
|
self._profile_attributes_id_map[p_id] for p_id in profile_ids if p_id in self._profile_attributes_id_map
|
|
94
94
|
]
|
|
95
95
|
|
|
96
|
-
def get_profile_priority(nafd: NodeAttributesFromDB) -> tuple[
|
|
96
|
+
def get_profile_priority(nafd: NodeAttributesFromDB) -> tuple[int | float, str]:
|
|
97
97
|
try:
|
|
98
98
|
return (int(nafd.attrs.get("profile_priority").value), nafd.node.get("uuid"))
|
|
99
99
|
except (TypeError, AttributeError):
|
|
@@ -134,13 +134,13 @@ class NodeManager:
|
|
|
134
134
|
async def query(
|
|
135
135
|
cls,
|
|
136
136
|
db: InfrahubDatabase,
|
|
137
|
-
schema:
|
|
137
|
+
schema: NodeSchema | GenericSchema | ProfileSchema | TemplateSchema | str,
|
|
138
138
|
filters: dict | None = ...,
|
|
139
139
|
fields: dict | None = ...,
|
|
140
140
|
offset: int | None = ...,
|
|
141
141
|
limit: int | None = ...,
|
|
142
|
-
at:
|
|
143
|
-
branch:
|
|
142
|
+
at: Timestamp | str | None = ...,
|
|
143
|
+
branch: Branch | str | None = ...,
|
|
144
144
|
include_source: bool = ...,
|
|
145
145
|
include_owner: bool = ...,
|
|
146
146
|
prefetch_relationships: bool = ...,
|
|
@@ -160,8 +160,8 @@ class NodeManager:
|
|
|
160
160
|
fields: dict | None = ...,
|
|
161
161
|
offset: int | None = ...,
|
|
162
162
|
limit: int | None = ...,
|
|
163
|
-
at:
|
|
164
|
-
branch:
|
|
163
|
+
at: Timestamp | str | None = ...,
|
|
164
|
+
branch: Branch | str | None = ...,
|
|
165
165
|
include_source: bool = ...,
|
|
166
166
|
include_owner: bool = ...,
|
|
167
167
|
prefetch_relationships: bool = ...,
|
|
@@ -180,8 +180,8 @@ class NodeManager:
|
|
|
180
180
|
fields: dict | None = None,
|
|
181
181
|
offset: int | None = None,
|
|
182
182
|
limit: int | None = None,
|
|
183
|
-
at:
|
|
184
|
-
branch:
|
|
183
|
+
at: Timestamp | str | None = None,
|
|
184
|
+
branch: Branch | str | None = None,
|
|
185
185
|
include_source: bool = False,
|
|
186
186
|
include_owner: bool = False,
|
|
187
187
|
prefetch_relationships: bool = False,
|
|
@@ -272,10 +272,10 @@ class NodeManager:
|
|
|
272
272
|
async def count(
|
|
273
273
|
cls,
|
|
274
274
|
db: InfrahubDatabase,
|
|
275
|
-
schema:
|
|
276
|
-
filters:
|
|
277
|
-
at:
|
|
278
|
-
branch:
|
|
275
|
+
schema: type[SchemaProtocol] | NodeSchema | GenericSchema | ProfileSchema | TemplateSchema | str,
|
|
276
|
+
filters: dict | None = None,
|
|
277
|
+
at: Timestamp | str | None = None,
|
|
278
|
+
branch: Branch | str | None = None,
|
|
279
279
|
account=None, # noqa: ARG003
|
|
280
280
|
partial_match: bool = False,
|
|
281
281
|
branch_agnostic: bool = False,
|
|
@@ -317,8 +317,8 @@ class NodeManager:
|
|
|
317
317
|
schema: RelationshipSchema,
|
|
318
318
|
filters: dict,
|
|
319
319
|
db: InfrahubDatabase,
|
|
320
|
-
at:
|
|
321
|
-
branch:
|
|
320
|
+
at: Timestamp | str | None = None,
|
|
321
|
+
branch: Branch | str | None = None,
|
|
322
322
|
branch_agnostic: bool = False,
|
|
323
323
|
) -> int:
|
|
324
324
|
branch = await registry.get_branch(branch=branch, db=db)
|
|
@@ -346,11 +346,11 @@ class NodeManager:
|
|
|
346
346
|
source_kind: str,
|
|
347
347
|
schema: RelationshipSchema,
|
|
348
348
|
filters: dict,
|
|
349
|
-
fields:
|
|
350
|
-
offset:
|
|
351
|
-
limit:
|
|
352
|
-
at:
|
|
353
|
-
branch:
|
|
349
|
+
fields: dict | None = None,
|
|
350
|
+
offset: int | None = None,
|
|
351
|
+
limit: int | None = None,
|
|
352
|
+
at: Timestamp | str | None = None,
|
|
353
|
+
branch: Branch | str | None = None,
|
|
354
354
|
branch_agnostic: bool = False,
|
|
355
355
|
fetch_peers: bool = False,
|
|
356
356
|
) -> list[Relationship]:
|
|
@@ -420,8 +420,8 @@ class NodeManager:
|
|
|
420
420
|
node_schema: NodeSchema,
|
|
421
421
|
filters: dict,
|
|
422
422
|
db: InfrahubDatabase,
|
|
423
|
-
at:
|
|
424
|
-
branch:
|
|
423
|
+
at: Timestamp | str | None = None,
|
|
424
|
+
branch: Branch | str | None = None,
|
|
425
425
|
) -> int:
|
|
426
426
|
branch = await registry.get_branch(branch=branch, db=db)
|
|
427
427
|
at = Timestamp(at)
|
|
@@ -446,12 +446,12 @@ class NodeManager:
|
|
|
446
446
|
direction: RelationshipHierarchyDirection,
|
|
447
447
|
node_schema: NodeSchema,
|
|
448
448
|
filters: dict,
|
|
449
|
-
fields:
|
|
450
|
-
offset:
|
|
451
|
-
limit:
|
|
452
|
-
at:
|
|
453
|
-
branch:
|
|
454
|
-
) -> dict[str,
|
|
449
|
+
fields: dict | None = None,
|
|
450
|
+
offset: int | None = None,
|
|
451
|
+
limit: int | None = None,
|
|
452
|
+
at: Timestamp | str | None = None,
|
|
453
|
+
branch: Branch | str | None = None,
|
|
454
|
+
) -> dict[str, Node]:
|
|
455
455
|
branch = await registry.get_branch(branch=branch, db=db)
|
|
456
456
|
at = Timestamp(at)
|
|
457
457
|
|
|
@@ -1039,7 +1039,7 @@ class NodeManager:
|
|
|
1039
1039
|
prefetch_relationships: bool = False,
|
|
1040
1040
|
account=None,
|
|
1041
1041
|
branch_agnostic: bool = False,
|
|
1042
|
-
) ->
|
|
1042
|
+
) -> Any | None:
|
|
1043
1043
|
"""Return one node based on its ID."""
|
|
1044
1044
|
branch = await registry.get_branch(branch=branch, db=db)
|
|
1045
1045
|
|
|
@@ -1095,9 +1095,9 @@ class NodeManager:
|
|
|
1095
1095
|
cls,
|
|
1096
1096
|
db: InfrahubDatabase,
|
|
1097
1097
|
ids: list[str],
|
|
1098
|
-
fields:
|
|
1099
|
-
at:
|
|
1100
|
-
branch:
|
|
1098
|
+
fields: dict | None = None,
|
|
1099
|
+
at: Timestamp | str | None = None,
|
|
1100
|
+
branch: Branch | str | None = None,
|
|
1101
1101
|
include_source: bool = False,
|
|
1102
1102
|
include_owner: bool = False,
|
|
1103
1103
|
prefetch_relationships: bool = False,
|
|
@@ -1158,7 +1158,7 @@ class NodeManager:
|
|
|
1158
1158
|
continue
|
|
1159
1159
|
|
|
1160
1160
|
node = nodes_info_by_id[node_id]
|
|
1161
|
-
new_node_data: dict[str,
|
|
1161
|
+
new_node_data: dict[str, str | AttributeFromDB] = {
|
|
1162
1162
|
"db_id": node.node_id,
|
|
1163
1163
|
"id": node_id,
|
|
1164
1164
|
"updated_at": node.updated_at,
|
|
@@ -1313,9 +1313,9 @@ class NodeManager:
|
|
|
1313
1313
|
cls,
|
|
1314
1314
|
db: InfrahubDatabase,
|
|
1315
1315
|
nodes: list[Node],
|
|
1316
|
-
branch:
|
|
1317
|
-
at:
|
|
1318
|
-
) -> list[
|
|
1316
|
+
branch: Branch | str | None = None,
|
|
1317
|
+
at: Timestamp | str | None = None,
|
|
1318
|
+
) -> list[Node]:
|
|
1319
1319
|
"""Returns list of deleted nodes because of cascading deletes"""
|
|
1320
1320
|
branch = await registry.get_branch(branch=branch, db=db)
|
|
1321
1321
|
node_delete_validator = NodeDeleteValidator(db=db, branch=branch)
|
infrahub/core/merge.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import TYPE_CHECKING
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
4
|
|
|
5
5
|
from infrahub.core.constants import RepositoryInternalStatus
|
|
6
6
|
from infrahub.core.diff.model.path import BranchTrackingId
|
|
@@ -39,8 +39,8 @@ class BranchMerger:
|
|
|
39
39
|
diff_coordinator: DiffCoordinator,
|
|
40
40
|
diff_merger: DiffMerger,
|
|
41
41
|
diff_repository: DiffRepository,
|
|
42
|
-
destination_branch:
|
|
43
|
-
service:
|
|
42
|
+
destination_branch: Branch | None = None,
|
|
43
|
+
service: InfrahubServices | None = None,
|
|
44
44
|
):
|
|
45
45
|
self.source_branch = source_branch
|
|
46
46
|
self.destination_branch: Branch = destination_branch or registry.get_branch_from_registry()
|
|
@@ -51,9 +51,9 @@ class BranchMerger:
|
|
|
51
51
|
self.migrations: list[SchemaUpdateMigrationInfo] = []
|
|
52
52
|
self._merge_at = Timestamp()
|
|
53
53
|
|
|
54
|
-
self._source_schema:
|
|
55
|
-
self._destination_schema:
|
|
56
|
-
self._initial_source_schema:
|
|
54
|
+
self._source_schema: SchemaBranch | None = None
|
|
55
|
+
self._destination_schema: SchemaBranch | None = None
|
|
56
|
+
self._initial_source_schema: SchemaBranch | None = None
|
|
57
57
|
|
|
58
58
|
self._service = service
|
|
59
59
|
|
|
@@ -173,7 +173,7 @@ class BranchMerger:
|
|
|
173
173
|
|
|
174
174
|
async def merge(
|
|
175
175
|
self,
|
|
176
|
-
at:
|
|
176
|
+
at: str | Timestamp | None = None,
|
|
177
177
|
) -> EnrichedDiffRoot:
|
|
178
178
|
"""Merge the current branch into main."""
|
|
179
179
|
if self.source_branch.name == registry.default_branch:
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from typing import Optional
|
|
2
|
-
|
|
3
1
|
from .schema.attribute_name_update import AttributeNameUpdateMigration
|
|
4
2
|
from .schema.node_attribute_add import NodeAttributeAddMigration
|
|
5
3
|
from .schema.node_attribute_remove import NodeAttributeRemoveMigration
|
|
@@ -8,11 +6,12 @@ from .schema.node_remove import NodeRemoveMigration
|
|
|
8
6
|
from .schema.placeholder_dummy import PlaceholderDummyMigration
|
|
9
7
|
from .shared import SchemaMigration
|
|
10
8
|
|
|
11
|
-
MIGRATION_MAP: dict[str,
|
|
9
|
+
MIGRATION_MAP: dict[str, type[SchemaMigration] | None] = {
|
|
12
10
|
"node.remove": NodeRemoveMigration,
|
|
13
11
|
"node.branch.update": None,
|
|
14
12
|
"node.attribute.add": NodeAttributeAddMigration,
|
|
15
13
|
"node.attribute.remove": NodeAttributeRemoveMigration,
|
|
14
|
+
"node.inherit_from.update": NodeKindUpdateMigration,
|
|
16
15
|
"node.name.update": NodeKindUpdateMigration,
|
|
17
16
|
"node.namespace.update": NodeKindUpdateMigration,
|
|
18
17
|
"node.relationship.remove": PlaceholderDummyMigration,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import TYPE_CHECKING, Sequence
|
|
3
|
+
from typing import TYPE_CHECKING, Sequence
|
|
4
4
|
|
|
5
5
|
from .m001_add_version_to_graph import Migration001
|
|
6
6
|
from .m002_attribute_is_default import Migration002
|
|
@@ -20,13 +20,17 @@ from .m015_diff_format_update import Migration015
|
|
|
20
20
|
from .m016_diff_delete_bug_fix import Migration016
|
|
21
21
|
from .m017_add_core_profile import Migration017
|
|
22
22
|
from .m018_uniqueness_nulls import Migration018
|
|
23
|
+
from .m019_restore_rels_to_time import Migration019
|
|
24
|
+
from .m020_duplicate_edges import Migration020
|
|
25
|
+
from .m021_missing_hierarchy_merge import Migration021
|
|
26
|
+
from .m022_add_generate_template_attr import Migration022
|
|
23
27
|
|
|
24
28
|
if TYPE_CHECKING:
|
|
25
29
|
from infrahub.core.root import Root
|
|
26
30
|
|
|
27
31
|
from ..shared import ArbitraryMigration, GraphMigration, InternalSchemaMigration
|
|
28
32
|
|
|
29
|
-
MIGRATIONS: list[type[
|
|
33
|
+
MIGRATIONS: list[type[GraphMigration | InternalSchemaMigration | ArbitraryMigration]] = [
|
|
30
34
|
Migration001,
|
|
31
35
|
Migration002,
|
|
32
36
|
Migration003,
|
|
@@ -45,12 +49,17 @@ MIGRATIONS: list[type[Union[GraphMigration, InternalSchemaMigration, ArbitraryMi
|
|
|
45
49
|
Migration016,
|
|
46
50
|
Migration017,
|
|
47
51
|
Migration018,
|
|
52
|
+
Migration019,
|
|
53
|
+
Migration020,
|
|
54
|
+
Migration021,
|
|
55
|
+
Migration022,
|
|
56
|
+
# Migration023, Enable this migration once it has been tested on bigger databases
|
|
48
57
|
]
|
|
49
58
|
|
|
50
59
|
|
|
51
60
|
async def get_graph_migrations(
|
|
52
61
|
root: Root,
|
|
53
|
-
) -> Sequence[
|
|
62
|
+
) -> Sequence[GraphMigration | InternalSchemaMigration | ArbitraryMigration]:
|
|
54
63
|
applicable_migrations = []
|
|
55
64
|
for migration_class in MIGRATIONS:
|
|
56
65
|
migration = migration_class.init()
|
|
@@ -4,7 +4,6 @@ from typing import TYPE_CHECKING, Sequence
|
|
|
4
4
|
|
|
5
5
|
from infrahub.core import registry
|
|
6
6
|
from infrahub.core.migrations.shared import MigrationResult
|
|
7
|
-
from infrahub.core.schema import GenericSchema
|
|
8
7
|
from infrahub.core.schema.definitions.core import core_profile_schema_definition
|
|
9
8
|
from infrahub.core.schema.manager import SchemaManager
|
|
10
9
|
from infrahub.log import get_logger
|
|
@@ -31,14 +30,11 @@ class Migration017(InternalSchemaMigration):
|
|
|
31
30
|
"""
|
|
32
31
|
Load CoreProfile schema node in db.
|
|
33
32
|
"""
|
|
34
|
-
|
|
35
|
-
core_profile = GenericSchema(**core_profile_schema_definition)
|
|
36
|
-
|
|
37
33
|
default_branch = registry.get_branch_from_registry()
|
|
38
34
|
manager = SchemaManager()
|
|
39
35
|
manager.set_schema_branch(name=default_branch.name, schema=self.get_internal_schema())
|
|
40
36
|
|
|
41
37
|
db.add_schema(manager.get_schema_branch(default_branch.name))
|
|
42
|
-
await manager.load_node_to_db(node=
|
|
38
|
+
await manager.load_node_to_db(node=core_profile_schema_definition, db=db, branch=default_branch)
|
|
43
39
|
|
|
44
40
|
return MigrationResult()
|
|
@@ -50,18 +50,18 @@ class Migration018(InternalSchemaMigration):
|
|
|
50
50
|
schema_branch = await manager.load_schema_from_db(db=db, branch=default_branch)
|
|
51
51
|
manager.set_schema_branch(name=default_branch.name, schema=schema_branch)
|
|
52
52
|
|
|
53
|
-
for schema_kind in schema_branch.node_names + schema_branch.
|
|
53
|
+
for schema_kind in schema_branch.node_names + schema_branch.generic_names_without_templates:
|
|
54
54
|
schema = schema_branch.get(name=schema_kind, duplicate=False)
|
|
55
55
|
if not isinstance(schema, NodeSchema | GenericSchema):
|
|
56
56
|
continue
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
uniqueness_constraint_paths = schema.get_unique_constraint_schema_attribute_paths(
|
|
59
59
|
schema_branch=schema_branch
|
|
60
60
|
)
|
|
61
61
|
includes_optional_attr: bool = False
|
|
62
62
|
|
|
63
|
-
for
|
|
64
|
-
for schema_attribute_path in
|
|
63
|
+
for uniqueness_constraint_path in uniqueness_constraint_paths:
|
|
64
|
+
for schema_attribute_path in uniqueness_constraint_path.attributes_paths:
|
|
65
65
|
if (
|
|
66
66
|
schema_attribute_path.attribute_schema
|
|
67
67
|
and schema_attribute_path.attribute_schema.optional is True
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, Any, Sequence
|
|
4
|
+
|
|
5
|
+
from infrahub.core.migrations.shared import GraphMigration, MigrationResult
|
|
6
|
+
from infrahub.log import get_logger
|
|
7
|
+
|
|
8
|
+
from ...constants import GLOBAL_BRANCH_NAME, BranchSupportType
|
|
9
|
+
from ...query import Query, QueryType
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from infrahub.database import InfrahubDatabase
|
|
13
|
+
|
|
14
|
+
log = get_logger()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class FixBranchAwareEdgesQuery(Query):
|
|
18
|
+
name = "replace_global_edges"
|
|
19
|
+
type = QueryType.WRITE
|
|
20
|
+
insert_return = False
|
|
21
|
+
|
|
22
|
+
async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None: # noqa: ARG002
|
|
23
|
+
"""
|
|
24
|
+
Between a Node and a Relationship, if Relationship.branch_support=aware, replace any global edge
|
|
25
|
+
to the branch of a non-global edge leaving out of the Relationship node. Note that there can't
|
|
26
|
+
be multiple non-global branches on these edges, as a dedicated Relationship node would exist for that.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
query = """
|
|
30
|
+
MATCH (node:Node)-[global_edge:IS_RELATED {branch: $global_branch}]-(rel:Relationship)
|
|
31
|
+
WHERE rel.branch_support=$branch_aware
|
|
32
|
+
MATCH (rel)-[non_global_edge:IS_RELATED]-(node_2: Node)
|
|
33
|
+
WHERE non_global_edge.branch <> $global_branch
|
|
34
|
+
SET global_edge.branch = non_global_edge.branch
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
params = {
|
|
38
|
+
"global_branch": GLOBAL_BRANCH_NAME,
|
|
39
|
+
"branch_aware": BranchSupportType.AWARE.value,
|
|
40
|
+
"branch_agnostic": BranchSupportType.AGNOSTIC.value,
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
self.params.update(params)
|
|
44
|
+
self.add_to_query(query)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class SetMissingToTimeQuery(Query):
|
|
48
|
+
name = "set_missing_to_time"
|
|
49
|
+
type = QueryType.WRITE
|
|
50
|
+
insert_return = False
|
|
51
|
+
|
|
52
|
+
async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None: # noqa: ARG002
|
|
53
|
+
"""
|
|
54
|
+
If both a deleted edge and an active edge with no time exist between 2 nodes on the same branch,
|
|
55
|
+
set `to` time of active edge using `from` time of the deleted one. This would typically happen after having
|
|
56
|
+
replaced a deleted edge on global branch by correct branch with above query.
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
query = """
|
|
60
|
+
MATCH (node:Node)-[deleted_edge:IS_RELATED {status: "deleted"}]-(rel:Relationship)
|
|
61
|
+
MATCH (rel)-[active_edge:IS_RELATED {status: "active"}]-(node)
|
|
62
|
+
WHERE active_edge.to IS NULL AND deleted_edge.branch = active_edge.branch
|
|
63
|
+
SET active_edge.to = deleted_edge.from
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
self.add_to_query(query)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class DeleteNodesRelsQuery(Query):
|
|
70
|
+
name = "delete_relationships_of_deleted_nodes"
|
|
71
|
+
type = QueryType.WRITE
|
|
72
|
+
insert_return = False
|
|
73
|
+
|
|
74
|
+
async def query_init(self, db: InfrahubDatabase, **kwargs: dict[str, Any]) -> None: # noqa: ARG002
|
|
75
|
+
"""
|
|
76
|
+
Some nodes may have been incorrectly deleted, typically, while these nodes edges connected to Root
|
|
77
|
+
are correctly deleted, edges connected to other `Node` through a `Relationship` node may still be active.
|
|
78
|
+
Following query correctly deletes these edges by both setting correct to time and creating corresponding deleted edge.
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
query = """
|
|
82
|
+
MATCH (deleted_node: Node)-[deleted_edge:IS_PART_OF {status: "deleted"}]->(:Root)
|
|
83
|
+
MATCH (deleted_node)-[:IS_RELATED]-(rel:Relationship)
|
|
84
|
+
|
|
85
|
+
// exclude nodes having been deleted through migration. find those with same uuid and exclude the one with earlier
|
|
86
|
+
// timestamp on active branch
|
|
87
|
+
WHERE NOT EXISTS {
|
|
88
|
+
MATCH (deleted_node)-[e1:IS_RELATED]-(rel)-[e2:IS_RELATED]-(other_node)
|
|
89
|
+
WITH deleted_node, other_node, MIN(e1.from) AS min_e1_from, MIN(e2.from) AS min_e2_from
|
|
90
|
+
WHERE deleted_node <> other_node AND deleted_node.uuid = other_node.uuid AND min_e1_from < min_e2_from
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Note that if an AWARE node has been deleted on a branch and relationship is AGNOSTIC, we do not "delete" this relationship
|
|
94
|
+
// right now as this aware node might exist on another branch.
|
|
95
|
+
|
|
96
|
+
// Set to time if there is an active edge:
|
|
97
|
+
// - on deleted edge branch
|
|
98
|
+
// - or on any branch and deleted node is agnostic
|
|
99
|
+
// - or deleted node is aware and rel is agnostic
|
|
100
|
+
CALL {
|
|
101
|
+
WITH rel, deleted_edge
|
|
102
|
+
OPTIONAL MATCH (rel)-[peer_active_edge {status: "active"}]-(peer_1)
|
|
103
|
+
WHERE (peer_active_edge.branch = deleted_edge.branch OR (rel.branch_support <> $branch_agnostic AND deleted_edge.branch = $global_branch))
|
|
104
|
+
AND peer_active_edge.to IS NULL
|
|
105
|
+
SET peer_active_edge.to = deleted_edge.from
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Get distinct rel nodes linked to a deleted node, with the time at which we should delete rel edges.
|
|
109
|
+
// Take the MAX time so if it does not take the deleted time of a node deleted through a duplication migration.
|
|
110
|
+
WITH DISTINCT rel,
|
|
111
|
+
deleted_edge.branch AS deleted_edge_branch,
|
|
112
|
+
deleted_edge.branch_level AS branch_level,
|
|
113
|
+
MAX(deleted_edge.from) as deleted_time,
|
|
114
|
+
deleted_node.branch_support as deleted_node_branch_support
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
// No need to check deleted edge branch because
|
|
118
|
+
// If deleted_node has different branch support type (agnostic/aware) than rel type,
|
|
119
|
+
// there might already be a deleted edge that we would not match if we filter on deleted_edge_branch.
|
|
120
|
+
// If both are aware, it still works, as we would have one Relationship node for each branch on which this relationship exists.
|
|
121
|
+
MATCH (rel)-[]-(peer_2)
|
|
122
|
+
WHERE NOT exists((rel)-[{status: "deleted"}]-(peer_2))
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
// If res is agnostic and delete node is agnostic, we should delete on global branch
|
|
126
|
+
// If rel is aware and deleted node is aware, we should use deleted edge branch
|
|
127
|
+
// If rel is aware and delete node is agnostic, we need to create deleted edges for every distinct branch on which this relationship exists.
|
|
128
|
+
WITH DISTINCT
|
|
129
|
+
CASE
|
|
130
|
+
// Branch on which `deleted` edge should be created depends on rel.branch_support.
|
|
131
|
+
WHEN rel.branch_support = $branch_agnostic
|
|
132
|
+
THEN CASE
|
|
133
|
+
WHEN deleted_node_branch_support = $branch_agnostic THEN [$global_branch]
|
|
134
|
+
ELSE []
|
|
135
|
+
END
|
|
136
|
+
ELSE
|
|
137
|
+
CASE
|
|
138
|
+
WHEN deleted_node_branch_support = $branch_agnostic
|
|
139
|
+
THEN COLLECT {
|
|
140
|
+
WITH rel
|
|
141
|
+
MATCH (rel)-[active_edge {status: "active"}]-(peer_2)
|
|
142
|
+
RETURN DISTINCT active_edge.branch
|
|
143
|
+
}
|
|
144
|
+
ELSE
|
|
145
|
+
CASE
|
|
146
|
+
// if no active edge on this branch exists it means this relationship node is dedicated for another branch
|
|
147
|
+
WHEN exists((rel)-[{status: "active", branch: deleted_edge_branch}]-(peer_2)) THEN [deleted_edge_branch]
|
|
148
|
+
ELSE []
|
|
149
|
+
END
|
|
150
|
+
END
|
|
151
|
+
END AS branches,
|
|
152
|
+
branch_level,
|
|
153
|
+
deleted_time,
|
|
154
|
+
peer_2,
|
|
155
|
+
rel
|
|
156
|
+
|
|
157
|
+
UNWIND branches as branch
|
|
158
|
+
|
|
159
|
+
// Then creates `deleted` edge.
|
|
160
|
+
// Below CALL subqueries are called once for each rel-peer_2 pair for which we want to create a deleted edge.
|
|
161
|
+
// Note that with current infrahub relationships edges design, only one of this CALL should be matched per pair.
|
|
162
|
+
|
|
163
|
+
CALL {
|
|
164
|
+
WITH rel, peer_2, branch, branch_level, deleted_time
|
|
165
|
+
MATCH (rel)-[:IS_RELATED]->(peer_2)
|
|
166
|
+
MERGE (rel)-[:IS_RELATED {status: "deleted", branch: branch, branch_level: branch_level, from: deleted_time}]->(peer_2)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
CALL {
|
|
170
|
+
WITH rel, peer_2, branch, branch_level, deleted_time
|
|
171
|
+
MATCH (rel)-[:IS_PROTECTED]->(peer_2)
|
|
172
|
+
MERGE (rel)-[:IS_PROTECTED {status: "deleted", branch: branch, branch_level: branch_level, from: deleted_time}]->(peer_2)
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
CALL {
|
|
176
|
+
WITH rel, peer_2, branch, branch_level, deleted_time
|
|
177
|
+
MATCH (rel)-[:IS_VISIBLE]->(peer_2)
|
|
178
|
+
MERGE (rel)-[:IS_VISIBLE {status: "deleted", branch: branch, branch_level: branch_level, from: deleted_time}]->(peer_2)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
CALL {
|
|
182
|
+
WITH rel, peer_2, branch, branch_level, deleted_time
|
|
183
|
+
MATCH (rel)-[:HAS_OWNER]->(peer_2)
|
|
184
|
+
MERGE (rel)-[:HAS_OWNER {status: "deleted", branch: branch, branch_level: branch_level, from: deleted_time}]->(peer_2)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
CALL {
|
|
188
|
+
WITH rel, peer_2, branch, branch_level, deleted_time
|
|
189
|
+
MATCH (rel)-[:HAS_SOURCE]->(peer_2)
|
|
190
|
+
MERGE (rel)-[:HAS_SOURCE {status: "deleted", branch: branch, branch_level: branch_level, from: deleted_time}]->(peer_2)
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
CALL {
|
|
194
|
+
WITH rel, peer_2, branch, branch_level, deleted_time
|
|
195
|
+
MATCH (rel)<-[:IS_RELATED]-(peer_2)
|
|
196
|
+
MERGE (rel)<-[:IS_RELATED {status: "deleted", branch: branch, branch_level: branch_level, from: deleted_time}]-(peer_2)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
CALL {
|
|
200
|
+
WITH rel, peer_2, branch, branch_level, deleted_time
|
|
201
|
+
MATCH (rel)<-[:IS_PROTECTED]-(peer_2)
|
|
202
|
+
MERGE (rel)<-[:IS_PROTECTED {status: "deleted", branch: branch, branch_level: branch_level, from: deleted_time}]-(peer_2)
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
CALL {
|
|
206
|
+
WITH rel, peer_2, branch, branch_level, deleted_time
|
|
207
|
+
MATCH (rel)<-[:IS_VISIBLE]-(peer_2)
|
|
208
|
+
MERGE (rel)<-[:IS_VISIBLE {status: "deleted", branch: branch, branch_level: branch_level, from: deleted_time}]-(peer_2)
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
CALL {
|
|
212
|
+
WITH rel, peer_2, branch, branch_level, deleted_time
|
|
213
|
+
MATCH (rel)<-[:HAS_OWNER]-(peer_2)
|
|
214
|
+
MERGE (rel)<-[:HAS_OWNER {status: "deleted", branch: branch, branch_level: branch_level, from: deleted_time}]-(peer_2)
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
CALL {
|
|
218
|
+
WITH rel, peer_2, branch, branch_level, deleted_time
|
|
219
|
+
MATCH (rel)<-[:HAS_SOURCE]-(peer_2)
|
|
220
|
+
MERGE (rel)<-[:HAS_SOURCE {status: "deleted", branch: branch, branch_level: branch_level, from: deleted_time}]-(peer_2)
|
|
221
|
+
}
|
|
222
|
+
"""
|
|
223
|
+
|
|
224
|
+
params = {
|
|
225
|
+
"global_branch": GLOBAL_BRANCH_NAME,
|
|
226
|
+
"branch_aware": BranchSupportType.AWARE.value,
|
|
227
|
+
"branch_agnostic": BranchSupportType.AGNOSTIC.value,
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
self.params.update(params)
|
|
231
|
+
self.add_to_query(query)
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
class Migration019(GraphMigration):
|
|
235
|
+
"""
|
|
236
|
+
Fix corrupted state introduced by Migration012 when duplicating a CoreAccount (branch Aware)
|
|
237
|
+
being part of a CoreStandardGroup (branch Agnostic). Database is corrupted at multiple points:
|
|
238
|
+
- Old CoreAccount node <> group_member node `active` edge has no `to` time (possibly because of #5590).
|
|
239
|
+
- Old CoreAccount node <> group_member node `deleted` edge is on `$global_branch` branch instead of `main`.
|
|
240
|
+
- New CoreAccount node <> group_member node `active` edge is on `$global_branch` branch instead of `main`.
|
|
241
|
+
|
|
242
|
+
Also, users having deleted corresponding CoreStandardGroup will also have the following data corruption,
|
|
243
|
+
as deletion did not happen correctly due to above issues:
|
|
244
|
+
- Both CoreAccount <> group_member and CoreStandardGroup <> group_member edges
|
|
245
|
+
have not been deleted (ie status is `active` without `to` time and no additional `deleted` edge).
|
|
246
|
+
|
|
247
|
+
This migration fixes all above issues to have consistent edges, and fixes IFC-1204.
|
|
248
|
+
"""
|
|
249
|
+
|
|
250
|
+
name: str = "019_fix_edges_state"
|
|
251
|
+
minimum_version: int = 18
|
|
252
|
+
queries: Sequence[type[Query]] = [FixBranchAwareEdgesQuery, SetMissingToTimeQuery, DeleteNodesRelsQuery]
|
|
253
|
+
|
|
254
|
+
async def validate_migration(self, db: InfrahubDatabase) -> MigrationResult: # noqa: ARG002
|
|
255
|
+
result = MigrationResult()
|
|
256
|
+
return result
|