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
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Mapping
|
|
4
5
|
|
|
5
6
|
from graphene import InputObjectType, Mutation
|
|
6
7
|
from graphene.types.mutation import MutationOptions
|
|
@@ -9,27 +10,24 @@ from typing_extensions import Self
|
|
|
9
10
|
|
|
10
11
|
from infrahub import config, lock
|
|
11
12
|
from infrahub.core import registry
|
|
12
|
-
from infrahub.core.changelog.models import RelationshipChangelogGetter
|
|
13
13
|
from infrahub.core.constants import InfrahubKind, MutationAction, RelationshipCardinality, RelationshipKind
|
|
14
14
|
from infrahub.core.constraint.node.runner import NodeConstraintRunner
|
|
15
15
|
from infrahub.core.manager import NodeManager
|
|
16
16
|
from infrahub.core.node import Node
|
|
17
|
-
from infrahub.core.schema import NodeSchema, RelationshipSchema
|
|
17
|
+
from infrahub.core.schema import MainSchemaTypes, NodeSchema, RelationshipSchema
|
|
18
18
|
from infrahub.core.schema.generic_schema import GenericSchema
|
|
19
19
|
from infrahub.core.schema.profile_schema import ProfileSchema
|
|
20
20
|
from infrahub.core.schema.template_schema import TemplateSchema
|
|
21
21
|
from infrahub.core.timestamp import Timestamp
|
|
22
22
|
from infrahub.database import retry_db_transaction
|
|
23
23
|
from infrahub.dependencies.registry import get_component_registry
|
|
24
|
-
from infrahub.events import
|
|
25
|
-
from infrahub.exceptions import
|
|
24
|
+
from infrahub.events.generator import generate_node_mutation_events
|
|
25
|
+
from infrahub.exceptions import HFIDViolatedError, InitializationError
|
|
26
|
+
from infrahub.graphql.context import apply_external_context
|
|
26
27
|
from infrahub.lock import InfrahubMultiLock, build_object_lock_name
|
|
27
28
|
from infrahub.log import get_log_data, get_logger
|
|
28
|
-
from infrahub.worker import WORKER_IDENTITY
|
|
29
29
|
|
|
30
30
|
from .node_getter.by_default_filter import MutationNodeGetterByDefaultFilter
|
|
31
|
-
from .node_getter.by_hfid import MutationNodeGetterByHfid
|
|
32
|
-
from .node_getter.by_id import MutationNodeGetterById
|
|
33
31
|
|
|
34
32
|
if TYPE_CHECKING:
|
|
35
33
|
from graphql import GraphQLResolveInfo
|
|
@@ -39,9 +37,9 @@ if TYPE_CHECKING:
|
|
|
39
37
|
from infrahub.core.relationship.model import RelationshipManager
|
|
40
38
|
from infrahub.core.schema.schema_branch import SchemaBranch
|
|
41
39
|
from infrahub.database import InfrahubDatabase
|
|
40
|
+
from infrahub.graphql.types.context import ContextInput
|
|
42
41
|
|
|
43
42
|
from ..initialization import GraphqlContext
|
|
44
|
-
from .node_getter.interface import MutationNodeGetterInterface
|
|
45
43
|
|
|
46
44
|
|
|
47
45
|
log = get_logger()
|
|
@@ -49,44 +47,74 @@ log = get_logger()
|
|
|
49
47
|
KINDS_CONCURRENT_MUTATIONS_NOT_ALLOWED = [InfrahubKind.GENERICGROUP]
|
|
50
48
|
|
|
51
49
|
|
|
50
|
+
@dataclass
|
|
51
|
+
class DeleteResult:
|
|
52
|
+
node: Node
|
|
53
|
+
mutation: InfrahubMutationMixin
|
|
54
|
+
deleted_nodes: list[Node] = field(default_factory=list)
|
|
55
|
+
|
|
56
|
+
|
|
52
57
|
# ------------------------------------------
|
|
53
58
|
# Infrahub GraphQLType
|
|
54
59
|
# ------------------------------------------
|
|
55
60
|
class InfrahubMutationOptions(MutationOptions):
|
|
56
|
-
schema:
|
|
61
|
+
schema: MainSchemaTypes | None = None
|
|
62
|
+
|
|
63
|
+
@property
|
|
64
|
+
def active_schema(self) -> MainSchemaTypes:
|
|
65
|
+
if self.schema:
|
|
66
|
+
return self.schema
|
|
67
|
+
raise InitializationError("This class is not initialized with a schema")
|
|
57
68
|
|
|
58
69
|
|
|
59
70
|
class InfrahubMutationMixin:
|
|
71
|
+
_meta: InfrahubMutationOptions
|
|
72
|
+
|
|
60
73
|
@classmethod
|
|
61
|
-
async def mutate(
|
|
74
|
+
async def mutate(
|
|
75
|
+
cls,
|
|
76
|
+
root: dict, # noqa: ARG003
|
|
77
|
+
info: GraphQLResolveInfo,
|
|
78
|
+
data: InputObjectType,
|
|
79
|
+
context: ContextInput | None = None,
|
|
80
|
+
**kwargs: dict[str, Any],
|
|
81
|
+
) -> Self:
|
|
62
82
|
graphql_context: GraphqlContext = info.context
|
|
83
|
+
await apply_external_context(graphql_context=graphql_context, context_input=context)
|
|
63
84
|
|
|
64
85
|
obj = None
|
|
65
86
|
mutation = None
|
|
66
87
|
action = MutationAction.UNDEFINED
|
|
88
|
+
deleted_nodes: list[Node] = []
|
|
67
89
|
|
|
68
90
|
if "Create" in cls.__name__:
|
|
69
|
-
obj, mutation = await cls.mutate_create(info=info, branch=graphql_context.branch, data=data
|
|
91
|
+
obj, mutation = await cls.mutate_create(info=info, branch=graphql_context.branch, data=data)
|
|
70
92
|
action = MutationAction.CREATED
|
|
71
93
|
elif "Update" in cls.__name__:
|
|
72
94
|
obj, mutation = await cls.mutate_update(info=info, branch=graphql_context.branch, data=data, **kwargs)
|
|
73
95
|
action = MutationAction.UPDATED
|
|
74
96
|
elif "Upsert" in cls.__name__:
|
|
75
97
|
node_manager = NodeManager()
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
MutationNodeGetterByDefaultFilter(db=graphql_context.db, node_manager=node_manager),
|
|
80
|
-
]
|
|
98
|
+
node_getter_default_filter = MutationNodeGetterByDefaultFilter(
|
|
99
|
+
db=graphql_context.db, node_manager=node_manager
|
|
100
|
+
)
|
|
81
101
|
obj, mutation, created = await cls.mutate_upsert(
|
|
82
|
-
info=info,
|
|
102
|
+
info=info,
|
|
103
|
+
branch=graphql_context.branch,
|
|
104
|
+
data=data,
|
|
105
|
+
node_getter_default_filter=node_getter_default_filter,
|
|
106
|
+
**kwargs,
|
|
83
107
|
)
|
|
84
108
|
if created:
|
|
85
109
|
action = MutationAction.CREATED
|
|
86
110
|
else:
|
|
87
111
|
action = MutationAction.UPDATED
|
|
88
112
|
elif "Delete" in cls.__name__:
|
|
89
|
-
|
|
113
|
+
delete_result = await cls.mutate_delete(info=info, branch=graphql_context.branch, data=data, **kwargs)
|
|
114
|
+
obj = delete_result.node
|
|
115
|
+
mutation = delete_result.mutation
|
|
116
|
+
deleted_nodes = delete_result.deleted_nodes
|
|
117
|
+
|
|
90
118
|
action = MutationAction.DELETED
|
|
91
119
|
else:
|
|
92
120
|
raise ValueError(
|
|
@@ -100,41 +128,15 @@ class InfrahubMutationMixin:
|
|
|
100
128
|
log_data = get_log_data()
|
|
101
129
|
request_id = log_data.get("request_id", "")
|
|
102
130
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
meta = EventMeta(
|
|
108
|
-
account_id=account_id,
|
|
109
|
-
initiator_id=WORKER_IDENTITY,
|
|
110
|
-
request_id=request_id,
|
|
131
|
+
events = await generate_node_mutation_events(
|
|
132
|
+
node=obj,
|
|
133
|
+
deleted_nodes=deleted_nodes,
|
|
134
|
+
db=graphql_context.db,
|
|
111
135
|
branch=graphql_context.branch,
|
|
112
136
|
context=graphql_context.get_context(),
|
|
113
|
-
|
|
114
|
-
main_event = NodeMutatedEvent(
|
|
115
|
-
kind=obj._schema.kind,
|
|
116
|
-
node_id=obj.id,
|
|
117
|
-
data=obj.node_changelog,
|
|
137
|
+
request_id=request_id,
|
|
118
138
|
action=action,
|
|
119
|
-
fields=_get_data_fields(data),
|
|
120
|
-
meta=meta,
|
|
121
139
|
)
|
|
122
|
-
relationship_changelogs = RelationshipChangelogGetter(db=graphql_context.db, branch=graphql_context.branch)
|
|
123
|
-
node_changelogs = await relationship_changelogs.get_changelogs(primary_changelog=obj.node_changelog)
|
|
124
|
-
|
|
125
|
-
events = [main_event]
|
|
126
|
-
|
|
127
|
-
for node_changelog in node_changelogs:
|
|
128
|
-
meta = EventMeta.from_parent(parent=main_event)
|
|
129
|
-
event = NodeMutatedEvent(
|
|
130
|
-
kind=node_changelog.node_kind,
|
|
131
|
-
node_id=node_changelog.node_id,
|
|
132
|
-
data=node_changelog,
|
|
133
|
-
action=MutationAction.UPDATED,
|
|
134
|
-
fields=node_changelog.updated_fields,
|
|
135
|
-
meta=meta,
|
|
136
|
-
)
|
|
137
|
-
events.append(event)
|
|
138
140
|
|
|
139
141
|
for event in events:
|
|
140
142
|
graphql_context.background.add_task(graphql_context.active_service.event.send, event)
|
|
@@ -150,7 +152,7 @@ class InfrahubMutationMixin:
|
|
|
150
152
|
|
|
151
153
|
@classmethod
|
|
152
154
|
async def _refresh_for_profile_update(
|
|
153
|
-
cls, db: InfrahubDatabase, branch: Branch, obj: Node, previous_profile_ids:
|
|
155
|
+
cls, db: InfrahubDatabase, branch: Branch, obj: Node, previous_profile_ids: set[str] | None = None
|
|
154
156
|
) -> Node:
|
|
155
157
|
if not hasattr(obj, "profiles"):
|
|
156
158
|
return obj
|
|
@@ -158,7 +160,7 @@ class InfrahubMutationMixin:
|
|
|
158
160
|
if previous_profile_ids is None or previous_profile_ids != current_profile_ids:
|
|
159
161
|
refreshed_node = await NodeManager.get_one_by_id_or_default_filter(
|
|
160
162
|
db=db,
|
|
161
|
-
kind=cls._meta.
|
|
163
|
+
kind=cls._meta.active_schema.kind,
|
|
162
164
|
id=obj.get_id(),
|
|
163
165
|
branch=branch,
|
|
164
166
|
include_owner=True,
|
|
@@ -169,13 +171,13 @@ class InfrahubMutationMixin:
|
|
|
169
171
|
return obj
|
|
170
172
|
|
|
171
173
|
@classmethod
|
|
172
|
-
async def _call_mutate_create_object(cls, data: InputObjectType, db: InfrahubDatabase, branch: Branch):
|
|
174
|
+
async def _call_mutate_create_object(cls, data: InputObjectType, db: InfrahubDatabase, branch: Branch) -> Node:
|
|
173
175
|
"""
|
|
174
176
|
Wrapper around mutate_create_object to potentially activate locking.
|
|
175
177
|
"""
|
|
176
178
|
schema_branch = db.schema.get_schema_branch(name=branch.name)
|
|
177
179
|
lock_names = _get_kind_lock_names_on_object_mutation(
|
|
178
|
-
kind=cls._meta.
|
|
180
|
+
kind=cls._meta.active_schema.kind, branch=branch, schema_branch=schema_branch
|
|
179
181
|
)
|
|
180
182
|
if lock_names:
|
|
181
183
|
async with InfrahubMultiLock(lock_registry=lock.registry, locks=lock_names):
|
|
@@ -203,7 +205,7 @@ class InfrahubMutationMixin:
|
|
|
203
205
|
cls,
|
|
204
206
|
db: InfrahubDatabase,
|
|
205
207
|
template_peer: Node,
|
|
206
|
-
obj_peer_schema,
|
|
208
|
+
obj_peer_schema: MainSchemaTypes,
|
|
207
209
|
parent_obj: Node,
|
|
208
210
|
current_template: CoreObjectTemplate,
|
|
209
211
|
) -> Mapping[str, Any]:
|
|
@@ -212,7 +214,7 @@ class InfrahubMutationMixin:
|
|
|
212
214
|
for attr in template_peer.get_schema().attribute_names:
|
|
213
215
|
if attr not in obj_peer_schema.attribute_names:
|
|
214
216
|
continue
|
|
215
|
-
obj_peer_data[attr] = {"value": getattr(template_peer, attr).value}
|
|
217
|
+
obj_peer_data[attr] = {"value": getattr(template_peer, attr).value, "source": template_peer.id}
|
|
216
218
|
|
|
217
219
|
for rel in template_peer.get_schema().relationship_names:
|
|
218
220
|
rel_manager: RelationshipManager = getattr(template_peer, rel)
|
|
@@ -248,8 +250,13 @@ class InfrahubMutationMixin:
|
|
|
248
250
|
if not template_relationship_peers:
|
|
249
251
|
continue
|
|
250
252
|
|
|
251
|
-
obj_peer_schema = relationship.get_peer_schema(db=db, branch=branch)
|
|
252
253
|
for template_relationship_peer in template_relationship_peers.values():
|
|
254
|
+
# We retrieve peer schema for each peer in case we are processing a relationship which is based on a generic
|
|
255
|
+
obj_peer_schema = registry.schema.get_node_schema(
|
|
256
|
+
name=template_relationship_peer.get_schema().kind.removeprefix("Template"),
|
|
257
|
+
branch=branch,
|
|
258
|
+
duplicate=False,
|
|
259
|
+
)
|
|
253
260
|
obj_peer_data = await cls._extract_peer_data(
|
|
254
261
|
db=db,
|
|
255
262
|
template_peer=template_relationship_peer,
|
|
@@ -258,7 +265,7 @@ class InfrahubMutationMixin:
|
|
|
258
265
|
current_template=template,
|
|
259
266
|
)
|
|
260
267
|
|
|
261
|
-
obj_peer = await Node.init(schema=obj_peer_schema, db=db)
|
|
268
|
+
obj_peer = await Node.init(schema=obj_peer_schema, db=db, branch=branch)
|
|
262
269
|
await obj_peer.new(db=db, **obj_peer_data)
|
|
263
270
|
await constraint_runner.check(node=obj_peer, field_filters=list(obj_peer_data))
|
|
264
271
|
await obj_peer.save(db=db)
|
|
@@ -278,7 +285,7 @@ class InfrahubMutationMixin:
|
|
|
278
285
|
info: GraphQLResolveInfo,
|
|
279
286
|
data: InputObjectType,
|
|
280
287
|
branch: Branch,
|
|
281
|
-
database:
|
|
288
|
+
database: InfrahubDatabase | None = None,
|
|
282
289
|
) -> tuple[Node, Self]:
|
|
283
290
|
graphql_context: GraphqlContext = info.context
|
|
284
291
|
db = database or graphql_context.db
|
|
@@ -299,44 +306,41 @@ class InfrahubMutationMixin:
|
|
|
299
306
|
NodeConstraintRunner, db=db.start_session(), branch=branch
|
|
300
307
|
)
|
|
301
308
|
node_class = Node
|
|
302
|
-
if cls._meta.
|
|
303
|
-
node_class = registry.node[cls._meta.
|
|
309
|
+
if cls._meta.active_schema.kind in registry.node:
|
|
310
|
+
node_class = registry.node[cls._meta.active_schema.kind]
|
|
304
311
|
|
|
305
312
|
fields_to_validate = list(data)
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
313
|
+
if db.is_transaction:
|
|
314
|
+
obj = await node_class.init(db=db, schema=cls._meta.schema, branch=branch)
|
|
315
|
+
await obj.new(db=db, **data)
|
|
316
|
+
await node_constraint_runner.check(node=obj, field_filters=fields_to_validate)
|
|
317
|
+
await obj.save(db=db)
|
|
318
|
+
|
|
319
|
+
object_template = await obj.get_object_template(db=db)
|
|
320
|
+
if object_template:
|
|
321
|
+
await cls._handle_template_relationships(
|
|
322
|
+
db=db,
|
|
323
|
+
branch=branch,
|
|
324
|
+
template=object_template,
|
|
325
|
+
obj=obj,
|
|
326
|
+
data=data,
|
|
327
|
+
)
|
|
328
|
+
else:
|
|
329
|
+
async with db.start_transaction() as dbt:
|
|
330
|
+
obj = await node_class.init(db=dbt, schema=cls._meta.schema, branch=branch)
|
|
331
|
+
await obj.new(db=dbt, **data)
|
|
310
332
|
await node_constraint_runner.check(node=obj, field_filters=fields_to_validate)
|
|
311
|
-
await obj.save(db=
|
|
333
|
+
await obj.save(db=dbt)
|
|
312
334
|
|
|
313
|
-
object_template = await obj.get_object_template(db=
|
|
335
|
+
object_template = await obj.get_object_template(db=dbt)
|
|
314
336
|
if object_template:
|
|
315
337
|
await cls._handle_template_relationships(
|
|
316
|
-
db=
|
|
338
|
+
db=dbt,
|
|
317
339
|
branch=branch,
|
|
318
340
|
template=object_template,
|
|
319
341
|
obj=obj,
|
|
320
342
|
data=data,
|
|
321
343
|
)
|
|
322
|
-
else:
|
|
323
|
-
async with db.start_transaction() as dbt:
|
|
324
|
-
obj = await node_class.init(db=dbt, schema=cls._meta.schema, branch=branch)
|
|
325
|
-
await obj.new(db=dbt, **data)
|
|
326
|
-
await node_constraint_runner.check(node=obj, field_filters=fields_to_validate)
|
|
327
|
-
await obj.save(db=dbt)
|
|
328
|
-
|
|
329
|
-
object_template = await obj.get_object_template(db=dbt)
|
|
330
|
-
if object_template:
|
|
331
|
-
await cls._handle_template_relationships(
|
|
332
|
-
db=dbt,
|
|
333
|
-
branch=branch,
|
|
334
|
-
template=object_template,
|
|
335
|
-
obj=obj,
|
|
336
|
-
data=data,
|
|
337
|
-
)
|
|
338
|
-
except ValidationError as exc:
|
|
339
|
-
raise ValueError(str(exc)) from exc
|
|
340
344
|
|
|
341
345
|
if await cls._get_profile_ids(db=db, obj=obj):
|
|
342
346
|
obj = await cls._refresh_for_profile_update(db=db, branch=branch, obj=obj)
|
|
@@ -346,7 +350,7 @@ class InfrahubMutationMixin:
|
|
|
346
350
|
@classmethod
|
|
347
351
|
async def mutate_create_to_graphql(cls, info: GraphQLResolveInfo, db: InfrahubDatabase, obj: Node) -> Self:
|
|
348
352
|
fields = await extract_fields(info.field_nodes[0].selection_set)
|
|
349
|
-
result = {"ok": True}
|
|
353
|
+
result: dict[str, Any] = {"ok": True}
|
|
350
354
|
if "object" in fields:
|
|
351
355
|
result["object"] = await obj.to_graphql(db=db, fields=fields.get("object", {}))
|
|
352
356
|
return cls(**result)
|
|
@@ -359,6 +363,7 @@ class InfrahubMutationMixin:
|
|
|
359
363
|
branch: Branch,
|
|
360
364
|
db: InfrahubDatabase,
|
|
361
365
|
obj: Node,
|
|
366
|
+
run_constraint_checks: bool = True,
|
|
362
367
|
) -> tuple[Node, Self]:
|
|
363
368
|
"""
|
|
364
369
|
Wrapper around mutate_update to potentially activate locking and call it within a database transaction.
|
|
@@ -366,24 +371,37 @@ class InfrahubMutationMixin:
|
|
|
366
371
|
|
|
367
372
|
schema_branch = db.schema.get_schema_branch(name=branch.name)
|
|
368
373
|
lock_names = _get_kind_lock_names_on_object_mutation(
|
|
369
|
-
kind=cls._meta.
|
|
374
|
+
kind=cls._meta.active_schema.kind, branch=branch, schema_branch=schema_branch
|
|
370
375
|
)
|
|
371
376
|
|
|
372
377
|
if db.is_transaction:
|
|
373
378
|
if lock_names:
|
|
374
379
|
async with InfrahubMultiLock(lock_registry=lock.registry, locks=lock_names):
|
|
375
|
-
obj = await cls.mutate_update_object(
|
|
380
|
+
obj = await cls.mutate_update_object(
|
|
381
|
+
db=db, info=info, data=data, branch=branch, obj=obj, run_constraint_checks=run_constraint_checks
|
|
382
|
+
)
|
|
376
383
|
else:
|
|
377
|
-
obj = await cls.mutate_update_object(
|
|
384
|
+
obj = await cls.mutate_update_object(
|
|
385
|
+
db=db, info=info, data=data, branch=branch, obj=obj, run_constraint_checks=run_constraint_checks
|
|
386
|
+
)
|
|
378
387
|
result = await cls.mutate_update_to_graphql(db=db, info=info, obj=obj)
|
|
379
388
|
return obj, result
|
|
380
389
|
|
|
381
390
|
async with db.start_transaction() as dbt:
|
|
382
391
|
if lock_names:
|
|
383
392
|
async with InfrahubMultiLock(lock_registry=lock.registry, locks=lock_names):
|
|
384
|
-
obj = await cls.mutate_update_object(
|
|
393
|
+
obj = await cls.mutate_update_object(
|
|
394
|
+
db=dbt,
|
|
395
|
+
info=info,
|
|
396
|
+
data=data,
|
|
397
|
+
branch=branch,
|
|
398
|
+
obj=obj,
|
|
399
|
+
run_constraint_checks=run_constraint_checks,
|
|
400
|
+
)
|
|
385
401
|
else:
|
|
386
|
-
obj = await cls.mutate_update_object(
|
|
402
|
+
obj = await cls.mutate_update_object(
|
|
403
|
+
db=dbt, info=info, data=data, branch=branch, obj=obj, run_constraint_checks=run_constraint_checks
|
|
404
|
+
)
|
|
387
405
|
result = await cls.mutate_update_to_graphql(db=dbt, info=info, obj=obj)
|
|
388
406
|
return obj, result
|
|
389
407
|
|
|
@@ -394,20 +412,17 @@ class InfrahubMutationMixin:
|
|
|
394
412
|
info: GraphQLResolveInfo,
|
|
395
413
|
data: InputObjectType,
|
|
396
414
|
branch: Branch,
|
|
397
|
-
database:
|
|
398
|
-
node:
|
|
415
|
+
database: InfrahubDatabase | None = None,
|
|
416
|
+
node: Node | None = None,
|
|
399
417
|
) -> tuple[Node, Self]:
|
|
400
418
|
graphql_context: GraphqlContext = info.context
|
|
401
419
|
db = database or graphql_context.db
|
|
402
420
|
|
|
403
421
|
obj = node or await NodeManager.find_object(
|
|
404
|
-
db=db, kind=cls._meta.
|
|
422
|
+
db=db, kind=cls._meta.active_schema.kind, id=data.get("id"), hfid=data.get("hfid"), branch=branch
|
|
405
423
|
)
|
|
406
424
|
|
|
407
|
-
|
|
408
|
-
obj, result = await cls._call_mutate_update(info=info, data=data, db=db, branch=branch, obj=obj)
|
|
409
|
-
except ValidationError as exc:
|
|
410
|
-
raise ValueError(str(exc)) from exc
|
|
425
|
+
obj, result = await cls._call_mutate_update(info=info, data=data, db=db, branch=branch, obj=obj)
|
|
411
426
|
|
|
412
427
|
return obj, result
|
|
413
428
|
|
|
@@ -419,6 +434,7 @@ class InfrahubMutationMixin:
|
|
|
419
434
|
data: InputObjectType,
|
|
420
435
|
branch: Branch,
|
|
421
436
|
obj: Node,
|
|
437
|
+
run_constraint_checks: bool = True,
|
|
422
438
|
) -> Node:
|
|
423
439
|
component_registry = get_component_registry()
|
|
424
440
|
node_constraint_runner = await component_registry.get_component(NodeConstraintRunner, db=db, branch=branch)
|
|
@@ -426,12 +442,13 @@ class InfrahubMutationMixin:
|
|
|
426
442
|
before_mutate_profile_ids = await cls._get_profile_ids(db=db, obj=obj)
|
|
427
443
|
await obj.from_graphql(db=db, data=data)
|
|
428
444
|
fields_to_validate = list(data)
|
|
429
|
-
|
|
445
|
+
if run_constraint_checks:
|
|
446
|
+
await node_constraint_runner.check(node=obj, field_filters=fields_to_validate)
|
|
430
447
|
|
|
431
448
|
fields = list(data.keys())
|
|
432
|
-
for
|
|
433
|
-
if
|
|
434
|
-
fields.remove(
|
|
449
|
+
for field_to_remove in ("id", "hfid"):
|
|
450
|
+
if field_to_remove in fields:
|
|
451
|
+
fields.remove(field_to_remove)
|
|
435
452
|
|
|
436
453
|
await obj.save(db=db, fields=fields)
|
|
437
454
|
|
|
@@ -449,7 +466,7 @@ class InfrahubMutationMixin:
|
|
|
449
466
|
) -> Self:
|
|
450
467
|
fields_object = await extract_fields(info.field_nodes[0].selection_set)
|
|
451
468
|
fields_object = fields_object.get("object", {})
|
|
452
|
-
result = {"ok": True}
|
|
469
|
+
result: dict[str, Any] = {"ok": True}
|
|
453
470
|
if fields_object:
|
|
454
471
|
result["object"] = await obj.to_graphql(db=db, fields=fields_object)
|
|
455
472
|
return cls(**result)
|
|
@@ -461,31 +478,76 @@ class InfrahubMutationMixin:
|
|
|
461
478
|
info: GraphQLResolveInfo,
|
|
462
479
|
data: InputObjectType,
|
|
463
480
|
branch: Branch,
|
|
464
|
-
|
|
465
|
-
database:
|
|
481
|
+
node_getter_default_filter: MutationNodeGetterByDefaultFilter,
|
|
482
|
+
database: InfrahubDatabase | None = None,
|
|
466
483
|
) -> tuple[Node, Self, bool]:
|
|
467
|
-
|
|
484
|
+
"""
|
|
485
|
+
First, check whether payload contains data identifying the node, such as id, hfid, or relevant fields for
|
|
486
|
+
default_filter. If not, we will try to create the node, but this creation might fail if payload contains
|
|
487
|
+
hfid fields (not `hfid` field itself) that would match an existing node in the database. In that case,
|
|
488
|
+
we would update the node without rerunning uniqueness constraint.
|
|
489
|
+
"""
|
|
490
|
+
|
|
491
|
+
schema_name = cls._meta.active_schema.kind
|
|
468
492
|
|
|
469
493
|
graphql_context: GraphqlContext = info.context
|
|
470
494
|
db = database or graphql_context.db
|
|
471
|
-
|
|
472
|
-
node_schema = db.schema.get(name=schema_name, branch=branch)
|
|
473
|
-
|
|
495
|
+
dict_data = dict(data)
|
|
474
496
|
node = None
|
|
475
|
-
|
|
476
|
-
node = await getter.get_node(node_schema=node_schema, data=data, branch=branch)
|
|
477
|
-
if node:
|
|
478
|
-
break
|
|
497
|
+
run_constraint_checks = True
|
|
479
498
|
|
|
480
|
-
if
|
|
481
|
-
|
|
499
|
+
if "id" in dict_data:
|
|
500
|
+
node = await NodeManager.get_one(
|
|
501
|
+
db=db, id=dict_data["id"], kind=schema_name, branch=branch, raise_on_error=True
|
|
502
|
+
)
|
|
503
|
+
updated_obj, mutation = await cls._call_mutate_update(
|
|
504
|
+
info=info,
|
|
505
|
+
data=data,
|
|
506
|
+
db=db,
|
|
507
|
+
branch=branch,
|
|
508
|
+
obj=node,
|
|
509
|
+
run_constraint_checks=run_constraint_checks,
|
|
510
|
+
)
|
|
482
511
|
return updated_obj, mutation, False
|
|
483
|
-
|
|
484
|
-
|
|
512
|
+
|
|
513
|
+
if cls._meta.active_schema.default_filter is not None:
|
|
514
|
+
node = await node_getter_default_filter.get_node(
|
|
515
|
+
node_schema=cls._meta.active_schema, data=data, branch=branch
|
|
516
|
+
)
|
|
517
|
+
|
|
485
518
|
if "hfid" in data:
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
519
|
+
node = await NodeManager.get_one_by_hfid(db=db, hfid=dict_data["hfid"], kind=schema_name, branch=branch)
|
|
520
|
+
|
|
521
|
+
if node is not None:
|
|
522
|
+
updated_obj, mutation = await cls._call_mutate_update(
|
|
523
|
+
info=info,
|
|
524
|
+
data=data,
|
|
525
|
+
db=db,
|
|
526
|
+
branch=branch,
|
|
527
|
+
obj=node,
|
|
528
|
+
run_constraint_checks=run_constraint_checks,
|
|
529
|
+
)
|
|
530
|
+
return updated_obj, mutation, False
|
|
531
|
+
|
|
532
|
+
try:
|
|
533
|
+
dict_data.pop("hfid", "unused") # `hfid` is invalid for creation.
|
|
534
|
+
created_obj, mutation = await cls.mutate_create(info=info, data=dict_data, branch=branch)
|
|
535
|
+
return created_obj, mutation, True
|
|
536
|
+
except HFIDViolatedError as exc:
|
|
537
|
+
# Only the HFID constraint has been violated, it means the node exists and we can update without rerunning constraints
|
|
538
|
+
if len(exc.matching_nodes_ids) > 1:
|
|
539
|
+
raise RuntimeError(f"Multiple {schema_name} nodes have the same hfid (database corrupted)") from exc
|
|
540
|
+
node_id = list(exc.matching_nodes_ids)[0]
|
|
541
|
+
node = await NodeManager.get_one(db=db, id=node_id, kind=schema_name, branch=branch, raise_on_error=True)
|
|
542
|
+
updated_obj, mutation = await cls._call_mutate_update(
|
|
543
|
+
info=info,
|
|
544
|
+
data=data,
|
|
545
|
+
db=db,
|
|
546
|
+
branch=branch,
|
|
547
|
+
obj=node,
|
|
548
|
+
run_constraint_checks=run_constraint_checks,
|
|
549
|
+
)
|
|
550
|
+
return updated_obj, mutation, False
|
|
489
551
|
|
|
490
552
|
@classmethod
|
|
491
553
|
@retry_db_transaction(name="object_delete")
|
|
@@ -494,34 +556,35 @@ class InfrahubMutationMixin:
|
|
|
494
556
|
info: GraphQLResolveInfo,
|
|
495
557
|
data: InputObjectType,
|
|
496
558
|
branch: Branch,
|
|
497
|
-
) ->
|
|
559
|
+
) -> DeleteResult:
|
|
498
560
|
graphql_context: GraphqlContext = info.context
|
|
499
561
|
|
|
500
562
|
obj = await NodeManager.find_object(
|
|
501
|
-
db=graphql_context.db,
|
|
563
|
+
db=graphql_context.db,
|
|
564
|
+
kind=cls._meta.active_schema.kind,
|
|
565
|
+
id=data.get("id"),
|
|
566
|
+
hfid=data.get("hfid"),
|
|
567
|
+
branch=branch,
|
|
502
568
|
)
|
|
503
569
|
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
deleted = await NodeManager.delete(db=db, branch=branch, nodes=[obj])
|
|
507
|
-
except ValidationError as exc:
|
|
508
|
-
raise ValueError(str(exc)) from exc
|
|
570
|
+
async with graphql_context.db.start_transaction() as db:
|
|
571
|
+
deleted = await NodeManager.delete(db=db, branch=branch, nodes=[obj])
|
|
509
572
|
|
|
510
573
|
deleted_str = ", ".join([f"{d.get_kind()}({d.get_id()})" for d in deleted])
|
|
511
574
|
log.info(f"nodes deleted: {deleted_str}")
|
|
512
575
|
|
|
513
576
|
ok = True
|
|
514
577
|
|
|
515
|
-
return obj, cls(ok=ok)
|
|
578
|
+
return DeleteResult(node=obj, mutation=cls(ok=ok), deleted_nodes=deleted)
|
|
516
579
|
|
|
517
580
|
|
|
518
581
|
class InfrahubMutation(InfrahubMutationMixin, Mutation):
|
|
519
582
|
@classmethod
|
|
520
583
|
def __init_subclass_with_meta__(
|
|
521
584
|
cls,
|
|
522
|
-
schema:
|
|
523
|
-
_meta=None,
|
|
524
|
-
**options,
|
|
585
|
+
schema: NodeSchema | GenericSchema | ProfileSchema | TemplateSchema | None = None,
|
|
586
|
+
_meta: InfrahubMutationOptions | None = None,
|
|
587
|
+
**options: dict[str, Any],
|
|
525
588
|
) -> None:
|
|
526
589
|
# Make sure schema is a valid NodeSchema Node Class
|
|
527
590
|
if not isinstance(schema, NodeSchema | GenericSchema | ProfileSchema | TemplateSchema):
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import TYPE_CHECKING, Any
|
|
1
|
+
from typing import TYPE_CHECKING, Any
|
|
2
2
|
|
|
3
3
|
from graphene import InputObjectType, Mutation
|
|
4
4
|
from graphql import GraphQLResolveInfo
|
|
@@ -14,7 +14,7 @@ from infrahub.database import InfrahubDatabase
|
|
|
14
14
|
from infrahub.exceptions import ValidationError
|
|
15
15
|
from infrahub.graphql.mutations.main import InfrahubMutationMixin
|
|
16
16
|
|
|
17
|
-
from .main import InfrahubMutationOptions
|
|
17
|
+
from .main import DeleteResult, InfrahubMutationOptions
|
|
18
18
|
|
|
19
19
|
if TYPE_CHECKING:
|
|
20
20
|
from infrahub.graphql.initialization import GraphqlContext
|
|
@@ -35,7 +35,7 @@ def validate_namespace(data: InputObjectType) -> None:
|
|
|
35
35
|
class InfrahubCoreMenuMutation(InfrahubMutationMixin, Mutation):
|
|
36
36
|
@classmethod
|
|
37
37
|
def __init_subclass_with_meta__(
|
|
38
|
-
cls, schema: NodeSchema, _meta:
|
|
38
|
+
cls, schema: NodeSchema, _meta: Any | None = None, **options: dict[str, Any]
|
|
39
39
|
) -> None:
|
|
40
40
|
# Make sure schema is a valid NodeSchema Node Class
|
|
41
41
|
if not isinstance(schema, NodeSchema):
|
|
@@ -53,7 +53,7 @@ class InfrahubCoreMenuMutation(InfrahubMutationMixin, Mutation):
|
|
|
53
53
|
info: GraphQLResolveInfo,
|
|
54
54
|
data: InputObjectType,
|
|
55
55
|
branch: Branch,
|
|
56
|
-
database:
|
|
56
|
+
database: InfrahubDatabase | None = None, # noqa: ARG003
|
|
57
57
|
) -> tuple[Node, Self]:
|
|
58
58
|
validate_namespace(data=data)
|
|
59
59
|
|
|
@@ -67,8 +67,8 @@ class InfrahubCoreMenuMutation(InfrahubMutationMixin, Mutation):
|
|
|
67
67
|
info: GraphQLResolveInfo,
|
|
68
68
|
data: InputObjectType,
|
|
69
69
|
branch: Branch,
|
|
70
|
-
database:
|
|
71
|
-
node:
|
|
70
|
+
database: InfrahubDatabase | None = None, # noqa: ARG003
|
|
71
|
+
node: Node | None = None, # noqa: ARG003
|
|
72
72
|
) -> tuple[Node, Self]:
|
|
73
73
|
graphql_context: GraphqlContext = info.context
|
|
74
74
|
|
|
@@ -89,7 +89,7 @@ class InfrahubCoreMenuMutation(InfrahubMutationMixin, Mutation):
|
|
|
89
89
|
info: GraphQLResolveInfo,
|
|
90
90
|
data: InputObjectType,
|
|
91
91
|
branch: Branch,
|
|
92
|
-
) ->
|
|
92
|
+
) -> DeleteResult:
|
|
93
93
|
graphql_context: GraphqlContext = info.context
|
|
94
94
|
obj = await NodeManager.find_object(
|
|
95
95
|
db=graphql_context.db, kind=CoreMenuItem, id=data.get("id"), hfid=data.get("hfid"), branch=branch
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
from typing import Optional
|
|
2
|
-
|
|
3
1
|
from pydantic import BaseModel
|
|
4
2
|
|
|
5
3
|
|
|
6
4
|
class BranchCreateModel(BaseModel):
|
|
7
5
|
name: str
|
|
8
|
-
id:
|
|
6
|
+
id: str | None = None
|
|
9
7
|
description: str = ""
|
|
10
8
|
origin_branch: str = "main"
|
|
11
|
-
branched_from:
|
|
9
|
+
branched_from: str | None = None
|
|
12
10
|
sync_with_git: bool = True
|
|
13
11
|
is_isolated: bool = True
|