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/changelog/diff.py
CHANGED
|
@@ -7,6 +7,8 @@ from infrahub_sdk.utils import str_to_bool
|
|
|
7
7
|
|
|
8
8
|
from infrahub.core.constants import DiffAction, RelationshipCardinality
|
|
9
9
|
from infrahub.core.constants.database import DatabaseEdgeType
|
|
10
|
+
from infrahub.core.diff.model.path import ConflictSelection
|
|
11
|
+
from infrahub.exceptions import SchemaNotFoundError
|
|
10
12
|
|
|
11
13
|
from .models import (
|
|
12
14
|
AttributeChangelog,
|
|
@@ -21,9 +23,11 @@ if TYPE_CHECKING:
|
|
|
21
23
|
from infrahub.core.diff.model.path import (
|
|
22
24
|
EnrichedDiffAttribute,
|
|
23
25
|
EnrichedDiffNode,
|
|
26
|
+
EnrichedDiffProperty,
|
|
24
27
|
EnrichedDiffRelationship,
|
|
25
28
|
EnrichedDiffRoot,
|
|
26
29
|
)
|
|
30
|
+
from infrahub.core.models import SchemaUpdateMigrationInfo
|
|
27
31
|
from infrahub.core.schema import MainSchemaTypes
|
|
28
32
|
from infrahub.database import InfrahubDatabase
|
|
29
33
|
|
|
@@ -36,11 +40,18 @@ class NodeInDiff:
|
|
|
36
40
|
|
|
37
41
|
|
|
38
42
|
class DiffChangelogCollector:
|
|
39
|
-
def __init__(
|
|
43
|
+
def __init__(
|
|
44
|
+
self,
|
|
45
|
+
diff: EnrichedDiffRoot,
|
|
46
|
+
branch: Branch,
|
|
47
|
+
db: InfrahubDatabase,
|
|
48
|
+
migration_tracker: MigrationTracker | None = None,
|
|
49
|
+
) -> None:
|
|
40
50
|
self._diff = diff
|
|
41
51
|
self._branch = branch
|
|
42
52
|
self._db = db
|
|
43
53
|
self._diff_nodes: dict[str, NodeInDiff]
|
|
54
|
+
self.migration = migration_tracker or MigrationTracker()
|
|
44
55
|
|
|
45
56
|
def _populate_diff_nodes(self) -> None:
|
|
46
57
|
self._diff_nodes = {
|
|
@@ -61,7 +72,11 @@ class DiffChangelogCollector:
|
|
|
61
72
|
|
|
62
73
|
def _process_node(self, node: EnrichedDiffNode) -> NodeChangelog:
|
|
63
74
|
node_changelog = NodeChangelog(node_id=node.uuid, node_kind=node.kind, display_label=node.label)
|
|
64
|
-
|
|
75
|
+
try:
|
|
76
|
+
schema = self._db.schema.get(node_changelog.node_kind, branch=self._branch, duplicate=False)
|
|
77
|
+
except SchemaNotFoundError:
|
|
78
|
+
# if the schema has been deleted on self._branch
|
|
79
|
+
schema = None
|
|
65
80
|
for attribute in node.attributes:
|
|
66
81
|
self._process_node_attribute(node=node_changelog, attribute=attribute, schema=schema)
|
|
67
82
|
|
|
@@ -71,49 +86,59 @@ class DiffChangelogCollector:
|
|
|
71
86
|
return node_changelog
|
|
72
87
|
|
|
73
88
|
def _process_node_attribute(
|
|
74
|
-
self, node: NodeChangelog, attribute: EnrichedDiffAttribute, schema: MainSchemaTypes
|
|
89
|
+
self, node: NodeChangelog, attribute: EnrichedDiffAttribute, schema: MainSchemaTypes | None
|
|
75
90
|
) -> None:
|
|
76
|
-
|
|
77
|
-
schema_attribute = schema.get_attribute(name=attribute.name)
|
|
78
|
-
attribute_kind = schema_attribute.kind
|
|
79
|
-
except ValueError:
|
|
80
|
-
# This would currently happen if there has been a schema migration as part of the merge
|
|
81
|
-
# then we don't have access to the attribute kind
|
|
91
|
+
if schema is None:
|
|
82
92
|
attribute_kind = "n/a"
|
|
93
|
+
else:
|
|
94
|
+
try:
|
|
95
|
+
schema_attribute = schema.get_attribute(name=attribute.name)
|
|
96
|
+
attribute_kind = schema_attribute.kind
|
|
97
|
+
except ValueError:
|
|
98
|
+
# This would currently happen if there has been a schema migration as part of the merge
|
|
99
|
+
# then we don't have access to the attribute kind
|
|
100
|
+
attribute_kind = "n/a"
|
|
83
101
|
|
|
84
|
-
changelog_attribute = AttributeChangelog(
|
|
102
|
+
changelog_attribute = AttributeChangelog(
|
|
103
|
+
name=self.migration.get_attribute_name(node=node, attribute=attribute), kind=attribute_kind
|
|
104
|
+
)
|
|
85
105
|
for attr_property in attribute.properties:
|
|
86
106
|
match attr_property.property_type:
|
|
87
107
|
case DatabaseEdgeType.HAS_VALUE:
|
|
88
108
|
# TODO deserialize correct value type from string
|
|
89
|
-
|
|
90
|
-
|
|
109
|
+
if _keep_branch_update(diff_property=attr_property):
|
|
110
|
+
changelog_attribute.set_value(value=attr_property.new_value)
|
|
111
|
+
changelog_attribute.set_value_previous(value=attr_property.previous_value)
|
|
91
112
|
case DatabaseEdgeType.IS_PROTECTED:
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
113
|
+
if _keep_branch_update(diff_property=attr_property):
|
|
114
|
+
changelog_attribute.add_property(
|
|
115
|
+
name="is_protected",
|
|
116
|
+
value_current=self._convert_string_boolean_value(value=attr_property.new_value),
|
|
117
|
+
value_previous=self._convert_string_boolean_value(value=attr_property.previous_value),
|
|
118
|
+
)
|
|
97
119
|
case DatabaseEdgeType.IS_VISIBLE:
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
120
|
+
if _keep_branch_update(diff_property=attr_property):
|
|
121
|
+
changelog_attribute.add_property(
|
|
122
|
+
name="is_visible",
|
|
123
|
+
value_current=self._convert_string_boolean_value(value=attr_property.new_value),
|
|
124
|
+
value_previous=self._convert_string_boolean_value(value=attr_property.previous_value),
|
|
125
|
+
)
|
|
103
126
|
case DatabaseEdgeType.HAS_SOURCE:
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
127
|
+
if _keep_branch_update(diff_property=attr_property):
|
|
128
|
+
changelog_attribute.add_property(
|
|
129
|
+
name="source",
|
|
130
|
+
value_current=attr_property.new_value,
|
|
131
|
+
value_previous=attr_property.previous_value,
|
|
132
|
+
)
|
|
109
133
|
case DatabaseEdgeType.HAS_OWNER:
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
134
|
+
if _keep_branch_update(diff_property=attr_property):
|
|
135
|
+
changelog_attribute.add_property(
|
|
136
|
+
name="owner",
|
|
137
|
+
value_current=attr_property.new_value,
|
|
138
|
+
value_previous=attr_property.previous_value,
|
|
139
|
+
)
|
|
115
140
|
|
|
116
|
-
node.
|
|
141
|
+
node.add_attribute(attribute=changelog_attribute)
|
|
117
142
|
|
|
118
143
|
def _process_node_relationship(self, node: NodeChangelog, relationship: EnrichedDiffRelationship) -> None:
|
|
119
144
|
match relationship.cardinality:
|
|
@@ -170,7 +195,7 @@ class DiffChangelogCollector:
|
|
|
170
195
|
value_previous=rel_prop.previous_value,
|
|
171
196
|
)
|
|
172
197
|
|
|
173
|
-
node.add_relationship(
|
|
198
|
+
node.add_relationship(relationship_changelog=changelog_rel)
|
|
174
199
|
|
|
175
200
|
def _convert_string_boolean_value(self, value: str | None) -> bool | None:
|
|
176
201
|
"""Convert string based boolean for is_protected and is_visible."""
|
|
@@ -220,7 +245,7 @@ class DiffChangelogCollector:
|
|
|
220
245
|
|
|
221
246
|
changelog_rel.peers.append(peer_log)
|
|
222
247
|
|
|
223
|
-
node.add_relationship(
|
|
248
|
+
node.add_relationship(relationship_changelog=changelog_rel)
|
|
224
249
|
|
|
225
250
|
def collect_changelogs(self) -> Sequence[tuple[DiffAction, NodeChangelog]]:
|
|
226
251
|
self._populate_diff_nodes()
|
|
@@ -229,4 +254,38 @@ class DiffChangelogCollector:
|
|
|
229
254
|
for node in self._diff.nodes
|
|
230
255
|
if node.action != DiffAction.UNCHANGED
|
|
231
256
|
]
|
|
232
|
-
return changelogs
|
|
257
|
+
return [(action, node_changelog) for action, node_changelog in changelogs if node_changelog.has_changes]
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def _keep_branch_update(diff_property: EnrichedDiffProperty) -> bool:
|
|
261
|
+
if diff_property.conflict and diff_property.conflict.selected_branch == ConflictSelection.BASE_BRANCH:
|
|
262
|
+
return False
|
|
263
|
+
return True
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
class MigrationTracker:
|
|
267
|
+
"""Keeps track of schema updates that happened as part of a migration"""
|
|
268
|
+
|
|
269
|
+
def __init__(self, migrations: list[SchemaUpdateMigrationInfo] | None = None) -> None:
|
|
270
|
+
# A dictionary of Node kind, previous attribute name and new attribute
|
|
271
|
+
# {"TestPerson": {"old_attribute_name": "new_attribute_name"}}
|
|
272
|
+
self._migrations_attribute_map: dict[str, dict[str, str]] = {}
|
|
273
|
+
|
|
274
|
+
migrations = migrations or []
|
|
275
|
+
for migration in migrations:
|
|
276
|
+
if migration.migration_name == "attribute.name.update":
|
|
277
|
+
if migration.path.schema_kind not in self._migrations_attribute_map:
|
|
278
|
+
self._migrations_attribute_map[migration.path.schema_kind] = {}
|
|
279
|
+
if migration.path.property_name and migration.path.field_name:
|
|
280
|
+
self._migrations_attribute_map[migration.path.schema_kind][migration.path.property_name] = (
|
|
281
|
+
migration.path.field_name
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
def get_attribute_name(self, node: NodeChangelog, attribute: EnrichedDiffAttribute) -> str:
|
|
285
|
+
"""Return the current name of the requested attribute"""
|
|
286
|
+
if node.node_kind not in self._migrations_attribute_map:
|
|
287
|
+
return attribute.name
|
|
288
|
+
if attribute.name not in self._migrations_attribute_map[node.node_kind]:
|
|
289
|
+
return attribute.name
|
|
290
|
+
|
|
291
|
+
return self._migrations_attribute_map[node.node_kind][attribute.name]
|
|
@@ -13,6 +13,8 @@ if TYPE_CHECKING:
|
|
|
13
13
|
from infrahub.core.manager import RelationshipSchema
|
|
14
14
|
from infrahub.core.query.relationship import RelationshipPeerData
|
|
15
15
|
from infrahub.core.relationship.model import Relationship
|
|
16
|
+
from infrahub.core.schema import MainSchemaTypes
|
|
17
|
+
from infrahub.core.schema.schema_branch import SchemaBranch
|
|
16
18
|
from infrahub.database import InfrahubDatabase
|
|
17
19
|
|
|
18
20
|
|
|
@@ -75,6 +77,18 @@ class AttributeChangelog(BaseModel):
|
|
|
75
77
|
return True
|
|
76
78
|
return False
|
|
77
79
|
|
|
80
|
+
def set_value(self, value: Any) -> None:
|
|
81
|
+
if isinstance(value, str) and value == NULL_VALUE:
|
|
82
|
+
self.value = None
|
|
83
|
+
return
|
|
84
|
+
self.value = value
|
|
85
|
+
|
|
86
|
+
def set_value_previous(self, value: Any) -> None:
|
|
87
|
+
if isinstance(value, str) and value == NULL_VALUE:
|
|
88
|
+
self.value_previous = None
|
|
89
|
+
return
|
|
90
|
+
self.value_previous = value
|
|
91
|
+
|
|
78
92
|
@field_validator("value", "value_previous")
|
|
79
93
|
@classmethod
|
|
80
94
|
def convert_null_values(cls, value: Any) -> Any:
|
|
@@ -129,8 +143,8 @@ class RelationshipCardinalityOneChangelog(BaseModel):
|
|
|
129
143
|
def set_parent(self, parent_id: str, parent_kind: str) -> None:
|
|
130
144
|
self._parent = ChangelogRelatedNode(node_id=parent_id, node_kind=parent_kind)
|
|
131
145
|
|
|
132
|
-
def set_parent_from_relationship(self,
|
|
133
|
-
if
|
|
146
|
+
def set_parent_from_relationship(self, rel_kind: RelationshipKind) -> None:
|
|
147
|
+
if rel_kind == RelationshipKind.PARENT:
|
|
134
148
|
if (
|
|
135
149
|
self.peer_status in [DiffAction.ADDED, DiffAction.UNCHANGED, DiffAction.UPDATED]
|
|
136
150
|
and self.peer_id
|
|
@@ -304,17 +318,18 @@ class NodeChangelog(BaseModel):
|
|
|
304
318
|
)
|
|
305
319
|
|
|
306
320
|
def add_attribute(self, attribute: AttributeChangelog) -> None:
|
|
307
|
-
|
|
321
|
+
if attribute.has_updates:
|
|
322
|
+
self.attributes[attribute.name] = attribute
|
|
308
323
|
|
|
309
324
|
def add_relationship(
|
|
310
|
-
self,
|
|
325
|
+
self, relationship_changelog: RelationshipCardinalityOneChangelog | RelationshipCardinalityManyChangelog
|
|
311
326
|
) -> None:
|
|
312
|
-
if isinstance(
|
|
313
|
-
self.add_parent(parent=
|
|
314
|
-
if
|
|
327
|
+
if isinstance(relationship_changelog, RelationshipCardinalityOneChangelog) and relationship_changelog.parent:
|
|
328
|
+
self.add_parent(parent=relationship_changelog.parent)
|
|
329
|
+
if relationship_changelog.is_empty:
|
|
315
330
|
return
|
|
316
331
|
|
|
317
|
-
self.relationships[
|
|
332
|
+
self.relationships[relationship_changelog.name] = relationship_changelog
|
|
318
333
|
|
|
319
334
|
def create_attribute(self, attribute: BaseAttribute) -> None:
|
|
320
335
|
changelog_attribute = AttributeChangelog(
|
|
@@ -382,7 +397,7 @@ class ChangelogRelationshipMapper:
|
|
|
382
397
|
def _set_cardinality_one_peer(self, relationship: Relationship) -> None:
|
|
383
398
|
self.cardinality_one_relationship.peer_id = relationship.peer_id
|
|
384
399
|
self.cardinality_one_relationship.peer_kind = relationship.get_peer_kind()
|
|
385
|
-
self.cardinality_one_relationship.set_parent_from_relationship(
|
|
400
|
+
self.cardinality_one_relationship.set_parent_from_relationship(rel_kind=relationship.schema.kind)
|
|
386
401
|
|
|
387
402
|
def add_parent_from_relationship(self, relationship: Relationship) -> None:
|
|
388
403
|
if self.schema.cardinality == RelationshipCardinality.ONE:
|
|
@@ -419,18 +434,16 @@ class ChangelogRelationshipMapper:
|
|
|
419
434
|
value_current=getattr(relationship, property_name),
|
|
420
435
|
value_previous=previous_value,
|
|
421
436
|
)
|
|
422
|
-
self.cardinality_one_relationship.set_parent_from_relationship(
|
|
437
|
+
self.cardinality_one_relationship.set_parent_from_relationship(rel_kind=relationship.schema.kind)
|
|
423
438
|
|
|
424
|
-
def delete_relationship(self,
|
|
439
|
+
def delete_relationship(self, peer_id: str, peer_kind: str, rel_schema: RelationshipSchema) -> None:
|
|
425
440
|
if self.schema.cardinality == RelationshipCardinality.ONE:
|
|
426
|
-
self.cardinality_one_relationship.peer_id_previous =
|
|
427
|
-
self.cardinality_one_relationship.peer_kind_previous =
|
|
428
|
-
self.cardinality_one_relationship.set_parent_from_relationship(
|
|
441
|
+
self.cardinality_one_relationship.peer_id_previous = peer_id
|
|
442
|
+
self.cardinality_one_relationship.peer_kind_previous = peer_kind
|
|
443
|
+
self.cardinality_one_relationship.set_parent_from_relationship(rel_kind=rel_schema.kind)
|
|
429
444
|
|
|
430
445
|
elif self.schema.cardinality == RelationshipCardinality.MANY:
|
|
431
|
-
self.cardinality_many_relationship.remove_peer(
|
|
432
|
-
peer_id=relationship.get_peer_id(), peer_kind=relationship.get_peer_kind()
|
|
433
|
-
)
|
|
446
|
+
self.cardinality_many_relationship.remove_peer(peer_id=peer_id, peer_kind=peer_kind)
|
|
434
447
|
|
|
435
448
|
@property
|
|
436
449
|
def changelog(self) -> RelationshipCardinalityOneChangelog | RelationshipCardinalityManyChangelog:
|
|
@@ -452,37 +465,198 @@ class RelationshipChangelogGetter:
|
|
|
452
465
|
These will typically include updates to relationships on other nodes.
|
|
453
466
|
"""
|
|
454
467
|
schema_branch = self._db.schema.get_schema_branch(name=self._branch.name)
|
|
455
|
-
node_schema = schema_branch.get(name=primary_changelog.node_kind)
|
|
468
|
+
node_schema = schema_branch.get(name=primary_changelog.node_kind, duplicate=False)
|
|
456
469
|
secondaries: list[NodeChangelog] = []
|
|
457
470
|
|
|
458
471
|
for relationship in primary_changelog.relationships.values():
|
|
459
|
-
rel_schema = node_schema.get_relationship(name=relationship.name)
|
|
460
472
|
if isinstance(relationship, RelationshipCardinalityOneChangelog):
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
id=str(rel_schema.identifier), raise_on_error=False
|
|
473
|
+
secondaries.extend(
|
|
474
|
+
self._parse_cardinality_one_relationship(
|
|
475
|
+
relationship=relationship,
|
|
476
|
+
node_schema=node_schema,
|
|
477
|
+
primary_changelog=primary_changelog,
|
|
478
|
+
schema_branch=schema_branch,
|
|
468
479
|
)
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
480
|
+
)
|
|
481
|
+
elif isinstance(relationship, RelationshipCardinalityManyChangelog):
|
|
482
|
+
secondaries.extend(
|
|
483
|
+
self._parse_cardinality_many_relationship(
|
|
484
|
+
relationship=relationship,
|
|
485
|
+
node_schema=node_schema,
|
|
486
|
+
primary_changelog=primary_changelog,
|
|
487
|
+
schema_branch=schema_branch,
|
|
488
|
+
)
|
|
489
|
+
)
|
|
490
|
+
|
|
491
|
+
return secondaries
|
|
492
|
+
|
|
493
|
+
def _parse_cardinality_one_relationship(
|
|
494
|
+
self,
|
|
495
|
+
relationship: RelationshipCardinalityOneChangelog,
|
|
496
|
+
node_schema: MainSchemaTypes,
|
|
497
|
+
primary_changelog: NodeChangelog,
|
|
498
|
+
schema_branch: SchemaBranch,
|
|
499
|
+
) -> list[NodeChangelog]:
|
|
500
|
+
secondaries: list[NodeChangelog] = []
|
|
501
|
+
rel_schema = node_schema.get_relationship(name=relationship.name)
|
|
502
|
+
|
|
503
|
+
if relationship.peer_status == DiffAction.ADDED:
|
|
504
|
+
peer_schema = schema_branch.get(name=str(relationship.peer_kind), duplicate=False)
|
|
505
|
+
secondaries.extend(
|
|
506
|
+
self._process_added_peers(
|
|
507
|
+
peer_id=str(relationship.peer_id),
|
|
508
|
+
peer_kind=str(relationship.peer_kind),
|
|
509
|
+
peer_schema=peer_schema,
|
|
510
|
+
rel_schema=rel_schema,
|
|
511
|
+
primary_changelog=primary_changelog,
|
|
512
|
+
)
|
|
513
|
+
)
|
|
514
|
+
|
|
515
|
+
elif relationship.peer_status == DiffAction.UPDATED:
|
|
516
|
+
peer_schema = schema_branch.get(name=str(relationship.peer_kind), duplicate=False)
|
|
517
|
+
secondaries.extend(
|
|
518
|
+
self._process_added_peers(
|
|
519
|
+
peer_id=str(relationship.peer_id),
|
|
520
|
+
peer_kind=str(relationship.peer_kind),
|
|
521
|
+
peer_schema=peer_schema,
|
|
522
|
+
rel_schema=rel_schema,
|
|
523
|
+
primary_changelog=primary_changelog,
|
|
524
|
+
)
|
|
525
|
+
)
|
|
526
|
+
secondaries.extend(
|
|
527
|
+
self._process_removed_peers(
|
|
528
|
+
peer_schema=peer_schema,
|
|
529
|
+
peer_id=str(relationship.peer_id_previous),
|
|
530
|
+
peer_kind=str(relationship.peer_kind_previous),
|
|
531
|
+
rel_schema=rel_schema,
|
|
532
|
+
primary_changelog=primary_changelog,
|
|
533
|
+
)
|
|
534
|
+
)
|
|
535
|
+
|
|
536
|
+
elif relationship.peer_status == DiffAction.REMOVED:
|
|
537
|
+
peer_schema = schema_branch.get(name=str(relationship.peer_kind_previous), duplicate=False)
|
|
538
|
+
|
|
539
|
+
secondaries.extend(
|
|
540
|
+
self._process_removed_peers(
|
|
541
|
+
peer_id=str(relationship.peer_id_previous),
|
|
542
|
+
peer_kind=str(relationship.peer_kind_previous),
|
|
543
|
+
peer_schema=peer_schema,
|
|
544
|
+
rel_schema=rel_schema,
|
|
545
|
+
primary_changelog=primary_changelog,
|
|
546
|
+
)
|
|
547
|
+
)
|
|
548
|
+
|
|
549
|
+
return secondaries
|
|
550
|
+
|
|
551
|
+
def _parse_cardinality_many_relationship(
|
|
552
|
+
self,
|
|
553
|
+
relationship: RelationshipCardinalityManyChangelog,
|
|
554
|
+
node_schema: MainSchemaTypes,
|
|
555
|
+
primary_changelog: NodeChangelog,
|
|
556
|
+
schema_branch: SchemaBranch,
|
|
557
|
+
) -> list[NodeChangelog]:
|
|
558
|
+
secondaries: list[NodeChangelog] = []
|
|
559
|
+
rel_schema = node_schema.get_relationship(name=relationship.name)
|
|
560
|
+
|
|
561
|
+
for peer in relationship.peers:
|
|
562
|
+
if peer.peer_status == DiffAction.ADDED:
|
|
563
|
+
peer_schema = schema_branch.get(name=peer.peer_kind)
|
|
564
|
+
secondaries.extend(
|
|
565
|
+
self._process_added_peers(
|
|
566
|
+
peer_id=peer.peer_id,
|
|
567
|
+
peer_kind=peer.peer_kind,
|
|
568
|
+
peer_schema=peer_schema,
|
|
569
|
+
rel_schema=rel_schema,
|
|
570
|
+
primary_changelog=primary_changelog,
|
|
571
|
+
)
|
|
572
|
+
)
|
|
573
|
+
|
|
574
|
+
elif peer.peer_status == DiffAction.REMOVED:
|
|
575
|
+
peer_schema = schema_branch.get(name=peer.peer_kind)
|
|
576
|
+
secondaries.extend(
|
|
577
|
+
self._process_removed_peers(
|
|
578
|
+
peer_id=peer.peer_id,
|
|
579
|
+
peer_kind=peer.peer_kind,
|
|
580
|
+
peer_schema=peer_schema,
|
|
581
|
+
rel_schema=rel_schema,
|
|
582
|
+
primary_changelog=primary_changelog,
|
|
583
|
+
)
|
|
584
|
+
)
|
|
585
|
+
|
|
586
|
+
return secondaries
|
|
587
|
+
|
|
588
|
+
def _process_added_peers(
|
|
589
|
+
self,
|
|
590
|
+
peer_id: str,
|
|
591
|
+
peer_kind: str,
|
|
592
|
+
peer_schema: MainSchemaTypes,
|
|
593
|
+
rel_schema: RelationshipSchema,
|
|
594
|
+
primary_changelog: NodeChangelog,
|
|
595
|
+
) -> list[NodeChangelog]:
|
|
596
|
+
secondaries: list[NodeChangelog] = []
|
|
597
|
+
peer_relation = peer_schema.get_relationship_by_identifier(id=str(rel_schema.identifier), raise_on_error=False)
|
|
598
|
+
if peer_relation:
|
|
599
|
+
node_changelog = NodeChangelog(
|
|
600
|
+
node_id=peer_id,
|
|
601
|
+
node_kind=peer_kind,
|
|
602
|
+
display_label="n/a",
|
|
603
|
+
)
|
|
604
|
+
if peer_relation.cardinality == RelationshipCardinality.ONE:
|
|
605
|
+
node_changelog.relationships[peer_relation.name] = RelationshipCardinalityOneChangelog(
|
|
606
|
+
name=peer_relation.name,
|
|
607
|
+
peer_id=primary_changelog.node_id,
|
|
608
|
+
peer_kind=primary_changelog.node_kind,
|
|
609
|
+
)
|
|
610
|
+
secondaries.append(node_changelog)
|
|
611
|
+
elif peer_relation.cardinality == RelationshipCardinality.MANY:
|
|
612
|
+
node_changelog.relationships[peer_relation.name] = RelationshipCardinalityManyChangelog(
|
|
613
|
+
name=peer_relation.name,
|
|
614
|
+
peers=[
|
|
615
|
+
RelationshipPeerChangelog(
|
|
616
|
+
peer_id=primary_changelog.node_id,
|
|
617
|
+
peer_kind=primary_changelog.node_kind,
|
|
618
|
+
peer_status=DiffAction.ADDED,
|
|
474
619
|
)
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
620
|
+
],
|
|
621
|
+
)
|
|
622
|
+
secondaries.append(node_changelog)
|
|
623
|
+
|
|
624
|
+
return secondaries
|
|
625
|
+
|
|
626
|
+
def _process_removed_peers(
|
|
627
|
+
self,
|
|
628
|
+
peer_id: str,
|
|
629
|
+
peer_kind: str,
|
|
630
|
+
peer_schema: MainSchemaTypes,
|
|
631
|
+
rel_schema: RelationshipSchema,
|
|
632
|
+
primary_changelog: NodeChangelog,
|
|
633
|
+
) -> list[NodeChangelog]:
|
|
634
|
+
secondaries: list[NodeChangelog] = []
|
|
635
|
+
peer_relation = peer_schema.get_relationship_by_identifier(id=str(rel_schema.identifier), raise_on_error=False)
|
|
636
|
+
if peer_relation:
|
|
637
|
+
node_changelog = NodeChangelog(
|
|
638
|
+
node_id=peer_id,
|
|
639
|
+
node_kind=peer_kind,
|
|
640
|
+
display_label="n/a",
|
|
641
|
+
)
|
|
642
|
+
if peer_relation.cardinality == RelationshipCardinality.ONE:
|
|
643
|
+
node_changelog.relationships[peer_relation.name] = RelationshipCardinalityOneChangelog(
|
|
644
|
+
name=peer_relation.name,
|
|
645
|
+
peer_id_previous=primary_changelog.node_id,
|
|
646
|
+
peer_kind_previous=primary_changelog.node_kind,
|
|
647
|
+
)
|
|
648
|
+
secondaries.append(node_changelog)
|
|
649
|
+
elif peer_relation.cardinality == RelationshipCardinality.MANY:
|
|
650
|
+
node_changelog.relationships[peer_relation.name] = RelationshipCardinalityManyChangelog(
|
|
651
|
+
name=peer_relation.name,
|
|
652
|
+
peers=[
|
|
653
|
+
RelationshipPeerChangelog(
|
|
654
|
+
peer_id=primary_changelog.node_id,
|
|
655
|
+
peer_kind=primary_changelog.node_kind,
|
|
656
|
+
peer_status=DiffAction.REMOVED,
|
|
657
|
+
)
|
|
658
|
+
],
|
|
659
|
+
)
|
|
660
|
+
secondaries.append(node_changelog)
|
|
487
661
|
|
|
488
662
|
return secondaries
|
|
@@ -43,6 +43,33 @@ RESERVED_ATTR_GEN_NAMES = ["type"]
|
|
|
43
43
|
|
|
44
44
|
NULL_VALUE = "NULL"
|
|
45
45
|
|
|
46
|
+
EVENT_NAMESPACE = "infrahub"
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class EventType(InfrahubStringEnum):
|
|
50
|
+
BRANCH_CREATED = f"{EVENT_NAMESPACE}.branch.created"
|
|
51
|
+
BRANCH_DELETED = f"{EVENT_NAMESPACE}.branch.deleted"
|
|
52
|
+
BRANCH_MERGED = f"{EVENT_NAMESPACE}.branch.merged"
|
|
53
|
+
BRANCH_REBASED = f"{EVENT_NAMESPACE}.branch.rebased"
|
|
54
|
+
|
|
55
|
+
SCHEMA_UPDATED = f"{EVENT_NAMESPACE}.schema.updated"
|
|
56
|
+
|
|
57
|
+
NODE_CREATED = f"{EVENT_NAMESPACE}.node.created"
|
|
58
|
+
NODE_UPDATED = f"{EVENT_NAMESPACE}.node.updated"
|
|
59
|
+
NODE_DELETED = f"{EVENT_NAMESPACE}.node.deleted"
|
|
60
|
+
|
|
61
|
+
GROUP_MEMBER_ADDED = f"{EVENT_NAMESPACE}.group.member_added"
|
|
62
|
+
GROUP_MEMBER_REMOVED = f"{EVENT_NAMESPACE}.group.member_removed"
|
|
63
|
+
|
|
64
|
+
REPOSITORY_UPDATE_COMMIT = f"{EVENT_NAMESPACE}.repository.update_commit"
|
|
65
|
+
|
|
66
|
+
ARTIFACT_CREATED = f"{EVENT_NAMESPACE}.artifact.created"
|
|
67
|
+
ARTIFACT_UPDATED = f"{EVENT_NAMESPACE}.artifact.updated"
|
|
68
|
+
|
|
69
|
+
VALIDATOR_STARTED = f"{EVENT_NAMESPACE}.validator.started"
|
|
70
|
+
VALIDATOR_PASSED = f"{EVENT_NAMESPACE}.validator.passed"
|
|
71
|
+
VALIDATOR_FAILED = f"{EVENT_NAMESPACE}.validator.failed"
|
|
72
|
+
|
|
46
73
|
|
|
47
74
|
class PermissionLevel(enum.Flag):
|
|
48
75
|
READ = 1
|
|
@@ -60,6 +87,7 @@ class GlobalPermissions(InfrahubStringEnum):
|
|
|
60
87
|
MANAGE_ACCOUNTS = "manage_accounts"
|
|
61
88
|
MANAGE_PERMISSIONS = "manage_permissions"
|
|
62
89
|
MANAGE_REPOSITORIES = "manage_repositories"
|
|
90
|
+
OVERRIDE_CONTEXT = "override_context"
|
|
63
91
|
|
|
64
92
|
|
|
65
93
|
class PermissionAction(InfrahubStringEnum):
|
|
@@ -11,6 +11,7 @@ ARTIFACTVALIDATOR = "CoreArtifactValidator"
|
|
|
11
11
|
BASEPERMISSION = "CoreBasePermission"
|
|
12
12
|
CHANGECOMMENT = "CoreChangeComment"
|
|
13
13
|
CHANGETHREAD = "CoreChangeThread"
|
|
14
|
+
CHECK = "CoreCheck"
|
|
14
15
|
CHECKDEFINITION = "CoreCheckDefinition"
|
|
15
16
|
COMMENT = "CoreComment"
|
|
16
17
|
CUSTOMWEBHOOK = "CoreCustomWebhook"
|
|
@@ -41,6 +42,7 @@ NODE = "CoreNode"
|
|
|
41
42
|
NUMBERPOOL = "CoreNumberPool"
|
|
42
43
|
LINEAGEOWNER = "LineageOwner"
|
|
43
44
|
LINEAGESOURCE = "LineageSource"
|
|
45
|
+
OBJECTCOMPONENTTEMPLATE = "CoreObjectComponentTemplate"
|
|
44
46
|
OBJECTPERMISSION = "CoreObjectPermission"
|
|
45
47
|
OBJECTTEMPLATE = "CoreObjectTemplate"
|
|
46
48
|
OBJECTTHREAD = "CoreObjectThread"
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
from typing import TYPE_CHECKING
|
|
1
|
+
from typing import TYPE_CHECKING
|
|
2
2
|
|
|
3
3
|
from infrahub.core.branch import Branch
|
|
4
4
|
from infrahub.core.node import Node
|
|
5
|
-
from infrahub.core.node.constraints.
|
|
5
|
+
from infrahub.core.node.constraints.grouped_uniqueness import NodeGroupedUniquenessConstraint
|
|
6
6
|
from infrahub.core.relationship.constraints.interface import RelationshipManagerConstraintInterface
|
|
7
7
|
from infrahub.database import InfrahubDatabase
|
|
8
8
|
|
|
@@ -15,21 +15,18 @@ class NodeConstraintRunner:
|
|
|
15
15
|
self,
|
|
16
16
|
db: InfrahubDatabase,
|
|
17
17
|
branch: Branch,
|
|
18
|
-
|
|
18
|
+
uniqueness_constraint: NodeGroupedUniquenessConstraint,
|
|
19
19
|
relationship_manager_constraints: list[RelationshipManagerConstraintInterface],
|
|
20
20
|
) -> None:
|
|
21
21
|
self.db = db
|
|
22
22
|
self.branch = branch
|
|
23
|
-
self.
|
|
23
|
+
self.uniqueness_constraint = uniqueness_constraint
|
|
24
24
|
self.relationship_manager_constraints = relationship_manager_constraints
|
|
25
25
|
|
|
26
|
-
async def check(self, node: Node, field_filters:
|
|
26
|
+
async def check(self, node: Node, field_filters: list[str] | None = None) -> None:
|
|
27
27
|
async with self.db.start_session() as db:
|
|
28
28
|
await node.resolve_relationships(db=db)
|
|
29
29
|
|
|
30
|
-
for node_constraint in self.node_constraints:
|
|
31
|
-
await node_constraint.check(node, filters=field_filters)
|
|
32
|
-
|
|
33
30
|
for relationship_name in node.get_schema().relationship_names:
|
|
34
31
|
if field_filters and relationship_name not in field_filters:
|
|
35
32
|
continue
|
|
@@ -37,3 +34,7 @@ class NodeConstraintRunner:
|
|
|
37
34
|
await relationship_manager.fetch_relationship_ids(db=db, force_refresh=True)
|
|
38
35
|
for relationship_constraint in self.relationship_manager_constraints:
|
|
39
36
|
await relationship_constraint.check(relm=relationship_manager, node_schema=node.get_schema())
|
|
37
|
+
|
|
38
|
+
# If HFID constraint is the only constraint violated, all other constraints need to have ran before,
|
|
39
|
+
# as it means there is an existing node that we might want to update in the case of an upsert
|
|
40
|
+
await self.uniqueness_constraint.check(node, filters=field_filters)
|